예제 #1
0
def mdp_request(socket, service, msg, timeout=None):
    """Synchronous MDP request.

    This function sends a request to the given service and
    waits for a reply.

    If timeout is set and no reply received in the given time
    the function will return `None`.

    :param socket:    zmq REQ socket to use.
    :type socket:     zmq.Socket
    :param service:   service id to send the msg to.
    :type service:    str
    :param msg:       list of message parts to send.
    :type msg:        list of str
    :param timeout:   time to wait for answer in seconds.
    :type timeout:    float

    :rtype list of str:
    """
    if not timeout or timeout < 0.0:
        timeout = None
    to_send = [PROTO_VERSION, service]
    to_send.extend(msg)
    socket.send_multipart(to_send)
    ret = None
    rlist, _, _ = select([socket], [], [], timeout)
    if rlist and rlist[0] == socket:
        ret = socket.recv_multipart()
        ret.pop(0)  # remove service from reply
    return ret
예제 #2
0
파일: eventlet.py 프로젝트: ged/m2wsgi
 def _poll(self,sockets,timeout=None):
     #  Don't bother trampolining if there's data available immediately.
     #  This also avoids calling into the eventlet hub with a timeout of
     #  zero, which doesn't work right (it still switches the greenthread)
     (r,_,_) = zmq_poll.select(sockets,[],[],timeout=0)
     if r:
         return r
     if timeout == 0:
         return []
     #  Looks like we'll have to block :-(
     ready = []
     threads = []
     res = Event()
     for sock in sockets:
         threads.append(eventlet.spawn(self._do_poll,sock,ready,res,timeout))
     self.poll_threads.append((res,threads))
     try:
         res.wait()
     finally:
         self.poll_threads.remove((res,threads))
         for t in threads:
             t.kill()
             try:
                 t.wait()
             except GreenletExit:
                 pass
     return ready
예제 #3
0
파일: client.py 프로젝트: caustin/pyzmq-mdp
def mdp_request(socket, service, msg, timeout=None):
    """Synchronous MDP request.

    This function sends a request to the given service and
    waits for a reply.

    If timeout is set and no reply received in the given time
    the function will return `None`.

    :param socket:    zmq REQ socket to use.
    :type socket:     zmq.Socket
    :param service:   service id to send the msg to.
    :type service:    str
    :param msg:       list of message parts to send.
    :type msg:        list of str
    :param timeout:   time to wait for answer in seconds.
    :type timeout:    float

    :rtype list of str:
    """
    if not timeout or timeout < 0.0:
        timeout = None
    if type(msg) in (str, unicode):
        msg = [msg]
    to_send = [PROTO_VERSION, service]
    to_send.extend(msg)
    socket.send_multipart(to_send)
    ret = None
    rlist, _, _ = select([socket], [], [], timeout)
    if rlist and rlist[0] == socket:
        ret = socket.recv_multipart()
        ret.pop(0) # remove service from reply
    return ret
예제 #4
0
 def _poll(self, sockets, timeout=None):
     #  Don't bother trampolining if there's data available immediately.
     #  This also avoids calling into the eventlet hub with a timeout of
     #  zero, which doesn't work right (it still switches the greenthread)
     (r, _, _) = zmq_poll.select(sockets, [], [], timeout=0)
     if r:
         return r
     if timeout == 0:
         return []
     #  Looks like we'll have to block :-(
     ready = []
     threads = []
     res = Event()
     for sock in sockets:
         threads.append(
             eventlet.spawn(self._do_poll, sock, ready, res, timeout))
     self.poll_threads.append((res, threads))
     try:
         res.wait()
     finally:
         self.poll_threads.remove((res, threads))
         for t in threads:
             t.kill()
             try:
                 t.wait()
             except GreenletExit:
                 pass
     return ready
