aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-01-28 15:16:22 -0500
committerBen Johnson <benbjohnson@yahoo.com>2014-01-28 15:16:22 -0500
commita942c1d1686f2af42a8a2f3d59d7e1b5afd0922a (patch)
treedeb42e921e50c12ec9811ce6578ec2bfea7de729
parentClean up test suite. (diff)
downloaddedo-a942c1d1686f2af42a8a2f3d59d7e1b5afd0922a.tar.gz
dedo-a942c1d1686f2af42a8a2f3d59d7e1b5afd0922a.tar.xz
Add tpage.put() test.
-rw-r--r--db.go2
-rw-r--r--db_test.go1
-rw-r--r--rwtransaction.go18
-rw-r--r--tnode.go (renamed from mnode.go)5
-rw-r--r--tpage.go (renamed from mpage.go)32
-rw-r--r--tpage_test.go35
6 files changed, 64 insertions, 29 deletions
diff --git a/db.go b/db.go
index 4da4540..275c4f5 100644
--- a/db.go
+++ b/db.go
@@ -115,7 +115,7 @@ func (db *DB) mmap() error {
info, err := db.file.Stat()
if err != nil {
return &Error{"mmap stat error", err}
- } else if int(info.Size()) < db.pageSize * 2 {
+ } else if int(info.Size()) < db.pageSize*2 {
return &Error{"file size too small", err}
}
size := int(info.Size())
diff --git a/db_test.go b/db_test.go
index a68f64d..20ed51c 100644
--- a/db_test.go
+++ b/db_test.go
@@ -145,7 +145,6 @@ func TestDBCorruptMeta0(t *testing.T) {
})
}
-
//--------------------------------------
// Transaction()
//--------------------------------------
diff --git a/rwtransaction.go b/rwtransaction.go
index 9ecd4ee..14aceb9 100644
--- a/rwtransaction.go
+++ b/rwtransaction.go
@@ -8,7 +8,7 @@ import (
// Only one read/write transaction can be active for a DB at a time.
type RWTransaction struct {
Transaction
- mpages map[pgid]*mpage
+ tpages map[pgid]*tpage
}
// TODO: Allocate scratch meta page.
@@ -61,7 +61,7 @@ func (t *RWTransaction) CreateBucket(name string) error {
// Insert new node.
c := t.sys.cursor()
c.Goto([]byte(name))
- t.mpage(c.page().id).put([]byte(name), buf[:])
+ t.tpage(c.page().id).put([]byte(name), buf[:])
return nil
}
@@ -104,7 +104,7 @@ func (t *RWTransaction) Put(name string, key []byte, value []byte) error {
// Insert a new node.
c := b.cursor()
c.Goto(key)
- t.mpage(c.page().id).put(key, value)
+ t.tpage(c.page().id).put(key, value)
return nil
}
@@ -124,18 +124,18 @@ func (t *RWTransaction) allocate(size int) (*page, error) {
return nil, nil
}
-// mpage returns a deserialized leaf page.
-func (t *RWTransaction) mpage(id pgid) *mpage {
- if t.mpages != nil {
- if p := t.mpages[id]; p != nil {
+// tpage returns a deserialized leaf page.
+func (t *RWTransaction) tpage(id pgid) *tpage {
+ if t.tpages != nil {
+ if p := t.tpages[id]; p != nil {
return p
}
}
// Read raw page and deserialize.
- p := &mpage{}
+ p := &tpage{}
p.read(t.page(id))
- t.mpages[id] = p
+ t.tpages[id] = p
return p
}
diff --git a/mnode.go b/tnode.go
index 1d0abca..fcb4782 100644
--- a/mnode.go
+++ b/tnode.go
@@ -1,9 +1,8 @@
package bolt
-type mnodes []mnode
+type tnodes []tnode
-type mnode struct {
+type tnode struct {
key []byte
value []byte
}
-
diff --git a/mpage.go b/tpage.go
index 7c5e048..c4dc83f 100644
--- a/mpage.go
+++ b/tpage.go
@@ -6,23 +6,25 @@ import (
"unsafe"
)
-// mpage represents a deserialized leaf page.
+// tpage represents a temporary, in-memory leaf page.
// It is deserialized from an memory-mapped page and is not restricted by page size.
-type mpage struct {
- nodes mnodes
+type tpage struct {
+ nodes tnodes
}
// allocator is a function that returns a set of contiguous pages.
type allocator func(count int) (*page, error)
// put inserts or replaces a key on a leaf page.
-func (p *mpage) put(key []byte, value []byte) {
+func (p *tpage) put(key []byte, value []byte) {
// Find insertion index.
index := sort.Search(len(p.nodes), func(i int) bool { return bytes.Compare(p.nodes[i].key, key) != -1 })
// If there is no existing key then add a new node.
- if len(p.nodes) == 0 || !bytes.Equal(p.nodes[index].key, key) {
- p.nodes = append(p.nodes, mnode{})
+ if index == len(p.nodes) {
+ p.nodes = append(p.nodes, tnode{})
+ } else if len(p.nodes) == 0 || !bytes.Equal(p.nodes[index].key, key) {
+ p.nodes = append(p.nodes, tnode{})
copy(p.nodes[index+1:], p.nodes[index:])
}
p.nodes[index].key = key
@@ -30,8 +32,8 @@ func (p *mpage) put(key []byte, value []byte) {
}
// read initializes the node data from an on-disk page.
-func (p *mpage) read(page *page) {
- p.nodes = make(mnodes, page.count)
+func (p *tpage) read(page *page) {
+ p.nodes = make(tnodes, page.count)
lnodes := (*[maxNodesPerPage]lnode)(unsafe.Pointer(&page.ptr))
for i := 0; i < int(page.count); i++ {
lnode := lnodes[i]
@@ -42,7 +44,7 @@ func (p *mpage) read(page *page) {
}
// write writes the nodes onto one or more leaf pages.
-func (p *mpage) write(pageSize int, allocate allocator) ([]*page, error) {
+func (p *tpage) write(pageSize int, allocate allocator) ([]*page, error) {
var pages []*page
for _, nodes := range p.split(pageSize) {
@@ -84,10 +86,10 @@ func (p *mpage) write(pageSize int, allocate allocator) ([]*page, error) {
}
// split divides up the noes in the page into appropriately sized groups.
-func (p *mpage) split(pageSize int) []mnodes {
+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 {
- return []mnodes{p.nodes}
+ return []tnodes{p.nodes}
}
// If we're not larger than one page then just return the nodes.
@@ -96,13 +98,13 @@ func (p *mpage) split(pageSize int) []mnodes {
totalSize += lnodeSize + len(node.key) + len(node.value)
}
if totalSize < pageSize {
- return []mnodes{p.nodes}
+ return []tnodes{p.nodes}
}
// Otherwise group into smaller pages and target a given fill size.
var size int
- var group mnodes
- var groups []mnodes
+ var group tnodes
+ var groups []tnodes
// Set fill threshold to 25%.
threshold := pageSize >> 4
@@ -113,7 +115,7 @@ func (p *mpage) split(pageSize int) []mnodes {
// TODO(benbjohnson): Don't create a new group for just the last node.
if group == nil || (len(group) > minKeysPerPage && size+nodeSize > threshold) {
size = pageHeaderSize
- group = make(mnodes, 0)
+ group = make(tnodes, 0)
groups = append(groups, group)
}
diff --git a/tpage_test.go b/tpage_test.go
new file mode 100644
index 0000000..d14ebdb
--- /dev/null
+++ b/tpage_test.go
@@ -0,0 +1,35 @@
+package bolt
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// Ensure that a temporary page can insert a key/value.
+func TestTpagePut(t *testing.T) {
+ p := &tpage{nodes: make(tnodes, 0)}
+ p.put([]byte("baz"), []byte("2"))
+ p.put([]byte("foo"), []byte("0"))
+ p.put([]byte("bar"), []byte("1"))
+ p.put([]byte("foo"), []byte("3"))
+ assert.Equal(t, len(p.nodes), 3)
+ assert.Equal(t, p.nodes[0], tnode{[]byte("bar"), []byte("1")})
+ assert.Equal(t, p.nodes[1], tnode{[]byte("baz"), []byte("2")})
+ assert.Equal(t, p.nodes[2], tnode{[]byte("foo"), []byte("3")})
+}
+
+// Ensure that a temporary page can deserialize from a page.
+func TestTpageRead(t *testing.T) {
+ t.Skip("pending")
+}
+
+// Ensure that a temporary page can serialize itself.
+func TestTpageWrite(t *testing.T) {
+ t.Skip("pending")
+}
+
+// Ensure that a temporary page can split into appropriate subgroups.
+func TestTpageSplit(t *testing.T) {
+ t.Skip("pending")
+}