LCOV - code coverage report
Current view: top level - src/leveldb/table - filter_block.cc (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 57 59 96.6 %
Date: 2015-10-12 22:39:14 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file. See the AUTHORS file for names of contributors.
       4             : 
       5             : #include "table/filter_block.h"
       6             : 
       7             : #include "leveldb/filter_policy.h"
       8             : #include "util/coding.h"
       9             : 
      10             : namespace leveldb {
      11             : 
      12             : // See doc/table_format.txt for an explanation of the filter block format.
      13             : 
      14             : // Generate new filter every 2KB of data
      15             : static const size_t kFilterBaseLg = 11;
      16             : static const size_t kFilterBase = 1 << kFilterBaseLg;
      17             : 
      18         122 : FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)
      19         610 :     : policy_(policy) {
      20         122 : }
      21             : 
      22         639 : void FilterBlockBuilder::StartBlock(uint64_t block_offset) {
      23         639 :   uint64_t filter_index = (block_offset / kFilterBase);
      24        1278 :   assert(filter_index >= filter_offsets_.size());
      25        3016 :   while (filter_index > filter_offsets_.size()) {
      26         869 :     GenerateFilter();
      27             :   }
      28         639 : }
      29             : 
      30       18237 : void FilterBlockBuilder::AddKey(const Slice& key) {
      31       18237 :   Slice k = key;
      32       54711 :   start_.push_back(keys_.size());
      33       18237 :   keys_.append(k.data(), k.size());
      34       18237 : }
      35             : 
      36         122 : Slice FilterBlockBuilder::Finish() {
      37         244 :   if (!start_.empty()) {
      38          45 :     GenerateFilter();
      39             :   }
      40             : 
      41             :   // Append array of per-filter offsets
      42         244 :   const uint32_t array_offset = result_.size();
      43        2072 :   for (size_t i = 0; i < filter_offsets_.size(); i++) {
      44        1828 :     PutFixed32(&result_, filter_offsets_[i]);
      45             :   }
      46             : 
      47         122 :   PutFixed32(&result_, array_offset);
      48         122 :   result_.push_back(kFilterBaseLg);  // Save encoding parameter in result
      49         244 :   return Slice(result_);
      50             : }
      51             : 
      52         914 : void FilterBlockBuilder::GenerateFilter() {
      53        1828 :   const size_t num_keys = start_.size();
      54         914 :   if (num_keys == 0) {
      55             :     // Fast path if there are no keys for this filter
      56        1191 :     filter_offsets_.push_back(result_.size());
      57        1311 :     return;
      58             :   }
      59             : 
      60             :   // Make list of keys from flattened key structure
      61        1551 :   start_.push_back(keys_.size());  // Simplify length computation
      62         517 :   tmp_keys_.resize(num_keys);
      63       18754 :   for (size_t i = 0; i < num_keys; i++) {
      64       54711 :     const char* base = keys_.data() + start_[i];
      65       36474 :     size_t length = start_[i+1] - start_[i];
      66       36474 :     tmp_keys_[i] = Slice(base, length);
      67             :   }
      68             : 
      69             :   // Generate filter for current set of keys and append to result_.
      70        1551 :   filter_offsets_.push_back(result_.size());
      71         517 :   policy_->CreateFilter(&tmp_keys_[0], num_keys, &result_);
      72             : 
      73         517 :   tmp_keys_.clear();
      74         517 :   keys_.clear();
      75         517 :   start_.clear();
      76             : }
      77             : 
      78         160 : FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
      79             :                                      const Slice& contents)
      80             :     : policy_(policy),
      81             :       data_(NULL),
      82             :       offset_(NULL),
      83             :       num_(0),
      84         160 :       base_lg_(0) {
      85         160 :   size_t n = contents.size();
      86         160 :   if (n < 5) return;  // 1 byte for base_lg_ and 4 for start of offset array
      87         160 :   base_lg_ = contents[n-1];
      88         320 :   uint32_t last_word = DecodeFixed32(contents.data() + n - 5);
      89         160 :   if (last_word > n - 5) return;
      90         160 :   data_ = contents.data();
      91         160 :   offset_ = data_ + last_word;
      92         160 :   num_ = (n - 5 - last_word) / 4;
      93             : }
      94             : 
      95       16890 : bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
      96       16890 :   uint64_t index = block_offset >> base_lg_;
      97       16890 :   if (index < num_) {
      98       33780 :     uint32_t start = DecodeFixed32(offset_ + index*4);
      99       33780 :     uint32_t limit = DecodeFixed32(offset_ + index*4 + 4);
     100       16890 :     if (start <= limit && limit <= (offset_ - data_)) {
     101       16890 :       Slice filter = Slice(data_ + start, limit - start);
     102       16890 :       return policy_->KeyMayMatch(key, filter);
     103           0 :     } else if (start == limit) {
     104             :       // Empty filters do not match any keys
     105             :       return false;
     106             :     }
     107             :   }
     108           0 :   return true;  // Errors are treated as potential matches
     109             : }
     110             : 
     111             : }

Generated by: LCOV version 1.11