chore: cleanup store/v2 interface (#20280)

This commit is contained in:
cool-developer 2024-05-13 07:14:01 -04:00 committed by GitHub
parent 11de280625
commit 8d1946c9ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 244 additions and 215 deletions

View File

@ -30,6 +30,56 @@ type KVStore interface {
ReverseIterator(start, end []byte) (Iterator, error)
}
// Batch represents a group of writes. They may or may not be written atomically depending on the
// backend. Callers must call Close on the batch when done.
//
// As with KVStore, given keys and values should be considered read-only, and must not be modified after
// passing them to the batch.
type Batch interface {
// Set sets a key/value pair.
// CONTRACT: key, value readonly []byte
Set(key, value []byte) error
// Delete deletes a key/value pair.
// CONTRACT: key readonly []byte
Delete(key []byte) error
// Write writes the batch, possibly without flushing to disk. Only Close() can be called after,
// other methods will error.
Write() error
// WriteSync writes the batch and flushes it to disk. Only Close() can be called after, other
// methods will error.
WriteSync() error
// Close closes the batch. It is idempotent, but calls to other methods afterwards will error.
Close() error
// GetByteSize that returns the current size of the batch in bytes. Depending on the implementation,
// this may return the size of the underlying LSM batch, including the size of additional metadata
// on top of the expected key and value total byte count.
GetByteSize() (int, error)
}
// BatchCreator defines an interface for creating a new batch.
type BatchCreator interface {
// NewBatch creates a new batch for atomic updates. The caller must call Batch.Close.
NewBatch() Batch
// NewBatchWithSize create a new batch for atomic updates, but with pre-allocated size.
// This will does the same thing as NewBatch if the batch implementation doesn't support pre-allocation.
NewBatchWithSize(int) Batch
}
// KVStoreWithBatch is an extension of KVStore that allows for batch writes.
type KVStoreWithBatch interface {
KVStore
BatchCreator
// Close closes the KVStoreWithBatch, releasing any resources held.
Close() error
}
// Iterator represents an iterator over a domain of keys. Callers must call
// Close when done. No writes can happen to a domain while there exists an
// iterator over it. Some backends may take out database locks to ensure this

View File

@ -3,7 +3,15 @@ package store
// Batch is a write-only database that commits changes to the underlying database
// when Write is called. A batch cannot be used concurrently.
type Batch interface {
Writer
// Set inserts the given value into the key-value data store.
//
// Note: <key, value> are safe to modify and read after calling Set.
Set(storeKey, key, value []byte) error
// Delete removes the key from the backing key-value data store.
//
// Note: <key> is safe to modify and read after calling Delete.
Delete(storeKey, key []byte) error
// Size retrieves the amount of data queued up for writing, this includes
// the keys, values, and deleted keys.
@ -15,34 +23,3 @@ type Batch interface {
// Reset resets the batch.
Reset() error
}
// RawBatch represents a group of writes. They may or may not be written atomically depending on the
// backend. Callers must call Close on the batch when done.
//
// As with RawDB, given keys and values should be considered read-only, and must not be modified after
// passing them to the batch.
type RawBatch interface {
// Set sets a key/value pair.
// CONTRACT: key, value readonly []byte
Set(key, value []byte) error
// Delete deletes a key/value pair.
// CONTRACT: key readonly []byte
Delete(key []byte) error
// Write writes the batch, possibly without flushing to disk. Only Close() can be called after,
// other methods will error.
Write() error
// WriteSync writes the batch and flushes it to disk. Only Close() can be called after, other
// methods will error.
WriteSync() error
// Close closes the batch. It is idempotent, but calls to other methods afterwards will error.
Close() error
// GetByteSize that returns the current size of the batch in bytes. Depending on the implementation,
// this may return the size of the underlying LSM batch, including the size of additional metadata
// on top of the expected key and value total byte count.
GetByteSize() (int, error)
}

View File

@ -8,10 +8,10 @@ into store/v2, specifically the `RootStore` type.
A foremost design goal is that SC backends should be easily swappable, i.e. not
necessarily IAVL. To this end, the scope of SC has been reduced, it must only:
* Provide a stateful root app hash for height h resulting from applying a batch
- Provide a stateful root app hash for height h resulting from applying a batch
of key-value set/deletes to height h-1.
* Fulfill (though not necessarily provide) historical proofs for all heights < `h`.
* Provide an API for snapshot create/restore to fulfill state sync requests.
- Fulfill (though not necessarily provide) historical proofs for all heights < `h`.
- Provide an API for snapshot create/restore to fulfill state sync requests.
Notably, SC is not required to provide key iteration or value retrieval for either
queries or state machine execution, this now being the responsibility of state
@ -42,6 +42,6 @@ and `Restore` methods.
Similar to the `storage` package, the `commitment` package is designed to be used
in a broader store implementation, i.e. it fulfills the role of the SC backend.
Specifically, it provides a `CommitStore` type which accepts a `store.RawDB` and
a mapping from store key, a string meant to represent a single module, to a `Tree`,
which reflects the commitment structure.
Specifically, it provides a `CommitStore` type which accepts a `corestore.KVStore`
and a mapping from store key, a string meant to represent a single module, to a
`Tree`, which reflects the commitment structure.

View File

@ -6,8 +6,8 @@ import (
"github.com/cosmos/iavl"
ics23 "github.com/cosmos/ics23/go"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
dbm "cosmossdk.io/store/v2/db"
)
@ -20,7 +20,7 @@ type IavlTree struct {
}
// NewIavlTree creates a new IavlTree instance.
func NewIavlTree(db store.RawDB, logger log.Logger, cfg *Config) *IavlTree {
func NewIavlTree(db corestore.KVStoreWithBatch, logger log.Logger, cfg *Config) *IavlTree {
tree := iavl.NewMutableTree(dbm.NewWrapper(db), cfg.CacheSize, cfg.SkipFastStorageUpgrade, logger)
return &IavlTree{
tree: tree,

View File

@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
@ -14,7 +15,7 @@ import (
func TestCommitterSuite(t *testing.T) {
s := &commitment.CommitStoreTestSuite{
NewStore: func(db store.RawDB, storeKeys []string, pruneOpts *store.PruneOptions, logger log.Logger) (*commitment.CommitStore, error) {
NewStore: func(db corestore.KVStoreWithBatch, storeKeys []string, pruneOpts *store.PruneOptions, logger log.Logger) (*commitment.CommitStore, error) {
multiTrees := make(map[string]commitment.Tree)
cfg := DefaultConfig()
for _, storeKey := range storeKeys {

View File

@ -36,7 +36,7 @@ var (
// and trees.
type CommitStore struct {
logger log.Logger
db store.RawDB
db corestore.KVStoreWithBatch
multiTrees map[string]Tree
// pruneOptions is the pruning configuration.
@ -44,7 +44,7 @@ type CommitStore struct {
}
// NewCommitStore creates a new CommitStore instance.
func NewCommitStore(trees map[string]Tree, db store.RawDB, pruneOpts *store.PruneOptions, logger log.Logger) (*CommitStore, error) {
func NewCommitStore(trees map[string]Tree, db corestore.KVStoreWithBatch, pruneOpts *store.PruneOptions, logger log.Logger) (*CommitStore, error) {
if pruneOpts == nil {
pruneOpts = store.DefaultPruneOptions()
}

View File

@ -25,7 +25,7 @@ const (
type CommitStoreTestSuite struct {
suite.Suite
NewStore func(db store.RawDB, storeKeys []string, pruneOpts *store.PruneOptions, logger log.Logger) (*CommitStore, error)
NewStore func(db corestore.KVStoreWithBatch, storeKeys []string, pruneOpts *store.PruneOptions, logger log.Logger) (*CommitStore, error)
}
func (s *CommitStoreTestSuite) TestStore_Snapshotter() {

View File

@ -7,42 +7,6 @@ import (
"cosmossdk.io/store/v2/proof"
)
// Reader wraps the Has and Get method of a backing data store.
type Reader interface {
// Has retrieves if a key is present in the key-value data store.
//
// Note: <key> is safe to modify and read after calling Has.
Has(storeKey, key []byte) (bool, error)
// Get retrieves the given key if it's present in the key-value data store.
//
// Note: <key> is safe to modify and read after calling Get.
// The returned byte slice is safe to read, but cannot be modified.
Get(storeKey, key []byte) ([]byte, error)
}
// Writer wraps the Set method of a backing data store.
type Writer interface {
// Set inserts the given value into the key-value data store.
//
// Note: <key, value> are safe to modify and read after calling Set.
Set(storeKey, key, value []byte) error
// Delete removes the key from the backing key-value data store.
//
// Note: <key> is safe to modify and read after calling Delete.
Delete(storeKey, key []byte) error
}
// Database contains all the methods required to allow handling different
// key-value data stores backing the database.
type Database interface {
Reader
Writer
corestore.IteratorCreator
io.Closer
}
// VersionedDatabase defines an API for a versioned database that allows reads,
// writes, iteration and commitment over a series of versions.
type VersionedDatabase interface {
@ -107,44 +71,3 @@ type Committer interface {
// only be called once and any call after may panic.
io.Closer
}
// RawDB is the main interface for all key-value database backends. DBs are concurrency-safe.
// Callers must call Close on the database when done.
//
// Keys cannot be nil or empty, while values cannot be nil. Keys and values should be considered
// read-only, both when returned and when given, and must be copied before they are modified.
type RawDB interface {
// Get fetches the value of the given key, or nil if it does not exist.
// CONTRACT: key, value readonly []byte
Get([]byte) ([]byte, error)
// Has checks if a key exists.
// CONTRACT: key, value readonly []byte
Has(key []byte) (bool, error)
// Iterator returns an iterator over a domain of keys, in ascending order. The caller must call
// Close when done. End is exclusive, and start must be less than end. A nil start iterates
// from the first key, and a nil end iterates to the last key (inclusive). Empty keys are not
// valid.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// CONTRACT: start, end readonly []byte
Iterator(start, end []byte) (corestore.Iterator, error)
// ReverseIterator returns an iterator over a domain of keys, in descending order. The caller
// must call Close when done. End is exclusive, and start must be less than end. A nil end
// iterates from the last key (inclusive), and a nil start iterates to the first key (inclusive).
// Empty keys are not valid.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// CONTRACT: start, end readonly []byte
ReverseIterator(start, end []byte) (corestore.Iterator, error)
// Close closes the database connection.
Close() error
// NewBatch creates a batch for atomic updates. The caller must call Batch.Close.
NewBatch() RawBatch
// NewBatchWithSize create a new batch for atomic updates, but with pre-allocated size.
// This will does the same thing as NewBatch if the batch implementation doesn't support pre-allocation.
NewBatchWithSize(int) RawBatch
}

View File

@ -3,21 +3,22 @@ package db
import (
"fmt"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2"
)
type RawDBType string
type DBType string
const (
DBTypeGoLevelDB RawDBType = "goleveldb"
DBTypeRocksDB RawDBType = "rocksdb"
DBTypePebbleDB RawDBType = "pebbledb"
DBTypePrefixDB RawDBType = "prefixdb"
DBTypeGoLevelDB DBType = "goleveldb"
DBTypeRocksDB DBType = "rocksdb"
DBTypePebbleDB DBType = "pebbledb"
DBTypePrefixDB DBType = "prefixdb"
DBFileSuffix string = ".db"
)
func NewRawDB(dbType RawDBType, name, dataDir string, opts store.DBOptions) (store.RawDB, error) {
func NewDB(dbType DBType, name, dataDir string, opts store.DBOptions) (corestore.KVStoreWithBatch, error) {
switch dbType {
case DBTypeGoLevelDB:
return NewGoLevelDB(name, dataDir, opts)

View File

@ -7,13 +7,13 @@ import (
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"cosmossdk.io/store/v2"
corestore "cosmossdk.io/core/store"
)
type DBTestSuite struct {
suite.Suite
db store.RawDB
db corestore.KVStoreWithBatch
}
func (s *DBTestSuite) TearDownSuite() {
@ -21,7 +21,7 @@ func (s *DBTestSuite) TearDownSuite() {
}
func (s *DBTestSuite) TestDBOperations() {
// Set
// Batch Set
b := s.db.NewBatch()
s.Require().NoError(b.Set([]byte("key"), []byte("value")))
s.Require().NoError(b.Set([]byte("key1"), []byte("value1")))
@ -41,7 +41,7 @@ func (s *DBTestSuite) TestDBOperations() {
s.Require().NoError(err)
s.Require().False(has)
// Delete
// Batch Delete
b = s.db.NewBatch()
s.Require().NoError(b.Delete([]byte("key1")))
s.Require().NoError(b.Write())
@ -50,6 +50,22 @@ func (s *DBTestSuite) TestDBOperations() {
has, err = s.db.Has([]byte("key1"))
s.Require().NoError(err)
s.Require().False(has)
// Set & Delete
s.Require().NoError(s.db.Set([]byte("key3"), []byte("value3")))
has, err = s.db.Has([]byte("key3"))
s.Require().NoError(err)
s.Require().True(has)
value, err = s.db.Get([]byte("key3"))
s.Require().NoError(err)
s.Require().Equal([]byte("value3"), value)
s.Require().NoError(s.db.Delete([]byte("key3")))
has, err = s.db.Has([]byte("key3"))
s.Require().NoError(err)
s.Require().False(has)
value, err = s.db.Get([]byte("key3"))
s.Require().NoError(err)
s.Require().Nil(value)
}
func (s *DBTestSuite) TestIterator() {

View File

@ -19,9 +19,9 @@ import (
storeerrors "cosmossdk.io/store/v2/errors"
)
var _ store.RawDB = (*GoLevelDB)(nil)
var _ corestore.KVStoreWithBatch = (*GoLevelDB)(nil)
// GoLevelDB implements RawDB using github.com/syndtr/goleveldb/leveldb.
// GoLevelDB implements corestore.KVStore using github.com/syndtr/goleveldb/leveldb.
// It is used for only store v2 migration, since some clients use goleveldb as
// the IAVL v0/v1 backend.
type GoLevelDB struct {
@ -52,7 +52,7 @@ func NewGoLevelDBWithOpts(name, dir string, o *opt.Options) (*GoLevelDB, error)
return &GoLevelDB{db: db}, nil
}
// Get implements RawDB.
// Get implements corestore.KVStore.
func (db *GoLevelDB) Get(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, storeerrors.ErrKeyEmpty
@ -67,12 +67,12 @@ func (db *GoLevelDB) Get(key []byte) ([]byte, error) {
return res, nil
}
// Has implements RawDB.
// Has implements corestore.KVStore.
func (db *GoLevelDB) Has(key []byte) (bool, error) {
return db.db.Has(key, nil)
}
// Set implements RawDB.
// Set implements corestore.KVStore.
func (db *GoLevelDB) Set(key, value []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -83,7 +83,7 @@ func (db *GoLevelDB) Set(key, value []byte) error {
return db.db.Put(key, value, nil)
}
// SetSync implements RawDB.
// SetSync implements corestore.KVStore.
func (db *GoLevelDB) SetSync(key, value []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -94,7 +94,7 @@ func (db *GoLevelDB) SetSync(key, value []byte) error {
return db.db.Put(key, value, &opt.WriteOptions{Sync: true})
}
// Delete implements RawDB.
// Delete implements corestore.KVStore.
func (db *GoLevelDB) Delete(key []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -102,7 +102,7 @@ func (db *GoLevelDB) Delete(key []byte) error {
return db.db.Delete(key, nil)
}
// DeleteSync implements RawDB.
// DeleteSync implements corestore.KVStore.
func (db *GoLevelDB) DeleteSync(key []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -114,12 +114,12 @@ func (db *GoLevelDB) RawDB() *leveldb.DB {
return db.db
}
// Close implements RawDB.
// Close implements corestore.KVStore.
func (db *GoLevelDB) Close() error {
return db.db.Close()
}
// Print implements RawDB.
// Print implements corestore.KVStore.
func (db *GoLevelDB) Print() error {
str, err := db.db.GetProperty("leveldb.stats")
if err != nil {
@ -136,7 +136,7 @@ func (db *GoLevelDB) Print() error {
return nil
}
// Stats implements RawDB.
// Stats implements corestore.KVStore.
func (db *GoLevelDB) Stats() map[string]string {
keys := []string{
"leveldb.num-files-at-level{n}",
@ -162,17 +162,17 @@ func (db *GoLevelDB) ForceCompact(start, limit []byte) error {
return db.db.CompactRange(util.Range{Start: start, Limit: limit})
}
// NewBatch implements RawDB.
func (db *GoLevelDB) NewBatch() store.RawBatch {
// NewBatch implements corestore.BatchCreator.
func (db *GoLevelDB) NewBatch() corestore.Batch {
return newGoLevelDBBatch(db)
}
// NewBatchWithSize implements RawDB.
func (db *GoLevelDB) NewBatchWithSize(size int) store.RawBatch {
// NewBatchWithSize implements corestore.BatchCreator.
func (db *GoLevelDB) NewBatchWithSize(size int) corestore.Batch {
return newGoLevelDBBatchWithSize(db, size)
}
// Iterator implements RawDB.
// Iterator implements corestore.KVStore.
func (db *GoLevelDB) Iterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, storeerrors.ErrKeyEmpty
@ -181,7 +181,7 @@ func (db *GoLevelDB) Iterator(start, end []byte) (corestore.Iterator, error) {
return newGoLevelDBIterator(itr, start, end, false), nil
}
// ReverseIterator implements RawDB.
// ReverseIterator implements corestore.KVStore.
func (db *GoLevelDB) ReverseIterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, storeerrors.ErrKeyEmpty
@ -323,7 +323,7 @@ type goLevelDBBatch struct {
batch *leveldb.Batch
}
var _ store.RawBatch = (*goLevelDBBatch)(nil)
var _ corestore.Batch = (*goLevelDBBatch)(nil)
func newGoLevelDBBatch(db *GoLevelDB) *goLevelDBBatch {
return &goLevelDBBatch{
@ -339,7 +339,7 @@ func newGoLevelDBBatchWithSize(db *GoLevelDB, size int) *goLevelDBBatch {
}
}
// Set implements RawBatch.
// Set implements corestore.Batch.
func (b *goLevelDBBatch) Set(key, value []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -354,7 +354,7 @@ func (b *goLevelDBBatch) Set(key, value []byte) error {
return nil
}
// Delete implements RawBatch.
// Delete implements corestore.Batch.
func (b *goLevelDBBatch) Delete(key []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
@ -366,12 +366,12 @@ func (b *goLevelDBBatch) Delete(key []byte) error {
return nil
}
// Write implements RawBatch.
// Write implements corestore.Batch.
func (b *goLevelDBBatch) Write() error {
return b.write(false)
}
// WriteSync implements RawBatch.
// WriteSync implements corestore.Batch.
func (b *goLevelDBBatch) WriteSync() error {
return b.write(true)
}
@ -387,7 +387,7 @@ func (b *goLevelDBBatch) write(sync bool) error {
return b.Close()
}
// Close implements RawBatch.
// Close implements corestore.Batch.
func (b *goLevelDBBatch) Close() error {
if b.batch != nil {
b.batch.Reset()
@ -396,7 +396,7 @@ func (b *goLevelDBBatch) Close() error {
return nil
}
// GetByteSize implements RawBatch
// GetByteSize implements corestore.Batch
func (b *goLevelDBBatch) GetByteSize() (int, error) {
if b.batch == nil {
return 0, storeerrors.ErrBatchClosed

View File

@ -9,7 +9,6 @@ import (
"github.com/google/btree"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/errors"
)
@ -41,6 +40,8 @@ func newPair(key, value []byte) item {
return item{key: key, value: value}
}
var _ corestore.KVStoreWithBatch = (*MemDB)(nil)
// MemDB is an in-memory database backend using a B-tree for storage.
//
// For performance reasons, all given and returned keys and values are pointers to the in-memory
@ -52,8 +53,6 @@ type MemDB struct {
btree *btree.BTree
}
var _ store.RawDB = (*MemDB)(nil)
// NewMemDB creates a new in-memory database.
func NewMemDB() *MemDB {
database := &MemDB{
@ -168,13 +167,13 @@ func (db *MemDB) Stats() map[string]string {
}
// NewBatch implements DB.
func (db *MemDB) NewBatch() store.RawBatch {
func (db *MemDB) NewBatch() corestore.Batch {
return newMemDBBatch(db)
}
// NewBatchWithSize implements DB.
// It does the same thing as NewBatch because we can't pre-allocate memDBBatch
func (db *MemDB) NewBatchWithSize(size int) store.RawBatch {
func (db *MemDB) NewBatchWithSize(size int) corestore.Batch {
return newMemDBBatch(db)
}
@ -382,7 +381,7 @@ type memDBBatch struct {
size int
}
var _ store.RawBatch = (*memDBBatch)(nil)
var _ corestore.Batch = (*memDBBatch)(nil)
// newMemDBBatch creates a new memDBBatch
func newMemDBBatch(db *MemDB) *memDBBatch {

View File

@ -15,9 +15,9 @@ import (
storeerrors "cosmossdk.io/store/v2/errors"
)
var _ store.RawDB = (*PebbleDB)(nil)
var _ corestore.KVStoreWithBatch = (*PebbleDB)(nil)
// PebbleDB implements RawDB using PebbleDB as the underlying storage engine.
// PebbleDB implements `corestore.KVStoreWithBatch` using PebbleDB as the underlying storage engine.
// It is used for only store v2 migration, since some clients use PebbleDB as
// the IAVL v0/v1 backend.
type PebbleDB struct {
@ -87,6 +87,25 @@ func (db *PebbleDB) Has(key []byte) (bool, error) {
return bz != nil, nil
}
func (db *PebbleDB) Set(key, value []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
}
if value == nil {
return storeerrors.ErrValueNil
}
return db.storage.Set(key, value, &pebble.WriteOptions{Sync: false})
}
func (db *PebbleDB) Delete(key []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
}
return db.storage.Delete(key, &pebble.WriteOptions{Sync: false})
}
func (db *PebbleDB) Iterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, storeerrors.ErrKeyEmpty
@ -113,14 +132,14 @@ func (db *PebbleDB) ReverseIterator(start, end []byte) (corestore.Iterator, erro
return newPebbleDBIterator(itr, start, end, true), nil
}
func (db *PebbleDB) NewBatch() store.RawBatch {
func (db *PebbleDB) NewBatch() corestore.Batch {
return &pebbleDBBatch{
db: db,
batch: db.storage.NewBatch(),
}
}
func (db *PebbleDB) NewBatchWithSize(size int) store.RawBatch {
func (db *PebbleDB) NewBatchWithSize(size int) corestore.Batch {
return &pebbleDBBatch{
db: db,
batch: db.storage.NewBatchWithSize(size),
@ -225,7 +244,7 @@ func (itr *pebbleDBIterator) assertIsValid() {
}
}
var _ store.RawBatch = (*pebbleDBBatch)(nil)
var _ corestore.Batch = (*pebbleDBBatch)(nil)
type pebbleDBBatch struct {
db *PebbleDB

View File

@ -6,7 +6,6 @@ import (
"sync"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/errors"
)
@ -14,20 +13,20 @@ import (
type PrefixDB struct {
mtx sync.Mutex
prefix []byte
db store.RawDB
db corestore.KVStoreWithBatch
}
var _ store.RawDB = (*PrefixDB)(nil)
var _ corestore.KVStoreWithBatch = (*PrefixDB)(nil)
// NewPrefixDB lets you namespace multiple RawDBs within a single RawDB.
func NewPrefixDB(db store.RawDB, prefix []byte) *PrefixDB {
// NewPrefixDB lets you namespace multiple corestore.KVStores within a single corestore.KVStore.
func NewPrefixDB(db corestore.KVStoreWithBatch, prefix []byte) *PrefixDB {
return &PrefixDB{
prefix: prefix,
db: db,
}
}
// Get implements RawDB.
// Get implements corestore.KVStore.
func (pdb *PrefixDB) Get(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, errors.ErrKeyEmpty
@ -38,10 +37,11 @@ func (pdb *PrefixDB) Get(key []byte) ([]byte, error) {
if err != nil {
return nil, err
}
return value, nil
}
// Has implements RawDB.
// Has implements corestore.KVStore.
func (pdb *PrefixDB) Has(key []byte) (bool, error) {
if len(key) == 0 {
return false, errors.ErrKeyEmpty
@ -55,7 +55,25 @@ func (pdb *PrefixDB) Has(key []byte) (bool, error) {
return ok, nil
}
// Iterator implements RawDB.
// Set implements corestore.KVStore.
func (pdb *PrefixDB) Set(key, value []byte) error {
if len(key) == 0 {
return errors.ErrKeyEmpty
}
return pdb.db.Set(pdb.prefixed(key), value)
}
// Delete implements corestore.KVStore.
func (pdb *PrefixDB) Delete(key []byte) error {
if len(key) == 0 {
return errors.ErrKeyEmpty
}
return pdb.db.Delete(pdb.prefixed(key))
}
// Iterator implements corestore.KVStore.
func (pdb *PrefixDB) Iterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errors.ErrKeyEmpty
@ -76,7 +94,7 @@ func (pdb *PrefixDB) Iterator(start, end []byte) (corestore.Iterator, error) {
return newPrefixIterator(pdb.prefix, start, end, itr)
}
// ReverseIterator implements RawDB.
// ReverseIterator implements corestore.KVStore.
func (pdb *PrefixDB) ReverseIterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errors.ErrKeyEmpty
@ -97,17 +115,17 @@ func (pdb *PrefixDB) ReverseIterator(start, end []byte) (corestore.Iterator, err
return newPrefixIterator(pdb.prefix, start, end, ritr)
}
// NewBatch implements RawDB.
func (pdb *PrefixDB) NewBatch() store.RawBatch {
// NewBatch implements corestore.BatchCreator.
func (pdb *PrefixDB) NewBatch() corestore.Batch {
return newPrefixBatch(pdb.prefix, pdb.db.NewBatch())
}
// NewBatchWithSize implements RawDB.
func (pdb *PrefixDB) NewBatchWithSize(size int) store.RawBatch {
// NewBatchWithSize implements corestore.BatchCreator.
func (pdb *PrefixDB) NewBatchWithSize(size int) corestore.Batch {
return newPrefixBatch(pdb.prefix, pdb.db.NewBatchWithSize(size))
}
// Close implements RawDB.
// Close implements corestore.KVStore.
func (pdb *PrefixDB) Close() error {
pdb.mtx.Lock()
defer pdb.mtx.Unlock()
@ -115,7 +133,7 @@ func (pdb *PrefixDB) Close() error {
return pdb.db.Close()
}
// Print implements RawDB.
// Print implements corestore.KVStore.
func (pdb *PrefixDB) Print() error {
fmt.Printf("prefix: %X\n", pdb.prefix)
@ -138,7 +156,7 @@ func (pdb *PrefixDB) prefixed(key []byte) []byte {
// IteratePrefix is a convenience function for iterating over a key domain
// restricted by prefix.
func IteratePrefix(db store.RawDB, prefix []byte) (corestore.Iterator, error) {
func IteratePrefix(db corestore.KVStore, prefix []byte) (corestore.Iterator, error) {
var start, end []byte
if len(prefix) == 0 {
start = nil
@ -263,19 +281,19 @@ func (itr *prefixDBIterator) assertIsValid() {
type prefixDBBatch struct {
prefix []byte
source store.RawBatch
source corestore.Batch
}
var _ store.RawBatch = (*prefixDBBatch)(nil)
var _ corestore.Batch = (*prefixDBBatch)(nil)
func newPrefixBatch(prefix []byte, source store.RawBatch) prefixDBBatch {
func newPrefixBatch(prefix []byte, source corestore.Batch) prefixDBBatch {
return prefixDBBatch{
prefix: prefix,
source: source,
}
}
// Set implements RawBatch.
// Set implements corestore.Batch.
func (pb prefixDBBatch) Set(key, value []byte) error {
if len(key) == 0 {
return errors.ErrKeyEmpty
@ -287,7 +305,7 @@ func (pb prefixDBBatch) Set(key, value []byte) error {
return pb.source.Set(pkey, value)
}
// Delete implements RawBatch.
// Delete implements corestore.Batch.
func (pb prefixDBBatch) Delete(key []byte) error {
if len(key) == 0 {
return errors.ErrKeyEmpty
@ -296,22 +314,22 @@ func (pb prefixDBBatch) Delete(key []byte) error {
return pb.source.Delete(pkey)
}
// Write implements RawBatch.
// Write implements corestore.Batch.
func (pb prefixDBBatch) Write() error {
return pb.source.Write()
}
// WriteSync implements RawBatch.
// WriteSync implements corestore.Batch.
func (pb prefixDBBatch) WriteSync() error {
return pb.source.WriteSync()
}
// Close implements RawBatch.
// Close implements corestore.Batch.
func (pb prefixDBBatch) Close() error {
return pb.source.Close()
}
// GetByteSize implements RawBatch
// GetByteSize implements corestore.Batch
func (pb prefixDBBatch) GetByteSize() (int, error) {
if pb.source == nil {
return 0, errors.ErrBatchClosed

View File

@ -13,17 +13,16 @@ import (
"github.com/linxGnu/grocksdb"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2"
storeerrors "cosmossdk.io/store/v2/errors"
)
var (
_ store.RawDB = (*RocksDB)(nil)
_ corestore.KVStoreWithBatch = (*RocksDB)(nil)
defaultReadOpts = grocksdb.NewDefaultReadOptions()
)
// RocksDB implements RawDB using RocksDB as the underlying storage engine.
// RocksDB implements `corestore.KVStoreWithBatch` using RocksDB as the underlying storage engine.
// It is used for only store v2 migration, since some clients use RocksDB as
// the IAVL v0/v1 backend.
type RocksDB struct {
@ -92,6 +91,25 @@ func (db *RocksDB) Has(key []byte) (bool, error) {
return bz != nil, nil
}
func (db *RocksDB) Set(key, value []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
}
if value == nil {
return storeerrors.ErrValueNil
}
return db.storage.Put(grocksdb.NewDefaultWriteOptions(), key, value)
}
func (db *RocksDB) Delete(key []byte) error {
if len(key) == 0 {
return storeerrors.ErrKeyEmpty
}
return db.storage.Delete(grocksdb.NewDefaultWriteOptions(), key)
}
func (db *RocksDB) Iterator(start, end []byte) (corestore.Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, storeerrors.ErrKeyEmpty
@ -110,14 +128,14 @@ func (db *RocksDB) ReverseIterator(start, end []byte) (corestore.Iterator, error
return newRocksDBIterator(itr, start, end, true), nil
}
func (db *RocksDB) NewBatch() store.RawBatch {
func (db *RocksDB) NewBatch() corestore.Batch {
return &rocksDBBatch{
db: db,
batch: grocksdb.NewWriteBatch(),
}
}
func (db *RocksDB) NewBatchWithSize(_ int) store.RawBatch {
func (db *RocksDB) NewBatchWithSize(_ int) corestore.Batch {
return db.NewBatch()
}

View File

@ -8,9 +8,9 @@ import (
"cosmossdk.io/store/v2"
)
var _ store.RawDB = (*RocksDB)(nil)
var _ corestore.KVStoreWithBatch = (*RocksDB)(nil)
// RocksDB implements RawDB using RocksDB as the underlying storage engine.
// RocksDB implements `corestore.KVStoreWithBatch` using RocksDB as the underlying storage engine.
// It is used for only store v2 migration, since some clients use RocksDB as
// the IAVL v0/v1 backend.
type RocksDB struct{}
@ -35,6 +35,14 @@ func (db *RocksDB) Has(key []byte) (bool, error) {
panic("rocksdb must be built with -tags rocksdb")
}
func (db *RocksDB) Set(key, value []byte) error {
panic("rocksdb must be built with -tags rocksdb")
}
func (db *RocksDB) Delete(key []byte) error {
panic("rocksdb must be built with -tags rocksdb")
}
func (db *RocksDB) Iterator(start, end []byte) (corestore.Iterator, error) {
panic("rocksdb must be built with -tags rocksdb")
}
@ -43,10 +51,10 @@ func (db *RocksDB) ReverseIterator(start, end []byte) (corestore.Iterator, error
panic("rocksdb must be built with -tags rocksdb")
}
func (db *RocksDB) NewBatch() store.RawBatch {
func (db *RocksDB) NewBatch() corestore.Batch {
panic("rocksdb must be built with -tags rocksdb")
}
func (db *RocksDB) NewBatchWithSize(_ int) store.RawBatch {
return db.NewBatch()
func (db *RocksDB) NewBatchWithSize(_ int) corestore.Batch {
panic("rocksdb must be built with -tags rocksdb")
}

View File

@ -3,37 +3,37 @@ package db
import (
idb "github.com/cosmos/iavl/db"
"cosmossdk.io/store/v2"
corestore "cosmossdk.io/core/store"
)
// Wrapper wraps a RawDB to implement iavl.DB which is used by iavl.Tree.
// Wrapper wraps a `corestore.KVStoreWithBatch` to implement iavl.DB which is used by iavl.Tree.
type Wrapper struct {
store.RawDB
corestore.KVStoreWithBatch
}
var _ idb.DB = (*Wrapper)(nil)
// NewWrapper returns a new Wrapper.
func NewWrapper(db store.RawDB) *Wrapper {
return &Wrapper{RawDB: db}
func NewWrapper(db corestore.KVStoreWithBatch) *Wrapper {
return &Wrapper{KVStoreWithBatch: db}
}
// Iterator implements iavl.DB.
func (db *Wrapper) Iterator(start, end []byte) (idb.Iterator, error) {
return db.RawDB.Iterator(start, end)
return db.KVStoreWithBatch.Iterator(start, end)
}
// ReverseIterator implements iavl.DB.
func (db *Wrapper) ReverseIterator(start, end []byte) (idb.Iterator, error) {
return db.RawDB.ReverseIterator(start, end)
return db.KVStoreWithBatch.ReverseIterator(start, end)
}
// NewBatch implements iavl.DB.
func (db *Wrapper) NewBatch() idb.Batch {
return db.RawDB.NewBatch()
return db.KVStoreWithBatch.NewBatch()
}
// NewBatchWithSize implements iavl.DB.
func (db *Wrapper) NewBatchWithSize(size int) idb.Batch {
return db.RawDB.NewBatchWithSize(size)
return db.KVStoreWithBatch.NewBatchWithSize(size)
}

View File

@ -12,7 +12,6 @@ import (
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
"cosmossdk.io/store/v2/internal/encoding"
"cosmossdk.io/store/v2/snapshots"
@ -43,7 +42,7 @@ type Manager struct {
stateStorage *storage.StorageStore
stateCommitment *commitment.CommitStore
db store.RawDB
db corestore.KVStoreWithBatch
mtx sync.Mutex // mutex for migratedVersion
migratedVersion uint64
@ -54,7 +53,7 @@ type Manager struct {
// NewManager returns a new Manager.
//
// NOTE: `sc` can be `nil` if don't want to migrate the commitment.
func NewManager(db store.RawDB, sm *snapshots.Manager, ss *storage.StorageStore, sc *commitment.CommitStore, logger log.Logger) *Manager {
func NewManager(db corestore.KVStoreWithBatch, sm *snapshots.Manager, ss *storage.StorageStore, sc *commitment.CommitStore, logger log.Logger) *Manager {
return &Manager{
logger: logger,
snapshotsManager: sm,

View File

@ -16,8 +16,8 @@ import (
"github.com/cosmos/gogoproto/proto"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/errors"
"cosmossdk.io/store/v2"
storeerrors "cosmossdk.io/store/v2/errors"
"cosmossdk.io/store/v2/snapshots/types"
)
@ -420,7 +420,7 @@ func legacyV1EncodeKey(height uint64, format uint32) []byte {
return k
}
func (s *Store) MigrateFromV1(db store.RawDB) error {
func (s *Store) MigrateFromV1(db corestore.KVStore) error {
itr, err := db.Iterator(legacyV1EncodeKey(0, 0), legacyV1EncodeKey(math.MaxUint64, math.MaxUint32))
if err != nil {
return err