Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
bloom.cc
Go to the documentation of this file.
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 
6 
7 #include "leveldb/slice.h"
8 #include "util/hash.h"
9 
10 namespace leveldb {
11 
12 namespace {
13 static uint32_t BloomHash(const Slice& key) {
14  return Hash(key.data(), key.size(), 0xbc9f1d34);
15 }
16 
17 class BloomFilterPolicy : public FilterPolicy {
18  private:
19  size_t bits_per_key_;
20  size_t k_;
21 
22  public:
23  explicit BloomFilterPolicy(int bits_per_key)
24  : bits_per_key_(bits_per_key) {
25  // We intentionally round down to reduce probing cost a little bit
26  k_ = static_cast<size_t>(bits_per_key * 0.69); // 0.69 =~ ln(2)
27  if (k_ < 1) k_ = 1;
28  if (k_ > 30) k_ = 30;
29  }
30 
31  virtual const char* Name() const {
32  return "leveldb.BuiltinBloomFilter";
33  }
34 
35  virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
36  // Compute bloom filter size (in both bits and bytes)
37  size_t bits = n * bits_per_key_;
38 
39  // For small n, we can see a very high false positive rate. Fix it
40  // by enforcing a minimum bloom filter length.
41  if (bits < 64) bits = 64;
42 
43  size_t bytes = (bits + 7) / 8;
44  bits = bytes * 8;
45 
46  const size_t init_size = dst->size();
47  dst->resize(init_size + bytes, 0);
48  dst->push_back(static_cast<char>(k_)); // Remember # of probes in filter
49  char* array = &(*dst)[init_size];
50  for (size_t i = 0; i < n; i++) {
51  // Use double-hashing to generate a sequence of hash values.
52  // See analysis in [Kirsch,Mitzenmacher 2006].
53  uint32_t h = BloomHash(keys[i]);
54  const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
55  for (size_t j = 0; j < k_; j++) {
56  const uint32_t bitpos = h % bits;
57  array[bitpos/8] |= (1 << (bitpos % 8));
58  h += delta;
59  }
60  }
61  }
62 
63  virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const {
64  const size_t len = bloom_filter.size();
65  if (len < 2) return false;
66 
67  const char* array = bloom_filter.data();
68  const size_t bits = (len - 1) * 8;
69 
70  // Use the encoded k so that we can read filters generated by
71  // bloom filters created using different parameters.
72  const size_t k = array[len-1];
73  if (k > 30) {
74  // Reserved for potentially new encodings for short bloom filters.
75  // Consider it a match.
76  return true;
77  }
78 
79  uint32_t h = BloomHash(key);
80  const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
81  for (size_t j = 0; j < k; j++) {
82  const uint32_t bitpos = h % bits;
83  if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false;
84  h += delta;
85  }
86  return true;
87  }
88 };
89 }
90 
91 const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) {
92  return new BloomFilterPolicy(bits_per_key);
93 }
94 
95 } // namespace leveldb
uint32_t Hash(const char *data, size_t n, uint32_t seed)
Definition: hash.cc:18
size_t bits_per_key_
Definition: bloom.cc:19
unsigned int uint32_t
Definition: stdint.h:21
const FilterPolicy * NewBloomFilterPolicy(int bits_per_key)
Definition: bloom.cc:91
size_t k_
Definition: bloom.cc:20