From b461948e5260963bca1367435d282f969a99b908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 29 Apr 2015 18:42:43 +0300 Subject: [PATCH] p2p: add a dialer cooldown to prevent reattempting failures Conflicts: p2p/server.go --- p2p/peer_error.go | 2 ++ p2p/server.go | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/p2p/peer_error.go b/p2p/peer_error.go index a912f60644..d9c09a9c6c 100644 --- a/p2p/peer_error.go +++ b/p2p/peer_error.go @@ -73,6 +73,7 @@ const ( DiscSelf DiscReadTimeout DiscSubprotocolError + DiscFailureCooldown ) var discReasonToString = [...]string{ @@ -89,6 +90,7 @@ var discReasonToString = [...]string{ DiscSelf: "Connected to self", DiscReadTimeout: "Read timeout", DiscSubprotocolError: "Subprotocol error", + DiscFailureCooldown: "Failure cooldown", } func (d DiscReason) String() string { diff --git a/p2p/server.go b/p2p/server.go index 77f66f1673..8d5fb7a442 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -21,6 +21,7 @@ const ( defaultDialTimeout = 10 * time.Second refreshPeersInterval = 30 * time.Second staticPeerCheckInterval = 15 * time.Second + dialFailureCooldown = 30 * time.Second // Maximum number of concurrently handshaking inbound connections. maxAcceptConns = 10 @@ -113,6 +114,7 @@ type Server struct { lock sync.RWMutex // protects running, peers and the trust fields running bool peers map[discover.NodeID]*Peer + fails map[discover.NodeID]bool // List of recently failed connections staticNodes map[discover.NodeID]*discover.Node // Map of currently maintained static remote nodes staticDial chan *discover.Node // Dial request channel reserved for the static nodes staticCycle time.Duration // Overrides staticPeerCheckInterval, used for testing @@ -217,6 +219,7 @@ func (srv *Server) Start() (err error) { } srv.quit = make(chan struct{}) srv.peers = make(map[discover.NodeID]*Peer) + srv.fails = make(map[discover.NodeID]bool) // Create the current trust maps, and the associated dialing channel srv.trustedNodes = make(map[discover.NodeID]bool) @@ -491,7 +494,20 @@ func (srv *Server) dialNode(dest *discover.Node) { // dialNode, so we need to count it down again. startPeer also // does that when an error occurs. srv.peerWG.Done() - glog.V(logger.Detail).Infof("dial error: %v", err) + + // Mark the dialing as failed so prevent too fast redials, and set a + // timer for re-allowing dialing + srv.lock.Lock() + srv.fails[dest.ID] = true + srv.lock.Unlock() + go func() { + glog.V(logger.Detail).Infof("Dialing %v failed: %v. Locked until %v\n", dest, err, time.Now().Add(dialFailureCooldown)) + <-time.After(dialFailureCooldown) + + srv.lock.Lock() + delete(srv.fails, dest.ID) + srv.lock.Unlock() + }() return } srv.startPeer(conn, dest) @@ -586,6 +602,8 @@ func (srv *Server) checkPeer(id discover.NodeID) (bool, DiscReason) { return false, DiscAlreadyConnected case id == srv.ntab.Self().ID: return false, DiscSelf + case srv.fails[id]: + return false, DiscFailureCooldown default: return true, 0 }