Beispiel #1
0
 def _hpumpChild(self, mtype, spname, msg):
     #print "** mswitch._hpumpChild: mtype(%s) spname(%s)" % (mtype, spname)
     
     if mtype=="_ready":
         #print "mswitch._hpumpChild: sending `_ready` on local Bus"
         Bus.publish(self, "_ready")
         return
     
     if mtype=="_sub":
         
         try:    msgtype=msg.pop(0)
         except:
             raise RuntimeError("missing `msgType` from `_sub` message")
         
         self._addSub(self.MAIN_PNAME, msgtype)
         #print "*** mswitch_hpumpChild: child(%s) subscribing to msgtype(%s)" % (self._pname, msgtype)
         return
     
     ## All other "system" messages are ignored
     if mtype.startswith("_"):
         return
     
     ## Finally, publish whatever message we receive
     ##  from the Main process: we should have subscribed
     ##  to these anyhow (unless of course there is a bug ;-)
     #print "mswitch._hpumpChild: mtype(%s) msg(%s)" % (mtype, msg)
     Bus.publish(self, mtype, *tuple(msg))
Beispiel #2
0
 def _handleMsg(self, mtype, msg):
     """Performs message dispatching
     """
     
     ## If we are a Child instance and we receive
     ##  a message, that means we have already subscribed
     ##  to be a recipient of this message type.  Just
     ##  pass it on the local Message Bus then.
     if self._child:
         Bus.publish(self, mtype, msg)
         return True
     
     #Bus.publish(self, "log", "_handleMsg(%s)" % mtype)
     subs=self._map.get(mtype, [])
     if not subs:
         self._log("no subscribers for type(%s)" % mtype)
         return True
     
     for proc_name in subs:
         q=self._qmap.get(proc_name, None)
         if q is None:
             self._log("error", "missing 'queue' object for proc(%s)" % proc_name)
             continue
         q.put(msg)
         #self._log("queued, type(%s) for proc(%s)" % (mtype, proc_name))
     return True
Beispiel #3
0
 def _hpump(self):
     """ Pulls message(s) (if any) from the message queue
     
         Must be called periodically - it serves as "event loop"
         for the whole process (normally)
     
         A Child process:
         - "_sub"  : locally subscribe the Main process to msgType
                     This will send all local messages of msgType
                     up to the Main process where it can
                     be further distributed (multicasted)
                     
         - "_ready" : just pass along to Message Bus
         
         The Main process:
         - "_sub" : 
             - subscribe locally from Message Bus
             - send down to all Children in "split-horizon"
             
         - "_started" : just pass along on Message Bus
             
     """
     #print "mswitch._hpump: (%s) msg: %s" % (self._pname, "begin")
     
     Bus.publish(self, "%beat?")
     msg = self._getMsg()
     while (msg is not None) and (not self._term):
         self._processMsg(msg)
         msg=self._getMsgNoWait()
     Bus.publish(self, "%beat?")
Beispiel #4
0
    def _qbeat(self):
        if self._beat:
            if self._child:
                Bus.publish(self, "%beat", self.pname)
            else:
                Bus.publish(self, "beat", self.pname)

        self._beat = False  ## atomic assignment
Beispiel #5
0
 def run(self):
     while not self._exitFlag:
         try:
             Bus.publish(None, "mswitch_pump")
         except Exception,e:
             print "*** (MAIN) Comm Exception!"
             Bus.publish(None, "log", "*** (MAIN) Comm exception: %s" % e)
             break
Beispiel #6
0
 def _hstarted(self, pname):
     """ Generates `ready` message when all the
         Child processes report as being started
     """
     if self.is_child:
         return
     
     self._started.extend([pname])
     if len(self._started) == len(self._procs):
         Bus.publish(self, "_ready")
         self._ready=True
Beispiel #7
0
    def _hbeat(self, *p):
        """ Heart-beat from Main process
        """
        self._beat_count=0
        
        if self._termSent:
            return

        if self._term:
            self._termSent=True
            Bus.publish(self, "%log", "warning", "SIGTERM received, proc(%s)" % self.pname)
            Bus.publish(self, "_sigterm", self.pname)
