From 3d886d9fc3524711e9cad9d5d47a121edeb363ad Mon Sep 17 00:00:00 2001 From: Morgan Collett Date: Tue, 10 Jul 2007 13:55:38 +0000 Subject: Reapply "Rework reconnection logic so RECONNECT_TIME is interpreted as a minimum, to avoid eating CPU if Avahi or NM becomes unstable (or if dbus-python has the buggy pre-0.82 watch_name_owner() implementation)." This reverts commit ae18c6f3897ee10a2136b36061dab14d465198b1. --- diff --git a/src/linklocal_plugin.py b/src/linklocal_plugin.py index b60eb15..10924e1 100644 --- a/src/linklocal_plugin.py +++ b/src/linklocal_plugin.py @@ -68,15 +68,19 @@ class LinkLocalPlugin(TelepathyPlugin): if unique_name: self._have_avahi = True if not had_avahi: - _logger.info('Avahi appeared on the system bus (%s) - ' - 'starting...', unique_name) - self.start() + if self._backoff_id > 0: + _logger.info('Avahi appeared on the system bus (%s) - ' + 'will start when retry time is reached') + else: + _logger.info('Avahi appeared on the system bus (%s) - ' + 'starting...', unique_name) + self.start() else: self._have_avahi = False if had_avahi: _logger.info('Avahi disappeared from the system bus - ' 'stopping...') - self.stop() + self._stop() def cleanup(self): TelepathyPlugin.cleanup(self) @@ -85,7 +89,7 @@ class LinkLocalPlugin(TelepathyPlugin): self._watch = None def _could_connect(self): - return self._have_avahi + return TelepathyPlugin._could_connect(self) and self._have_avahi def _get_account_info(self): """Retrieve connection manager parameters for this account diff --git a/src/server_plugin.py b/src/server_plugin.py index ab00be7..7c275b1 100644 --- a/src/server_plugin.py +++ b/src/server_plugin.py @@ -68,12 +68,12 @@ class ServerPlugin(TelepathyPlugin): if address: _logger.debug("::: valid IP4 address, conn_status %s", self._conn_status) - if self._conn_status == CONNECTION_STATUS_DISCONNECTED: - _logger.debug("::: will connect") + # this is a no-op if starting would be inappropriate right now + if self._conn_status != CONNECTION_STATUS_DISCONNECTED: self.start() else: _logger.debug("::: invalid IP4 address, will disconnect") - self.stop() + self._stop() def _get_account_info(self): """Retrieve connection manager parameters for this account @@ -126,7 +126,8 @@ class ServerPlugin(TelepathyPlugin): return None def _could_connect(self): - return bool(self._ip4am.props.address) + return bool(self._ip4am.props.address and + TelepathyPlugin._could_connect(self)) def _server_is_trusted(self, hostname): """Return True if the server with the given hostname is trusted to diff --git a/src/telepathy_plugin.py b/src/telepathy_plugin.py index d28e6a3..a9ddfe0 100644 --- a/src/telepathy_plugin.py +++ b/src/telepathy_plugin.py @@ -112,8 +112,8 @@ class TelepathyPlugin(gobject.GObject): #: The connection's status self._conn_status = CONNECTION_STATUS_DISCONNECTED - #: GLib signal ID for reconnections - self._reconnect_id = 0 + #: GLib source ID indicating when we may try to reconnect + self._backoff_id = 0 #: Parameters for the connection manager self._account = self._get_account_info() @@ -156,8 +156,16 @@ class TelepathyPlugin(gobject.GObject): raise NotImplementedError def _reconnect_cb(self): - """Attempt to reconnect to the server""" + """Attempt to reconnect to the server after the back-off time has + elapsed. + """ + if self._backoff_id > 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = 0 + + # this is a no-op unless _could_connect() returns True self.start() + return False def _init_connection(self): @@ -192,9 +200,11 @@ class TelepathyPlugin(gobject.GObject): _logger.debug('%r: Connect() succeeded', self) def connect_error(e): _logger.debug('%r: Connect() failed: %s', self, e) - if not self._reconnect_id: - self._reconnect_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, - self._reconnect_cb) + # we don't allow ourselves to retry more often than this + if self._backoff_id != 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, + self._reconnect_cb) self._conn[CONN_INTERFACE].Connect(reply_handler=connect_reply, error_handler=connect_error) @@ -228,26 +238,30 @@ class TelepathyPlugin(gobject.GObject): _logger.debug("%r: connected", self) self._connected_cb() elif status == CONNECTION_STATUS_DISCONNECTED: - self.stop() + self._conn = None + self._stop() _logger.debug("%r: disconnected (reason %r)", self, reason) if reason == CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED: # FIXME: handle connection failure; retry later? pass else: - # If disconnected, but still have a network connection, retry - # If disconnected and no network connection, do nothing here - # and let the IP4AddressMonitor address-changed signal handle - # reconnection - if self._could_connect() and not self._reconnect_id: - self._reconnect_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, + # Try again later. We'll detect whether we have a network + # connection after the retry period elapses. The fact that + # this timer is running also serves as a marker to indicate + # that we shouldn't try to go back online yet. + if self._backoff_id: + gobject.source_remove(self._backoff_id) + self._backoff_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, self._reconnect_cb) self.emit('status', self._conn_status, int(reason)) def _could_connect(self): - return True + # Don't allow connection unless the reconnect timeout has elapsed, + # or this is the first attempt + return (self._backoff_id == 0) - def stop(self): + def _stop(self): """If we still have a connection, disconnect it""" matches = self._matches @@ -266,12 +280,12 @@ class TelepathyPlugin(gobject.GObject): if self._online_contacts: self._contacts_offline(self._online_contacts) - if self._reconnect_id > 0: - gobject.source_remove(self._reconnect_id) - self._reconnect_id = 0 - def cleanup(self): - self.stop() + self._stop() + + if self._backoff_id > 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = 0 def _contacts_offline(self, handles): """Handle contacts going offline (send message, update set)""" @@ -454,13 +468,11 @@ class TelepathyPlugin(gobject.GObject): otherwise initiate a connection and transfer control to _connect_reply_cb or _connect_error_cb """ + if self._conn is not None: + return _logger.debug("%r: Starting up...", self) - if self._reconnect_id > 0: - gobject.source_remove(self._reconnect_id) - self._reconnect_id = 0 - # Only init connection if we have a valid IP address if self._could_connect(): self._init_connection() -- cgit v0.9.1