diff --git a/rbf/cursor.go b/rbf/cursor.go index 66f721039..9bb59fb6b 100644 --- a/rbf/cursor.go +++ b/rbf/cursor.go @@ -84,7 +84,7 @@ func runAdd(runs []roaring.Interval16, v uint16) ([]roaring.Interval16, bool) { } return runs, true } -func checkRun(runs []roaring.Interval16, key uint64) leafArgs { +func checkRun(runs []roaring.Interval16, key uint64) leafCell { if len(runs) >= RLEMaxSize { //convertToBitmap bitmap := make([]uint64, BitmapN) @@ -123,9 +123,9 @@ func checkRun(runs []roaring.Interval16, key uint64) leafArgs { n += popcount(v) } - return leafArgs{Key: key, N: int(n), Type: ContainerTypeBitmap, Data: fromArray64(bitmap)} + return leafCell{Key: key, N: int(n), Type: ContainerTypeBitmap, Data: fromArray64(bitmap)} } - return leafArgs{Key: key, N: len(runs), Type: ContainerTypeRLE, Data: fromInterval16(runs)} + return leafCell{Key: key, N: len(runs), Type: ContainerTypeRLE, Data: fromInterval16(runs)} } // Add sets a bit on the underlying bitmap. @@ -136,7 +136,7 @@ func (c *Cursor) Add(v uint64) (changed bool, err error) { if exact, err := c.Seek(hi); err != nil { return false, err } else if !exact { - return true, c.putLeafCell(leafArgs{Key: hi, Type: ContainerTypeArray, N: 1, Data: fromArray16([]uint16{lo})}) + return true, c.putLeafCell(leafCell{Key: hi, Type: ContainerTypeArray, N: 1, Data: fromArray16([]uint16{lo})}) } // If the container exists and bit is not set then update the page. @@ -155,7 +155,7 @@ func (c *Cursor) Add(v uint64) (changed bool, err error) { copy(other, a[:i]) other[i] = lo copy(other[i+1:], a[i:]) - return true, c.putLeafCell(leafArgs{Key: cell.Key, Type: ContainerTypeArray, N: len(other), Data: fromArray16(other)}) + return true, c.putLeafCell(leafCell{Key: cell.Key, Type: ContainerTypeArray, N: len(other), Data: fromArray16(other)}) case ContainerTypeRLE: runs := toInterval16(cell.Data) @@ -167,7 +167,7 @@ func (c *Cursor) Add(v uint64) (changed bool, err error) { return true, c.putLeafCell(leaf) } return false, nil - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: // Exit if bit set in bitmap container. pgno, bm, err := c.tx.leafCellBitmap(toPgno(cell.Data)) @@ -220,7 +220,7 @@ func (c *Cursor) Remove(v uint64) (changed bool, err error) { other := make([]uint16, len(a)-1) copy(other[:i], a[:i]) copy(other[i:], a[i+1:]) - return true, c.putLeafCell(leafArgs{Key: cell.Key, Type: ContainerTypeArray, N: len(other), Data: fromArray16(other)}) + return true, c.putLeafCell(leafCell{Key: cell.Key, Type: ContainerTypeArray, N: len(other), Data: fromArray16(other)}) case ContainerTypeRLE: r := toInterval16(cell.Data) @@ -247,8 +247,8 @@ func (c *Cursor) Remove(v uint64) (changed bool, err error) { if len(runs) == 0 { return true, c.deleteLeafCell(cell.Key) } - return true, c.putLeafCell(leafArgs{Key: cell.Key, Type: ContainerTypeRLE, N: len(runs), Data: fromInterval16(runs)}) - case ContainerTypeBitmap: + return true, c.putLeafCell(leafCell{Key: cell.Key, Type: ContainerTypeRLE, N: len(runs), Data: fromInterval16(runs)}) + case ContainerTypeBitmapPtr: pgno, bm, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return false, errors.Wrap(err, "cursor.add") @@ -298,7 +298,7 @@ func (c *Cursor) Contains(v uint64) (exists bool, err error) { return (lo >= a[i].Start) && (lo <= a[i].Last), nil } return false, nil - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, a, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return false, errors.Wrap(err, "cursor.Contains") @@ -317,33 +317,33 @@ func fromPgno(val uint32) []byte { func toPgno(val []byte) uint32 { return binary.LittleEndian.Uint32(val) } -func (c *Cursor) putLeafCell(in leafArgs) (err error) { +func (c *Cursor) putLeafCell(in leafCell) (err error) { cells := readLeafCells(c.leafPage, c.leafCells[:]) elem := &c.stack.elems[c.stack.index] - cell := leafCell(in) - + cell := in if elem.index >= len(cells) || c.Key() != cell.Key { //new cell - if cell.Type == ContainerTypeBitmap { + if in.Type == ContainerTypeBitmap { //allocated bitmap() bitmapPgno, _ := c.tx.allocate() cell.Data = fromPgno(bitmapPgno) + cell.Type = ContainerTypeBitmapPtr } - // Shift cells over if this is an insertion. cells = append(cells, leafCell{}) copy(cells[elem.index+1:], cells[elem.index:]) - } else if in.Type == ContainerTypeBitmap { - ecell := cells[elem.index] - if ecell.Type != ContainerTypeBitmap { - bitmapPgno, err := c.tx.allocate() - if err != nil { - return errors.Wrap(err, "cursor.putLeafCell") + } else { + if in.Type == ContainerTypeBitmap { + cell = cells[elem.index] + if cell.Type != ContainerTypeBitmapPtr { + bitmapPgno, err := c.tx.allocate() + if err != nil { + return errors.Wrap(err, "cursor.putLeafCell") + } + cell.Type = ContainerTypeBitmapPtr + cell.Data = fromPgno(bitmapPgno) } - cell.Data = fromPgno(bitmapPgno) - } else { - cell.Data = ecell.Data //fill in the old pgno } } @@ -355,7 +355,7 @@ func (c *Cursor) putLeafCell(in leafArgs) (err error) { a[v/64] |= 1 << uint64(v%64) } in.Data = fromArray64(a) - cell.Type = ContainerTypeBitmap + cell.Type = ContainerTypeBitmapPtr bitmapPgno, _ := c.tx.allocate() cell.Data = fromPgno(bitmapPgno) } @@ -436,7 +436,7 @@ func (c *Cursor) deleteLeafCell(key uint64) (err error) { elem := &c.stack.elems[c.stack.index] oldPageKey := cells[0].Key cell := c.cell() - if cell.Type == ContainerTypeBitmap { + if cell.Type == ContainerTypeBitmapPtr { if err := c.tx.deallocate(toPgno(cell.Data)); err != nil { return err } @@ -957,7 +957,7 @@ func (c *Cursor) Union(rowID uint64, row []uint64) error { } case ContainerTypeRLE: panic("TODO(BBJ): rbf.Bitmap.Union() RLE support") - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, bm, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return errors.Wrap(err, "union") @@ -1005,7 +1005,7 @@ func (c *Cursor) Intersect(rowID uint64, row []uint64) error { } case ContainerTypeRLE: panic("TODO(BBJ): rbf.Bitmap.Intersect() RLE support") - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, bm, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return errors.Wrap(err, "cursor.Intersect") @@ -1086,7 +1086,7 @@ func (c *Cursor) goNextPage() error { } } -func ConvertToLeafArgs(key uint64, c *roaring.Container) (result leafArgs) { +func ConvertToLeafArgs(key uint64, c *roaring.Container) (result leafCell) { result.Key = key result.N = int(c.N()) result.Type = ContainerTypeNone @@ -1131,7 +1131,7 @@ func (c *Cursor) merge(key uint64, data *roaring.Container) (bool, error) { case ContainerTypeArray: d := toArray16(cell.Data) container = roaring.NewContainerArray(d) - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, d, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return false, errors.Wrap(err, "cursor.merge") @@ -1218,7 +1218,7 @@ func (c *Cursor) difference(key uint64, data *roaring.Container) (bool, error) { case ContainerTypeArray: d := toArray16(cell.Data) container = roaring.NewContainerArray(d) - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, d, err := c.tx.leafCellBitmap(toPgno(cell.Data)) if err != nil { return false, errors.Wrap(err, "cursor.difference") diff --git a/rbf/cursor_test.go b/rbf/cursor_test.go index dae1c246c..f4f16cf08 100644 --- a/rbf/cursor_test.go +++ b/rbf/cursor_test.go @@ -803,8 +803,6 @@ func TestCursor_RLEConversion(t *testing.T) { } if got, want := c.Values(), want; !reflect.DeepEqual(got, want) { t.Fatalf("Values()=%#v, want %#v", got, want) - } else if c.CurrentPageType() != rbf.ContainerTypeBitmap { - t.Fatalf("Should be bitmap but is %v", c.CurrentPageType()) } } diff --git a/rbf/cursorx.go b/rbf/cursorx.go index 767ff564a..8a317c184 100644 --- a/rbf/cursorx.go +++ b/rbf/cursorx.go @@ -126,7 +126,7 @@ func (c *Cursor) Row(rowID uint64) (*roaring.Bitmap, error) { if cell.Key >= hi1 { break } - other.Containers.Put(off+(cell.Key-hi0), toContainer(cell)) + other.Containers.Put(off+(cell.Key-hi0), toContainer(cell, c.tx)) } return other, nil } @@ -138,10 +138,13 @@ func (c *Cursor) CurrentPageType() int { return cell.Type } -func toContainer(l leafCell) *roaring.Container { +func toContainer(l leafCell, tx *Tx) *roaring.Container { switch l.Type { case ContainerTypeArray: return roaring.NewContainerArray(toArray16(l.Data)) + case ContainerTypeBitmapPtr: + _, bm, _ := tx.leafCellBitmap(toPgno(l.Data)) + return roaring.NewContainerBitmap(l.N, bm) case ContainerTypeBitmap: return roaring.NewContainerBitmap(l.N, toArray64(l.Data)) case ContainerTypeRLE: @@ -181,11 +184,7 @@ func Page(tx *Tx, pgno uint32, walker Walker) { walker.Visit(pgno, Branch) for i, n := 0, readCellN(page); i < n; i++ { cell := readBranchCell(page, i) - if cell.Flags&ContainerTypeBitmap == 0 { // leaf/branch child page - Page(tx, cell.Pgno, walker) - } else { - walker.Visit(cell.Pgno, Bitmap) - } + Page(tx, cell.Pgno, walker) } case PageTypeLeaf: walker.Visit(pgno, Leaf) diff --git a/rbf/dot.go b/rbf/dot.go index adbb96dcf..6914b7aaf 100644 --- a/rbf/dot.go +++ b/rbf/dot.go @@ -29,7 +29,7 @@ func dotCell(b []byte, parent string, writer io.Writer) { fmt.Fprintf(writer, "[%d]: key=%d type=array n=%d\n", i, cell.Key, cell.N) case ContainerTypeRLE: fmt.Fprintf(writer, "[%d]: key=%d type=rle n=%d\n", i, cell.Key, cell.N) - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: bpn := toPgno(cell.Data) fmt.Fprintf(writer, "[%d]: key=%d type=bitmap n=%d \n", bpn, i, cell.Key, cell.N) links = append(links, fmt.Sprintf("bitmap%d[label=\"bitmap (%d)\"]\n cell%d:%d -> bitmap%d\n", bpn, bpn, pgno, i, bpn)) diff --git a/rbf/rbf.go b/rbf/rbf.go index cc0132599..a1be23951 100644 --- a/rbf/rbf.go +++ b/rbf/rbf.go @@ -67,6 +67,7 @@ const ( ContainerTypeArray ContainerTypeRLE ContainerTypeBitmap + ContainerTypeBitmapPtr ) const ( @@ -295,7 +296,7 @@ func (c *leafCell) Bitmap(tx *Tx) []uint64 { } } return buf - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: _, bm, _ := tx.leafCellBitmap(toPgno(c.Data)) return bm default: @@ -320,7 +321,7 @@ func (c *leafCell) Values(tx *Tx) []uint16 { } a = a[:n] return a - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: a := make([]uint16, 0, BitmapN*64) _, bm, _ := tx.leafCellBitmap(toPgno(c.Data)) for i, v := range bm { @@ -347,7 +348,7 @@ func (c *leafCell) firstValue() uint16 { case ContainerTypeRLE: r := toInterval16(c.Data) return r[0].Start - case ContainerTypeBitmap: + case ContainerTypeBitmapPtr: for i, v := range toArray64(c.Data) { for j := uint(0); j < 64; j++ { if v&(1< n=%d\n", indent, i, cell.Key, cell.Type, cell.N) @@ -575,11 +576,7 @@ func treedump(tx *Tx, pgno uint32, indent string, writer io.Writer) { for i, n := 0, readCellN(page); i < n; i++ { cell := readBranchCell(page, i) - if cell.Flags&ContainerTypeBitmap == 0 { // leaf/branch child page - treedump(tx, cell.Pgno, " "+indent, writer) - } else { - fmt.Fprintf(writer, "%s BITMAP(%d)\n", fmtindent(" "+indent), cell.Pgno) - } + treedump(tx, cell.Pgno, " "+indent, writer) } case PageTypeLeaf: fmt.Fprintf(writer, "%s LEAF(%d) n=%d\n", fmtindent(indent), pgno, readCellN(page)) diff --git a/rbf/tx.go b/rbf/tx.go index 5c04b58ed..6c0adfcce 100644 --- a/rbf/tx.go +++ b/rbf/tx.go @@ -78,7 +78,11 @@ func (tx *Tx) Rollback() error { } // Disconnect transaction from DB. - return tx.db.removeTx(tx) + err := tx.db.removeTx(tx) + if err != nil { + //TODO need to fix this error + } + return nil } // Root returns the root page number for a bitmap. Returns 0 if the bitmap does not exist. @@ -516,14 +520,8 @@ func (tx *Tx) walkTree(pgno uint32, fn func(uint32) error) error { case PageTypeBranch: for i, n := 0, readCellN(page); i < n; i++ { cell := readBranchCell(page, i) - if cell.Flags&ContainerTypeBitmap != 0 { // bitmap cell (cannot traverse into) - if err := fn(cell.Pgno); err != nil { - return err - } - } else { - if err := tx.walkTree(cell.Pgno, fn); err != nil { - return err - } + if err := tx.walkTree(cell.Pgno, fn); err != nil { + return err } } return nil @@ -600,14 +598,8 @@ func (tx *Tx) deallocateTree(pgno uint32) error { case PageTypeBranch: for i, n := 0, readCellN(page); i < n; i++ { cell := readBranchCell(page, i) - if cell.Flags&ContainerTypeBitmap == 0 { // leaf/branch child page - if err := tx.deallocateTree(cell.Pgno); err != nil { - return err - } - } else { - if err := tx.deallocate(cell.Pgno); err != nil { // bitmap child page - return err - } + if err := tx.deallocateTree(cell.Pgno); err != nil { + return err } } return nil