Merge pull request #561 from ethersphere/frontier/blockpool

bugfix with idle too long triggered after peer switch
This commit is contained in:
Felix Lange 2015-03-25 13:55:05 +01:00
commit 7f0c2545a9
3 changed files with 17 additions and 10 deletions

View File

@ -238,12 +238,17 @@ func (self *BlockPool) Start() {
case event := <-self.tdSub.Chan(): case event := <-self.tdSub.Chan():
if ev, ok := event.(core.ChainHeadEvent); ok { if ev, ok := event.(core.ChainHeadEvent); ok {
td := ev.Block.Td td := ev.Block.Td
plog.DebugDetailf("td: %v", td) var height *big.Int
if (ev.Block.HeaderHash == common.Hash{}) {
height = ev.Block.Header().Number
}
plog.DebugDetailf("ChainHeadEvent: height: %v, td: %v, hash: %s", height, td, hex(ev.Block.Hash()))
self.setTD(td) self.setTD(td)
self.peers.lock.Lock() self.peers.lock.Lock()
if best := self.peers.best; best != nil { if best := self.peers.best; best != nil {
if td.Cmp(best.td) >= 0 { // only switch if we strictly go above otherwise we may stall if only
if td.Cmp(best.td) > 0 {
self.peers.best = nil self.peers.best = nil
self.switchPeer(best, nil) self.switchPeer(best, nil)
} }
@ -706,7 +711,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
It activates the section process on incomplete sections with peer. It activates the section process on incomplete sections with peer.
It relinks orphaned sections with their parent if root block (and its parent hash) is known. It relinks orphaned sections with their parent if root block (and its parent hash) is known.
*/ */
func (self *BlockPool) activateChain(sec *section, p *peer, connected map[string]*section) { func (self *BlockPool) activateChain(sec *section, p *peer, connected map[common.Hash]*section) {
p.lock.RLock() p.lock.RLock()
switchC := p.switchC switchC := p.switchC
@ -720,7 +725,7 @@ LOOP:
plog.DebugDetailf("activateChain: section [%s] activated by peer <%s>", sectionhex(sec), p.id) plog.DebugDetailf("activateChain: section [%s] activated by peer <%s>", sectionhex(sec), p.id)
sec.activate(p) sec.activate(p)
if i > 0 && connected != nil { if i > 0 && connected != nil {
connected[sec.top.hash.Str()] = sec connected[sec.top.hash] = sec
} }
/* /*
Need to relink both complete and incomplete sections Need to relink both complete and incomplete sections

View File

@ -356,16 +356,16 @@ func (self *BlockPool) switchPeer(oldp, newp *peer) {
} }
var connected = make(map[string]*section) var connected = make(map[common.Hash]*section)
var sections []common.Hash var sections []common.Hash
for _, hash := range newp.sections { for _, hash := range newp.sections {
plog.DebugDetailf("activate chain starting from section [%s]", hex(hash)) plog.DebugDetailf("activate chain starting from section [%s]", hex(hash))
// if section not connected (ie, top of a contiguous sequence of sections) // if section not connected (ie, top of a contiguous sequence of sections)
if connected[hash.Str()] == nil { if connected[hash] == nil {
// if not deleted, then reread from pool (it can be orphaned top half of a split section) // if not deleted, then reread from pool (it can be orphaned top half of a split section)
if entry := self.get(hash); entry != nil { if entry := self.get(hash); entry != nil {
self.activateChain(entry.section, newp, connected) self.activateChain(entry.section, newp, connected)
connected[hash.Str()] = entry.section connected[hash] = entry.section
sections = append(sections, hash) sections = append(sections, hash)
} }
} }
@ -531,6 +531,7 @@ func (self *peer) run() {
self.blocksRequestTimer = time.After(0) self.blocksRequestTimer = time.After(0)
self.headInfoTimer = time.After(self.bp.Config.BlockHashesTimeout) self.headInfoTimer = time.After(self.bp.Config.BlockHashesTimeout)
self.bestIdleTimer = nil
var ping = time.NewTicker(5 * time.Second) var ping = time.NewTicker(5 * time.Second)
@ -581,7 +582,7 @@ LOOP:
case <-self.bp.quit: case <-self.bp.quit:
break LOOP break LOOP
// quit // best
case <-self.bestIdleTimer: case <-self.bestIdleTimer:
self.peerError(self.bp.peers.errors.New(ErrIdleTooLong, "timed out without providing new blocks (td: %v, head: %s)...quitting", self.td, hex(self.currentBlockHash))) self.peerError(self.bp.peers.errors.New(ErrIdleTooLong, "timed out without providing new blocks (td: %v, head: %s)...quitting", self.td, hex(self.currentBlockHash)))

View File

@ -14,7 +14,7 @@ import (
// the actual tests // the actual tests
func TestAddPeer(t *testing.T) { func TestAddPeer(t *testing.T) {
test.LogInit() test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t) hashPool, blockPool, blockPoolTester := newTestBlockPool(t)
peer0 := blockPoolTester.newPeer("peer0", 1, 1) peer0 := blockPoolTester.newPeer("peer0", 1, 1)
peer1 := blockPoolTester.newPeer("peer1", 2, 2) peer1 := blockPoolTester.newPeer("peer1", 2, 2)
peer2 := blockPoolTester.newPeer("peer2", 3, 3) peer2 := blockPoolTester.newPeer("peer2", 3, 3)
@ -119,7 +119,8 @@ func TestAddPeer(t *testing.T) {
} }
peer0.waitBlocksRequests(3) peer0.waitBlocksRequests(3)
newblock := &types.Block{Td: common.Big3} hash := hashPool.IndexesToHashes([]int{0})[0]
newblock := &types.Block{Td: common.Big3, HeaderHash: hash}
blockPool.chainEvents.Post(core.ChainHeadEvent{newblock}) blockPool.chainEvents.Post(core.ChainHeadEvent{newblock})
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
if blockPool.peers.best != nil { if blockPool.peers.best != nil {