core, miner: added queued write to WriteBlock

This fixes an issue with the lru cache not being available when calling
WriteBlock. WriteBlock previously always assumed to be called from the
InsertChain where the lru cache was always created prior to calling
WriteBlock. When being called from the worker this could lead in to a
nil pointer exception being thrown and causing database corruption.
This commit is contained in:
Jeffrey Wilcke 2015-06-30 11:14:43 +02:00
parent 7625b07dd9
commit d8fe64acaa
2 changed files with 19 additions and 16 deletions

View File

@ -364,14 +364,12 @@ func (bc *ChainManager) insert(block *types.Block) {
func (bc *ChainManager) write(block *types.Block) { func (bc *ChainManager) write(block *types.Block) {
tstart := time.Now() tstart := time.Now()
go func() { enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block)) key := append(blockHashPre, block.Hash().Bytes()...)
key := append(blockHashPre, block.Hash().Bytes()...) err := bc.blockDb.Put(key, enc)
err := bc.blockDb.Put(key, enc) if err != nil {
if err != nil { glog.Fatal("db write fail:", err)
glog.Fatal("db write fail:", err) }
}
}()
if glog.V(logger.Debug) { if glog.V(logger.Debug) {
glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart)) glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart))
@ -555,7 +553,8 @@ const (
sideStatTy sideStatTy
) )
func (self *ChainManager) WriteBlock(block *types.Block) (status writeStatus, err error) { // WriteBlock writes the block to the chain (or pending queue)
func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status writeStatus, err error) {
self.wg.Add(1) self.wg.Add(1)
defer self.wg.Done() defer self.wg.Done()
@ -587,11 +586,15 @@ func (self *ChainManager) WriteBlock(block *types.Block) (status writeStatus, er
status = sideStatTy status = sideStatTy
} }
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are if queued {
// not in the canonical chain. // Write block to database. Eventually we'll have to improve on this and throw away blocks that are
self.mu.Lock() // not in the canonical chain.
self.enqueueForWrite(block) self.mu.Lock()
self.mu.Unlock() self.enqueueForWrite(block)
self.mu.Unlock()
} else {
self.write(block)
}
// Delete from future blocks // Delete from future blocks
self.futureBlocks.Remove(block.Hash()) self.futureBlocks.Remove(block.Hash())
@ -693,7 +696,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
txcount += len(block.Transactions()) txcount += len(block.Transactions())
// write the block to the chain and get the status // write the block to the chain and get the status
status, err := self.WriteBlock(block) status, err := self.WriteBlock(block, true)
if err != nil { if err != nil {
return i, err return i, err
} }

View File

@ -233,7 +233,7 @@ func (self *worker) wait() {
continue continue
} }
_, err := self.chain.WriteBlock(block) _, err := self.chain.WriteBlock(block, false)
if err != nil { if err != nil {
glog.V(logger.Error).Infoln("error writing block to chain", err) glog.V(logger.Error).Infoln("error writing block to chain", err)
continue continue