Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement object stores #206

Merged
merged 13 commits into from
Mar 25, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features

* (baseapp) [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Add `TxExecutor` baseapp option, add `TxIndex`/`TxCount`/`MsgIndex`/`BlockGasUsed` fields to `Context, to support tx parallel execution.
* (baseapp) [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Support mount object store in baseapp, add `ObjectStore` api in context..

## [Unreleased-Upstream]

Expand Down
11 changes: 11 additions & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,17 @@ func (app *BaseApp) MountMemoryStores(keys map[string]*storetypes.MemoryStoreKey
}
}

// MountObjectStores mounts all in-memory KVStores with the BaseApp's internal
yihuang marked this conversation as resolved.
Show resolved Hide resolved
// commit multi-store.
func (app *BaseApp) MountObjectStores(keys map[string]*storetypes.ObjectStoreKey) {
skeys := maps.Keys(keys)
sort.Strings(skeys)
for _, key := range skeys {
memKey := keys[key]
app.MountStore(memKey, storetypes.StoreTypeObject)
}
}

// MountStore mounts a store to the provided key in the BaseApp multistore,
// using the default DB.
func (app *BaseApp) MountStore(key storetypes.StoreKey, typ storetypes.StoreType) {
Expand Down
11 changes: 2 additions & 9 deletions runtime/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ package runtime

import (
"context"
"io"

dbm "github.com/cosmos/cosmos-db"

"cosmossdk.io/core/store"
storetypes "cosmossdk.io/store/types"
Expand Down Expand Up @@ -104,10 +101,6 @@ func (kvStoreAdapter) CacheWrap() storetypes.CacheWrap {
panic("unimplemented")
}

func (kvStoreAdapter) CacheWrapWithTrace(w io.Writer, tc storetypes.TraceContext) storetypes.CacheWrap {
panic("unimplemented")
}

func (kvStoreAdapter) GetStoreType() storetypes.StoreType {
panic("unimplemented")
}
Expand Down Expand Up @@ -142,15 +135,15 @@ func (s kvStoreAdapter) Set(key, value []byte) {
}
}

func (s kvStoreAdapter) Iterator(start, end []byte) dbm.Iterator {
func (s kvStoreAdapter) Iterator(start, end []byte) storetypes.Iterator {
it, err := s.store.Iterator(start, end)
if err != nil {
panic(err)
}
return it
}

func (s kvStoreAdapter) ReverseIterator(start, end []byte) dbm.Iterator {
func (s kvStoreAdapter) ReverseIterator(start, end []byte) storetypes.Iterator {
it, err := s.store.ReverseIterator(start, end)
if err != nil {
panic(err)
Expand Down
4 changes: 0 additions & 4 deletions server/mock/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
storetypes "cosmossdk.io/store/types"
)

var _ storetypes.MultiStore = multiStore{}

Check failure on line 15 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / dependency-review

cannot use multiStore{} (value of type multiStore) as "cosmossdk.io/store/types".MultiStore value in variable declaration: multiStore does not implement "cosmossdk.io/store/types".MultiStore (missing method GetObjKVStore)

Check failure on line 15 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / Analyze

cannot use multiStore{} (value of type multiStore) as "cosmossdk.io/store/types".MultiStore value in variable declaration: multiStore does not implement "cosmossdk.io/store/types".MultiStore (missing method GetObjKVStore)

Check failure on line 15 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / Analyze

cannot use multiStore{} (value of type multiStore) as "cosmossdk.io/store/types".MultiStore value in variable declaration: multiStore does not implement "cosmossdk.io/store/types".MultiStore (missing method GetObjKVStore)

type multiStore struct {
kv map[storetypes.StoreKey]kvStore
Expand Down Expand Up @@ -178,10 +178,6 @@
panic("not implemented")
}

func (kv kvStore) CacheWrapWithTrace(w io.Writer, tc storetypes.TraceContext) storetypes.CacheWrap {
panic("not implemented")
}

func (kv kvStore) CacheWrapWithListeners(_ storetypes.StoreKey, _ []storetypes.MemoryListener) storetypes.CacheWrap {
panic("not implemented")
}
Expand Down Expand Up @@ -237,5 +233,5 @@
}

func NewCommitMultiStore() storetypes.CommitMultiStore {
return multiStore{kv: make(map[storetypes.StoreKey]kvStore)}

Check failure on line 236 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / dependency-review

cannot use multiStore{…} (value of type multiStore) as "cosmossdk.io/store/types".CommitMultiStore value in return statement: multiStore does not implement "cosmossdk.io/store/types".CommitMultiStore (missing method GetObjKVStore)

Check failure on line 236 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / Analyze

cannot use multiStore{…} (value of type multiStore) as "cosmossdk.io/store/types".CommitMultiStore value in return statement: multiStore does not implement "cosmossdk.io/store/types".CommitMultiStore (missing method GetObjKVStore) (typecheck)

Check failure on line 236 in server/mock/store.go

View workflow job for this annotation

GitHub Actions / Analyze

cannot use multiStore{…} (value of type multiStore) as "cosmossdk.io/store/types".CommitMultiStore value in return statement: multiStore does not implement "cosmossdk.io/store/types".CommitMultiStore (missing method GetObjKVStore)) (typecheck)
}
1 change: 1 addition & 0 deletions store/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements

* [#207](https://github.com/crypto-org-chain/cosmos-sdk/pull/207) Remove api CacheWrapWithTrace.
* [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Support object store.

## v1.1.0 (March 20, 2024)

Expand Down
43 changes: 23 additions & 20 deletions store/cachekv/internal/mergeiterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,24 @@ import (
// cache shadows (overrides) the parent.
//
// TODO: Optimize by memoizing.
type cacheMergeIterator struct {
parent types.Iterator
cache types.Iterator
type cacheMergeIterator[V any] struct {
parent types.GIterator[V]
cache types.GIterator[V]
ascending bool

valid bool

isZero func(V) bool
}

var _ types.Iterator = (*cacheMergeIterator)(nil)
var _ types.Iterator = (*cacheMergeIterator[[]byte])(nil)

func NewCacheMergeIterator(parent, cache types.Iterator, ascending bool) types.Iterator {
iter := &cacheMergeIterator{
func NewCacheMergeIterator[V any](parent, cache types.GIterator[V], ascending bool, isZero func(V) bool) types.GIterator[V] {
iter := &cacheMergeIterator[V]{
parent: parent,
cache: cache,
ascending: ascending,
isZero: isZero,
}

iter.valid = iter.skipUntilExistsOrInvalid()
Expand All @@ -37,17 +40,17 @@ func NewCacheMergeIterator(parent, cache types.Iterator, ascending bool) types.I

// Domain implements Iterator.
// Returns parent domain because cache and parent domains are the same.
func (iter *cacheMergeIterator) Domain() (start, end []byte) {
func (iter *cacheMergeIterator[V]) Domain() (start, end []byte) {
return iter.parent.Domain()
}

// Valid implements Iterator.
func (iter *cacheMergeIterator) Valid() bool {
func (iter *cacheMergeIterator[V]) Valid() bool {
return iter.valid
}

// Next implements Iterator
func (iter *cacheMergeIterator) Next() {
func (iter *cacheMergeIterator[V]) Next() {
iter.assertValid()

switch {
Expand All @@ -74,7 +77,7 @@ func (iter *cacheMergeIterator) Next() {
}

// Key implements Iterator
func (iter *cacheMergeIterator) Key() []byte {
func (iter *cacheMergeIterator[V]) Key() []byte {
iter.assertValid()

// If parent is invalid, get the cache key.
Expand Down Expand Up @@ -104,7 +107,7 @@ func (iter *cacheMergeIterator) Key() []byte {
}

// Value implements Iterator
func (iter *cacheMergeIterator) Value() []byte {
func (iter *cacheMergeIterator[V]) Value() V {
iter.assertValid()

// If parent is invalid, get the cache value.
Expand Down Expand Up @@ -134,7 +137,7 @@ func (iter *cacheMergeIterator) Value() []byte {
}

// Close implements Iterator
func (iter *cacheMergeIterator) Close() error {
func (iter *cacheMergeIterator[V]) Close() error {
err1 := iter.cache.Close()
if err := iter.parent.Close(); err != nil {
return err
Expand All @@ -145,7 +148,7 @@ func (iter *cacheMergeIterator) Close() error {

// Error returns an error if the cacheMergeIterator is invalid defined by the
// Valid method.
func (iter *cacheMergeIterator) Error() error {
func (iter *cacheMergeIterator[V]) Error() error {
if !iter.Valid() {
return errors.New("invalid cacheMergeIterator")
}
Expand All @@ -155,14 +158,14 @@ func (iter *cacheMergeIterator) Error() error {

// If not valid, panics.
// NOTE: May have side-effect of iterating over cache.
func (iter *cacheMergeIterator) assertValid() {
func (iter *cacheMergeIterator[V]) assertValid() {
if err := iter.Error(); err != nil {
panic(err)
}
}

// Like bytes.Compare but opposite if not ascending.
func (iter *cacheMergeIterator) compare(a, b []byte) int {
func (iter *cacheMergeIterator[V]) compare(a, b []byte) int {
if iter.ascending {
return bytes.Compare(a, b)
}
Expand All @@ -175,9 +178,9 @@ func (iter *cacheMergeIterator) compare(a, b []byte) int {
// If the current cache item is not a delete item, does nothing.
// If `until` is nil, there is no limit, and cache may end up invalid.
// CONTRACT: cache is valid.
func (iter *cacheMergeIterator) skipCacheDeletes(until []byte) {
func (iter *cacheMergeIterator[V]) skipCacheDeletes(until []byte) {
for iter.cache.Valid() &&
iter.cache.Value() == nil &&
iter.isZero(iter.cache.Value()) &&
(until == nil || iter.compare(iter.cache.Key(), until) < 0) {
iter.cache.Next()
}
Expand All @@ -186,7 +189,7 @@ func (iter *cacheMergeIterator) skipCacheDeletes(until []byte) {
// Fast forwards cache (or parent+cache in case of deleted items) until current
// item exists, or until iterator becomes invalid.
// Returns whether the iterator is valid.
func (iter *cacheMergeIterator) skipUntilExistsOrInvalid() bool {
func (iter *cacheMergeIterator[V]) skipUntilExistsOrInvalid() bool {
for {
// If parent is invalid, fast-forward cache.
if !iter.parent.Valid() {
Expand All @@ -211,7 +214,7 @@ func (iter *cacheMergeIterator) skipUntilExistsOrInvalid() bool {
case 0: // parent == cache.
// Skip over if cache item is a delete.
valueC := iter.cache.Value()
if valueC == nil {
if iter.isZero(valueC) {
iter.parent.Next()
iter.cache.Next()

Expand All @@ -223,7 +226,7 @@ func (iter *cacheMergeIterator) skipUntilExistsOrInvalid() bool {
case 1: // cache < parent
// Skip over if cache item is a delete.
valueC := iter.cache.Value()
if valueC == nil {
if iter.isZero(valueC) {
iter.skipCacheDeletes(keyP)
continue
}
Expand Down
12 changes: 6 additions & 6 deletions store/cachekv/search_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"strconv"
"testing"

"cosmossdk.io/store/cachekv/internal"
"cosmossdk.io/store/internal/btree"
)

func BenchmarkLargeUnsortedMisses(b *testing.B) {
Expand All @@ -22,23 +22,23 @@ func BenchmarkLargeUnsortedMisses(b *testing.B) {
}

func generateStore() *Store {
cache := map[string]*cValue{}
cache := map[string]*cValue[[]byte]{}
unsorted := map[string]struct{}{}
for i := 0; i < 5000; i++ {
key := "A" + strconv.Itoa(i)
unsorted[key] = struct{}{}
cache[key] = &cValue{}
cache[key] = &cValue[[]byte]{}
}

for i := 0; i < 5000; i++ {
key := "Z" + strconv.Itoa(i)
unsorted[key] = struct{}{}
cache[key] = &cValue{}
cache[key] = &cValue[[]byte]{}
}

return &Store{
return &GStore[[]byte]{
cache: cache,
unsortedCache: unsorted,
sortedCache: internal.NewBTree(),
sortedCache: btree.NewBTree[[]byte](),
}
}
Loading
Loading