Beispiel #8
0
 def _sendToSubscribers(self, mtype, spname, msgTail):
     msg=[mtype, spname]
     msg.extend(msgTail)
     subs=self._subs.get(mtype, [])
     #print "mswitch._sendToSubscribers: mtype(%s) subs: %s " % (mtype, subs)
     for pname in subs:
         if pname==spname:# or pname==self.MAIN_PNAME:
             continue
         
         if pname==self.MAIN_PNAME:
             Bus.publish(self, mtype, *tuple(msgTail))
         else:
             #print "mswitch._sendToSubscribers: mtype(%s) pname(%s) msg(%s)" % (mtype, pname, msg)
             q=self._getQueue(pname)
             q.put(msg)
Beispiel #9
0
 def _hstart(self):
     """ Handler for "start" message
         marking the debut of all registered processes
     """
     for proc_name in self._procs:
         procDetails=self._procs[proc_name]
         try:     proc=procDetails["proc"]
         except:  raise RuntimeError("procDetails require a `proc` entry")
             
         try:
             Bus.publish(self, "%log", "< starting process(%s)" % procDetails["name"])
             proc.start()
             Bus.publish(self, "%log", "> started process(%s)" % procDetails["name"])
         except Exception,e:
             raise RuntimeError("Exception whilst starting process (%s)" % e)
Beispiel #10
0
 def _hxbridge(self, mtype):
     """ Configures the Switch for bridging 
         the specified message type
         
         This configuration will enable this instance
         to listen on the local Message Bus for the
         specified message-type and "bridge" any much
         message toward the "subscribers".
     """
     def makeThunk(mtype):
         def _thunk(*p):
             return self._hmbus(mtype, *p)
         return _thunk
         
     ## We need a `thunk` to hold the message-type
     ##  as when the message is delivered it won't
     ##  carry this essential information
     Bus.subscribe(mtype, makeThunk(mtype))
Beispiel #11
0
    def _hpumpMain(self, mtype, spname, msg):
        
        #print "@@ mswitch._hpumpMain: mtype(%s) spname(%s)" % (mtype, spname)
        
        if mtype=="_started":
            Bus.publish(self, "started", spname)
            return
            
        if mtype=="_sub":
            try:    msgtype=msg.pop(0)
            except:
                raise RuntimeError("missing `msgType` from `_sub` message")           
            self._addSub(spname, msgtype)

            #print "*** mswitch._hpumpMain: subscribing to msgtype: ", msgtype
            
            ## repeat source message
            self._sendSplitHorizon(mtype, spname, [msgtype])
            return
        
        self._sendToSubscribers(mtype, spname, msg)
Beispiel #12
0
 def doRun(self):
            
     print "TestProcRx.doRun (%s) pid(%s)" % (self.name, os.getpid())
     Bus.publish(self, "log", "doRun: starting (%s) pid(%s)" % (self.name, os.getpid()))
     
     while not self.is_SigTerm() and not self.is_bark() and not self.is_shutdown():
         try:
             Bus.publish(self, "mswitch_pump")
         except Exception,e:
             Bus.publish(self, "log", "*** (%s) Comm Exception: %s" % (self.name, e))
             Bus.publish(self, "shutdown")
             print "getMsg, exception: ", e
             break
         sleep(0.01)
Beispiel #13
0
    def run(self):
        """ Called by the multiprocessing module
            once the process is ready to run i.e. after the "fork"
            
            We intercept this call in order to make the
            final preparation before handing the control
            to the user process
        """
        ## For now, there isn't that much to do
        ##  except to reset the process level Message Bus
        ##  to a known start state
        Bus.reset()
        
        Bus.subscribe("_ready", self._hready)

        ## Announce to the Agents we are starting and, incidentally,
        ## that "we" are a "Child" process
        Bus.publish(self, "proc_starting", (self.name, self.pqueue))
        Bus.subscribe("beat",     self._hbeat)
        Bus.subscribe("shutdown", self._hshutdown)
                
        return self.doRun()
Beispiel #14
0
    def _hlbeat(self, *p):
        """ Process-local Heart-Beat
        """
        if self._barked:
            return
        
        self._beat_count=self._beat_count+1
        
        if self._beat_count >= self.MISSING_BEATS:
            Bus.publish(self, "%log", "warning", "watchdog expired, proc(%s)" % self.pname)
            Bus.publish(self, "%bark", self.pname)
            self._barked=True 

        Bus.publish(self, "alive", self.pname)
