mito2/sst/
location.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use object_store::util;
16use snafu::OptionExt as _;
17use store_api::metric_engine_consts::{DATA_REGION_SUBDIR, METADATA_REGION_SUBDIR};
18use store_api::path_utils::region_name;
19use store_api::region_request::PathType;
20use store_api::storage::{FileId, RegionId};
21
22use crate::error::UnexpectedSnafu;
23use crate::sst::file::RegionFileId;
24
25/// Generate region dir from table_dir, region_id and path_type
26pub fn region_dir_from_table_dir(
27    table_dir: &str,
28    region_id: RegionId,
29    path_type: PathType,
30) -> String {
31    let region_name = region_name(region_id.table_id(), region_id.region_sequence());
32    let base_region_dir = util::join_dir(table_dir, &region_name);
33
34    match path_type {
35        PathType::Bare => base_region_dir,
36        PathType::Data => util::join_dir(&base_region_dir, DATA_REGION_SUBDIR),
37        PathType::Metadata => util::join_dir(&base_region_dir, METADATA_REGION_SUBDIR),
38    }
39}
40
41pub fn sst_file_path(table_dir: &str, region_file_id: RegionFileId, path_type: PathType) -> String {
42    let region_dir = region_dir_from_table_dir(table_dir, region_file_id.region_id(), path_type);
43    util::join_path(
44        &region_dir,
45        &format!("{}.parquet", region_file_id.file_id()),
46    )
47}
48
49pub fn index_file_path(
50    table_dir: &str,
51    region_file_id: RegionFileId,
52    path_type: PathType,
53) -> String {
54    let region_dir = region_dir_from_table_dir(table_dir, region_file_id.region_id(), path_type);
55    let index_dir = util::join_dir(&region_dir, "index");
56    util::join_path(&index_dir, &format!("{}.puffin", region_file_id.file_id()))
57}
58
59/// Get RegionFileId from sst or index filename
60pub fn parse_file_id_from_path(filepath: &str) -> crate::error::Result<FileId> {
61    let filename = filepath.rsplit('/').next().context(UnexpectedSnafu {
62        reason: format!("invalid file path: {}", filepath),
63    })?;
64    let parts: Vec<&str> = filename.split('.').collect();
65    if parts.len() != 2 {
66        return UnexpectedSnafu {
67            reason: format!("invalid file name: {}", filename),
68        }
69        .fail();
70    }
71    if parts[1] != "parquet" && parts[1] != "puffin" {
72        return UnexpectedSnafu {
73            reason: format!("invalid file extension: {}", parts[1]),
74        }
75        .fail();
76    }
77    let file_id = parts[0];
78    FileId::parse_str(file_id).map_err(|e| {
79        UnexpectedSnafu {
80            reason: format!("invalid file id: {}, err: {}", file_id, e),
81        }
82        .build()
83    })
84}
85
86#[cfg(test)]
87mod tests {
88    use store_api::storage::{FileId, RegionId};
89
90    use super::*;
91
92    #[test]
93    fn test_sst_file_path() {
94        let file_id = FileId::random();
95        let region_file_id = RegionFileId::new(RegionId::new(1, 2), file_id);
96        assert_eq!(
97            sst_file_path("table_dir", region_file_id, PathType::Bare),
98            format!("table_dir/1_0000000002/{}.parquet", file_id)
99        );
100        assert_eq!(
101            sst_file_path("table_dir", region_file_id, PathType::Data),
102            format!("table_dir/1_0000000002/data/{}.parquet", file_id)
103        );
104        assert_eq!(
105            sst_file_path("table_dir", region_file_id, PathType::Metadata),
106            format!("table_dir/1_0000000002/metadata/{}.parquet", file_id)
107        );
108    }
109
110    #[test]
111    fn test_index_file_path() {
112        let file_id = FileId::random();
113        let region_file_id = RegionFileId::new(RegionId::new(1, 2), file_id);
114        assert_eq!(
115            index_file_path("table_dir", region_file_id, PathType::Bare),
116            format!("table_dir/1_0000000002/index/{}.puffin", file_id)
117        );
118        assert_eq!(
119            index_file_path("table_dir", region_file_id, PathType::Data),
120            format!("table_dir/1_0000000002/data/index/{}.puffin", file_id)
121        );
122        assert_eq!(
123            index_file_path("table_dir", region_file_id, PathType::Metadata),
124            format!("table_dir/1_0000000002/metadata/index/{}.puffin", file_id)
125        );
126    }
127}