Skip to content

Commit

Permalink
support scanning across pages
Browse files Browse the repository at this point in the history
  • Loading branch information
chirst committed Jun 26, 2024
1 parent e813d15 commit bcfb5cc
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
23 changes: 20 additions & 3 deletions kv/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ func (kv *KV) Get(pageNumber uint16, key []byte) ([]byte, bool, error) {
func (kv *KV) Set(pageNumber uint16, key, value []byte) error {
// TODO set has some issues. One being set doesn't differentiate between
// insert and update which isn't very intentional. Two being set cannot
// perform multiple insertions in the span of one transaction since page
// splits pull out stale pages on subsequent inserts which causes difficult
// bugs.
// perform multiple insertions in the span of one transaction. This is
// because page splits pull out stale pages on subsequent inserts which
// causes difficult to diagnose bugs.
if pageNumber == pager.EMPTY_PARENT_PAGE_NUMBER {
return errorReservedPage
}
Expand Down Expand Up @@ -146,6 +146,8 @@ func (kv *KV) splitPage(page *pager.Page) (left, right *pager.Page) {
rightPage := kv.pager.NewPage()
rightEntries := entries[len(entries)/2:]
rightPage.SetEntries(rightEntries)
leftPage.SetRightPageNumber(rightPage.GetNumber())
rightPage.SetLeftPageNumber(leftPage.GetNumber())
return leftPage, rightPage
}

Expand Down Expand Up @@ -262,6 +264,8 @@ type Cursor struct {
rootPageNumber int
currentPageEntries []pager.PageTuple
currentTupleIndex int
currentLeftPage uint16
currentRightPage uint16
pager *pager.Pager
}

Expand All @@ -286,6 +290,8 @@ func (c *Cursor) GotoFirstRecord() bool {
}
c.currentPageEntries = candidatePage.GetEntries()
c.currentTupleIndex = 0
_, c.currentLeftPage = candidatePage.GetLeftPageNumber()
_, c.currentRightPage = candidatePage.GetRightPageNumber()
return true
}

Expand Down Expand Up @@ -321,5 +327,16 @@ func (c *Cursor) GotoNext() bool {
c.currentTupleIndex += 1
return true
}
if c.currentRightPage != 0 {
candidatePage := c.pager.GetPage(c.currentRightPage)
if len(candidatePage.GetEntries()) == 0 {
return false
}
c.currentPageEntries = candidatePage.GetEntries()
c.currentTupleIndex = 0
_, c.currentLeftPage = candidatePage.GetLeftPageNumber()
_, c.currentRightPage = candidatePage.GetRightPageNumber()
return true
}
return false
}
28 changes: 28 additions & 0 deletions pager/pager.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,34 @@ func (p *Page) SetParentPageNumber(pageNumber uint16) {
copy(p.content[PARENT_POINTER_OFFSET:PARENT_POINTER_OFFSET+PAGE_POINTER_SIZE], bpn)
}

func (p *Page) GetLeftPageNumber() (hasLeft bool, pageNumber uint16) {
pn := binary.LittleEndian.Uint16(p.content[LEFT_POINTER_OFFSET : LEFT_POINTER_OFFSET+PAGE_POINTER_SIZE])
if pn == EMPTY_PARENT_PAGE_NUMBER {
return false, EMPTY_PARENT_PAGE_NUMBER
}
return true, pn
}

func (p *Page) SetLeftPageNumber(pageNumber uint16) {
bpn := make([]byte, PAGE_POINTER_SIZE)
binary.LittleEndian.PutUint16(bpn, pageNumber)
copy(p.content[LEFT_POINTER_OFFSET:LEFT_POINTER_OFFSET+PAGE_POINTER_SIZE], bpn)
}

func (p *Page) GetRightPageNumber() (hasRight bool, pageNumber uint16) {
pn := binary.LittleEndian.Uint16(p.content[RIGHT_POINTER_OFFSET : RIGHT_POINTER_OFFSET+PAGE_POINTER_SIZE])
if pn == EMPTY_PARENT_PAGE_NUMBER {
return false, EMPTY_PARENT_PAGE_NUMBER
}
return true, pn
}

func (p *Page) SetRightPageNumber(pageNumber uint16) {
bpn := make([]byte, PAGE_POINTER_SIZE)
binary.LittleEndian.PutUint16(bpn, pageNumber)
copy(p.content[RIGHT_POINTER_OFFSET:RIGHT_POINTER_OFFSET+PAGE_POINTER_SIZE], bpn)
}

func (p *Page) GetNumber() uint16 {
return p.number
}
Expand Down
24 changes: 24 additions & 0 deletions pager/pager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ func TestPageHelpers(t *testing.T) {
t.Errorf("got %d want %d", gotPn, wantPn)
}
})

t.Run("get set left page number", func(t *testing.T) {
var wantPn uint16 = 21
p.SetLeftPageNumber(wantPn)
gotHas, gotPn := p.GetLeftPageNumber()
if gotHas != true {
t.Error("want true got false")
}
if gotPn != wantPn {
t.Errorf("got %d want %d", gotPn, wantPn)
}
})

t.Run("get set right page number", func(t *testing.T) {
var wantPn uint16 = 33
p.SetRightPageNumber(wantPn)
gotHas, gotPn := p.GetRightPageNumber()
if gotHas != true {
t.Error("want true got false")
}
if gotPn != wantPn {
t.Errorf("got %d want %d", gotPn, wantPn)
}
})
}

func TestPageSet(t *testing.T) {
Expand Down

0 comments on commit bcfb5cc

Please sign in to comment.