bitcoinleveldb_version/setbuilder.rs
1crate::ix!();
2
3/**
4 | A helper class so we can efficiently apply
5 | a whole sequence of edits to a particular state
6 | without creating intermediate Versions that
7 | contain full copies of the intermediate state.
8 */
9pub struct VersionSetBuilder {
10 vset: *mut VersionSet,
11 base: *mut Version,
12 levels: [version_set_builder::LevelState; NUM_LEVELS],
13}
14
15pub mod version_set_builder {
16
17 use super::*;
18
19 /**
20 | Helper to sort by
21 | v->files_[file_number].smallest
22 |
23 */
24 pub struct BySmallestKey {
25 internal_comparator: *const InternalKeyComparator,
26 }
27
28 impl BySmallestKey {
29
30 pub fn invoke(&self,
31 f1: *mut FileMetaData,
32 f2: *mut FileMetaData) -> bool {
33
34 todo!();
35 /*
36 int r = internal_comparator->Compare(f1->smallest, f2->smallest);
37 if (r != 0) {
38 return (r < 0);
39 } else {
40 // Break ties by file number
41 return (f1->number < f2->number);
42 }
43 */
44 }
45 }
46
47 pub type FileSet = HashSet<*mut FileMetaData,BySmallestKey>;
48
49 pub struct LevelState {
50 deleted_files: HashSet<u64>,
51 added_files: *mut FileSet,
52 }
53}
54
55impl Drop for VersionSetBuilder {
56
57 fn drop(&mut self) {
58 todo!();
59 /*
60 for (int level = 0; level < config::NUM_LEVELS; level++) {
61 const FileSet* added = levels_[level].added_files;
62 std::vector<FileMetaData*> to_unref;
63 to_unref.reserve(added->size());
64 for (FileSet::const_iterator it = added->begin(); it != added->end();
65 ++it) {
66 to_unref.push_back(*it);
67 }
68 delete added;
69 for (uint32_t i = 0; i < to_unref.size(); i++) {
70 FileMetaData* f = to_unref[i];
71 f->refs--;
72 if (f->refs <= 0) {
73 delete f;
74 }
75 }
76 }
77 base_->Unref();
78 */
79 }
80}
81
82impl VersionSetBuilder {
83
84 /**
85 | Initialize a builder with the files
86 | from *base and other info from *vset
87 |
88 */
89 pub fn new(
90 vset: *mut VersionSet,
91 base: *mut Version) -> Self {
92
93 todo!();
94 /*
95 : vset(vset),
96 : base(base),
97
98 base_->Ref();
99 BySmallestKey cmp;
100 cmp.internal_comparator = &vset_->icmp_;
101 for (int level = 0; level < config::NUM_LEVELS; level++) {
102 levels_[level].added_files = new FileSet(cmp);
103 }
104 */
105 }
106
107 /**
108 | Apply all of the edits in *edit to the
109 | current state.
110 |
111 */
112 pub fn apply(&mut self, edit: *mut VersionEdit) {
113
114 todo!();
115 /*
116 // Update compaction pointers
117 for (size_t i = 0; i < edit->compact_pointers_.size(); i++) {
118 const int level = edit->compact_pointers_[i].first;
119 vset_->compact_pointer_[level] =
120 edit->compact_pointers_[i].second.Encode().ToString();
121 }
122
123 // Delete files
124 for (const auto& deleted_file_set_kvp : edit->deleted_files_) {
125 const int level = deleted_file_set_kvp.first;
126 const uint64_t number = deleted_file_set_kvp.second;
127 levels_[level].deleted_files.insert(number);
128 }
129
130 // Add new files
131 for (size_t i = 0; i < edit->new_files_.size(); i++) {
132 const int level = edit->new_files_[i].first;
133 FileMetaData* f = new FileMetaData(edit->new_files_[i].second);
134 f->refs = 1;
135
136 // We arrange to automatically compact this file after
137 // a certain number of seeks. Let's assume:
138 // (1) One seek costs 10ms
139 // (2) Writing or reading 1MB costs 10ms (100MB/s)
140 // (3) A compaction of 1MB does 25MB of IO:
141 // 1MB read from this level
142 // 10-12MB read from next level (boundaries may be misaligned)
143 // 10-12MB written to next level
144 // This implies that 25 seeks cost the same as the compaction
145 // of 1MB of data. I.e., one seek costs approximately the
146 // same as the compaction of 40KB of data. We are a little
147 // conservative and allow approximately one seek for every 16KB
148 // of data before triggering a compaction.
149 f->allowed_seeks = static_cast<int>((f->file_size / 16384U));
150 if (f->allowed_seeks < 100) f->allowed_seeks = 100;
151
152 levels_[level].deleted_files.erase(f->number);
153 levels_[level].added_files->insert(f);
154 }
155 */
156 }
157
158 /**
159 | Save the current state in *v.
160 |
161 */
162 pub fn save_to(&mut self, v: *mut Version) {
163
164 todo!();
165 /*
166 BySmallestKey cmp;
167 cmp.internal_comparator = &vset_->icmp_;
168 for (int level = 0; level < config::NUM_LEVELS; level++) {
169 // Merge the set of added files with the set of pre-existing files.
170 // Drop any deleted files. Store the result in *v.
171 const std::vector<FileMetaData*>& base_files = base_->files_[level];
172 std::vector<FileMetaData*>::const_iterator base_iter = base_files.begin();
173 std::vector<FileMetaData*>::const_iterator base_end = base_files.end();
174 const FileSet* added_files = levels_[level].added_files;
175 v->files_[level].reserve(base_files.size() + added_files->size());
176 for (const auto& added_file : *added_files) {
177 // Add all smaller files listed in base_
178 for (std::vector<FileMetaData*>::const_iterator bpos =
179 std::upper_bound(base_iter, base_end, added_file, cmp);
180 base_iter != bpos; ++base_iter) {
181 MaybeAddFile(v, level, *base_iter);
182 }
183
184 MaybeAddFile(v, level, added_file);
185 }
186
187 // Add remaining base files
188 for (; base_iter != base_end; ++base_iter) {
189 MaybeAddFile(v, level, *base_iter);
190 }
191
192 #ifndef NDEBUG
193 // Make sure there is no overlap in levels > 0
194 if (level > 0) {
195 for (uint32_t i = 1; i < v->files_[level].size(); i++) {
196 const InternalKey& prev_end = v->files_[level][i - 1]->largest;
197 const InternalKey& this_begin = v->files_[level][i]->smallest;
198 if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) {
199 fprintf(stderr, "overlapping ranges in same level %s vs. %s\n",
200 prev_end.DebugString().c_str(),
201 this_begin.DebugString().c_str());
202 abort();
203 }
204 }
205 }
206 #endif
207 }
208 */
209 }
210
211 pub fn maybe_add_file(&mut self,
212 v: *mut Version,
213 level: i32,
214 f: *mut FileMetaData) {
215
216 todo!();
217 /*
218 if (levels_[level].deleted_files.count(f->number) > 0) {
219 // File is deleted: do nothing
220 } else {
221 std::vector<FileMetaData*>* files = &v->files_[level];
222 if (level > 0 && !files->empty()) {
223 // Must not overlap
224 assert(vset_->icmp_.Compare((*files)[files->size() - 1]->largest,
225 f->smallest) < 0);
226 }
227 f->refs++;
228 files->push_back(f);
229 }
230 */
231 }
232}