diff --git a/rbf/cursor_test.go b/rbf/cursor_test.go index ca946ef86..40f2756f0 100644 --- a/rbf/cursor_test.go +++ b/rbf/cursor_test.go @@ -1015,8 +1015,8 @@ func TestCursor_PlayContainer(t *testing.T) { } cur, _ := tx.Cursor("x") offset := uint64(0) - many(cur, 0, rbf.ArrayMaxSize+offset) - many(cur, 65536, rbf.ArrayMaxSize+offset) + many(&cur, 0, rbf.ArrayMaxSize+offset) + many(&cur, 65536, rbf.ArrayMaxSize+offset) /* many(cur, 2*65536, rbf.ArrayMaxSize+offset) many(cur, 3*65536, rbf.ArrayMaxSize) //+offset) diff --git a/rbf/tx.go b/rbf/tx.go index 9b7e69111..069f7441b 100644 --- a/rbf/tx.go +++ b/rbf/tx.go @@ -502,10 +502,10 @@ func (tx *Tx) Remove(name string, a ...uint64) (changeCount int, err error) { } c, err := tx.cursor(name) - if err != nil { - return 0, err - } else if c == nil { + if err == ErrBitmapNotFound { return 0, nil + } else if err != nil { + return 0, err } for _, v := range a { if vchanged, err := c.Remove(v); err != nil { @@ -529,38 +529,36 @@ func (tx *Tx) Contains(name string, v uint64) (bool, error) { } c, err := tx.cursor(name) - if err != nil { - return false, err - } else if c == nil { + if err == ErrBitmapNotFound { return false, nil + } else if err != nil { + return false, err } return c.Contains(v) } // Cursor returns an instance of a cursor this bitmap. -func (tx *Tx) Cursor(name string) (*Cursor, error) { +func (tx *Tx) Cursor(name string) (Cursor, error) { tx.mu.RLock() defer tx.mu.RUnlock() return tx.cursor(name) } -func (tx *Tx) cursor(name string) (*Cursor, error) { +func (tx *Tx) cursor(name string) (Cursor, error) { if tx.db == nil { - return nil, ErrTxClosed + return Cursor{}, ErrTxClosed } else if name == "" { - return nil, ErrBitmapNameRequired + return Cursor{}, ErrBitmapNameRequired } root, err := tx.root(name) - if err == ErrBitmapNotFound { - return nil, nil - } else if err != nil { - return nil, err + if err != nil { + return Cursor{}, err } c := Cursor{tx: tx} c.stack.elems[0] = stackElem{pgno: root} - return &c, nil + return c, nil } // RoaringBitmap returns a bitmap as a Roaring bitmap. @@ -575,10 +573,10 @@ func (tx *Tx) RoaringBitmap(name string) (*roaring.Bitmap, error) { } c, err := tx.cursor(name) - if err != nil { - return nil, err - } else if c == nil { + if err == ErrBitmapNotFound { return roaring.NewSliceBitmap(), nil + } else if err != nil { + return nil, err } other := roaring.NewSliceBitmap() @@ -615,9 +613,9 @@ func (tx *Tx) container(name string, key uint64) (*roaring.Container, error) { } c, err := tx.cursor(name) - if err != nil { - return nil, err - } else if c == nil { + if err == ErrBitmapNotFound { + return nil, nil + } else if err != nil { return nil, err } else if exact, err := c.Seek(key); err != nil || !exact { return nil, err @@ -671,10 +669,10 @@ func (tx *Tx) RemoveContainer(name string, key uint64) error { func (tx *Tx) removeContainer(name string, key uint64) error { c, err := tx.cursor(name) - if err != nil { - return err - } else if c == nil { + if err == ErrBitmapNotFound { return nil + } else if err != nil { + return err } else if exact, err := c.Seek(key); err != nil || !exact { return err } @@ -1007,14 +1005,12 @@ func (tx *Tx) ContainerIterator(name string, key uint64) (citer roaring.Containe defer tx.mu.RUnlock() c, err := tx.cursor(name) - if c == nil && err == nil { + if err == ErrBitmapNotFound { return &emptyContainerIterator{}, false, nil // nothing available. } else if err != nil { return nil, false, err } - // INVAR: c is not nil - exact, err := c.Seek(key) if err != nil { return nil, false, err @@ -1031,10 +1027,10 @@ func (tx *Tx) ForEachRange(name string, start, end uint64, fn func(uint64) error defer tx.mu.RUnlock() c, err := tx.cursor(name) - if err != nil { - return err - } else if c == nil { + if err == ErrBitmapNotFound { return nil + } else if err != nil { + return err } else if _, err := c.Seek(highbits(start)); err != nil { return err } @@ -1099,10 +1095,10 @@ func (tx *Tx) Count(name string) (uint64, error) { defer tx.mu.RUnlock() c, err := tx.cursor(name) - if err != nil { - return 0, err - } else if c == nil { + if err == ErrBitmapNotFound { return 0, nil + } else if err != nil { + return 0, err } else if err := c.First(); err != nil { return 0, err } @@ -1125,10 +1121,10 @@ func (tx *Tx) Max(name string) (uint64, error) { defer tx.mu.RUnlock() c, err := tx.cursor(name) - if err != nil { - return 0, err - } else if c == nil { + if err == ErrBitmapNotFound { return 0, nil + } else if err != nil { + return 0, err } else if err := c.Last(); err == io.EOF { return 0, nil } else if err != nil { @@ -1144,10 +1140,10 @@ func (tx *Tx) Min(name string) (uint64, bool, error) { defer tx.mu.RUnlock() c, err := tx.cursor(name) - if err != nil { - return 0, false, err - } else if c == nil { + if err == ErrBitmapNotFound { return 0, false, nil + } else if err != nil { + return 0, false, err } else if err := c.First(); err == io.EOF { return 0, false, nil } else if err != nil { @@ -1192,10 +1188,10 @@ func (tx *Tx) CountRange(name string, start, end uint64) (uint64, error) { ekey := highbits(end) csr, err := tx.cursor(name) - if err != nil { - return 0, err - } else if csr == nil { + if err == ErrBitmapNotFound { return 0, nil + } else if err != nil { + return 0, err } exact, err := csr.Seek(skey) @@ -1262,7 +1258,9 @@ func (tx *Tx) OffsetRange(name string, offset, start, endx uint64) (*roaring.Bit defer tx.mu.Unlock() c, err := tx.cursor(name) - if err != nil { + if err == ErrBitmapNotFound { + return roaring.NewSliceBitmap(), nil + } else if err != nil { return nil, err } @@ -1270,11 +1268,6 @@ func (tx *Tx) OffsetRange(name string, offset, start, endx uint64) (*roaring.Bit off := highbits(offset) hi0, hi1 := highbits(start), highbits(endx) - if c == nil { - // bitmap not found. Match what roaring does and return nil in this case. - return other, nil - } - if _, err := c.Seek(hi0); err == io.EOF { return other, nil } else if err != nil { @@ -1302,7 +1295,7 @@ func (tx *Tx) OffsetRange(name string, offset, start, endx uint64) (*roaring.Bit // containerIterator wraps Cursor to implement roaring.ContainerIterator. type containerIterator struct { - cursor *Cursor + cursor Cursor } // Close is a no-op. It exists to implement the roaring.ContainerIterator interface. @@ -1496,7 +1489,7 @@ func (tx *Tx) ImportRoaringBits(name string, itr roaring.RoaringIterator, clear changed += nsynth rowSet[currRow] += nsynth - if err := tx.putContainerWithCursor(cur, itrKey, synthC); err != nil { + if err := tx.putContainerWithCursor(&cur, itrKey, synthC); err != nil { return changed, rowSet, err } continue @@ -1517,7 +1510,7 @@ func (tx *Tx) ImportRoaringBits(name string, itr roaring.RoaringIterator, clear changes := int(existN - newC.N()) changed += changes rowSet[currRow] -= changes - err = tx.putContainerWithCursor(cur, itrKey, newC) + err = tx.putContainerWithCursor(&cur, itrKey, newC) if err != nil { return } @@ -1535,7 +1528,7 @@ func (tx *Tx) ImportRoaringBits(name string, itr roaring.RoaringIterator, clear // can nsynth be zero? No, because of the continue/invariant above where nsynth > 0 changed += nsynth rowSet[currRow] += nsynth - err = tx.putContainerWithCursor(cur, itrKey, synthC) + err = tx.putContainerWithCursor(&cur, itrKey, synthC) if err != nil { return } @@ -1552,7 +1545,7 @@ func (tx *Tx) ImportRoaringBits(name string, itr roaring.RoaringIterator, clear changed += changes rowSet[currRow] += changes - err = tx.putContainerWithCursor(cur, itrKey, newC) + err = tx.putContainerWithCursor(&cur, itrKey, newC) if err != nil { panicOn(err) return diff --git a/rbf/tx_test.go b/rbf/tx_test.go index b9bc99373..49f84c391 100644 --- a/rbf/tx_test.go +++ b/rbf/tx_test.go @@ -362,13 +362,13 @@ func TestTx_CursorCrashArray(t *testing.T) { if err != nil { t.Fatal(err) } - //setArray(t, 0, 2379, c) - //setArray(t, 1, 2337, c) - setArray(t, 32, 1216, c) - setArray(t, 33, 1195, c) - setArray(t, 48, 1186, c) - setArray(t, 49, 1223, c) - setArray(t, 50, 1223, c) + //setArray(t, 0, 2379, &c) + //setArray(t, 1, 2337, &c) + setArray(t, 32, 1216, &c) + setArray(t, 33, 1195, &c) + setArray(t, 48, 1186, &c) + setArray(t, 49, 1223, &c) + setArray(t, 50, 1223, &c) } @@ -388,8 +388,8 @@ func TestTx_CursorCrashBitmap(t *testing.T) { if err != nil { t.Fatal(err) } - setArray(t, 0, 22510, c) - setArray(t, 1, 23584, c) + setArray(t, 0, 22510, &c) + setArray(t, 1, 23584, &c) } func setArray(tb testing.TB, key, num int, c *rbf.Cursor) {