def test_createClientThread(self): hub = Hub(store=MockStore()) socket = MockSocket() expected = HubClient(clientSocket=socket, ip="127.0.0.1", store=MockStore()) client, metadata = hub.createClientThread(socket, "127.0.0.1") self.assertIsInstance(client, HubClient) self.assertEqual(client.clientSocket, expected.clientSocket) self.assertEqual(client.ip, expected.ip)
def __init__(self, tag=None, store=None, interval=None, enable_hub=True, is_thread=False, **args): self.TAG = tag or '' self.ID = str(hash(time()))[-5:] self.TAG += self.ID self.HISTORY_PATH = HISTORY + self.ID self.store = store if store else Store() self.interval = interval self.logger = logging.getLogger(str(self)) from bob.ami.Hub import Hub self.hub = Hub(store=self.store) if enable_hub else None self.is_thread = is_thread self.setState(INIT)
def test_startstop(self): hub = Hub(store=MockStore()) self.assertEqual(Util.getStates(Util.run(hub)), STATE_SEQUENCE)
def test_emit_offline(self): hub = Hub(store=MockStore()) assert (hub.store.get(OUBOUND_PATH) is None) signal = Signal(channel="CH1", data=B.serialize(B.create('a', 'p'))) hub.emit(signal) assert (hub.store.get(OUBOUND_PATH) == [signal.bytes()])
def test_init_host(self): self.assertEqual(Hub(store=MockStore()).host, "127.0.0.1") ip = "192.168.0.0" self.assertEqual(Hub(host=ip, store=MockStore()).host, ip)
def test_init_port(self): hub = Hub(store=MockStore()) self.assertTrue(hub.port > 1000) self.assertTrue(hub.port < 65000) self.assertEqual(Hub(port=15123, store=MockStore()).port, 15123)
class AMI(object): """ Abstract Processing node External API: * start() * stop() Life cycle: * start() * -> status=STARTING -> onStart() -> status=STARTED -> onInterval() * stop() # Can only be called from this instance * -> status=STOPPING -> onStop() -> status=STOPPED Overwrite any/all of the following: * __init__(): call super and accept arguments * onStart(): initialization * onStop(): cleanup * onInterval(): execute every x ms onInterval(): in onStart() or __init__() if the self.interval is not defined, then this method will only be executed once. Otherwise, this method will be excecuted every [self.interval] milliseconds. Store: self.store is a substore """ def __init__(self, tag=None, store=None, interval=None, enable_hub=True, is_thread=False, is_daemon=False, **args): self.TAG = tag or '' self.ID = str(hash(time()))[-5:] self.TAG += self.ID self.HISTORY_PATH = HISTORY + self.ID self.store = store if store else Store() self.interval = interval self.logger = logging.getLogger(str(self)) from bob.ami.Hub import Hub self.hub = Hub(store=self.store) if enable_hub else None self.is_thread = is_thread self.is_daemon = is_daemon self.setState(INIT) self._thread = None def onStart(self): pass def onInterval(self): raise NotImplementedError() def onStop(self): pass def stop(self): """ Stops the AMI completely, should not be overwritten An external call to this method will not stop this AMI. """ if self.getState() not in [RUNNING, FORCE_STOPPING, FAILED]: self.logger.debug("Can not stop [%s]" % self.getState()) return try: self.setState(STOPPING) self.onStop() # TODO: add timeout, call self.onStop() in thread self.setState(STOPPED) if not self.is_thread: os._exit(0) # exit without error except Exception: self.logger.error("Exception while running onStop()") print(sys.exc_info()) # push onto Store on top of STDOUT print(traceback.print_exc()) if not self.is_thread: os._exit(1) def start(self): if self.is_thread: """ Starts this AMI in a thread with shared memory """ self._thread = Thread(target=self.__start, name=self.TAG) self._thread.daemon = self.is_daemon self._thread.start() else: """ Starts this AMI in a new process and returns the unique node_id """ pid = os.fork() if pid: # parent process return self.TAG else: # AMI process self.__start() def __start(self): self.setState(STARTING) if self.hub is not None: self.hub.store = self.store self.hub.start() self.onStart() if self.getState() == STARTING: self.setState(RUNNING) try: while self.getState() == RUNNING: self.onInterval() if self.interval: # at interval execution sleep(self.interval or 0) else: # single execution break except Exception: (_, err, trace) = sys.exc_info() stack_trace = traceback.extract_tb(trace) self.logger.error("AMI failed: %s: %s", err, stack_trace) self.setState(FAILED) self.stop() def setState(self, newState): if newState not in STATES: raise ValueError("Invalid state [%s]" % newState) self.store.add(self.HISTORY_PATH, newState) self.logger.debug("State change to [%s]", STATES[newState]) def getState(self): return self.store.getLasts(self.HISTORY_PATH, 1)[0] def __repr__(self): return "[AMI.%s.%s]" % (self.__class__.__name__, self.TAG) def fail(self, *args): self.logger.error(*args) self.setState(FAILED)