def recv_message(self, *args, **kwargs): r"""Receive a message. Args: *args: Arguments are passed to the forked comm's recv_message method. **kwargs: Keyword arguments are passed to the forked comm's recv_message method. Returns: CommMessage: Received message. """ timeout = kwargs.pop('timeout', None) if timeout is None: timeout = self.recv_timeout kwargs['timeout'] = 0 first_comm = True T = self.start_timeout(timeout, key_suffix='recv:forkd') out = None i = 0 while ((not T.is_out) or first_comm) and self.is_open and (out is None): for i in range(len(self)): if out is not None: break x = self.curr_comm if x.is_open: msg = x.recv_message(*args, **kwargs) self.errors += x.errors if msg.flag == CommBase.FLAG_EOF: self.eof_recv[self.curr_comm_index % len(self)] = 1 if sum(self.eof_recv) == len(self): out = msg else: x.finalize_message(msg) elif msg.flag not in [CommBase.FLAG_FAILURE, CommBase.FLAG_EMPTY]: out = msg self.curr_comm_index += 1 first_comm = False if out is None: self.sleep() self.stop_timeout(key_suffix='recv:forkd') if out is None: if self.is_closed: self.debug('Comm closed') out = CommBase.CommMessage(flag=CommBase.FLAG_FAILURE) else: out = CommBase.CommMessage(flag=CommBase.FLAG_EMPTY, args=self.last_comm.empty_obj_recv) out.args = {i: out.args} return out
def remove_model(self, direction, name): r"""Remove a model from the list of models. Args: direction (str): Direction of model. name (str): Name of model exiting. Returns: bool: True if all of the input/output models have signed off; False otherwise. """ with self.lock: if (direction == "input") and (name in self.clients): super(RPCRequestDriver, self).send_message( CommBase.CommMessage(args=YGG_CLIENT_EOF, flag=CommBase.FLAG_SUCCESS), header_kwargs={ 'raw': True, 'model': name }, skip_processing=True) out = super(RPCRequestDriver, self).remove_model(direction, name) if out: self.send_eof() return out
def test_send_recv_closed(self, instance, send_comm, recv_comm, test_msg): r"""Test sending/receiving with queues closed.""" instance.close_comm() send_comm.close() recv_comm.close() assert (instance.is_comm_closed) assert (send_comm.is_closed) assert (recv_comm.is_closed) flag = instance.send_message(CommBase.CommMessage(args=test_msg)) assert (not flag) flag = instance.recv_message() if instance.icomm._commtype != 'value': assert (not flag) # Short if instance.icomm._commtype != 'value': flag = send_comm.send(test_msg) assert (not flag) flag, ret = recv_comm.recv() if instance.icomm._commtype != 'value': assert (not flag) assert (ret is None) # Long if instance.icomm._commtype != 'value': flag = send_comm.send_nolimit(test_msg) assert (not flag) flag, ret = recv_comm.recv_nolimit() if instance.icomm._commtype != 'value': assert (not flag) assert (ret is None) instance.confirm_output(timeout=1.0)
def test_send_recv(self): r"""Test sending/receiving with queues closed.""" self.instance.close_comm() self.send_comm.close() self.recv_comm.close() assert (self.instance.is_comm_closed) assert (self.send_comm.is_closed) assert (self.recv_comm.is_closed) flag = self.instance.send_message( CommBase.CommMessage(args=self.test_msg)) assert (not flag) flag = self.instance.recv_message() if self.instance.icomm._commtype != 'value': assert (not flag) # Short if self.instance.icomm._commtype != 'value': flag = self.send_comm.send(self.test_msg) assert (not flag) flag, ret = self.recv_comm.recv() if self.instance.icomm._commtype != 'value': assert (not flag) self.assert_equal(ret, None) # Long if self.instance.icomm._commtype != 'value': flag = self.send_comm.send_nolimit(self.test_msg) assert (not flag) flag, ret = self.recv_comm.recv_nolimit() if self.instance.icomm._commtype != 'value': assert (not flag) self.assert_equal(ret, None) self.instance.confirm_output(timeout=1.0)
def recv_message(self, timeout=None, **kwargs): r"""Receive a message. Args: *args: Arguments are passed to the response comm's recv_message method. **kwargs: Keyword arguments are passed to the response comm's recv_message method. Returns: CommMessage: Received message. """ # Sleep until there is a message if timeout is None: timeout = kwargs.get('timeout', self.recv_timeout) T = self.start_timeout(timeout, key_suffix='.recv:backlog') while (not T.is_out) and (not self.backlog_ready.is_set()): self.backlog_ready.wait(self.sleeptime) self.stop_timeout(key_suffix='.recv:backlog') # Handle absence of messages if self.n_msg_backlog == 0: self.verbose_debug("No messages waiting.") if self.is_closed: self.debug(("No messages waiting and comm closed." "%s, %s, %s") % (self.backlog_thread is not None, not self.backlog_thread.was_break, self.backlog_thread.is_alive())) self.printStatus(level='debug') if self.backlog_thread.was_break: self.debug("Break stack:\n%s", self.backlog_thread.break_stack) out = CommBase.CommMessage(flag=CommBase.FLAG_FAILURE) else: out = CommBase.CommMessage(flag=CommBase.FLAG_EMPTY, args=self.empty_obj_recv) # Return backlogged message else: self.debug('Returning backlogged received message') out = self.pop_backlog() return out
def send_eof(self, **kwargs): r"""Send EOF message. Returns: bool: Success or failure of send. """ with self.lock: if self._eof_sent: # pragma: debug self.debug('Already sent EOF') return False self._eof_sent = True self.debug('Sent EOF') msg = CommBase.CommMessage(flag=CommBase.FLAG_EOF, args=self.ocomm.eof_msg) return self.send_message(msg, **kwargs)
def on_eof(self, msg): r"""On EOF, decrement number of clients. Only send EOF if the number of clients drops to 0. Args: msg (CommMessage): Message object that provided the EOF. Returns: CommMessage, bool: Value that should be returned by recv_message on EOF. """ with self.lock: self.remove_model('input', msg.header.get('model', '')) if self.nclients == 0: self.debug("All clients have signed off (EOF).") return super(RPCRequestDriver, self).on_eof(msg) return CommBase.CommMessage(flag=CommBase.FLAG_EMPTY, args=self.icomm.empty_obj_recv)
def recv(self, timeout=None, return_message_object=False, dont_finalize=False, **kwargs): r"""Receive a message. Args: *args: All arguments are passed to comm _recv method. return_message_object (bool, optional): If True, the full wrapped CommMessage message object is returned instead of the tuple. Defaults to False. dont_finalize (bool, optional): If True, finalize_message will not be called even if async_recv_method is 'recv_message'. Defaults to False. **kwargs: All keywords arguments are passed to comm _recv method. Returns: tuple (bool, obj): Success or failure of receive and received message. """ self.precheck('recv') # Sleep until there is a message if timeout is None: timeout = kwargs.get('timeout', self.recv_timeout) T = self.start_timeout(timeout, key_suffix='.recv:backlog') while (not T.is_out) and (not self.backlog_ready.is_set()): self.backlog_ready.wait(self.sleeptime) self.stop_timeout(key_suffix='.recv:backlog') # Handle absence of messages if self.n_msg_backlog == 0: self.verbose_debug("No messages waiting.") if self.is_closed: self.info(("No messages waiting and comm closed." "%s, %s, %s") % (self.backlog_thread is not None, not self.backlog_thread.was_break, self.backlog_thread.is_alive())) self.printStatus() if self.backlog_thread.was_break: self.info("Break stack:\n%s", self.backlog_thread.break_stack) out = CommBase.CommMessage(flag=CommBase.FLAG_FAILURE) else: out = CommBase.CommMessage(flag=CommBase.FLAG_EMPTY, args=self.empty_obj_recv) # Return backlogged message else: self.debug('Returning backlogged received message') out = self.pop_backlog() if not dont_finalize: # if self.is_eof(out.args) and self.close_on_eof_recv: if (out.flag == CommBase.FLAG_EOF) and self.close_on_eof_recv: self.close() out.flag = CommBase.FLAG_FAILURE self._used = True if not dont_finalize: kws_finalize = { k: kwargs.pop(k) for k in self._finalize_message_kws if k in kwargs } if self.async_recv_method != 'recv_message': out.finalized = False kws_finalize['skip_processing'] = True out = self._wrapped.finalize_message(out, **kws_finalize) if not return_message_object: out = (bool(out.flag), out.args) return out
def recv_message(self, *args, **kwargs): r"""Receive a message. Args: *args: Arguments are passed to the forked comm's recv_message method. **kwargs: Keyword arguments are passed to the forked comm's recv_message method. Returns: CommMessage: Received message. """ timeout = kwargs.pop('timeout', None) if timeout is None: timeout = self.recv_timeout kwargs['timeout'] = 0 first_comm = True T = self.start_timeout(timeout, key_suffix='recv:forkd') out = None out_gather = {} idx = None if self.pattern == 'gather': def complete(): return (len(out_gather) == len(self)) else: def complete(): return bool(out_gather) while ((not T.is_out) or first_comm) and self.is_open and (not complete()): for i in range(len(self)): if complete(): break idx = self.curr_comm_index % len(self) x = self.curr_comm if idx not in out_gather: if self.comm_list_backlog[idx]: out_gather[idx] = self.comm_list_backlog[idx].pop(0) elif x.is_open: msg = x.recv_message(*args, **kwargs) self.errors += x.errors if msg.flag == CommBase.FLAG_EOF: self.eof_recv[idx] = 1 if self.pattern == 'gather': assert (all((v.flag == CommBase.FLAG_EOF) for v in out_gather.values())) out_gather[idx] = msg elif sum(self.eof_recv) == len(self): out_gather[idx] = msg else: x.finalize_message(msg) elif msg.flag == CommBase.FLAG_SUCCESS: out_gather[idx] = msg self.curr_comm_index += 1 first_comm = False if not complete(): self.sleep() self.stop_timeout(key_suffix='recv:forkd') if complete(): if self.pattern == 'cycle': idx, out = next(iter(out_gather.items())) args_copy = copy.deepcopy(out) out.args = {idx: args_copy} elif self.pattern == 'gather': out = copy.deepcopy(next(iter(out_gather.values()))) out.args = {idx: v for idx, v in out_gather.items()} # TODO: Gather header/type etc? else: for idx, v in out_gather.items(): self.comm_list_backlog[idx].append(v) if self.is_closed: self.debug('Comm closed') out = CommBase.CommMessage(flag=CommBase.FLAG_FAILURE) else: out = CommBase.CommMessage(flag=CommBase.FLAG_EMPTY) if self.pattern == 'cycle': out.args = self.last_comm.empty_obj_recv else: out.args = [] return out