From 511a90a5c58b617298da557bb2c2bd773175b28f Mon Sep 17 00:00:00 2001 From: Vadim Ushakov Date: Wed, 28 Oct 2020 20:31:48 +0700 Subject: [PATCH] Redesign Site.needConnections() --- src/File/FileServer.py | 10 ++--- src/Peer/Peer.py | 9 +++-- src/Site/Site.py | 87 +++++++++++++++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/File/FileServer.py b/src/File/FileServer.py index 186d88a3..c1134800 100644 --- a/src/File/FileServer.py +++ b/src/File/FileServer.py @@ -295,12 +295,12 @@ class FileServer(ConnectionServer): elif site.bad_files: site.retryBadFiles() - if time.time() - site.settings.get("modified", 0) < 60 * 60 * 24 * 7: - # Keep active connections if site has been modified witin 7 days - connected_num = site.needConnections(check_site_on_reconnect=True) + # Keep active connections + connected_num = site.needConnections(check_site_on_reconnect=True) - if connected_num < config.connected_limit: # This site has small amount of peers, protect them from closing - peers_protected.update([peer.key for peer in site.getConnectedPeers()]) + if connected_num < config.connected_limit: + # This site has small amount of peers, protect them from closing + peers_protected.update([peer.key for peer in site.getConnectedPeers()]) time.sleep(1) # Prevent too quick request diff --git a/src/Peer/Peer.py b/src/Peer/Peer.py index d8e28121..75eb190f 100644 --- a/src/Peer/Peer.py +++ b/src/Peer/Peer.py @@ -74,6 +74,9 @@ class Peer(object): logger.log(self.log_level, "%s:%s %s" % (self.ip, self.port, text)) + def isConnected(self): + return self.connection and self.connection.connected + # Connect to host def connect(self, connection=None): if self.reputation < -10: @@ -249,11 +252,11 @@ class Peer(object): return buff # Send a ping request - def ping(self): + def ping(self, timeout=10.0, tryes=3): response_time = None - for retry in range(1, 3): # Retry 3 times + for retry in range(1, tryes): # Retry 3 times s = time.time() - with gevent.Timeout(10.0, False): # 10 sec timeout, don't raise exception + with gevent.Timeout(timeout, False): res = self.request("ping") if res and "body" in res and res["body"] == b"Pong!": diff --git a/src/Site/Site.py b/src/Site/Site.py index 354fe9c0..fff592cd 100644 --- a/src/Site/Site.py +++ b/src/Site/Site.py @@ -853,36 +853,87 @@ class Site(object): if self.isServing(): self.announcer.announce(*args, **kwargs) - # Keep connections to get the updates - def needConnections(self, num=None, check_site_on_reconnect=False): - if num is None: - if len(self.peers) < 50: - num = 3 - else: - num = 6 - need = min(len(self.peers), num, config.connected_limit) # Need 5 peer, but max total peers + def getPreferableActiveConnectionCount(self): + if not self.isServing(): + return 0 + age = time.time() - self.settings.get("modified", 0) + count = 0 + + if age < 60 * 60: + count = 10 + elif age < 60 * 60 * 5: + count = 8 + elif age < 60 * 60 * 24: + count = 6 + elif age < 60 * 60 * 24 * 3: + count = 4 + elif age < 60 * 60 * 24 * 7: + count = 2 + + if len(self.peers) < 50: + count = max(count, 5) + + return count + + def tryConnectingToMorePeers(self, more=1, pex=True, try_harder=False): + max_peers = more * 2 + 10 + if try_harder: + max_peers += 10000 + + connected = 0 + for peer in self.getRecentPeers(max_peers): + if not peer.isConnected(): + if pex: + peer.pex() + else: + peer.ping(timeout=2.0, tryes=1) + + if peer.isConnected(): + connected += 1 + + if connected >= more: + break + + return connected + + def bringConnections(self, need=1, check_site_on_reconnect=False, pex=True, try_harder=False): connected = len(self.getConnectedPeers()) - connected_before = connected self.log.debug("Need connections: %s, Current: %s, Total: %s" % (need, connected, len(self.peers))) - if connected < need: # Need more than we have - for peer in self.getRecentPeers(30): - if not peer.connection or not peer.connection.connected: # No peer connection or disconnected - peer.pex() # Initiate peer exchange - if peer.connection and peer.connection.connected: - connected += 1 # Successfully connected - if connected >= need: - break + if connected < need: + connected += self.tryConnectingToMorePeers(more=(need-connected), pex=pex, try_harder=try_harder) self.log.debug( "Connected before: %s, after: %s. Check site: %s." % (connected_before, connected, check_site_on_reconnect) ) if check_site_on_reconnect and connected_before == 0 and connected > 0 and self.connection_server.has_internet: - gevent.spawn(self.update, check_files=False) + self.greenlet_manager.spawn(self.update, check_files=False) + + return connected + + # Keep connections + def needConnections(self, num=None, check_site_on_reconnect=False, pex=True): + if num is None: + num = self.getPreferableActiveConnectionCount() + + need = min(len(self.peers), num, config.connected_limit) + + connected = self.bringConnections( + need=need, + check_site_on_reconnect=check_site_on_reconnect, + pex=pex, + try_harder=False) + + if connected < need: + self.greenlet_manager.spawnLater(1.0, self.bringConnections, + need=need, + check_site_on_reconnect=check_site_on_reconnect, + pex=pex, + try_harder=True) return connected