Exemplo n.º 1
0
 def killContext(self, contextName):
     contextKey = self.contextKeys[contextName]
     LOG("Killing context '" + contextName + "':" + repr(contextKey), level = LOG_PROC )
     self.__ctxIFC.disconnect( contextKey, eoc = False )
     ProcessManager.instance().killProcess( contextName )
     LOG("Context killed", level = LOG_PROC )
     self.contextStatus[contextName] = LstMessages.DATA_CTX_AVAILABLE
     self.clearContext(contextName)
     # Now kill all associated executors
     try:
         registry = ProcessRegistry("CTX_" + contextName, True)
         executors = registry.getProcesses()
         for ex in executors:
             LOG("Killing child executor " + str(ex))
             ProcessManager.instance().killPID(ex.getPID())
             registry.removeProcess(ex.getName())
     except BaseException,ex:
         LOG("Unable to kill associated executors in context " + contextName + ": " + str(ex), LOG_ERROR )
Exemplo n.º 2
0
 def killContext(self, contextName):
     contextKey = self.contextKeys[contextName]
     LOG("Killing context '" + contextName + "':" + repr(contextKey),
         level=LOG_PROC)
     self.__ctxIFC.disconnect(contextKey, eoc=False)
     ProcessManager.instance().killProcess(contextName)
     LOG("Context killed", level=LOG_PROC)
     self.contextStatus[contextName] = LstMessages.DATA_CTX_AVAILABLE
     self.clearContext(contextName)
     # Now kill all associated executors
     try:
         registry = ProcessRegistry("CTX_" + contextName, True)
         executors = registry.getProcesses()
         for ex in executors:
             LOG("Killing child executor " + str(ex))
             ProcessManager.instance().killPID(ex.getPID())
             registry.removeProcess(ex.getName())
     except BaseException, ex:
         LOG(
             "Unable to kill associated executors in context " +
             contextName + ": " + str(ex), LOG_ERROR)
