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

.

parent cabc0f17
...@@ -17,6 +17,15 @@ ...@@ -17,6 +17,15 @@
// //
// http://btrees.readthedocs.io // http://btrees.readthedocs.io
// https://github.com/zopefoundation/BTrees // 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 package btree
// See https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/Development.txt#L198 // See https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/Development.txt#L198
...@@ -25,6 +34,7 @@ package btree ...@@ -25,6 +34,7 @@ package btree
import ( import (
"context" "context"
"fmt" "fmt"
"math"
"reflect" "reflect"
"sort" "sort"
...@@ -38,6 +48,29 @@ import ( ...@@ -38,6 +48,29 @@ import (
// XXX -> template? // XXX -> template?
type KEY int64 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. // Bucket is a leaf node of a B⁺ tree.
// //
// It mimics ?OBucket from btree/py, with ? being any integer. // It mimics ?OBucket from btree/py, with ? being any integer.
...@@ -57,37 +90,40 @@ type Bucket struct { ...@@ -57,37 +90,40 @@ type Bucket struct {
values []interface{} // 'len' corresponding values 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? // Key limits child's keys - see BTree.Entryv for details.
type _BTreeItem struct { type Entry struct {
key KEY key KEY
child interface{} // BTree or Bucket child interface{} // BTree or Bucket
} }
// BTree is a non-leaf node of a B⁺ tree. // Key returns BTree entry key.
// func (i *Entry) Key() KEY { return i.key }
// 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: // Child returns BTree entry child.
// func (i *Entry) Child() interface{} { return i.child }
// 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: // Entryv returns entries of BTree node.
// //
// The BTree points to 'len' children, via the "child" fields of the data // Entries keys limit the keys of all children reachable from an entry:
// 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 // [i].Key ≤ [i].Child.*.Key < [i+1].Key i ∈ [0, len([]))
// 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 +∞. // [0].Key = -∞ ; always returned so
data []_BTreeItem // [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. // Get searches BTree by key.
// //
// It loads intermediate BTree nodes from database on demand as needed. // It loads intermediate BTree nodes from database on demand as needed.
...@@ -309,7 +345,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) { ...@@ -309,7 +345,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
} }
bt.firstbucket = bucket bt.firstbucket = bucket
bt.data = []_BTreeItem{{key: 0, child: bucket}} bt.data = []Entry{{key: 0, child: bucket}}
return nil return nil
} }
...@@ -328,9 +364,9 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) { ...@@ -328,9 +364,9 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
} }
n := (len(t) + 1) / 2 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++ { for i, idx := 0, 0; i < n; i++ {
key := int64(0) key := int64(math.MinInt64) // int64(-∞) (qualifies for ≤)
if i > 0 { if i > 0 {
// key[0] is unused and not saved // key[0] is unused and not saved
key, ok = t[idx].(int64) // XXX Xint key, ok = t[idx].(int64) // XXX Xint
...@@ -346,11 +382,12 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) { ...@@ -346,11 +382,12 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
default: default:
return fmt.Errorf("data: [%d]: child must be BTree|Bucket; got %T", i, child) 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 *BTree: // ok
case *Bucket: // 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 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