From f3ed778040990a63ff9301aa4b28150c9c8950f8 Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Sat, 31 Jul 2004 04:58:53 +0000 Subject: [PATCH] Refactored _getNextServer and friends as well as logging. --- src/asyncoreDrivers.py | 33 ++++++--------------- src/drivers.py | 65 +++++++++++++++++++++++++++++++++++++++++- src/socketDrivers.py | 58 ++++++++++++------------------------- src/twistedDrivers.py | 31 +++++++------------- 4 files changed, 101 insertions(+), 86 deletions(-) diff --git a/src/asyncoreDrivers.py b/src/asyncoreDrivers.py index 06fce7511..b5c1eafcf 100644 --- a/src/asyncoreDrivers.py +++ b/src/asyncoreDrivers.py @@ -43,6 +43,7 @@ import asynchat import supybot.log as log import supybot.conf as conf import supybot.ircdb as ircdb +import supybot.utils as utils import supybot.world as world import supybot.drivers as drivers import supybot.ircmsgs as ircmsgs @@ -59,48 +60,30 @@ class AsyncoreRunnerDriver(drivers.IrcDriver): else: asyncore.poll(timeout) except: - log.exception('Uncaught exception:') + drivers.log.exception('Uncaught exception:') -class AsyncoreDriver(asynchat.async_chat, object): +class AsyncoreDriver(asynchat.async_chat, drivers.ServersMixin): def __init__(self, irc, servers=()): asynchat.async_chat.__init__(self) + drivers.ServersMixin.__init__(self, irc, servers=servers) self.irc = irc self.buffer = '' - self.servers = servers - self.networkGroup = conf.supybot.networks.get(self.irc.network) self.set_terminator('\n') try: server = self._getNextServer() sock = utils.getSocket(server[0]) self.set_socket(sock) - log.info('Connecting to %s.', self.currentServer) + drivers.log.connect(self.currentServer) self.connect(server) except socket.error, e: - log.warning('Error connecting to %s: %s', self.currentServer, e) + drivers.log.connectError(self.currentServer, e) self.reconnect(wait=True) - def _getServers(self): - # We do this, rather than itertools.cycle the servers in __init__, - # because otherwise registry updates given as setValues or sets - # wouldn't be visible until a restart. - return self.networkGroup.servers()[:] # Be sure to copy! - - def _getNextServer(self): - if not self.servers: - self.servers = self._getServers() - assert self.servers, 'Servers value for %s is empty.' % \ - self.networkGroup.name - server = self.servers.pop(0) - self.currentServer = '%s:%s' % server - return server - def _scheduleReconnect(self, at=60): when = time.time() + at if not world.dying: - whenS = log.timestamp(when) - log.info('Scheduling reconnect to %s at %s', - self.currentServer, whenS) + drivers.log.reconnect(self.irc.network, when) def makeNewDriver(): self.irc.reset() driver = self.__class__(self.irc, servers=self.servers) @@ -137,7 +120,7 @@ class AsyncoreDriver(asynchat.async_chat, object): pass def die(self): - log.info('Driver for %s dying.', self.irc) + drivers.log.die(self.irc) self.close() try: diff --git a/src/drivers.py b/src/drivers.py index a48a50342..b6d6efe7d 100644 --- a/src/drivers.py +++ b/src/drivers.py @@ -41,7 +41,7 @@ import re import os import sys -import supybot.log as log +import supybot.log as supylog import supybot.conf as conf import supybot.ansi as ansi import supybot.ircmsgs as ircmsgs @@ -70,6 +70,28 @@ class IrcDriver(object): def name(self): return repr(self) +class ServersMixin(object): + def __init__(self, irc, servers=()): + self.networkGroup = conf.supybot.networks.get(irc.network) + self.servers = servers + super(ServersMixin, self).__init__(irc) + + def _getServers(self): + # We do this, rather than itertools.cycle the servers in __init__, + # because otherwise registry updates given as setValues or sets + # wouldn't be visible until a restart. + return self.networkGroup.servers()[:] # Be sure to copy! + + def _getNextServer(self): + if not self.servers: + self.servers = self._getServers() + assert self.servers, 'Servers value for %s is empty.' % \ + self.networkGroup._name + server = self.servers.pop(0) + self.currentServer = '%s:%s' % server + return server + + def empty(): """Returns whether or not the driver loop is empty.""" return (len(_drivers) + len(_newDrivers)) == 0 @@ -111,6 +133,47 @@ def run(): del _drivers[name] _drivers[name] = driver +class Log(object): + """This is used to have a nice, consistent interface for drivers to use.""" + def connect(self, server): + self.info('Connecting to %s.', server) + + def connectError(self, server, e): + if isinstance(e, Exception): + e = utils.exnToString(e) + self.warning('Error connecting to %s: %s', server, e) + + def disconnect(self, server, e=None): + if e: + if isinstance(e, Exception): + e = utils.exnToString(e) + self.warning('Disconnect from %s: %s.', server, e) + else: + self.info('Disconnect from %s.', server) + + def reconnect(self, network, when=None): + s = 'Reconnecting to %s' % network + if when is not None: + if not isinstance(when, basestring): + when = self.timestamp(when) + s += ' at %s.' % when + else: + s += '.' + self.info(s) + + def die(self, irc): + self.info('Driver for %s dying.', irc) + + debug = staticmethod(supylog.debug) + info = staticmethod(supylog.info) + warning = staticmethod(supylog.warning) + error = staticmethod(supylog.warning) + critical = staticmethod(supylog.critical) + timestamp = staticmethod(supylog.timestamp) + exception = staticmethod(supylog.exception) + +log = Log() + def newDriver(irc, moduleName=None): """Returns a new driver for the given server using the irc given and using conf.supybot.driverModule to determine what driver to pick.""" diff --git a/src/socketDrivers.py b/src/socketDrivers.py index 7fbcace00..cec50a2fa 100644 --- a/src/socketDrivers.py +++ b/src/socketDrivers.py @@ -54,11 +54,11 @@ import supybot.ircmsgs as ircmsgs import supybot.schedule as schedule reconnectWaits = (0, 60, 300) -class SocketDriver(drivers.IrcDriver): +class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): def __init__(self, irc): self.irc = irc + drivers.ServersMixin.__init__(self, irc) drivers.IrcDriver.__init__(self) # Must come after setting irc. - self.networkGroup = conf.supybot.networks.get(self.irc.network) self.servers = () self.eagains = 0 self.inbuffer = '' @@ -68,27 +68,11 @@ class SocketDriver(drivers.IrcDriver): self.reconnectWaits = reconnectWaits self.connect() - def _getServers(self): - # We do this, rather than itertools.cycle the servers in __init__, - # because otherwise registry updates given as setValues or sets - # wouldn't be visible until a restart. - return self.networkGroup.servers()[:] # Be sure to copy! - - def _getNextServer(self): - if not self.servers: - self.servers = self._getServers() - assert self.servers, 'Servers value for %s is empty.' % \ - self.networkGroup.name - server = self.servers.pop(0) - self.currentServer = '%s:%s' % server - return server - def _handleSocketError(self, e): # (11, 'Resource temporarily unavailable') raised if connect # hasn't finished yet. We'll keep track of how many we get. if e.args[0] != 11 and self.eagains > 120: - log.warning('Disconnect from %s: %s.', - self.currentServer, e.args[1]) + drivers.log.disconnect(self.currentServer, e) self.reconnect(wait=True) else: log.debug('Got EAGAIN, current count: %s.', self.eagains) @@ -137,26 +121,24 @@ class SocketDriver(drivers.IrcDriver): def reconnect(self, wait=False, reset=True): server = self._getNextServer() - if reset: - log.debug('Resetting %s.', self.irc) - self.irc.reset() - else: - log.debug('Not resetting %s.', self.irc) if self.connected: - log.info('Reconnect called on driver for %s.', self.irc) + drivers.log.reconnect(self.irc.network) self.conn.close() elif not wait: - log.info('Connecting to %s.', self.currentServer) + drivers.log.connect(self.currentServer) + if reset: + drivers.log.debug('Resetting %s.', self.irc) + self.irc.reset() + else: + drivers.log.debug('Not resetting %s.', self.irc) self.connected = False if wait: - log.info('Reconnect to %s waiting.', self.currentServer) self._scheduleReconnect() return try: self.conn = utils.getSocket(server[0]) except socket.error, e: - log.warning('Error connecting to %s: %s', - self.currentServer, e.args[1]) + drivers.log.connectError(self.currentServer, e) self.reconnect(wait=True) return # We allow more time for the connect here, since it might take longer. @@ -172,37 +154,35 @@ class SocketDriver(drivers.IrcDriver): now = time.time() when = now + 60 whenS = log.timestamp(when) - log.info('Connection in progress, scheduling connectedness ' - 'check for %s', whenS) + drivers.log.debug('Connection in progress, scheduling ' + 'connectedness check for %s', whenS) schedule.addEvent(self._checkAndWriteOrReconnect, when) else: - log.warning('Error connecting to %s: %s', self.currentServer,e) + drivers.log.connectError(self.currentServer, e) self.reconnect(wait=True) return self.connected = True self.reconnectWaitPeriodsIndex = 0 def _checkAndWriteOrReconnect(self): - log.debug('Checking whether we are connected.') + drivers.log.debug('Checking whether we are connected.') (_, w, _) = select.select([], [self.conn], [], 0) if w: - log.info('Socket is writable, it might be connected.') + drivers.log.debug('Socket is writable, it might be connected.') self.connected = True self.reconnectWaitPeriodsIndex = 0 else: - log.warning('Error connecting to %s: Timed out.',self.currentServer) + drivers.log.connectError(self.currentServer, 'Timed out') self.reconnect() def _scheduleReconnect(self): when = time.time() + self.reconnectWaits[self.reconnectWaitsIndex] if not world.dying: - whenS = log.timestamp(when) - log.info('Scheduling reconnect to %s at %s', - self.irc.network, whenS) + drivers.log.reconnect(self.irc.network, when) schedule.addEvent(self.reconnect, when) def die(self): - log.info('Driver for %s dying.', self.irc) + drivers.log.die(self.irc) self.conn.close() # self.irc.die() Kill off the ircs yourself, jerk! diff --git a/src/twistedDrivers.py b/src/twistedDrivers.py index f4340961d..f0b865805 100644 --- a/src/twistedDrivers.py +++ b/src/twistedDrivers.py @@ -50,7 +50,7 @@ class TwistedRunnerDriver(drivers.IrcDriver): try: reactor.iterate(conf.supybot.drivers.poll()) except: - log.exception('Uncaught exception outside reactor:') + drivers.log.exception('Uncaught exception outside reactor:') class SupyIrcProtocol(LineReceiver): delimiter = '\n' @@ -74,7 +74,7 @@ class SupyIrcProtocol(LineReceiver): def connectionLost(self, failure): self.mostRecentCall.cancel() self.irc.reset() - log.warning(failure.getErrorMessage()) + drivers.log.disconnect(self.currentServer, errorMsg(failure)) def connectionMade(self): self.irc.reset() @@ -82,44 +82,33 @@ class SupyIrcProtocol(LineReceiver): self.irc.driver = self def die(self): - log.info('Driver for %s dying.', self.irc) + drivers.log.die(self.irc) self.factory.continueTrying = False self.transport.loseConnection() def reconnect(self): + drivers.log.reconnect(self.irc.network) self.transport.loseConnection() +def errorMsg(reason): + return reason.getErrorMessage() -class SupyReconnectingFactory(ReconnectingClientFactory): +class SupyReconnectingFactory(ReconnectingClientFactory, drivers.ServersMixin): maxDelay = 300 protocol = SupyIrcProtocol def __init__(self, irc): self.irc = irc - self.networkGroup = conf.supybot.networks.get(self.irc.network) - self.servers = () + drivers.ServersMixin.__init__(self, irc) (server, port) = self._getNextServer() reactor.connectTCP(server, port, self) - def _getServers(self): - # We do this, rather than itertools.cycle the servers in __init__, - # because otherwise registry updates given as setValues or sets - # wouldn't be visible until a restart. - return self.networkGroup.servers()[:] # Be sure to copy! - - def _getNextServer(self): - if not self.servers: - self.servers = self._getServers() - assert self.servers, 'Servers value for %s is empty.' % \ - self.networkGroup.name - server = self.servers.pop(0) - self.currentServer = '%s:%s' % server - return server - def clientConnectionFailed(self, connector, r): + drivers.log.connectError(self.currentServer, errorMsg(r)) (connector.host, connector.port) = self._getNextServer() ReconnectingClientFactory.clientConnectionFailed(self, connector, r) def clientConnectionLost(self, connector, r): + drivers.log.disconnect(self.currentServer, errorMsg(r)) (connector.host, connector.port) = self._getNextServer() ReconnectingClientFactory.clientConnectionLost(self, connector, r)