diff options
author | Martin Kobetic <mkobetic@gmail.com> | 2014-05-09 13:35:00 +0000 |
---|---|---|
committer | Martin Kobetic <mkobetic@gmail.com> | 2014-05-09 13:35:00 +0000 |
commit | d279ea44cedc355c5dc574d2fd6edfb5e2088410 (patch) | |
tree | 491e8944316bf0b6e68b979ee4128b2697c8ef7e | |
parent | Merge pull request #158 from benbjohnson/bolt-info (diff) | |
download | dedo-d279ea44cedc355c5dc574d2fd6edfb5e2088410.tar.gz dedo-d279ea44cedc355c5dc574d2fd6edfb5e2088410.tar.xz |
add asserts for detecting pgid high watermark overflow
-rw-r--r-- | bucket.go | 1 | ||||
-rw-r--r-- | cmd/bolt/stats.go | 54 | ||||
-rw-r--r-- | db.go | 4 | ||||
-rw-r--r-- | node.go | 4 |
4 files changed, 63 insertions, 0 deletions
@@ -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 + } +} @@ -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 @@ -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) } |