aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2025-02-19 16:31:05 -0300
committerEuAndreh <eu@euandre.org>2025-02-19 16:34:07 -0300
commit324d89a816da1ef30a33eff7bc796247e196a9e1 (patch)
treed1349b1aa2d350af864c0104872fdd5486e0266e
parentsrc/dedo.go: Add strict separation between ROBucketI and RWBucketI (diff)
downloaddedo-324d89a816da1ef30a33eff7bc796247e196a9e1.tar.gz
dedo-324d89a816da1ef30a33eff7bc796247e196a9e1.tar.xz
src/dedo.go: Add separate read and read-write ROCursorI and RWCursorI types
-rw-r--r--src/dedo.go72
-rw-r--r--tests/dedo.go40
2 files changed, 71 insertions, 41 deletions
diff --git a/src/dedo.go b/src/dedo.go
index f308b71..4a27286 100644
--- a/src/dedo.go
+++ b/src/dedo.go
@@ -62,27 +62,38 @@ import (
-type CursorI interface{
+type baseCursorI interface{
First() ([]byte, []byte)
Last() ([]byte, []byte)
Next() ([]byte, []byte)
Prev() ([]byte, []byte)
Seek([]byte) ([]byte, []byte)
+}
+
+type ROCursorI interface{
+ baseCursorI
+}
+
+type RWCursorI interface{
+ baseCursorI
Delete() error
}
-type ROBucketI interface{
+type baseBucketI interface{
Get([]byte) []byte
- Cursor() CursorI
ForEach(func([]byte, []byte) error) error
+}
+
+type ROBucketI interface{
+ baseBucketI
ROBucket([]byte) (ROBucketI, error)
+ ROCursor() ROCursorI
}
type RWBucketI interface{
- Get([]byte) []byte
- Cursor() CursorI
- ForEach(func([]byte, []byte) error) error
+ baseBucketI
RWBucket([]byte) (RWBucketI, error)
+ RWCursor() RWCursorI
Put([]byte, []byte) error
Delete([]byte) error
CreateBucket([]byte) (RWBucketI, error)
@@ -92,23 +103,23 @@ type RWBucketI interface{
NextSequence() (uint64, error)
}
+type baseOperationI interface{
+ WriteTo(io.Writer) (int64, error)
+ Check() <-chan error
+}
+
type SnapshotI interface{
+ baseOperationI
ROBucket([]byte) (ROBucketI, error)
- Cursor() CursorI
+ ROCursor() ROCursorI
ROForEach(func([]byte, ROBucketI) error) error
-
- WriteTo(io.Writer) (int64, error)
- Check() <-chan error
}
type TransactionI interface{
+ baseOperationI
RWBucket([]byte) (RWBucketI, error)
- Cursor() CursorI
+ RWCursor() RWCursorI
RWForEach(func([]byte, RWBucketI) error) error
-
- WriteTo(io.Writer) (int64, error)
- Check() <-chan error
-
CreateBucket ([]byte) (RWBucketI, error)
CreateBucketIfNotExists([]byte) (RWBucketI, error)
DeleteBucket([]byte) error
@@ -648,7 +659,11 @@ func bucketCursor(b *bucketT) *cursorT {
}
}
-func (b *bucketT) Cursor() CursorI {
+func (b *bucketT) ROCursor() ROCursorI {
+ return bucketCursor(b)
+}
+
+func (b *bucketT) RWCursor() RWCursorI {
return bucketCursor(b)
}
@@ -979,7 +994,7 @@ func bucketForEach(b *bucketT, fn func(k, v []byte) error) error {
if b.tx.db == nil {
return ErrTxClosed
}
- c := b.Cursor()
+ c := bucketCursor(b)
for k, v := c.First(); k != nil; k, v = c.Next() {
err := fn(k, v)
if err != nil {
@@ -1914,7 +1929,14 @@ func (bucket *inMemoryValueT) DeleteBucket(name []byte) error {
return nil
}
-func (bucket *inMemoryValueT) Cursor() CursorI {
+func (bucket *inMemoryValueT) ROCursor() ROCursorI {
+ return &inMemoryCursorT{
+ bucket: bucket,
+ iterator: bucket.data.Iterator(),
+ }
+}
+
+func (bucket *inMemoryValueT) RWCursor() RWCursorI {
return &inMemoryCursorT{
bucket: bucket,
iterator: bucket.data.Iterator(),
@@ -1926,7 +1948,7 @@ func (bucket *inMemoryValueT) ForEach(fn func([]byte, []byte) error) error {
return ErrTxClosed
}
- cursor := bucket.Cursor()
+ cursor := bucket.ROCursor()
for key, value := cursor.First(); key != nil; key, value = cursor.Next() {
err := fn(key, value)
if err != nil {
@@ -2003,7 +2025,11 @@ func (tx *inMemoryTxT) CreateBucketIfNotExists(name []byte) (RWBucketI, error) {
return nil, nil // FIXME
}
-func (tx *inMemoryTxT) Cursor() CursorI {
+func (tx *inMemoryTxT) ROCursor() ROCursorI {
+ return nil // FIXME
+}
+
+func (tx *inMemoryTxT) RWCursor() RWCursorI {
return nil // FIXME
}
@@ -3823,7 +3849,11 @@ func txCursor(tx *transactionT) *cursorT {
return bucketCursor(&tx.root)
}
-func (tx *transactionT) Cursor() CursorI {
+func (tx *transactionT) ROCursor() ROCursorI {
+ return txCursor(tx)
+}
+
+func (tx *transactionT) RWCursor() RWCursorI {
return txCursor(tx)
}
diff --git a/tests/dedo.go b/tests/dedo.go
index bce24b5..d0489ee 100644
--- a/tests/dedo.go
+++ b/tests/dedo.go
@@ -656,7 +656,7 @@ func TestBucket_Get_Capacity(t *testing.T) {
// Retrieve value and attempt to append to it.
err = db.Update(func(tx TransactionI) error {
- k, v := g.Must(tx.RWBucket([]byte("bucket"))).Cursor().First()
+ k, v := g.Must(tx.RWBucket([]byte("bucket"))).RWCursor().First()
// Verify capacity.
if len(k) != cap(k) {
@@ -1009,7 +1009,7 @@ func TestBucket_Delete_FreelistOverflow(t *testing.T) {
// Delete all of them in one large transaction
err := db.Update(func(tx TransactionI) error {
b := g.Must(tx.RWBucket([]byte("0")))
- c := b.Cursor()
+ c := b.RWCursor()
for k, _ := c.First(); k != nil; k, _ = c.Next() {
err := c.Delete()
if err != nil {
@@ -2224,7 +2224,7 @@ func TestCursor_Seek(t *testing.T) {
}
err = db.View(func(snapshot SnapshotI) error {
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
// Exact match should go to the key.
k, v := c.Seek([]byte("bar"))
@@ -2308,7 +2308,7 @@ func TestCursor_Delete(t *testing.T) {
}
err = db.Update(func(tx TransactionI) error {
- c := g.Must(tx.RWBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.RWBucket([]byte("widgets"))).RWCursor()
bound := make([]byte, 8)
binary.BigEndian.PutUint64(bound, uint64(count/2))
for
@@ -2370,7 +2370,7 @@ func TestCursor_Seek_Large(t *testing.T) {
}
err = db.View(func(snapshot SnapshotI) error {
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
for i := 0; i < count; i++ {
seek := make([]byte, 8)
binary.BigEndian.PutUint64(seek, uint64(i))
@@ -2422,7 +2422,7 @@ func TestCursor_EmptyBucket(t *testing.T) {
}
err = db.View(func(snapshot SnapshotI) error {
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
k, v := c.First()
if k != nil {
t.Fatalf("unexpected key: %v", k)
@@ -2452,7 +2452,7 @@ func TestCursor_EmptyBucketReverse(t *testing.T) {
}
err = db.View(func(snapshot SnapshotI) error {
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
k, v := c.Last()
if k != nil {
t.Fatalf("unexpected key: %v", k)
@@ -2506,7 +2506,7 @@ func TestCursor_Iterate_Leaf(t *testing.T) {
}
defer func() { _ = tx.rollback() }()
- c := g.Must(tx.RWBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
k, v := c.First()
if !bytes.Equal(k, []byte("bar")) {
@@ -2588,7 +2588,7 @@ func TestCursor_LeafRootReverse(t *testing.T) {
t.Fatal(err)
}
- c := g.Must(tx.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
k, v := c.Last()
if !bytes.Equal(k, []byte("foo")) {
t.Fatalf("unexpected key: %v", k)
@@ -2663,7 +2663,7 @@ func TestCursor_Restart(t *testing.T) {
t.Fatal(err)
}
- c := g.Must(tx.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
k, _ := c.First()
if !bytes.Equal(k, []byte("bar")) {
@@ -2726,7 +2726,7 @@ func TestCursor_First_EmptyPages(t *testing.T) {
}
}
- c := b.Cursor()
+ c := b.RWCursor()
var n int
for k, _ := c.First(); k != nil; k, _ = c.Next() {
n++
@@ -2780,7 +2780,7 @@ func TestCursor_QuickCheck(t *testing.T) {
t.Fatal(err)
}
- c := g.Must(tx.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
for
k, v := c.First();
k != nil && index < len(items);
@@ -2855,7 +2855,7 @@ func TestCursor_QuickCheck_Reverse(t *testing.T) {
t.Fatal(err)
}
- c := g.Must(tx.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
for
k, v := c.Last();
k != nil && index < len(items);
@@ -2925,7 +2925,7 @@ func TestCursor_QuickCheck_BucketsOnly(t *testing.T) {
err = db.View(func(snapshot SnapshotI) error {
names := []string{}
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
names = append(names, string(k))
if v != nil {
@@ -2979,7 +2979,7 @@ func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) {
err = db.View(func(snapshot SnapshotI) error {
names := []string{}
- c := g.Must(snapshot.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(snapshot.ROBucket([]byte("widgets"))).ROCursor()
for k, v := c.Last(); k != nil; k, v = c.Prev() {
names = append(names, string(k))
if v != nil {
@@ -3031,7 +3031,7 @@ func ExampleCursor() {
}
// Create a cursor for iteration.
- c := b.Cursor()
+ c := b.RWCursor()
// Iterate over items in sorted key order. This starts from the
// first key/value pair and updates the k/v variables to the
@@ -3093,7 +3093,7 @@ func ExampleCursor_reverse() {
}
// Create a cursor for iteration.
- c := b.Cursor()
+ c := b.RWCursor()
// Iterate over items in reverse sorted key order. This starts
// from the last key/value pair and updates the k/v variables to
@@ -4283,7 +4283,7 @@ func ExampleDB_Begin_ReadOnly() {
if err != nil {
log.Fatal(err)
}
- c := g.Must(tx.ROBucket([]byte("widgets"))).Cursor()
+ c := g.Must(tx.ROBucket([]byte("widgets"))).ROCursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
fmt.Printf("%s likes %s\n", k, v)
}
@@ -4499,7 +4499,7 @@ func validateBatchBench(b *testing.B, db *WDB) {
}
}
// should be empty now
- c := bucket.Cursor()
+ c := bucket.RWCursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
b.Errorf("unexpected key: %x = %q", k, v)
}
@@ -5808,7 +5808,7 @@ func TestTx_Cursor(t *testing.T) {
t.Fatal(err)
}
- c := tx.Cursor()
+ c := tx.RWCursor()
k, v := c.First()
if !bytes.Equal(k, []byte("widgets")) {
t.Fatalf("unexpected key: %v", k)