-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
R4R: Store Refactor 1 #2985
R4R: Store Refactor 1 #2985
Changes from 20 commits
a669428
83dac5d
fe1209a
c40055e
ff0e9dc
b08044a
26e05ae
324a849
9d806d6
cb8006b
9876e30
676e837
ab8143e
86b19d4
2c316e3
43ab0c3
30a4a58
4eda02b
04631ad
2429ef4
cad00ca
a1aaba3
d2e8044
fe063b3
20e02f7
67c5541
11c202a
1e68319
e1f3fec
9b16f2f
13470c3
997d88d
af69aeb
7cd7880
ab82454
ae9eeb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package store | ||
package cachekv | ||
|
||
import ( | ||
"bytes" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package store | ||
package cachekv | ||
|
||
import ( | ||
"bytes" | ||
|
@@ -8,6 +8,10 @@ import ( | |
|
||
cmn "github.com/tendermint/tendermint/libs/common" | ||
dbm "github.com/tendermint/tendermint/libs/db" | ||
|
||
"github.com/cosmos/cosmos-sdk/store/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/store/tracekv" | ||
) | ||
|
||
// If value is nil but deleted is false, it means the parent doesn't have the | ||
|
@@ -18,30 +22,30 @@ type cValue struct { | |
dirty bool | ||
} | ||
|
||
// cacheKVStore wraps an in-memory cache around an underlying KVStore. | ||
type cacheKVStore struct { | ||
// Store wraps an in-memory cache around an underlying types.KVStore. | ||
type Store struct { | ||
mtx sync.Mutex | ||
cache map[string]cValue | ||
parent KVStore | ||
parent types.KVStore | ||
} | ||
|
||
var _ CacheKVStore = (*cacheKVStore)(nil) | ||
var _ types.CacheKVStore = (*Store)(nil) | ||
|
||
// nolint | ||
func NewCacheKVStore(parent KVStore) *cacheKVStore { | ||
return &cacheKVStore{ | ||
func NewStore(parent types.KVStore) *Store { | ||
return &Store{ | ||
cache: make(map[string]cValue), | ||
parent: parent, | ||
} | ||
} | ||
|
||
// Implements Store. | ||
func (ci *cacheKVStore) GetStoreType() StoreType { | ||
func (ci *Store) GetStoreType() types.StoreType { | ||
mossid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return ci.parent.GetStoreType() | ||
} | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) Get(key []byte) (value []byte) { | ||
// Implements types.KVStore. | ||
func (ci *Store) Get(key []byte) (value []byte) { | ||
ci.mtx.Lock() | ||
defer ci.mtx.Unlock() | ||
ci.assertValidKey(key) | ||
|
@@ -57,8 +61,8 @@ func (ci *cacheKVStore) Get(key []byte) (value []byte) { | |
return value | ||
} | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) Set(key []byte, value []byte) { | ||
// Implements types.KVStore. | ||
func (ci *Store) Set(key []byte, value []byte) { | ||
ci.mtx.Lock() | ||
defer ci.mtx.Unlock() | ||
ci.assertValidKey(key) | ||
|
@@ -67,33 +71,23 @@ func (ci *cacheKVStore) Set(key []byte, value []byte) { | |
ci.setCacheValue(key, value, false, true) | ||
} | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) Has(key []byte) bool { | ||
// Implements types.KVStore. | ||
func (ci *Store) Has(key []byte) bool { | ||
value := ci.Get(key) | ||
return value != nil | ||
} | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) Delete(key []byte) { | ||
// Implements types.KVStore. | ||
func (ci *Store) Delete(key []byte) { | ||
ci.mtx.Lock() | ||
defer ci.mtx.Unlock() | ||
ci.assertValidKey(key) | ||
|
||
ci.setCacheValue(key, nil, true, true) | ||
} | ||
|
||
// Implements KVStore | ||
func (ci *cacheKVStore) Prefix(prefix []byte) KVStore { | ||
return prefixStore{ci, prefix} | ||
} | ||
|
||
// Implements KVStore | ||
func (ci *cacheKVStore) Gas(meter GasMeter, config GasConfig) KVStore { | ||
return NewGasKVStore(meter, config, ci) | ||
} | ||
|
||
// Implements CacheKVStore. | ||
func (ci *cacheKVStore) Write() { | ||
// Implements Cachetypes.KVStore. | ||
func (ci *Store) Write() { | ||
ci.mtx.Lock() | ||
defer ci.mtx.Unlock() | ||
|
||
|
@@ -126,33 +120,33 @@ func (ci *cacheKVStore) Write() { | |
} | ||
|
||
//---------------------------------------- | ||
// To cache-wrap this cacheKVStore further. | ||
// To cache-wrap this Store further. | ||
|
||
// Implements CacheWrapper. | ||
func (ci *cacheKVStore) CacheWrap() CacheWrap { | ||
return NewCacheKVStore(ci) | ||
func (ci *Store) CacheWrap() types.CacheWrap { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make sense to cache-wrap an already cached store? I recall there are places where we do this, but it leads to difficult debugging. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we will need multiple layers of cache wrapping in some cases(one of the examples is https://github.com/cosmos/cosmos-sdk/blob/develop/types/context.go#L235), although I'm not advocating it hard. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's OK, but SDK applications should be careful about repeatedly cache-wrapping. |
||
return NewStore(ci) | ||
} | ||
|
||
// CacheWrapWithTrace implements the CacheWrapper interface. | ||
func (ci *cacheKVStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap { | ||
return NewCacheKVStore(NewTraceKVStore(ci, w, tc)) | ||
func (ci *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above. |
||
return NewStore(tracekv.NewStore(ci, w, tc)) | ||
} | ||
|
||
//---------------------------------------- | ||
// Iteration | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) Iterator(start, end []byte) Iterator { | ||
// Implements types.KVStore. | ||
func (ci *Store) Iterator(start, end []byte) types.Iterator { | ||
return ci.iterator(start, end, true) | ||
} | ||
|
||
// Implements KVStore. | ||
func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator { | ||
// Implements types.KVStore. | ||
func (ci *Store) ReverseIterator(start, end []byte) types.Iterator { | ||
return ci.iterator(start, end, false) | ||
} | ||
|
||
func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { | ||
var parent, cache Iterator | ||
func (ci *Store) iterator(start, end []byte, ascending bool) types.Iterator { | ||
var parent, cache types.Iterator | ||
|
||
if ascending { | ||
parent = ci.parent.Iterator(start, end) | ||
|
@@ -167,7 +161,7 @@ func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { | |
} | ||
|
||
// Constructs a slice of dirty items, to use w/ memIterator. | ||
func (ci *cacheKVStore) dirtyItems(start, end []byte, ascending bool) []cmn.KVPair { | ||
func (ci *Store) dirtyItems(start, end []byte, ascending bool) []cmn.KVPair { | ||
items := make([]cmn.KVPair, 0) | ||
|
||
for key, cacheValue := range ci.cache { | ||
|
@@ -192,20 +186,20 @@ func (ci *cacheKVStore) dirtyItems(start, end []byte, ascending bool) []cmn.KVPa | |
//---------------------------------------- | ||
// etc | ||
|
||
func (ci *cacheKVStore) assertValidKey(key []byte) { | ||
func (ci *Store) assertValidKey(key []byte) { | ||
if key == nil { | ||
panic("key is nil") | ||
} | ||
} | ||
|
||
func (ci *cacheKVStore) assertValidValue(value []byte) { | ||
func (ci *Store) assertValidValue(value []byte) { | ||
if value == nil { | ||
panic("value is nil") | ||
} | ||
} | ||
|
||
// Only entrypoint to mutate ci.cache. | ||
func (ci *cacheKVStore) setCacheValue(key, value []byte, deleted bool, dirty bool) { | ||
func (ci *Store) setCacheValue(key, value []byte, deleted bool, dirty bool) { | ||
ci.cache[string(key)] = cValue{ | ||
value: value, | ||
deleted: deleted, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we need to set the context to
nil
if we set it tosdk.TraceContext
the next line?