core, trie: commit trie mempool on close, fix dao test

This commit is contained in:
Péter Szilágyi 2018-01-11 23:41:43 +02:00
parent 33cca2bbea
commit 0e91a178b7
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
3 changed files with 38 additions and 8 deletions

View file

@ -592,6 +592,17 @@ func (bc *BlockChain) Stop() {
atomic.StoreInt32(&bc.procInterrupt, 1) atomic.StoreInt32(&bc.procInterrupt, 1)
bc.wg.Wait() bc.wg.Wait()
// Ensure the state of the latest block is also stored to disk
root := bc.CurrentHeader().Root
batch := bc.chainDb.NewBatch()
if err := bc.trieMemPool.Commit(root, batch); err != nil {
log.Error("Failed to commit latest state trie", "err", err)
}
if err := batch.Write(); err != nil {
log.Error("Failed to write latest state trie", "err", err)
}
log.Info("Blockchain manager stopped") log.Info("Blockchain manager stopped")
} }

View file

@ -79,6 +79,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err) t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
} }
if err := bc.trieMemPool.Commit(bc.CurrentHeader().Root, db); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err == nil { if _, err := conBc.InsertChain(blocks); err == nil {
t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0])
@ -101,6 +104,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err) t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
} }
if err := bc.trieMemPool.Commit(bc.CurrentHeader().Root, db); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err == nil { if _, err := proBc.InsertChain(blocks); err == nil {
t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0])
@ -124,6 +130,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err) t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
} }
if err := bc.trieMemPool.Commit(bc.CurrentHeader().Root, db); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err != nil { if _, err := conBc.InsertChain(blocks); err != nil {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
@ -141,6 +150,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err) t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
} }
if err := bc.trieMemPool.Commit(bc.CurrentHeader().Root, db); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
}
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err != nil { if _, err := proBc.InsertChain(blocks); err != nil {
t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)

View file

@ -132,13 +132,15 @@ func (pool *MemPool) dereference(node common.Hash, parent common.Hash) {
// Commit iterates over all the children of a particular node, writes them out // Commit iterates over all the children of a particular node, writes them out
// to disk, forcefully tearing down all references in both directions. // to disk, forcefully tearing down all references in both directions.
func (pool *MemPool) Commit(node common.Hash, db DatabaseWriter) { func (pool *MemPool) Commit(node common.Hash, db DatabaseWriter) error {
pool.lock.Lock() pool.lock.Lock()
defer pool.lock.Unlock() defer pool.lock.Unlock()
nodes, storage, start := len(pool.cache), pool.size, time.Now() nodes, storage, start := len(pool.cache), pool.size, time.Now()
pool.commit(node, db) if err := pool.commit(node, db); err != nil {
log.Error("Failed to commit trie from mempool", "err", err)
return err
}
log.Debug("Committed trie from memory pool", "nodes", nodes-len(pool.cache), "size", storage-pool.size, "time", time.Since(start), log.Debug("Committed trie from memory pool", "nodes", nodes-len(pool.cache), "size", storage-pool.size, "time", time.Since(start),
"gcnodes", pool.gcnodes, "gcsize", pool.gcsize, "gctime", pool.gctime, "livenodes", len(pool.cache), "livesize", pool.size) "gcnodes", pool.gcnodes, "gcsize", pool.gcsize, "gctime", pool.gctime, "livenodes", len(pool.cache), "livesize", pool.size)
@ -152,23 +154,28 @@ func (pool *MemPool) Commit(node common.Hash, db DatabaseWriter) {
break break
} }
} }
return nil
} }
// commit is the private locked version of Commit. // commit is the private locked version of Commit.
func (pool *MemPool) commit(node common.Hash, db DatabaseWriter) { func (pool *MemPool) commit(node common.Hash, db DatabaseWriter) error {
// If the node does not exist, it's a previously comitted node. // If the node does not exist, it's a previously comitted node.
blob, ok := pool.cache[node] blob, ok := pool.cache[node]
if !ok { if !ok {
return return nil
} }
for child := range pool.children[node] { for child := range pool.children[node] {
pool.commit(child, db) if err := pool.commit(child, db); err != nil {
return err
}
}
if err := db.Put(node[:], blob); err != nil {
return err
} }
db.Put(node[:], blob)
delete(pool.cache, node) delete(pool.cache, node)
delete(pool.parents, node) delete(pool.parents, node)
delete(pool.children, node) delete(pool.children, node)
pool.size -= common.StorageSize(common.HashLength + len(blob)) pool.size -= common.StorageSize(common.HashLength + len(blob))
return nil
} }