From 0b12010d843dc322128807a55f9ae4e2e5747775 Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Mon, 31 Oct 2016 12:09:26 +0000 Subject: [PATCH] eth/trie: Implement upgrade process for direct cache --- eth/db_upgrade.go | 30 +++++++++++++++++++++++++++++- trie/directcache.go | 18 +++++++++--------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/eth/db_upgrade.go b/eth/db_upgrade.go index d53ca2930f..6e2657e010 100644 --- a/eth/db_upgrade.go +++ b/eth/db_upgrade.go @@ -26,11 +26,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" ) var useSequentialKeys = []byte("dbUpgrade_20160530sequentialKeys") @@ -355,6 +357,32 @@ func addMipmapBloomBins(db ethdb.Database) (err error) { return nil } -func populateDirectCache(db ethdb.Database, blockchain *core.BlockChain) error { +func populateDirectCache(db ethdb.Database, bc *core.BlockChain) error { + blockHash, status := trie.GetMigrationState(state.DirectCachePrefix, db) + if status == trie.NotStarted { + blockHash = core.GetHeadBlockHash(db) + status = trie.Running + trie.SetMigrationState(state.DirectCachePrefix, blockHash, status, db) + } + blockNum := core.GetBlockNumber(db, blockHash) + + if status == trie.Running { + tr, err := trie.New(core.GetBlock(db, blockHash, blockNum).Root(), db, 0) + if err != nil { + return err + } + dc := trie.NewDirectCache(tr, db, state.DirectCachePrefix, blockNum, blockHash, bc, false) + go func() { + for core.GetBlockNumber(db, core.GetHeadBlockHash(db)) < blockNum + 8 { + time.Sleep(10 * time.Second) + } + glog.Infof("Beginning direct cache upgrade at block %v", blockNum) + + if err := dc.Populate(); err != nil { + glog.Errorf("Direct cache upgrade failed: %v", err) + } + trie.SetMigrationState(state.DirectCachePrefix, blockHash, trie.Complete, db) + }() + } return nil } diff --git a/trie/directcache.go b/trie/directcache.go index 89825615b3..c7e114c1bc 100644 --- a/trie/directcache.go +++ b/trie/directcache.go @@ -189,7 +189,7 @@ func (dc *DirectCache) Populate() (err error) { it := dc.Iterator() for it.Next() { if err := DirectCacheTransaction(func() error { - if HasDirectCache(dc.keyPrefix, it.Key, dc.db) { + if !HasDirectCache(dc.keyPrefix, it.Key, dc.db) { writes += 1 if err = WriteDirectCache(dc.keyPrefix, it.Key, it.Value, dc.blockNum, dc.blockHash, dc.db); err != nil { return err @@ -202,7 +202,7 @@ func (dc *DirectCache) Populate() (err error) { i += 1 if i % 10000 == 0 && glog.V(logger.Info) { - glog.V(logger.Info).Infof("Constructing direct cache: processed %v entries, writing %v", i, writes) + glog.V(logger.Info).Infof("Constructing direct cache: processed %v entries, written %v", i, writes) } } return nil @@ -271,29 +271,29 @@ func HasDirectCache(prefix, key []byte, db Database) bool { type migrationState struct { Status MigrationStatus - Number uint64 + Hash common.Hash } // GetMigrationState returns the block number of the migration to the direct cache, and // whether or not it's complete. -func GetMigrationState(prefix []byte, db Database) (uint64, MigrationStatus) { +func GetMigrationState(prefix []byte, db Database) (common.Hash, MigrationStatus) { enc, _ := db.Get(append(MigrationPrefix, prefix...)) if len(enc) == 0 { - return 0, NotStarted + return common.Hash{}, NotStarted } var data migrationState if err := rlp.DecodeBytes(enc, &data); err != nil { glog.Errorf("Could not decode migration status: %v", err) - return 0, NotStarted + return common.Hash{}, NotStarted } - return data.Number, data.Status + return data.Hash, data.Status } // SetMigrationState updates the migration state in the database -func SetMigrationState(prefix []byte, blockNum uint64, status MigrationStatus, db Database) error { - enc, _ := rlp.EncodeToBytes(migrationState{status, blockNum}) +func SetMigrationState(prefix []byte, blockHash common.Hash, status MigrationStatus, db Database) error { + enc, _ := rlp.EncodeToBytes(migrationState{status, blockHash}) return db.Put(append(MigrationPrefix, prefix...), enc) }