aboutsummaryrefslogtreecommitdiffstats
path: root/trie
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2016-10-21 23:34:17 +0800
committerFelix Lange <fjl@twurst.com>2016-10-21 23:34:17 +0800
commitf8608a5228750076aa15b1e3a67acd7994492053 (patch)
tree39aaf06c7715da489927b2c8d7c50edf8b55a39b /trie
parent437c1e40b297efe6216e1d13840cee79f2dd643c (diff)
downloadgo-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar.gz
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar.bz2
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar.lz
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar.xz
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.tar.zst
go-tangerine-f8608a5228750076aa15b1e3a67acd7994492053.zip
trie: while fast syncing, don't keep trie nodes in memory (#3186)
Diffstat (limited to 'trie')
-rw-r--r--trie/sync.go32
1 files changed, 13 insertions, 19 deletions
diff --git a/trie/sync.go b/trie/sync.go
index 30caf6980..58b8a1fb6 100644
--- a/trie/sync.go
+++ b/trie/sync.go
@@ -31,9 +31,9 @@ var ErrNotRequested = errors.New("not requested")
// request represents a scheduled or already in-flight state retrieval request.
type request struct {
- hash common.Hash // Hash of the node data content to retrieve
- data []byte // Data content of the node, cached until all subtrees complete
- object *node // Target node to populate with retrieved data (hashnode originally)
+ hash common.Hash // Hash of the node data content to retrieve
+ data []byte // Data content of the node, cached until all subtrees complete
+ raw bool // Whether this is a raw entry (code) or a trie node
parents []*request // Parent state nodes referencing this entry (notify all upon completion)
depth int // Depth level within the trie the node is located to prioritise DFS
@@ -86,9 +86,7 @@ func (s *TrieSync) AddSubTrie(root common.Hash, depth int, parent common.Hash, c
return
}
// Assemble the new sub-trie sync request
- node := node(hashNode(root.Bytes()))
req := &request{
- object: &node,
hash: root,
depth: depth,
callback: callback,
@@ -120,6 +118,7 @@ func (s *TrieSync) AddRawEntry(hash common.Hash, depth int, parent common.Hash)
// Assemble the new sub-trie sync request
req := &request{
hash: hash,
+ raw: true,
depth: depth,
}
// If this sub-trie has a designated parent, link them together
@@ -152,7 +151,7 @@ func (s *TrieSync) Process(results []SyncResult) (int, error) {
return i, ErrNotRequested
}
// If the item is a raw entry request, commit directly
- if request.object == nil {
+ if request.raw {
request.data = item.Data
s.commit(request, nil)
continue
@@ -162,11 +161,10 @@ func (s *TrieSync) Process(results []SyncResult) (int, error) {
if err != nil {
return i, err
}
- *request.object = node
request.data = item.Data
// Create and schedule a request for all the children nodes
- requests, err := s.children(request)
+ requests, err := s.children(request, node)
if err != nil {
return i, err
}
@@ -203,27 +201,25 @@ func (s *TrieSync) schedule(req *request) {
// children retrieves all the missing children of a state trie entry for future
// retrieval scheduling.
-func (s *TrieSync) children(req *request) ([]*request, error) {
+func (s *TrieSync) children(req *request, object node) ([]*request, error) {
// Gather all the children of the node, irrelevant whether known or not
type child struct {
- node *node
+ node node
depth int
}
children := []child{}
- switch node := (*req.object).(type) {
+ switch node := (object).(type) {
case *shortNode:
- node = node.copy() // Prevents linking all downloaded nodes together.
children = []child{{
- node: &node.Val,
+ node: node.Val,
depth: req.depth + len(node.Key),
}}
case *fullNode:
- node = node.copy()
for i := 0; i < 17; i++ {
if node.Children[i] != nil {
children = append(children, child{
- node: &node.Children[i],
+ node: node.Children[i],
depth: req.depth + 1,
})
}
@@ -236,23 +232,21 @@ func (s *TrieSync) children(req *request) ([]*request, error) {
for _, child := range children {
// Notify any external watcher of a new key/value node
if req.callback != nil {
- if node, ok := (*child.node).(valueNode); ok {
+ if node, ok := (child.node).(valueNode); ok {
if err := req.callback(node, req.hash); err != nil {
return nil, err
}
}
}
// If the child references another node, resolve or schedule
- if node, ok := (*child.node).(hashNode); ok {
+ if node, ok := (child.node).(hashNode); ok {
// Try to resolve the node from the local database
blob, _ := s.database.Get(node)
if local, err := decodeNode(node[:], blob, 0); local != nil && err == nil {
- *child.node = local
continue
}
// Locally unknown node, schedule for retrieval
requests = append(requests, &request{
- object: child.node,
hash: common.BytesToHash(node),
parents: []*request{req},
depth: child.depth,