mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-07 19:37:51 +00:00
Fix RBF write corruption during direct write.
This commit fixes an issue where direct writes would overwrite the source page where data was being copied from because writes are immediate (instead of going to the WAL first).
This commit is contained in:
parent
dd4ffff704
commit
458984c756
3 changed files with 29 additions and 7 deletions
|
|
@ -322,14 +322,25 @@ func toPgno(val []byte) uint32 {
|
|||
return binary.LittleEndian.Uint32(val)
|
||||
}
|
||||
func (c *Cursor) putLeafCell(in leafCell) (err error) {
|
||||
cells := readLeafCells(c.leafPage, c.leafCells[:])
|
||||
// Copy target page if we are using direct writes because a split will
|
||||
// cause the source data to be overwritten after the first page is written.
|
||||
leafPage := c.leafPage
|
||||
if c.tx.exclusive {
|
||||
leafPage = make([]byte, PageSize)
|
||||
copy(leafPage, c.leafPage)
|
||||
}
|
||||
|
||||
cells := readLeafCells(leafPage, c.leafCells[:])
|
||||
elem := &c.stack.elems[c.stack.index]
|
||||
cell := in
|
||||
if elem.index >= len(cells) || c.Key() != cell.Key {
|
||||
//new cell
|
||||
if in.Type == ContainerTypeBitmap {
|
||||
//allocated bitmap()
|
||||
bitmapPgno, _ := c.tx.allocate()
|
||||
bitmapPgno, err := c.tx.allocate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cell.Data = fromPgno(bitmapPgno)
|
||||
cell.Type = ContainerTypeBitmapPtr
|
||||
}
|
||||
|
|
@ -494,6 +505,15 @@ func (c *Cursor) putBranchCells(stackIndex int, newCells []branchCell) (err erro
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy target page if we are using direct writes because a split will
|
||||
// cause the source data to be overwritten after the first page is written.
|
||||
if c.tx.exclusive {
|
||||
tmp := make([]byte, PageSize)
|
||||
copy(tmp, page)
|
||||
page = tmp
|
||||
}
|
||||
|
||||
cells := readBranchCells(page)
|
||||
|
||||
// Update current cell & insert additional cells after it.
|
||||
|
|
@ -522,7 +542,7 @@ func (c *Cursor) putBranchCells(stackIndex int, newCells []branchCell) (err erro
|
|||
parent.Pgno = origPgno
|
||||
} else {
|
||||
if parent.Pgno, err = c.tx.allocate(); err != nil {
|
||||
return fmt.Errorf("cannot allocate leaf: %w", err)
|
||||
return fmt.Errorf("cannot allocate branch: %w", err)
|
||||
}
|
||||
}
|
||||
parents = append(parents, parent)
|
||||
|
|
@ -544,6 +564,8 @@ func (c *Cursor) putBranchCells(stackIndex int, newCells []branchCell) (err erro
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(BBJ): Check if key on page changes and update parent if so.
|
||||
|
||||
// TODO(BBJ): Update page in buffer & cursor stack.
|
||||
|
||||
// If this is not a split, then exit now.
|
||||
|
|
|
|||
|
|
@ -441,7 +441,6 @@ func (db *DB) readWALPage(walID int64) ([]byte, error) {
|
|||
}
|
||||
|
||||
func (db *DB) writeWALPage(page []byte, isMeta bool) (walID int64, err error) {
|
||||
|
||||
if err := db.ensureWritableWALSegment(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -829,7 +828,6 @@ func (db *DB) Check() error {
|
|||
|
||||
// writePage writes a page to the data file.
|
||||
func (db *DB) writePage(pgno uint32, page []byte) error {
|
||||
|
||||
_, err := db.file.WriteAt(page, int64(pgno)*PageSize)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -720,10 +720,12 @@ func (tx *Tx) checkPageAllocations() error {
|
|||
if isInuse && isFree {
|
||||
return fmt.Errorf("page in-use & free: pgno=%d", pgno)
|
||||
} else if !isInuse && !isFree {
|
||||
page, _ := tx.readPage(pgno)
|
||||
page, err := tx.readPage(pgno)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flags := readFlags(page)
|
||||
if flags == PageTypeBranch || flags == PageTypeLeaf {
|
||||
|
||||
return fmt.Errorf("page not in-use & not free: pgno=%d", pgno)
|
||||
}
|
||||
//assuming its a bitmap so its ok TODO ben?
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue