...
1
2
3
4
5
6
7 package filter
8
9 import (
10 "github.com/syndtr/goleveldb/leveldb/util"
11 )
12
13 func bloomHash(key []byte) uint32 {
14 return util.Hash(key, 0xbc9f1d34)
15 }
16
17 type bloomFilter int
18
19
20
21
22 func (bloomFilter) Name() string {
23 return "leveldb.BuiltinBloomFilter"
24 }
25
26 func (f bloomFilter) Contains(filter, key []byte) bool {
27 nBytes := len(filter) - 1
28 if nBytes < 1 {
29 return false
30 }
31 nBits := uint32(nBytes * 8)
32
33
34
35 k := filter[nBytes]
36 if k > 30 {
37
38
39 return true
40 }
41
42 kh := bloomHash(key)
43 delta := (kh >> 17) | (kh << 15)
44 for j := uint8(0); j < k; j++ {
45 bitpos := kh % nBits
46 if (uint32(filter[bitpos/8]) & (1 << (bitpos % 8))) == 0 {
47 return false
48 }
49 kh += delta
50 }
51 return true
52 }
53
54 func (f bloomFilter) NewGenerator() FilterGenerator {
55
56 k := uint8(f * 69 / 100)
57 if k < 1 {
58 k = 1
59 } else if k > 30 {
60 k = 30
61 }
62 return &bloomFilterGenerator{
63 n: int(f),
64 k: k,
65 }
66 }
67
68 type bloomFilterGenerator struct {
69 n int
70 k uint8
71
72 keyHashes []uint32
73 }
74
75 func (g *bloomFilterGenerator) Add(key []byte) {
76
77
78 g.keyHashes = append(g.keyHashes, bloomHash(key))
79 }
80
81 func (g *bloomFilterGenerator) Generate(b Buffer) {
82
83 nBits := uint32(len(g.keyHashes) * g.n)
84
85
86 if nBits < 64 {
87 nBits = 64
88 }
89 nBytes := (nBits + 7) / 8
90 nBits = nBytes * 8
91
92 dest := b.Alloc(int(nBytes) + 1)
93 dest[nBytes] = g.k
94 for _, kh := range g.keyHashes {
95 delta := (kh >> 17) | (kh << 15)
96 for j := uint8(0); j < g.k; j++ {
97 bitpos := kh % nBits
98 dest[bitpos/8] |= (1 << (bitpos % 8))
99 kh += delta
100 }
101 }
102
103 g.keyHashes = g.keyHashes[:0]
104 }
105
106
107
108
109
110
111
112
113
114 func NewBloomFilter(bitsPerKey int) Filter {
115 return bloomFilter(bitsPerKey)
116 }
117
View as plain text