1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
2 // All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
10 "github.com/syndtr/goleveldb/leveldb/util"
13 func bloomHash(key []byte) uint32 {
14 return util.Hash(key, 0xbc9f1d34)
19 // The bloom filter serializes its parameters and is backward compatible
20 // with respect to them. Therefor, its parameters are not added to its
22 func (bloomFilter) Name() string {
23 return "leveldb.BuiltinBloomFilter"
26 func (f bloomFilter) Contains(filter, key []byte) bool {
27 nBytes := len(filter) - 1
31 nBits := uint32(nBytes * 8)
33 // Use the encoded k so that we can read filters generated by
34 // bloom filters created using different parameters.
37 // Reserved for potentially new encodings for short bloom filters.
38 // Consider it a match.
43 delta := (kh >> 17) | (kh << 15) // Rotate right 17 bits
44 for j := uint8(0); j < k; j++ {
46 if (uint32(filter[bitpos/8]) & (1 << (bitpos % 8))) == 0 {
54 func (f bloomFilter) NewGenerator() FilterGenerator {
55 // Round down to reduce probing cost a little bit.
56 k := uint8(f * 69 / 100) // 0.69 =~ ln(2)
62 return &bloomFilterGenerator{
68 type bloomFilterGenerator struct {
75 func (g *bloomFilterGenerator) Add(key []byte) {
76 // Use double-hashing to generate a sequence of hash values.
77 // See analysis in [Kirsch,Mitzenmacher 2006].
78 g.keyHashes = append(g.keyHashes, bloomHash(key))
81 func (g *bloomFilterGenerator) Generate(b Buffer) {
82 // Compute bloom filter size (in both bits and bytes)
83 nBits := uint32(len(g.keyHashes) * g.n)
84 // For small n, we can see a very high false positive rate. Fix it
85 // by enforcing a minimum bloom filter length.
89 nBytes := (nBits + 7) / 8
92 dest := b.Alloc(int(nBytes) + 1)
94 for _, kh := range g.keyHashes {
95 delta := (kh >> 17) | (kh << 15) // Rotate right 17 bits
96 for j := uint8(0); j < g.k; j++ {
98 dest[bitpos/8] |= (1 << (bitpos % 8))
103 g.keyHashes = g.keyHashes[:0]
106 // NewBloomFilter creates a new initialized bloom filter for given
109 // Since bitsPerKey is persisted individually for each bloom filter
110 // serialization, bloom filters are backwards compatible with respect to
111 // changing bitsPerKey. This means that no big performance penalty will
112 // be experienced when changing the parameter. See documentation for
113 // opt.Options.Filter for more information.
114 func NewBloomFilter(bitsPerKey int) Filter {
115 return bloomFilter(bitsPerKey)