aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2025-02-21 15:08:45 -0300
committerEuAndreh <eu@euandre.org>2025-02-21 15:08:45 -0300
commit5babfeb0d8a2c277e0d0169a51d8338292f4e8fa (patch)
tree7c3c8c638317084d87051c602b603ebe58b3949b
parentsrc/dedo.go: Add separate read and read-write ROCursorI and RWCursorI types (diff)
downloaddedo-5babfeb0d8a2c277e0d0169a51d8338292f4e8fa.tar.gz
dedo-5babfeb0d8a2c277e0d0169a51d8338292f4e8fa.tar.xz
src/dedo.go: (Re) Add API that allows external control of the transaction
-rw-r--r--src/dedo.go135
1 files changed, 94 insertions, 41 deletions
diff --git a/src/dedo.go b/src/dedo.go
index 4a27286..bca1d83 100644
--- a/src/dedo.go
+++ b/src/dedo.go
@@ -113,6 +113,7 @@ type SnapshotI interface{
ROBucket([]byte) (ROBucketI, error)
ROCursor() ROCursorI
ROForEach(func([]byte, ROBucketI) error) error
+ Close() error
}
type TransactionI interface{
@@ -124,14 +125,18 @@ type TransactionI interface{
CreateBucketIfNotExists([]byte) (RWBucketI, error)
DeleteBucket([]byte) error
OnCommit(func())
+ Commit() error
+ Rollback() error
}
type DatabaseI interface{
- Close() error
- View (func(tx SnapshotI) error) error
- Update(func(tx TransactionI) error) error
+ View (func(SnapshotI) error) error
+ Update(func(TransactionI) error) error
OnCommit(func())
+ Snapshot() (SnapshotI, error)
+ Transaction() (TransactionI, error)
Path() string
+ Close() error
}
/// transactionT represents a read-only or read/write transaction on the
@@ -2072,7 +2077,25 @@ func (db *inMemoryDatabaseT) Path() string {
return "" // FIXME
}
-func (db *inMemoryDatabaseT) Update(fn func(TransactionI) error) error {
+func memBeginSnapshot(db *inMemoryDatabaseT) (*inMemoryTxT, error) {
+ db.rwmutex.RLock()
+ defer db.rwmutex.RUnlock()
+
+ tx := &inMemoryTxT{
+ root: &inMemoryValueT{
+ isBucket: true,
+ value: nil,
+ data: db.root,
+ },
+ commitHandlers: nil,
+ writable: false,
+ }
+ tx.root.tx = tx
+
+ return tx, nil
+}
+
+func memBeginTransaction(db *inMemoryDatabaseT) (*inMemoryTxT, error) {
db.rwmutex.Lock()
defer db.rwmutex.Unlock()
@@ -2087,35 +2110,63 @@ func (db *inMemoryDatabaseT) Update(fn func(TransactionI) error) error {
}
tx.root.tx = tx
- err := fn(tx)
+ return tx, nil
+
+}
+
+func memTransactionRollback(transaction *inMemoryTxT) error {
+ transaction.root = nil
+ return nil
+}
+
+func memTransactionCommit(transaction *inMemoryTxT) error {
+ // transaction.db.root = transaction.root.data
+ // runHandlers(slices.Concat(transaction.commitHandlers, transaction.db.commitHandlers))
+ return nil
+}
+
+func (transaction *inMemoryTxT) Close() error {
+ return nil
+}
+
+func (transaction *inMemoryTxT) Rollback() error {
+ return memTransactionRollback(transaction)
+}
+
+func (transaction *inMemoryTxT) Commit() error {
+ return memTransactionCommit(transaction)
+}
+
+func (db *inMemoryDatabaseT) Update(fn func(TransactionI) error) error {
+ transaction, err := memBeginTransaction(db)
if err != nil {
- tx.root = nil
return err
}
+ defer memTransactionRollback(transaction)
- // commit
- db.root = tx.root.data
-
- runHandlers(slices.Concat(tx.commitHandlers, db.commitHandlers))
+ err = fn(transaction)
+ if err != nil {
+ return err
+ }
- return nil
+ return memTransactionCommit(transaction)
}
func (db *inMemoryDatabaseT) View(fn func(SnapshotI) error) error {
- db.rwmutex.RLock()
- defer db.rwmutex.RUnlock()
-
- tx := &inMemoryTxT{
- root: &inMemoryValueT{
- isBucket: true,
- value: nil,
- data: db.root,
- },
- commitHandlers: nil,
- writable: false,
+ snapshot, err := memBeginSnapshot(db)
+ if err != nil {
+ return err
}
- tx.root.tx = tx
- return fn(tx)
+
+ return fn(snapshot)
+}
+
+func (db *inMemoryDatabaseT) Snapshot() (SnapshotI, error) {
+ return memBeginSnapshot(db)
+}
+
+func (db *inMemoryDatabaseT) Transaction() (TransactionI, error) {
+ return memBeginTransaction(db)
}
func OpenMemory() DatabaseI {
@@ -2483,27 +2534,29 @@ func (db *databaseT) View(fn func(SnapshotI) error) error {
if err != nil {
return err
}
+ defer t.rollback()
- // Make sure the transaction rolls back in the event of a panic.
- defer func() {
- if t.db != nil {
- t.doRollback()
- }
- }()
+ return fn(t)
+}
- // If an error is returned from the function then pass it through.
- err = fn(t)
- if err != nil {
- _ = t.rollback()
- return err
- }
+func (db *databaseT) Snapshot() (SnapshotI, error) {
+ return db.beginSnapshot()
+}
- err = t.rollback()
- if err != nil {
- return err
- }
+func (db *databaseT) Transaction() (TransactionI, error) {
+ return db.beginTransaction()
+}
- return nil
+func (snapshot *transactionT) Close() error {
+ return snapshot.rollback()
+}
+
+func(transaction *transactionT) Rollback() error {
+ return transaction.rollback()
+}
+
+func(transaction *transactionT) Commit() error {
+ return transaction.Commit()
}
func needsNewBatch(batch *batch, max int) bool {