Skip to content

Commit 33c8314

Browse files
authored
feat: ADR-040: Implement RocksDB backend (#9851)
## Description Partially resolves: vulcanize#14 Implements a [RocksDB](https://github.com/facebook/rocksdb)-based backend for the DB interface introduced by #9573 and specified by [ADR-040](https://github.com/cosmos/cosmos-sdk/blob/eb7d939f86c6cd7b4218492364cdda3f649f06b5/docs/architecture/adr-040-storage-and-smt-state-commitments.md). * Historical versioning is implemented with [Checkpoints](https://github.com/facebook/rocksdb/wiki/Checkpoints). * Uses `OptimisticTransactionDB` to allow concurrent transactions with write conflict detection. This depends on some additional CGo bindings - see tecbot/gorocksdb#216, facebook/rocksdb#8526. We'll need to replace the `gorocksdb` module until these are upstream. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [x] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - n/a - [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [x] added a changelog entry to `CHANGELOG.md` - [x] included comments for [documenting Go code](https://blog.golang.org/godoc) - [x] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
1 parent 9094794 commit 33c8314

File tree

15 files changed

+1063
-55
lines changed

15 files changed

+1063
-55
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
188188
* [\#9573](https://github.com/cosmos/cosmos-sdk/pull/9573) ADR 040 implementation: New DB interface
189189
* [\#9952](https://github.com/cosmos/cosmos-sdk/pull/9952) ADR 040: Implement in-memory DB backend
190190
* [\#9848](https://github.com/cosmos/cosmos-sdk/pull/9848) ADR-040: Implement BadgerDB backend
191+
* [\#9851](https://github.com/cosmos/cosmos-sdk/pull/9851) ADR-040: Implement RocksDB backend
191192

192193

193194
### Client Breaking Changes

db/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,6 @@ tx2.Set(key, []byte("b"))
6262
tx1.Commit() // ok
6363
tx2.Commit() // ok
6464
```
65+
### RocksDB
66+
67+
A [RocksDB](https://github.com/facebook/rocksdb)-based backend. Internally this uses [`OptimisticTransactionDB`](https://github.com/facebook/rocksdb/wiki/Transactions#optimistictransactiondb) to allow concurrent transactions with write conflict detection. Historical versioning is internally implemented with [Checkpoints](https://github.com/facebook/rocksdb/wiki/Checkpoints).

db/badgerdb/db.go

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package badgerdb
33
import (
44
"bytes"
55
"encoding/csv"
6+
"errors"
67
"math"
78
"os"
89
"path/filepath"
@@ -11,6 +12,7 @@ import (
1112
"sync/atomic"
1213

1314
dbm "github.com/cosmos/cosmos-sdk/db"
15+
dbutil "github.com/cosmos/cosmos-sdk/db/internal"
1416

1517
"github.com/dgraph-io/badger/v3"
1618
)
@@ -41,14 +43,16 @@ type badgerTxn struct {
4143

4244
type badgerWriter struct {
4345
badgerTxn
46+
discarded bool
4447
}
4548

4649
type badgerIterator struct {
4750
reverse bool
4851
start, end []byte
4952
iter *badger.Iterator
5053
lastErr error
51-
primed bool
54+
// Whether iterator has been advanced to the first element (is fully initialized)
55+
primed bool
5256
}
5357

5458
// Map our versions to Badger timestamps.
@@ -168,9 +172,9 @@ func (b *BadgerDB) ReaderAt(version uint64) (dbm.DBReader, error) {
168172
func (b *BadgerDB) ReadWriter() dbm.DBReadWriter {
169173
atomic.AddInt32(&b.openWriters, 1)
170174
b.mtx.RLock()
171-
ts := b.vmgr.lastCommitTs()
175+
ts := b.vmgr.lastTs
172176
b.mtx.RUnlock()
173-
return &badgerWriter{badgerTxn{txn: b.db.NewTransactionAt(ts, true), db: b}}
177+
return &badgerWriter{badgerTxn{txn: b.db.NewTransactionAt(ts, true), db: b}, false}
174178
}
175179

176180
func (b *BadgerDB) Writer() dbm.DBWriter {
@@ -261,11 +265,8 @@ func (tx *badgerTxn) Has(key []byte) (bool, error) {
261265
}
262266

263267
func (tx *badgerWriter) Set(key, value []byte) error {
264-
if len(key) == 0 {
265-
return dbm.ErrKeyEmpty
266-
}
267-
if value == nil {
268-
return dbm.ErrValueNil
268+
if err := dbutil.ValidateKv(key, value); err != nil {
269+
return err
269270
}
270271
return tx.txn.Set(key, value)
271272
}
@@ -277,20 +278,31 @@ func (tx *badgerWriter) Delete(key []byte) error {
277278
return tx.txn.Delete(key)
278279
}
279280

280-
func (tx *badgerWriter) Commit() error {
281+
func (tx *badgerWriter) Commit() (err error) {
282+
if tx.discarded {
283+
return errors.New("transaction has been discarded")
284+
}
285+
defer func() { err = dbutil.CombineErrors(err, tx.Discard(), "Discard also failed") }()
281286
// Commit to the current commit TS, after ensuring it is > ReadTs
287+
tx.db.mtx.RLock()
282288
tx.db.vmgr.updateCommitTs(tx.txn.ReadTs())
283-
defer tx.Discard()
284-
return tx.txn.CommitAt(tx.db.vmgr.lastCommitTs(), nil)
289+
ts := tx.db.vmgr.lastTs
290+
tx.db.mtx.RUnlock()
291+
err = tx.txn.CommitAt(ts, nil)
292+
return
285293
}
286294

287-
func (tx *badgerTxn) Discard() {
295+
func (tx *badgerTxn) Discard() error {
288296
tx.txn.Discard()
297+
return nil
289298
}
290299

291-
func (tx *badgerWriter) Discard() {
292-
defer atomic.AddInt32(&tx.db.openWriters, -1)
293-
tx.badgerTxn.Discard()
300+
func (tx *badgerWriter) Discard() error {
301+
if !tx.discarded {
302+
defer atomic.AddInt32(&tx.db.openWriters, -1)
303+
tx.discarded = true
304+
}
305+
return tx.badgerTxn.Discard()
294306
}
295307

296308
func (tx *badgerTxn) iteratorOpts(start, end []byte, opts badger.IteratorOptions) (*badgerIterator, error) {
@@ -393,9 +405,11 @@ func (vm *versionManager) Copy() *versionManager {
393405
}
394406
}
395407

396-
// updateCommitTs atomically increments the lastTs if equal to readts.
408+
// updateCommitTs increments the lastTs if equal to readts.
397409
func (vm *versionManager) updateCommitTs(readts uint64) {
398-
atomic.CompareAndSwapUint64(&vm.lastTs, readts, readts+1)
410+
if vm.lastTs == readts {
411+
vm.lastTs += 1
412+
}
399413
}
400414
func (vm *versionManager) Save(target uint64) (uint64, error) {
401415
id, err := vm.VersionManager.Save(target)

0 commit comments

Comments
 (0)