Beispiel #15
0
 def __init__(self, name):
     Process.__init__(self)
     self.pqueue=Queue()
     self.name=name
     self.term=False
     self.bark=False
     self._shutdown=False
     
     Bus.subscribe("%bark",    self._hbark)
     Bus.subscribe("_sigterm", self._hsigterm)
     
     ## Publish the proc's details over the local message bus
     ##  The ProcessManager will need those details in order to
     ##  launch the process later on.
     Bus.publish(self, "proc", {"proc":self, "name":name, "queue":self.pqueue})
Beispiel #16
0
            Bus.publish(self, "_sigterm", self.pname)

    def _hproc_starting(self, (pname, _)):
        self._beat_count=0
        self.is_child=True
        self.pname=pname
        signal.signal(signal.SIGTERM, self._sterm)
        
        ### Only subscribe to the signals
        ###  when we know we are a Child process
        Bus.subscribe("beat",   _cwd._hbeat)        
        Bus.subscribe("%beat",  _cwd._hlbeat)
        

_cwd=Child_WatchDogAgent()
Bus.subscribe("proc_starting", _cwd._hproc_starting)





class Main_WatchDogAgent(object):
    
    BEATS_THRESHOLD = 3
    
    def __init__(self):
        self.pname="__main__"
        self._subToAlive=False
        self._ready=False
        self.alives=[]
        self.is_child=False
Beispiel #17
0
 def hready(self):
     print "TestProcRx (%s) ready!" % self.name
     self.ready=True
     Bus.subscribe("tick", self._htick)
Beispiel #18
0
    def doRun(self):
        print "TestProc.doRun (%s)" % self.name
        Bus.publish(self, "log", "starting (%s) pid(%s)" % (self.name, os.getpid()))
        try:
            while not self.is_SigTerm() and not self.is_bark() and not self.is_shutdown():
                Bus.publish(self, "mswitch_pump")

                #print "tick (%s)" % self.name
                Bus.publish(self, "tick", self.name, os.getpid())
                sleep(0.150+0.150*random.random())
                
            print ">>> Exiting (%s) <<<" % self.name
            
        except Exception,e:
            Bus.publish(self, "log", "*** (%s) Comm Exception: %s" % (self.name, e))
            print "TestProc: Exiting (%s)" % self.name
            Bus.publish(self, "log", "Exiting (%s)" % e)
            Bus.publish(self, "shutdown")
Beispiel #19
0
sys.path.insert(0, ppkg)

class _Printer(object):
    def __call__(self, msg):
        print "!Bus: ", msg


from phidgetsdbus.mbus import Bus
from phidgetsdbus.system.process import ProcessClass

from phidgetsdbus.agents import *

Bus.logger=_Printer()
#Bus.debug=True

Bus.publish(None, "logpath", "tmswitch", "~/tmswitch.log")


class TestProc(ProcessClass):
    def __init__(self, name):
        ProcessClass.__init__(self, name)

    def hready(self):
        print "TestProc (%s) ready!" % self.name        

    def doRun(self):
        print "TestProc.doRun (%s)" % self.name
        Bus.publish(self, "log", "starting (%s) pid(%s)" % (self.name, os.getpid()))
        try:
            while not self.is_SigTerm() and not self.is_bark() and not self.is_shutdown():
                Bus.publish(self, "mswitch_pump")
Beispiel #20
0
    def _getQueue(self, pname):
        try:    details=self._procs[pname]
        except:
            raise RuntimeError("missing proc from proc list")
        
        try:    q=details["queue"]
        except:
            raise RuntimeError("missing `queue` parameter for proc(%s)" % pname)
        
        return q

## ===============================================================================
## ===============================================================================


_mswitch=MessageSwitch()
        
Bus.subscribe("*",              _mswitch._promiscuousHandler)
Bus.subscribe("_sigterm",       _mswitch._hsigterm)
        
Bus.subscribe("_sub",           _mswitch._hsub)
Bus.subscribe("proc",           _mswitch._hproc)
Bus.subscribe("_ready",         _mswitch._hready)

Bus.subscribe("mswitch_pump",   _mswitch._hpump)
Bus.subscribe("mswitch_params", _mswitch._hparams)

