-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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(store/v1): async pruning iavl #20321
Changes from 1 commit
0b3814f
612c14d
977080c
1c74b2e
80ded44
21f0d35
cd502be
63d0dec
960b89b
c285a8d
ca0e980
7c89f7c
b435387
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 |
---|---|---|
|
@@ -52,7 +52,7 @@ func LoadStore(db dbm.DB, logger log.Logger, key types.StoreKey, id types.Commit | |
// provided DB. An error is returned if the version fails to load, or if called with a positive | ||
// version on an empty tree. | ||
func LoadStoreWithInitialVersion(db dbm.DB, logger log.Logger, key types.StoreKey, id types.CommitID, initialVersion uint64, cacheSize int, disableFastNode bool, metrics metrics.StoreMetrics) (types.CommitKVStore, error) { | ||
tree := iavl.NewMutableTree(wrapper.NewDBWrapper(db), cacheSize, disableFastNode, logger, iavl.InitialVersionOption(initialVersion)) | ||
tree := iavl.NewMutableTree(wrapper.NewDBWrapper(db), cacheSize, disableFastNode, logger, iavl.InitialVersionOption(initialVersion), iavl.AsyncPruningOption(true)) | ||
|
||
isUpgradeable, err := tree.IsUpgradeable() | ||
if err != nil { | ||
|
@@ -147,6 +147,15 @@ func (st *Store) LastCommitID() types.CommitID { | |
} | ||
} | ||
|
||
// SetCommitting implements CommitKVStore interface. | ||
func (st *Store) SetCommitting(isCommit bool) { | ||
if isCommit { | ||
st.tree.SetCommitting() | ||
} else { | ||
st.tree.UnsetCommitting() | ||
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 looked into the iavl impl and this method is not safe to be called (multiple times) without a 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 was also thinking if we need to provide better locking so that no other process accidentally unlocks? Do you think such a scenario exists? In this case, control must be within the iavl and you can have a 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 believe those should be handled within |
||
} | ||
} | ||
|
||
// SetPruning panics as pruning options should be provided at initialization | ||
// since IAVl accepts pruning options directly. | ||
func (st *Store) SetPruning(_ pruningtypes.PruningOptions) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ type ( | |
Get(key []byte) ([]byte, error) | ||
Set(key, value []byte) (bool, error) | ||
Remove(key []byte) ([]byte, bool, error) | ||
SetCommitting() | ||
UnsetCommitting() | ||
SaveVersion() ([]byte, int64, error) | ||
Comment on lines
+25
to
27
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. do we need to break this interface? 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. yes, this is the interface of |
||
Version() int64 | ||
Hash() []byte | ||
|
@@ -53,6 +55,14 @@ func (it *immutableTree) Remove(_ []byte) ([]byte, bool, error) { | |
panic("cannot call 'Remove' on an immutable IAVL tree") | ||
} | ||
|
||
func (it *immutableTree) SetCommitting() { | ||
panic("cannot call 'SetCommitting' on an immutable IAVL tree") | ||
} | ||
|
||
func (it *immutableTree) UnsetCommitting() { | ||
panic("cannot call 'UnsetCommitting' on an immutable IAVL tree") | ||
} | ||
|
||
func (it *immutableTree) SaveVersion() ([]byte, int64, error) { | ||
panic("cannot call 'SaveVersion' on an immutable IAVL tree") | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -531,6 +531,10 @@ func TestMultiStore_Pruning(t *testing.T) { | |
ms.Commit() | ||
} | ||
|
||
// Ensure async pruning is done | ||
time.Sleep(500 * time.Millisecond) | ||
ms.Commit() | ||
|
||
for _, v := range tc.saved { | ||
_, err := ms.CacheMultiStoreWithVersion(v) | ||
require.NoError(t, err, "expected no error when loading height: %d", v) | ||
|
@@ -563,16 +567,6 @@ func TestMultiStore_Pruning_SameHeightsTwice(t *testing.T) { | |
|
||
require.Equal(t, numVersions, lastCommitInfo.Version) | ||
|
||
for v := int64(1); v < numVersions-int64(keepRecent); v++ { | ||
err := ms.LoadVersion(v) | ||
require.Error(t, err, "expected error when loading pruned height: %d", v) | ||
} | ||
|
||
for v := (numVersions - int64(keepRecent)); v < numVersions; v++ { | ||
err := ms.LoadVersion(v) | ||
require.NoError(t, err, "expected no error when loading height: %d", v) | ||
} | ||
|
||
// Get latest | ||
err := ms.LoadVersion(numVersions - 1) | ||
require.NoError(t, err) | ||
|
@@ -585,8 +579,20 @@ func TestMultiStore_Pruning_SameHeightsTwice(t *testing.T) { | |
require.Equal(t, numVersions, lastCommitInfo.Version) | ||
|
||
// Ensure that can commit one more height with no panic | ||
// and the async pruning is done | ||
time.Sleep(500 * time.Millisecond) | ||
cool-develope marked this conversation as resolved.
Show resolved
Hide resolved
|
||
lastCommitInfo = ms.Commit() | ||
require.Equal(t, numVersions+1, lastCommitInfo.Version) | ||
|
||
for v := int64(1); v < numVersions-int64(keepRecent); v++ { | ||
err := ms.LoadVersion(v) | ||
require.Error(t, err, "expected error when loading pruned height: %d", v) | ||
} | ||
|
||
for v := (numVersions - int64(keepRecent)); v < numVersions; v++ { | ||
err := ms.LoadVersion(v) | ||
require.NoError(t, err, "expected no error when loading height: %d", v) | ||
} | ||
} | ||
|
||
func TestMultiStore_PruningRestart(t *testing.T) { | ||
|
@@ -617,6 +623,10 @@ func TestMultiStore_PruningRestart(t *testing.T) { | |
actualHeightToPrune = ms.pruningManager.GetPruningHeight(ms.LatestVersion()) | ||
require.Equal(t, int64(8), actualHeightToPrune) | ||
|
||
// Ensure async pruning is done | ||
time.Sleep(500 * time.Millisecond) | ||
cool-develope marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ms.Commit() | ||
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. nit: do you need this extra commit? It is passing without 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. yes, to flush the batch data which includes pruning info |
||
|
||
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. Tests are passing without 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.
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. It is not straight forward but you can ensure the pauses calls with some decorator: var _ types.PausablePruner = &pauseableCommitKVStoreStub{}
type pauseableCommitKVStoreStub struct {
types.CommitKVStore
pauseCalled []bool
}
func (p *pauseableCommitKVStoreStub) PausePruning(b bool) {
p.pauseCalled = append(p.pauseCalled, b)
}
func TestPausePruningOnCommit(t *testing.T) {
store := NewStore(dbm.NewMemDB(), log.NewNopLogger(), metrics.NewNoOpMetrics())
store.SetPruning(pruningtypes.NewCustomPruningOptions(2, 11))
store.MountStoreWithDB(testStoreKey1, types.StoreTypeIAVL, nil)
require.NoError(t, store.LoadLatestVersion())
myStub := &pauseableCommitKVStoreStub{CommitKVStore: store.stores[testStoreKey1]}
store.stores[testStoreKey1] = myStub
// when
store.Commit()
// then
assert.Equal(t, []bool{true, false}, myStub.pauseCalled)
} |
||
for v := int64(1); v <= actualHeightToPrune; v++ { | ||
_, err := ms.CacheMultiStoreWithVersion(v) | ||
require.Error(t, err, "expected error when loading height: %d", v) | ||
|
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.
Tip
Codebase Verification
Ensure consistent handling of the new pruning options.
The new pruning option
iavl.AsyncPruningOption
is only applied in one instance ofiavl.NewMutableTree
instore/iavl/store.go
. Other instances ofiavl.NewMutableTree
do not include this option, which may lead to inconsistent behavior.store/v2/commitment/iavl/tree.go
store/prefix/store_test.go
store/iavl/store_test.go
store/cache/cache_test.go
Please review these instances to ensure the new pruning option is correctly and consistently applied.
Analysis chain
Ensure proper handling of new pruning options.
Scripts Executed
The following scripts were executed for the analysis:
Script:
Length of output: 223
Script:
Length of output: 2000