Exemplo n.º 3
0
class ListenerClass(object):
    
    """
    Main class of the SPEL Listener entity. Listens at a given port waiting for
    GUI connections. Manages the SPEL Context processes on GUI requests.
    """
    
    # Client key list
    clientKeys = []
    # Context list
    contexts = []
    # Holds contextID / key pairs
    contextKeys = {}
    # Holds contextID / port pairs
    contextPorts = {}
    # Context status (available/running)
    contextStatus = {}
    # GUI operations delegate
    GUI_Operations = None
    # Synchronization issues
    buffer = None
    # IPC context interface
    __ctxIFC = None 
    # IPC gui interface
    __guiIFC = None 
    # Client lock
    __clientLock = None
    # Context lock
    __ctxLock = None
    
    #===========================================================================
    def __init__(self, warmStart=False):
        self.openContexts = {}
        self.buffer = Queue(1)
        self.GUI_Operations = GUIOperations(self)
        # Obtain the list of available contexts from cfg file
        self.contexts = Config.instance().getAvailableContexts()
        # Update the context status map (all available)
        for ctx in self.contexts:
            self.contextPorts[ctx] = 0
            self.contextStatus[ctx] = LstMessages.DATA_CTX_AVAILABLE
        self.__ctxIFC = IPCinterfaceServer("LST-CTX")
        self.__guiIFC = IPCinterfaceServer("LST-GUI")
        self.__clientLock = thread.allocate_lock()
        self.__ctxLock = thread.allocate_lock()
        self.__contextRegistry = ProcessRegistry("LST", warmStart)
    
    #===========================================================================
    def start(self):
        
        # Get the port number from configuration
        port = Config.instance().getProperty(LISTENER, "ListenerPort")
        LOG("Listening at port: " + str(port), level = LOG_INIT )
        
        # Setup the GUI io channel
        LOG("Setting up GUI channel", level = LOG_INIT)
        self.__guiIFC.connect(999, int(port), self.processGuiMessage, self.processGuiRequest, self.clientConnectionLost)
        self.__guiIFC.start()

        # Setup the Context io channel
        LOG("Setting up CTX channel", level = LOG_INIT)
        self.__ctxIFC.connect(998,0,self.processCtxMessage, self.processCtxRequest, self.contextConnectionLost)
        self.__ctxIFC.start()
        LOG("Ready", level = LOG_INIT )
        
        #Restoring warm context
        for contextInfo in self.__contextRegistry.getProcesses():
            #Only during startup we open contexts in warm mode
            self.openContext(contextInfo.getName(), None, True) 
   
    #===========================================================================
    def stop(self):
        LOG("Stopping, closing contexts", level = LOG_PROC )
        for contextName in self.contexts:
            if self.isContextRunning(contextName):
                self.closeContext(contextName)
        LOG("Killing remaining processes", level = LOG_PROC )
        ProcessManager.instance().killAll()
        self.__guiIFC.disconnect()
        self.__ctxIFC.disconnect()
        LOG("Disconnected", level = LOG_INIT )
        
    #===========================================================================
    def clientConnectionLost(self, clientKey):
        if clientKey in self.clientKeys:
            LOG("Listener lost connection with client: " + repr(clientKey), LOG_ERROR )
            self.clientKeys.remove(clientKey)

    #===========================================================================
    def contextConnectionLost(self, contextKey):
        # Obtain the corresponding name from the key
        for key in self.contextKeys:
            if self.contextKeys[key] == contextKey:
                contextName = key
        originalStatus = self.contextStatus[contextName]
        self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
        if not originalStatus == LstMessages.DATA_CTX_STARTING:
            LOG("Listener lost connection with starting context " + repr(contextName), LOG_ERROR)
        else:
            LOG("Listener lost connection with context " + repr(contextName), LOG_ERROR)
        self.notifyContextCrash(contextName)
        self.clearContext(contextName)
        self.__ctxIFC.disconnect(contextKey, eoc = False)
        LOG("Context-lost done")
        
    #===========================================================================
    def contextProcessLost(self, contextName, retCode):
        if (retCode == 0) and not contextName in self.contextKeys:
            LOG("Context finished with code 0")
            return
        self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
        if contextName in self.contexts:
            LOG("Listener lost track of context " + repr(contextName), LOG_ERROR)
            self.notifyContextCrash(contextName)
            self.clearContext(contextName)
            if contextName in self.contextKeys:
                contextKey = self.contextKeys[contextName]
                self.__ctxIFC.disconnect(contextKey, eoc = False)
            LOG("Done")
        
    #===========================================================================
    def processGuiMessage(self, msg):
        self.__clientLock.acquire()
        LOG("Received GUI message: " + msg.getId(), level = LOG_COMM)
        guiKey = int(msg.getKey())
        if msg.getId() == LstMessages.MSG_GUI_LOGIN:
            LOG("Client logged in: " + str(guiKey), level = LOG_PROC)
            self.clientKeys.append(guiKey)
        elif msg.getId() == LstMessages.MSG_GUI_LOGOUT:
            self.clientKeys.remove(guiKey)
            LOG("Client logged out: " + str(guiKey), level = LOG_PROC)
        else:
            LOG("ERROR: unknown message from client: " + str(msg.getId()), LOG_ERROR)
        self.__clientLock.release()

    #===========================================================================
    def processCtxMessage(self, msg):
        self.__ctxLock.acquire()
        LOG("Received Context message: " + msg.getId(), level = LOG_COMM)
        if msg.getId() == LstMessages.MSG_CONTEXT_OPEN:
            contextName = msg[LstMessages.FIELD_CTX_NAME]
            LOG("Context logged in: " + contextName, level = LOG_PROC)
            contextKey = int(msg.getKey())
            ctxPort = msg[LstMessages.FIELD_CTX_PORT]
            self.contextPorts[contextName] = ctxPort
            self.contextStatus[contextName] = LstMessages.DATA_CTX_RUNNING
            self.contextKeys[contextName] = contextKey
            self.buffer.put(ctxPort, True)
        elif msg.getId() == LstMessages.MSG_CONTEXT_CLOSED:
            contextName = msg[LstMessages.FIELD_CTX_NAME]
            contextKey = int(msg.getKey())
            LOG("Context logged out: " + contextName + ":" + repr(contextKey), level = LOG_PROC)
            self.contextStatus[contextName] = LstMessages.DATA_CTX_AVAILABLE
            self.buffer.put(contextName, True)
        else:
            LOG("ERROR: unknown message from context:" + str(msg.getId()), LOG_ERROR)
        self.__ctxLock.release()
            
    #===========================================================================
    def processGuiRequest(self, msg):
        self.__clientLock.acquire()
        resp = self.GUI_Operations.processRequest(msg)
        self.__clientLock.release()
        return resp

    #===========================================================================
    def processCtxRequest(self, msg):
        self.__ctxLock.acquire()
        resp = self.createResponse("NONE", msg)
        self.__ctxLock.release()
        return resp
            
    #===========================================================================
    def openContext(self, contextName, clientKey = None, warm = False ):
        
        ctxScript = Config.instance().getProperty(LISTENER, "ContextScript")
        ctxScript = Config.instance().getHome() + os.sep + ctxScript
        arguments = "-c \"" + Config.instance().filename + "\" -n \"" + contextName + "\""
        arguments += " -s " + str(self.__ctxIFC.port)
        if warm == True:
            arguments += " -w"
        pythonBin = os.getenv("PYTHON", "python")
        ctxScript = pythonBin + " \"" + ctxScript + "\" " + arguments
        
        # Set the status as starting (internal)
        self.contextStatus[contextName] = LstMessages.DATA_CTX_STARTING
        
        LOG("Starting context: '" + contextName + "'", level = LOG_PROC )
        pid = ProcessManager.instance().startProcess( contextName, ctxScript, self.contextProcessLost )
        LOG("Context started with pid " + str(pid), level = LOG_PROC )

        LOG("Waiting context port", level = LOG_PROC )
        try:
            ctxPort = self.buffer.get(True,CONTEXT_START_TIMEO)
            LOG("Context port is " + str(ctxPort), level = LOG_PROC )
            # Set the status as started
            self.contextStatus[contextName] = LstMessages.DATA_CTX_RUNNING
            self.notifyContextUpdate(contextName,clientKey)
            self.__contextRegistry.addProcess(pid,contextName)
            return ctxPort
        except BaseException,ex:
            txt = "Failed to open context"
            reason = "Unable to get context listening port"
            LOG(txt + ": " + reason, LOG_ERROR)
            self.killContext(contextName)
            # Set the status as error
            self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
            self.notifyContextUpdate(contextName,clientKey,txt,reason)
            return None
