Commit ded591a9 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent cce696b2
......@@ -61,7 +61,7 @@ type BTree struct {
// Key limits child's keys - see BTree.Entryv for details.
type Entry struct {
key KEY
child interface{} // BTree or Bucket
child zodb.IPersistent // BTree or Bucket
}
// Bucket is a leaf node of a B⁺ tree.
......@@ -99,7 +99,7 @@ type BucketEntry struct {
func (e *Entry) Key() KEY { return e.key }
// Child returns BTree entry child.
func (e *Entry) Child() interface{} { return e.child }
func (e *Entry) Child() zodb.IPersistent { return e.child }
// Entryv returns entries of a BTree node.
//
......@@ -153,30 +153,33 @@ func (b *Bucket) Next() *Bucket {
//
// t need not be activated beforehand for Get to work.
func (t *BTree) Get(ctx context.Context, key KEY) (_ interface{}, _ bool, err error) {
v, ok, _, _, err := t.GetTo(ctx, key)
return v, ok, err
return t.GetTo(ctx, key, nil)
}
// GetTo searches BTree by key and returns value and path.
// GetTo searches BTree by key and visits btree-path nodes.
//
// It is similar to Get, but additionally provides information via which
// intermediate tree nodes and leaf bucket the key was found.
func (t *BTree) GetTo(ctx context.Context, key KEY) (_ interface{}, _ bool, path []*BTree, leaf *Bucket, err error) {
// It is similar to Get, but additionally calls visit on every BTree node
// (BTree or Bucket) it traverses from root to leaf to find the key.
//
// Visit is called with node being activated.
func (t *BTree) GetTo(ctx context.Context, key KEY, visit func(node zodb.IPersistent)) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
return nil, false, err
}
if visit != nil {
visit(t)
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return nil, false, nil, nil, nil
return nil, false, nil
}
for {
path = append(path, t)
// search i: K(i) ≤ k < K(i+1) ; K(0) = -∞, K(len) = +∞
i := sort.Search(len(t.data), func(i int) bool {
j := i + 1
......@@ -186,47 +189,33 @@ func (t *BTree) GetTo(ctx context.Context, key KEY) (_ interface{}, _ bool, path
return key < t.data[j].key
})
switch child := t.data[i].child.(type) {
child := t.data[i].child
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return nil, false, err
}
if visit != nil {
visit(child)
}
switch child := child.(type) {
case *BTree:
t.PDeactivate()
t = child
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
}
case *Bucket:
t.PDeactivate()
v, ok, err := child.Get(ctx, key)
if err != nil {
path = nil
child = nil
}
return v, ok, path, child, err
v, ok := child.Get(key)
child.PDeactivate()
return v, ok, nil
}
}
}
// Get searches Bucket by key.
//
// TODO Bucket.Get should not get ctx argument and just require that the bucket
// must be already activated. Correspondingly there should be no error returned.
func (b *Bucket) Get(ctx context.Context, key KEY) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "bucket(%s): get %v", b.POid(), key)
err = b.PActivate(ctx)
if err != nil {
return nil, false, err
}
v, ok := b.get(key)
b.PDeactivate()
return v, ok, nil
}
// get searches Bucket by key.
//
// no loading from database is done. The bucket must be already activated.
func (b *Bucket) get(key KEY) (interface{}, bool) {
func (b *Bucket) Get(key KEY) (interface{}, bool) {
// search i: K(i-1) < k ≤ K(i) ; K(-1) = -∞, K(len) = +∞
i := sort.Search(len(b.keys), func(i int) bool {
return key <= b.keys[i]
......@@ -599,7 +588,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
fmt.Errorf("data: [%d]: children must be of the same type", i)
}
bt.data = append(bt.data, Entry{key: kkey, child: child})
bt.data = append(bt.data, Entry{key: kkey, child: child.(zodb.IPersistent)})
}
return nil
......
......@@ -79,7 +79,7 @@ func (b *bucketWrap) withBucket(ctx context.Context, f func()) error {
func (b *bucketWrap) Get(ctx context.Context, key int64) (v interface{}, ok bool, err error) {
err = b.withBucket(ctx, func() {
v, ok = b.bucket().get(key) // TODO -> Get
v, ok = b.bucket().Get(key)
})
return
}
......
......@@ -63,7 +63,7 @@ type IOBTree struct {
// Key limits child's keys - see IOBTree.Entryv for details.
type IOEntry struct {
key int32
child interface{} // IOBTree or IOBucket
child zodb.IPersistent // IOBTree or IOBucket
}
// IOBucket is a leaf node of a B⁺ tree.
......@@ -101,7 +101,7 @@ type IOBucketEntry struct {
func (e *IOEntry) Key() int32 { return e.key }
// Child returns IOBTree entry child.
func (e *IOEntry) Child() interface{} { return e.child }
func (e *IOEntry) Child() zodb.IPersistent { return e.child }
// Entryv returns entries of a IOBTree node.
//
......@@ -155,30 +155,33 @@ func (b *IOBucket) Next() *IOBucket {
//
// t need not be activated beforehand for Get to work.
func (t *IOBTree) Get(ctx context.Context, key int32) (_ interface{}, _ bool, err error) {
v, ok, _, _, err := t.GetTo(ctx, key)
return v, ok, err
return t.GetTo(ctx, key, nil)
}
// GetTo searches IOBTree by key and returns value and path.
// GetTo searches IOBTree by key and visits btree-path nodes.
//
// It is similar to Get, but additionally provides information via which
// intermediate tree nodes and leaf bucket the key was found.
func (t *IOBTree) GetTo(ctx context.Context, key int32) (_ interface{}, _ bool, path []*IOBTree, leaf *IOBucket, err error) {
// It is similar to Get, but additionally calls visit on every IOBTree node
// (IOBTree or IOBucket) it traverses from root to leaf to find the key.
//
// Visit is called with node being activated.
func (t *IOBTree) GetTo(ctx context.Context, key int32, visit func(node zodb.IPersistent)) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
return nil, false, err
}
if visit != nil {
visit(t)
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return nil, false, nil, nil, nil
return nil, false, nil
}
for {
path = append(path, t)
// search i: K(i) ≤ k < K(i+1) ; K(0) = -∞, K(len) = +∞
i := sort.Search(len(t.data), func(i int) bool {
j := i + 1
......@@ -188,47 +191,33 @@ func (t *IOBTree) GetTo(ctx context.Context, key int32) (_ interface{}, _ bool,
return key < t.data[j].key
})
switch child := t.data[i].child.(type) {
child := t.data[i].child
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return nil, false, err
}
if visit != nil {
visit(child)
}
switch child := child.(type) {
case *IOBTree:
t.PDeactivate()
t = child
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
}
case *IOBucket:
t.PDeactivate()
v, ok, err := child.Get(ctx, key)
if err != nil {
path = nil
child = nil
}
return v, ok, path, child, err
v, ok := child.Get(key)
child.PDeactivate()
return v, ok, nil
}
}
}
// Get searches IOBucket by key.
//
// TODO IOBucket.Get should not get ctx argument and just require that the bucket
// must be already activated. Correspondingly there should be no error returned.
func (b *IOBucket) Get(ctx context.Context, key int32) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "bucket(%s): get %v", b.POid(), key)
err = b.PActivate(ctx)
if err != nil {
return nil, false, err
}
v, ok := b.get(key)
b.PDeactivate()
return v, ok, nil
}
// get searches IOBucket by key.
//
// no loading from database is done. The bucket must be already activated.
func (b *IOBucket) get(key int32) (interface{}, bool) {
func (b *IOBucket) Get(key int32) (interface{}, bool) {
// search i: K(i-1) < k ≤ K(i) ; K(-1) = -∞, K(len) = +∞
i := sort.Search(len(b.keys), func(i int) bool {
return key <= b.keys[i]
......@@ -601,7 +590,7 @@ func (bt *iobtreeState) PySetState(pystate interface{}) (err error) {
fmt.Errorf("data: [%d]: children must be of the same type", i)
}
bt.data = append(bt.data, IOEntry{key: kkey, child: child})
bt.data = append(bt.data, IOEntry{key: kkey, child: child.(zodb.IPersistent)})
}
return nil
......
......@@ -63,7 +63,7 @@ type LOBTree struct {
// Key limits child's keys - see LOBTree.Entryv for details.
type LOEntry struct {
key int64
child interface{} // LOBTree or LOBucket
child zodb.IPersistent // LOBTree or LOBucket
}
// LOBucket is a leaf node of a B⁺ tree.
......@@ -101,7 +101,7 @@ type LOBucketEntry struct {
func (e *LOEntry) Key() int64 { return e.key }
// Child returns LOBTree entry child.
func (e *LOEntry) Child() interface{} { return e.child }
func (e *LOEntry) Child() zodb.IPersistent { return e.child }
// Entryv returns entries of a LOBTree node.
//
......@@ -155,30 +155,33 @@ func (b *LOBucket) Next() *LOBucket {
//
// t need not be activated beforehand for Get to work.
func (t *LOBTree) Get(ctx context.Context, key int64) (_ interface{}, _ bool, err error) {
v, ok, _, _, err := t.GetTo(ctx, key)
return v, ok, err
return t.GetTo(ctx, key, nil)
}
// GetTo searches LOBTree by key and returns value and path.
// GetTo searches LOBTree by key and visits btree-path nodes.
//
// It is similar to Get, but additionally provides information via which
// intermediate tree nodes and leaf bucket the key was found.
func (t *LOBTree) GetTo(ctx context.Context, key int64) (_ interface{}, _ bool, path []*LOBTree, leaf *LOBucket, err error) {
// It is similar to Get, but additionally calls visit on every LOBTree node
// (LOBTree or LOBucket) it traverses from root to leaf to find the key.
//
// Visit is called with node being activated.
func (t *LOBTree) GetTo(ctx context.Context, key int64, visit func(node zodb.IPersistent)) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
return nil, false, err
}
if visit != nil {
visit(t)
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return nil, false, nil, nil, nil
return nil, false, nil
}
for {
path = append(path, t)
// search i: K(i) ≤ k < K(i+1) ; K(0) = -∞, K(len) = +∞
i := sort.Search(len(t.data), func(i int) bool {
j := i + 1
......@@ -188,47 +191,33 @@ func (t *LOBTree) GetTo(ctx context.Context, key int64) (_ interface{}, _ bool,
return key < t.data[j].key
})
switch child := t.data[i].child.(type) {
child := t.data[i].child
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return nil, false, err
}
if visit != nil {
visit(child)
}
switch child := child.(type) {
case *LOBTree:
t.PDeactivate()
t = child
err = t.PActivate(ctx)
if err != nil {
return nil, false, nil, nil, err
}
case *LOBucket:
t.PDeactivate()
v, ok, err := child.Get(ctx, key)
if err != nil {
path = nil
child = nil
}
return v, ok, path, child, err
v, ok := child.Get(key)
child.PDeactivate()
return v, ok, nil
}
}
}
// Get searches LOBucket by key.
//
// TODO LOBucket.Get should not get ctx argument and just require that the bucket
// must be already activated. Correspondingly there should be no error returned.
func (b *LOBucket) Get(ctx context.Context, key int64) (_ interface{}, _ bool, err error) {
defer xerr.Contextf(&err, "bucket(%s): get %v", b.POid(), key)
err = b.PActivate(ctx)
if err != nil {
return nil, false, err
}
v, ok := b.get(key)
b.PDeactivate()
return v, ok, nil
}
// get searches LOBucket by key.
//
// no loading from database is done. The bucket must be already activated.
func (b *LOBucket) get(key int64) (interface{}, bool) {
func (b *LOBucket) Get(key int64) (interface{}, bool) {
// search i: K(i-1) < k ≤ K(i) ; K(-1) = -∞, K(len) = +∞
i := sort.Search(len(b.keys), func(i int) bool {
return key <= b.keys[i]
......@@ -601,7 +590,7 @@ func (bt *lobtreeState) PySetState(pystate interface{}) (err error) {
fmt.Errorf("data: [%d]: children must be of the same type", i)
}
bt.data = append(bt.data, LOEntry{key: kkey, child: child})
bt.data = append(bt.data, LOEntry{key: kkey, child: child.(zodb.IPersistent)})
}
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