mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie: enable batch updates
This commit is contained in:
parent
aa281e7d7e
commit
478d0ee00d
5 changed files with 36 additions and 3 deletions
|
|
@ -69,7 +69,8 @@ type Trie interface {
|
||||||
// by the caller while they are stored in the trie. If a node was not found in the
|
// by the caller while they are stored in the trie. If a node was not found in the
|
||||||
// database, a trie.MissingNodeError is returned.
|
// database, a trie.MissingNodeError is returned.
|
||||||
TryUpdate(key, value []byte) error
|
TryUpdate(key, value []byte) error
|
||||||
|
BatchStart()
|
||||||
|
BatchEnd()
|
||||||
// TryDelete removes any existing value for key from the trie. If a node was not
|
// TryDelete removes any existing value for key from the trie. If a node was not
|
||||||
// found in the database, a trie.MissingNodeError is returned.
|
// found in the database, a trie.MissingNodeError is returned.
|
||||||
TryDelete(key []byte) error
|
TryDelete(key []byte) error
|
||||||
|
|
|
||||||
|
|
@ -688,7 +688,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
// Finalise all the dirty storage states and write them into the tries
|
// Finalise all the dirty storage states and write them into the tries
|
||||||
s.Finalise(deleteEmptyObjects)
|
s.Finalise(deleteEmptyObjects)
|
||||||
|
s.trie.BatchStart()
|
||||||
for addr := range s.stateObjectsPending {
|
for addr := range s.stateObjectsPending {
|
||||||
obj := s.stateObjects[addr]
|
obj := s.stateObjects[addr]
|
||||||
if obj.deleted {
|
if obj.deleted {
|
||||||
|
|
@ -698,6 +698,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
s.updateStateObject(obj)
|
s.updateStateObject(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.trie.BatchEnd()
|
||||||
if len(s.stateObjectsPending) > 0 {
|
if len(s.stateObjectsPending) > 0 {
|
||||||
s.stateObjectsPending = make(map[common.Address]struct{})
|
s.stateObjectsPending = make(map[common.Address]struct{})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,9 @@ func (t *odrTrie) TryUpdate(key, value []byte) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *odrTrie) BatchStart() {}
|
||||||
|
func (t *odrTrie) BatchEnd() {}
|
||||||
|
|
||||||
func (t *odrTrie) TryDelete(key []byte) error {
|
func (t *odrTrie) TryDelete(key []byte) error {
|
||||||
key = crypto.Keccak256(key)
|
key = crypto.Keccak256(key)
|
||||||
return t.do(key, func() error {
|
return t.do(key, func() error {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,13 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *SecureTrie) BatchStart(){
|
||||||
|
t.trie.batchStart()
|
||||||
|
}
|
||||||
|
func (t *SecureTrie) BatchEnd(){
|
||||||
|
t.trie.batchEnd()
|
||||||
|
}
|
||||||
|
|
||||||
// Delete removes any existing value for key from the trie.
|
// Delete removes any existing value for key from the trie.
|
||||||
func (t *SecureTrie) Delete(key []byte) {
|
func (t *SecureTrie) Delete(key []byte) {
|
||||||
if err := t.TryDelete(key); err != nil {
|
if err := t.TryDelete(key); err != nil {
|
||||||
|
|
|
||||||
23
trie/trie.go
23
trie/trie.go
|
|
@ -52,6 +52,7 @@ type Trie struct {
|
||||||
dirtyCount int
|
dirtyCount int
|
||||||
// And leafs to hash
|
// And leafs to hash
|
||||||
unhashedCount int
|
unhashedCount int
|
||||||
|
batchMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFlag returns the cache flag value for a newly created node.
|
// newFlag returns the cache flag value for a newly created node.
|
||||||
|
|
@ -186,6 +187,13 @@ func (t *Trie) TryUpdate(key, value []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Trie) batchStart(){
|
||||||
|
t.batchMode = true
|
||||||
|
}
|
||||||
|
func (t *Trie) batchEnd(){
|
||||||
|
t.batchMode = false
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error) {
|
func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error) {
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
if v, ok := n.(valueNode); ok {
|
if v, ok := n.(valueNode); ok {
|
||||||
|
|
@ -228,7 +236,20 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
|
||||||
if !dirty || err != nil {
|
if !dirty || err != nil {
|
||||||
return false, n, err
|
return false, n, err
|
||||||
}
|
}
|
||||||
n = n.copy()
|
// If we're in batch-mode, we don't keep 'ephemeral' changes.
|
||||||
|
// When we modify a node, we only copy it in case it is an old committed
|
||||||
|
// node.
|
||||||
|
// If the node is "new", we just update in place.
|
||||||
|
if t.batchMode{
|
||||||
|
if h, dirty := n.cache(); !dirty || h != nil{
|
||||||
|
// This node is either not dirty, or already hashed. We copy it
|
||||||
|
n = n.copy()
|
||||||
|
}else{
|
||||||
|
// No copy
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
n = n.copy()
|
||||||
|
}
|
||||||
n.flags = t.newFlag()
|
n.flags = t.newFlag()
|
||||||
n.Children[key[0]] = nn
|
n.Children[key[0]] = nn
|
||||||
return true, n, nil
|
return true, n, nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue