diff options
author | EuAndreh <eu@euandre.org> | 2025-02-21 15:08:45 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-02-21 15:08:45 -0300 |
commit | 5babfeb0d8a2c277e0d0169a51d8338292f4e8fa (patch) | |
tree | 7c3c8c638317084d87051c602b603ebe58b3949b | |
parent | src/dedo.go: Add separate read and read-write ROCursorI and RWCursorI types (diff) | |
download | dedo-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.go | 135 |
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 { |