bitcoinleveldb_table/
table.rs

1crate::ix!();
2
3//-------------------------------------------[.cpp/bitcoin/src/leveldb/include/leveldb/table.h]
4
5/**
6  | A Table is a sorted map from strings to
7  | strings.  Tables are immutable and persistent.
8  | A Table may be safely accessed from multiple
9  | threads without external synchronization.
10  */
11pub struct Table {
12    rep: *const TableRep,
13}
14
15impl Table {
16
17    pub fn new(rep: *mut TableRep) -> Self {
18    
19        todo!();
20        /*
21        : rep(rep),
22        */
23    }
24
25    /**
26      | Attempt to open the table that is stored in
27      | bytes [0..file_size) of "file", and read the
28      | metadata entries necessary to allow
29      | retrieving data from the table.
30      |
31      | If successful, returns ok and sets "*table"
32      | to the newly opened table.  The client should
33      | delete "*table" when no longer needed.  If
34      | there was an error while initializing the
35      | table, sets "*table" to nullptr and returns
36      | a non-ok status.  Does not take ownership of
37      | "*source", but the client must ensure that
38      | "source" remains live for the duration of the
39      | returned table's lifetime.
40      |
41      | *file must remain live while this Table is in
42      | use.
43      */
44    pub fn open(&mut self, 
45        options: &Options,
46        file:    Rc<RefCell<dyn RandomAccessFile>>,
47        size:    u64,
48        table:   *mut *mut Table) -> Status {
49        
50        todo!();
51        /*
52            *table = nullptr;
53      if (size < Footer::kEncodedLength) {
54        return Status::Corruption("file is too short to be an sstable");
55      }
56
57      char footer_space[Footer::kEncodedLength];
58      Slice footer_input;
59      Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength,
60                            &footer_input, footer_space);
61      if (!s.ok()) return s;
62
63      Footer footer;
64      s = footer.DecodeFrom(&footer_input);
65      if (!s.ok()) return s;
66
67      // Read the index block
68      BlockContents index_block_contents;
69      if (s.ok()) {
70        ReadOptions opt;
71        if (options.paranoid_checks) {
72          opt.verify_checksums = true;
73        }
74        s = ReadBlock(file, opt, footer.index_handle(), &index_block_contents);
75      }
76
77      if (s.ok()) {
78        // We've successfully read the footer and the index block: we're
79        // ready to serve requests.
80        Block* index_block = new Block(index_block_contents);
81        Rep* rep = new Table::Rep;
82        rep->options = options;
83        rep->file = file;
84        rep->metaindex_handle = footer.metaindex_handle();
85        rep->index_block = index_block;
86        rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0);
87        rep->filter_data = nullptr;
88        rep->filter = nullptr;
89        *table = new Table(rep);
90        (*table)->ReadMeta(footer);
91      }
92
93      return s;
94        */
95    }
96    
97    pub fn read_meta(&mut self, footer: &Footer)  {
98        
99        todo!();
100        /*
101            if (rep_->options.filter_policy == nullptr) {
102        return;  // Do not need any metadata
103      }
104
105      // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates
106      // it is an empty block.
107      ReadOptions opt;
108      if (rep_->options.paranoid_checks) {
109        opt.verify_checksums = true;
110      }
111      BlockContents contents;
112      if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) {
113        // Do not propagate errors since meta info is not needed for operation
114        return;
115      }
116      Block* meta = new Block(contents);
117
118      Iterator* iter = meta->NewIterator(BytewiseComparator());
119      std::string key = "filter.";
120      key.append(rep_->options.filter_policy->Name());
121      iter->Seek(key);
122      if (iter->Valid() && iter->key() == Slice(key)) {
123        ReadFilter(iter->value());
124      }
125      delete iter;
126      delete meta;
127        */
128    }
129    
130    pub fn read_filter(&mut self, filter_handle_value: &Slice)  {
131        
132        todo!();
133        /*
134            Slice v = filter_handle_value;
135      BlockHandle filter_handle;
136      if (!filter_handle.DecodeFrom(&v).ok()) {
137        return;
138      }
139
140      // We might want to unify with ReadBlock() if we start
141      // requiring checksum verification in Table::Open.
142      ReadOptions opt;
143      if (rep_->options.paranoid_checks) {
144        opt.verify_checksums = true;
145      }
146      BlockContents block;
147      if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) {
148        return;
149      }
150      if (block.heap_allocated) {
151        rep_->filter_data = block.data.data();  // Will need to delete later
152      }
153      rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data);
154        */
155    }
156
157    /**
158      | Convert an index iterator value (i.e.,
159      | an encoded BlockHandle) into an iterator
160      | over the contents of the corresponding
161      | block.
162      |
163      */
164    pub fn block_reader(&mut self, 
165        arg:         *mut c_void,
166        options:     &ReadOptions,
167        index_value: &Slice) -> *mut LevelDBIterator {
168        
169        todo!();
170        /*
171            Table* table = reinterpret_cast<Table*>(arg);
172      Cache* block_cache = table->rep_->options.block_cache;
173      Block* block = nullptr;
174      Cache::Handle* cache_handle = nullptr;
175
176      BlockHandle handle;
177      Slice input = index_value;
178      Status s = handle.DecodeFrom(&input);
179      // We intentionally allow extra stuff in index_value so that we
180      // can add more features in the future.
181
182      if (s.ok()) {
183        BlockContents contents;
184        if (block_cache != nullptr) {
185          char cache_key_buffer[16];
186          EncodeFixed64(cache_key_buffer, table->rep_->cache_id);
187          EncodeFixed64(cache_key_buffer + 8, handle.offset());
188          Slice key(cache_key_buffer, sizeof(cache_key_buffer));
189          cache_handle = block_cache->Lookup(key);
190          if (cache_handle != nullptr) {
191            block = reinterpret_cast<Block*>(block_cache->Value(cache_handle));
192          } else {
193            s = ReadBlock(table->rep_->file, options, handle, &contents);
194            if (s.ok()) {
195              block = new Block(contents);
196              if (contents.cachable && options.fill_cache) {
197                cache_handle = block_cache->Insert(key, block, block->size(),
198                                                   &DeleteCachedBlock);
199              }
200            }
201          }
202        } else {
203          s = ReadBlock(table->rep_->file, options, handle, &contents);
204          if (s.ok()) {
205            block = new Block(contents);
206          }
207        }
208      }
209
210      Iterator* iter;
211      if (block != nullptr) {
212        iter = block->NewIterator(table->rep_->options.comparator);
213        if (cache_handle == nullptr) {
214          iter->RegisterCleanup(&DeleteBlock, block, nullptr);
215        } else {
216          iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle);
217        }
218      } else {
219        iter = NewErrorIterator(s);
220      }
221      return iter;
222        */
223    }
224    
225    /**
226      | Returns a new iterator over the table
227      | contents.
228      |
229      | The result of NewIterator() is initially
230      | invalid (caller must call one of the Seek
231      | methods on the iterator before using it).
232      */
233    pub fn new_iterator(&self, options: &ReadOptions) -> *mut LevelDBIterator {
234        
235        todo!();
236        /*
237            return NewTwoLevelIterator(
238          rep_->index_block->NewIterator(rep_->options.comparator),
239          &Table::BlockReader, const_cast<Table*>(this), options);
240        */
241    }
242    
243    /**
244      | Calls (*handle_result)(arg, ...) with the
245      | entry found after a call to Seek(key).  May
246      | not make such a call if filter policy says
247      | that key is not present.
248      */
249    pub fn internal_get(&mut self, 
250        options:       &ReadOptions,
251        k:             &Slice,
252        arg:           *mut c_void,
253        handle_result: fn(
254                _0: *mut c_void,
255                _1: &Slice,
256                _2: &Slice
257        ) -> c_void) -> Status {
258        
259        todo!();
260        /*
261            Status s;
262      Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator);
263      iiter->Seek(k);
264      if (iiter->Valid()) {
265        Slice handle_value = iiter->value();
266        FilterBlockReader* filter = rep_->filter;
267        BlockHandle handle;
268        if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() &&
269            !filter->KeyMayMatch(handle.offset(), k)) {
270          // Not found
271        } else {
272          Iterator* block_iter = BlockReader(this, options, iiter->value());
273          block_iter->Seek(k);
274          if (block_iter->Valid()) {
275            (*handle_result)(arg, block_iter->key(), block_iter->value());
276          }
277          s = block_iter->status();
278          delete block_iter;
279        }
280      }
281      if (s.ok()) {
282        s = iiter->status();
283      }
284      delete iiter;
285      return s;
286        */
287    }
288    
289    /**
290      | Given a key, return an approximate byte
291      | offset in the file where the data for that
292      | key begins (or would begin if the key were
293      | present in the file).  The returned value is
294      | in terms of file bytes, and so includes
295      | effects like compression of the underlying
296      | data.
297      |
298      | E.g., the approximate offset of the last key
299      | in the table will be close to the file
300      | length.
301      */
302    pub fn approximate_offset_of(&self, key_: &Slice) -> u64 {
303        
304        todo!();
305        /*
306            Iterator* index_iter =
307          rep_->index_block->NewIterator(rep_->options.comparator);
308      index_iter->Seek(key);
309      uint64_t result;
310      if (index_iter->Valid()) {
311        BlockHandle handle;
312        Slice input = index_iter->value();
313        Status s = handle.DecodeFrom(&input);
314        if (s.ok()) {
315          result = handle.offset();
316        } else {
317          // Strange: we can't decode the block handle in the index block.
318          // We'll just return the offset of the metaindex block, which is
319          // close to the whole file size for this case.
320          result = rep_->metaindex_handle.offset();
321        }
322      } else {
323        // key is past the last key in the file.  Approximate the offset
324        // by returning the offset of the metaindex block (which is
325        // right near the end of the file).
326        result = rep_->metaindex_handle.offset();
327      }
328      delete index_iter;
329      return result;
330        */
331    }
332}
333
334//-------------------------------------------[.cpp/bitcoin/src/leveldb/table/table.cc]
335
336pub struct TableRep {
337
338    options:          Options,
339    status:           Status,
340    file:             Rc<RefCell<dyn RandomAccessFile>>,
341    cache_id:         u64,
342    filter:           *mut FilterBlockReader,
343    filter_data:      *const u8,
344
345    /**
346      | Handle to metaindex_block: saved from
347      | footer
348      |
349      */
350    metaindex_handle: BlockHandle,
351
352    index_block:      *mut Block,
353}
354
355impl Drop for TableRep {
356    fn drop(&mut self) {
357        todo!();
358        /*
359            delete filter;
360        delete[] filter_data;
361        delete index_block;
362        */
363    }
364}
365
366impl Drop for Table {
367    fn drop(&mut self) {
368        todo!();
369        /*
370            delete rep_;
371        */
372    }
373}
374
375pub fn delete_block(
376        arg:     *mut c_void,
377        ignored: *mut c_void)  {
378    
379    todo!();
380        /*
381            delete reinterpret_cast<Block*>(arg);
382        */
383}
384
385pub fn delete_cached_block(
386        key_:   &Slice,
387        value: *mut c_void)  {
388    
389    todo!();
390        /*
391            Block* block = reinterpret_cast<Block*>(value);
392      delete block;
393        */
394}
395
396pub fn release_block(
397        arg: *mut c_void,
398        h:   *mut c_void)  {
399    
400    todo!();
401        /*
402            Cache* cache = reinterpret_cast<Cache*>(arg);
403      Cache::Handle* handle = reinterpret_cast<Cache::Handle*>(h);
404      cache->Release(handle);
405        */
406}