def recv(self): """Returns the reply message or None if there was no reply.""" try: items = self.poller.poll(self.timeout) except KeyboardInterrupt: return # interrupted if items: # if we got a reply, process it msg = self.client.recv_multipart() self.close() if self.verbose: logging.info("I: received reply:") dump(msg) # Don't try to handle errors, just assert noisily assert len(msg) >= 4 #first drop will be drop (cause empty) header = msg.pop(0) header = msg.pop(0) assert MDP.C_CLIENT == header #this one contains servicename #TODO: exploit this header = msg.pop(0) return msg else: logging.warn("W: permanent error, abandoning request")
def send(self, service, request): """Send request to broker """ if not isinstance(request, list): request = [request] # Prefix request with protocol frames # Frame 0: empty (REQ emulation) # Frame 1: "MDPCxy" (six bytes, MDP/Client x.y) # Frame 2: Service name (printable string) request = ['', MDP.C_CLIENT, service] + request if self.verbose: logging.warn("I: send request to '%s' service: ", service) dump(request) self.client.send_multipart(request)
def process_worker(self, sender, msg): """Process message sent to us by a worker.""" assert len(msg) >= 1 # At least, command command = msg.pop(0) worker_ready = hexlify(sender) in self.workers worker = self.require_worker(sender) if (MDP.W_READY == command): assert len(msg) >= 1 # At least, a service name service = msg.pop(0) # Not first command in session or Reserved service name if (worker_ready or service.startswith(self.INTERNAL_SERVICE_PREFIX)): self.delete_worker(worker, True) else: # Attach worker to service and mark as idle worker.service = self.require_service(service) self.worker_waiting(worker) elif (MDP.W_REPLY == command): if (worker_ready): # Remove & save client return envelope and insert the # protocol header and service name, then rewrap envelope. client = msg.pop(0) empty = msg.pop(0) # ? msg = [client, '', MDP.C_CLIENT, worker.service.name] + msg self.socket.send_multipart(msg) Metrics.inc(Metrics.BROKER_out_nb_client_reply) self.worker_waiting(worker) else: self.delete_worker(worker, True) elif (MDP.W_HEARTBEAT == command): if (worker_ready): worker.expiry = time.time() + 1e-3 * self.HEARTBEAT_EXPIRY else: self.delete_worker(worker, True) elif (MDP.W_DISCONNECT == command): self.delete_worker(worker, False) else: logging.error("E: invalid message:") dump(msg)
def send_to_broker(self, command, option=None, msg=None): """Send message to broker. If no msg is provided, creates one internally """ if msg is None: msg = [] elif not isinstance(msg, list): msg = [msg] if option: msg = [option] + msg msg = ['', MDP.W_WORKER, command] + msg if self.verbose: logging.info("I: sending %s to broker", command) dump(msg) self.worker.send_multipart(msg)
def mediate(self): """Main broker work happens here""" while True: try: if not(self._terminated): self._isup = True items = self.poller.poll(self.HEARTBEAT_INTERVAL) else: print "Quit broker sucessfully: terminated !" break except KeyboardInterrupt: print "Quit broker sucessfully: keyboard !" break # Interrupted if items: msg = self.socket.recv_multipart() if self.verbose: logging.info("I: received message:") dump(msg) sender = msg.pop(0) empty = msg.pop(0) assert empty == '' header = msg.pop(0) if (MDP.C_CLIENT == header): Metrics.inc(Metrics.BROKER_in_nb_client_request) self.process_client(sender, msg) elif (MDP.W_WORKER == header): Metrics.inc(Metrics.BROKER_in_nb_worker_reply) self.process_worker(sender, msg) else: Metrics.inc(Metrics.BROKER_in_invalid) logging.error("E: invalid message:") dump(msg) self.purge_workers() self.send_heartbeats()
def send_to_worker(self, worker, command, option, msg=None): """Send message to worker. If message is provided, sends that message. """ if msg is None: msg = [] elif not isinstance(msg, list): msg = [msg] # Stack routing and protocol envelopes to start of message # and routing envelope if option is not None: msg = [option] + msg msg = [worker.address, '', MDP.W_WORKER, command] + msg if self.verbose: logging.info("I: sending %r to worker", command) dump(msg) self.socket.send_multipart(msg) Metrics.inc(Metrics.BROKER_out_nb_worker_request)
def recv(self, reply=None): """Send reply, if any, to broker and wait for next request.""" # Format and send the reply if we were provided one assert reply is not None or not self.expect_reply if reply is not None: assert self.reply_to is not None reply = [self.reply_to, ''] + reply self.send_to_broker(MDP.W_REPLY, msg=reply) self.expect_reply = True while True: # Poll socket for a reply, with timeout try: if not (self._terminated): items = self.poller.poll(self.timeout) else: break except KeyboardInterrupt: break # Interrupted if items: msg = self.worker.recv_multipart() if self.verbose: logging.info("I: received message from broker: ") dump(msg) self.liveness = self.HEARTBEAT_LIVENESS # Don't try to handle errors, just assert noisily assert len(msg) >= 3 empty = msg.pop(0) assert empty == '' header = msg.pop(0) assert header == MDP.W_WORKER command = msg.pop(0) if command == MDP.W_REQUEST: # We should pop and save as many addresses as there are # up to a null part, but for now, just save one... self.reply_to = msg.pop(0) # pop empty assert msg.pop(0) == '' return msg # We have a request to process elif command == MDP.W_HEARTBEAT: # Do nothing for heartbeats pass elif command == MDP.W_DISCONNECT: self.reconnect_to_broker() else: logging.error("E: invalid input message: ") dump(msg) else: self.liveness -= 1 if self.liveness == 0: if self.verbose: logging.warn( "W: disconnected from broker - retrying...") try: time.sleep(1e-3 * self.reconnect) except KeyboardInterrupt: break self.reconnect_to_broker() # Send HEARTBEAT if it's time if time.time() > self.heartbeat_at: self.send_to_broker(MDP.W_HEARTBEAT) self.heartbeat_at = time.time() + 1e-3 * self.heartbeat logging.warn("W: interrupt received, killing worker...") return None
def recv(self, reply=None): """Send reply, if any, to broker and wait for next request.""" # Format and send the reply if we were provided one assert reply is not None or not self.expect_reply if reply is not None: assert self.reply_to is not None reply = [self.reply_to, ''] + reply self.send_to_broker(MDP.W_REPLY, msg=reply) self.expect_reply = True while True: # Poll socket for a reply, with timeout try: if not(self._terminated): items = self.poller.poll(self.timeout) else: break except KeyboardInterrupt: break # Interrupted if items: msg = self.worker.recv_multipart() if self.verbose: logging.info("I: received message from broker: ") dump(msg) self.liveness = self.HEARTBEAT_LIVENESS # Don't try to handle errors, just assert noisily assert len(msg) >= 3 empty = msg.pop(0) assert empty == '' header = msg.pop(0) assert header == MDP.W_WORKER command = msg.pop(0) if command == MDP.W_REQUEST: # We should pop and save as many addresses as there are # up to a null part, but for now, just save one... self.reply_to = msg.pop(0) # pop empty assert msg.pop(0) == '' return msg # We have a request to process elif command == MDP.W_HEARTBEAT: # Do nothing for heartbeats pass elif command == MDP.W_DISCONNECT: self.reconnect_to_broker() else: logging.error("E: invalid input message: ") dump(msg) else: self.liveness -= 1 if self.liveness == 0: if self.verbose: logging.warn("W: disconnected from broker - retrying...") try: time.sleep(1e-3 * self.reconnect) except KeyboardInterrupt: break self.reconnect_to_broker() # Send HEARTBEAT if it's time if time.time() > self.heartbeat_at: self.send_to_broker(MDP.W_HEARTBEAT) self.heartbeat_at = time.time() + 1e-3 * self.heartbeat logging.warn("W: interrupt received, killing worker...") return None