def handle_request_version_message(self, msg_id): """Handle request version message. :param: msg_id: message id to use for reply """ reply = IpcMessage(IpcMessage.ACK, 'request_version', id=msg_id) version = versioneer.get_versions()["version"] major_version = re.findall(MAJOR_VER_REGEX, version)[0] minor_version = re.findall(MINOR_VER_REGEX, version)[0] patch_version = re.findall(PATCH_VER_REGEX, version)[0] short_version = major_version + "." + minor_version + "." + patch_version version_dict = {} odin_data_dict = {} odin_data_dict["full"] = version odin_data_dict["major"] = major_version odin_data_dict["minor"] = minor_version odin_data_dict["patch"] = patch_version odin_data_dict["short"] = short_version version_dict["odin-data"] = odin_data_dict version_dict["writer"] = self.get_writer_version() reply.set_param('version', version_dict) return reply
def test_empty_ipc_msg_invalid(): # Instantiate an empty message the_msg = IpcMessage() # Check that the message is not valid assert_false(the_msg.is_valid())
def set_file_writing(self, enable): self.set_file_name(self.file_name) self.set_file_path(self.file_path) self.set_num_frames(self.frames) self.fp_config['hdf']['frames'] = self.frames self.fp_config['hdf']['write'] = enable # write_config = {} # if enable: # write_config['file'] = { # "path": self.file_path, # "name": self.file_name, # } # write_config["frames"] = self.frames # write_config["write"] = enable config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) #config_msg.set_param('hdf', write_config) config_msg.attrs['params'] = {'hdf': self.fp_config['hdf']} print(config_msg) self.logger.info('Sending file writing {} command to frame processor'.format( 'enable' if enable else 'disable')) self.fp_ctrl_channel.send(config_msg.encode()) self.await_response(self.fp_ctrl_channel)
def reset_stats_cmd(self, channel): ''' Used to reset statistics in LPD Process Plugin ''' reset = IpcMessage('cmd', 'reset_statistics', id=self._next_msg_id()) channel.send(reset.encode()) reply = self.await_response(channel) return reply
def _send_message(self, msg, timeout): msg.set_msg_id(self.message_id) self.message_id = (self.message_id + 1) % self.MESSAGE_ID_MAX self.logger.debug("Sending control message:\n%s", msg.encode()) with self._lock: self.ctrl_channel.send(msg.encode()) expected_id = msg.get_msg_id() id = None while not id == expected_id: pollevts = self.ctrl_channel.poll(timeout) if pollevts == zmq.POLLIN: reply = IpcMessage(from_str=self.ctrl_channel.recv()) id = reply.get_msg_id() if not id == expected_id: self.logger.warn("Dropping reply message with id [" + str(id) + "] as was expecting [" + str(expected_id) + "]") continue if reply.is_valid() and reply.get_msg_type( ) == IpcMessage.ACK: self.logger.debug("Request successful: %s", reply) return True, reply.attrs else: self.logger.debug("Request unsuccessful") return False, reply.attrs else: self.logger.warning("Received no response") return False, None
def send_config_msg(self, channel, config): ''' Sends a configuration command to the channel that's passed ''' config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) config_msg.attrs['params'] = config channel.send(config_msg.encode()) reply = self.await_response(channel)
def send_status_cmd(self, channel): ''' Sends a status command to the channel that's passed ''' status_msg = IpcMessage('cmd', 'status', id=self._next_msg_id()) channel.send(status_msg.encode()) reply = self.await_response(channel) return reply
def handle_status_message(self, msg_id): """Handle status message. :param: msg_id: message id to use for reply """ status_dict = {} for key in self._writers: writer = self._writers[key] status_dict[key] = { 'filename': writer.full_file_name, 'num_processors': writer.number_processes_running, 'written': writer.write_count, 'writing': writer.file_created and not writer.finished } writer.write_timeout_count = writer.write_timeout_count + 1 reply = IpcMessage(IpcMessage.ACK, 'status', id=msg_id) reply.set_param('acquisitions', status_dict) # Now delete any finished acquisitions, and stop any stagnant ones for key, value in self._writers.items(): if value.finished: del self._writers[key] else: if value.number_processes_running == 0 and value.write_timeout_count > 10 and value.file_created: self.logger.info('Force stopping stagnant acquisition: ' + str(key)) value.stop() return reply
def _callback(self, msg): # Handle the multi-part message reply = IpcMessage(from_str=msg[0]) if 'request_configuration' in reply.get_msg_val(): self._update_configuration(reply.attrs) if 'status' in reply.get_msg_val(): self._update_status(reply.attrs)
def handle_control_message(self, socket): """Handle a control message on the given socket Args: socket(zmq.Socket): The socket to receive a message and reply on """ message_handlers = { "status": self.status, "configure": self.configure, "request_configuration": self.request_configuration, "request_version": self.version, "shutdown": self.shutdown, } # The first message part is a channel ID channel_id = socket.recv() # The second message part is the IpcMessage message = IpcMessage(from_str=socket.recv()) request_type = message.get_msg_val() handler = message_handlers.get(request_type, None) if handler is not None: reply = handler(message) else: error = "Unknown request type: {}".format(request_type) self._logger.error(error) reply = self._construct_reply( message.get_msg_val(), message.get_msg_id(), error ) socket.send(channel_id, zmq.SNDMORE) socket.send(reply.encode())
def send_status_cmd(self, channel): status_msg = IpcMessage('cmd', 'status', id=self._next_msg_id()) channel.send(status_msg.encode()) reply = self.await_response(channel) return reply
def do_request_config_cmd(self): request_msg = IpcMessage('cmd', 'request_configuration', id=self._next_msg_id()) for (name, channel) in self.channels: self.logger.info("Sending configuration request for frame {}".format(name)) channel.send(request_msg.encode()) reply = self.await_response(channel) if reply is not None: self.logger.info("Got response: {}".format(reply))
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "process": { "number": int(self.ctrl1.value), "rank": int(self.ctrl2.value), }, } msg.set_param("hdf", config) self.parentApp.send_message(msg)
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "file": { "name": self.ctrl1.value, "path": self.ctrl2.value, }, "frames": int(self.ctrl3.value), } msg.set_param("hdf", config) self.parentApp.send_message(msg)
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "load": { "library": self.ctrl1.value, "index": self.ctrl2.value, "name": self.ctrl3.value, } } msg.set_param("plugin", config) self.parentApp.send_message(msg)
def recv_reply(self): """ Receive reply from ZMQ socket Receives a multipart message, forms an IPCmessage and prints out the REPLY string """ # Strip off the address r_address, reply = self.socket.recv_multipart() # format it as an IPC message reply = IpcMessage(from_str=reply) print("Received Response: %s" % reply.get_param("REPLY"))
def set_file_writing(self, enable): ''' Enables or disables file writing (typically once a run has finished) ''' self.config_processor['hdf']['frames'] = self.num_frames self.config_processor['hdf']['write'] = enable config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) config_msg.attrs['params'] = {'hdf': self.config_processor['hdf']} print('Sending file writing {} command to frame processor'.format( 'enable' if enable else 'disable')) self.fp_ctrl_channel.send(config_msg.encode()) self.await_response(self.fp_ctrl_channel)
def send_request(self, value, timeout=1000): msg = IpcMessage("cmd", value) success, reply = self._send_message(msg, timeout) if success: return reply else: self._raise_reply_error(msg, reply)
def send_message(self, ipc_message): self._ctrl_channel.send(ipc_message.encode()) pollevts = self._ctrl_channel.poll(1000) if pollevts == zmq.POLLIN: reply = IpcMessage(from_str=self._ctrl_channel.recv()) if reply: self._current_value = str(reply)
def await_response(self, channel, timeout_ms=1000): ''' Polls the passed channel for any data to be received, used in various functions below ''' reply = None pollevts = channel.poll(timeout_ms) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=channel.recv()) return reply
def await_response(self, channel, timeout_ms=1000): reply = None pollevts = channel.poll(1000) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=channel.recv()) return reply
def do_config_cmd(self, config_file): try: config_params = json.load(config_file) config_msg = IpcMessage('cmd', 'configure') for param, value in config_params.items(): config_msg.set_param(param, value) self.logger.info( "Sending configure command to frame receiver with specified parameters" ) self.ctrl_channel.send(config_msg.encode()) self.await_response() except JSONDecodeError as e: self.logger.error( "Failed to parse configuration file: {}".format(e))
def test_filled_ipc_msg_valid(): # Instantiate an empty Message the_msg = IpcMessage() # Check that empty message is not valid assert_false(the_msg.is_valid()) # Set the message type, Value and id msg_type = "cmd" the_msg.set_msg_type(msg_type) msg_val = "reset" the_msg.set_msg_val(msg_val) msg_id = 54223 the_msg.set_msg_id(msg_id) # Check that the message is now valid assert_true(the_msg.is_valid())
def test_valid_ipc_msg_from_string(): # Instantiate a valid message from a JSON string json_str = """ {\"msg_type\":\"cmd\", \"msg_val\":\"status\", \"timestamp\" : \"2015-01-27T15:26:01.123456\", \"params\" : { \"paramInt\" : 1234, \"paramStr\" : \"testParam\", \"paramDouble\" : 3.1415 } } """ # Instantiate a valid message from the JSON string the_msg = IpcMessage(from_str=json_str) # Check the message is indeed valid assert_true(the_msg.is_valid()) # Check that all attributes are as expected assert_equals(the_msg.get_msg_type(), "cmd") assert_equals(the_msg.get_msg_val(), "status") assert_equals(the_msg.get_msg_timestamp(), "2015-01-27T15:26:01.123456") # Check that all parameters are as expected assert_equals(the_msg.get_param("paramInt"), 1234) assert_equals(the_msg.get_param("paramStr"), "testParam") assert_equals(the_msg.get_param("paramDouble"), 3.1415) # Check valid message throws an exception on missing parameter with assert_raises(IpcMessageException) as cm: missingParam = the_msg.get_param("missingParam") ex = cm.exception assert_equals(ex.msg, 'Missing parameter missingParam') # Check valid message can fall back to default value if parameter missing defaultParamValue = 90210 assert_equals(the_msg.get_param("missingParam", defaultParamValue), defaultParamValue)
def handle_request_config_message(self, msg_id): """Handle request config message. :param: msg_id: message id to use for reply """ acquisitions_dict = {} for key in self._writers: writer = self._writers[key] acquisitions_dict[key] = { 'output_dir': writer.directory, 'flush': writer.flush_frequency, 'file_prefix': writer.file_prefix } reply = IpcMessage(IpcMessage.ACK, 'request_configuration', id=msg_id) reply.set_param('acquisitions', acquisitions_dict) reply.set_param('inputs', self._inputs) reply.set_param('default_directory', self._directory) reply.set_param('ctrl_port', self._ctrl_port) return reply
def _construct_reply(msg_val, msg_id, error=None): reply = IpcMessage(IpcMessage.ACK, msg_val, id=msg_id) if error is not None: reply.set_msg_type(IpcMessage.NACK) reply.set_param("error", error) return reply
def send_configuration(self, content, target=None, valid_error=None): msg = IpcMessage("cmd", "configure") if target is not None: msg.set_param(target, content) else: for parameter, value in content.items(): msg.set_param(parameter, value) self._send_message(msg)
def run(self): self.logger.info("Frame receiver client starting up") self.logger.debug("Control IPC channel has identity {}".format( self.ctrl_channel.identity)) msg = IpcMessage('cmd', 'configure') msg.set_param('test', {'list': True}) self.ctrl_channel.send(msg.encode()) pollevts = self.ctrl_channel.poll(1000) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=self.ctrl_channel.recv()) self.logger.info("Got response: {}".format(reply))
def request_shared_buffer_config(self): success = False max_request_retries = 10 max_reply_retries = 10 request_retries = 0 config_request = IpcMessage(msg_type='cmd', msg_val='request_buffer_config') while success is False and request_retries < max_request_retries: self.logger.debug( "Sending buffer config request {}".format(request_retries + 1)) self.release_channel.send(config_request.encode()) reply_retries = 0 while success is False and reply_retries < max_reply_retries: if self.ready_channel.poll(100): config_msg = self.ready_channel.recv() config_decoded = IpcMessage(from_str=config_msg) self.logger.debug( 'Got buffer configuration response with shared buffer name: {}' .format( config_decoded.get_param('shared_buffer_name'))) self.config.sharedbuf = config_decoded.get_param( 'shared_buffer_name') success = True else: reply_retries += 1 request_retries += 1 # temp hack if not success: self.logger.error("Failed to obtain shared buffer configuration") return success
def send_configuration(self, content, target=None, valid_error=None, timeout=1000): msg = IpcMessage("cmd", "configure") if target is not None: msg.set_param(target, content) else: for parameter, value in content.items(): msg.set_param(parameter, value) success, reply = self._send_message(msg, timeout) if not success and None not in [reply, valid_error]: if reply["params"]["error"] != valid_error: self._raise_reply_error(msg, reply) else: self.logger.debug("Got valid error for request %s: %s", msg, reply) return success, reply