This commit is contained in:
Jeffrey Wilcke 2015-07-17 15:43:16 +02:00
parent a75b95b876
commit 4a472a8b54
7 changed files with 53 additions and 31 deletions

View file

@ -43,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/trie"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
) )
@ -338,6 +339,10 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
func main() { func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
defer logger.Flush() defer logger.Flush()
defer func() {
fmt.Println("written using the trie:", trie.Written, "bytes")
fmt.Println("written by the database:", ethdb.Written, "bytes")
}()
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
os.Exit(1) os.Exit(1)

View file

@ -73,9 +73,6 @@ type ChainManager struct {
lastBlockHash common.Hash lastBlockHash common.Hash
currentGasLimit *big.Int currentGasLimit *big.Int
transState *state.StateDB
txState *state.ManagedState
cache *lru.Cache // cache is the LRU caching cache *lru.Cache // cache is the LRU caching
futureBlocks *lru.Cache // future blocks are blocks added for later processing futureBlocks *lru.Cache // future blocks are blocks added for later processing
@ -128,9 +125,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux
} }
} }
bc.transState = bc.State().Copy()
// Take ownership of this particular state // Take ownership of this particular state
bc.txState = state.ManageState(bc.State().Copy())
bc.futureBlocks, _ = lru.New(maxFutureBlocks) bc.futureBlocks, _ = lru.New(maxFutureBlocks)
bc.makeCache() bc.makeCache()
@ -152,9 +147,6 @@ func (bc *ChainManager) SetHead(head *types.Block) {
bc.currentBlock = head bc.currentBlock = head
bc.makeCache() bc.makeCache()
statedb := state.New(head.Root(), bc.stateDb)
bc.txState = state.ManageState(statedb)
bc.transState = statedb.Copy()
bc.setTotalDifficulty(head.Td) bc.setTotalDifficulty(head.Td)
bc.insert(head) bc.insert(head)
bc.setLastState() bc.setLastState()
@ -203,17 +195,6 @@ func (self *ChainManager) State() *state.StateDB {
return state.New(self.CurrentBlock().Root(), self.stateDb) return state.New(self.CurrentBlock().Root(), self.stateDb)
} }
func (self *ChainManager) TransState() *state.StateDB {
self.tsmu.RLock()
defer self.tsmu.RUnlock()
return self.transState
}
func (self *ChainManager) setTransState(statedb *state.StateDB) {
self.transState = statedb
}
func (bc *ChainManager) recover() bool { func (bc *ChainManager) recover() bool {
data, _ := bc.blockDb.Get([]byte("checkpoint")) data, _ := bc.blockDb.Get([]byte("checkpoint"))
if len(data) != 0 { if len(data) != 0 {
@ -529,9 +510,6 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr
self.insert(block) self.insert(block)
self.mu.Unlock() self.mu.Unlock()
self.setTransState(state.New(block.Root(), self.stateDb))
self.txState.SetState(state.New(block.Root(), self.stateDb))
status = CanonStatTy status = CanonStatTy
} else { } else {
status = SideStatTy status = SideStatTy

View file

@ -19,9 +19,11 @@ package core
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/syndtr/goleveldb/leveldb"
) )
var ( var (
@ -31,13 +33,21 @@ var (
// PutTransactions stores the transactions in the given database // PutTransactions stores the transactions in the given database
func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) {
batch := new(leveldb.Batch)
_, batchWrite := db.(*ethdb.LDBDatabase)
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
rlpEnc, err := rlp.EncodeToBytes(tx) rlpEnc, err := rlp.EncodeToBytes(tx)
if err != nil { if err != nil {
glog.V(logger.Debug).Infoln("Failed encoding tx", err) glog.V(logger.Debug).Infoln("Failed encoding tx", err)
return return
} }
if batchWrite {
batch.Put(tx.Hash().Bytes(), rlpEnc)
} else {
db.Put(tx.Hash().Bytes(), rlpEnc) db.Put(tx.Hash().Bytes(), rlpEnc)
}
var txExtra struct { var txExtra struct {
BlockHash common.Hash BlockHash common.Hash
@ -52,23 +62,47 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti
glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err)
return return
} }
if batchWrite {
batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
} else {
db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
} }
} }
if db, ok := db.(*ethdb.LDBDatabase); ok {
if err := db.LDB().Write(batch, nil); err != nil {
glog.V(logger.Error).Infoln("db write err:", err)
}
}
}
// PutReceipts stores the receipts in the current database // PutReceipts stores the receipts in the current database
func PutReceipts(db common.Database, receipts types.Receipts) error { func PutReceipts(db common.Database, receipts types.Receipts) error {
batch := new(leveldb.Batch)
_, batchWrite := db.(*ethdb.LDBDatabase)
for _, receipt := range receipts { for _, receipt := range receipts {
storageReceipt := (*types.ReceiptForStorage)(receipt) storageReceipt := (*types.ReceiptForStorage)(receipt)
bytes, err := rlp.EncodeToBytes(storageReceipt) bytes, err := rlp.EncodeToBytes(storageReceipt)
if err != nil { if err != nil {
return err return err
} }
if batchWrite {
batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
} else {
err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
if err != nil { if err != nil {
return err return err
} }
} }
}
if db, ok := db.(*ethdb.LDBDatabase); ok {
if err := db.LDB().Write(batch, nil); err != nil {
return err
}
}
return nil return nil
} }

