# ********************************************************************** # # Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** """ Glacier2 module """ import threading, traceback, copy # # Import the Python extension. # import Ice Ice.updateModule("Glacier2") import Glacier2_Router_ice import Glacier2_Session_ice import Glacier2_PermissionsVerifier_ice import Glacier2_SSLInfo_ice class SessionNotExistException(Exception): def __init__(self): pass class RestartSessionException(Exception): def __init__(self): pass class AMI_Router_refreshSessionI: def __init__(self, app, pinger): self._app = app self._pinger = pinger def ice_response(self): pass def ice_exception(self, ex): # Here the session has gone. The thread # terminates, and we notify the # application that the session has been # destroyed. self._pinger.done() self._app.sessionDestroyed() class SessionPingThread(threading.Thread): def __init__(self, app, router, period): threading.Thread.__init__(self) self._app = app self._router = router self._period = period self._done = False self._cond = threading.Condition() def run(self): self._cond.acquire() try: while not self._done: self._router.refreshSession_async(AMI_Router_refreshSessionI(self._app, self)) if not self._done: self._cond.wait(self._period) finally: self._cond.release() def done(self): self._cond.acquire() try: if not self._done: self._done = True self._cond.notify() finally: self._cond.release() class Application(Ice.Application): def __init__(self, signalPolicy=0): # HandleSignals=0 '''The constructor accepts an optional argument indicating whether to handle signals. The value should be either Application.HandleSignals (the default) or Application.NoSignalHandling. ''' if type(self) == Application: raise RuntimeError("Glacier2.Application is an abstract class") Ice.Application.__init__(self, signalPolicy) Application._adapter = None Application._router = None Application._session = None Application._createdSession = False Application._category = None def run(self, args): raise RuntimeError('run should not be called on Glacier2.Application - call runWithSession instead') def runWithSession(self, args): raise RuntimeError('runWithSession() not implemented') def createSession(self, args): raise RuntimeError('createSession() not implemented') def restart(self): raise RestartSessionException() def sessionDestroyed(self): pass def router(self): return Application._router router = classmethod(router) def session(self): return Application._session session = classmethod(session) def categoryForClient(self): if Application._router == None: raise SessionNotExistException() return Application._category def createCallbackIdentity(self, name): return Ice.Identity(name, self.categoryForClient()) def addWithUUID(self, servant): return objectAdapter().add(servant, createCallbackIdentity(Ice.generateUUID())) def objectAdapter(self): if Application._router == None: raise SessionNotExistException() if Application._adapter == None: Application._adapter = self.communicator().createObjectAdapterWithRouter("", Application._router) Application._adapter.activate() return Application._adapter def doMainInternal(self, args, initData): # Reset internal state variables from Ice.Application. The # remainder are reset at the end of this method. Ice.Application._callbackInProgress = False Ice.Application._destroyed = False Ice.Application._interrupted = False restart = False status = 0 ping = None try: Ice.Application._communicator = Ice.initialize(args, initData) Application._router = RouterPrx.uncheckedCast(Ice.Application.communicator().getDefaultRouter()) if Application._router == None: Ice.getProcessLogger().error("no glacier2 router configured") status = 1 else: # # The default is to destroy when a signal is received. # if Ice.Application._signalPolicy == Ice.Application.HandleSignals: Ice.Application.destroyOnInterrupt() # If createSession throws, we're done. try: Application._session = self.createSession() Application._createdSession = True except Ice.LocalException: Ice.getProcessLogger().error(traceback.format_exc()) status = 1 if Application._createdSession: timeout = Application._router.getSessionTimeout(); if timeout > 0: ping = SessionPingThread(self, Application._router, timeout / 2) ping.start() Application._category = Application._router.getCategoryForClient() status = self.runWithSession(args) # We want to restart on those exceptions which indicate a # break down in communications, but not those exceptions that # indicate a programming logic error (ie: marshal, protocol # failure, etc). except(RestartSessionException): restart = True except(Ice.ConnectionRefusedException, Ice.ConnectionLostException, Ice.UnknownLocalException, \ Ice.RequestFailedException, Ice.TimeoutException): Ice.getProcessLogger().error(traceback.format_exc()) restart = True except: Ice.getProcessLogger().error(traceback.format_exc()) status = 1 # # Don't want any new interrupt and at this point (post-run), # it would not make sense to release a held signal to run # shutdown or destroy. # if Ice.Application._signalPolicy == Ice.Application.HandleSignals: Ice.Application.ignoreInterrupt() Ice.Application._condVar.acquire() while Ice.Application._callbackInProgress: Ice.Application._condVar.wait() if Ice.Application._destroyed: Ice.Application._communicator = None else: Ice.Application._destroyed = True # # And _communicator != None, meaning will be destroyed # next, _destroyed = True also ensures that any # remaining callback won't do anything # Ice.Application._condVar.release() if ping: ping.done() ping.join() if Application._createdSession and Application._router: try: Application._router.destroySession() except (Ice.ConnectionLostException, SessionNotExistException): pass except: Ice.getProcessLogger().error("unexpected exception when destroying the session " + \ traceback.format_exc()) Application._router = None if Ice.Application._communicator: try: Ice.Application._communicator.destroy() except: getProcessLogger().error(traceback.format_exc()) status = 1 Ice.Application._communicator = None # Reset internal state. We cannot reset the Application state # here, since _destroyed must remain true until we re-run # this method. Application._adapter = None Application._router = None Application._session = None Application._createdSession = False Application._category = None return (restart, status) def doMain(self, args, initData): # Set the default properties for all Glacier2 applications. initData.properties.setProperty("Ice.ACM.Client", "0") initData.properties.setProperty("Ice.RetryIntervals", "-1") restart = True ret = 0 while restart: # A copy of the initialization data and the string seq # needs to be passed to doMainInternal, as these can be # changed by the application. id = copy.copy(initData) if id.properties: id.properties = id.properties.clone() argsCopy = args[:] (restart, ret) = self.doMainInternal(argsCopy, initData) return ret