@@ -45,6 +45,7 @@ type BloomFilter struct {
4545 seeds []int64
4646
4747 path string
48+ opts * BloomOptions
4849}
4950
5051// BloomOptions is the options for creating a new bloom filter
@@ -71,7 +72,7 @@ type BloomOptions struct {
7172var DefaultBloomOptions = BloomOptions {
7273 Path : "bloom.db" ,
7374 Err_rate : 0.001 ,
74- Capacity : 100000 ,
75+ Capacity : 10000 ,
7576 GrowthRate : 2 ,
7677 Database : nil ,
7778}
@@ -89,8 +90,8 @@ func NewBloom(opts *BloomOptions) *BloomFilter {
8990 if opts .Err_rate <= 0 || opts .Err_rate >= 1 {
9091 panic ("Error rate must be between 0 and 1" )
9192 }
92- if opts .Capacity <= 0 {
93- panic ("Capacity must be greater than 0 " )
93+ if opts .Capacity <= 10 {
94+ panic ("Capacity must be greater than 10 " )
9495 }
9596
9697 // number of hash functions (k)
@@ -114,11 +115,6 @@ func NewBloom(opts *BloomOptions) *BloomFilter {
114115 opts .Path = "/tmp/bloom.db"
115116 }
116117
117- f , err := os .OpenFile (opts .Path , os .O_RDWR | os .O_CREATE , 0644 )
118- if err != nil {
119- log .Fatalf ("error opening file: %v" , err )
120- }
121-
122118 var b byte
123119 byteSize := int (unsafe .Sizeof (& b ))
124120
@@ -127,23 +123,12 @@ func NewBloom(opts *BloomOptions) *BloomFilter {
127123 bit_width += byteSize // add extra 1 byte to ensure we have a full byte at the end
128124
129125 pageOffset := opts .dataSize
130- opts .dataSize += bit_width
126+ opts .dataSize += bit_width // will be the offset of the next filter
131127
132- if err := f .Truncate (int64 (opts .dataSize )); err != nil {
133- log .Fatalf ("Error truncating file: %s" , err )
134- }
135-
136- mem , err := mmap .MapRegion (f , opts .dataSize , mmap .RDWR , 0 , 0 )
137- if err != nil {
138- log .Fatalf ("Mmap error: %v" , err )
139- }
140-
141- return & BloomFilter {
128+ bf := & BloomFilter {
142129 err_rate : opts .Err_rate ,
143130 capacity : opts .Capacity ,
144131 bit_width : bit_width ,
145- memFile : f ,
146- mem : mem ,
147132 m : bits_per_slice ,
148133 seeds : seeds ,
149134 db : opts .Database ,
@@ -152,7 +137,15 @@ func NewBloom(opts *BloomOptions) *BloomFilter {
152137 path : opts .Path ,
153138 k : numHashFn ,
154139 pageOffset : pageOffset ,
140+ opts : opts ,
141+ }
142+
143+ err := bf .mmap ()
144+ if err != nil {
145+ log .Fatalf ("Mmap error: %v" , err )
155146 }
147+
148+ return bf
156149}
157150
158151// Add adds the key to the bloom filter
@@ -338,13 +331,7 @@ func (bf *BloomFilter) Close() error {
338331 _ = bf .memFile .Close ()
339332 return err
340333 }
341-
342- if err := bf .mem .Unmap (); err != nil {
343- _ = bf .memFile .Close ()
344- return err
345- }
346-
347- return bf .memFile .Close ()
334+ return bf .unmap ()
348335}
349336
350337// Count returns the number of items added to the bloom filter
@@ -392,6 +379,26 @@ func (bf *BloomFilter) Stats() BloomFilterStats {
392379 }
393380}
394381
382+ // mmap opens a the filter file and maps it into memory
383+ func (bf * BloomFilter ) mmap () error {
384+ var err error
385+ bf .memFile , err = os .OpenFile (bf .path , os .O_RDWR | os .O_CREATE , 0666 )
386+ if err != nil {
387+ return fmt .Errorf ("Unable to open bloom filter file: %s" , err )
388+ }
389+
390+ if err := bf .memFile .Truncate (int64 (bf .opts .dataSize )); err != nil {
391+ log .Fatalf ("Error truncating file: %s" , err )
392+ }
393+
394+ bf .mem , err = mmap .MapRegion (bf .memFile , bf .opts .dataSize , mmap .RDWR , 0 , 0 )
395+ if err != nil {
396+ return fmt .Errorf ("Unable to mmap bloom filter file: %s" , err )
397+ }
398+
399+ return nil
400+ }
401+
395402// divmod returns the quotient and remainder of a/b
396403func divmod (num , denom int64 ) (quot , rem int64 ) {
397404 quot = num / denom
0 commit comments