diff options
-rw-r--r-- | src/dedo.go | 27 | ||||
-rw-r--r-- | tests/dedo.go | 150 |
2 files changed, 96 insertions, 81 deletions
diff --git a/src/dedo.go b/src/dedo.go index 9f64693..c0aecaf 100644 --- a/src/dedo.go +++ b/src/dedo.go @@ -127,13 +127,20 @@ type ITx interface{ OnCommit(func()) WriteTo(io.Writer) (int64, error) +} + +type SnapshotI interface{ + Bucket([]byte) *Bucket + + WriteTo(io.Writer) (int64, error) + ForEach(func([]byte, *Bucket) error) error Check() <-chan error } type IDedo interface{ Close() error - View (func(tx ITx) error) error + View (func(tx SnapshotI) error) error Update(func(tx ITx) error) error Path() string } @@ -1743,7 +1750,7 @@ func (m *InMemory) Update(fn func(ITx) error) error { return err } -func (m *InMemory) View(func(ITx) error) error { +func (m *InMemory) View(func(SnapshotI) error) error { return nil } @@ -2109,7 +2116,7 @@ func (db *DB) Update(fn func(ITx) error) error { /// the DB.View() method. /// /// Attempting to manually rollback within the function will cause a panic. -func (db *DB) View(fn func(ITx) error) error { +func (db *DB) View(fn func(SnapshotI) error) error { t, err := db.begin(false) if err != nil { return err @@ -3967,9 +3974,9 @@ func setGetopt(args argsT, w io.Writer) (argsT, bool) { } func checkExec(args argsT, db IDedo, _r io.Reader, _w io.Writer) error { - return db.View(func(tx ITx) error { + return db.View(func(snapshot SnapshotI) error { var errs error - for err := range tx.Check() { + for err := range snapshot.Check() { errs = g.WrapErrors(errs, err) } return errs @@ -3977,8 +3984,8 @@ func checkExec(args argsT, db IDedo, _r io.Reader, _w io.Writer) error { } func getExec(args argsT, db IDedo, r io.Reader, w io.Writer) error { - return db.View(func(tx ITx) error { - bucket := tx.Bucket(args.bucket) + return db.View(func(snapshot SnapshotI) error { + bucket := snapshot.Bucket(args.bucket) if bucket == nil { return ErrBucketNotFound } @@ -4016,9 +4023,9 @@ func rmExec(args argsT, db IDedo, r io.Reader, w io.Writer) error { } func listExec(args argsT, db IDedo, r io.Reader, w io.Writer) error { - return db.View(func(tx ITx) error { + return db.View(func(snapshot SnapshotI) error { if len(args.bucket) == 0 { - return tx.ForEach(func( + return snapshot.ForEach(func( name []byte, bucket *Bucket, ) error { @@ -4027,7 +4034,7 @@ func listExec(args argsT, db IDedo, r io.Reader, w io.Writer) error { }) } - bucket := tx.Bucket(args.bucket) + bucket := snapshot.Bucket(args.bucket) if bucket == nil { return ErrBucketNotFound } diff --git a/tests/dedo.go b/tests/dedo.go index 7dba449..b5ed229 100644 --- a/tests/dedo.go +++ b/tests/dedo.go @@ -753,8 +753,8 @@ func TestBucket_Put_Large(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for i := 1; i < count; i++ { value := b.Get([]byte(strings.Repeat("0", i*factor))) expected := []byte(strings.Repeat( @@ -884,8 +884,8 @@ func TestBucket_Put_ReadOnly(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) err := b.Put([]byte("foo"), []byte("bar")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) @@ -974,8 +974,8 @@ func TestBucket_Delete_Large(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for i := 0; i < 100; i++ { v := b.Get([]byte(strconv.Itoa(i))) if v != nil { @@ -1128,8 +1128,8 @@ func TestBucket_Nested(t *testing.T) { db.MustCheck() // Verify. - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) v := b.Bucket([]byte("foo")).Get([]byte("baz")) if !bytes.Equal(v, []byte("yyyy")) { t.Fatalf("unexpected value: %v", v) @@ -1201,8 +1201,8 @@ func TestBucket_Delete_ReadOnly(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")) + err = db.View(func(snapshot SnapshotI) error { + err := snapshot.Bucket([]byte("widgets")).Delete([]byte("foo")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } @@ -1346,8 +1346,8 @@ func TestBucket_DeleteBucket_Nested2(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - if tx.Bucket([]byte("widgets")) != nil { + err = db.View(func(snapshot SnapshotI) error { + if snapshot.Bucket([]byte("widgets")) != nil { t.Fatal("expected bucket to be deleted") } return nil @@ -1604,8 +1604,8 @@ func TestBucket_NextSequence_ReadOnly(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - _, err := tx.Bucket([]byte("widgets")).NextSequence() + err = db.View(func(snapshot SnapshotI) error { + _, err := snapshot.Bucket([]byte("widgets")).NextSequence() if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } @@ -1915,10 +1915,10 @@ func TestBucket_Put_Single(t *testing.T) { const errmsg = "value mismatch [run %d] (%d of %d):\n" + "key: %x\ngot: %x\nexp: %x" // Verify all key/values so far. - err = db.View(func(tx ITx) error { + err = db.View(func(snapshot SnapshotI) error { i := 0 for k, v := range m { - value := tx.Bucket( + value := snapshot.Bucket( []byte("widgets"), ).Get([]byte(k)) if !bytes.Equal(value, v) { @@ -1991,8 +1991,8 @@ func TestBucket_Put_Multiple(t *testing.T) { } // Verify all items exist. - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for _, item := range items { value := b.Get(item.Key) if !bytes.Equal(item.Value, value) { @@ -2070,8 +2070,8 @@ func TestBucket_Delete_Quick(t *testing.T) { } // Anything before our deletion index should be nil. - err = db.View(func(tx ITx) error { - err := tx.Bucket( + err = db.View(func(snapshot SnapshotI) error { + err := snapshot.Bucket( []byte("widgets"), ).ForEach(func(k, v []byte) error { t.Fatalf( @@ -2126,8 +2126,8 @@ func ExampleBucket_Put() { } // Read value back in a different read-only transaction. - err = db.View(func(tx ITx) error { - value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + err = db.View(func(snapshot SnapshotI) error { + value := snapshot.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value of 'foo' is: %s\n", value) return nil }) @@ -2186,8 +2186,8 @@ func ExampleBucket_Delete() { } // Retrieve the key again. - err = db.View(func(tx ITx) error { - value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + err = db.View(func(snapshot SnapshotI) error { + value := snapshot.Bucket([]byte("widgets")).Get([]byte("foo")) if value == nil { fmt.Printf("The value of 'foo' is now: nil\n") } @@ -2303,8 +2303,8 @@ func TestCursor_Seek(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - c := tx.Bucket([]byte("widgets")).Cursor() + err = db.View(func(snapshot SnapshotI) error { + c := snapshot.Bucket([]byte("widgets")).Cursor() // Exact match should go to the key. k, v := c.Seek([]byte("bar")) @@ -2449,8 +2449,8 @@ func TestCursor_Seek_Large(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - c := tx.Bucket([]byte("widgets")).Cursor() + err = db.View(func(snapshot SnapshotI) error { + c := snapshot.Bucket([]byte("widgets")).Cursor() for i := 0; i < count; i++ { seek := make([]byte, 8) binary.BigEndian.PutUint64(seek, uint64(i)) @@ -2501,8 +2501,8 @@ func TestCursor_EmptyBucket(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - c := tx.Bucket([]byte("widgets")).Cursor() + err = db.View(func(snapshot SnapshotI) error { + c := snapshot.Bucket([]byte("widgets")).Cursor() k, v := c.First() if k != nil { t.Fatalf("unexpected key: %v", k) @@ -2531,8 +2531,8 @@ func TestCursor_EmptyBucketReverse(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - c := tx.Bucket([]byte("widgets")).Cursor() + err = db.View(func(snapshot SnapshotI) error { + c := snapshot.Bucket([]byte("widgets")).Cursor() k, v := c.Last() if k != nil { t.Fatalf("unexpected key: %v", k) @@ -3003,9 +3003,9 @@ func TestCursor_QuickCheck_BucketsOnly(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { + err = db.View(func(snapshot SnapshotI) error { names := []string{} - c := tx.Bucket([]byte("widgets")).Cursor() + c := snapshot.Bucket([]byte("widgets")).Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { names = append(names, string(k)) if v != nil { @@ -3057,9 +3057,9 @@ func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { + err = db.View(func(snapshot SnapshotI) error { names := []string{} - c := tx.Bucket([]byte("widgets")).Cursor() + c := snapshot.Bucket([]byte("widgets")).Cursor() for k, v := c.Last(); k != nil; k, v = c.Prev() { names = append(names, string(k)) if v != nil { @@ -3494,7 +3494,9 @@ func TestOpen_Check(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { return <-tx.Check() }) + err = db.View(func(snapshot SnapshotI) error { + return <-snapshot.Check() + }) if err != nil { t.Fatal(err) } @@ -3509,7 +3511,9 @@ func TestOpen_Check(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { return <-tx.Check() }) + err = db.View(func(snapshot SnapshotI) error { + return <-snapshot.Check() + }) if err != nil { t.Fatal(err) } @@ -3753,8 +3757,8 @@ func TestDB_Update(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) v := b.Get([]byte("foo")) if v != nil { t.Fatalf("expected nil value, got: %v", v) @@ -3848,7 +3852,7 @@ func TestDB_View_Error(t *testing.T) { defer db.MustClose() defer os.Remove(db.Path()) - err := db.View(func(tx ITx) error { + err := db.View(func(snapshot SnapshotI) error { return errors.New("xxx") }) if err == nil || err.Error() != "xxx" { @@ -3883,8 +3887,8 @@ func TestDB_View_Panic(t *testing.T) { } }() - err := db.View(func(tx ITx) error { - if tx.Bucket([]byte("widgets")) == nil { + err := db.View(func(snapshot SnapshotI) error { + if snapshot.Bucket([]byte("widgets")) == nil { t.Fatal("expected bucket") } panic("omg") @@ -3895,8 +3899,8 @@ func TestDB_View_Panic(t *testing.T) { }() // Verify that we can still use read transactions. - err = db.View(func(tx ITx) error { - if tx.Bucket([]byte("widgets")) == nil { + err = db.View(func(snapshot SnapshotI) error { + if snapshot.Bucket([]byte("widgets")) == nil { t.Fatal("expected bucket") } return nil @@ -4034,8 +4038,8 @@ func TestDB_Batch(t *testing.T) { } // Ensure data is correct. - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for i := 0; i < n; i++ { v := b.Get(u64tob(uint64(i))) if v == nil { @@ -4139,8 +4143,8 @@ func TestDB_BatchFull(t *testing.T) { } // Ensure data is correct. - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for i := 1; i <= size; i++ { v := b.Get(u64tob(uint64(i))) if v == nil { @@ -4195,8 +4199,8 @@ func TestDB_BatchTime(t *testing.T) { } // Ensure data is correct. - err = db.View(func(tx ITx) error { - b := tx.Bucket([]byte("widgets")) + err = db.View(func(snapshot SnapshotI) error { + b := snapshot.Bucket([]byte("widgets")) for i := 1; i <= size; i++ { if v := b.Get(u64tob(uint64(i))); v == nil { t.Errorf("key not found: %d", i) @@ -4236,8 +4240,8 @@ func ExampleDB_Update() { } // Read the value back from a separate read-only transaction. - err = db.View(func(tx ITx) error { - value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + err = db.View(func(snapshot SnapshotI) error { + value := snapshot.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value of 'foo' is: %s\n", value) return nil }) @@ -4287,8 +4291,8 @@ func ExampleDB_View() { } // Access data from within a read-only transactional block. - err = db.View(func(tx ITx) error { - v := tx.Bucket([]byte("people")).Get([]byte("john")) + err = db.View(func(snapshot SnapshotI) error { + v := snapshot.Bucket([]byte("people")).Get([]byte("john")) fmt.Printf("John's last name is %s.\n", v) return nil }) @@ -4671,8 +4675,8 @@ func (db *WDB) MustCheck() { // CopyTempFile copies a database to a temporary file. func (db *WDB) CopyTempFile() { path := tempfile() - err := db.View(func(itx ITx) error { - tx := itx.(*Tx) + err := db.View(func(snapshot SnapshotI) error { + tx := snapshot.(*Tx) return tx.copyFile(path, 0600) }) if err != nil { @@ -5902,14 +5906,15 @@ func TestTx_Cursor(t *testing.T) { } } +/* // Ensure that creating a bucket with a read-only transaction returns an error. func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { db := MustOpenDB() defer db.MustClose() defer os.Remove(db.Path()) - err := db.View(func(tx ITx) error { - _, err := tx.CreateBucket([]byte("foo")) + err := db.View(func(snapshot SnapshotI) error { + _, err := snapshot.CreateBucket([]byte("foo")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } @@ -5920,6 +5925,7 @@ func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { t.Fatal(err) } } +*/ // Ensure that creating a bucket on a closed transaction returns an error. func TestTx_CreateBucket_ErrTxClosed(t *testing.T) { @@ -6016,8 +6022,8 @@ func TestTx_CreateBucket(t *testing.T) { } // Read the bucket through a separate transaction. - err = db.View(func(tx ITx) error { - if tx.Bucket([]byte("widgets")) == nil { + err = db.View(func(snapshot SnapshotI) error { + if snapshot.Bucket([]byte("widgets")) == nil { t.Fatal("expected bucket") } @@ -6058,8 +6064,8 @@ func TestTx_CreateBucketIfNotExists(t *testing.T) { } // Read the bucket through a separate transaction. - err = db.View(func(tx ITx) error { - if tx.Bucket([]byte("widgets")) == nil { + err = db.View(func(snapshot SnapshotI) error { + if snapshot.Bucket([]byte("widgets")) == nil { t.Fatal("expected bucket") } @@ -6229,13 +6235,14 @@ func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) { } } +/* // Ensure that deleting a bucket with a read-only transaction returns an error. func TestTx_DeleteBucket_ReadOnly(t *testing.T) { db := MustOpenDB() defer db.MustClose() defer os.Remove(db.Path()) - err := db.View(func(tx ITx) error { + err := db.View(func(snapshot SnapshotI) error { err := tx.DeleteBucket([]byte("foo")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) @@ -6247,6 +6254,7 @@ func TestTx_DeleteBucket_ReadOnly(t *testing.T) { t.Fatal(err) } } +*/ // Ensure that nothing happens when deleting a bucket that doesn't exist. func TestTx_DeleteBucket_NotFound(t *testing.T) { @@ -6429,8 +6437,8 @@ func TestTx_WriteTo_Error_Meta(t *testing.T) { } const expectedMsg = "meta 0 copy: error injected for tests" - err = db.View(func(tx ITx) error { - _, err := tx.WriteTo(&failWriter{}) + err = db.View(func(snapshot SnapshotI) error { + _, err := snapshot.WriteTo(&failWriter{}) return err }) if err == nil || err.Error() != expectedMsg { @@ -6466,8 +6474,8 @@ func TestTx_WriteTo_Error_Normal(t *testing.T) { t.Fatal(err) } - err = db.View(func(tx ITx) error { - _, err := tx.WriteTo(&failWriter{3 * db.pageSize}) + err = db.View(func(snapshot SnapshotI) error { + _, err := snapshot.WriteTo(&failWriter{3 * db.pageSize}) return err }) if err == nil || err.Error() != "error injected for tests" { @@ -6522,7 +6530,7 @@ func ExampleTx_Rollback() { } // Ensure that our original value is still set. - err = db.View(func(tx ITx) error { + err = db.View(func(snapshot SnapshotI) error { value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value for 'foo' is still: %s\n", value) return nil @@ -6750,7 +6758,7 @@ func MainTest() { { "TestTx_Rollback_ErrTxClosed", TestTx_Rollback_ErrTxClosed }, { "TestTx_Commit_ErrTxNotWritable", TestTx_Commit_ErrTxNotWritable }, { "TestTx_Cursor", TestTx_Cursor }, - { "TestTx_CreateBucket_ErrTxNotWritable", TestTx_CreateBucket_ErrTxNotWritable }, + // { "TestTx_CreateBucket_ErrTxNotWritable", TestTx_CreateBucket_ErrTxNotWritable }, { "TestTx_CreateBucket_ErrTxClosed", TestTx_CreateBucket_ErrTxClosed }, { "TestTx_Bucket", TestTx_Bucket }, { "TestTx_Get_NotFound", TestTx_Get_NotFound }, @@ -6761,7 +6769,7 @@ func MainTest() { { "TestTx_CreateBucket_ErrBucketNameRequired", TestTx_CreateBucket_ErrBucketNameRequired }, { "TestTx_DeleteBucket", TestTx_DeleteBucket }, { "TestTx_DeleteBucket_ErrTxClosed", TestTx_DeleteBucket_ErrTxClosed }, - { "TestTx_DeleteBucket_ReadOnly", TestTx_DeleteBucket_ReadOnly }, + // { "TestTx_DeleteBucket_ReadOnly", TestTx_DeleteBucket_ReadOnly }, { "TestTx_DeleteBucket_NotFound", TestTx_DeleteBucket_NotFound }, { "TestTx_ForEach_NoError", TestTx_ForEach_NoError }, { "TestTx_ForEach_WithError", TestTx_ForEach_WithError }, |