aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kobetic <mkobetic@gmail.com>2014-05-09 13:35:00 +0000
committerMartin Kobetic <mkobetic@gmail.com>2014-05-09 13:35:00 +0000
commitd279ea44cedc355c5dc574d2fd6edfb5e2088410 (patch)
tree491e8944316bf0b6e68b979ee4128b2697c8ef7e
parentMerge pull request #158 from benbjohnson/bolt-info (diff)
downloaddedo-d279ea44cedc355c5dc574d2fd6edfb5e2088410.tar.gz
dedo-d279ea44cedc355c5dc574d2fd6edfb5e2088410.tar.xz
add asserts for detecting pgid high watermark overflow
-rw-r--r--bucket.go1
-rw-r--r--cmd/bolt/stats.go54
-rw-r--r--db.go4
-rw-r--r--node.go4
4 files changed, 63 insertions, 0 deletions
diff --git a/bucket.go b/bucket.go
index 25ad1ba..a57f456 100644
--- a/bucket.go
+++ b/bucket.go
@@ -476,6 +476,7 @@ func (b *Bucket) spill() error {
b.rootNode = b.rootNode.root()
// Update the root node for this bucket.
+ _assert(b.rootNode.pgid < b.tx.meta.pgid, "pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid)
b.root = b.rootNode.pgid
return nil
diff --git a/cmd/bolt/stats.go b/cmd/bolt/stats.go
new file mode 100644
index 0000000..da344d0
--- /dev/null
+++ b/cmd/bolt/stats.go
@@ -0,0 +1,54 @@
+package main
+
+import (
+ "os"
+
+ "github.com/boltdb/bolt"
+)
+
+// Keys retrieves a list of keys for a given bucket.
+func Stats(path, name string) {
+ if _, err := os.Stat(path); os.IsNotExist(err) {
+ fatal(err)
+ return
+ }
+
+ db, err := bolt.Open(path, 0600)
+ if err != nil {
+ fatal(err)
+ return
+ }
+ defer db.Close()
+
+ err = db.View(func(tx *bolt.Tx) error {
+ // Find bucket.
+ b := tx.Bucket([]byte(name))
+ if b == nil {
+ fatalf("bucket not found: %s", name)
+ return nil
+ }
+
+ // Iterate over each key.
+ s := b.Stats()
+ println("Page count statistics")
+ printf("\tNumber of logical branch pages: %d\n", s.BranchPageN)
+ printf("\tNumber of physical branch overflow pages: %d\n", s.BranchOverflowN)
+ printf("\tNumber of logical leaf pages: %d\n", s.LeafPageN)
+ printf("\tNumber of physical leaf overflow pages: %d\n", s.LeafOverflowN)
+
+ println("Tree statistics")
+ printf("\tNumber of keys/value pairs: %d\n", s.KeyN)
+ printf("\tNumber of levels in B+tree: %d\n", s.Depth)
+
+ println("Page size utilization")
+ printf("\tBytes allocated for physical branch pages: %d\n", s.BranchAlloc)
+ printf("\tBytes actually used for branch data: %d\n", s.BranchInuse)
+ printf("\tBytes allocated for physical leaf pages: %d\n", s.LeafAlloc)
+ printf("\tBytes actually used for leaf data: %d\n", s.LeafInuse)
+ return nil
+ })
+ if err != nil {
+ fatal(err)
+ return
+ }
+}
diff --git a/db.go b/db.go
index d96a161..0b74621 100644
--- a/db.go
+++ b/db.go
@@ -705,6 +705,10 @@ func (m *meta) copy(dest *meta) {
// write writes the meta onto a page.
func (m *meta) write(p *page) {
+
+ _assert(m.root.root < m.pgid, "root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid)
+ _assert(m.freelist < m.pgid, "freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid)
+
// Page id is either going to be 0 or 1 which we can determine by the transaction ID.
p.id = pgid(m.txid % 2)
p.flags |= metaPageFlag
diff --git a/node.go b/node.go
index 1bc889d..14bf136 100644
--- a/node.go
+++ b/node.go
@@ -98,6 +98,8 @@ func (n *node) prevSibling() *node {
// put inserts a key/value.
func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) {
+ _assert(pgid < n.bucket.tx.meta.pgid, "pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid)
+
// Find insertion index.
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 })
@@ -278,6 +280,7 @@ func (n *node) spill() error {
}
// Write the node.
+ _assert(p.id < tx.meta.pgid, "pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)
node.pgid = p.id
node.write(p)
@@ -307,6 +310,7 @@ func (n *node) spill() error {
}
// Write the new root.
+ _assert(p.id < tx.meta.pgid, "pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)
parent.pgid = p.id
parent.write(p)
}