From 1fc9a35a695a134ef2c057d35826405d0671f49a Mon Sep 17 00:00:00 2001 From: codchen Date: Tue, 19 Mar 2024 17:42:21 +0800 Subject: [PATCH] Fix DeleteAll --- server/mock/store.go | 4 ++++ store/cachekv/store.go | 32 ++++++++++++++++++++++---------- store/cachekv/store_test.go | 5 ++++- store/dbadapter/store.go | 9 +++++++++ store/gaskv/store.go | 4 ++++ store/iavl/store.go | 9 +++++++++ store/listenkv/store.go | 4 ++++ store/multiversion/mvkv.go | 23 ++++++++++++++++++++++- store/prefix/store.go | 12 ++++++++++++ store/tracekv/store.go | 4 ++++ store/types/store.go | 2 ++ storev2/commitment/store.go | 9 +++++++++ storev2/state/store.go | 9 +++++++++ 13 files changed, 114 insertions(+), 12 deletions(-) diff --git a/server/mock/store.go b/server/mock/store.go index 6096f35d4..be3523caa 100644 --- a/server/mock/store.go +++ b/server/mock/store.go @@ -234,6 +234,10 @@ func (kv kvStore) DeleteAll(start, end []byte) error { panic("not implemented") } +func (kv kvStore) GetAllKeyStrsInRange(start, end []byte) []string { + panic("not implemented") +} + func NewCommitMultiStore() sdk.CommitMultiStore { return multiStore{kv: make(map[sdk.StoreKey]kvStore)} } diff --git a/store/cachekv/store.go b/store/cachekv/store.go index a33adf17c..01ebf2f69 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -369,16 +369,28 @@ func (store *Store) GetParent() types.KVStore { } func (store *Store) DeleteAll(start, end []byte) error { - store.dirtyItems(start, end) - // memdb iterator - cachedIter, err := store.sortedCache.Iterator(start, end) - if err != nil { - return err - } - defer cachedIter.Close() - for ; cachedIter.Valid(); cachedIter.Next() { - // `Delete` would not touch sortedCache so it's okay to perform inside iterator - store.Delete(cachedIter.Key()) + for _, k := range store.GetAllKeyStrsInRange(start, end) { + store.Delete([]byte(k)) } return nil } + +func (store *Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + keyStrs := map[string]struct{}{} + for _, pk := range store.parent.GetAllKeyStrsInRange(start, end) { + keyStrs[pk] = struct{}{} + } + store.cache.Range(func(key, value any) bool { + cv := value.(*types.CValue) + if cv.Value() == nil { + delete(keyStrs, key.(string)) + } else { + keyStrs[key.(string)] = struct{}{} + } + return true + }) + for k := range keyStrs { + res = append(res, k) + } + return res +} diff --git a/store/cachekv/store_test.go b/store/cachekv/store_test.go index c6e7ab5b6..a3a40664f 100644 --- a/store/cachekv/store_test.go +++ b/store/cachekv/store_test.go @@ -67,14 +67,17 @@ func TestCacheKVStore(t *testing.T) { require.NotNil(t, st.GetParent()) // DeleteAll deletes all entries in cache but not affect mem - st = cachekv.NewStore(mem, types.NewKVStoreKey("CacheKvTest"), types.DefaultCacheSizeLimit) mem.Set(keyFmt(1), valFmt(1)) + mem.Set(keyFmt(3), valFmt(4)) + st = cachekv.NewStore(mem, types.NewKVStoreKey("CacheKvTest"), types.DefaultCacheSizeLimit) st.Set(keyFmt(1), valFmt(2)) st.Set(keyFmt(2), valFmt(3)) require.Nil(t, st.DeleteAll(nil, nil)) require.Nil(t, st.Get(keyFmt(1))) require.Nil(t, st.Get(keyFmt(2))) + require.Nil(t, st.Get(keyFmt(3))) require.Equal(t, valFmt(1), mem.Get(keyFmt(1))) + require.Equal(t, valFmt(4), mem.Get(keyFmt(3))) } func TestCacheKVStoreNoNilSet(t *testing.T) { diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index b8de090f1..53aa80e88 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -112,5 +112,14 @@ func (dsa Store) DeleteAll(start, end []byte) error { return nil } +func (dsa Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + iter := dsa.Iterator(start, end) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + res = append(res, string(iter.Key())) + } + return +} + // dbm.DB implements KVStore so we can CacheKVStore it. var _ types.KVStore = Store{} diff --git a/store/gaskv/store.go b/store/gaskv/store.go index 62e3d89c4..2b52d2cc3 100644 --- a/store/gaskv/store.go +++ b/store/gaskv/store.go @@ -134,6 +134,10 @@ func (gs *Store) DeleteAll(start, end []byte) error { return gs.parent.DeleteAll(start, end) } +func (gs *Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + return gs.parent.GetAllKeyStrsInRange(start, end) +} + type gasIterator struct { gasMeter types.GasMeter gasConfig types.GasConfig diff --git a/store/iavl/store.go b/store/iavl/store.go index 2d5bfad88..ca2c73977 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -436,6 +436,15 @@ func (st *Store) DeleteAll(start, end []byte) error { return nil } +func (st *Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + iter := st.Iterator(start, end) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + res = append(res, string(iter.Key())) + } + return +} + // Takes a MutableTree, a key, and a flag for creating existence or absence proof and returns the // appropriate merkle.Proof. Since this must be called after querying for the value, this function should never error // Thus, it will panic on error rather than returning it diff --git a/store/listenkv/store.go b/store/listenkv/store.go index 20f103ec0..725e7f6ca 100644 --- a/store/listenkv/store.go +++ b/store/listenkv/store.go @@ -165,3 +165,7 @@ func (s *Store) onWrite(delete bool, key, value []byte) { func (s *Store) DeleteAll(start, end []byte) error { return s.parent.DeleteAll(start, end) } + +func (s *Store) GetAllKeyStrsInRange(start, end []byte) []string { + return s.parent.GetAllKeyStrsInRange(start, end) +} diff --git a/store/multiversion/mvkv.go b/store/multiversion/mvkv.go index 14f4be5a0..8540efddc 100644 --- a/store/multiversion/mvkv.go +++ b/store/multiversion/mvkv.go @@ -316,7 +316,28 @@ func (v *VersionIndexedStore) VersionExists(version int64) bool { } func (v *VersionIndexedStore) DeleteAll(start, end []byte) error { - return v.parent.DeleteAll(start, end) + for _, k := range v.GetAllKeyStrsInRange(start, end) { + v.Delete([]byte(k)) + } + return nil +} + +func (v *VersionIndexedStore) GetAllKeyStrsInRange(start, end []byte) (res []string) { + keyStrs := map[string]struct{}{} + for _, pk := range v.parent.GetAllKeyStrsInRange(start, end) { + keyStrs[pk] = struct{}{} + } + for k, val := range v.writeset { + if val == nil { + delete(keyStrs, string(k)) + } else { + keyStrs[string(k)] = struct{}{} + } + } + for k := range keyStrs { + res = append(res, k) + } + return res } // GetStoreType implements types.KVStore. diff --git a/store/prefix/store.go b/store/prefix/store.go index fd1f2672b..2bdceaf4f 100644 --- a/store/prefix/store.go +++ b/store/prefix/store.go @@ -102,6 +102,18 @@ func (s Store) DeleteAll(start, end []byte) error { return s.parent.DeleteAll(newstart, newend) } +func (s Store) GetAllKeyStrsInRange(start, end []byte) []string { + newstart := cloneAppend(s.prefix, start) + + var newend []byte + if end == nil { + newend = cpIncr(s.prefix) + } else { + newend = cloneAppend(s.prefix, end) + } + return s.parent.GetAllKeyStrsInRange(newstart, newend) +} + // Implements KVStore // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 func (s Store) Iterator(start, end []byte) types.Iterator { diff --git a/store/tracekv/store.go b/store/tracekv/store.go index 81fe2034c..50bac5024 100644 --- a/store/tracekv/store.go +++ b/store/tracekv/store.go @@ -190,6 +190,10 @@ func (tkv *Store) DeleteAll(start, end []byte) error { return tkv.parent.DeleteAll(start, end) } +func (tkv *Store) GetAllKeyStrsInRange(start, end []byte) []string { + return tkv.parent.GetAllKeyStrsInRange(start, end) +} + // writeOperation writes a KVStore operation to the underlying io.Writer as // JSON-encoded data where the key/value pair is base64 encoded. func writeOperation(w io.Writer, op operation, tc types.TraceContext, key, value []byte) { diff --git a/store/types/store.go b/store/types/store.go index e1f4b0a97..b66e4a53b 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -257,6 +257,8 @@ type KVStore interface { VersionExists(version int64) bool DeleteAll(start, end []byte) error + + GetAllKeyStrsInRange(start, end []byte) []string } // Iterator is an alias db's Iterator for convenience. diff --git a/storev2/commitment/store.go b/storev2/commitment/store.go index f48362873..60dcefe0a 100644 --- a/storev2/commitment/store.go +++ b/storev2/commitment/store.go @@ -195,3 +195,12 @@ func (st *Store) DeleteAll(start, end []byte) error { } return nil } + +func (st *Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + iter := st.Iterator(start, end) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + res = append(res, string(iter.Key())) + } + return +} diff --git a/storev2/state/store.go b/storev2/state/store.go index b9c9c7599..e38b9a485 100644 --- a/storev2/state/store.go +++ b/storev2/state/store.go @@ -147,3 +147,12 @@ func (st *Store) DeleteAll(start, end []byte) error { } return nil } + +func (st *Store) GetAllKeyStrsInRange(start, end []byte) (res []string) { + iter := st.Iterator(start, end) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + res = append(res, string(iter.Key())) + } + return +}