aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-02-05 22:16:48 -0700
committerBen Johnson <benbjohnson@yahoo.com>2014-02-05 22:16:48 -0700
commitcf464375a1d2037403aa47ebed567078ae8aba41 (patch)
treeac84cf42ed379c1d7b9b0d094a1ac2fe02869dd2
parentMerge pull request #7 from benbjohnson/delete (diff)
parentRename sys ☞ buckets. (diff)
downloaddedo-cf464375a1d2037403aa47ebed567078ae8aba41.tar.gz
dedo-cf464375a1d2037403aa47ebed567078ae8aba41.tar.xz
Merge pull request #8 from benbjohnson/master
Rename sys ☞ buckets.
-rw-r--r--buckets.go (renamed from sys.go)65
-rw-r--r--buckets_test.go70
-rw-r--r--db.go13
-rw-r--r--meta.go4
-rw-r--r--page.go6
-rw-r--r--rwtransaction.go24
-rw-r--r--stat.go10
-rw-r--r--sys_test.go70
-rw-r--r--transaction.go9
9 files changed, 136 insertions, 135 deletions
diff --git a/sys.go b/buckets.go
index ec1b858..59a82d8 100644
--- a/sys.go
+++ b/buckets.go
@@ -5,51 +5,51 @@ import (
"unsafe"
)
-// sys represents a in-memory system page.
-type sys struct {
+// buckets represents a in-memory buckets page.
+type buckets struct {
pgid pgid
- buckets map[string]*bucket
+ items map[string]*bucket
}
// size returns the size of the page after serialization.
-func (s *sys) size() int {
+func (b *buckets) size() int {
var size int = pageHeaderSize
- for key, _ := range s.buckets {
+ for key, _ := range b.items {
size += int(unsafe.Sizeof(bucket{})) + len(key)
}
return size
}
// get retrieves a bucket by name.
-func (s *sys) get(key string) *bucket {
- return s.buckets[key]
+func (b *buckets) get(key string) *bucket {
+ return b.items[key]
}
// put sets a new value for a bucket.
-func (s *sys) put(key string, b *bucket) {
- s.buckets[key] = b
+func (b *buckets) put(key string, item *bucket) {
+ b.items[key] = item
}
// del deletes a bucket by name.
-func (s *sys) del(key string) {
- if b := s.buckets[key]; b != nil {
- delete(s.buckets, key)
+func (b *buckets) del(key string) {
+ if item := b.items[key]; item != nil {
+ delete(b.items, key)
}
}
// read initializes the data from an on-disk page.
-func (s *sys) read(p *page) {
- s.pgid = p.id
- s.buckets = make(map[string]*bucket)
+func (b *buckets) read(p *page) {
+ b.pgid = p.id
+ b.items = make(map[string]*bucket)
- var buckets []*bucket
+ var items []*bucket
var keys []string
- // Read buckets.
+ // Read items.
nodes := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
for i := 0; i < int(p.count); i++ {
node := &nodes[i]
- buckets = append(buckets, node)
+ items = append(items, node)
}
// Read keys.
@@ -61,34 +61,33 @@ func (s *sys) read(p *page) {
buf = buf[size:]
}
- // Associate keys and buckets.
+ // Associate keys and items.
for index, key := range keys {
- b := &bucket{buckets[index].root}
- s.buckets[key] = b
+ b.items[key] = &bucket{items[index].root}
}
}
// write writes the items onto a page.
-func (s *sys) write(p *page) {
+func (b *buckets) write(p *page) {
// Initialize page.
- p.flags |= p_sys
- p.count = uint16(len(s.buckets))
+ p.flags |= p_buckets
+ p.count = uint16(len(b.items))
// Sort keys.
var keys []string
- for key, _ := range s.buckets {
+ for key, _ := range b.items {
keys = append(keys, key)
}
sort.StringSlice(keys).Sort()
// Write each bucket to the page.
- buckets := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
+ items := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
for index, key := range keys {
- buckets[index] = *s.buckets[key]
+ items[index] = *b.items[key]
}
// Write each key to the page.
- buf := (*[maxAllocSize]byte)(unsafe.Pointer(&buckets[p.count]))[:]
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(&items[p.count]))[:]
for _, key := range keys {
buf[0] = byte(len(key))
buf = buf[1:]
@@ -96,3 +95,13 @@ func (s *sys) write(p *page) {
buf = buf[len(key):]
}
}
+
+// updateRoot finds a bucket by root id and then updates it to point to a new root.
+func (b *buckets) updateRoot(oldid, newid pgid) {
+ for _, b := range b.items {
+ if b.root == oldid {
+ b.root = newid
+ return
+ }
+ }
+}
diff --git a/buckets_test.go b/buckets_test.go
new file mode 100644
index 0000000..0fc6288
--- /dev/null
+++ b/buckets_test.go
@@ -0,0 +1,70 @@
+package bolt
+
+import (
+ "testing"
+ "unsafe"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// Ensure that a buckets page can set a bucket.
+func TestBucketsPut(t *testing.T) {
+ b := &buckets{items: make(map[string]*bucket)}
+ b.put("foo", &bucket{root: 2})
+ b.put("bar", &bucket{root: 3})
+ b.put("foo", &bucket{root: 4})
+ assert.Equal(t, len(b.items), 2)
+ assert.Equal(t, b.get("foo").root, pgid(4))
+ assert.Equal(t, b.get("bar").root, pgid(3))
+ assert.Nil(t, b.get("no_such_bucket"))
+}
+
+// Ensure that a buckets page can deserialize from a page.
+func TestBucketsRead(t *testing.T) {
+ // Create a page.
+ var buf [4096]byte
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.count = 2
+
+ // Insert 2 items at the beginning.
+ s := (*[3]bucket)(unsafe.Pointer(&page.ptr))
+ s[0] = bucket{root: 3}
+ s[1] = bucket{root: 4}
+
+ // Write data for the nodes at the end.
+ data := (*[4096]byte)(unsafe.Pointer(&s[2]))
+ data[0] = 3
+ copy(data[1:], []byte("bar"))
+ data[4] = 10
+ copy(data[5:], []byte("helloworld"))
+
+ // Deserialize page into a buckets page.
+ b := &buckets{items: make(map[string]*bucket)}
+ b.read(page)
+
+ // Check that there are two items with correct data.
+ assert.Equal(t, len(b.items), 2)
+ assert.Equal(t, b.get("bar").root, pgid(3))
+ assert.Equal(t, b.get("helloworld").root, pgid(4))
+}
+
+// Ensure that a buckets page can serialize itself.
+func TestBucketsWrite(t *testing.T) {
+ b := &buckets{items: make(map[string]*bucket)}
+ b.put("foo", &bucket{root: 2})
+ b.put("bar", &bucket{root: 3})
+
+ // Write it to a page.
+ var buf [4096]byte
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ b.write(p)
+
+ // Read the page back in.
+ b2 := &buckets{items: make(map[string]*bucket)}
+ b2.read(p)
+
+ // Check that the two pages are the same.
+ assert.Equal(t, len(b.items), 2)
+ assert.Equal(t, b.get("foo").root, pgid(2))
+ assert.Equal(t, b.get("bar").root, pgid(3))
+}
diff --git a/db.go b/db.go
index 41fbc64..d62114a 100644
--- a/db.go
+++ b/db.go
@@ -156,7 +156,7 @@ func (db *DB) init() error {
m.pageSize = uint32(db.pageSize)
m.version = version
m.free = 2
- m.sys = 3
+ m.buckets = 3
m.pgid = 4
m.txnid = txnid(i)
}
@@ -170,7 +170,7 @@ func (db *DB) init() error {
// Write an empty leaf page at page 4.
p = db.pageInBuffer(buf[:], pgid(3))
p.id = pgid(3)
- p.flags = p_sys
+ p.flags = p_buckets
p.count = 0
// Write the buffer to our data file.
@@ -385,3 +385,12 @@ func (db *DB) Stat() *Stat {
// TODO: Calculate size, depth, page count (by type), entry count, readers, etc.
return nil
}
+
+type Stat struct {
+ PageSize int
+ Depth int
+ BranchPageCount int
+ LeafPageCount int
+ OverflowPageCount int
+ EntryCount int
+}
diff --git a/meta.go b/meta.go
index 33f45d4..5c68fa7 100644
--- a/meta.go
+++ b/meta.go
@@ -7,7 +7,7 @@ type meta struct {
version uint32
pageSize uint32
flags uint32
- sys pgid
+ buckets pgid
free pgid
pgid pgid
txnid txnid
@@ -31,7 +31,7 @@ func (m *meta) copy(dest *meta) {
dest.pgid = m.pgid
dest.free = m.free
dest.txnid = m.txnid
- dest.sys = m.sys
+ dest.buckets = m.buckets
}
// write writes the meta onto a page.
diff --git a/page.go b/page.go
index d05dce6..7c5a91c 100644
--- a/page.go
+++ b/page.go
@@ -19,7 +19,7 @@ const (
p_branch = 0x01
p_leaf = 0x02
p_meta = 0x04
- p_sys = 0x08
+ p_buckets = 0x08
p_freelist = 0x10
)
@@ -41,8 +41,8 @@ func (p *page) typ() string {
return "leaf"
} else if (p.flags & p_meta) != 0 {
return "meta"
- } else if (p.flags & p_sys) != 0 {
- return "system"
+ } else if (p.flags & p_buckets) != 0 {
+ return "buckets"
} else if (p.flags & p_freelist) != 0 {
return "freelist"
}
diff --git a/rwtransaction.go b/rwtransaction.go
index 93e544b..505d107 100644
--- a/rwtransaction.go
+++ b/rwtransaction.go
@@ -38,18 +38,17 @@ func (t *RWTransaction) CreateBucket(name string) error {
p := t.allocate(1)
p.flags = p_leaf
- // Add bucket to system page.
- t.sys.put(name, &bucket{root: p.id})
+ // Add bucket to buckets page.
+ t.buckets.put(name, &bucket{root: p.id})
return nil
}
// DropBucket deletes a bucket.
func (t *RWTransaction) DeleteBucket(name string) error {
- // Remove from system page.
- t.sys.del(name)
+ // Remove from buckets page.
+ t.buckets.del(name)
- // TODO: Delete entry from system bucket.
// TODO: Free all pages.
// TODO: Remove cursor.
return nil
@@ -105,9 +104,9 @@ func (t *RWTransaction) Commit() error {
// Spill data onto dirty pages.
t.spill()
- // Spill system page.
- p := t.allocate((t.sys.size() / t.db.pageSize) + 1)
- t.sys.write(p)
+ // Spill buckets page.
+ p := t.allocate((t.buckets.size() / t.db.pageSize) + 1)
+ t.buckets.write(p)
// Write dirty pages to disk.
if err := t.write(); err != nil {
@@ -115,7 +114,7 @@ func (t *RWTransaction) Commit() error {
}
// Update the meta.
- t.meta.sys = p.id
+ t.meta.buckets = p.id
// Write meta to disk.
if err := t.writeMeta(); err != nil {
@@ -223,12 +222,7 @@ func (t *RWTransaction) spill() {
// Update roots with new roots.
for _, root := range roots {
- for _, b := range t.sys.buckets {
- if b.root == root.pgid {
- b.root = root.node.root().pgid
- break
- }
- }
+ t.buckets.updateRoot(root.pgid, root.node.root().pgid)
}
}
diff --git a/stat.go b/stat.go
deleted file mode 100644
index b01fa99..0000000
--- a/stat.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package bolt
-
-type Stat struct {
- PageSize int
- Depth int
- BranchPageCount int
- LeafPageCount int
- OverflowPageCount int
- EntryCount int
-}
diff --git a/sys_test.go b/sys_test.go
deleted file mode 100644
index 0dcae66..0000000
--- a/sys_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package bolt
-
-import (
- "testing"
- "unsafe"
-
- "github.com/stretchr/testify/assert"
-)
-
-// Ensure that a system page can set a bucket.
-func TestSysPut(t *testing.T) {
- s := &sys{buckets: make(map[string]*bucket)}
- s.put("foo", &bucket{root: 2})
- s.put("bar", &bucket{root: 3})
- s.put("foo", &bucket{root: 4})
- assert.Equal(t, len(s.buckets), 2)
- assert.Equal(t, s.get("foo").root, pgid(4))
- assert.Equal(t, s.get("bar").root, pgid(3))
- assert.Nil(t, s.get("no_such_bucket"))
-}
-
-// Ensure that a system page can deserialize from a page.
-func TestSysRead(t *testing.T) {
- // Create a page.
- var buf [4096]byte
- page := (*page)(unsafe.Pointer(&buf[0]))
- page.count = 2
-
- // Insert 2 buckets at the beginning.
- buckets := (*[3]bucket)(unsafe.Pointer(&page.ptr))
- buckets[0] = bucket{root: 3}
- buckets[1] = bucket{root: 4}
-
- // Write data for the nodes at the end.
- data := (*[4096]byte)(unsafe.Pointer(&buckets[2]))
- data[0] = 3
- copy(data[1:], []byte("bar"))
- data[4] = 10
- copy(data[5:], []byte("helloworld"))
-
- // Deserialize page into a system page.
- s := &sys{buckets: make(map[string]*bucket)}
- s.read(page)
-
- // Check that there are two items with correct data.
- assert.Equal(t, len(s.buckets), 2)
- assert.Equal(t, s.get("bar").root, pgid(3))
- assert.Equal(t, s.get("helloworld").root, pgid(4))
-}
-
-// Ensure that a system page can serialize itself.
-func TestSysWrite(t *testing.T) {
- s := &sys{buckets: make(map[string]*bucket)}
- s.put("foo", &bucket{root: 2})
- s.put("bar", &bucket{root: 3})
-
- // Write it to a page.
- var buf [4096]byte
- p := (*page)(unsafe.Pointer(&buf[0]))
- s.write(p)
-
- // Read the page back in.
- s2 := &sys{buckets: make(map[string]*bucket)}
- s2.read(p)
-
- // Check that the two pages are the same.
- assert.Equal(t, len(s.buckets), 2)
- assert.Equal(t, s.get("foo").root, pgid(2))
- assert.Equal(t, s.get("bar").root, pgid(3))
-}
diff --git a/transaction.go b/transaction.go
index 29337c6..5733e9e 100644
--- a/transaction.go
+++ b/transaction.go
@@ -13,7 +13,7 @@ type Transaction struct {
id int
db *DB
meta *meta
- sys *sys
+ buckets *buckets
pages map[pgid]*page
}
@@ -23,8 +23,8 @@ func (t *Transaction) init(db *DB) {
t.meta = db.meta()
t.pages = nil
- t.sys = &sys{}
- t.sys.read(t.page(t.meta.sys))
+ t.buckets = &buckets{}
+ t.buckets.read(t.page(t.meta.buckets))
}
func (t *Transaction) Close() {
@@ -37,8 +37,7 @@ func (t *Transaction) DB() *DB {
// Bucket retrieves a bucket by name.
func (t *Transaction) Bucket(name string) *Bucket {
- // Lookup bucket from the system page.
- b := t.sys.get(name)
+ b := t.buckets.get(name)
if b == nil {
return nil
}