diff --git a/db/kvstorewithbuffer.go b/db/kvstorewithbuffer.go index 2fe33d1b09..ea88b2c337 100644 --- a/db/kvstorewithbuffer.go +++ b/db/kvstorewithbuffer.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/iotexproject/iotex-core/v2/db/batch" + "github.com/iotexproject/iotex-core/v2/pkg/lifecycle" "github.com/iotexproject/iotex-core/v2/pkg/log" ) @@ -23,7 +24,12 @@ type ( // KVStoreWithBuffer defines a KVStore with a buffer, which enables snapshot, revert, // and transaction with multiple writes KVStoreWithBuffer interface { - KVStore + lifecycle.StartStopper + Put(string, []byte, []byte) error + Get(string, []byte) ([]byte, bool, error) + Delete(string, []byte) error + WriteBatch(batch.KVStoreBatch) error + Filter(string, Condition, []byte, []byte) ([][]byte, [][]byte, error) withBuffer } @@ -165,15 +171,18 @@ func (kvb *kvStoreWithBuffer) Size() int { return kvb.buffer.Size() } -func (kvb *kvStoreWithBuffer) Get(ns string, key []byte) ([]byte, error) { +func (kvb *kvStoreWithBuffer) Get(ns string, key []byte) ([]byte, bool, error) { value, err := kvb.buffer.Get(ns, key) + if err == nil { + return value, true, nil + } if errors.Cause(err) == batch.ErrNotExist { value, err = kvb.store.Get(ns, key) } if errors.Cause(err) == batch.ErrAlreadyDeleted { err = errors.Wrapf(ErrNotExist, "failed to get key %x in %s, deleted in buffer level", key, ns) } - return value, err + return value, false, err } func (kvb *kvStoreWithBuffer) Put(ns string, key, value []byte) error { diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 5bd0385281..f0c9aae5bb 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -345,12 +345,16 @@ func (ws *workingSet) State(s interface{}, opts ...protocol.StateOption) (uint64 if cfg.Keys != nil { return 0, errors.Wrap(ErrNotSupported, "Read state with keys option has not been implemented yet") } + value, inCache, err := ws.store.Get(cfg.Namespace, cfg.Key) + if inCache && err == nil { + return ws.height, state.Deserialize(s, value) + } if ws.parent != nil { - if value, err := ws.parent.store.Get(cfg.Namespace, cfg.Key); err == nil { + value, inCache, err = ws.parent.store.Get(cfg.Namespace, cfg.Key) + if inCache && err == nil { return ws.height, state.Deserialize(s, value) } } - value, err := ws.store.Get(cfg.Namespace, cfg.Key) if err != nil { return ws.height, err } diff --git a/state/factory/workingsetstore.go b/state/factory/workingsetstore.go index a6445df079..5756b711dd 100644 --- a/state/factory/workingsetstore.go +++ b/state/factory/workingsetstore.go @@ -10,11 +10,15 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/db" + "github.com/iotexproject/iotex-core/v2/pkg/lifecycle" ) type ( workingSetStore interface { - db.KVStoreBasic + lifecycle.StartStopper + Put(string, []byte, []byte) error + Get(string, []byte) ([]byte, bool, error) + Delete(string, []byte) error Commit() error States(string, [][]byte) ([][]byte, [][]byte, error) Digest() hash.Hash256 diff --git a/state/factory/workingsetstore_statedb.go b/state/factory/workingsetstore_statedb.go index 4f96237204..3f525d6d01 100644 --- a/state/factory/workingsetstore_statedb.go +++ b/state/factory/workingsetstore_statedb.go @@ -39,15 +39,15 @@ func (store *stateDBWorkingSetStore) Stop(context.Context) error { return nil } -func (store *stateDBWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { - data, err := store.flusher.KVStoreWithBuffer().Get(ns, key) +func (store *stateDBWorkingSetStore) Get(ns string, key []byte) ([]byte, bool, error) { + data, inCache, err := store.flusher.KVStoreWithBuffer().Get(ns, key) if err != nil { if errors.Cause(err) == db.ErrNotExist { - return nil, errors.Wrapf(state.ErrStateNotExist, "failed to get state of ns = %x and key = %x", ns, key) + return nil, inCache, errors.Wrapf(state.ErrStateNotExist, "failed to get state of ns = %x and key = %x", ns, key) } - return nil, err + return nil, inCache, err } - return data, nil + return data, inCache, nil } func (store *stateDBWorkingSetStore) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) {