Bus.subscribe("proc_starting",  _mswitch._hproc_starting)

Beispiel #21
0
 def _qpname(self):
     """ Answer for the question "pname?"
     """
     Bus.publish(self, "pname", self._name)
Beispiel #22
0
        proc.update(procDetails)
        self._procs[name]=proc
        
    def _hstart(self):
        """ Handler for "start" message
            marking the debut of all registered processes
        """
        for proc_name in self._procs:
            procDetails=self._procs[proc_name]
            try:     proc=procDetails["proc"]
            except:  raise RuntimeError("procDetails require a `proc` entry")
                
            try:
                Bus.publish(self, "%log", "< starting process(%s)" % procDetails["name"])
                proc.start()
                Bus.publish(self, "%log", "> started process(%s)" % procDetails["name"])
            except Exception,e:
                raise RuntimeError("Exception whilst starting process (%s)" % e)
                


## ======================================================================================
## ======================================================================================


_pm=ProcessManager()
Bus.subscribe("start",          _pm._hstart)
Bus.subscribe("proc",           _pm._hproc)
Bus.subscribe("pname?",         _pm._qpname)
Bus.subscribe("proc_starting",  _pm._hproc_starting)
Beispiel #23
0
 def _log(self, *p):
     print p
     Bus.publish(self, "log", *p)
Beispiel #24
0
    def _tick(self):
        self._beat = True  ## atomic assignment

    def _qbeat(self):
        if self._beat:
            if self._child:
                Bus.publish(self, "%beat", self.pname)
            else:
                Bus.publish(self, "beat", self.pname)

        self._beat = False  ## atomic assignment


_heart = HeartAgent()
Bus.subscribe("%beat?", _heart._qbeat)
Bus.subscribe("proc_starting", _heart._hproc_starting)


## =====================================================

if __name__ == "__main__":
    from time import sleep

    Bus.debug = True

    class Cb(object):
        def beat(self, state):
            print "state: ", state

    _cb = Cb()
Beispiel #25
0
 def _qmqueue(self):
     """ 'mqueue' question handler - Message Bus
     """
     Bus.publish(self, "mqueue", self._mq)
Beispiel #26
0
            self._log("sub: `proc_name` missing for mtype(%s)" % mtype)
            return
        
        if mtype is None:
            self._log("sub: `mtype` missing for proc_name(%s)" % pname)
            return
        
        subs=self._map.get(mtype, [])
        subs.append(pname)
        self._map[mtype]=subs
            

## ================================================================

_centralInputQueue=Queue()
_centralInputQueue.cancel_join_thread()
_mswitch=MessageSwitch(_centralInputQueue)
        
Bus.subscribe("_sub",           _mswitch._hsub)
Bus.subscribe("proc",           _mswitch._hproc)
Bus.subscribe("start",          _mswitch._hstart)

Bus.subscribe("mqueue?",        _mswitch._qmqueue)
Bus.subscribe("mswitch_pump",   _mswitch._hpump)
Bus.subscribe("mswitch_params", _mswitch._hparams)

Bus.subscribe("proc_starting",  _mswitch._hproc_starting)
Bus.subscribe("xsub",           _mswitch._hxsub)
Bus.subscribe("xbridge",        _mswitch._hxbridge)

Beispiel #27
0
 def _hbeat(self, _):
     """ Local "beat" message-type
     """
     if self.is_child:
         return
 
     if self._termSent or self._shutdown_initiated:
         return
     
     if self._term:
         Bus.publish(self, "%log", "warning", "SIGTERM received, Main Proc")
         Bus.publish(self, "shutdown")
         self._shutdown_initiated=True
     
     if not self._subToAlive:
         if self._ready:
             self._subToAlive=True
             Bus.subscribe("alive", self._halive)
     
     ### Make sure we have a response from each of the
     ###  Child processes within the Time Interval
     self._beat_count=self._beat_count+1
     if self._beat_count == self.BEATS_THRESHOLD:
         self._beat_count=0
         if len(self.alives) != len(self._procs):
             Bus.publish(self, "%log", "warning", "child process(es) missing")
             Bus.publish(self, "%bark", self.pname)
             Bus.publish(self, "shutdown")
             self._shutdown_initiated
         self.alives=[]