Commit 4d6e59f3 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent cabc0f17
......@@ -17,6 +17,15 @@
//
// http://btrees.readthedocs.io
// https://github.com/zopefoundation/BTrees
//
// A B⁺ tree consists of nodes. Only leaf tree nodes point to data.
// Intermediate tree nodes contains keys and pointer to next-level tree nodes.
// B⁺ always have uniform height - that is the path to any leaf node from the
// tree root is the same.
//
// BTree.Get(key) performs point-query.
//
// B⁺ Trees
package btree
// See https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/Development.txt#L198
......@@ -25,6 +34,7 @@ package btree
import (
"context"
"fmt"
"math"
"reflect"
"sort"
......@@ -38,6 +48,29 @@ import (
// XXX -> template?
type KEY int64
// BTree is a non-leaf node of a B⁺ tree.
//
// It mimics ?OBTree from btree/py, with ? being any integer.
type BTree struct {
zodb.Persistent
// https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/BTreeModuleTemplate.c#L205:
//
// firstbucket points to the bucket containing the smallest key in
// the BTree. This is found by traversing leftmost child pointers
// (data[0].child) until reaching a Bucket.
firstbucket *Bucket
// https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/BTreeModuleTemplate.c#L211:
//
// The BTree points to 'len' children, via the "child" fields of the data
// array. There are len-1 keys in the 'key' fields, stored in increasing
// order. data[0].key is unused. For i in 0 .. len-1, all keys reachable
// from data[i].child are >= data[i].key and < data[i+1].key, at the
// endpoints pretending that data[0].key is -∞ and data[len].key is +∞.
data []Entry
}
// Bucket is a leaf node of a B⁺ tree.
//
// It mimics ?OBucket from btree/py, with ? being any integer.
......@@ -57,37 +90,40 @@ type Bucket struct {
values []interface{} // 'len' corresponding values
}
// _BTreeItem mimics BTreeItem from btree/py.
// Entry is one BTree node entry.
//
// It contains key and child, who is either BTree or Bucket.
//
// XXX export for BTree.Children?
type _BTreeItem struct {
// Key limits child's keys - see BTree.Entryv for details.
type Entry struct {
key KEY
child interface{} // BTree or Bucket
}
// BTree is a non-leaf node of a B⁺ tree.
//
// It mimics ?OBTree from btree/py, with ? being any integer.
type BTree struct {
zodb.Persistent
// Key returns BTree entry key.
func (i *Entry) Key() KEY { return i.key }
// https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/BTreeModuleTemplate.c#L205:
//
// firstbucket points to the bucket containing the smallest key in
// the BTree. This is found by traversing leftmost child pointers
// (data[0].child) until reaching a Bucket.
firstbucket *Bucket
// Child returns BTree entry child.
func (i *Entry) Child() interface{} { return i.child }
// https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/BTreeModuleTemplate.c#L211:
//
// The BTree points to 'len' children, via the "child" fields of the data
// array. There are len-1 keys in the 'key' fields, stored in increasing
// order. data[0].key is unused. For i in 0 .. len-1, all keys reachable
// from data[i].child are >= data[i].key and < data[i+1].key, at the
// endpoints pretending that data[0].key is -∞ and data[len].key is +∞.
data []_BTreeItem
// Entryv returns entries of BTree node.
//
// Entries keys limit the keys of all children reachable from an entry:
//
// [i].Key ≤ [i].Child.*.Key < [i+1].Key i ∈ [0, len([]))
//
// [0].Key = -∞ ; always returned so
// [len(ev)].Key = +∞ ; should be assumed so
//
//
// Children of all entries are guaranteed to be of the same kind - either all BTree, or all Bucket.
//
// The caller must not modify returned array.
func (t *BTree) Entryv() []Entry {
return t.data
}
// Get searches BTree by key.
//
// It loads intermediate BTree nodes from database on demand as needed.
......@@ -309,7 +345,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
}
bt.firstbucket = bucket
bt.data = []_BTreeItem{{key: 0, child: bucket}}
bt.data = []Entry{{key: 0, child: bucket}}
return nil
}
......@@ -328,9 +364,9 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
}
n := (len(t) + 1) / 2
bt.data = make([]_BTreeItem, 0, n)
bt.data = make([]Entry, 0, n)
for i, idx := 0, 0; i < n; i++ {
key := int64(0)
key := int64(math.MinInt64) // int64(-∞) (qualifies for ≤)
if i > 0 {
// key[0] is unused and not saved
key, ok = t[idx].(int64) // XXX Xint
......@@ -346,11 +382,12 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
default:
return fmt.Errorf("data: [%d]: child must be BTree|Bucket; got %T", i, child)
// XXX check all children are of the same type
case *BTree: // ok
case *Bucket: // ok
}
bt.data = append(bt.data, _BTreeItem{key: KEY(key), child: child})
bt.data = append(bt.data, Entry{key: KEY(key), child: child})
}
return nil
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment