1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::{db_state::ScndIdxNum, lsm::unit::CommitInfo};
use anyhow::Result;
use derive_more::From;
use pancake_engine_common::fs_utils::{self, NamePattern, PathNameNum};
use std::path::{Path, PathBuf};

const PI_KV_FILE_NAME: &str = "pi.kv";
const SI_KV_FILE_NAME_PFX: &str = "si-";
const SI_KV_FILE_NAME_EXT: &str = ".kv";
const COMMIT_INFO_FILE_NAME: &str = "commit_info.txt";

#[derive(From, PartialEq, Eq)]
pub struct UnitDir(PathBuf);

impl UnitDir {
    pub fn path(&self) -> &PathBuf {
        &self.0
    }

    /* Primary index */
    pub fn format_prim_file_path(&self) -> PathBuf {
        self.0.join(PI_KV_FILE_NAME)
    }

    /* Secondary indexes */
    fn scnd_file_name_pattern() -> NamePattern {
        NamePattern::new(SI_KV_FILE_NAME_PFX, SI_KV_FILE_NAME_EXT)
    }
    pub fn format_scnd_file_path(&self, si_num: ScndIdxNum) -> PathBuf {
        let path_name_num: PathNameNum = si_num.into();
        let file_name = Self::scnd_file_name_pattern().format(path_name_num);
        let file_path = self.0.join(file_name);
        file_path
    }
    fn parse_scnd_file_num<P: AsRef<Path>>(file_path: P) -> Option<ScndIdxNum> {
        let file_path = file_path.as_ref();
        let file_name = file_path.file_name().and_then(|os_str| os_str.to_str());
        let path_name_num = file_name.and_then(|s| Self::scnd_file_name_pattern().parse(s).ok());
        let si_num = path_name_num.map(ScndIdxNum::from);
        si_num
    }
    pub fn list_scnd_file_paths<'a>(
        &'a self,
    ) -> Result<impl 'a + Iterator<Item = Result<(PathBuf, ScndIdxNum)>>> {
        let ret_iter = fs_utils::read_dir(&self.0)?.filter_map(|res_path| {
            res_path
                .map(|path| Self::parse_scnd_file_num(&path).map(|si_num| (path, si_num)))
                .transpose()
        });
        Ok(ret_iter)
    }

    /* Commit info */
    pub fn format_commit_info_file_path(&self) -> PathBuf {
        self.0.join(COMMIT_INFO_FILE_NAME)
    }
    pub fn load_commit_info(&self) -> Result<CommitInfo> {
        let file_path = self.format_commit_info_file_path();
        CommitInfo::deser(file_path)
    }
}