# ********************************************************************** # # Copyright (c) 2003-2009 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. # # ********************************************************************** """ Ice module """ import sys, exceptions, string, imp, os, threading, warnings, datetime # # Import the Python extension. # import IcePy # # Add some symbols to the Ice module. # ObjectPrx = IcePy.ObjectPrx stringVersion = IcePy.stringVersion intVersion = IcePy.intVersion generateUUID = IcePy.generateUUID loadSlice = IcePy.loadSlice # # This value is used as the default value for struct types in the constructors # of user-defined types. It allows us to determine whether the application has # supplied a value. (See bug 3676) # _struct_marker = object() # # Core Ice types. # class Object(object): def ice_isA(self, id, current=None): '''Determines whether the target object supports the interface denoted by the given Slice type id. Arguments: id The Slice type id Returns: True if the target object supports the interface, or false otherwise. ''' return id in self.ice_ids() def ice_ping(self, current=None): '''A reachability test for the target object.''' pass def ice_ids(self, current=None): '''Obtains the type ids corresponding to the Slice interface that are supported by the target object. Returns: A list of type ids. ''' return [ self.ice_id() ] def ice_id(self, current=None): '''Obtains the type id corresponding to the most-derived Slice interface supported by the target object. Returns: The type id. ''' return '::Ice::Object' def ice_staticId(): '''Obtains the type id of this Slice class or interface. Returns: The type id. ''' return '::Ice::Object' ice_staticId = staticmethod(ice_staticId) # # Do not define these here. They will be invoked if defined by a subclass. # #def ice_preMarshal(self): # pass # #def ice_postUnmarshal(self): # pass # # LocalObject is deprecated; use the Python base 'object' type instead. # class LocalObject(object): pass class Blobject(Object): '''Special-purpose servant base class that allows a subclass to handle synchronous Ice invocations as "blobs" of bytes.''' def ice_invoke(self, bytes, current): '''Dispatch a synchronous Ice invocation. The operation's arguments are encoded in the bytes argument. The return value must be a tuple of two values: the first is a boolean indicating whether the operation succeeded (True) or raised a user exception (False), and the second is the encoded form of the operation's results or the user exception. ''' pass class BlobjectAsync(Object): '''Special-purpose servant base class that allows a subclass to handle asynchronous Ice invocations as "blobs" of bytes.''' def ice_invoke_async(self, cb, bytes, current): '''Dispatch an asynchronous Ice invocation. The operation's arguments are encoded in the bytes argument. When the dispatch is complete, the subclass can invoke either ice_response or ice_exception on the supplied callback object. ''' pass # # Exceptions. # class Exception(exceptions.Exception): '''The base class for all Ice exceptions.''' def __str__(self): return self.__class__.__name__ def ice_name(self): '''Returns the type name of this exception.''' return self._ice_name class LocalException(Exception): '''The base class for all Ice run-time exceptions.''' def __init__(self, args=''): self.args = args class UserException(Exception): '''The base class for all user-defined exceptions.''' pass def getSliceDir(): '''Convenience function for locating the directory containing the Slice files.''' # # Get the parent of the directory containing this file (Ice.py). # pyHome = os.path.join(os.path.dirname(__file__), "..") # # For an installation from a source distribution, a binary tarball, or a # Windows installer, the "slice" directory is a sibling of the "python" # directory. # dir = os.path.join(pyHome, "slice") if os.path.exists(dir): return os.path.normpath(dir) # # In a source distribution, the "slice" directory is one level higher. # dir = os.path.join(pyHome, "..", "slice") if os.path.exists(dir): return os.path.normpath(dir) iceVer = stringVersion() if sys.platform[:5] == "linux": # # Check the default RPM location. # dir = os.path.join("/", "usr", "share", "Ice-" + iceVer, "slice") if os.path.exists(dir): return dir return None # # Utilities for use by generated code. # def openModule(name): if sys.modules.has_key(name): result = sys.modules[name] else: result = createModule(name) return result def createModule(name): l = string.split(name, ".") curr = '' mod = None for s in l: curr = curr + s if sys.modules.has_key(curr): mod = sys.modules[curr] else: nmod = imp.new_module(curr) if mod: setattr(mod, s, nmod) sys.modules[curr] = nmod mod = nmod curr = curr + "." return mod def createTempClass(): class __temp: pass return __temp # # Forward declarations. # IcePy._t_Object = IcePy.declareClass('::Ice::Object') IcePy._t_ObjectPrx = IcePy.declareProxy('::Ice::Object') IcePy._t_LocalObject = IcePy.declareClass('::Ice::LocalObject') # # Sequence mappings. # IcePy.SEQ_DEFAULT = 0 IcePy.SEQ_TUPLE = 1 IcePy.SEQ_LIST = 2 #IcePy.SEQ_ARRAY = 3 # # Slice checksum dictionary. # sliceChecksums = {} # # Import generated Ice modules. # import Ice_BuiltinSequences_ice import Ice_Communicator_ice import Ice_Current_ice import Ice_ImplicitContext_ice import Ice_Endpoint_ice import Ice_EndpointTypes_ice import Ice_Identity_ice import Ice_LocalException_ice import Ice_Locator_ice import Ice_Logger_ice import Ice_ObjectAdapter_ice import Ice_ObjectFactory_ice import Ice_Properties_ice import Ice_Router_ice import Ice_ServantLocator_ice # # Replace EndpointInfo with our implementation. # #del EndpointInfo #Endpoint = IcePy.EndpointInfo #del TcpEndpointInfo #TcpEndpointInfo = IcePy.TcpEndpointInfo #del UdpEndpointInfo #UdpEndpointInfo = IcePy.UdpEndpointInfo #del OpaqueEndpointInfo #OpaqueEndpointInfo = IcePy.OpaqueEndpointInfo class ThreadNotification(object): '''Base class for thread notification callbacks. A subclass must define the start and stop methods.''' def __init__(self): pass def start(): '''Invoked in the context of a thread created by the Ice run time.''' pass def stop(): '''Invoked in the context of an Ice run-time thread that is about to terminate.''' pass # # Initialization data. # class InitializationData(object): '''The attributes of this class are used to initialize a new communicator instance. The supported attributes are as follows: properties: An instance of Ice.Properties. You can use the Ice.createProperties function to create a new property set. logger: An instance of Ice.Logger. threadHook: An object that implements ThreadNotification. ''' def __init__(self): self.properties = None self.logger = None #self.stats = None # Stats not currently supported in Python. self.threadHook = None # # Communicator wrapper. # class CommunicatorI(Communicator): def __init__(self, impl): self._impl = impl impl._setWrapper(self) def destroy(self): self._impl.destroy() def shutdown(self): self._impl.shutdown() def waitForShutdown(self): # # If invoked by the main thread, waitForShutdown only blocks for # the specified timeout in order to give us a chance to handle # signals. # while not self._impl.waitForShutdown(500): pass def isShutdown(self): return self._impl.isShutdown() def stringToProxy(self, str): return self._impl.stringToProxy(str) def proxyToString(self, obj): return self._impl.proxyToString(obj) def propertyToProxy(self, str): return self._impl.propertyToProxy(str) def stringToIdentity(self, str): return self._impl.stringToIdentity(str) def identityToString(self, ident): return self._impl.identityToString(ident) def createObjectAdapter(self, name): adapter = self._impl.createObjectAdapter(name) return ObjectAdapterI(adapter) def createObjectAdapterWithEndpoints(self, name, endpoints): adapter = self._impl.createObjectAdapterWithEndpoints(name, endpoints) return ObjectAdapterI(adapter) def createObjectAdapterWithRouter(self, name, router): adapter = self._impl.createObjectAdapterWithRouter(name, router) return ObjectAdapterI(adapter) def addObjectFactory(self, factory, id): self._impl.addObjectFactory(factory, id) def findObjectFactory(self, id): return self._impl.findObjectFactory(id) def getImplicitContext(self): context = self._impl.getImplicitContext() if context == None: return None; else: return ImplicitContextI(context) def getProperties(self): properties = self._impl.getProperties() return PropertiesI(properties) def getLogger(self): logger = self._impl.getLogger() if isinstance(logger, Logger): return logger else: return LoggerI(logger) def getStats(self): raise RuntimeError("operation `getStats' not implemented") def getDefaultRouter(self): return self._impl.getDefaultRouter() def setDefaultRouter(self, rtr): self._impl.setDefaultRouter(rtr) def getDefaultLocator(self): return self._impl.getDefaultLocator() def setDefaultLocator(self, loc): self._impl.setDefaultLocator(loc) def getPluginManager(self): raise RuntimeError("operation `getPluginManager' not implemented") def flushBatchRequests(self): self._impl.flushBatchRequests() def getAdmin(self): return self._impl.getAdmin() def addAdminFacet(self, servant, facet): self._impl.addAdminFacet(servant, facet) def removeAdminFacet(self, facet): return self._impl.removeAdminFacet(facet) # # Ice.initialize() # def initialize(args=None, data=None): '''Initializes a new communicator. The optional arguments represent an argument list (such as sys.argv) and an instance of InitializationData. You can invoke this function as follows: Ice.initialize() Ice.initialize(args) Ice.initialize(data) Ice.initialize(args, data) If you supply an argument list, the function removes those arguments from the list that were recognized by the Ice run time. ''' communicator = IcePy.Communicator(args, data) return CommunicatorI(communicator) # # ObjectAdapter wrapper. # class ObjectAdapterI(ObjectAdapter): def __init__(self, impl): self._impl = impl def getName(self): return self._impl.getName() def getCommunicator(self): communicator = self._impl.getCommunicator() return communicator._getWrapper() def activate(self): self._impl.activate() def hold(self): self._impl.hold() def waitForHold(self): # # If invoked by the main thread, waitForHold only blocks for # the specified timeout in order to give us a chance to handle # signals. # while not self._impl.waitForHold(1000): pass def deactivate(self): self._impl.deactivate() def waitForDeactivate(self): # # If invoked by the main thread, waitForDeactivate only blocks for # the specified timeout in order to give us a chance to handle # signals. # while not self._impl.waitForDeactivate(1000): pass def isDeactivated(self): self._impl.isDeactivated() def destroy(self): self._impl.destroy() def add(self, servant, id): return self._impl.add(servant, id) def addFacet(self, servant, id, facet): return self._impl.addFacet(servant, id, facet) def addWithUUID(self, servant): return self._impl.addWithUUID(servant) def addFacetWithUUID(self, servant, facet): return self._impl.addFacetWIthUUID(servant, facet) def addDefaultServant(self, servant, category): self._impl.addDefaultServant(servant, category) def remove(self, id): return self._impl.remove(id) def removeFacet(self, id, facet): return self._impl.removeFacet(id, facet) def removeAllFacets(self, id): return self._impl.removeAllFacets(id) def removeDefaultServant(self, category): return self._impl.removeDefaultServant(category) def find(self, id): return self._impl.find(id) def findFacet(self, id, facet): return self._impl.findFacet(id, facet) def findAllFacets(self, id): return self._impl.findAllFacets(id) def findByProxy(self, proxy): return self._impl.findByProxy(proxy) def findDefaultServant(self, category): return self._impl.findDefaultServant(category) def addServantLocator(self, locator, category): self._impl.addServantLocator(locator, category) def removeServantLocator(self, category): return self._impl.removeServantLocator(category) def findServantLocator(self, category): return self._impl.findServantLocator(category) def createProxy(self, id): return self._impl.createProxy(id) def createDirectProxy(self, id): return self._impl.createDirectProxy(id) def createIndirectProxy(self, id): return self._impl.createIndirectProxy(id) def createReverseProxy(self, id): return self._impl.createReverseProxy(id) def setLocator(self, loc): self._impl.setLocator(loc) def refreshPublishedEndpoints(self): self._impl.refreshPublishedEndpoints() def getEndpoints(self): return self._impl.getEndpoints() def getPublishedEndpoints(self): return self._impl.getPublishedEndpoints() # # Logger wrapper. # class LoggerI(Logger): def __init__(self, impl): self._impl = impl def _print(self, message): return self._impl._print(message) def trace(self, category, message): return self._impl.trace(category, message) def warning(self, message): return self._impl.warning(message) def error(self, message): return self._impl.error(message) # # Properties wrapper. # class PropertiesI(Properties): def __init__(self, impl): self._impl = impl def getProperty(self, key): return self._impl.getProperty(key) def getPropertyWithDefault(self, key, value): return self._impl.getPropertyWithDefault(key, value) def getPropertyAsInt(self, key): return self._impl.getPropertyAsInt(key) def getPropertyAsIntWithDefault(self, key, value): return self._impl.getPropertyAsIntWithDefault(key, value) def getPropertyAsList(self, key): return self._impl.getPropertyAsList(key) def getPropertyAsListWithDefault(self, key, value): return self._impl.getPropertyAsListWithDefault(key, value) def getPropertiesForPrefix(self, prefix): return self._impl.getPropertiesForPrefix(prefix) def setProperty(self, key, value): self._impl.setProperty(key, value) def getCommandLineOptions(self): return self._impl.getCommandLineOptions() def parseCommandLineOptions(self, prefix, options): return self._impl.parseCommandLineOptions(prefix, options) def parseIceCommandLineOptions(self, options): return self._impl.parseIceCommandLineOptions(options) def load(self, file): self._impl.load(file) def clone(self): properties = self._impl.clone() return PropertiesI(properties) def __iter__(self): dict = self._impl.getPropertiesForPrefix('') return iter(dict) def __str__(self): return str(self._impl) # # Ice.createProperties() # def createProperties(args=[], defaults=None): '''Creates a new property set. The optional arguments represent an argument list (such as sys.argv) and a property set that supplies default values. You can invoke this function as follows: Ice.createProperties() Ice.createProperties(args) Ice.createProperties(defaults) Ice.createProperties(args, defaults) If you supply an argument list, the function removes those arguments from the list that were recognized by the Ice run time. ''' properties = IcePy.createProperties(args, defaults) return PropertiesI(properties) # # Ice.getProcessLogger() # Ice.setProcessLogger() # def getProcessLogger(): '''Returns the default logger object.''' logger = IcePy.getProcessLogger() if isinstance(logger, Logger): return logger else: return LoggerI(logger) def setProcessLogger(logger): '''Sets the default logger object.''' IcePy.setProcessLogger(logger) # # ImplicitContext wrapper # class ImplicitContextI(ImplicitContext): def __init__(self, impl): self._impl = impl def setContext(self, ctx): self._impl.setContext(ctx) def getContext(self): return self._impl.getContext() def containsKey(self, key): return self._impl.containsKey(key) def get(self, key): return self._impl.get(key) def put(self, key, value): return self._impl.put(key, value) def remove(self, key): return self._impl.remove(key) # # Its not possible to block in a python signal handler since this # blocks the main thread from doing further work. As such we queue the # signal with a worker thread which then "dispatches" the signal to # the registered callback object. # # Note the interface is the same as the C++ CtrlCHandler # implementation, however, the implementation is different. # class CtrlCHandler(threading.Thread): # Class variable referring to the one and only handler for use # from the signal handling callback. _self = None def __init__(self): threading.Thread.__init__(self) if CtrlCHandler._self != None: raise RuntimeError("Only a single instance of a CtrlCHandler can be instantiated.") CtrlCHandler._self = self # State variables. These are not class static variables. self._condVar = threading.Condition() self._queue = [] self._done = False self._callback = None # # Setup and install signal handlers # if signal.__dict__.has_key('SIGHUP'): signal.signal(signal.SIGHUP, CtrlCHandler.signalHandler) if signal.__dict__.has_key('SIGBREAK'): signal.signal(signal.SIGBREAK, CtrlCHandler.signalHandler) signal.signal(signal.SIGINT, CtrlCHandler.signalHandler) signal.signal(signal.SIGTERM, CtrlCHandler.signalHandler) # Start the thread once everything else is done. self.start() # Dequeue and dispatch signals. def run(self): while True: self._condVar.acquire() while len(self._queue) == 0 and not self._done: self._condVar.wait() if self._done: self._condVar.release() break sig, callback = self._queue.pop() self._condVar.release() if callback: callback(sig) # Destroy the object. Wait for the thread to terminate and cleanup # the internal state. def destroy(self): self._condVar.acquire() self._done = True self._condVar.notify() self._condVar.release() # Wait for the thread to terminate self.join() # # Cleanup any state set by the CtrlCHandler. # if signal.__dict__.has_key('SIGHUP'): signal.signal(signal.SIGHUP, signal.SIG_DFL) if signal.__dict__.has_key('SIGBREAK'): signal.signal(signal.SIGBREAK, signal.SIG_DFL) signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) CtrlCHandler._self = None def setCallback(self, callback): self._condVar.acquire() self._callback = callback self._condVar.release() def getCallback(self): self._condVar.acquire() callback = self._callback self._condVar.release() return callback # Private. Only called by the signal handling mechanism. def signalHandler(self, sig, frame): self._self._condVar.acquire() # # The signal AND the current callback are queued together. # self._self._queue.append([sig, self._self._callback]) self._self._condVar.notify() self._self._condVar.release() signalHandler = classmethod(signalHandler) # # Application logger. # class _ApplicationLoggerI(Logger): def __init__(self, prefix): if len(prefix) > 0: self._prefix = prefix + ": " else: self._prefix = "" self._outputMutex = threading.Lock() def _print(self, message): s = "[ " + str(datetime.datetime.now()) + " " + self._prefix self._outputMutex.acquire() sys.stderr.write(message + "\n") self._outputMutex.release() def trace(self, category, message): s = "[ " + str(datetime.datetime.now()) + " " + self._prefix if len(category) > 0: s += category + ": " s += message + " ]" s = s.replace("\n", "\n ") self._outputMutex.acquire() sys.stderr.write(s + "\n") self._outputMutex.release() def warning(self, message): self._outputMutex.acquire() sys.stderr.write(str(datetime.datetime.now()) + " " + self._prefix + "warning: " + message + "\n") self._outputMutex.release() def error(self, message): self._outputMutex.acquire() sys.stderr.write(str(datetime.datetime.now()) + " " + self._prefix + "error: " + message + "\n") self._outputMutex.release() # # Application class. # import signal, traceback class Application(object): '''Convenience class that initializes a communicator and reacts gracefully to signals. An application must define a subclass of this class and supply an implementation of the run method. ''' 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("Ice.Application is an abstract class") Application._signalPolicy = signalPolicy def main(self, args, configFile=None, initData=None): '''The main entry point for the Application class. The arguments are an argument list (such as sys.argv), the name of an Ice configuration file (optional), and an instance of InitializationData (optional). This method does not return until after the completion of the run method. The return value is an integer representing the exit status. ''' if Application._communicator: getProcessLogger().error(args[0] + ": only one instance of the Application class can be used") return 1 # # We parse the properties here to extract Ice.ProgramName. # if not initData: initData = InitializationData() if configFile: try: initData.properties = createProperties(None, initData.properties) initData.properties.load(configFile) except: getProcessLogger().error(traceback.format_exc()) return 1 initData.properties = createProperties(args, initData.properties) # # If the process logger is the default logger, we replace it with a # a logger which is using the program name for the prefix. # if isinstance(getProcessLogger(), LoggerI): setProcessLogger(_ApplicationLoggerI(initData.properties.getProperty("Ice.ProgramName"))) # # Install our handler for the signals we are interested in. We assume main() # is called from the main thread. # Application._ctrlCHandler = CtrlCHandler() try: status = 0 Application._interrupted = False Application._appName = args[0] Application._application = self Application._communicator = initialize(args, initData) Application._destroyed = False # # Used by _destroyOnInterruptCallback and _shutdownOnInterruptCallback. # Application._nohup = Application._communicator.getProperties().getPropertyAsInt("Ice.Nohup") > 0 # # The default is to destroy when a signal is received. # if Application._signalPolicy == Application.HandleSignals: Application.destroyOnInterrupt() status = self.doMain(args, initData) except: 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 Application._signalPolicy == Application.HandleSignals: Application.ignoreInterrupt() Application._condVar.acquire() while Application._callbackInProgress: Application._condVar.wait() if Application._destroyed: Application._communicator = None else: Application._destroyed = True # # And _communicator != 0, meaning will be destroyed # next, _destroyed = true also ensures that any # remaining callback won't do anything # Application._application = None Application._condVar.release() if Application._communicator: try: Application._communicator.destroy() except: getProcessLogger().error(traceback.format_exc()) status = 1 Application._communicator = None # # Set _ctrlCHandler to 0 only once communicator.destroy() has # completed. # Application._ctrlCHandler.destroy() Application._ctrlCHandler = None return status def doMain(self, args, initData): self.run(args) def run(self, args): '''This method must be overridden in a subclass. The base class supplies an argument list from which all Ice arguments have already been removed. The method returns an integer exit status (0 is success, non-zero is failure). ''' raise RuntimeError('run() not implemented') def interruptCallback(self, sig): '''Subclass hook to intercept an interrupt.''' pass def appName(self): '''Returns the application name (the first element of the argument list).''' return self._appName appName = classmethod(appName) def communicator(self): '''Returns the communicator that was initialized for the application.''' return self._communicator communicator = classmethod(communicator) def destroyOnInterrupt(self): '''Configures the application to destroy its communicator when interrupted by a signal.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() == self._holdInterruptCallback: self._released = True self._condVar.notify() self._ctrlCHandler.setCallback(self._destroyOnInterruptCallback) self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") destroyOnInterrupt = classmethod(destroyOnInterrupt) def shutdownOnInterrupt(self): '''Configures the application to shutdown its communicator when interrupted by a signal.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() == self._holdInterruptCallback: self._released = True self._condVar.notify() self._ctrlCHandler.setCallback(self._shutdownOnInterruptCallback) self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") shutdownOnInterrupt = classmethod(shutdownOnInterrupt) def ignoreInterrupt(self): '''Configures the application to ignore signals.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() == self._holdInterruptCallback: self._released = True self._condVar.notify() self._ctrlCHandler.setCallback(None) self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") ignoreInterrupt = classmethod(ignoreInterrupt) def callbackOnInterrupt(self): '''Configures the application to invoke interruptCallback when interrupted by a signal.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() == self._holdInterruptCallback: self._released = True self._condVar.notify() self._ctrlCHandler.setCallback(self._callbackOnInterruptCallback) self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") callbackOnInterrupt = classmethod(callbackOnInterrupt) def holdInterrupt(self): '''Configures the application to queue an interrupt for later processing.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() != self._holdInterruptCallback: self._previousCallback = self._ctrlCHandler.getCallback() self._released = False self._ctrlCHandler.setCallback(self._holdInterruptCallback) # else, we were already holding signals self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") holdInterrupt = classmethod(holdInterrupt) def releaseInterrupt(self): '''Instructs the application to process any queued interrupt.''' if Application._signalPolicy == Application.HandleSignals: self._condVar.acquire() if self._ctrlCHandler.getCallback() == self._holdInterruptCallback: # # Note that it's very possible no signal is held; # in this case the callback is just replaced and # setting _released to true and signalling _condVar # do no harm. # self._released = True self._ctrlCHandler.setCallback(self._previousCallback) self._condVar.notify() # Else nothing to release. self._condVar.release() else: getProcessLogger().error(Application._appName + \ ": warning: interrupt method called on Application configured to not handle interrupts.") releaseInterrupt = classmethod(releaseInterrupt) def interrupted(self): '''Returns True if the application was interrupted by a signal, or False otherwise.''' self._condVar.acquire() result = self._interrupted self._condVar.release() return result interrupted = classmethod(interrupted) def _holdInterruptCallback(self, sig): self._condVar.acquire() while not self._released: self._condVar.wait() if self._destroyed: # # Being destroyed by main thread # self._condVar.release() return callback = self._ctrlCHandler.getCallback() self._condVar.release() if callback: callback(sig) _holdInterruptCallback = classmethod(_holdInterruptCallback) def _destroyOnInterruptCallback(self, sig): self._condVar.acquire() if self._destroyed or self._nohup and sig == signal.SIGHUP: # # Being destroyed by main thread, or nohup. # self._condVar.release() return self._callbackInProcess = True self._interrupted = True self._destroyed = True self._condVar.release() try: self._communicator.destroy() except: getProcessLogger().error(self._appName + " (while destroying in response to signal " + str(sig) + "):" + \ traceback.format_exc()) self._condVar.acquire() self._callbackInProcess = False self._condVar.notify() self._condVar.release() _destroyOnInterruptCallback = classmethod(_destroyOnInterruptCallback) def _shutdownOnInterruptCallback(self, sig): self._condVar.acquire() if self._destroyed or self._nohup and sig == signal.SIGHUP: # # Being destroyed by main thread, or nohup. # self._condVar.release() return self._callbackInProcess = True self._interrupted = True self._condVar.release() try: self._communicator.shutdown() except: getProcessLogger().error(self._appName + " (while shutting down in response to signal " + str(sig) + \ "):" + traceback.format_exc()) self._condVar.acquire() self._callbackInProcess = False self._condVar.notify() self._condVar.release() _shutdownOnInterruptCallback = classmethod(_shutdownOnInterruptCallback) def _callbackOnInterruptCallback(self, sig): self._condVar.acquire() if self._destroyed: # # Being destroyed by main thread. # self._condVar.release() return # For SIGHUP the user callback is always called. It can decide # what to do. self._callbackInProcess = True self._interrupted = True self._condVar.release() try: self._application.interruptCallback(sig) except: getProcessLogger().error(self._appName + " (while interrupting in response to signal " + str(sig) + \ "):" + traceback.format_exc()) self._condVar.acquire() self._callbackInProcess = False self._condVar.notify() self._condVar.release() _callbackOnInterruptCallback = classmethod(_callbackOnInterruptCallback) HandleSignals = 0 NoSignalHandling = 1 _appName = None _communicator = None _application = None _ctrlCHandler = None _previousCallback = None _interrupted = False _released = False _destroyed = False _callbackInProgress = False _condVar = threading.Condition() _signalPolicy = HandleSignals # # Define Ice::Object and Ice::ObjectPrx. # IcePy._t_Object = IcePy.defineClass('::Ice::Object', Object, (), False, None, (), ()) IcePy._t_ObjectPrx = IcePy.defineProxy('::Ice::Object', ObjectPrx) Object._ice_type = IcePy._t_Object Object._op_ice_isA = IcePy.Operation('ice_isA', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (((), IcePy._t_string),), (), IcePy._t_bool, ()) Object._op_ice_ping = IcePy.Operation('ice_ping', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), None, ()) Object._op_ice_ids = IcePy.Operation('ice_ids', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), _t_StringSeq, ()) Object._op_ice_id = IcePy.Operation('ice_id', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), IcePy._t_string, ()) IcePy._t_LocalObject = IcePy.defineClass('::Ice::LocalObject', object, (), False, None, (), ()) # # Annotate some exceptions. # def SyscallException__str__(self): return "Ice.SyscallException:\n" + os.strerror(self.error) SyscallException.__str__ = SyscallException__str__ del SyscallException__str__ def SocketException__str__(self): return "Ice.SocketException:\n" + os.strerror(self.error) SocketException.__str__ = SocketException__str__ del SocketException__str__ def ConnectFailedException__str__(self): return "Ice.ConnectFailedException:\n" + os.strerror(self.error) ConnectFailedException.__str__ = ConnectFailedException__str__ del ConnectFailedException__str__ def ConnectionRefusedException__str__(self): return "Ice.ConnectionRefusedException:\n" + os.strerror(self.error) ConnectionRefusedException.__str__ = ConnectionRefusedException__str__ del ConnectionRefusedException__str__ def ConnectionLostException__str__(self): if self.error == 0: return "Ice.ConnectionLostException:\nrecv() returned zero" else: return "Ice.ConnectionLostException:\n" + os.strerror(self.error) ConnectionLostException.__str__ = ConnectionLostException__str__ del ConnectionLostException__str__ # # Proxy comparison functions. # def proxyIdentityEqual(lhs, rhs): '''Determines whether the identities of two proxies are equal.''' return proxyIdentityCompare(lhs, rhs) == 0 def proxyIdentityCompare(lhs, rhs): '''Compares the identities of two proxies.''' if (lhs and not isinstance(lhs, ObjectPrx)) or (rhs and not isinstance(rhs, ObjectPrx)): raise ValueError('argument is not a proxy') if not lhs and not rhs: return True elif not lhs and rhs: return -1 elif lhs and not rhs: return 1 else: return cmp(lhs.ice_getIdentity(), rhs.ice_getIdentity()) def proxyIdentityAndFacetEqual(lhs, rhs): '''Determines whether the identities and facets of two proxies are equal.''' return proxyIdentityAndFacetCompare(lhs, rhs) == 0 def proxyIdentityAndFacetCompare(lhs, rhs): '''Compares the identities and facets of two proxies.''' if (lhs and not isinstance(lhs, ObjectPrx)) or (rhs and not isinstance(rhs, ObjectPrx)): raise ValueError('argument is not a proxy') if not lhs and not rhs: return True elif not lhs and rhs: return -1 elif lhs and not rhs: return 1 elif lhs.ice_getIdentity() != rhs.ice_getIdentity(): return cmp(lhs.ice_getIdentity(), rhs.ice_getIdentity()) else: return cmp(lhs.ice_getFacet(), rhs.ice_getFacet())