diff options
-rw-r--r-- | src/dedo.go | 76 | ||||
-rw-r--r-- | tests/dedo.go | 18 |
2 files changed, 55 insertions, 39 deletions
diff --git a/src/dedo.go b/src/dedo.go index d8655bb..af29fdd 100644 --- a/src/dedo.go +++ b/src/dedo.go @@ -63,28 +63,44 @@ import ( type CursorI interface{ First() ([]byte, []byte) + Last() ([]byte, []byte) Next() ([]byte, []byte) + Prev() ([]byte, []byte) + Seek([]byte) ([]byte, []byte) + Delete() error +} + +type BucketI interface{ + Get([]byte) []byte + Put([]byte, []byte) error + Delete([]byte) error + ForEach(func([]byte, []byte) error) error + CreateBucket([]byte) (BucketI, error) + DeleteBucket([]byte) error + Bucket([]byte) BucketI + NextSequence() (uint64, error) + Cursor() CursorI } type SnapshotI interface{ - Bucket([]byte) *bucketT + Bucket([]byte) BucketI Cursor() CursorI - ForEach(func([]byte, *bucketT) error) error + ForEach(func([]byte, BucketI) error) error WriteTo(io.Writer) (int64, error) Check() <-chan error } type TransactionI interface{ - Bucket([]byte) *bucketT + Bucket([]byte) BucketI Cursor() CursorI - ForEach(func([]byte, *bucketT) error) error + ForEach(func([]byte, BucketI) error) error WriteTo(io.Writer) (int64, error) Check() <-chan error - CreateBucket ([]byte) (*bucketT, error) - CreateBucketIfNotExists([]byte) (*bucketT, error) + CreateBucket ([]byte) (BucketI, error) + CreateBucketIfNotExists([]byte) (BucketI, error) DeleteBucket([]byte) error OnCommit(func()) } @@ -597,7 +613,7 @@ func bucketCursor(b *bucketT) *cursorT { } } -func (b *bucketT) Cursor() *cursorT { +func (b *bucketT) Cursor() CursorI { return bucketCursor(b) } @@ -613,7 +629,7 @@ func bucketGetNested(b *bucketT, name []byte) *bucketT { } // Move cursor to key. - c := b.Cursor() + c := bucketCursor(b) k, v, flags := c.seek(name) // Return nil if the key doesn't exist or it is not a bucket. @@ -630,7 +646,7 @@ func bucketGetNested(b *bucketT, name []byte) *bucketT { return child } -func (b *bucketT) Bucket(name []byte) *bucketT { +func (b *bucketT) Bucket(name []byte) BucketI { return bucketGetNested(b, name) } @@ -670,7 +686,7 @@ func bucketCreateBucket(b *bucketT, key []byte) (*bucketT, error) { } // Move cursor to correct position. - c := b.Cursor() + c := bucketCursor(b) k, _, flags := c.seek(key) // Return an error if there is an existing key. @@ -698,10 +714,10 @@ func bucketCreateBucket(b *bucketT, key []byte) (*bucketT, error) { // the tx. b.page = nil - return b.Bucket(key), nil + return bucketGetNested(b, key), nil } -func (b *bucketT) CreateBucket(key []byte) (*bucketT, error) { +func (b *bucketT) CreateBucket(key []byte) (BucketI, error) { return bucketCreateBucket(b, key) } @@ -710,9 +726,9 @@ func (b *bucketT) CreateBucket(key []byte) (*bucketT, error) { /// blank, or if the bucket name is too long. The bucket instance is only valid /// for the lifetime of the transaction. func bucketCreateBucketIfNotExists(b *bucketT, key []byte) (*bucketT, error) { - child, err := b.CreateBucket(key) + child, err := bucketCreateBucket(b, key) if err == ErrBucketExists { - return b.Bucket(key), nil + return bucketGetNested(b, key), nil } else if err != nil { return nil, err } @@ -733,7 +749,7 @@ func bucketDeleteBucket(b *bucketT, key []byte) error { } // Move cursor to correct position. - c := b.Cursor() + c := bucketCursor(b) k, _, flags := c.seek(key) // Return an error if bucket doesn't exist or is not a bucket. @@ -744,7 +760,7 @@ func bucketDeleteBucket(b *bucketT, key []byte) error { } // Recursively delete all child buckets. - child := b.Bucket(key) + child := bucketGetNested(b, key) err := child.ForEach(func(k, v []byte) error { if v == nil { err := child.DeleteBucket(k) @@ -780,7 +796,7 @@ func (b *bucketT) DeleteBucket(key []byte) error { /// value if the key does not exist or if the key is a nested bucket. The /// returned value is only valid for the life of the transaction. func bucketGet(b *bucketT, key []byte) []byte { - k, v, flags := b.Cursor().seek(key) + k, v, flags := bucketCursor(b).seek(key) // Return nil if this is a bucket. if (flags & bucketLeafFlag) != 0 { @@ -818,7 +834,7 @@ func bucketPut(b *bucketT, key []byte, value []byte) error { } // Move cursor to correct position. - c := b.Cursor() + c := bucketCursor(b) k, _, flags := c.seek(key) // Return an error if there is an existing key with a bucket value. @@ -848,7 +864,7 @@ func bucketDelete(b *bucketT, key []byte) error { } // Move cursor to correct position. - c := b.Cursor() + c := bucketCursor(b) _, _, flags := c.seek(key) // Return an error if there is already existing bucket value. @@ -998,7 +1014,7 @@ func (b *bucketT) spill() error { } // Update parent node. - c := b.Cursor() + c := bucketCursor(b) k, _, flags := c.seek([]byte(name)) if !bytes.Equal([]byte(name), k) { panic(fmt.Sprintf( @@ -3554,7 +3570,7 @@ func (tx *transactionT) Size() int64 { /// buckets. The cursor is only valid as long as the transaction is open. Do /// not use a cursor after the transaction is closed. func txCursor(tx *transactionT) *cursorT { - return tx.root.Cursor() + return bucketCursor(&tx.root) } func (tx *transactionT) Cursor() CursorI { @@ -3565,10 +3581,10 @@ func (tx *transactionT) Cursor() CursorI { /// exist. The bucket instance is only valid for the lifetime of the /// transaction. func txBucket(tx *transactionT, name []byte) *bucketT { - return tx.root.Bucket(name) + return bucketGetNested(&tx.root, name) } -func (tx *transactionT) Bucket(name []byte) *bucketT { +func (tx *transactionT) Bucket(name []byte) BucketI { return txBucket(tx, name) } @@ -3577,10 +3593,10 @@ func (tx *transactionT) Bucket(name []byte) *bucketT { /// long. The bucket instance is only valid for the lifetime of the /// transaction. func txCreateBucket(tx *transactionT, name []byte) (*bucketT, error) { - return tx.root.CreateBucket(name) + return bucketCreateBucket(&tx.root, name) } -func (tx *transactionT) CreateBucket(name []byte) (*bucketT, error) { +func (tx *transactionT) CreateBucket(name []byte) (BucketI, error) { return txCreateBucket(tx, name) } @@ -3592,7 +3608,7 @@ func txCreateBucketIfNotExists(tx *transactionT, name []byte) (*bucketT, error) return tx.root.CreateBucketIfNotExists(name) } -func (tx *transactionT) CreateBucketIfNotExists(name []byte) (*bucketT, error) { +func (tx *transactionT) CreateBucketIfNotExists(name []byte) (BucketI, error) { return txCreateBucketIfNotExists(tx, name) } @@ -3609,7 +3625,7 @@ func (tx *transactionT) DeleteBucket(name []byte) error { /// transactionT.ForEach() executes a function for each bucket in the root. If the /// provided function returns an error then the iteration is stopped and the /// error is returned to the caller. -func txForEach(tx *transactionT, fn func([]byte, *bucketT) error) error { +func txForEach(tx *transactionT, fn func([]byte, BucketI) error) error { return tx.root.ForEach(func(k []byte, v []byte) error { err := fn(k, tx.root.Bucket(k)) if err != nil { @@ -3619,7 +3635,7 @@ func txForEach(tx *transactionT, fn func([]byte, *bucketT) error) error { }) } -func (tx *transactionT) ForEach(fn func([]byte, *bucketT) error) error { +func (tx *transactionT) ForEach(fn func([]byte, BucketI) error) error { return txForEach(tx, fn) } @@ -3907,7 +3923,7 @@ func (tx *transactionT) checkBucket( // Check each bucket within this bucket. _ = b.ForEach(func(k, v []byte) error { - child := b.Bucket(k) + child := bucketGetNested(b, k) if child != nil { tx.checkBucket(child, reachable, freed, ch) } @@ -4133,7 +4149,7 @@ func listExec(args argsT, db DatabaseI, r io.Reader, w io.Writer) error { if len(args.bucket) == 0 { return snapshot.ForEach(func( name []byte, - bucket *bucketT, + bucket BucketI, ) error { fmt.Fprintf(w, "%s\n", string(name)) return nil diff --git a/tests/dedo.go b/tests/dedo.go index 245eb07..efb386f 100644 --- a/tests/dedo.go +++ b/tests/dedo.go @@ -1347,7 +1347,7 @@ func TestBucket_DeleteBucket_Nested2(t *testing.T) { } err = db.View(func(snapshot SnapshotI) error { - if snapshot.Bucket([]byte("widgets")) != nil { + if snapshot.Bucket([]byte("widgets")) != /* nil FIXME */ (*bucketT)(nil) { t.Fatal("expected bucket to be deleted") } return nil @@ -1422,7 +1422,7 @@ func TestBucket_Bucket_IncompatibleValue(t *testing.T) { } b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo")) - if b != nil { + if b != /* nil FIXME */ (*bucketT)(nil) { t.Fatal("expected nil bucket") } @@ -5624,7 +5624,7 @@ func simulatePutHandler(tx *transactionT, qdb *QuickDB) { // Retrieve root bucket. b := tx.Bucket(keys[0]) - if b == nil { + if b == /* nil FIXME */ (*bucketT)(nil) { b, err = tx.CreateBucket(keys[0]) if err != nil { panic("create bucket: " + err.Error()) @@ -5634,7 +5634,7 @@ func simulatePutHandler(tx *transactionT, qdb *QuickDB) { // Create nested buckets, if necessary. for _, key := range keys[1 : len(keys)-1] { child := b.Bucket(key) - if child != nil { + if child != /* nil FIXME */ (*bucketT)(nil) { b = child } else { b, err = b.CreateBucket(key) @@ -6188,7 +6188,7 @@ func TestTx_DeleteBucket(t *testing.T) { t.Fatal(err) } - if tx.Bucket([]byte("widgets")) != nil { + if tx.Bucket([]byte("widgets")) != /* nil FIXME */ (*bucketT)(nil) { t.Fatal("unexpected bucket") } @@ -6297,7 +6297,7 @@ func TestTx_ForEach_NoError(t *testing.T) { t.Fatal(err) } - err = tx.ForEach(func(name []byte, b *bucketT) error { + err = tx.ForEach(func(name []byte, b BucketI) error { return nil }) if err != nil { @@ -6329,7 +6329,7 @@ func TestTx_ForEach_WithError(t *testing.T) { } marker := errors.New("marker") - err = tx.ForEach(func(name []byte, b *bucketT) error { + err = tx.ForEach(func(name []byte, b BucketI) error { return marker }) if err != marker { @@ -6603,7 +6603,7 @@ func fillBucket(b *bucketT, prefix []byte) error { n = 1 + rand.Intn(3) for i := 0; i < n; i++ { k := append(prefix, []byte(fmt.Sprintf("b%d", i))...) - sb, err := b.CreateBucket(k) + sb, err := bucketCreateBucket(b, k) if err != nil { return err } @@ -6628,7 +6628,7 @@ func walkBucket(parent *bucketT, k []byte, v []byte, w io.Writer) error { } return parent.ForEach(func(k, v []byte) error { if v == nil { - return walkBucket(parent.Bucket(k), k, nil, w) + return walkBucket(bucketGetNested(parent, k), k, nil, w) } return walkBucket(parent, k, v, w) }) |