-
Notifications
You must be signed in to change notification settings - Fork 198
/
trieNodeResolver.go
134 lines (115 loc) · 4.1 KB
/
trieNodeResolver.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
134
package storageResolvers
import (
"time"
"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/data/batch"
"github.com/ElrondNetwork/elrond-go-core/data/endProcess"
"github.com/ElrondNetwork/elrond-go-core/marshal"
"github.com/ElrondNetwork/elrond-go/common"
"github.com/ElrondNetwork/elrond-go/dataRetriever"
)
// maxBuffToSendTrieNodes represents max buffer size to send in bytes
var maxBuffToSendTrieNodes = uint64(1 << 18) //256KB
// ArgTrieResolver is the argument structure used to create new TrieResolver instance
type ArgTrieResolver struct {
Messenger dataRetriever.MessageHandler
ResponseTopicName string
Marshalizer marshal.Marshalizer
TrieDataGetter dataRetriever.TrieDataGetter
TrieStorageManager common.StorageManager
ManualEpochStartNotifier dataRetriever.ManualEpochStartNotifier
ChanGracefullyClose chan endProcess.ArgEndProcess
DelayBeforeGracefulClose time.Duration
}
type trieNodeResolver struct {
*storageResolver
trieDataGetter dataRetriever.TrieDataGetter
trieStorageManager common.StorageManager
marshalizer marshal.Marshalizer
}
// NewTrieNodeResolver returns a new trie node resolver instance. It uses trie snapshots in order to get older data
func NewTrieNodeResolver(arg ArgTrieResolver) (*trieNodeResolver, error) {
if check.IfNil(arg.Messenger) {
return nil, dataRetriever.ErrNilMessenger
}
if check.IfNil(arg.ManualEpochStartNotifier) {
return nil, dataRetriever.ErrNilManualEpochStartNotifier
}
if arg.ChanGracefullyClose == nil {
return nil, dataRetriever.ErrNilGracefullyCloseChannel
}
if check.IfNil(arg.TrieStorageManager) {
return nil, dataRetriever.ErrNilTrieStorageManager
}
if check.IfNil(arg.TrieDataGetter) {
return nil, dataRetriever.ErrNilTrieDataGetter
}
if check.IfNil(arg.Marshalizer) {
return nil, dataRetriever.ErrNilMarshalizer
}
return &trieNodeResolver{
storageResolver: &storageResolver{
messenger: arg.Messenger,
responseTopicName: arg.ResponseTopicName,
manualEpochStartNotifier: arg.ManualEpochStartNotifier,
chanGracefullyClose: arg.ChanGracefullyClose,
delayBeforeGracefulClose: arg.DelayBeforeGracefulClose,
},
trieStorageManager: arg.TrieStorageManager,
trieDataGetter: arg.TrieDataGetter,
marshalizer: arg.Marshalizer,
}, nil
}
// RequestDataFromHash tries to fetch the required trie node and send it to self
func (tnr *trieNodeResolver) RequestDataFromHash(hash []byte, _ uint32) error {
nodes, _, err := tnr.getSubTrie(hash, maxBuffToSendTrieNodes)
if err != nil {
return err
}
return tnr.sendDataToSelf(nodes)
}
// RequestDataFromHashArray tries to fetch the required trie nodes and send it to self
func (tnr *trieNodeResolver) RequestDataFromHashArray(hashes [][]byte, _ uint32) error {
remainingSpace := maxBuffToSendTrieNodes
nodes := make([][]byte, 0, maxBuffToSendTrieNodes)
var nextNodes [][]byte
var err error
for _, hash := range hashes {
nextNodes, remainingSpace, err = tnr.getSubTrie(hash, remainingSpace)
if err != nil {
continue
}
nodes = append(nodes, nextNodes...)
lenNextNodes := uint64(len(nextNodes))
if lenNextNodes == 0 || remainingSpace == 0 {
break
}
}
return tnr.sendDataToSelf(nodes)
}
func (tnr *trieNodeResolver) getSubTrie(hash []byte, remainingSpace uint64) ([][]byte, uint64, error) {
serializedNodes, remainingSpace, err := tnr.trieDataGetter.GetSerializedNodes(hash, remainingSpace)
if err != nil {
tnr.signalGracefullyClose()
return nil, remainingSpace, err
}
return serializedNodes, remainingSpace, nil
}
func (tnr *trieNodeResolver) sendDataToSelf(serializedNodes [][]byte) error {
buff, err := tnr.marshalizer.Marshal(
&batch.Batch{
Data: serializedNodes,
})
if err != nil {
return err
}
return tnr.sendToSelf(buff)
}
// Close will try to close the associated opened storers
func (tnr *trieNodeResolver) Close() error {
return tnr.trieStorageManager.Close()
}
// IsInterfaceNil returns true if there is no value under the interface
func (tnr *trieNodeResolver) IsInterfaceNil() bool {
return tnr == nil
}