les: address comments

This commit is contained in:
rjl493456442 2020-02-24 10:45:53 +08:00
parent 16d2323590
commit 15d3b0a05c
10 changed files with 228 additions and 201 deletions

View file

@ -49,6 +49,7 @@ import (
type LightEthereum struct { type LightEthereum struct {
lesCommons lesCommons
peers *serverPeerSet
reqDist *requestDistributor reqDist *requestDistributor
retriever *retrieveManager retriever *retrieveManager
odr *LesOdr odr *LesOdr
@ -80,7 +81,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
} }
log.Info("Initialised chain configuration", "config", chainConfig) log.Info("Initialised chain configuration", "config", chainConfig)
peers := newPeerSet(true) peers := newServerPeerSet()
leth := &LightEthereum{ leth := &LightEthereum{
lesCommons: lesCommons{ lesCommons: lesCommons{
genesis: genesisHash, genesis: genesisHash,
@ -88,9 +89,9 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
chainConfig: chainConfig, chainConfig: chainConfig,
iConfig: light.DefaultClientIndexerConfig, iConfig: light.DefaultClientIndexerConfig,
chainDb: chainDb, chainDb: chainDb,
peers: peers,
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
}, },
peers: peers,
eventMux: ctx.EventMux, eventMux: ctx.EventMux,
reqDist: newRequestDistributor(peers, &mclock.System{}), reqDist: newRequestDistributor(peers, &mclock.System{}),
accountManager: ctx.AccountManager, accountManager: ctx.AccountManager,
@ -225,7 +226,7 @@ func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux
// network protocols to start. // network protocols to start.
func (s *LightEthereum) Protocols() []p2p.Protocol { func (s *LightEthereum) Protocols() []p2p.Protocol {
return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
if p := s.peers.serverPeer(peerIdToString(id)); p != nil { if p := s.peers.peer(peerIdToString(id)); p != nil {
return p.Info() return p.Info()
} }
return nil return nil

View file

@ -61,7 +61,6 @@ type lesCommons struct {
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
iConfig *light.IndexerConfig iConfig *light.IndexerConfig
chainDb ethdb.Database chainDb ethdb.Database
peers *peerSet
chainReader chainReader chainReader chainReader
chtIndexer, bloomTrieIndexer *core.ChainIndexer chtIndexer, bloomTrieIndexer *core.ChainIndexer
oracle *checkpointoracle.CheckpointOracle oracle *checkpointoracle.CheckpointOracle

View file

@ -73,7 +73,7 @@ type distReq struct {
} }
// newRequestDistributor creates a new request distributor // newRequestDistributor creates a new request distributor
func newRequestDistributor(peers *peerSet, clock mclock.Clock) *requestDistributor { func newRequestDistributor(peers *serverPeerSet, clock mclock.Clock) *requestDistributor {
d := &requestDistributor{ d := &requestDistributor{
clock: clock, clock: clock,
reqQueue: list.New(), reqQueue: list.New(),

View file

@ -163,11 +163,11 @@ func (p *peerCommons) queueSend(f func()) bool {
// mustQueueSend starts a for loop and retry the caching if failed. // mustQueueSend starts a for loop and retry the caching if failed.
// If the stopCh is closed, then it returns. // If the stopCh is closed, then it returns.
func (p *peerCommons) mustQueueSend(f func(), stopCh chan struct{}) { func (p *peerCommons) mustQueueSend(f func()) {
for { for {
// Check whether the stopCh is closed. // Check whether the stopCh is closed.
select { select {
case <-stopCh: case <-p.closeCh:
return return
default: default:
} }
@ -198,8 +198,7 @@ func (p *peerCommons) Head() (hash common.Hash) {
p.lock.RLock() p.lock.RLock()
defer p.lock.RUnlock() defer p.lock.RUnlock()
copy(hash[:], p.headInfo.Hash[:]) return p.headInfo.Hash
return hash
} }
// Td retrieves the current total difficulty of a peer. // Td retrieves the current total difficulty of a peer.
@ -215,8 +214,7 @@ func (p *peerCommons) HeadAndTd() (hash common.Hash, td *big.Int) {
p.lock.RLock() p.lock.RLock()
defer p.lock.RUnlock() defer p.lock.RUnlock()
copy(hash[:], p.headInfo.Hash[:]) return p.headInfo.Hash, new(big.Int).Set(p.headInfo.Td)
return hash, new(big.Int).Set(p.headInfo.Td)
} }
// sendReceiveHandshake exchanges handshake packet with remote peer and returns any error // sendReceiveHandshake exchanges handshake packet with remote peer and returns any error
@ -805,9 +803,7 @@ func (p *clientPeer) updateCapacity(cap uint64) {
var kvList keyValueList var kvList keyValueList
kvList = kvList.add("flowControl/MRR", cap) kvList = kvList.add("flowControl/MRR", cap)
kvList = kvList.add("flowControl/BL", cap*bufLimitRatio) kvList = kvList.add("flowControl/BL", cap*bufLimitRatio)
p.mustQueueSend(func() { p.sendAnnounce(announceData{Update: kvList}) })
// todo(rjl493456442) please ensure the capacity upgrade function can be queued
p.mustQueueSend(func() { p.sendAnnounce(announceData{Update: kvList}) }, p.closeCh)
} }
// freezeClient temporarily puts the client in a frozen state which means all // freezeClient temporarily puts the client in a frozen state which means all
@ -900,223 +896,272 @@ func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, ge
}) })
} }
// serverPeerSubscriber is a callback interface to notify services about added or // serverPeerSubscriber is an interface to notify services about added or
// removed server peers // removed server peers
type serverPeerSubscriber interface { type serverPeerSubscriber interface {
registerPeer(*serverPeer) registerPeer(*serverPeer)
unregisterPeer(*serverPeer) unregisterPeer(*serverPeer)
} }
// clientPeerSubscriber is a callback interface to notify services about added or // clientPeerSubscriber is an interface to notify services about added or
// removed client peers // removed client peers
type clientPeerSubscriber interface { type clientPeerSubscriber interface {
registerPeer(*clientPeer) registerPeer(*clientPeer)
unregisterPeer(*clientPeer) unregisterPeer(*clientPeer)
} }
// peerSet represents the collection of active peers currently participating in // clientPeerSet represents the set of active client peers currently
// the Light Ethereum sub-protocol. // participating in the Light Ethereum sub-protocol.
type peerSet struct { type clientPeerSet struct {
serverPeers map[string]*serverPeer peers map[string]*clientPeer
clientPeers map[string]*clientPeer // subscribers is a batch of subscribers and peerset will notify
// these subscribers when the peerset changes(new client peer is
// sSubs is a batch of subscribers and peerset will notify these // added or removed)
// subscribers when the peerset changes(new server peer is added subscribers []clientPeerSubscriber
// or removed)
sSubs []serverPeerSubscriber
// cSubs is a batch of subscribers and peerset will notify these
// subscribers when the peerset changes(new client peer is added
// or removed)
cSubs []clientPeerSubscriber
closed bool closed bool
client bool
lock sync.RWMutex lock sync.RWMutex
} }
// newPeerSet creates a new peer set to track the active participants. // newClientPeerSet creates a new peer set to track the client peers.
func newPeerSet(client bool) *peerSet { func newClientPeerSet() *clientPeerSet {
set := &peerSet{client: client} return &clientPeerSet{peers: make(map[string]*clientPeer)}
if client {
set.serverPeers = make(map[string]*serverPeer)
} else {
set.clientPeers = make(map[string]*clientPeer)
}
return set
} }
// subscribe adds a service to be notified about added or removed // subscribe adds a service to be notified about added or removed
// peers and also register all active peers into the given service. // peers and also register all active peers into the given service.
func (ps *peerSet) subscribe(s interface{}) { func (ps *clientPeerSet) subscribe(sub clientPeerSubscriber) {
ps.lock.Lock() ps.lock.Lock()
defer ps.lock.Unlock() defer ps.lock.Unlock()
if ps.client { ps.subscribers = append(ps.subscribers, sub)
sub := s.(serverPeerSubscriber) for _, p := range ps.peers {
ps.sSubs = append(ps.sSubs, sub)
for _, p := range ps.serverPeers {
sub.registerPeer(p) sub.registerPeer(p)
} }
} else {
sub := s.(clientPeerSubscriber)
ps.cSubs = append(ps.cSubs, sub)
for _, p := range ps.clientPeers {
sub.registerPeer(p)
}
}
} }
// unSubscribe removes the specified service from the subscriber pool. // unSubscribe removes the specified service from the subscriber pool.
func (ps *peerSet) unSubscribe(s interface{}) { func (ps *clientPeerSet) unSubscribe(sub clientPeerSubscriber) {
ps.lock.Lock() ps.lock.Lock()
defer ps.lock.Unlock() defer ps.lock.Unlock()
if ps.client { for i, s := range ps.subscribers {
sub := s.(serverPeerSubscriber) if s == sub {
for i, ss := range ps.sSubs { ps.subscribers = append(ps.subscribers[:i], ps.subscribers[i+1:]...)
if ss == sub { return
ps.sSubs = append(ps.sSubs[:i], ps.sSubs[i+1:]...)
}
}
} else {
sub := s.(clientPeerSubscriber)
for i, cs := range ps.cSubs {
if cs == sub {
ps.cSubs = append(ps.cSubs[:i], ps.cSubs[i+1:]...)
}
} }
} }
} }
// Register injects a new peer into the working set, or returns an error if the // register adds a new peer into the peer set, or returns an error if the
// peer is already known. // peer is already known.
func (ps *peerSet) register(p interface{}) error { func (ps *clientPeerSet) register(peer *clientPeer) error {
ps.lock.Lock() ps.lock.Lock()
defer ps.lock.Unlock() defer ps.lock.Unlock()
if ps.closed { if ps.closed {
return errClosed return errClosed
} }
if ps.client { if _, exist := ps.peers[peer.id]; exist {
peer := p.(*serverPeer)
if _, exist := ps.serverPeers[peer.id]; exist {
return errAlreadyRegistered return errAlreadyRegistered
} }
ps.serverPeers[peer.id] = peer ps.peers[peer.id] = peer
for _, sub := range ps.sSubs { for _, sub := range ps.subscribers {
sub.registerPeer(peer) sub.registerPeer(peer)
} }
} else {
peer := p.(*clientPeer)
if _, exist := ps.clientPeers[peer.id]; exist {
return errAlreadyRegistered
}
ps.clientPeers[peer.id] = peer
for _, sub := range ps.cSubs {
sub.registerPeer(peer)
}
}
return nil return nil
} }
// Unregister removes a remote peer from the active set, disabling any further // unregister removes a remote peer from the peer set, disabling any further
// actions to/from that particular entity. It also initiates disconnection at the networking layer. // actions to/from that particular entity. It also initiates disconnection
func (ps *peerSet) unregister(id string) error { // at the networking layer.
func (ps *clientPeerSet) unregister(id string) error {
ps.lock.Lock() ps.lock.Lock()
defer ps.lock.Unlock() defer ps.lock.Unlock()
if ps.client { p, ok := ps.peers[id]
p, ok := ps.serverPeers[id]
if !ok { if !ok {
return errNotRegistered return errNotRegistered
} }
delete(ps.serverPeers, id) delete(ps.peers, id)
for _, sub := range ps.sSubs { for _, sub := range ps.subscribers {
sub.unregisterPeer(p) sub.unregisterPeer(p)
} }
p.Peer.Disconnect(p2p.DiscUselessPeer) p.Peer.Disconnect(p2p.DiscRequested)
} else {
p, ok := ps.clientPeers[id]
if !ok {
return errNotRegistered
}
delete(ps.clientPeers, id)
for _, sub := range ps.cSubs {
sub.unregisterPeer(p)
}
p.Peer.Disconnect(p2p.DiscUselessPeer)
}
return nil return nil
} }
// AllPeerIDs returns a list of all registered peer IDs // ids returns a list of all registered peer IDs
func (ps *peerSet) allPeerIds() []string { func (ps *clientPeerSet) ids() []string {
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()
var ids []string var ids []string
if ps.client { for id := range ps.peers {
for id := range ps.serverPeers {
ids = append(ids, id) ids = append(ids, id)
} }
} else {
for id := range ps.clientPeers {
ids = append(ids, id)
}
}
return ids return ids
} }
// Peer retrieves the registered peer with the given id. // peer retrieves the registered peer with the given id.
func (ps *peerSet) serverPeer(id string) *serverPeer { func (ps *clientPeerSet) peer(id string) *clientPeer {
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()
if !ps.client { return ps.peers[id]
}
// len returns if the current number of peers in the set.
func (ps *clientPeerSet) len() int {
ps.lock.RLock()
defer ps.lock.RUnlock()
return len(ps.peers)
}
// allClientPeers returns all client peers in a list.
func (ps *clientPeerSet) allPeers() []*clientPeer {
ps.lock.RLock()
defer ps.lock.RUnlock()
list := make([]*clientPeer, 0, len(ps.peers))
for _, p := range ps.peers {
list = append(list, p)
}
return list
}
// close disconnects all peers. No new peers can be registered
// after close has returned.
func (ps *clientPeerSet) close() {
ps.lock.Lock()
defer ps.lock.Unlock()
for _, p := range ps.peers {
p.Disconnect(p2p.DiscQuitting)
}
ps.closed = true
}
// serverPeerSet represents the set of active server peers currently
// participating in the Light Ethereum sub-protocol.
type serverPeerSet struct {
peers map[string]*serverPeer
// subscribers is a batch of subscribers and peerset will notify
// these subscribers when the peerset changes(new server peer is
// added or removed)
subscribers []serverPeerSubscriber
closed bool
lock sync.RWMutex
}
// newServerPeerSet creates a new peer set to track the active server peers.
func newServerPeerSet() *serverPeerSet {
return &serverPeerSet{peers: make(map[string]*serverPeer)}
}
// subscribe adds a service to be notified about added or removed
// peers and also register all active peers into the given service.
func (ps *serverPeerSet) subscribe(sub serverPeerSubscriber) {
ps.lock.Lock()
defer ps.lock.Unlock()
ps.subscribers = append(ps.subscribers, sub)
for _, p := range ps.peers {
sub.registerPeer(p)
}
}
// unSubscribe removes the specified service from the subscriber pool.
func (ps *serverPeerSet) unSubscribe(sub serverPeerSubscriber) {
ps.lock.Lock()
defer ps.lock.Unlock()
for i, s := range ps.subscribers {
if s == sub {
ps.subscribers = append(ps.subscribers[:i], ps.subscribers[i+1:]...)
return
}
}
}
// register adds a new server peer into the set, or returns an error if the
// peer is already known.
func (ps *serverPeerSet) register(peer *serverPeer) error {
ps.lock.Lock()
defer ps.lock.Unlock()
if ps.closed {
return errClosed
}
if _, exist := ps.peers[peer.id]; exist {
return errAlreadyRegistered
}
ps.peers[peer.id] = peer
for _, sub := range ps.subscribers {
sub.registerPeer(peer)
}
return nil return nil
}
return ps.serverPeers[id]
} }
// Peer retrieves the registered peer with the given id. // unregister removes a remote peer from the active set, disabling any further
func (ps *peerSet) clientPeer(id string) *clientPeer { // actions to/from that particular entity. It also initiates disconnection at
ps.lock.RLock() // the networking layer.
defer ps.lock.RUnlock() func (ps *serverPeerSet) unregister(id string) error {
ps.lock.Lock()
defer ps.lock.Unlock()
if ps.client { p, ok := ps.peers[id]
if !ok {
return errNotRegistered
}
delete(ps.peers, id)
for _, sub := range ps.subscribers {
sub.unregisterPeer(p)
}
p.Peer.Disconnect(p2p.DiscRequested)
return nil return nil
}
return ps.clientPeers[id]
} }
// Len returns if the current number of peers in the set. // ids returns a list of all registered peer IDs
func (ps *peerSet) len() int { func (ps *serverPeerSet) ids() []string {
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()
if ps.client { var ids []string
return len(ps.serverPeers) for id := range ps.peers {
} else { ids = append(ids, id)
return len(ps.clientPeers)
} }
return ids
} }
// BestPeer retrieves the known peer with the currently highest total difficulty. // peer retrieves the registered peer with the given id.
func (ps *serverPeerSet) peer(id string) *serverPeer {
ps.lock.RLock()
defer ps.lock.RUnlock()
return ps.peers[id]
}
// len returns if the current number of peers in the set.
func (ps *serverPeerSet) len() int {
ps.lock.RLock()
defer ps.lock.RUnlock()
return len(ps.peers)
}
// bestPeer retrieves the known peer with the currently highest total difficulty.
// If the peerset is "client peer set", then nothing meaningful will return. The // If the peerset is "client peer set", then nothing meaningful will return. The
// reason is client peer never send back their latest status to server. // reason is client peer never send back their latest status to server.
func (ps *peerSet) bestPeer() *serverPeer { func (ps *serverPeerSet) bestPeer() *serverPeer {
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()
if !ps.client {
return nil
}
var ( var (
bestPeer *serverPeer bestPeer *serverPeer
bestTd *big.Int bestTd *big.Int
) )
for _, p := range ps.serverPeers { for _, p := range ps.peers {
if td := p.Td(); bestTd == nil || td.Cmp(bestTd) > 0 { if td := p.Td(); bestTd == nil || td.Cmp(bestTd) > 0 {
bestPeer, bestTd = p, td bestPeer, bestTd = p, td
} }
@ -1125,49 +1170,25 @@ func (ps *peerSet) bestPeer() *serverPeer {
} }
// allServerPeers returns all server peers in a list. // allServerPeers returns all server peers in a list.
func (ps *peerSet) allServerPeers() []*serverPeer { func (ps *serverPeerSet) allPeers() []*serverPeer {
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()
if !ps.client { list := make([]*serverPeer, 0, len(ps.peers))
return nil for _, p := range ps.peers {
}
list := make([]*serverPeer, 0, len(ps.serverPeers))
for _, p := range ps.serverPeers {
list = append(list, p) list = append(list, p)
} }
return list return list
} }
// allClientPeers returns all client peers in a list. // close disconnects all peers. No new peers can be registered
func (ps *peerSet) allClientPeers() []*clientPeer { // after close has returned.
ps.lock.RLock() func (ps *serverPeerSet) close() {
defer ps.lock.RUnlock()
if ps.client {
return nil
}
list := make([]*clientPeer, 0, len(ps.clientPeers))
for _, p := range ps.clientPeers {
list = append(list, p)
}
return list
}
// Close disconnects all peers.
// No new peers can be registered after Close has returned.
func (ps *peerSet) close() {
ps.lock.Lock() ps.lock.Lock()
defer ps.lock.Unlock() defer ps.lock.Unlock()
if ps.client { for _, p := range ps.peers {
for _, p := range ps.serverPeers {
p.Disconnect(p2p.DiscQuitting) p.Disconnect(p2p.DiscQuitting)
} }
} else {
for _, p := range ps.clientPeers {
p.Disconnect(p2p.DiscQuitting)
}
}
ps.closed = true ps.closed = true
} }

View file

@ -45,11 +45,11 @@ func (t *testServerPeerSub) registerPeer(p *serverPeer) { t.regCh <- p }
func (t *testServerPeerSub) unregisterPeer(p *serverPeer) { t.unregCh <- p } func (t *testServerPeerSub) unregisterPeer(p *serverPeer) { t.unregCh <- p }
func TestPeerSubscription(t *testing.T) { func TestPeerSubscription(t *testing.T) {
peers := newPeerSet(true) peers := newServerPeerSet()
defer peers.close() defer peers.close()
checkIds := func(expect []string) { checkIds := func(expect []string) {
given := peers.allPeerIds() given := peers.ids()
if len(given) == 0 && len(expect) == 0 { if len(given) == 0 && len(expect) == 0 {
return return
} }

View file

@ -38,7 +38,7 @@ var (
// matching replies by request ID and handles timeouts and resends if necessary. // matching replies by request ID and handles timeouts and resends if necessary.
type retrieveManager struct { type retrieveManager struct {
dist *requestDistributor dist *requestDistributor
peers *peerSet peers *serverPeerSet
serverPool peerSelector serverPool peerSelector
lock sync.RWMutex lock sync.RWMutex
@ -99,7 +99,7 @@ const (
) )
// newRetrieveManager creates the retrieve manager // newRetrieveManager creates the retrieve manager
func newRetrieveManager(peers *peerSet, dist *requestDistributor, serverPool peerSelector) *retrieveManager { func newRetrieveManager(peers *serverPeerSet, dist *requestDistributor, serverPool peerSelector) *retrieveManager {
return &retrieveManager{ return &retrieveManager{
peers: peers, peers: peers,
dist: dist, dist: dist,

View file

@ -40,6 +40,7 @@ type LesServer struct {
lesCommons lesCommons
archiveMode bool // Flag whether the ethereum node runs in archive mode. archiveMode bool // Flag whether the ethereum node runs in archive mode.
peers *clientPeerSet
handler *serverHandler handler *serverHandler
lesTopics []discv5.Topic lesTopics []discv5.Topic
privateKey *ecdsa.PrivateKey privateKey *ecdsa.PrivateKey
@ -75,13 +76,13 @@ func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
chainConfig: e.BlockChain().Config(), chainConfig: e.BlockChain().Config(),
iConfig: light.DefaultServerIndexerConfig, iConfig: light.DefaultServerIndexerConfig,
chainDb: e.ChainDb(), chainDb: e.ChainDb(),
peers: newPeerSet(false),
chainReader: e.BlockChain(), chainReader: e.BlockChain(),
chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations), chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations),
bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency), bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
}, },
archiveMode: e.ArchiveMode(), archiveMode: e.ArchiveMode(),
peers: newClientPeerSet(),
lesTopics: lesTopics, lesTopics: lesTopics,
fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}), fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}),
servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100), servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100),
@ -152,7 +153,7 @@ func (s *LesServer) APIs() []rpc.API {
func (s *LesServer) Protocols() []p2p.Protocol { func (s *LesServer) Protocols() []p2p.Protocol {
ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
if p := s.peers.clientPeer(peerIdToString(id)); p != nil { if p := s.peers.peer(peerIdToString(id)); p != nil {
return p.Info() return p.Info()
} }
return nil return nil

View file

@ -266,7 +266,7 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
default: default:
} }
} }
}, p.closeCh) })
} }
} }
switch msg.Code { switch msg.Code {
@ -914,7 +914,7 @@ func (h *serverHandler) broadcastHeaders() {
for { for {
select { select {
case ev := <-headCh: case ev := <-headCh:
peers := h.server.peers.allClientPeers() peers := h.server.peers.allPeers()
if len(peers) == 0 { if len(peers) == 0 {
continue continue
} }
@ -940,14 +940,18 @@ func (h *serverHandler) broadcastHeaders() {
p := p p := p
switch p.announceType { switch p.announceType {
case announceTypeSimple: case announceTypeSimple:
p.mustQueueSend(func() { p.sendAnnounce(announce) }, p.closeCh) if !p.queueSend(func() { p.sendAnnounce(announce) }) {
log.Debug("Drop announcement because queue is full", "number", number, "hash", hash)
}
case announceTypeSigned: case announceTypeSigned:
if !signed { if !signed {
signedAnnounce = announce signedAnnounce = announce
signedAnnounce.sign(h.server.privateKey) signedAnnounce.sign(h.server.privateKey)
signed = true signed = true
} }
p.mustQueueSend(func() { p.sendAnnounce(signedAnnounce) }, p.closeCh) if !p.queueSend(func() { p.sendAnnounce(signedAnnounce) }) {
log.Debug("Drop announcement because queue is full", "number", number, "hash", hash)
}
} }
} }
case <-h.closeCh: case <-h.closeCh:

View file

@ -166,7 +166,7 @@ func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.Indexer
return indexers[:] return indexers[:]
} }
func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, ulcServers []string, ulcFraction int) *clientHandler { func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *serverPeerSet, ulcServers []string, ulcFraction int) *clientHandler {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
engine = ethash.NewFaker() engine = ethash.NewFaker()
@ -206,9 +206,9 @@ func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, index
chainDb: db, chainDb: db,
oracle: oracle, oracle: oracle,
chainReader: chain, chainReader: chain,
peers: peers,
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
}, },
peers: peers,
reqDist: odr.retriever.dist, reqDist: odr.retriever.dist,
retriever: odr.retriever, retriever: odr.retriever,
odr: odr, odr: odr,
@ -224,7 +224,7 @@ func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, index
return client.handler return client.handler
} }
func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) { func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *clientPeerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) {
var ( var (
gspec = core.Genesis{ gspec = core.Genesis{
Config: params.AllEthashProtocolChanges, Config: params.AllEthashProtocolChanges,
@ -269,9 +269,9 @@ func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Da
chainDb: db, chainDb: db,
chainReader: simulation.Blockchain(), chainReader: simulation.Blockchain(),
oracle: oracle, oracle: oracle,
peers: peers,
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
}, },
peers: peers,
servingQueue: newServingQueue(int64(time.Millisecond*10), 1), servingQueue: newServingQueue(int64(time.Millisecond*10), 1),
defParams: flowcontrol.ServerParams{ defParams: flowcontrol.ServerParams{
BufLimit: testBufLimit, BufLimit: testBufLimit,
@ -446,7 +446,7 @@ func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallba
if simClock { if simClock {
clock = &mclock.Simulated{} clock = &mclock.Simulated{}
} }
handler, b := newTestServerHandler(blocks, indexers, db, newPeerSet(false), clock) handler, b := newTestServerHandler(blocks, indexers, db, newClientPeerSet(), clock)
var peer *testPeer var peer *testPeer
if newPeer { if newPeer {
@ -485,14 +485,14 @@ func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallba
func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) { func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) {
sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase() sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase()
speers, cPeers := newPeerSet(false), newPeerSet(true) speers, cpeers := newServerPeerSet(), newClientPeerSet()
var clock mclock.Clock = &mclock.System{} var clock mclock.Clock = &mclock.System{}
if simClock { if simClock {
clock = &mclock.Simulated{} clock = &mclock.Simulated{}
} }
dist := newRequestDistributor(cPeers, clock) dist := newRequestDistributor(speers, clock)
rm := newRetrieveManager(cPeers, dist, nil) rm := newRetrieveManager(speers, dist, nil)
odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm) odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm)
sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig) sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig)
@ -502,8 +502,8 @@ func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexer
ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2] ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2]
odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer) odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer)
server, b := newTestServerHandler(blocks, sindexers, sdb, speers, clock) server, b := newTestServerHandler(blocks, sindexers, sdb, cpeers, clock)
client := newTestClientHandler(b, odr, cIndexers, cdb, cPeers, ulcServers, ulcFraction) client := newTestClientHandler(b, odr, cIndexers, cdb, speers, ulcServers, ulcFraction)
scIndexer.Start(server.blockchain) scIndexer.Start(server.blockchain)
sbIndexer.Start(server.blockchain) sbIndexer.Start(server.blockchain)

View file

@ -41,7 +41,7 @@ type lesTxRelay struct {
retriever *retrieveManager retriever *retrieveManager
} }
func newLesTxRelay(ps *peerSet, retriever *retrieveManager) *lesTxRelay { func newLesTxRelay(ps *serverPeerSet, retriever *retrieveManager) *lesTxRelay {
r := &lesTxRelay{ r := &lesTxRelay{
txSent: make(map[common.Hash]*ltrInfo), txSent: make(map[common.Hash]*ltrInfo),
txPending: make(map[common.Hash]struct{}), txPending: make(map[common.Hash]struct{}),
@ -75,6 +75,7 @@ func (ltrx *lesTxRelay) unregisterPeer(p *serverPeer) {
if peer == p { if peer == p {
// Remove from the peer list // Remove from the peer list
ltrx.peerList = append(ltrx.peerList[:i], ltrx.peerList[i+1:]...) ltrx.peerList = append(ltrx.peerList[:i], ltrx.peerList[i+1:]...)
return
} }
} }
} }