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