mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
core, trie: fix duplicate references, sanity check on shutdown
This commit is contained in:
parent
b46b291742
commit
4315480e09
2 changed files with 19 additions and 13 deletions
|
|
@ -669,6 +669,9 @@ func (bc *BlockChain) Stop() {
|
||||||
for !bc.triegc.Empty() {
|
for !bc.triegc.Empty() {
|
||||||
bc.triedb.Dereference(bc.triegc.PopItem().(common.Hash), common.Hash{})
|
bc.triedb.Dereference(bc.triegc.PopItem().(common.Hash), common.Hash{})
|
||||||
}
|
}
|
||||||
|
if size := bc.triedb.Size(); size != 0 {
|
||||||
|
log.Error("Dangling trie nodes after full cleanup")
|
||||||
|
}
|
||||||
log.Info("Blockchain manager stopped")
|
log.Info("Blockchain manager stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ type Database struct {
|
||||||
type cachedNode struct {
|
type cachedNode struct {
|
||||||
blob []byte // Cached data block of the trie node
|
blob []byte // Cached data block of the trie node
|
||||||
parents int // Number of live nodes referencing this one
|
parents int // Number of live nodes referencing this one
|
||||||
children map[common.Hash]int // Children referenced by this nodes
|
children map[common.Hash]struct{} // Children referenced by this nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a new trie database to store ephemeral trie content before
|
// NewDatabase creates a new trie database to store ephemeral trie content before
|
||||||
|
|
@ -72,7 +72,7 @@ func NewDatabase(diskdb ethdb.Database) *Database {
|
||||||
return &Database{
|
return &Database{
|
||||||
diskdb: diskdb,
|
diskdb: diskdb,
|
||||||
nodes: map[common.Hash]*cachedNode{
|
nodes: map[common.Hash]*cachedNode{
|
||||||
common.Hash{}: {children: make(map[common.Hash]int)},
|
common.Hash{}: {children: make(map[common.Hash]struct{})},
|
||||||
},
|
},
|
||||||
preimages: make(map[common.Hash][]byte),
|
preimages: make(map[common.Hash][]byte),
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +99,7 @@ func (db *Database) insert(hash common.Hash, blob []byte) {
|
||||||
}
|
}
|
||||||
db.nodes[hash] = &cachedNode{
|
db.nodes[hash] = &cachedNode{
|
||||||
blob: common.CopyBytes(blob),
|
blob: common.CopyBytes(blob),
|
||||||
children: make(map[common.Hash]int),
|
children: make(map[common.Hash]struct{}),
|
||||||
}
|
}
|
||||||
db.size += common.StorageSize(common.HashLength + len(blob))
|
db.size += common.StorageSize(common.HashLength + len(blob))
|
||||||
}
|
}
|
||||||
|
|
@ -185,8 +185,12 @@ func (db *Database) reference(child common.Hash, parent common.Hash) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// If the reference already exists, don't duplicate it
|
||||||
|
if _, ok = db.nodes[parent].children[child]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
node.parents++
|
node.parents++
|
||||||
db.nodes[parent].children[child]++
|
db.nodes[parent].children[child] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dereference removes an existing reference from a parent node to a child node.
|
// Dereference removes an existing reference from a parent node to a child node.
|
||||||
|
|
@ -200,17 +204,16 @@ func (db *Database) Dereference(child common.Hash, parent common.Hash) {
|
||||||
db.gcnodes += uint64(nodes - len(db.nodes))
|
db.gcnodes += uint64(nodes - len(db.nodes))
|
||||||
db.gcsize += storage - db.size
|
db.gcsize += storage - db.size
|
||||||
db.gctime += time.Since(start)
|
db.gctime += time.Since(start)
|
||||||
|
|
||||||
|
log.Debug("Dereferenced trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.size, "time", time.Since(start),
|
||||||
|
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dereference is the private locked version of Dereference.
|
// dereference is the private locked version of Dereference.
|
||||||
func (db *Database) dereference(child common.Hash, parent common.Hash) {
|
func (db *Database) dereference(child common.Hash, parent common.Hash) {
|
||||||
// Dereference the parent-child
|
// Dereference the parent-child relationship
|
||||||
node := db.nodes[parent]
|
delete(db.nodes[parent].children, child)
|
||||||
|
|
||||||
node.children[child]--
|
|
||||||
if node.children[child] == 0 {
|
|
||||||
delete(node.children, child)
|
|
||||||
}
|
|
||||||
// If the node does not exist, it's a previously comitted node.
|
// If the node does not exist, it's a previously comitted node.
|
||||||
node, ok := db.nodes[child]
|
node, ok := db.nodes[child]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -271,7 +274,7 @@ func (db *Database) Commit(node common.Hash) error {
|
||||||
db.preimages = make(map[common.Hash][]byte)
|
db.preimages = make(map[common.Hash][]byte)
|
||||||
db.uncache(node)
|
db.uncache(node)
|
||||||
|
|
||||||
log.Debug("Persisted trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.size, "time", time.Since(start),
|
log.Info("Persisted trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.size, "time", time.Since(start),
|
||||||
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.size)
|
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.size)
|
||||||
|
|
||||||
// Reset the garbage collection statistics
|
// Reset the garbage collection statistics
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue