Skip to content

Commit 6ac9264

Browse files
authored
[factory] refactore workingsetstore (#4519)
1 parent 5848248 commit 6ac9264

File tree

3 files changed

+221
-197
lines changed

3 files changed

+221
-197
lines changed

state/factory/workingsetstore.go

Lines changed: 14 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
1-
// Copyright (c) 2022 IoTeX Foundation
1+
// Copyright (c) 2024 IoTeX Foundation
22
// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
33
// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
44
// This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
55

66
package factory
77

88
import (
9-
"context"
10-
"fmt"
11-
129
"github.com/iotexproject/go-pkgs/hash"
13-
"go.uber.org/zap"
14-
15-
"github.com/pkg/errors"
1610

1711
"github.com/iotexproject/iotex-core/v2/action/protocol"
1812
"github.com/iotexproject/iotex-core/v2/db"
19-
"github.com/iotexproject/iotex-core/v2/db/trie"
20-
"github.com/iotexproject/iotex-core/v2/pkg/log"
21-
"github.com/iotexproject/iotex-core/v2/pkg/util/byteutil"
22-
"github.com/iotexproject/iotex-core/v2/state"
2313
)
2414

2515
type (
@@ -35,220 +25,47 @@ type (
3525
ReadView(string) (interface{}, error)
3626
WriteView(string, interface{}) error
3727
}
38-
stateDBWorkingSetStore struct {
39-
view protocol.View
40-
flusher db.KVStoreFlusher
41-
readBuffer bool
42-
}
43-
factoryWorkingSetStore struct {
44-
view protocol.View
45-
flusher db.KVStoreFlusher
46-
tlt trie.TwoLayerTrie
47-
trieRoots map[int][]byte
28+
workingSetStoreCommon struct {
29+
view protocol.View
30+
flusher db.KVStoreFlusher
4831
}
4932
)
5033

51-
func newStateDBWorkingSetStore(view protocol.View, flusher db.KVStoreFlusher, readBuffer bool) workingSetStore {
52-
return &stateDBWorkingSetStore{
53-
flusher: flusher,
54-
view: view,
55-
readBuffer: readBuffer,
56-
}
57-
}
58-
59-
func newFactoryWorkingSetStore(view protocol.View, flusher db.KVStoreFlusher) (workingSetStore, error) {
60-
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, flusher.KVStoreWithBuffer(), ArchiveTrieRootKey, true)
61-
if err != nil {
62-
return nil, err
63-
}
64-
65-
return &factoryWorkingSetStore{
66-
flusher: flusher,
67-
view: view,
68-
tlt: tlt,
69-
trieRoots: make(map[int][]byte),
70-
}, nil
71-
}
72-
73-
func newFactoryWorkingSetStoreAtHeight(view protocol.View, flusher db.KVStoreFlusher, height uint64) (workingSetStore, error) {
74-
rootKey := fmt.Sprintf("%s-%d", ArchiveTrieRootKey, height)
75-
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, flusher.KVStoreWithBuffer(), rootKey, false)
76-
if err != nil {
77-
return nil, err
78-
}
79-
80-
return &factoryWorkingSetStore{
81-
flusher: flusher,
82-
view: view,
83-
tlt: tlt,
84-
trieRoots: make(map[int][]byte),
85-
}, nil
86-
}
87-
88-
func (store *stateDBWorkingSetStore) Start(context.Context) error {
89-
return nil
90-
}
91-
92-
func (store *stateDBWorkingSetStore) Stop(context.Context) error {
93-
return nil
94-
}
95-
96-
func (store *stateDBWorkingSetStore) ReadView(name string) (interface{}, error) {
34+
func (store *workingSetStoreCommon) ReadView(name string) (interface{}, error) {
9735
return store.view.Read(name)
9836
}
9937

100-
func (store *stateDBWorkingSetStore) WriteView(name string, value interface{}) error {
38+
func (store *workingSetStoreCommon) WriteView(name string, value interface{}) error {
10139
return store.view.Write(name, value)
10240
}
10341

104-
func (store *stateDBWorkingSetStore) Get(ns string, key []byte) ([]byte, error) {
105-
data, err := store.flusher.KVStoreWithBuffer().Get(ns, key)
106-
if err != nil {
107-
if errors.Cause(err) == db.ErrNotExist {
108-
return nil, errors.Wrapf(state.ErrStateNotExist, "failed to get state of ns = %x and key = %x", ns, key)
109-
}
110-
return nil, err
111-
}
112-
return data, nil
113-
}
114-
115-
func (store *stateDBWorkingSetStore) Put(ns string, key []byte, value []byte) error {
42+
func (store *workingSetStoreCommon) Put(ns string, key []byte, value []byte) error {
11643
store.flusher.KVStoreWithBuffer().MustPut(ns, key, value)
11744
return nil
11845
}
11946

120-
func (store *stateDBWorkingSetStore) Delete(ns string, key []byte) error {
47+
func (store *workingSetStoreCommon) Delete(ns string, key []byte) error {
12148
store.flusher.KVStoreWithBuffer().MustDelete(ns, key)
12249
return nil
12350
}
12451

125-
func (store *stateDBWorkingSetStore) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) {
126-
if store.readBuffer {
127-
return readStates(store.flusher.KVStoreWithBuffer(), ns, keys)
128-
}
129-
return readStates(store.flusher.BaseKVStore(), ns, keys)
130-
}
131-
132-
func (store *stateDBWorkingSetStore) Digest() hash.Hash256 {
52+
func (store *workingSetStoreCommon) Digest() hash.Hash256 {
13353
return hash.Hash256b(store.flusher.SerializeQueue())
13454
}
13555

136-
func (store *stateDBWorkingSetStore) Finalize(height uint64) error {
137-
// Persist current chain Height
138-
store.flusher.KVStoreWithBuffer().MustPut(
139-
AccountKVNamespace,
140-
[]byte(CurrentHeightKey),
141-
byteutil.Uint64ToBytes(height),
142-
)
143-
return nil
144-
}
145-
146-
func (store *stateDBWorkingSetStore) Commit() error {
56+
func (store *workingSetStoreCommon) Commit() error {
57+
_dbBatchSizelMtc.WithLabelValues().Set(float64(store.flusher.KVStoreWithBuffer().Size()))
14758
return store.flusher.Flush()
14859
}
14960

150-
func (store *stateDBWorkingSetStore) Snapshot() int {
61+
func (store *workingSetStoreCommon) Snapshot() int {
15162
return store.flusher.KVStoreWithBuffer().Snapshot()
15263
}
15364

154-
func (store *stateDBWorkingSetStore) RevertSnapshot(snapshot int) error {
65+
func (store *workingSetStoreCommon) RevertSnapshot(snapshot int) error {
15566
return store.flusher.KVStoreWithBuffer().RevertSnapshot(snapshot)
15667
}
15768

158-
func (store *stateDBWorkingSetStore) ResetSnapshots() {
159-
store.flusher.KVStoreWithBuffer().ResetSnapshots()
160-
}
161-
162-
func (store *factoryWorkingSetStore) Start(ctx context.Context) error {
163-
return store.tlt.Start(ctx)
164-
}
165-
166-
func (store *factoryWorkingSetStore) Stop(ctx context.Context) error {
167-
return store.tlt.Stop(ctx)
168-
}
169-
170-
func (store *factoryWorkingSetStore) ReadView(name string) (interface{}, error) {
171-
return store.view.Read(name)
172-
}
173-
174-
func (store *factoryWorkingSetStore) WriteView(name string, value interface{}) error {
175-
return store.view.Write(name, value)
176-
}
177-
178-
func (store *factoryWorkingSetStore) Get(ns string, key []byte) ([]byte, error) {
179-
return readStateFromTLT(store.tlt, ns, key)
180-
}
181-
182-
func (store *factoryWorkingSetStore) Put(ns string, key []byte, value []byte) error {
183-
store.flusher.KVStoreWithBuffer().MustPut(ns, key, value)
184-
nsHash := hash.Hash160b([]byte(ns))
185-
186-
return store.tlt.Upsert(nsHash[:], toLegacyKey(key), value)
187-
}
188-
189-
func (store *factoryWorkingSetStore) Delete(ns string, key []byte) error {
190-
store.flusher.KVStoreWithBuffer().MustDelete(ns, key)
191-
nsHash := hash.Hash160b([]byte(ns))
192-
193-
err := store.tlt.Delete(nsHash[:], toLegacyKey(key))
194-
if errors.Cause(err) == trie.ErrNotExist {
195-
return errors.Wrapf(state.ErrStateNotExist, "key %x doesn't exist in namespace %x", key, nsHash)
196-
}
197-
return err
198-
}
199-
200-
func (store *factoryWorkingSetStore) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) {
201-
return readStatesFromTLT(store.tlt, ns, keys)
202-
}
203-
204-
func (store *factoryWorkingSetStore) Digest() hash.Hash256 {
205-
return hash.Hash256b(store.flusher.SerializeQueue())
206-
}
207-
208-
func (store *factoryWorkingSetStore) Finalize(h uint64) error {
209-
rootHash, err := store.tlt.RootHash()
210-
if err != nil {
211-
return err
212-
}
213-
store.flusher.KVStoreWithBuffer().MustPut(AccountKVNamespace, []byte(CurrentHeightKey), byteutil.Uint64ToBytes(h))
214-
store.flusher.KVStoreWithBuffer().MustPut(ArchiveTrieNamespace, []byte(ArchiveTrieRootKey), rootHash)
215-
// Persist the historical accountTrie's root hash
216-
store.flusher.KVStoreWithBuffer().MustPut(
217-
ArchiveTrieNamespace,
218-
[]byte(fmt.Sprintf("%s-%d", ArchiveTrieRootKey, h)),
219-
rootHash,
220-
)
221-
return nil
222-
}
223-
224-
func (store *factoryWorkingSetStore) Commit() error {
225-
_dbBatchSizelMtc.WithLabelValues().Set(float64(store.flusher.KVStoreWithBuffer().Size()))
226-
return store.flusher.Flush()
227-
}
228-
229-
func (store *factoryWorkingSetStore) Snapshot() int {
230-
rh, err := store.tlt.RootHash()
231-
if err != nil {
232-
log.L().Panic("failed to do snapshot", zap.Error(err))
233-
}
234-
s := store.flusher.KVStoreWithBuffer().Snapshot()
235-
store.trieRoots[s] = rh
236-
return s
237-
}
238-
239-
func (store *factoryWorkingSetStore) RevertSnapshot(snapshot int) error {
240-
if err := store.flusher.KVStoreWithBuffer().RevertSnapshot(snapshot); err != nil {
241-
return err
242-
}
243-
root, ok := store.trieRoots[snapshot]
244-
if !ok {
245-
// this should not happen, b/c we save the trie root on a successful return of Snapshot(), but check anyway
246-
return errors.Wrapf(trie.ErrInvalidTrie, "failed to get trie root for snapshot = %d", snapshot)
247-
}
248-
return store.tlt.SetRootHash(root[:])
249-
}
250-
251-
func (store *factoryWorkingSetStore) ResetSnapshots() {
69+
func (store *workingSetStoreCommon) ResetSnapshots() {
25270
store.flusher.KVStoreWithBuffer().ResetSnapshots()
253-
store.trieRoots = make(map[int][]byte)
25471
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright (c) 2024 IoTeX Foundation
2+
// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
3+
// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
4+
// This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
5+
6+
package factory
7+
8+
import (
9+
"context"
10+
"fmt"
11+
12+
"github.com/iotexproject/go-pkgs/hash"
13+
"github.com/pkg/errors"
14+
"go.uber.org/zap"
15+
16+
"github.com/iotexproject/iotex-core/v2/action/protocol"
17+
"github.com/iotexproject/iotex-core/v2/db"
18+
"github.com/iotexproject/iotex-core/v2/db/trie"
19+
"github.com/iotexproject/iotex-core/v2/pkg/log"
20+
"github.com/iotexproject/iotex-core/v2/pkg/util/byteutil"
21+
"github.com/iotexproject/iotex-core/v2/state"
22+
)
23+
24+
type factoryWorkingSetStore struct {
25+
*workingSetStoreCommon
26+
tlt trie.TwoLayerTrie
27+
trieRoots map[int][]byte
28+
}
29+
30+
func newFactoryWorkingSetStore(view protocol.View, flusher db.KVStoreFlusher) (workingSetStore, error) {
31+
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, flusher.KVStoreWithBuffer(), ArchiveTrieRootKey, true)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
return &factoryWorkingSetStore{
37+
workingSetStoreCommon: &workingSetStoreCommon{
38+
flusher: flusher,
39+
view: view,
40+
},
41+
tlt: tlt,
42+
trieRoots: make(map[int][]byte),
43+
}, nil
44+
}
45+
46+
func newFactoryWorkingSetStoreAtHeight(view protocol.View, flusher db.KVStoreFlusher, height uint64) (workingSetStore, error) {
47+
rootKey := fmt.Sprintf("%s-%d", ArchiveTrieRootKey, height)
48+
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, flusher.KVStoreWithBuffer(), rootKey, false)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
return &factoryWorkingSetStore{
54+
workingSetStoreCommon: &workingSetStoreCommon{
55+
flusher: flusher,
56+
view: view,
57+
},
58+
tlt: tlt,
59+
trieRoots: make(map[int][]byte),
60+
}, nil
61+
}
62+
63+
func (store *factoryWorkingSetStore) Start(ctx context.Context) error {
64+
return store.tlt.Start(ctx)
65+
}
66+
67+
func (store *factoryWorkingSetStore) Stop(ctx context.Context) error {
68+
return store.tlt.Stop(ctx)
69+
}
70+
71+
func (store *factoryWorkingSetStore) Get(ns string, key []byte) ([]byte, error) {
72+
return readStateFromTLT(store.tlt, ns, key)
73+
}
74+
75+
func (store *factoryWorkingSetStore) Put(ns string, key []byte, value []byte) error {
76+
store.workingSetStoreCommon.Put(ns, key, value)
77+
nsHash := hash.Hash160b([]byte(ns))
78+
79+
return store.tlt.Upsert(nsHash[:], toLegacyKey(key), value)
80+
}
81+
82+
func (store *factoryWorkingSetStore) Delete(ns string, key []byte) error {
83+
store.workingSetStoreCommon.Delete(ns, key)
84+
nsHash := hash.Hash160b([]byte(ns))
85+
86+
err := store.tlt.Delete(nsHash[:], toLegacyKey(key))
87+
if errors.Cause(err) == trie.ErrNotExist {
88+
return errors.Wrapf(state.ErrStateNotExist, "key %x doesn't exist in namespace %x", key, nsHash)
89+
}
90+
return err
91+
}
92+
93+
func (store *factoryWorkingSetStore) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) {
94+
return readStatesFromTLT(store.tlt, ns, keys)
95+
}
96+
97+
func (store *factoryWorkingSetStore) Finalize(h uint64) error {
98+
rootHash, err := store.tlt.RootHash()
99+
if err != nil {
100+
return err
101+
}
102+
store.flusher.KVStoreWithBuffer().MustPut(AccountKVNamespace, []byte(CurrentHeightKey), byteutil.Uint64ToBytes(h))
103+
store.flusher.KVStoreWithBuffer().MustPut(ArchiveTrieNamespace, []byte(ArchiveTrieRootKey), rootHash)
104+
// Persist the historical accountTrie's root hash
105+
store.flusher.KVStoreWithBuffer().MustPut(
106+
ArchiveTrieNamespace,
107+
[]byte(fmt.Sprintf("%s-%d", ArchiveTrieRootKey, h)),
108+
rootHash,
109+
)
110+
return nil
111+
}
112+
113+
func (store *factoryWorkingSetStore) Snapshot() int {
114+
rh, err := store.tlt.RootHash()
115+
if err != nil {
116+
log.L().Panic("failed to do snapshot", zap.Error(err))
117+
}
118+
s := store.workingSetStoreCommon.Snapshot()
119+
store.trieRoots[s] = rh
120+
return s
121+
}
122+
123+
func (store *factoryWorkingSetStore) RevertSnapshot(snapshot int) error {
124+
if err := store.workingSetStoreCommon.RevertSnapshot(snapshot); err != nil {
125+
return err
126+
}
127+
root, ok := store.trieRoots[snapshot]
128+
if !ok {
129+
// this should not happen, b/c we save the trie root on a successful return of Snapshot(), but check anyway
130+
return errors.Wrapf(trie.ErrInvalidTrie, "failed to get trie root for snapshot = %d", snapshot)
131+
}
132+
return store.tlt.SetRootHash(root[:])
133+
}
134+
135+
func (store *factoryWorkingSetStore) ResetSnapshots() {
136+
store.workingSetStoreCommon.ResetSnapshots()
137+
store.trieRoots = make(map[int][]byte)
138+
}

0 commit comments

Comments
 (0)