eth/trie: Implement upgrade process for direct cache

This commit is contained in:
Nick Johnson 2016-10-31 12:09:26 +00:00
parent 548487b968
commit 0b12010d84
2 changed files with 38 additions and 10 deletions

View file

@ -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
}

View file

@ -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)
}