Commit 7fbd77cb authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent cdd85527
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
// //
// BTree.FirstBucket() and Bucket.Next() allow to iterate through leaf B⁺ tree nodes. // BTree.FirstBucket() and Bucket.Next() allow to iterate through leaf B⁺ tree nodes.
// //
// BTree.V<op>(..., visit) performs <op> with calling visit on every accessed tree node.
//
// -------- // --------
// //
// (*) https://github.com/zopefoundation/ZODB/blob/3.10.7-4-gb8d7a8567/src/BTrees/Development.txt#L211 // (*) https://github.com/zopefoundation/ZODB/blob/3.10.7-4-gb8d7a8567/src/BTrees/Development.txt#L211
......
...@@ -153,16 +153,13 @@ func (b *Bucket) Next() *Bucket { ...@@ -153,16 +153,13 @@ func (b *Bucket) Next() *Bucket {
// //
// t need not be activated beforehand for Get to work. // t need not be activated beforehand for Get to work.
func (t *BTree) Get(ctx context.Context, key KEY) (_ interface{}, _ bool, err error) { func (t *BTree) Get(ctx context.Context, key KEY) (_ interface{}, _ bool, err error) {
return t.GetTo(ctx, key, nil) return t.VGet(ctx, key, nil)
} }
// GetTo searches BTree by key and visits btree-path nodes. // VGet is like Get but also calls visit while traversing the tree.
//
// 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. // 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) { func (t *BTree) VGet(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) defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
...@@ -234,12 +231,23 @@ func (b *Bucket) Get(key KEY) (interface{}, bool) { ...@@ -234,12 +231,23 @@ func (b *Bucket) Get(key KEY) (interface{}, bool) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) { func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) {
return t.VMinKey(ctx, nil)
}
// VMinKey is like MinKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *BTree) VMinKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ KEY, ok bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
if len(t.data) == 0 { if len(t.data) == 0 {
// empty btree // empty btree
t.PDeactivate() t.PDeactivate()
...@@ -255,6 +263,10 @@ func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) { ...@@ -255,6 +263,10 @@ func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *BTree: case *BTree:
t = child t = child
...@@ -272,12 +284,23 @@ func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) { ...@@ -272,12 +284,23 @@ func (t *BTree) MinKey(ctx context.Context) (_ KEY, ok bool, err error) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *BTree) MaxKey(ctx context.Context) (_ KEY, _ bool, err error) { func (t *BTree) MaxKey(ctx context.Context) (_ KEY, _ bool, err error) {
return t.VMaxKey(ctx, nil)
}
// VMaxKey is like MaxKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *BTree) VMaxKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ KEY, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
l := len(t.data) l := len(t.data)
if l == 0 { if l == 0 {
// empty btree // empty btree
...@@ -293,6 +316,10 @@ func (t *BTree) MaxKey(ctx context.Context) (_ KEY, _ bool, err error) { ...@@ -293,6 +316,10 @@ func (t *BTree) MaxKey(ctx context.Context) (_ KEY, _ bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *BTree: case *BTree:
t = child t = child
......
...@@ -155,16 +155,13 @@ func (b *IOBucket) Next() *IOBucket { ...@@ -155,16 +155,13 @@ func (b *IOBucket) Next() *IOBucket {
// //
// t need not be activated beforehand for Get to work. // t need not be activated beforehand for Get to work.
func (t *IOBTree) Get(ctx context.Context, key int32) (_ interface{}, _ bool, err error) { func (t *IOBTree) Get(ctx context.Context, key int32) (_ interface{}, _ bool, err error) {
return t.GetTo(ctx, key, nil) return t.VGet(ctx, key, nil)
} }
// GetTo searches IOBTree by key and visits btree-path nodes. // VGet is like Get but also calls visit while traversing the tree.
//
// 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. // 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) { func (t *IOBTree) VGet(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) defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
...@@ -236,12 +233,23 @@ func (b *IOBucket) Get(key int32) (interface{}, bool) { ...@@ -236,12 +233,23 @@ func (b *IOBucket) Get(key int32) (interface{}, bool) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) { func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) {
return t.VMinKey(ctx, nil)
}
// VMinKey is like MinKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *IOBTree) VMinKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ int32, ok bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
if len(t.data) == 0 { if len(t.data) == 0 {
// empty btree // empty btree
t.PDeactivate() t.PDeactivate()
...@@ -257,6 +265,10 @@ func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) { ...@@ -257,6 +265,10 @@ func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *IOBTree: case *IOBTree:
t = child t = child
...@@ -274,12 +286,23 @@ func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) { ...@@ -274,12 +286,23 @@ func (t *IOBTree) MinKey(ctx context.Context) (_ int32, ok bool, err error) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *IOBTree) MaxKey(ctx context.Context) (_ int32, _ bool, err error) { func (t *IOBTree) MaxKey(ctx context.Context) (_ int32, _ bool, err error) {
return t.VMaxKey(ctx, nil)
}
// VMaxKey is like MaxKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *IOBTree) VMaxKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ int32, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
l := len(t.data) l := len(t.data)
if l == 0 { if l == 0 {
// empty btree // empty btree
...@@ -295,6 +318,10 @@ func (t *IOBTree) MaxKey(ctx context.Context) (_ int32, _ bool, err error) { ...@@ -295,6 +318,10 @@ func (t *IOBTree) MaxKey(ctx context.Context) (_ int32, _ bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *IOBTree: case *IOBTree:
t = child t = child
......
...@@ -155,16 +155,13 @@ func (b *LOBucket) Next() *LOBucket { ...@@ -155,16 +155,13 @@ func (b *LOBucket) Next() *LOBucket {
// //
// t need not be activated beforehand for Get to work. // t need not be activated beforehand for Get to work.
func (t *LOBTree) Get(ctx context.Context, key int64) (_ interface{}, _ bool, err error) { func (t *LOBTree) Get(ctx context.Context, key int64) (_ interface{}, _ bool, err error) {
return t.GetTo(ctx, key, nil) return t.VGet(ctx, key, nil)
} }
// GetTo searches LOBTree by key and visits btree-path nodes. // VGet is like Get but also calls visit while traversing the tree.
//
// 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. // 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) { func (t *LOBTree) VGet(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) defer xerr.Contextf(&err, "btree(%s): get %v", t.POid(), key)
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
...@@ -236,12 +233,23 @@ func (b *LOBucket) Get(key int64) (interface{}, bool) { ...@@ -236,12 +233,23 @@ func (b *LOBucket) Get(key int64) (interface{}, bool) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) { func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) {
return t.VMinKey(ctx, nil)
}
// VMinKey is like MinKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *LOBTree) VMinKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ int64, ok bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
if len(t.data) == 0 { if len(t.data) == 0 {
// empty btree // empty btree
t.PDeactivate() t.PDeactivate()
...@@ -257,6 +265,10 @@ func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) { ...@@ -257,6 +265,10 @@ func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *LOBTree: case *LOBTree:
t = child t = child
...@@ -274,12 +286,23 @@ func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) { ...@@ -274,12 +286,23 @@ func (t *LOBTree) MinKey(ctx context.Context) (_ int64, ok bool, err error) {
// If the tree is empty, ok=false is returned. // If the tree is empty, ok=false is returned.
// The tree does not need to be activated beforehand. // The tree does not need to be activated beforehand.
func (t *LOBTree) MaxKey(ctx context.Context) (_ int64, _ bool, err error) { func (t *LOBTree) MaxKey(ctx context.Context) (_ int64, _ bool, err error) {
return t.VMaxKey(ctx, nil)
}
// VMaxKey is like MaxKey but also calls visit while traversing the tree.
//
// Visit is called with node being activated.
func (t *LOBTree) VMaxKey(ctx context.Context, visit func(node zodb.IPersistent)) (_ int64, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid()) defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx) err = t.PActivate(ctx)
if err != nil { if err != nil {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(t)
}
l := len(t.data) l := len(t.data)
if l == 0 { if l == 0 {
// empty btree // empty btree
...@@ -295,6 +318,10 @@ func (t *LOBTree) MaxKey(ctx context.Context) (_ int64, _ bool, err error) { ...@@ -295,6 +318,10 @@ func (t *LOBTree) MaxKey(ctx context.Context) (_ int64, _ bool, err error) {
return 0, false, err return 0, false, err
} }
if visit != nil {
visit(child)
}
switch child := child.(type) { switch child := child.(type) {
case *LOBTree: case *LOBTree:
t = child t = child
......
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