Merge pull request #1021 from obscuren/global_chain_lock
core: global chain insert lock
This commit is contained in:
		
						commit
						443d024843
					
				| @ -83,8 +83,9 @@ type ChainManager struct { | |||||||
| 	eventMux     *event.TypeMux | 	eventMux     *event.TypeMux | ||||||
| 	genesisBlock *types.Block | 	genesisBlock *types.Block | ||||||
| 	// Last known total difficulty
 | 	// Last known total difficulty
 | ||||||
| 	mu   sync.RWMutex | 	mu      sync.RWMutex | ||||||
| 	tsmu sync.RWMutex | 	chainmu sync.RWMutex | ||||||
|  | 	tsmu    sync.RWMutex | ||||||
| 
 | 
 | ||||||
| 	td              *big.Int | 	td              *big.Int | ||||||
| 	currentBlock    *types.Block | 	currentBlock    *types.Block | ||||||
| @ -518,6 +519,9 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { | |||||||
| 	self.wg.Add(1) | 	self.wg.Add(1) | ||||||
| 	defer self.wg.Done() | 	defer self.wg.Done() | ||||||
| 
 | 
 | ||||||
|  | 	self.chainmu.Lock() | ||||||
|  | 	defer self.chainmu.Unlock() | ||||||
|  | 
 | ||||||
| 	// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
 | 	// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
 | ||||||
| 	var ( | 	var ( | ||||||
| 		queue      = make([]interface{}, len(chain)) | 		queue      = make([]interface{}, len(chain)) | ||||||
| @ -542,7 +546,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { | |||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			block.Td = new(big.Int) |  | ||||||
| 			// Do not penelise on future block. We'll need a block queue eventually that will queue
 | 			// Do not penelise on future block. We'll need a block queue eventually that will queue
 | ||||||
| 			// future block for future use
 | 			// future block for future use
 | ||||||
| 			if err == BlockFutureErr { | 			if err == BlockFutureErr { | ||||||
| @ -568,54 +571,50 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { | |||||||
| 			return i, err | 			return i, err | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		self.mu.Lock() | 		cblock := self.currentBlock | ||||||
| 		{ | 		// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
 | ||||||
| 			cblock := self.currentBlock | 		// not in the canonical chain.
 | ||||||
| 			// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
 | 		self.write(block) | ||||||
| 			// not in the canonical chain.
 | 		// Compare the TD of the last known block in the canonical chain to make sure it's greater.
 | ||||||
| 			self.write(block) | 		// At this point it's possible that a different chain (fork) becomes the new canonical chain.
 | ||||||
| 			// Compare the TD of the last known block in the canonical chain to make sure it's greater.
 | 		if block.Td.Cmp(self.td) > 0 { | ||||||
| 			// At this point it's possible that a different chain (fork) becomes the new canonical chain.
 | 			// chain fork
 | ||||||
| 			if block.Td.Cmp(self.td) > 0 { | 			if block.ParentHash() != cblock.Hash() { | ||||||
| 				// chain fork
 | 				// during split we merge two different chains and create the new canonical chain
 | ||||||
| 				if block.ParentHash() != cblock.Hash() { | 				self.merge(cblock, block) | ||||||
| 					// during split we merge two different chains and create the new canonical chain
 |  | ||||||
| 					self.merge(cblock, block) |  | ||||||
| 
 | 
 | ||||||
| 					queue[i] = ChainSplitEvent{block, logs} | 				queue[i] = ChainSplitEvent{block, logs} | ||||||
| 					queueEvent.splitCount++ | 				queueEvent.splitCount++ | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				self.setTotalDifficulty(block.Td) |  | ||||||
| 				self.insert(block) |  | ||||||
| 
 |  | ||||||
| 				jsonlogger.LogJson(&logger.EthChainNewHead{ |  | ||||||
| 					BlockHash:     block.Hash().Hex(), |  | ||||||
| 					BlockNumber:   block.Number(), |  | ||||||
| 					ChainHeadHash: cblock.Hash().Hex(), |  | ||||||
| 					BlockPrevHash: block.ParentHash().Hex(), |  | ||||||
| 				}) |  | ||||||
| 
 |  | ||||||
| 				self.setTransState(state.New(block.Root(), self.stateDb)) |  | ||||||
| 				self.txState.SetState(state.New(block.Root(), self.stateDb)) |  | ||||||
| 
 |  | ||||||
| 				queue[i] = ChainEvent{block, block.Hash(), logs} |  | ||||||
| 				queueEvent.canonicalCount++ |  | ||||||
| 
 |  | ||||||
| 				if glog.V(logger.Debug) { |  | ||||||
| 					glog.Infof("[%v] inserted block #%d (%d TXs %d UNCs) (%x...)\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4]) |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				if glog.V(logger.Detail) { |  | ||||||
| 					glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...)\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4]) |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				queue[i] = ChainSideEvent{block, logs} |  | ||||||
| 				queueEvent.sideCount++ |  | ||||||
| 			} | 			} | ||||||
| 			self.futureBlocks.Delete(block.Hash()) | 
 | ||||||
|  | 			self.setTotalDifficulty(block.Td) | ||||||
|  | 			self.insert(block) | ||||||
|  | 
 | ||||||
|  | 			jsonlogger.LogJson(&logger.EthChainNewHead{ | ||||||
|  | 				BlockHash:     block.Hash().Hex(), | ||||||
|  | 				BlockNumber:   block.Number(), | ||||||
|  | 				ChainHeadHash: cblock.Hash().Hex(), | ||||||
|  | 				BlockPrevHash: block.ParentHash().Hex(), | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			self.setTransState(state.New(block.Root(), self.stateDb)) | ||||||
|  | 			self.txState.SetState(state.New(block.Root(), self.stateDb)) | ||||||
|  | 
 | ||||||
|  | 			queue[i] = ChainEvent{block, block.Hash(), logs} | ||||||
|  | 			queueEvent.canonicalCount++ | ||||||
|  | 
 | ||||||
|  | 			if glog.V(logger.Debug) { | ||||||
|  | 				glog.Infof("[%v] inserted block #%d (%d TXs %d UNCs) (%x...)\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4]) | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if glog.V(logger.Detail) { | ||||||
|  | 				glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...)\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4]) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			queue[i] = ChainSideEvent{block, logs} | ||||||
|  | 			queueEvent.sideCount++ | ||||||
| 		} | 		} | ||||||
| 		self.mu.Unlock() | 		self.futureBlocks.Delete(block.Hash()) | ||||||
| 
 | 
 | ||||||
| 		stats.processed++ | 		stats.processed++ | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user