diff --git a/cmd/Godeps/Godeps.json b/cmd/Godeps/Godeps.json index a3e4b4f2f..c696f6e11 100644 --- a/cmd/Godeps/Godeps.json +++ b/cmd/Godeps/Godeps.json @@ -88,7 +88,7 @@ }, { "ImportPath": "github.com/google/btree", - "Rev": "cc6329d4279e3f025a53a83c397d2339b5705c45" + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/inconshreveable/mousetrap", diff --git a/cmd/vendor/github.com/google/btree/README.md b/cmd/vendor/github.com/google/btree/README.md index 26d687ef8..6062a4dac 100644 --- a/cmd/vendor/github.com/google/btree/README.md +++ b/cmd/vendor/github.com/google/btree/README.md @@ -2,7 +2,7 @@ ![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) -This package provides an in-memory B-Tree implementation for Go, useful as a +This package provides an in-memory B-Tree implementation for Go, useful as an ordered, mutable data structure. The API is based off of the wonderful diff --git a/cmd/vendor/github.com/google/btree/btree.go b/cmd/vendor/github.com/google/btree/btree.go index eb1f75cda..fc5aaaa13 100644 --- a/cmd/vendor/github.com/google/btree/btree.go +++ b/cmd/vendor/github.com/google/btree/btree.go @@ -64,6 +64,39 @@ type Item interface { Less(than Item) bool } +const ( + DefaultFreeListSize = 32 +) + +// FreeList represents a free list of btree nodes. By default each +// BTree has its own FreeList, but multiple BTrees can share the same +// FreeList. +// Two Btrees using the same freelist are not safe for concurrent write access. +type FreeList struct { + freelist []*node +} + +// NewFreeList creates a new free list. +// size is the maximum size of the returned free list. +func NewFreeList(size int) *FreeList { + return &FreeList{freelist: make([]*node, 0, size)} +} + +func (f *FreeList) newNode() (n *node) { + index := len(f.freelist) - 1 + if index < 0 { + return new(node) + } + f.freelist, n = f.freelist[:index], f.freelist[index] + return +} + +func (f *FreeList) freeNode(n *node) { + if len(f.freelist) < cap(f.freelist) { + f.freelist = append(f.freelist, n) + } +} + // ItemIterator allows callers of Ascend* to iterate in-order over portions of // the tree. When this function returns false, iteration will stop and the // associated Ascend* function will immediately return. @@ -74,12 +107,17 @@ type ItemIterator func(i Item) bool // New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items // and 2-4 children). func New(degree int) *BTree { + return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize)) +} + +// NewWithFreeList creates a new B-Tree that uses the given node free list. +func NewWithFreeList(degree int, f *FreeList) *BTree { if degree <= 1 { panic("bad degree") } return &BTree{ degree: degree, - freelist: make([]*node, 0, 32), + freelist: f, } } @@ -100,6 +138,7 @@ func (s *items) insertAt(index int, item Item) { // back. func (s *items) removeAt(index int) Item { item := (*s)[index] + (*s)[index] = nil copy((*s)[index:], (*s)[index+1:]) *s = (*s)[:len(*s)-1] return item @@ -108,7 +147,9 @@ func (s *items) removeAt(index int) Item { // pop removes and returns the last element in the list. func (s *items) pop() (out Item) { index := len(*s) - 1 - out, *s = (*s)[index], (*s)[:index] + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] return } @@ -142,6 +183,7 @@ func (s *children) insertAt(index int, n *node) { // back. func (s *children) removeAt(index int) *node { n := (*s)[index] + (*s)[index] = nil copy((*s)[index:], (*s)[index+1:]) *s = (*s)[:len(*s)-1] return n @@ -150,7 +192,9 @@ func (s *children) removeAt(index int) *node { // pop removes and returns the last element in the list. func (s *children) pop() (out *node) { index := len(*s) - 1 - out, *s = (*s)[index], (*s)[:index] + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] return } @@ -234,6 +278,34 @@ func (n *node) get(key Item) Item { return nil } +// min returns the first item in the subtree. +func min(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[0] + } + if len(n.items) == 0 { + return nil + } + return n.items[0] +} + +// max returns the last item in the subtree. +func max(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[len(n.children)-1] + } + if len(n.items) == 0 { + return nil + } + return n.items[len(n.items)-1] +} + // toRemove details what item to remove in a node.remove call. type toRemove int @@ -396,7 +468,7 @@ type BTree struct { degree int length int root *node - freelist []*node + freelist *FreeList } // maxItems returns the max number of items to allow per node. @@ -411,26 +483,22 @@ func (t *BTree) minItems() int { } func (t *BTree) newNode() (n *node) { - index := len(t.freelist) - 1 - if index < 0 { - return &node{t: t} - } - t.freelist, n = t.freelist[:index], t.freelist[index] + n = t.freelist.newNode() + n.t = t return } func (t *BTree) freeNode(n *node) { - if len(t.freelist) < cap(t.freelist) { - for i := range n.items { - n.items[i] = nil // clear to allow GC - } - n.items = n.items[:0] - for i := range n.children { - n.children[i] = nil // clear to allow GC - } - n.children = n.children[:0] - t.freelist = append(t.freelist, n) + for i := range n.items { + n.items[i] = nil // clear to allow GC } + n.items = n.items[:0] + for i := range n.children { + n.children[i] = nil // clear to allow GC + } + n.children = n.children[:0] + n.t = nil // clear to allow GC + t.freelist.freeNode(n) } // ReplaceOrInsert adds the given item to the tree. If an item in the tree @@ -552,6 +620,16 @@ func (t *BTree) Get(key Item) Item { return t.root.get(key) } +// Min returns the smallest item in the tree, or nil if the tree is empty. +func (t *BTree) Min() Item { + return min(t.root) +} + +// Max returns the largest item in the tree, or nil if the tree is empty. +func (t *BTree) Max() Item { + return max(t.root) +} + // Has returns true if the given key is in the tree. func (t *BTree) Has(key Item) bool { return t.Get(key) != nil