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
|
||||
// database, a trie.MissingNodeError is returned.
|
||||
TryUpdate(key, value []byte) error
|
||||
|
||||
BatchStart()
|
||||
BatchEnd()
|
||||
// TryDelete removes any existing value for key from the trie. If a node was not
|
||||
// found in the database, a trie.MissingNodeError is returned.
|
||||
TryDelete(key []byte) error
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
|||
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
// Finalise all the dirty storage states and write them into the tries
|
||||
s.Finalise(deleteEmptyObjects)
|
||||
|
||||
s.trie.BatchStart()
|
||||
for addr := range s.stateObjectsPending {
|
||||
obj := s.stateObjects[addr]
|
||||
if obj.deleted {
|
||||
|
|
@ -698,6 +698,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||
s.updateStateObject(obj)
|
||||
}
|
||||
}
|
||||
s.trie.BatchEnd()
|
||||
if len(s.stateObjectsPending) > 0 {
|
||||
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 {
|
||||
key = crypto.Keccak256(key)
|
||||
return t.do(key, func() error {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,13 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error {
|
|||
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.
|
||||
func (t *SecureTrie) Delete(key []byte) {
|
||||
if err := t.TryDelete(key); err != nil {
|
||||
|
|
|
|||
23
trie/trie.go
23
trie/trie.go
|
|
@ -52,6 +52,7 @@ type Trie struct {
|
|||
dirtyCount int
|
||||
// And leafs to hash
|
||||
unhashedCount int
|
||||
batchMode bool
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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) {
|
||||
if len(key) == 0 {
|
||||
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 {
|
||||
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.Children[key[0]] = nn
|
||||
return true, n, nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue