@@ -36,17 +36,23 @@ type Filter struct {
36
36
hashCount byte
37
37
table []byte
38
38
39
- tableSize fastdiv.Uint64
39
+ offset byte
40
+ rangeOffset byte
41
+ tableSize fastdiv.Uint64
40
42
}
41
43
42
44
// NewExplicit returns a new filter with the explicit seed and parameters.
43
45
func NewExplicit (seed , hashCount byte , sizeInBytes int ) * Filter {
46
+ offset , rangeOffset := initialConditions (seed )
47
+
44
48
return & Filter {
45
49
seed : seed ,
46
50
hashCount : hashCount ,
47
51
table : make ([]byte , sizeInBytes ),
48
52
49
- tableSize : fastdiv .NewUint64 (uint64 (sizeInBytes )),
53
+ offset : offset ,
54
+ rangeOffset : rangeOffset ,
55
+ tableSize : fastdiv .NewUint64 (uint64 (sizeInBytes )),
50
56
}
51
57
}
52
58
@@ -82,59 +88,57 @@ func (filter *Filter) Add(pieceID storj.PieceID) {
82
88
copy (id [:], pieceID [:])
83
89
copy (id [len (pieceID ):], pieceID [:])
84
90
85
- offset , rangeOffset := initialConditions ( filter .seed )
86
- for k := byte ( 0 ); k < filter . hashCount ; k ++ {
91
+ offset , rangeOffset := filter .offset , filter . rangeOffset
92
+ for h := int ( filter . hashCount ); h > 0 ; h -- {
87
93
hash , bit := binary .LittleEndian .Uint64 (id [offset :offset + 8 ]), id [offset + 8 ]
88
- offset = (offset + rangeOffset ) % len (storj.PieceID {})
89
-
90
94
bucket := filter .tableSize .Mod (hash )
91
95
filter .table [bucket ] |= 1 << (bit % 8 )
96
+ offset = (offset + rangeOffset ) % byte (len (storj.PieceID {}))
92
97
}
93
98
}
94
99
95
- // AddFilter adds the given filter into the receiver. The filters
96
- // must have a matching seed and parameters.
97
- func (filter * Filter ) AddFilter (operand * Filter ) error {
98
- switch {
99
- case filter .seed != operand .seed :
100
- return errs .New ("cannot merge: mismatched seed: expected %d but got %d" , filter .seed , operand .seed )
101
- case filter .hashCount != operand .hashCount :
102
- return errs .New ("cannot merge: mismatched hash count: expected %d but got %d" , filter .hashCount , operand .hashCount )
103
- case len (filter .table ) != len (operand .table ):
104
- return errs .New ("cannot merge: mismatched table size: expected %d but got %d" , len (filter .table ), len (operand .table ))
105
- }
106
- for i := 0 ; i < len (filter .table ); i ++ {
107
- filter .table [i ] |= operand .table [i ]
108
- }
109
- return nil
110
- }
111
-
112
100
// Contains return true if pieceID may be in the set.
113
101
func (filter * Filter ) Contains (pieceID storj.PieceID ) bool {
114
102
var id [len (pieceID ) * 2 ]byte
115
103
copy (id [:], pieceID [:])
116
104
copy (id [len (pieceID ):], pieceID [:])
117
105
118
- offset , rangeOffset := initialConditions ( filter .seed )
106
+ offset , rangeOffset := filter .offset , filter . rangeOffset
119
107
for k := byte (0 ); k < filter .hashCount ; k ++ {
120
108
hash , bit := binary .LittleEndian .Uint64 (id [offset :offset + 8 ]), id [offset + 8 ]
121
- offset = (offset + rangeOffset ) % len (storj.PieceID {})
122
-
123
109
bucket := filter .tableSize .Mod (hash )
124
110
if filter .table [bucket ]& (1 << (bit % 8 )) == 0 {
125
111
return false
126
112
}
113
+ offset = (offset + rangeOffset ) % byte (len (storj.PieceID {}))
127
114
}
128
115
129
116
return true
130
117
}
131
118
132
- func initialConditions (seed byte ) (initialOffset , rangeOffset int ) {
133
- initialOffset = int ( seed % 32 )
134
- rangeOffset = int ( rangeOffsets [int (seed / 32 )% len (rangeOffsets )])
119
+ func initialConditions (seed byte ) (initialOffset , rangeOffset byte ) {
120
+ initialOffset = seed % 32
121
+ rangeOffset = rangeOffsets [int (seed / 32 )% len (rangeOffsets )]
135
122
return initialOffset , rangeOffset
136
123
}
137
124
125
+ // AddFilter adds the given filter into the receiver. The filters
126
+ // must have a matching seed and parameters.
127
+ func (filter * Filter ) AddFilter (operand * Filter ) error {
128
+ switch {
129
+ case filter .seed != operand .seed :
130
+ return errs .New ("cannot merge: mismatched seed: expected %d but got %d" , filter .seed , operand .seed )
131
+ case filter .hashCount != operand .hashCount :
132
+ return errs .New ("cannot merge: mismatched hash count: expected %d but got %d" , filter .hashCount , operand .hashCount )
133
+ case len (filter .table ) != len (operand .table ):
134
+ return errs .New ("cannot merge: mismatched table size: expected %d but got %d" , len (filter .table ), len (operand .table ))
135
+ }
136
+ for i := 0 ; i < len (filter .table ); i ++ {
137
+ filter .table [i ] |= operand .table [i ]
138
+ }
139
+ return nil
140
+ }
141
+
138
142
// NewFromBytes decodes the filter from a sequence of bytes.
139
143
//
140
144
// Note: data will be referenced inside the table.
@@ -155,6 +159,7 @@ func NewFromBytes(data []byte) (*Filter, error) {
155
159
return nil , errs .New ("invalid hash count %d" , filter .hashCount )
156
160
}
157
161
162
+ filter .offset , filter .rangeOffset = initialConditions (filter .seed )
158
163
filter .tableSize = fastdiv .NewUint64 (uint64 (len (filter .table )))
159
164
160
165
return filter , nil
0 commit comments