eth: make the peer set thread safe
This commit is contained in:
@ -47,9 +47,7 @@ type ProtocolManager struct {
|
||||
txpool txPool
|
||||
chainman *core.ChainManager
|
||||
downloader *downloader.Downloader
|
||||
|
||||
pmu sync.Mutex
|
||||
peers map[string]*peer
|
||||
peers *peerSet
|
||||
|
||||
SubProtocol p2p.Protocol
|
||||
|
||||
@ -73,7 +71,7 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
|
||||
txpool: txpool,
|
||||
chainman: chainman,
|
||||
downloader: downloader,
|
||||
peers: make(map[string]*peer),
|
||||
peers: newPeerSet(),
|
||||
newPeerCh: make(chan *peer, 1),
|
||||
quitSync: make(chan struct{}),
|
||||
}
|
||||
@ -95,10 +93,14 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
|
||||
}
|
||||
|
||||
func (pm *ProtocolManager) removePeer(peer *peer) {
|
||||
pm.pmu.Lock()
|
||||
defer pm.pmu.Unlock()
|
||||
// Unregister the peer from the downloader
|
||||
pm.downloader.UnregisterPeer(peer.id)
|
||||
delete(pm.peers, peer.id)
|
||||
|
||||
// Remove the peer from the Ethereum peer set too
|
||||
glog.V(logger.Detail).Infoln("Removing peer", peer.id)
|
||||
if err := pm.peers.Unregister(peer.id); err != nil {
|
||||
glog.V(logger.Error).Infoln("Removal failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *ProtocolManager) Start() {
|
||||
@ -136,31 +138,32 @@ func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter
|
||||
}
|
||||
|
||||
func (pm *ProtocolManager) handle(p *peer) error {
|
||||
// Execute the Ethereum handshake, short circuit if fails
|
||||
if err := p.handleStatus(); err != nil {
|
||||
return err
|
||||
}
|
||||
pm.pmu.Lock()
|
||||
pm.peers[p.id] = p
|
||||
pm.pmu.Unlock()
|
||||
|
||||
pm.downloader.RegisterPeer(p.id, p.recentHash, p.requestHashes, p.requestBlocks)
|
||||
defer func() {
|
||||
pm.removePeer(p)
|
||||
}()
|
||||
// Register the peer locally and in the downloader too
|
||||
glog.V(logger.Detail).Infoln("Adding peer", p.id)
|
||||
if err := pm.peers.Register(p); err != nil {
|
||||
glog.V(logger.Error).Infoln("Addition failed:", err)
|
||||
return err
|
||||
}
|
||||
defer pm.removePeer(p)
|
||||
|
||||
if err := pm.downloader.RegisterPeer(p.id, p.recentHash, p.requestHashes, p.requestBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
// propagate existing transactions. new transactions appearing
|
||||
// after this will be sent via broadcasts.
|
||||
if err := p.sendTransactions(pm.txpool.GetTransactions()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// main loop. handle incoming messages.
|
||||
for {
|
||||
if err := pm.handleMsg(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -346,18 +349,8 @@ func (pm *ProtocolManager) verifyTd(peer *peer, request newBlockMsgData) error {
|
||||
// out which peers do not contain the block in their block set and will do a
|
||||
// sqrt(peers) to determine the amount of peers we broadcast to.
|
||||
func (pm *ProtocolManager) BroadcastBlock(hash common.Hash, block *types.Block) {
|
||||
pm.pmu.Lock()
|
||||
defer pm.pmu.Unlock()
|
||||
|
||||
// Find peers who don't know anything about the given hash. Peers that
|
||||
// don't know about the hash will be a candidate for the broadcast loop
|
||||
var peers []*peer
|
||||
for _, peer := range pm.peers {
|
||||
if !peer.blockHashes.Has(hash) {
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
}
|
||||
// Broadcast block to peer set
|
||||
// Broadcast block to a batch of peers not knowing about it
|
||||
peers := pm.peers.BlockLackingPeers(hash)
|
||||
peers = peers[:int(math.Sqrt(float64(len(peers))))]
|
||||
for _, peer := range peers {
|
||||
peer.sendNewBlock(block)
|
||||
@ -369,18 +362,8 @@ func (pm *ProtocolManager) BroadcastBlock(hash common.Hash, block *types.Block)
|
||||
// out which peers do not contain the block in their block set and will do a
|
||||
// sqrt(peers) to determine the amount of peers we broadcast to.
|
||||
func (pm *ProtocolManager) BroadcastTx(hash common.Hash, tx *types.Transaction) {
|
||||
pm.pmu.Lock()
|
||||
defer pm.pmu.Unlock()
|
||||
|
||||
// Find peers who don't know anything about the given hash. Peers that
|
||||
// don't know about the hash will be a candidate for the broadcast loop
|
||||
var peers []*peer
|
||||
for _, peer := range pm.peers {
|
||||
if !peer.txHashes.Has(hash) {
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
}
|
||||
// Broadcast block to peer set
|
||||
// Broadcast transaction to a batch of peers not knowing about it
|
||||
peers := pm.peers.TxLackingPeers(hash)
|
||||
//FIXME include this again: peers = peers[:int(math.Sqrt(float64(len(peers))))]
|
||||
for _, peer := range peers {
|
||||
peer.sendTransaction(tx)
|
||||
|
Reference in New Issue
Block a user