11 namespace fs = std::filesystem;
13 static constexpr auto snapshot_file_prefix =
"snapshot";
14 static constexpr auto snapshot_idx_delimiter =
"_";
15 static constexpr auto snapshot_committed_suffix =
".committed";
17 static bool is_snapshot_file(
const std::string& file_name)
19 return file_name.starts_with(snapshot_file_prefix);
22 static bool is_snapshot_file_committed(
const std::string& file_name)
24 return file_name.find(snapshot_committed_suffix) != std::string::npos;
27 static size_t read_idx(
const std::string& str)
30 auto end_ptr = str.data() + str.size();
32 auto res = std::from_chars(str.data(), end_ptr, idx);
33 if (res.ec != std::errc())
35 throw std::logic_error(
36 fmt::format(
"Could not read idx from string \"{}\": {}", str, res.ec));
38 else if (res.ptr != end_ptr)
40 throw std::logic_error(fmt::format(
41 "Trailing characters in \"{}\" cannot be converted to idx: \"{}\"",
43 std::string(res.ptr, end_ptr)));
48 static std::optional<size_t> get_evidence_commit_idx_from_file_name(
49 const std::string& file_name)
55 auto pos = file_name.find(snapshot_committed_suffix);
56 if (pos == std::string::npos)
58 throw std::logic_error(
59 fmt::format(
"Snapshot file \"{}\" is not committed", file_name));
62 pos = file_name.find(snapshot_idx_delimiter, pos);
63 if (pos == std::string::npos)
69 return read_idx(file_name.substr(pos + 1));
72 static size_t get_snapshot_idx_from_file_name(
const std::string& file_name)
74 if (!is_snapshot_file(file_name))
76 throw std::logic_error(
77 fmt::format(
"File \"{}\" is not a valid snapshot file", file_name));
80 auto idx_pos = file_name.find_first_of(snapshot_idx_delimiter);
81 if (idx_pos == std::string::npos)
83 throw std::logic_error(fmt::format(
84 "Snapshot file name {} does not contain snapshot seqno", file_name));
87 auto evidence_idx_pos =
88 file_name.find_first_of(snapshot_idx_delimiter, idx_pos + 1);
89 if (evidence_idx_pos == std::string::npos)
91 throw std::logic_error(fmt::format(
92 "Snapshot file \"{}\" does not contain evidence index", file_name));
96 file_name.substr(idx_pos + 1, evidence_idx_pos - idx_pos - 1));
99 static size_t get_snapshot_evidence_idx_from_file_name(
100 const std::string& file_name)
102 if (!is_snapshot_file(file_name))
104 throw std::logic_error(
105 fmt::format(
"File \"{}\" is not a valid snapshot file", file_name));
108 auto idx_pos = file_name.find_first_of(snapshot_idx_delimiter);
109 if (idx_pos == std::string::npos)
111 throw std::logic_error(
112 fmt::format(
"Snapshot file \"{}\" does not contain index", file_name));
115 auto evidence_idx_pos =
116 file_name.find_first_of(snapshot_idx_delimiter, idx_pos + 1);
117 if (evidence_idx_pos == std::string::npos)
119 throw std::logic_error(fmt::format(
120 "Snapshot file \"{}\" does not contain evidence index", file_name));
124 size_t end_str = std::string::npos;
125 auto commit_suffix_pos =
126 file_name.find_first_of(snapshot_committed_suffix, evidence_idx_pos + 1);
127 if (commit_suffix_pos != std::string::npos)
129 end_str = commit_suffix_pos - evidence_idx_pos - 1;
132 return read_idx(file_name.substr(evidence_idx_pos + 1, end_str));
136 const fs::path& directory,
size_t& latest_committed_snapshot_idx)
138 std::optional<fs::path> latest_committed_snapshot_file_name = std::nullopt;
140 for (
auto& f : fs::directory_iterator(directory))
142 auto file_name = f.path().filename();
143 if (!is_snapshot_file(file_name))
145 LOG_INFO_FMT(
"Ignoring non-snapshot file {}", file_name);
149 if (!is_snapshot_file_committed(file_name))
151 LOG_INFO_FMT(
"Ignoring non-committed snapshot file {}", file_name);
155 if (fs::exists(f.path()) && fs::is_empty(f.path()))
157 LOG_INFO_FMT(
"Ignoring empty snapshot file {}", file_name);
161 auto snapshot_idx = get_snapshot_idx_from_file_name(file_name);
162 if (snapshot_idx > latest_committed_snapshot_idx)
164 latest_committed_snapshot_file_name = file_name;
165 latest_committed_snapshot_idx = snapshot_idx;
169 return latest_committed_snapshot_file_name;
#define LOG_INFO_FMT
Definition logger.h:362
std::optional< fs::path > find_latest_committed_snapshot_in_directory(const fs::path &directory, size_t &latest_committed_snapshot_idx)
Definition filenames.h:135