View file

@ -34,6 +34,8 @@ import (
gometrics "github.com/rcrowley/go-metrics" gometrics "github.com/rcrowley/go-metrics"
) )
var Written uint64
var OpenFileLimit = 64 var OpenFileLimit = 64
type LDBDatabase struct { type LDBDatabase struct {
@ -59,7 +61,7 @@ type LDBDatabase struct {
// when data needs to be stored and written to disk. // when data needs to be stored and written to disk.
func NewLDBDatabase(file string) (*LDBDatabase, error) { func NewLDBDatabase(file string) (*LDBDatabase, error) {
// Open the db // Open the db
db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit}) db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit, BlockSize: 1 * opt.KiB})
// check for corruption and attempt to recover // check for corruption and attempt to recover
if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted {
db, err = leveldb.RecoverFile(file, nil) db, err = leveldb.RecoverFile(file, nil)
@ -76,6 +78,7 @@ func NewLDBDatabase(file string) (*LDBDatabase, error) {
// Put puts the given key / value to the queue // Put puts the given key / value to the queue
func (self *LDBDatabase) Put(key []byte, value []byte) error { func (self *LDBDatabase) Put(key []byte, value []byte) error {
Written += uint64(len(value))
// Measure the database put latency, if requested // Measure the database put latency, if requested
if self.putTimer != nil { if self.putTimer != nil {
defer self.putTimer.UpdateSince(time.Now()) defer self.putTimer.UpdateSince(time.Now())

View file

@ -42,5 +42,5 @@ func (self *HashNode) setDirty(dirty bool) {
// These methods will never be called but we have to satisfy Node interface // These methods will never be called but we have to satisfy Node interface
func (self *HashNode) Value() Node { return nil } func (self *HashNode) Value() Node { return nil }
func (self *HashNode) Dirty() bool { return true } func (self *HashNode) Dirty() bool { return false }
func (self *HashNode) Copy(t *Trie) Node { return NewHash(common.CopyBytes(self.key), t) } func (self *HashNode) Copy(t *Trie) Node { return NewHash(common.CopyBytes(self.key), t) }

View file

@ -27,6 +27,8 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var Written uint64
func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) { func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) {
t2 := New(nil, backend) t2 := New(nil, backend)
@ -373,9 +375,9 @@ func (self *Trie) store(node Node) interface{} {
if len(data) >= 32 { if len(data) >= 32 {
key := crypto.Sha3(data) key := crypto.Sha3(data)
if node.Dirty() { if node.Dirty() {
//fmt.Println("save", node) Written += uint64(len(data))
//fmt.Println()
self.cache.Put(key, data) self.cache.Put(key, data)
node.setDirty(false)
} }
return key return key

View file

@ -123,7 +123,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
if frontend == nil { if frontend == nil {
xeth.frontend = dummyFrontend{} xeth.frontend = dummyFrontend{}
} }
xeth.state = NewState(xeth, xeth.backend.ChainManager().TransState()) xeth.state = NewState(xeth, xeth.backend.ChainManager().State())
go xeth.start() go xeth.start()
go xeth.filterManager.Start() go xeth.filterManager.Start()