Commit d68f573e authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent fd501e3d
......@@ -93,6 +93,7 @@ type BucketEntry struct {
value interface{}
}
// ---- access []entry ----
// Key returns BTree entry key.
func (e *Entry) Key() KEY { return e.key }
......@@ -132,6 +133,7 @@ func (b *Bucket) Entryv() []BucketEntry {
return ev
}
// ---- point query ----
// Get searches BTree by key.
//
......@@ -208,9 +210,93 @@ func (b *Bucket) get(key KEY) (interface{}, bool) {
return b.values[i], true
}
// TODO Bucket.MinKey
// TODO Bucket.MaxKey
// ---- min/max key ----
// XXX
func (t *BTree) MinKey(ctx context.Context) (_ KEY, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[0].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *BTree:
t = child
case *Bucket:
k, ok := child.MinKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (t *BTree) MaxKey(ctx context.Context) (_ KEY, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
l := len(t.data)
if l == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[l-1].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *BTree:
t = child
case *Bucket:
k, ok := child.MaxKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (b *Bucket) MinKey() (KEY, bool) {
if len(b.keys) == 0 {
return 0, false
}
return b.keys[0], true
}
// XXX
func (b *Bucket) MaxKey() (KEY, bool) {
l := len(b.keys)
if l == 0 {
return 0, false
}
return b.keys[l-1], true
}
// ---- serialization ----
......
......@@ -26,6 +26,7 @@ import (
"testing"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
_ "lab.nexedi.com/kirr/neo/go/zodb/wks"
......@@ -50,9 +51,48 @@ type testEntry struct {
itemv []kv
}
// bmapping represents Get of Bucket or BTree.
// bmapping represents LOBTree or a LOBucket wrapper.
type bmapping interface {
Get(context.Context, int64) (interface{}, bool, error)
MinKey(context.Context) (int64, bool, error)
MaxKey(context.Context) (int64, bool, error)
}
type bucketWrap struct {
*LOBucket
}
// withBucket runs f with b.LOBucket activated.
func (b *bucketWrap) withBucket(ctx context.Context, f func()) error {
err := b.LOBucket.PActivate(ctx)
if err != nil {
return err
}
defer b.LOBucket.PDeactivate()
f()
return nil
}
func (b *bucketWrap) Get(ctx context.Context, key int64) (v interface{}, ok bool, err error) {
err = b.withBucket(ctx, func() {
v, ok = b.LOBucket.get(key) // XXX -> Get
})
return
}
func (b *bucketWrap) MinKey(ctx context.Context) (k int64, ok bool, err error) {
err = b.withBucket(ctx, func() {
k, ok = b.LOBucket.MinKey()
})
return
}
func (b *bucketWrap) MaxKey(ctx context.Context) (k int64, ok bool, err error) {
err = b.withBucket(ctx, func() {
k, ok = b.LOBucket.MaxKey()
})
return
}
func TestBTree(t *testing.T) {
......@@ -81,19 +121,18 @@ func TestBTree(t *testing.T) {
t.Fatal(err)
}
obj, ok := xobj.(bmapping)
if !ok {
t.Fatalf("%s: got %T; want LOBucket|LOBTree", tt.oid, xobj)
}
want := ""
switch tt.kind {
case kindBucket:
if _, ok = obj.(*LOBucket); !ok {
bobj, ok := xobj.(*LOBucket)
if !ok {
want = "LOBucket"
} else {
// bucket wrapper that accepts ctx on Get, MinKey etc
xobj = &bucketWrap{bobj}
}
case kindBTree:
if _, ok = obj.(*LOBTree); !ok {
if _, ok := xobj.(*LOBTree); !ok {
want = "LOBTree"
}
default:
......@@ -101,9 +140,11 @@ func TestBTree(t *testing.T) {
}
if want != "" {
t.Fatalf("%s: got %T; want %s", tt.oid, obj, want)
t.Fatalf("%s: got %T; want %s", tt.oid, xobj, want)
}
obj := xobj.(bmapping)
for _, kv := range tt.itemv {
value, ok, err := obj.Get(ctx, kv.key)
if err != nil {
......@@ -123,6 +164,27 @@ func TestBTree(t *testing.T) {
// XXX .next == nil
// XXX check keys, values directly (i.e. there is nothing else)
}
// {Min,Max}Key
kmin, okmin, emin := obj.MinKey(ctx)
kmax, okmax, emax := obj.MaxKey(ctx)
if err := xerr.Merge(emin, emax); err != nil {
t.Error(err)
continue
}
ok := false
ka, kb := int64(0), int64(0)
if l := len(tt.itemv); l != 0 {
ok = true
ka = tt.itemv[0].key
kb = tt.itemv[l-1].key
}
if !(kmin == ka && kmax == kb && okmin == ok && okmax == ok) {
t.Errorf("%s: min/max key wrong: got [%v, %v] (%v, %v); want [%v, %v] (%v, %v)",
tt.oid, kmin, kmax, okmin, okmax, ka, kb, ok, ok)
}
}
......
......@@ -95,6 +95,7 @@ type IOBucketEntry struct {
value interface{}
}
// ---- access []entry ----
// Key returns IOBTree entry key.
func (e *IOEntry) Key() int32 { return e.key }
......@@ -134,6 +135,7 @@ func (b *IOBucket) Entryv() []IOBucketEntry {
return ev
}
// ---- point query ----
// Get searches IOBTree by key.
//
......@@ -210,9 +212,93 @@ func (b *IOBucket) get(key int32) (interface{}, bool) {
return b.values[i], true
}
// TODO IOBucket.MinKey
// TODO IOBucket.MaxKey
// ---- min/max key ----
// XXX
func (t *IOBTree) MinKey(ctx context.Context) (_ int32, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[0].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *IOBTree:
t = child
case *IOBucket:
k, ok := child.MinKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (t *IOBTree) MaxKey(ctx context.Context) (_ int32, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
l := len(t.data)
if l == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[l-1].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *IOBTree:
t = child
case *IOBucket:
k, ok := child.MaxKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (b *IOBucket) MinKey() (int32, bool) {
if len(b.keys) == 0 {
return 0, false
}
return b.keys[0], true
}
// XXX
func (b *IOBucket) MaxKey() (int32, bool) {
l := len(b.keys)
if l == 0 {
return 0, false
}
return b.keys[l-1], true
}
// ---- serialization ----
......
......@@ -95,6 +95,7 @@ type LOBucketEntry struct {
value interface{}
}
// ---- access []entry ----
// Key returns LOBTree entry key.
func (e *LOEntry) Key() int64 { return e.key }
......@@ -134,6 +135,7 @@ func (b *LOBucket) Entryv() []LOBucketEntry {
return ev
}
// ---- point query ----
// Get searches LOBTree by key.
//
......@@ -210,9 +212,93 @@ func (b *LOBucket) get(key int64) (interface{}, bool) {
return b.values[i], true
}
// TODO LOBucket.MinKey
// TODO LOBucket.MaxKey
// ---- min/max key ----
// XXX
func (t *LOBTree) MinKey(ctx context.Context) (_ int64, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): minkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
if len(t.data) == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[0].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *LOBTree:
t = child
case *LOBucket:
k, ok := child.MinKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (t *LOBTree) MaxKey(ctx context.Context) (_ int64, _ bool, err error) {
defer xerr.Contextf(&err, "btree(%s): maxkey", t.POid())
err = t.PActivate(ctx)
if err != nil {
return 0, false, err // XXX 0 ok?
}
l := len(t.data)
if l == 0 {
// empty btree
t.PDeactivate()
return 0, false, nil
}
for {
child := t.data[l-1].child.(zodb.IPersistent)
t.PDeactivate()
err = child.PActivate(ctx)
if err != nil {
return 0, false, err
}
switch child := child.(type) {
case *LOBTree:
t = child
case *LOBucket:
k, ok := child.MaxKey()
child.PDeactivate()
return k, ok, nil
}
}
}
// XXX
func (b *LOBucket) MinKey() (int64, bool) {
if len(b.keys) == 0 {
return 0, false
}
return b.keys[0], true
}
// XXX
func (b *LOBucket) MaxKey() (int64, bool) {
l := len(b.keys)
if l == 0 {
return 0, false
}
return b.keys[l-1], true
}
// ---- serialization ----
......
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