- fix peer disconnect by adding severity function to errs

- improve logging
- suicide -> removeChain
- improved status BlocksInPool calculation
This commit is contained in:
zelig 2015-03-03 00:43:12 +07:00
parent 16ecda951b
commit a60a18b080
4 changed files with 55 additions and 38 deletions

View File

@ -149,6 +149,15 @@ func New(
} }
} }
func severity(code int) ethlogger.LogLevel {
switch code {
case ErrUnrequestedBlock:
return ethlogger.WarnLevel
default:
return ethlogger.ErrorLevel
}
}
// allows restart // allows restart
func (self *BlockPool) Start() { func (self *BlockPool) Start() {
self.lock.Lock() self.lock.Lock()
@ -169,6 +178,7 @@ func (self *BlockPool) Start() {
errors: &errs.Errors{ errors: &errs.Errors{
Package: "Blockpool", Package: "Blockpool",
Errors: errorToString, Errors: errorToString,
Level: severity,
}, },
peers: make(map[string]*peer), peers: make(map[string]*peer),
status: self.status, status: self.status,
@ -363,6 +373,8 @@ LOOP:
// check if known block connecting the downloaded chain to our blockchain // check if known block connecting the downloaded chain to our blockchain
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found block %s in the blockchain", peerId, hex(bestpeer.currentBlockHash), hex(hash)) plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found block %s in the blockchain", peerId, hex(bestpeer.currentBlockHash), hex(hash))
if len(nodes) == 1 { if len(nodes) == 1 {
plog.DebugDetailf("AddBlockHashes: singleton section pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain", peerId, hex(bestpeer.currentBlockHash), hex(hash))
// create new section if needed and push it to the blockchain // create new section if needed and push it to the blockchain
sec = self.newSection(nodes) sec = self.newSection(nodes)
sec.addSectionToBlockChain(bestpeer) sec.addSectionToBlockChain(bestpeer)
@ -379,6 +391,8 @@ LOOP:
and td together with blockBy are recorded on the node and td together with blockBy are recorded on the node
*/ */
if len(nodes) == 0 && child != nil { if len(nodes) == 0 && child != nil {
plog.DebugDetailf("AddBlockHashes: child section [%s] pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain", sectionhex(child), peerId, hex(bestpeer.currentBlockHash), hex(hash))
child.addSectionToBlockChain(bestpeer) child.addSectionToBlockChain(bestpeer)
} }
} }
@ -446,10 +460,12 @@ LOOP:
*/ */
sec = self.linkSections(nodes, parent, child) sec = self.linkSections(nodes, parent, child)
self.status.lock.Lock() if sec != nil {
self.status.values.BlockHashes += len(nodes) self.status.lock.Lock()
self.status.lock.Unlock() self.status.values.BlockHashes += len(nodes)
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s): section [%s] created", peerId, hex(bestpeer.currentBlockHash), sectionhex(sec)) self.status.lock.Unlock()
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s): section [%s] created", peerId, hex(bestpeer.currentBlockHash), sectionhex(sec))
}
self.chainLock.Unlock() self.chainLock.Unlock()
@ -549,6 +565,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
self.status.lock.Unlock() self.status.lock.Unlock()
} else { } else {
plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(sender.currentBlockHash)) plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(sender.currentBlockHash))
sender.currentBlockC <- block
} }
} else { } else {
@ -644,11 +661,15 @@ LOOP:
we need to relink both complete and incomplete sections we need to relink both complete and incomplete sections
the latter could have been blockHashesRequestsComplete before being delinked from its parent the latter could have been blockHashesRequestsComplete before being delinked from its parent
*/ */
if parent == nil && sec.bottom.block != nil { if parent == nil {
if entry := self.get(sec.bottom.block.ParentHash()); entry != nil { if sec.bottom.block != nil {
parent = entry.section if entry := self.get(sec.bottom.block.ParentHash()); entry != nil {
plog.DebugDetailf("activateChain: [%s]-[%s] relink", sectionhex(parent), sectionhex(sec)) parent = entry.section
link(parent, sec) plog.DebugDetailf("activateChain: [%s]-[%s] link", sectionhex(parent), sectionhex(sec))
link(parent, sec)
}
} else {
plog.DebugDetailf("activateChain: section [%s] activated by peer <%s> has missing root block", sectionhex(sec), p.id)
} }
} }
sec = parent sec = parent
@ -704,9 +725,15 @@ func (self *BlockPool) remove(sec *section) {
// delete node entries from pool index under pool lock // delete node entries from pool index under pool lock
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
for _, node := range sec.nodes { for _, node := range sec.nodes {
delete(self.pool, string(node.hash)) delete(self.pool, string(node.hash))
} }
if sec.initialised && sec.poolRootIndex != 0 {
self.status.lock.Lock()
self.status.values.BlocksInPool -= len(sec.nodes) - sec.missing
self.status.lock.Unlock()
}
} }
func (self *BlockPool) getHashSlice() (s [][]byte) { func (self *BlockPool) getHashSlice() (s [][]byte) {

View File

@ -503,7 +503,7 @@ LOOP:
// quitting on timeout // quitting on timeout
case <-self.suicide: case <-self.suicide:
self.peerError(self.bp.peers.errors.New(ErrInsufficientChainInfo, "timed out without providing block hashes or head block", currentBlockHash)) self.peerError(self.bp.peers.errors.New(ErrInsufficientChainInfo, "timed out without providing block hashes or head block %x", currentBlockHash))
self.bp.status.lock.Lock() self.bp.status.lock.Lock()
self.bp.status.badPeers[self.id]++ self.bp.status.badPeers[self.id]++

View File

@ -138,7 +138,7 @@ func (self *section) addSectionToBlockChain(p *peer) {
plog.Warnf("penalise peers %v (hash), %v (block)", node.hashBy, node.blockBy) plog.Warnf("penalise peers %v (hash), %v (block)", node.hashBy, node.blockBy)
// or invalid block and the entire chain needs to be removed // or invalid block and the entire chain needs to be removed
self.removeInvalidChain() self.removeChain()
} else { } else {
// if all blocks inserted in this section // if all blocks inserted in this section
// then need to try to insert blocks in child section // then need to try to insert blocks in child section
@ -235,16 +235,14 @@ LOOP:
// timebomb - if section is not complete in time, nuke the entire chain // timebomb - if section is not complete in time, nuke the entire chain
case <-self.suicideTimer: case <-self.suicideTimer:
self.suicide() self.removeChain()
plog.Debugf("[%s] timeout. (%v total attempts): missing %v/%v/%v...suicide", sectionhex(self), self.blocksRequests, self.missing, self.lastMissing, self.depth) plog.Debugf("[%s] timeout. (%v total attempts): missing %v/%v/%v...suicide", sectionhex(self), self.blocksRequests, self.missing, self.lastMissing, self.depth)
self.suicideTimer = nil self.suicideTimer = nil
break LOOP
// closing suicideC triggers section suicide: removes section nodes from pool and terminates section process // closing suicideC triggers section suicide: removes section nodes from pool and terminates section process
case <-self.suicideC: case <-self.suicideC:
plog.DebugDetailf("[%s] suicide", sectionhex(self)) plog.DebugDetailf("[%s] quit", sectionhex(self))
self.unlink()
self.bp.remove(self)
plog.DebugDetailf("[%s] done", sectionhex(self))
break LOOP break LOOP
// alarm for checking blocks in the section // alarm for checking blocks in the section
@ -283,7 +281,7 @@ LOOP:
checking = false checking = false
break break
} }
plog.DebugDetailf("[%s] section proc step %v: missing %v/%v/%v", sectionhex(self), self.step, self.missing, self.lastMissing, self.depth) // plog.DebugDetailf("[%s] section proc step %v: missing %v/%v/%v", sectionhex(self), self.step, self.missing, self.lastMissing, self.depth)
if !checking { if !checking {
self.step = 0 self.step = 0
self.missing = 0 self.missing = 0
@ -522,7 +520,7 @@ func (self *section) checkRound() {
// too many idle rounds // too many idle rounds
if self.idle >= self.bp.Config.BlocksRequestMaxIdleRounds { if self.idle >= self.bp.Config.BlocksRequestMaxIdleRounds {
plog.DebugDetailf("[%s] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up...", sectionhex(self), self.idle, self.blocksRequests, self.missing, self.lastMissing, self.depth) plog.DebugDetailf("[%s] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up...", sectionhex(self), self.idle, self.blocksRequests, self.missing, self.lastMissing, self.depth)
self.suicide() self.removeChain()
} }
} else { } else {
self.idle = 0 self.idle = 0
@ -602,10 +600,12 @@ func (self *BlockPool) linkSections(nodes []*node, parent, child *section) (sec
link(parent, sec) link(parent, sec)
link(sec, child) link(sec, child)
} else { } else {
// now this can only happen if we allow response to hash request to include <from> hash if parent != nil && child != nil {
// in this case we just link parent and child (without needing root block of child section) // now this can only happen if we allow response to hash request to include <from> hash
plog.Debugf("[%s]->[%s] connecting known sections", sectionhex(parent), sectionhex(child)) // in this case we just link parent and child (without needing root block of child section)
link(parent, child) plog.Debugf("[%s]->[%s] connecting known sections", sectionhex(parent), sectionhex(child))
link(parent, child)
}
} }
return return
} }
@ -614,6 +614,7 @@ func (self *section) activate(p *peer) {
self.bp.wg.Add(1) self.bp.wg.Add(1)
select { select {
case <-self.offC: case <-self.offC:
plog.DebugDetailf("[%s] completed section process. cannot activate for peer <%s>", sectionhex(self), p.id)
self.bp.wg.Done() self.bp.wg.Done()
case self.controlC <- p: case self.controlC <- p:
plog.DebugDetailf("[%s] activate section process for peer <%s>", sectionhex(self), p.id) plog.DebugDetailf("[%s] activate section process for peer <%s>", sectionhex(self), p.id)
@ -625,22 +626,10 @@ func (self *section) deactivate() {
self.controlC <- nil self.controlC <- nil
} }
func (self *section) suicide() {
select {
case <-self.suicideC:
return
default:
}
close(self.suicideC)
}
// removes this section exacly // removes this section exacly
func (self *section) remove() { func (self *section) remove() {
select { select {
case <-self.offC: case <-self.offC:
// section is complete, no process
self.unlink()
self.bp.remove(self)
close(self.suicideC) close(self.suicideC)
plog.DebugDetailf("[%s] remove: suicide", sectionhex(self)) plog.DebugDetailf("[%s] remove: suicide", sectionhex(self))
case <-self.suicideC: case <-self.suicideC:
@ -649,21 +638,23 @@ func (self *section) remove() {
plog.DebugDetailf("[%s] remove: suicide", sectionhex(self)) plog.DebugDetailf("[%s] remove: suicide", sectionhex(self))
close(self.suicideC) close(self.suicideC)
} }
self.unlink()
self.bp.remove(self)
plog.DebugDetailf("[%s] removed section.", sectionhex(self)) plog.DebugDetailf("[%s] removed section.", sectionhex(self))
} }
// remove a section and all its descendents from the pool // remove a section and all its descendents from the pool
func (self *section) removeInvalidChain() { func (self *section) removeChain() {
// need to get the child before removeSection delinks the section // need to get the child before removeSection delinks the section
self.bp.chainLock.RLock() self.bp.chainLock.RLock()
child := self.child child := self.child
self.bp.chainLock.RUnlock() self.bp.chainLock.RUnlock()
plog.DebugDetailf("[%s] remove invalid chain", sectionhex(self)) plog.DebugDetailf("[%s] remove chain", sectionhex(self))
self.remove() self.remove()
if child != nil { if child != nil {
child.removeInvalidChain() child.removeChain()
} }
} }

View File

@ -51,7 +51,6 @@ type Status struct {
func (self *BlockPool) Status() *Status { func (self *BlockPool) Status() *Status {
self.status.lock.Lock() self.status.lock.Lock()
defer self.status.lock.Unlock() defer self.status.lock.Unlock()
self.status.values.BlockHashesInPool = len(self.pool)
self.status.values.ActivePeers = len(self.status.activePeers) self.status.values.ActivePeers = len(self.status.activePeers)
self.status.values.BestPeers = len(self.status.bestPeers) self.status.values.BestPeers = len(self.status.bestPeers)
self.status.values.BadPeers = len(self.status.badPeers) self.status.values.BadPeers = len(self.status.badPeers)