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}