Merge pull request #831 from molecula/rbf-tx-cursor-stack-allocate

Stack allocate return from rbf.Tx.cursor()
This commit is contained in:
jaten-molecula 2020-09-16 23:40:32 -04:00 committed by GitHub
commit 7dc59c4d9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 66 deletions

View file

@ -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)

View file

@ -594,8 +594,6 @@ func (db *DB) HasData(requireOneHotBit bool) (hasAnyRecords bool, err error) {
cur, err := tx.Cursor(record.Name)
if err != nil {
return false, err
} else if cur == nil {
continue // no bitmap
}
if !requireOneHotBit {
return true, nil

View file

@ -504,10 +504,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 {
@ -531,38 +531,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.
@ -577,10 +575,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()
@ -617,9 +615,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
@ -673,10 +671,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
}
@ -1011,14 +1009,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
@ -1035,10 +1031,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
}
@ -1103,10 +1099,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
}
@ -1129,10 +1125,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 {
@ -1148,10 +1144,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 {
@ -1196,10 +1192,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)
@ -1266,7 +1262,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
}
@ -1274,11 +1272,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 {
@ -1306,7 +1299,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.
@ -1502,7 +1495,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
@ -1523,7 +1516,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
}
@ -1541,7 +1534,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
}
@ -1558,7 +1551,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

View file

@ -363,13 +363,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)
}
@ -389,8 +389,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) {