Exemplo n.º 4
0
class ListenerClass(object):
    """
    Main class of the SPEL Listener entity. Listens at a given port waiting for
    GUI connections. Manages the SPEL Context processes on GUI requests.
    """

    # Client key list
    clientKeys = []
    # Context list
    contexts = []
    # Holds contextID / key pairs
    contextKeys = {}
    # Holds contextID / port pairs
    contextPorts = {}
    # Context status (available/running)
    contextStatus = {}
    # GUI operations delegate
    GUI_Operations = None
    # Synchronization issues
    buffer = None
    # IPC context interface
    __ctxIFC = None
    # IPC gui interface
    __guiIFC = None
    # Client lock
    __clientLock = None
    # Context lock
    __ctxLock = None

    #===========================================================================
    def __init__(self, warmStart=False):
        self.openContexts = {}
        self.buffer = Queue(1)
        self.GUI_Operations = GUIOperations(self)
        # Obtain the list of available contexts from cfg file
        self.contexts = Config.instance().getAvailableContexts()
        # Update the context status map (all available)
        for ctx in self.contexts:
            self.contextPorts[ctx] = 0
            self.contextStatus[ctx] = LstMessages.DATA_CTX_AVAILABLE
        self.__ctxIFC = IPCinterfaceServer("LST-CTX")
        self.__guiIFC = IPCinterfaceServer("LST-GUI")
        self.__clientLock = thread.allocate_lock()
        self.__ctxLock = thread.allocate_lock()
        self.__contextRegistry = ProcessRegistry("LST", warmStart)

    #===========================================================================
    def start(self):

        # Get the port number from configuration
        port = Config.instance().getProperty(LISTENER, "ListenerPort")
        LOG("Listening at port: " + str(port), level=LOG_INIT)

        # Setup the GUI io channel
        LOG("Setting up GUI channel", level=LOG_INIT)
        self.__guiIFC.connect(999, int(port), self.processGuiMessage,
                              self.processGuiRequest,
                              self.clientConnectionLost)
        self.__guiIFC.start()

        # Setup the Context io channel
        LOG("Setting up CTX channel", level=LOG_INIT)
        self.__ctxIFC.connect(998, 0, self.processCtxMessage,
                              self.processCtxRequest,
                              self.contextConnectionLost)
        self.__ctxIFC.start()
        LOG("Ready", level=LOG_INIT)

        #Restoring warm context
        for contextInfo in self.__contextRegistry.getProcesses():
            #Only during startup we open contexts in warm mode
            self.openContext(contextInfo.getName(), None, True)

    #===========================================================================
    def stop(self):
        LOG("Stopping, closing contexts", level=LOG_PROC)
        for contextName in self.contexts:
            if self.isContextRunning(contextName):
                self.closeContext(contextName)
        LOG("Killing remaining processes", level=LOG_PROC)
        ProcessManager.instance().killAll()
        self.__guiIFC.disconnect()
        self.__ctxIFC.disconnect()
        LOG("Disconnected", level=LOG_INIT)

    #===========================================================================
    def clientConnectionLost(self, clientKey):
        if clientKey in self.clientKeys:
            LOG("Listener lost connection with client: " + repr(clientKey),
                LOG_ERROR)
            self.clientKeys.remove(clientKey)

    #===========================================================================
    def contextConnectionLost(self, contextKey):
        # Obtain the corresponding name from the key
        for key in self.contextKeys:
            if self.contextKeys[key] == contextKey:
                contextName = key
        originalStatus = self.contextStatus[contextName]
        self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
        if not originalStatus == LstMessages.DATA_CTX_STARTING:
            LOG(
                "Listener lost connection with starting context " +
                repr(contextName), LOG_ERROR)
        else:
            LOG("Listener lost connection with context " + repr(contextName),
                LOG_ERROR)
        self.notifyContextCrash(contextName)
        self.clearContext(contextName)
        self.__ctxIFC.disconnect(contextKey, eoc=False)
        LOG("Context-lost done")

    #===========================================================================
    def contextProcessLost(self, contextName, retCode):
        if (retCode == 0) and not contextName in self.contextKeys:
            LOG("Context finished with code 0")
            return
        self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
        if contextName in self.contexts:
            LOG("Listener lost track of context " + repr(contextName),
                LOG_ERROR)
            self.notifyContextCrash(contextName)
            self.clearContext(contextName)
            if contextName in self.contextKeys:
                contextKey = self.contextKeys[contextName]
                self.__ctxIFC.disconnect(contextKey, eoc=False)
            LOG("Done")

    #===========================================================================
    def processGuiMessage(self, msg):
        self.__clientLock.acquire()
        LOG("Received GUI message: " + msg.getId(), level=LOG_COMM)
        guiKey = int(msg.getKey())
        if msg.getId() == LstMessages.MSG_GUI_LOGIN:
            LOG("Client logged in: " + str(guiKey), level=LOG_PROC)
            self.clientKeys.append(guiKey)
        elif msg.getId() == LstMessages.MSG_GUI_LOGOUT:
            self.clientKeys.remove(guiKey)
            LOG("Client logged out: " + str(guiKey), level=LOG_PROC)
        else:
            LOG("ERROR: unknown message from client: " + str(msg.getId()),
                LOG_ERROR)
        self.__clientLock.release()

    #===========================================================================
    def processCtxMessage(self, msg):
        self.__ctxLock.acquire()
        LOG("Received Context message: " + msg.getId(), level=LOG_COMM)
        if msg.getId() == LstMessages.MSG_CONTEXT_OPEN:
            contextName = msg[LstMessages.FIELD_CTX_NAME]
            LOG("Context logged in: " + contextName, level=LOG_PROC)
            contextKey = int(msg.getKey())
            ctxPort = msg[LstMessages.FIELD_CTX_PORT]
            self.contextPorts[contextName] = ctxPort
            self.contextStatus[contextName] = LstMessages.DATA_CTX_RUNNING
            self.contextKeys[contextName] = contextKey
            self.buffer.put(ctxPort, True)
        elif msg.getId() == LstMessages.MSG_CONTEXT_CLOSED:
            contextName = msg[LstMessages.FIELD_CTX_NAME]
            contextKey = int(msg.getKey())
            LOG("Context logged out: " + contextName + ":" + repr(contextKey),
                level=LOG_PROC)
            self.contextStatus[contextName] = LstMessages.DATA_CTX_AVAILABLE
            self.buffer.put(contextName, True)
        else:
            LOG("ERROR: unknown message from context:" + str(msg.getId()),
                LOG_ERROR)
        self.__ctxLock.release()

    #===========================================================================
    def processGuiRequest(self, msg):
        self.__clientLock.acquire()
        resp = self.GUI_Operations.processRequest(msg)
        self.__clientLock.release()
        return resp

    #===========================================================================
    def processCtxRequest(self, msg):
        self.__ctxLock.acquire()
        resp = self.createResponse("NONE", msg)
        self.__ctxLock.release()
        return resp

    #===========================================================================
    def openContext(self, contextName, clientKey=None, warm=False):

        ctxScript = Config.instance().getProperty(LISTENER, "ContextScript")
        ctxScript = Config.instance().getHome() + os.sep + ctxScript
        arguments = "-c \"" + Config.instance(
        ).filename + "\" -n \"" + contextName + "\""
        arguments += " -s " + str(self.__ctxIFC.port)
        if warm == True:
            arguments += " -w"
        pythonBin = os.getenv("PYTHON", "python")
        ctxScript = pythonBin + " \"" + ctxScript + "\" " + arguments

        # Set the status as starting (internal)
        self.contextStatus[contextName] = LstMessages.DATA_CTX_STARTING

        LOG("Starting context: '" + contextName + "'", level=LOG_PROC)
        pid = ProcessManager.instance().startProcess(contextName, ctxScript,
                                                     self.contextProcessLost)
        LOG("Context started with pid " + str(pid), level=LOG_PROC)

        LOG("Waiting context port", level=LOG_PROC)
        try:
            ctxPort = self.buffer.get(True, CONTEXT_START_TIMEO)
            LOG("Context port is " + str(ctxPort), level=LOG_PROC)
            # Set the status as started
            self.contextStatus[contextName] = LstMessages.DATA_CTX_RUNNING
            self.notifyContextUpdate(contextName, clientKey)
            self.__contextRegistry.addProcess(pid, contextName)
            return ctxPort
        except BaseException, ex:
            txt = "Failed to open context"
            reason = "Unable to get context listening port"
            LOG(txt + ": " + reason, LOG_ERROR)
            self.killContext(contextName)
            # Set the status as error
            self.contextStatus[contextName] = LstMessages.DATA_CTX_ERROR
            self.notifyContextUpdate(contextName, clientKey, txt, reason)
            return None