예제 #5
0
 def _poll(self,sockets,timeout=None):
     #  If there's anything available non-blockingly, just use it.
     (ready,_,error) = zmq_poll.select(sockets,[],sockets,timeout=0)
     if ready:
         return ready
     if error:
         return []
     if timeout == 0:
         return []
     #  Spawn a greenthread to poll-recv from each socket.
     ready = []
     threads = []
     res = gevent.event.Event()
     for sock in sockets:
         threads.append(gevent.spawn(self._do_poll,sock,ready,res,timeout))
     self.poll_threads.append((res,threads))
     #  Wait for one of them to return, or for an interrupt.
     try:
         res.wait()
     finally:
         gevent.killall(threads)
         gevent.joinall(threads)
     return ready
예제 #6
0
 def _poll(self, sockets, timeout=None):
     #  If there's anything available non-blockingly, just use it.
     (ready, _, error) = zmq_poll.select(sockets, [], sockets, timeout=0)
     if ready:
         return ready
     if error:
         return []
     if timeout == 0:
         return []
     #  Spawn a greenthread to poll-recv from each socket.
     ready = []
     threads = []
     res = gevent.event.Event()
     for sock in sockets:
         threads.append(
             gevent.spawn(self._do_poll, sock, ready, res, timeout))
     self.poll_threads.append((res, threads))
     #  Wait for one of them to return, or for an interrupt.
     try:
         res.wait()
     finally:
         gevent.killall(threads)
         gevent.joinall(threads)
     return ready
예제 #7
0
        def _loop():
            # Make a copy of the connections registry. Copy is atomic due to the GIL.
            remote_node_addresses = set(self._connections.keys())

            # Add any connections that we are not monitoring
            for remote_node_address in remote_node_addresses:
                if remote_node_address not in hb_socks_registry:
                    hb_socket = _create_socket(self._ctx, zmq.XREQ)
                    # The identity of the heartbeat socket should be constant for any given
                    # local-node and remote-node
                    hb_socket.identity = self.address + "->" + remote_node_address
                    # Stash away the remote endpoint for each socket (this is somehow not exposed
                    # by the socket itself)
                    endpoints[hb_socket] = remote_node_address
                    hb_socket.connect(remote_node_address)
                    hb_socks_registry[remote_node_address] = hb_socket

            # Remove heartbeat sockets that we no longer need
            for remote_node_address in hb_socks_registry.keys():
                if remote_node_address not in remote_node_addresses:
                    log.debug("Removing disconnected node %s from heartbeat registry.", remote_node_address)
                    sock = hb_socks_registry.pop(remote_node_address)
                    del endpoints[sock]
                    sock.close()

            remote_node_count = len(hb_socks_registry)
            log.debug("Pinging %d remote nodes in registry", remote_node_count)

            # If there are no sockets to watch, skip the pinging bit
            if not remote_node_count:
                # Wait a bit before retrying
                time.sleep(self._timeout)
                return

            # Get a list of the actual sockets
            hb_socks = hb_socks_registry.values()

            # Send a ping to all sockets
            for sock in hb_socks:
                sock.send_multipart(message.can_ctr(ctr_ping))

            # Wait at most <timeout> seconds for a reply.
            time.sleep(self._timeout)

            # Get all sockets that responded (wait a bit extra if there are no responses at all)
            resp, _, _ = zpoll.select(hb_socks, [], [], timeout=10)

            # Get a list of nodes which did not respond in time
            failures = set(hb_socks).difference(resp)

            for sock in resp:
                # TODO: Add some handling for the replies. At the moment we just throw away them away.
                sock.recv_multipart(zmq.NOBLOCK)

            num_failures = len(failures)
            if num_failures > 0:
                log.warn("%d nodes failed to respond", num_failures)

                dead_node_addresses = [endpoints[failed_hb_sock] for failed_hb_sock in failures]

                # Send a message to the main execution loop that it should kill all pending
                # requests on the affected channels
                msg_disconnect = message.can_disconnect_channels(dead_node_addresses, "TIMEOUT")
                msg_disconnect = message.can_msg(_msg_disconnect_channels, msg_disconnect)
                msg_disconnect = message.can_ctr(ctr_data, msg_disconnect)
                exec_loop_sock.send_multipart([self.address] + msg_disconnect, copy=False)