AddBlockHashes call uses lazy rlp decoding so it cannot be async since message is discarded by protocol

This commit is contained in:
zelig 2015-01-03 03:41:29 +00:00
parent b768d14620
commit 60d73fa261

View file

@ -322,118 +322,118 @@ func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string)
// peer is still the best // peer is still the best
poolLogger.Debugf("adding hashes for best peer %s", peerId) poolLogger.Debugf("adding hashes for best peer %s", peerId)
self.wg.Add(1) // self.wg.Add(1)
self.procWg.Add(1) // self.procWg.Add(1)
go func() { // go func() {
var size, n int var size, n int
var hash []byte var hash []byte
var ok bool = true var ok bool = true
var section, child, parent *section var section, child, parent *section
var entry *poolEntry var entry *poolEntry
var nodes []*poolNode var nodes []*poolNode
LOOP: LOOP:
// iterate using next (rlp stream lazy decoder) feeding hashesC // iterate using next (rlp stream lazy decoder) feeding hashesC
for hash, ok = next(); ok; hash, ok = next() { for hash, ok = next(); ok; hash, ok = next() {
n++ n++
select { select {
case <-self.quit: case <-self.quit:
break LOOP break LOOP
case <-peer.quitC: case <-peer.quitC:
// if the peer is demoted, no more hashes taken // if the peer is demoted, no more hashes taken
break LOOP break LOOP
default: default:
} }
if self.hasBlock(hash) { if self.hasBlock(hash) {
// check if known block connecting the downloaded chain to our blockchain // check if known block connecting the downloaded chain to our blockchain
poolLogger.Debugf("[%s] known block", name(hash)) poolLogger.Debugf("[%s] known block", name(hash))
// mark child as absolute pool root with parent known to blockchain // mark child as absolute pool root with parent known to blockchain
if section != nil { if section != nil {
self.connectToBlockChain(section) self.connectToBlockChain(section)
} else { } else {
if child != nil { if child != nil {
self.connectToBlockChain(child) self.connectToBlockChain(child)
}
} }
break LOOP
} }
// look up node in pool break LOOP
entry = self.get(hash) }
if entry != nil { // look up node in pool
poolLogger.Debugf("[%s] found block", name(hash)) entry = self.get(hash)
// reached a known chain in the pool if entry != nil {
if entry.node == entry.section.bottom && n == 1 { poolLogger.Debugf("[%s] found block", name(hash))
// the first block hash received is an orphan in the pool, so rejoice and continue // reached a known chain in the pool
poolLogger.Debugf("[%s] first hash is orphan block, keep building", name(hash)) if entry.node == entry.section.bottom && n == 1 {
child = entry.section // the first block hash received is an orphan in the pool, so rejoice and continue
continue LOOP poolLogger.Debugf("[%s] first hash is orphan block, keep building", name(hash))
} child = entry.section
poolLogger.Debugf("[%s] reached blockpool chain", name(hash)) continue LOOP
parent = entry.section
break LOOP
} }
// if node for block hash does not exist, create it and index in the pool poolLogger.Debugf("[%s] reached blockpool chain", name(hash))
poolLogger.Debugf("[%s] create node %v", name(hash), size) parent = entry.section
node := &poolNode{ break LOOP
hash: hash,
peer: peerId,
}
if size == 0 {
section = newSection()
}
nodes = append(nodes, node)
size++
} //for
self.chainLock.Lock()
poolLogger.Debugf("lock chain lock")
poolLogger.Debugf("read %v hashes added by %s", n, peerId)
if parent != nil && entry != nil && entry.node != parent.top {
poolLogger.Debugf("[%s] fork section", sectionName(parent))
parent.controlC <- false
waiter := make(chan bool)
parent.forkC <- waiter
chain := parent.nodes
parent.nodes = chain[entry.index:]
parent.top = parent.nodes[0]
orphan := newSection()
self.link(orphan, parent.child)
self.processSection(orphan, chain[0:entry.index])
orphan.controlC <- false
close(waiter)
} }
// if node for block hash does not exist, create it and index in the pool
if size > 0 { poolLogger.Debugf("[%s] create node %v", name(hash), size)
self.processSection(section, nodes) node := &poolNode{
poolLogger.Debugf("[%s]->[%s](%v)->[%s] new chain section", sectionName(parent), sectionName(section), size, sectionName(child)) hash: hash,
self.link(parent, section) peer: peerId,
self.link(section, child)
} else {
poolLogger.Debugf("[%s]->[%s] connecting known sections", sectionName(parent), sectionName(child))
self.link(parent, child)
} }
if size == 0 {
self.chainLock.Unlock() section = newSection()
poolLogger.Debugf("[%s] unlock chain lock", sectionName(section))
if parent != nil {
poolLogger.Debugf("[%s] activating parent chain [%s]...", name(parent.top.hash), sectionName(parent))
self.activateChain(parent, peer)
poolLogger.Debugf("[%s] activated parent chain [%s]. done", name(parent.top.hash), sectionName(parent))
} }
nodes = append(nodes, node)
size++
} //for
if section != nil { self.chainLock.Lock()
poolLogger.Debugf("[%s] activate new section process", sectionName(section)) poolLogger.Debugf("lock chain lock")
peer.addSection(section.top.hash, section)
section.controlC <- true
}
self.procWg.Done()
self.wg.Done()
}() poolLogger.Debugf("read %v hashes added by %s", n, peerId)
if parent != nil && entry != nil && entry.node != parent.top {
poolLogger.Debugf("[%s] fork section", sectionName(parent))
parent.controlC <- false
waiter := make(chan bool)
parent.forkC <- waiter
chain := parent.nodes
parent.nodes = chain[entry.index:]
parent.top = parent.nodes[0]
orphan := newSection()
self.link(orphan, parent.child)
self.processSection(orphan, chain[0:entry.index])
orphan.controlC <- false
close(waiter)
}
if size > 0 {
self.processSection(section, nodes)
poolLogger.Debugf("[%s]->[%s](%v)->[%s] new chain section", sectionName(parent), sectionName(section), size, sectionName(child))
self.link(parent, section)
self.link(section, child)
} else {
poolLogger.Debugf("[%s]->[%s] connecting known sections", sectionName(parent), sectionName(child))
self.link(parent, child)
}
self.chainLock.Unlock()
poolLogger.Debugf("[%s] unlock chain lock", sectionName(section))
if parent != nil {
poolLogger.Debugf("[%s] activating parent chain [%s]...", name(parent.top.hash), sectionName(parent))
self.activateChain(parent, peer)
poolLogger.Debugf("[%s] activated parent chain [%s]. done", name(parent.top.hash), sectionName(parent))
}
if section != nil {
poolLogger.Debugf("[%s] activate new section process", sectionName(section))
peer.addSection(section.top.hash, section)
section.controlC <- true
}
// self.procWg.Done()
// self.wg.Done()
// }()
} }
func name(hash []byte) (name string) { func name(hash []byte) (name string) {