# $Id: __init__.py,v 1.1.1.1 2005/06/27 08:37:21 dieter Exp $ '''ZEOKeepAlive. Our cluster checks made us aware that 'ZEOClientStorage' depends on the operating system to inform about connection breaks and that this cannot do this reliably during inactivity periods. This product starts a thread that periodically sends a keep alive message to all ZEO connections. Sending will fail when the connection is no longer intact triggering 'ZEOClientStorage's automatic reconnect. The thread is controlled by the environment variable 'ZEO_KEEPALIVE_PERIOD'. If not specified, the keep alive thread is not started. For use by non Zope ZEO clients, it defines the function 'startThread'. It has the optional argument 'period' specifying the period (default: use value given by environment variable 'ZEO_KEEPALIVE_PERIOD'). As in 'ZEOClientStorage', we assume that no communication will hang, not even under abnormal conditions. The solution would be much more complex had we not made this assumption. Logs We log as 'INFO' whether or not we start the keep alive thread. We log as 'WARNING' unready storages We log as 'BLATHER' send and response events for keep alive messages ''' from os import environ from time import sleep from thread import start_new_thread from zLOG import LOG, INFO, WARNING, BLATHER, ERROR, PANIC from App.config import getConfiguration from ZEO.ClientStorage import ClientStorage _period = None def startThread(period=None): global _period if _period: raise ValueError('KeepAlive thread already started') if period is None: period = environ.get('ZEO_KEEPALIVE_PERIOD') if period is not None: period = int(period) period = _period = period and period > 0 and period _log(INFO, period and 'Thread started with period %s sec' % period or 'Thread not started' ) if period: start_new_thread(_keepAlive, (period,)) def initialize(context): startThread() def _keepAlive(period): try: while True: sleep(period) dbs = getConfiguration().dbtab for db in dbs.opened.values(): S = db._storage if isinstance(S, ClientStorage): name = S.getName() if S._ready.isSet(): _log(BLATHER, "Sending keep alive for %s" % name) S._load_lock.acquire() try: try: S._server.get_info() _log(BLATHER, "Keep alive for %s successful" % name) except: _log(ERROR, "Keep alive for %s failed" % name, error=True) finally: S._load_lock.release() else: _log(WARNING, "Connection for %s is down" % name) except: _log(PANIC, "Exception in keep alive thread", error=True) def _log(*args, **kw): LOG('ZEO KeepAlive', *args, **kw)