Commit 6ce406bc authored by Jakub Sztandera's avatar Jakub Sztandera

Change constructor to return error

parent 885bb5be
......@@ -23,7 +23,7 @@ package bbloom
import (
"bytes"
"encoding/json"
"log"
"errors"
"math"
"sync"
"unsafe"
......@@ -50,35 +50,44 @@ func calcSizeByWrongPositives(numEntries, wrongs float64) (uint64, uint64) {
return uint64(size), uint64(locs)
}
var ErrUsage = errors.New("usage: New(float64(number_of_entries), float64(number_of_hashlocations)) i.e. New(float64(1000), float64(3)) or New(float64(number_of_entries), float64(ratio_of_false_positives)) i.e. New(float64(1000), float64(0.03))")
var ErrInvalidParms = errors.New("One of parameters was outside of allowed range")
// New
// returns a new bloomfilter
func New(params ...float64) (bloomfilter Bloom) {
func New(params ...float64) (bloomfilter *Bloom, err error) {
var entries, locs uint64
if len(params) == 2 {
if params[0] < 0 || params[1] < 0 {
return nil, ErrInvalidParms
}
if params[1] < 1 {
entries, locs = calcSizeByWrongPositives(params[0], params[1])
} else {
entries, locs = uint64(params[0]), uint64(params[1])
}
} else {
log.Fatal("usage: New(float64(number_of_entries), float64(number_of_hashlocations)) i.e. New(float64(1000), float64(3)) or New(float64(number_of_entries), float64(ratio_of_false_positives)) i.e. New(float64(1000), float64(0.03))")
return nil, ErrUsage
}
size, exponent := getSize(uint64(entries))
bloomfilter = Bloom{
bloomfilter = &Bloom{
sizeExp: exponent,
size: size - 1,
setLocs: locs,
shift: 64 - exponent,
bitset: make([]uint64, size>>6),
}
return bloomfilter
return bloomfilter, nil
}
// NewWithBoolset
// takes a []byte slice and number of locs per entry
// returns the bloomfilter with a bitset populated according to the input []byte
func NewWithBoolset(bs *[]byte, locs uint64) (bloomfilter Bloom) {
bloomfilter = New(float64(len(*bs)<<3), float64(locs))
func NewWithBoolset(bs *[]byte, locs uint64) (bloomfilter *Bloom) {
bloomfilter, err := New(float64(len(*bs)<<3), float64(locs))
if err != nil {
panic(err) // Should never happen
}
ptr := uintptr(unsafe.Pointer(&bloomfilter.bitset[0]))
for _, b := range *bs {
*(*uint8)(unsafe.Pointer(ptr)) = b
......@@ -233,7 +242,7 @@ func (bl *Bloom) isSet(idx uint64) bool {
// JSONMarshal
// returns JSON-object (type bloomJSONImExport) as []byte
func (bl *Bloom) JSONMarshal() []byte {
func (bl *Bloom) JSONMarshal() ([]byte, error) {
bl.Mtx.RLock()
defer bl.Mtx.RUnlock()
bloomImEx := bloomJSONImExport{}
......@@ -245,16 +254,13 @@ func (bl *Bloom) JSONMarshal() []byte {
ptr++
}
data, err := json.Marshal(bloomImEx)
if err != nil {
log.Fatal("json.Marshal failed: ", err)
}
return data
return data, err
}
// JSONUnmarshal
// takes JSON-Object (type bloomJSONImExport) as []bytes
// returns bloom32 / bloom64 object
func JSONUnmarshal(dbData []byte) Bloom {
func JSONUnmarshal(dbData []byte) *Bloom {
bloomImEx := bloomJSONImExport{}
json.Unmarshal(dbData, &bloomImEx)
buf := bytes.NewBuffer(bloomImEx.FilterSet)
......
......@@ -38,7 +38,10 @@ func TestMain(m *testing.M) {
}
func TestM_NumberOfWrongs(t *testing.T) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
t.Fatal(err)
}
cnt := 0
for i := range wordlist1 {
......@@ -53,7 +56,10 @@ func TestM_NumberOfWrongs(t *testing.T) {
func TestM_JSON(t *testing.T) {
const shallBe = int(1 << 16)
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
t.Fatal(err)
}
cnt := 0
for i := range wordlist1 {
......@@ -62,7 +68,10 @@ func TestM_JSON(t *testing.T) {
}
}
Json := bf.JSONMarshal()
Json, err := bf.JSONMarshal()
if err != nil {
t.Fatal(err)
}
// create new bloomfilter from bloomfilter's JSON representation
bf2 := JSONUnmarshal(Json)
......@@ -81,7 +90,10 @@ func TestM_JSON(t *testing.T) {
}
func ExampleM_NewAddHasAddIfNotHas() {
bf := New(float64(512), float64(1))
bf, err := New(float64(512), float64(1))
if err != nil {
panic(err)
}
fmt.Printf("%v %v %v %v\n", bf.sizeExp, bf.size, bf.setLocs, bf.shift)
......@@ -114,12 +126,15 @@ func ExampleM_NewAddHasAddIfNotHas() {
func BenchmarkM_New(b *testing.B) {
for r := 0; r < b.N; r++ {
_ = New(float64(n*10), float64(7))
_, _ = New(float64(n*10), float64(7))
}
}
func BenchmarkM_Clear(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
for i := range wordlist1 {
bf.Add(wordlist1[i])
}
......@@ -130,7 +145,10 @@ func BenchmarkM_Clear(b *testing.B) {
}
func BenchmarkM_Add(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for r := 0; r < b.N; r++ {
for i := range wordlist1 {
......@@ -151,7 +169,10 @@ func BenchmarkM_Has(b *testing.B) {
}
func BenchmarkM_AddIfNotHasFALSE(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
for i := range wordlist1 {
bf.Has(wordlist1[i])
}
......@@ -164,7 +185,10 @@ func BenchmarkM_AddIfNotHasFALSE(b *testing.B) {
}
func BenchmarkM_AddIfNotHasClearTRUE(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for r := 0; r < b.N; r++ {
......@@ -176,7 +200,10 @@ func BenchmarkM_AddIfNotHasClearTRUE(b *testing.B) {
}
func BenchmarkM_AddTS(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for r := 0; r < b.N; r++ {
......@@ -198,7 +225,10 @@ func BenchmarkM_HasTS(b *testing.B) {
}
func BenchmarkM_AddIfNotHasTSFALSE(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
for i := range wordlist1 {
bf.Has(wordlist1[i])
}
......@@ -211,7 +241,10 @@ func BenchmarkM_AddIfNotHasTSFALSE(b *testing.B) {
}
func BenchmarkM_AddIfNotHasTSClearTRUE(b *testing.B) {
bf = New(float64(n*10), float64(7))
bf, err := New(float64(n*10), float64(7))
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for r := 0; r < b.N; r++ {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment