-
Notifications
You must be signed in to change notification settings - Fork 177
/
storage_state.go
133 lines (109 loc) · 2.46 KB
/
storage_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package state
import (
"fmt"
"github.com/onflow/flow-go/fvm/storage/snapshot"
"github.com/onflow/flow-go/model/flow"
)
type storageState struct {
baseStorage snapshot.StorageSnapshot
// The read set only include reads from the baseStorage
readSet map[flow.RegisterID]struct{}
writeSet map[flow.RegisterID]flow.RegisterValue
}
func newStorageState(base snapshot.StorageSnapshot) *storageState {
return &storageState{
baseStorage: base,
readSet: map[flow.RegisterID]struct{}{},
writeSet: map[flow.RegisterID]flow.RegisterValue{},
}
}
func (state *storageState) NewChild() *storageState {
return newStorageState(snapshot.NewPeekerStorageSnapshot(state))
}
func (state *storageState) Finalize() *snapshot.ExecutionSnapshot {
return &snapshot.ExecutionSnapshot{
ReadSet: state.readSet,
WriteSet: state.writeSet,
}
}
func (state *storageState) Merge(snapshot *snapshot.ExecutionSnapshot) error {
for id := range snapshot.ReadSet {
_, ok := state.writeSet[id]
if ok {
continue
}
state.readSet[id] = struct{}{}
}
for id, value := range snapshot.WriteSet {
state.writeSet[id] = value
}
return nil
}
func (state *storageState) Set(
id flow.RegisterID,
value flow.RegisterValue,
) error {
state.writeSet[id] = value
return nil
}
func (state *storageState) get(
id flow.RegisterID,
) (
bool, // read from base storage
flow.RegisterValue,
error,
) {
value, ok := state.writeSet[id]
if ok {
return false, value, nil
}
if state.baseStorage == nil {
return true, nil, nil
}
value, err := state.baseStorage.Get(id)
if err != nil {
return true, nil, fmt.Errorf("get register failed: %w", err)
}
return true, value, nil
}
func (state *storageState) Get(
id flow.RegisterID,
) (
flow.RegisterValue,
error,
) {
readFromBaseStorage, value, err := state.get(id)
if err != nil {
return nil, err
}
if readFromBaseStorage {
state.readSet[id] = struct{}{}
}
return value, nil
}
func (state *storageState) Peek(
id flow.RegisterID,
) (
flow.RegisterValue,
error,
) {
_, value, err := state.get(id)
return value, err
}
func (state *storageState) DropChanges() error {
state.writeSet = map[flow.RegisterID]flow.RegisterValue{}
return nil
}
func (state *storageState) readSetSize() int {
return len(state.readSet)
}
func (state *storageState) interimReadSet(
accumulator map[flow.RegisterID]struct{},
) {
for id := range state.writeSet {
delete(accumulator, id)
}
for id := range state.readSet {
accumulator[id] = struct{}{}
}
}