diff --git a/epochStart/bootstrap/disabled/disabledAccountsAdapter.go b/epochStart/bootstrap/disabled/disabledAccountsAdapter.go index ce928b21fca..d6ace804ff9 100644 --- a/epochStart/bootstrap/disabled/disabledAccountsAdapter.go +++ b/epochStart/bootstrap/disabled/disabledAccountsAdapter.go @@ -99,6 +99,10 @@ func (a *accountsAdapter) RecreateTrieIfNeeded(_ common.RootHashHolder) error { func (a *accountsAdapter) CancelPrune(_ []byte, _ state.TriePruningIdentifier) { } +// ResetPruning - +func (a *accountsAdapter) ResetPruning() { +} + // SnapshotState - func (a *accountsAdapter) SnapshotState(_ []byte, _ uint32) { } diff --git a/process/transactionEvaluator/simulationAccountsDB.go b/process/transactionEvaluator/simulationAccountsDB.go index edad278c798..835a64252e5 100644 --- a/process/transactionEvaluator/simulationAccountsDB.go +++ b/process/transactionEvaluator/simulationAccountsDB.go @@ -145,6 +145,10 @@ func (r *simulationAccountsDB) PruneTrie(_ []byte, _ state.TriePruningIdentifier func (r *simulationAccountsDB) CancelPrune(_ []byte, _ state.TriePruningIdentifier) { } +// ResetPruning won't do anything as write operations are disabled on this component +func (r *simulationAccountsDB) ResetPruning() { +} + // SnapshotState won't do anything as write operations are disabled on this component func (r *simulationAccountsDB) SnapshotState(_ []byte, _ uint32) { } diff --git a/state/accountsDB.go b/state/accountsDB.go index b412bac97d6..52dcb16be87 100644 --- a/state/accountsDB.go +++ b/state/accountsDB.go @@ -1230,6 +1230,14 @@ func (adb *AccountsDB) CancelPrune(rootHash []byte, identifier TriePruningIdenti adb.storagePruningManager.CancelPrune(rootHash, identifier, adb.mainTrie.GetStorageManager()) } +// ResetPruning will reset all collected data needed for pruning +func (adb *AccountsDB) ResetPruning() { + adb.mutOp.Lock() + defer adb.mutOp.Unlock() + + adb.storagePruningManager.Reset() +} + // SnapshotState triggers the snapshotting process of the state trie func (adb *AccountsDB) SnapshotState(rootHash []byte, epoch uint32) { adb.snapshotsManger.SnapshotState(rootHash, epoch, adb.getMainTrie().GetStorageManager()) diff --git a/state/accountsDBApi.go b/state/accountsDBApi.go index 76ee0d506d8..915a9e9bea5 100644 --- a/state/accountsDBApi.go +++ b/state/accountsDBApi.go @@ -224,6 +224,10 @@ func (accountsDB *accountsDBApi) PruneTrie(_ []byte, _ TriePruningIdentifier, _ func (accountsDB *accountsDBApi) CancelPrune(_ []byte, _ TriePruningIdentifier) { } +// ResetPruning is a not permitted operation in this implementation and thus, does nothing +func (accountsDB *accountsDBApi) ResetPruning() { +} + // SnapshotState is a not permitted operation in this implementation and thus, does nothing func (accountsDB *accountsDBApi) SnapshotState(_ []byte, _ uint32) { } diff --git a/state/accountsDBApiWithHistory.go b/state/accountsDBApiWithHistory.go index e39a24ea7c7..048fbd44bbe 100644 --- a/state/accountsDBApiWithHistory.go +++ b/state/accountsDBApiWithHistory.go @@ -112,6 +112,10 @@ func (accountsDB *accountsDBApiWithHistory) PruneTrie(_ []byte, _ TriePruningIde func (accountsDB *accountsDBApiWithHistory) CancelPrune(_ []byte, _ TriePruningIdentifier) { } +// ResetPruning is a not permitted operation in this implementation and thus, does nothing +func (accountsDB *accountsDBApiWithHistory) ResetPruning() { +} + // SnapshotState is a not permitted operation in this implementation and thus, does nothing func (accountsDB *accountsDBApiWithHistory) SnapshotState(_ []byte, _ uint32) { } diff --git a/state/interface.go b/state/interface.go index 2e9893f1cc6..254c68ddd44 100644 --- a/state/interface.go +++ b/state/interface.go @@ -84,6 +84,7 @@ type AccountsAdapter interface { RecreateTrieIfNeeded(options common.RootHashHolder) error PruneTrie(rootHash []byte, identifier TriePruningIdentifier, handler PruningHandler) CancelPrune(rootHash []byte, identifier TriePruningIdentifier) + ResetPruning() SnapshotState(rootHash []byte, epoch uint32) IsPruningEnabled() bool GetAllLeaves(leavesChannels *common.TrieIteratorChannels, ctx context.Context, rootHash []byte, trieLeafParser common.TrieLeafParser) error @@ -178,6 +179,7 @@ type DBRemoveCacher interface { Put([]byte, common.ModifiedHashes) error Evict([]byte) (common.ModifiedHashes, error) ShouldKeepHash(hash string, identifier TriePruningIdentifier) (bool, error) + Reset() IsInterfaceNil() bool Close() error } @@ -194,6 +196,7 @@ type StoragePruningManager interface { MarkForEviction([]byte, []byte, common.ModifiedHashes, common.ModifiedHashes) error PruneTrie(rootHash []byte, identifier TriePruningIdentifier, tsm common.StorageManager, handler PruningHandler) CancelPrune(rootHash []byte, identifier TriePruningIdentifier, tsm common.StorageManager) + Reset() Close() error IsInterfaceNil() bool } diff --git a/state/storagePruningManager/disabled/disabledStoragePruningManager.go b/state/storagePruningManager/disabled/disabledStoragePruningManager.go index 6de7e2b0845..2e10c84a7f3 100644 --- a/state/storagePruningManager/disabled/disabledStoragePruningManager.go +++ b/state/storagePruningManager/disabled/disabledStoragePruningManager.go @@ -26,6 +26,9 @@ func (i *disabledStoragePruningManager) PruneTrie(_ []byte, _ state.TriePruningI func (i *disabledStoragePruningManager) CancelPrune(_ []byte, _ state.TriePruningIdentifier, _ common.StorageManager) { } +// Reset does nothing for this implementation +func (i *disabledStoragePruningManager) Reset() {} + // Close does nothing for this implementation func (i *disabledStoragePruningManager) Close() error { return nil diff --git a/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList.go b/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList.go index 52aa401c5ba..df91bfcc525 100644 --- a/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList.go +++ b/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList.go @@ -205,6 +205,19 @@ func (mewl *memoryEvictionWaitingList) ShouldKeepHash(hash string, identifier st return false, nil } +// Reset will reinitialize the eviction waiting list, by emptying the cache and reversed cache. It will not change the sizes of the caches. +func (mewl *memoryEvictionWaitingList) Reset() { + mewl.opMutex.Lock() + + for key := range mewl.cache { + log.Debug("trie nodes eviction waiting list reset", "rootHash", []byte(key)) + } + + mewl.cache = make(map[string]*rootHashData) + mewl.reversedCache = make(map[string]*hashInfo) + mewl.opMutex.Unlock() +} + // Close returns nil func (mewl *memoryEvictionWaitingList) Close() error { return nil diff --git a/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList_test.go b/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList_test.go index 21099502f93..69ef10606d3 100644 --- a/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList_test.go +++ b/state/storagePruningManager/evictionWaitingList/memoryEvictionWaitingList_test.go @@ -359,3 +359,18 @@ func TestMemoryEvictionWaitingList_RemoveFromInversedCache(t *testing.T) { assert.Nil(t, info) assert.False(t, exists) } + +func TestMemoryEvictionWaitingList_Reset(t *testing.T) { + t.Parallel() + + mewl, _ := NewMemoryEvictionWaitingList(getDefaultArgsForMemoryEvictionWaitingList()) + + _ = mewl.Put([]byte("root1"), common.ModifiedHashes{"hash1": {}, "hash2": {}}) + _ = mewl.Put([]byte("root2"), common.ModifiedHashes{"hash3": {}, "hash4": {}}) + + assert.Equal(t, 2, len(mewl.cache)) + assert.Equal(t, 4, len(mewl.reversedCache)) + mewl.Reset() + assert.Equal(t, 0, len(mewl.cache)) + assert.Equal(t, 0, len(mewl.reversedCache)) +} diff --git a/state/storagePruningManager/storagePruningManager.go b/state/storagePruningManager/storagePruningManager.go index 757d04cc9ed..2478316a02a 100644 --- a/state/storagePruningManager/storagePruningManager.go +++ b/state/storagePruningManager/storagePruningManager.go @@ -234,6 +234,14 @@ func (spm *storagePruningManager) removeFromDb( return nil } +func (spm *storagePruningManager) Reset() { + bufferedHashes := spm.pruningBuffer.RemoveAll() + for _, hash := range bufferedHashes { + log.Trace("trie storage manager reset", "hash", hash) + } + spm.dbEvictionWaitingList.Reset() +} + // Close will handle the closing of the underlying components func (spm *storagePruningManager) Close() error { return spm.dbEvictionWaitingList.Close() diff --git a/state/storagePruningManager/storagePruningManager_test.go b/state/storagePruningManager/storagePruningManager_test.go index 006a88e4d70..2f656e6b556 100644 --- a/state/storagePruningManager/storagePruningManager_test.go +++ b/state/storagePruningManager/storagePruningManager_test.go @@ -260,3 +260,37 @@ func TestStoragePruningManager_MarkForEviction_removeDuplicatedKeys(t *testing.T _, ok = map2["hash4"] assert.False(t, ok) } + +func TestStoragePruningManager_Reset(t *testing.T) { + t.Parallel() + + args := storage.GetStorageManagerArgs() + trieStorage, _ := trie.NewTrieStorageManager(args) + ewlArgs := evictionWaitingList.MemoryEvictionWaitingListArgs{ + RootHashesSize: 100, + HashesSize: 10000, + } + ewl, _ := evictionWaitingList.NewMemoryEvictionWaitingList(ewlArgs) + spm, _ := NewStoragePruningManager(ewl, 1000) + + err := spm.MarkForEviction([]byte("rootHash"), []byte("newRootHash"), map[string]struct{}{"hash1": {}, "hash2": {}}, map[string]struct{}{"hash3": {}, "hash4": {}}) + assert.Nil(t, err) + err = spm.markForEviction([]byte("rootHash2"), map[string]struct{}{"hash5": {}, "hash6": {}}, state.NewRoot) + assert.Nil(t, err) + + trieStorage.EnterPruningBufferingMode() + spm.PruneTrie([]byte("rootHash"), state.OldRoot, trieStorage, state.NewPruningHandler(state.EnableDataRemoval)) + spm.CancelPrune([]byte("newRootHash"), state.NewRoot, trieStorage) + trieStorage.ExitPruningBufferingMode() + + assert.Equal(t, 2, spm.pruningBuffer.Len()) + + spm.Reset() + assert.Equal(t, 0, spm.pruningBuffer.Len()) + + // rootHash2 should not be added to the pruning buffer because ewl was also reset when spm.Reset() was called + trieStorage.EnterPruningBufferingMode() + spm.PruneTrie([]byte("rootHash2"), state.NewRoot, trieStorage, state.NewPruningHandler(state.EnableDataRemoval)) + trieStorage.ExitPruningBufferingMode() + assert.Equal(t, 0, spm.pruningBuffer.Len()) +} diff --git a/testscommon/state/accountsAdapterStub.go b/testscommon/state/accountsAdapterStub.go index aa3d41e1355..04608b50045 100644 --- a/testscommon/state/accountsAdapterStub.go +++ b/testscommon/state/accountsAdapterStub.go @@ -29,6 +29,7 @@ type AccountsStub struct { RecreateTrieIfNeededCalled func(options common.RootHashHolder) error PruneTrieCalled func(rootHash []byte, identifier state.TriePruningIdentifier, handler state.PruningHandler) CancelPruneCalled func(rootHash []byte, identifier state.TriePruningIdentifier) + ResetPruningCalled func() SnapshotStateCalled func(rootHash []byte, epoch uint32) IsPruningEnabledCalled func() bool GetAllLeavesCalled func(leavesChannels *common.TrieIteratorChannels, ctx context.Context, rootHash []byte, trieLeafParser common.TrieLeafParser) error @@ -208,6 +209,13 @@ func (as *AccountsStub) CancelPrune(rootHash []byte, identifier state.TriePrunin } } +// ResetPruning - +func (as *AccountsStub) ResetPruning() { + if as.ResetPruningCalled != nil { + as.ResetPruningCalled() + } +} + // SnapshotState - func (as *AccountsStub) SnapshotState(rootHash []byte, epoch uint32) { if as.SnapshotStateCalled != nil { diff --git a/testscommon/state/evictionWaitingListMock.go b/testscommon/state/evictionWaitingListMock.go index c071440d7b1..84d0e31e9e7 100644 --- a/testscommon/state/evictionWaitingListMock.go +++ b/testscommon/state/evictionWaitingListMock.go @@ -81,6 +81,13 @@ func (ewl *EvictionWaitingListMock) ShouldKeepHash(hash string, identifier state return false, nil } +// Reset will reinitialize the cache +func (ewl *EvictionWaitingListMock) Reset() { + ewl.OpMutex.Lock() + ewl.Cache = make(map[string]common.ModifiedHashes) + ewl.OpMutex.Unlock() +} + // Close - func (ewl *EvictionWaitingListMock) Close() error { return nil diff --git a/testscommon/state/storagePruningManagerStub.go b/testscommon/state/storagePruningManagerStub.go index 92c697c5224..5b91046909c 100644 --- a/testscommon/state/storagePruningManagerStub.go +++ b/testscommon/state/storagePruningManagerStub.go @@ -10,6 +10,7 @@ type StoragePruningManagerStub struct { MarkForEvictionCalled func(bytes []byte, bytes2 []byte, hashes common.ModifiedHashes, hashes2 common.ModifiedHashes) error PruneTrieCalled func(rootHash []byte, identifier state.TriePruningIdentifier, tsm common.StorageManager, handler state.PruningHandler) CancelPruneCalled func(rootHash []byte, identifier state.TriePruningIdentifier, tsm common.StorageManager) + ResetCalled func() CloseCalled func() error } @@ -36,6 +37,13 @@ func (stub *StoragePruningManagerStub) CancelPrune(rootHash []byte, identifier s } } +// Reset - +func (stub *StoragePruningManagerStub) Reset() { + if stub.ResetCalled != nil { + stub.ResetCalled() + } +} + // Close - func (stub *StoragePruningManagerStub) Close() error { if stub.CloseCalled != nil {