diff --git a/core/state/statedb.go b/core/state/statedb.go index fe29e318a5..6a35e2d425 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -42,7 +42,6 @@ var StartingNonce uint64 var MaxTrieCacheGen = uint16(120) var DirectCachePrefix = []byte("accounthashcache:") -var DirectStateCacheCompleteKey = []byte("directstatecache:complete") const ( // Number of past tries to keep. This value is chosen such that @@ -193,12 +192,12 @@ func (self *StateDB) SetBlockContext(blockHash common.Hash, blockNum uint64, val // Check if cache population has completed if !self.cacheComplete { - if value, err := self.db.Get(DirectStateCacheCompleteKey); err == nil && value != nil { + if _, status := trie.GetMigrationState(DirectCachePrefix, self.db); status == trie.Complete { self.cacheComplete = true } } - storage := trie.NewDirectCache(self.trie, self.db, DirectCachePrefix, blockNum, blockHash, validator, true) + storage := trie.NewDirectCache(self.trie, self.db, DirectCachePrefix, blockNum, blockHash, validator, self.cacheComplete) self.storage = trie.NewSecure(storage, self.db) } diff --git a/eth/db_upgrade.go b/eth/db_upgrade.go index f7ba391576..d53ca2930f 100644 --- a/eth/db_upgrade.go +++ b/eth/db_upgrade.go @@ -355,9 +355,6 @@ func addMipmapBloomBins(db ethdb.Database) (err error) { return nil } -//struct upgradeState - func populateDirectCache(db ethdb.Database, blockchain *core.BlockChain) error { - return nil } diff --git a/trie/directcache.go b/trie/directcache.go index 84b555be13..89825615b3 100644 --- a/trie/directcache.go +++ b/trie/directcache.go @@ -30,13 +30,22 @@ import ( ) var ( - directCacheLock = &sync.Mutex{} - directCacheLocked = false - directCacheWrites = metrics.NewCounter("directcache/writes") - directCacheHits = metrics.NewCounter("directcache/hits") - directCacheMisses = metrics.NewCounter("directcache/misses") - directCacheTimer = metrics.NewTimer("directcache/timer") - NotFound = errors.New("Cache entry not found") + directCacheLock = &sync.Mutex{} + directCacheLocked = false + directCacheWrites = metrics.NewCounter("directcache/writes") + directCacheHits = metrics.NewCounter("directcache/hits") + directCacheMisses = metrics.NewCounter("directcache/misses") + directCacheTimer = metrics.NewTimer("directcache/timer") + NotFound = errors.New("Cache entry not found") + MigrationPrefix = []byte("directstatecachemigration:") +) + +type MigrationStatus int + +const ( + NotStarted = iota + Running = iota + Complete = iota ) // CacheValidator can check whether a certain block is in the current canonical chain. @@ -206,10 +215,6 @@ type cachedValue struct { } func DirectCacheTransaction(tx func() (error)) error { - if directCacheLocked { - return fmt.Errorf("Reentrant calls to DirectCacheTransaction are not permitted") - } - directCacheLock.Lock() directCacheLocked = true defer func() { @@ -250,7 +255,7 @@ func GetDirectCache(prefix, key []byte, db Database) ([]byte, uint64, common.Has } var data cachedValue - if err := rlp.DecodeBytes(enc, &data); err != nil && glog.V(logger.Error) { + if err := rlp.DecodeBytes(enc, &data); err != nil { return nil, 0, common.Hash{}, fmt.Errorf("Can't decode cached object at %x: %v", key, err) } return data.Value, data.BlockNum, data.BlockHash, nil @@ -264,6 +269,34 @@ func HasDirectCache(prefix, key []byte, db Database) bool { return false } +type migrationState struct { + Status MigrationStatus + Number uint64 +} + +// 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) { + enc, _ := db.Get(append(MigrationPrefix, prefix...)) + if len(enc) == 0 { + return 0, 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 data.Number, 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}) + return db.Put(append(MigrationPrefix, prefix...), enc) +} + // DirectCacheReads retrieves a global counter measuring the number of direct // cache reads from the disk since process startup. This isn't useful for anything // apart from trie debugging purposes.