aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tpage.go13
-rw-r--r--tpage_test.go60
2 files changed, 67 insertions, 6 deletions
diff --git a/tpage.go b/tpage.go
index 07fe641..facc789 100644
--- a/tpage.go
+++ b/tpage.go
@@ -88,8 +88,8 @@ func (p *tpage) write(pageSize int, allocate allocator) ([]*page, error) {
// split divides up the noes in the page into appropriately sized groups.
func (p *tpage) split(pageSize int) []tnodes {
- // If we only have enough nodes for one page then just return the nodes.
- if len(p.nodes) <= minKeysPerPage {
+ // If we only have enough nodes for multiple pages then just return the nodes.
+ if len(p.nodes) <= (minKeysPerPage * 2) {
return []tnodes{p.nodes}
}
@@ -110,19 +110,22 @@ func (p *tpage) split(pageSize int) []tnodes {
// Set fill threshold to 25%.
threshold := pageSize >> 4
- for _, node := range p.nodes {
+ for index, node := range p.nodes {
nodeSize := lnodeSize + len(node.key) + len(node.value)
// TODO(benbjohnson): Don't create a new group for just the last node.
- if group == nil || (len(group) > minKeysPerPage && size+nodeSize > threshold) {
+ if group == nil || (len(group) >= minKeysPerPage && index < len(p.nodes)-minKeysPerPage && size+nodeSize > threshold) {
size = pageHeaderSize
+ if group != nil {
+ groups = append(groups, group)
+ }
group = make(tnodes, 0)
- groups = append(groups, group)
}
size += nodeSize
group = append(group, node)
}
+ groups = append(groups, group)
return groups
}
diff --git a/tpage_test.go b/tpage_test.go
index 389a176..ace4c53 100644
--- a/tpage_test.go
+++ b/tpage_test.go
@@ -79,7 +79,65 @@ func TestTpageWrite(t *testing.T) {
assert.Equal(t, p2.nodes[2].value, []byte("que"))
}
+// Ensure that an error that an allocation error during writing is returned.
+func TestTpageWriteError(t *testing.T) {
+ // Create a temp page.
+ p := &tpage{nodes: make(tnodes, 0)}
+ p.put([]byte("susy"), []byte("que"))
+
+ // Write it to a page.
+ exp := &Error{}
+ allocate := func(size int) (*page, error) {
+ return nil, exp
+ }
+ pages, err := p.write(4096, allocate)
+ assert.Nil(t, pages)
+ assert.Equal(t, err, exp)
+}
+
// Ensure that a temporary page can split into appropriate subgroups.
func TestTpageSplit(t *testing.T) {
- t.Skip("pending")
+ // Create a temp page.
+ p := &tpage{nodes: make(tnodes, 0)}
+ p.put([]byte("00000001"), []byte("0123456701234567"))
+ p.put([]byte("00000002"), []byte("0123456701234567"))
+ p.put([]byte("00000003"), []byte("0123456701234567"))
+ p.put([]byte("00000004"), []byte("0123456701234567"))
+ p.put([]byte("00000005"), []byte("0123456701234567"))
+
+ // Split between 3 & 4.
+ pages := p.split(100)
+
+ assert.Equal(t, len(pages), 2)
+ assert.Equal(t, len(pages[0]), 2)
+ assert.Equal(t, len(pages[1]), 3)
+}
+
+// Ensure that a temporary page with the minimum number of nodes just returns a single split group.
+func TestTpageSplitWithMinKeys(t *testing.T) {
+ // Create a temp page.
+ p := &tpage{nodes: make(tnodes, 0)}
+ p.put([]byte("00000001"), []byte("0123456701234567"))
+ p.put([]byte("00000002"), []byte("0123456701234567"))
+
+ // Split.
+ pages := p.split(20)
+ assert.Equal(t, len(pages), 1)
+ assert.Equal(t, len(pages[0]), 2)
+}
+
+// Ensure that a temporary page that has keys that all fit on a page just returns one split group.
+func TestTpageSplitFitsInPage(t *testing.T) {
+ // Create a temp page.
+ p := &tpage{nodes: make(tnodes, 0)}
+ p.put([]byte("00000001"), []byte("0123456701234567"))
+ p.put([]byte("00000002"), []byte("0123456701234567"))
+ p.put([]byte("00000003"), []byte("0123456701234567"))
+ p.put([]byte("00000004"), []byte("0123456701234567"))
+ p.put([]byte("00000005"), []byte("0123456701234567"))
+
+ // Split.
+ pages := p.split(4096)
+ assert.Equal(t, len(pages), 1)
+ assert.Equal(t, len(pages[0]), 5)
}