aboutsummaryrefslogtreecommitdiff
path: root/bucket.go
diff options
context:
space:
mode:
authorMartin Kobetic <mkobetic@gmail.com>2014-05-09 20:50:55 +0000
committerMartin Kobetic <mkobetic@gmail.com>2014-05-09 20:50:55 +0000
commitb9899d09ab6c032b54fe4a09e9389dff28d8a7f8 (patch)
tree30a0bdbcd865fd26bbb268afab23f3f68d3f692a /bucket.go
parentMerge pull request #160 from benbjohnson/fix-deletion (diff)
downloaddedo-b9899d09ab6c032b54fe4a09e9389dff28d8a7f8.tar.gz
dedo-b9899d09ab6c032b54fe4a09e9389dff28d8a7f8.tar.xz
first part
Diffstat (limited to 'bucket.go')
-rw-r--r--bucket.go43
1 files changed, 38 insertions, 5 deletions
diff --git a/bucket.go b/bucket.go
index 43204f7..41156d7 100644
--- a/bucket.go
+++ b/bucket.go
@@ -129,16 +129,23 @@ func (b *Bucket) Bucket(name []byte) *Bucket {
}
// Otherwise create a bucket and cache it.
- var child = newBucket(b.tx)
- child.bucket = &bucket{}
- *child.bucket = *(*bucket)(unsafe.Pointer(&v[0]))
- b.buckets[string(name)] = &child
+ var child = b.openBucket(v)
+ b.buckets[string(name)] = child
// Save a reference to the inline page if the bucket is inline.
if child.root == 0 {
child.page = (*page)(unsafe.Pointer(&v[bucketHeaderSize]))
}
+ return child
+}
+
+// Helper method that re-interprets a sub-bucket value
+// from a parent into a Bucket
+func (b *Bucket) openBucket(value []byte) *Bucket {
+ var child = newBucket(b.tx)
+ child.bucket = &bucket{}
+ *child.bucket = *(*bucket)(unsafe.Pointer(&value[0]))
return &child
}
@@ -354,7 +361,7 @@ func (b *Bucket) ForEach(fn func(k, v []byte) error) error {
// Stat returns stats on a bucket.
func (b *Bucket) Stats() BucketStats {
- var s BucketStats
+ var s, subStats BucketStats
pageSize := b.tx.db.pageSize
b.forEachPage(func(p *page, depth int) {
if (p.flags & leafPageFlag) != 0 {
@@ -365,6 +372,13 @@ func (b *Bucket) Stats() BucketStats {
used += int(lastElement.pos + lastElement.ksize + lastElement.vsize)
s.LeafInuse += used
s.LeafOverflowN += int(p.overflow)
+
+ // Recurse into sub-buckets
+ for _, e := range p.leafPageElements() {
+ if e.flags&bucketLeafFlag != 0 {
+ subStats.Add(b.openBucket(e.value()).Stats())
+ }
+ }
} else if (p.flags & branchPageFlag) != 0 {
s.BranchPageN++
lastElement := p.branchPageElement(p.count - 1)
@@ -380,6 +394,10 @@ func (b *Bucket) Stats() BucketStats {
})
s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize
s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize
+
+ // add the max depth of sub-buckets to get total nested depth
+ s.Depth += subStats.Depth
+ s.Add(subStats)
return s
}
@@ -643,6 +661,21 @@ type BucketStats struct {
LeafInuse int // bytes actually used for leaf data
}
+func (s *BucketStats) Add(other BucketStats) {
+ s.BranchPageN += other.BranchPageN
+ s.BranchOverflowN += other.BranchOverflowN
+ s.LeafPageN += other.LeafPageN
+ s.LeafOverflowN += other.LeafOverflowN
+ s.KeyN += s.KeyN
+ if s.Depth < other.Depth {
+ s.Depth = other.Depth
+ }
+ s.BranchAlloc += other.BranchAlloc
+ s.BranchInuse += other.BranchInuse
+ s.LeafAlloc += other.LeafAlloc
+ s.LeafInuse += other.LeafInuse
+}
+
// cloneBytes returns a copy of a given slice.
func cloneBytes(v []byte) []byte {
var clone = make([]byte, len(v))