static
int process_meta_information_and_handle_heartbeat(subscriber_state_t *state, zmsg_t* msg)
{
    zframe_t *first = zmsg_first(msg);
    char *pub_spec = NULL;
    bool is_heartbeat = zframe_streq(first, "heartbeat");

    msg_meta_t meta;
    int rc = msg_extract_meta_info(msg, &meta);
    if (!rc) {
        // dump_meta_info(&meta);
        if (!state->meta_info_failures++)
            fprintf(stderr, "[E] subscriber: received invalid meta info\n");
        return is_heartbeat;
    }
    if (meta.device_number == 0) {
        // ignore device number 0
        state->messages_dev_zero++;
        return is_heartbeat;
    }
    if (is_heartbeat) {
        if (debug)
            printf("received heartbeat from device %d\n", meta.device_number);
        zmsg_first(msg); // msg_extract_meta_info repositions the pointer, so reset
        zframe_t *spec_frame = zmsg_next(msg);
        pub_spec = zframe_strdup(spec_frame);
    }
    state->message_gap_size += device_tracker_calculate_gap(state->tracker, &meta, pub_spec);
    return is_heartbeat;
}
Пример #2
0
void pss_response(void *spss, req_store_t * req_store, void *sweb, void *sgraph)
{

	zmsg_t *msg = zmsg_recv(spss);
	zframe_t *null = zmsg_unwrap(msg);
	zframe_destroy(&null);
	json_error_t error;
	printf("\nbroker:spss received: %s\n",
	       (const char *)zframe_data(zmsg_first(msg)));
	const char *data;
	size_t data_size = zframe_size(zmsg_first(msg));
	data = zframe_data(zmsg_first(msg));

	json_t *pss_resp_json = json_loadb(data,
					   data_size, 0, &error);
	zmsg_destroy(&msg);

	//identify the request
	int32_t requestId =
	    json_integer_value(json_object_get(pss_resp_json, "requestId"));

	req_t *req = request_store_req(req_store, requestId);

	json_t *response = json_object_get(pss_resp_json, "response");
	json_incref(response);
	json_decref(pss_resp_json);

	const char *resp_type =
	    json_string_value(json_object_get(response, "type"));

	const char *req_type =
	    json_string_value(json_object_get
			      (json_object_get
			       (json_object_get(req->request, "clientRequest"),
				"request"), "type"));
	if ((strcmp(resp_type, "searchResponse") == 0)
	    && (strcmp(req_type, "searchRequest") == 0))

		pss_response_searchResponse(req, response, requestId, sgraph);

	else if ((strcmp(resp_type, "newNodeResponse") == 0)
		 && (strcmp(req_type, "newNode") == 0))
		pss_response_newNodeResponse(req, response, requestId, sweb,
					     req_store);

	else if ((strcmp(resp_type, "delNode") == 0)
		 && (strcmp(req_type, "delNode") == 0))
		pss_response_delNode(req, response, requestId, sweb, req_store);

	else {

	}

}
Пример #3
0
// Handle input from worker, on backend
int s_handle_backend(zloop_t *loop, zmq_pollitem_t *poller, void *arg)
{
	// Use worker identity for load-balancing
	lbbroker_t *self = (lbbroker_t *)arg;
	zmsg_t *msg = zmsg_recv(self->backend);
	if (msg) {
		zframe_t *identity = zmsg_unwrap(msg);
		zlist_append(self->workers, identity);

		// Enable reader on frontend if we went from 0 to 1 workers
		if (zlist_size(self->workers) == 1) {
			zmq_pollitem_t poller = { self->frontend, 0, ZMQ_POLLIN };
			zloop_poller(loop, &poller, s_handle_frontend, self);
		}

		// Forward message to client if it's not a READY
		zframe_t *frame = zmsg_first(msg);
		if (memcmp(zframe_data(frame), WORKER_READY, strlen(WORKER_READY)) == 0) {
			zmsg_destroy(&msg);
		} else {
			zmsg_send(&msg, self->frontend);
		}
	}
	return 0;
}
Пример #4
0
int
zsock_wait (void *self)
{
    assert (self);

    //  A signal is a message containing one frame with our 8-byte magic 
    //  value. If we get anything else, we discard it and continue to look
    //  for the signal message
    while (true) {
        zmsg_t *msg = zmsg_recv (self);
        if (!msg)
            return -1;
        if (zmsg_size (msg) == 1
        &&  zmsg_content_size (msg) == 8) {
            zframe_t *frame = zmsg_first (msg);
            int64_t signal_value = *((int64_t *) zframe_data (frame));
            if ((signal_value & 0xFFFFFFFFFFFFFF00L) == 0x7766554433221100L) {
                zmsg_destroy (&msg);
                return signal_value & 255;
            }
        }
        zmsg_destroy (&msg);
    }
    return -1;
}
Пример #5
0
/* ================ download_data() ================ */
int download_data(zsock_t *sock, const char *key)
{
    /* ---------------- Send Message ---------------- */
    zmsg_t *download_msg = create_action_message(MSG_ACTION_GET);
    message_add_key_data(download_msg, key, "", 0);

    zmsg_send(&download_msg, sock);

    /* ---------------- Receive Message ---------------- */

    zmsg_t *recv_msg = zmsg_recv(sock);
    if ( recv_msg == NULL ){
        return -2;
    }
    /*zmsg_print(recv_msg);*/

    int rc = -1;
    if (message_check_status(recv_msg, MSG_STATUS_WORKER_NOTFOUND) == 0 ){
        warning_log("Not Found. key=%s", key);
        rc = 0;
    } else if ( message_check_status(recv_msg, MSG_STATUS_WORKER_ERROR) == 0 ){
        error_log("Return MSG_STATUS_WORKER_ERROR. key=%s", key);
        rc = -1;
    } else {
        /*zmsg_print(recv_msg);*/
        zframe_t *frame_msgtype = zmsg_first(recv_msg);
        if ( frame_msgtype != NULL ){
            int16_t msgtype = *(int16_t*)zframe_data(frame_msgtype);
            if ( msgtype == MSGTYPE_DATA ){
                zmsg_first(recv_msg);

                zframe_t *frame_key = zmsg_next(recv_msg);
                UNUSED const char *key = (const char *)zframe_data(frame_key);

                zframe_t *frame_data = zmsg_next(recv_msg);
                UNUSED const char *data =  (const char *)zframe_data(frame_data);
                UNUSED uint32_t data_size = zframe_size(frame_data);
                /*notice_log("Receive key:%s data_size:%d", key, data_size);*/
                rc = 0;
            }
        }
    }

    zmsg_destroy(&recv_msg);

    return rc;
}
Пример #6
0
int16_t message_get_msgtype(zmsg_t *msg){
    zframe_t *frame_msgtype = zmsg_first(msg);
    if ( frame_msgtype != NULL && zframe_size(frame_msgtype) == sizeof(int16_t) ){
        return *(int16_t*)zframe_data(frame_msgtype);
    } 

    return MSGTYPE_UNKNOWN;
}
Пример #7
0
int main (void)
{
    zctx_t *ctx = zctx_new ();
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    void *backend = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (frontend, "tcp://*:5555");    //  For clients
    zsocket_bind (backend,  "tcp://*:5556");    //  For workers

    //  Queue of available workers
    zlist_t *workers = zlist_new ();
    
    //  The body of this example is exactly the same as lruqueue2.
    //  .skip
    while (1) {
        zmq_pollitem_t items [] = {
            { backend,  0, ZMQ_POLLIN, 0 },
            { frontend, 0, ZMQ_POLLIN, 0 }
        };
        //  Poll frontend only if we have available workers
        int rc = zmq_poll (items, zlist_size (workers)? 2: 1, -1);
        if (rc == -1)
            break;              //  Interrupted

        //  Handle worker activity on backend
        if (items [0].revents & ZMQ_POLLIN) {
            //  Use worker address for LRU routing
            zmsg_t *msg = zmsg_recv (backend);
            if (!msg)
                break;          //  Interrupted
            zframe_t *address = zmsg_unwrap (msg);
            zlist_append (workers, address);

            //  Forward message to client if it's not a READY
            zframe_t *frame = zmsg_first (msg);
            if (memcmp (zframe_data (frame), LRU_READY, 1) == 0)
                zmsg_destroy (&msg);
            else
                zmsg_send (&msg, frontend);
        }
        if (items [1].revents & ZMQ_POLLIN) {
            //  Get client request, route to first available worker
            zmsg_t *msg = zmsg_recv (frontend);
            if (msg) {
                zmsg_wrap (msg, (zframe_t *) zlist_pop (workers));
                zmsg_send (&msg, backend);
            }
        }
    }
    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        zframe_t *frame = (zframe_t *) zlist_pop (workers);
        zframe_destroy (&frame);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return 0;
    //  .until
}
Пример #8
0
size_t
zmsg_encode (zmsg_t *self, byte **buffer)
{
    assert (self);
    assert (zmsg_is (self));

    //  Calculate real size of buffer
    size_t buffer_size = 0;
    zframe_t *frame = zmsg_first (self);
    while (frame) {
        size_t frame_size = zframe_size (frame);
        if (frame_size < 255)
            buffer_size += frame_size + 1;
        else
            buffer_size += frame_size + 1 + 4;
        frame = zmsg_next (self);
    }
    *buffer = (byte *) zmalloc (buffer_size);

    if (*buffer) {
        //  Encode message now
        byte *dest = *buffer;
        frame = zmsg_first (self);
        while (frame) {
            size_t frame_size = zframe_size (frame);
            if (frame_size < 255) {
                *dest++ = (byte) frame_size;
                memcpy (dest, zframe_data (frame), frame_size);
                dest += frame_size;
            }
            else {
                *dest++ = 0xFF;
                *dest++ = (frame_size >> 24) & 255;
                *dest++ = (frame_size >> 16) & 255;
                *dest++ = (frame_size >>  8) & 255;
                *dest++ =  frame_size        & 255;
                memcpy (dest, zframe_data (frame), frame_size);
                dest += frame_size;
            }
            frame = zmsg_next (self);
        }
        assert ((dest - *buffer) == buffer_size);
    }
    return buffer_size;
}
Пример #9
0
int
zmsg_signal (zmsg_t *self)
{
    if (zmsg_size (self) == 1
    &&  zmsg_content_size (self) == 8) {
        zframe_t *frame = zmsg_first (self);
        int64_t signal_value = *((int64_t *) zframe_data (frame));
        if ((signal_value & 0xFFFFFFFFFFFFFF00L) == 0x7766554433221100L)
            return signal_value & 255;
    }
    return -1;
}
Пример #10
0
int message_check_action(zmsg_t *msg, const char *action)
{
    int16_t msgtype = message_get_msgtype(msg);
    if ( msgtype == MSGTYPE_ACTION ){
        zmsg_first(msg);
        zframe_t *frame = zmsg_next(msg);
        if ( frame != NULL ){
            return memcmp(zframe_data(frame), action, strlen(action));
        }
    }
    return -1;
}
Пример #11
0
int message_check_heartbeat(zmsg_t *msg, const char *heartbeat)
{
    int16_t msgtype = message_get_msgtype(msg);
    if ( msgtype == MSGTYPE_HEARTBEAT ){
        zmsg_first(msg);
        zframe_t *frame = zmsg_next(msg);
        if ( frame != NULL ){
            return memcmp(zframe_data(frame), heartbeat, strlen(heartbeat));
        }
    }
    return -1;
}
Пример #12
0
int message_check_status(zmsg_t *msg, const char *status)
{
    int16_t msgtype = message_get_msgtype(msg);
    if ( msgtype == MSGTYPE_STATUS ){
        zmsg_first(msg);
        zframe_t *frame = zmsg_next(msg);
        if ( frame != NULL ){
            return memcmp(zframe_data(frame), status, strlen(status));
        }
    }
    return -1;
}
Пример #13
0
zframe_t *
zmsg_unwrap (zmsg_t *self)
{
    assert (self);
    zframe_t *frame = zmsg_pop (self);
    zframe_t *empty = zmsg_first (self);
    if (zframe_size (empty) == 0) {
        empty = zmsg_pop (self);
        zframe_destroy (&empty);
    }
    return frame;
}
Пример #14
0
size_t
zmsg_encode (zmsg_t *self, byte **buffer)
{
    assert (self);

    //  Calculate real size of buffer
    size_t buffer_size = 0;
    zframe_t *frame = zmsg_first (self);
    while (frame) {
        size_t frame_size = zframe_size (frame);
        if (frame_size < ZMSG_SHORT_LEN)
            buffer_size += frame_size + 1;
        else
        if (frame_size < 0x10000)
            buffer_size += frame_size + 3;
        else
            buffer_size += frame_size + 5;
        frame = zmsg_next (self);
    }
    *buffer = malloc (buffer_size);

    //  Encode message now
    byte *dest = *buffer;
    frame = zmsg_first (self);
    while (frame) {
        size_t frame_size = zframe_size (frame);
        if (frame_size < ZMSG_SHORT_LEN) {
            *dest++ = (byte) frame_size;
            memcpy (dest, zframe_data (frame), frame_size);
            dest += frame_size;
        }
        else
        if (frame_size < 0x10000) {
            *dest++ = ZMSG_SHORT_LEN;
            *dest++ = (frame_size >> 8) & 255;
            *dest++ =  frame_size       & 255;
            memcpy (dest, zframe_data (frame), frame_size);
            dest += frame_size;
        }
        else {
Пример #15
0
void
interval_minit (interval_t ** interval, zmsg_t * msg)
{

    *interval = malloc (sizeof (interval_t));

    zframe_t *frame = zmsg_first (msg);
    memcpy (&((*interval)->start), zframe_data (frame), zframe_size (frame));
    frame = zmsg_next (msg);
    memcpy (&((*interval)->end), zframe_data (frame), zframe_size (frame));


}
Пример #16
0
void
zmsg_print (zmsg_t *self)
{
    assert (self);
    assert (zmsg_is (self));

    if (!self) {
        zsys_debug ("(NULL)");
        return;
    }
    zframe_t *frame = zmsg_first (self);
    while (frame) {
        zframe_print (frame, NULL);
        frame = zmsg_next (self);
    }
}
static zmsg_t *_thsafe_zmq_client_recv_confirmation (smio_t *self)
{
    DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Calling _thsafe_zmq_client_recv_confirmation\n");

    assert (self);
    /* Wait for response */
    zmsg_t *recv_msg = zmsg_recv (self->pipe);
    /* Do not pop the message, just set a cursor to it */
    zframe_t *reply_frame = zmsg_first (recv_msg);

    DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Receiving message:\n");
#ifdef LOCAL_MSG_DBG
    zmsg_print (recv_msg);
#endif

    /* Message is:
     * frame 0: Reply code */
    if (reply_frame == NULL) {
        /* Interrupted or malformed message */
        goto err_recv_data;
    }

    /* Check if the frame has the correct number of bytes */
    if (zframe_size (reply_frame) != THSAFE_REPLY_SIZE) {
        goto err_recv_data;
    }

    uint8_t *raw_data = (uint8_t *) zframe_data (reply_frame);
    ASSERT_TEST(raw_data != NULL, "Could not receive confirmation code", err_null_raw_data);
    uint32_t reply_code = *(uint32_t *) raw_data;

    /* Check for confirmation */
    if (reply_code != THSAFE_OK) {
        DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Received reply code OK\n");
        goto err_reply_code_not_ok;
    }

    /* Caller owns the message and is its responsability to destroy it */
    return recv_msg;

/* TODO: reduce code repetition */
err_reply_code_not_ok:
err_null_raw_data:
err_recv_data:
    zmsg_destroy (&recv_msg);
    return NULL;
}
Пример #18
0
//  --------------------------------------------------------------------------
//  Save message to an open file, return 0 if OK, else -1.
int
zmsg_save (zmsg_t *self, FILE *file)
{
    assert (self);
    assert (file);

    zframe_t *frame = zmsg_first (self);
    while (frame) {
        size_t frame_size = zframe_size (frame);
        if (fwrite (&frame_size, sizeof (frame_size), 1, file) != 1)
            return -1;
        if (fwrite (zframe_data (frame), frame_size, 1, file) != 1)
            return -1;
        frame = zmsg_next (self);
    }
    return 0;
}
Пример #19
0
void
zmsg_fprint (zmsg_t *self, FILE *file)
{
    assert (self);
    assert (zmsg_is (self));

    fprintf (file, "--------------------------------------\n");
    if (!self) {
        fprintf (file, "NULL");
        return;
    }
    zframe_t *frame = zmsg_first (self);
    int frame_nbr = 0;
    while (frame && frame_nbr++ < 10) {
        zframe_fprint (frame, NULL, file);
        frame = zmsg_next (self);
    }
}
Пример #20
0
zmsg_t *
zmsg_dup (zmsg_t *self)
{
    assert (self);
    assert (zmsg_is (self));

    zmsg_t *copy = zmsg_new ();
    if (!copy)
        return NULL;

    zframe_t *frame = zmsg_first (self);
    while (frame) {
        if (zmsg_addmem (copy, zframe_data (frame), zframe_size (frame))) {
            zmsg_destroy (&copy);
            return NULL;
        }
        frame = zmsg_next (self);
    }
    return copy;
}
Пример #21
0
zmsg_t *
zmsg_dup (zmsg_t *self)
{
    if (self) {
        assert (zmsg_is (self));
        zmsg_t *copy = zmsg_new ();
        if (copy) {
            zframe_t *frame = zmsg_first (self);
            while (frame) {
                if (zmsg_addmem (copy, zframe_data (frame), zframe_size (frame))) {
                    zmsg_destroy (&copy);
                    break;      //  Abandon attempt to copy message
                }
                frame = zmsg_next (self);
            }
        }
        return copy;
    }
    else
        return NULL;
}
Пример #22
0
static void
handle_frontend (GPPWorker *self)
{
  GPPWorkerPrivate *priv = GET_PRIV (self);
  GPPWorkerClass *klass = GPP_WORKER_GET_CLASS (self);
  zmsg_t *msg = zmsg_recv (priv->frontend);
  if (!msg)
    return;

  if (zmsg_size (msg) == 3) {
    char *request = zframe_strdup (zmsg_last (msg));
    g_info ("I: normal reply\n");
    priv->liveness = HEARTBEAT_LIVENESS;
    priv->current_task = msg;
    if (!klass->handle_request (self, request))
      gpp_worker_set_task_done (self, NULL, FALSE);
    free (request);
  } else {
    if (zmsg_size (msg) == 1) {
      zframe_t *frame = zmsg_first (msg);
      if (memcmp (zframe_data (frame), PPP_HEARTBEAT, 1) == 0) {
        priv->liveness = HEARTBEAT_LIVENESS;
        g_debug ("got heartbeat from queue !\n");
      } else {
        g_warning ("E: invalid message\n");
        zmsg_dump (msg);
      }
      zmsg_destroy (&msg);
    }
    else {
      g_warning ("E: invalid message\n");
      zmsg_dump (msg);
    }
  }
  priv->interval = INTERVAL_INIT;
}
Пример #23
0
int main (int argc, char *argv [])
{
    //  First argument is this broker's name
    //  Other arguments are our peers' names
    //
    if (argc < 2) {
        printf ("syntax: peering3 me {you}...\n");
        exit (EXIT_FAILURE);
    }
    self = argv [1];
    printf ("I: preparing broker at %s...\n", self);
    srandom ((unsigned) time (NULL));

    //  Prepare our context and sockets
    zctx_t *ctx = zctx_new ();
    char endpoint [256];

    //  Bind cloud frontend to endpoint
    void *cloudfe = zsocket_new (ctx, ZMQ_ROUTER);
    zsockopt_set_identity (cloudfe, self);
    zsocket_bind (cloudfe, "ipc://%s-cloud.ipc", self);

    //  Bind state backend / publisher to endpoint
    void *statebe = zsocket_new (ctx, ZMQ_PUB);
    zsocket_bind (statebe, "ipc://%s-state.ipc", self);

    //  Connect cloud backend to all peers
    void *cloudbe = zsocket_new (ctx, ZMQ_ROUTER);
    zsockopt_set_identity (cloudbe, self);
    int argn;
    for (argn = 2; argn < argc; argn++) {
        char *peer = argv [argn];
        printf ("I: connecting to cloud frontend at '%s'\n", peer);
        zsocket_connect (cloudbe, "ipc://%s-cloud.ipc", peer);
    }

    //  Connect statefe to all peers
    void *statefe = zsocket_new (ctx, ZMQ_SUB);
    for (argn = 2; argn < argc; argn++) {
        char *peer = argv [argn];
        printf ("I: connecting to state backend at '%s'\n", peer);
        zsocket_connect (statefe, "ipc://%s-state.ipc", peer);
    }
    //  Prepare local frontend and backend
    void *localfe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (localfe, "ipc://%s-localfe.ipc", self);

    void *localbe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (localbe, "ipc://%s-localbe.ipc", self);

    //  Prepare monitor socket
    void *monitor = zsocket_new (ctx, ZMQ_PULL);
    zsocket_bind (monitor, "ipc://%s-monitor.ipc", self);

    //  Start local workers
    int worker_nbr;
    for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++)
        zthread_new (ctx, worker_task, NULL);

    //  Start local clients
    int client_nbr;
    for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++)
        zthread_new (ctx, client_task, NULL);

    //  Interesting part
    //  -------------------------------------------------------------
    //  Publish-subscribe flow
    //  - Poll statefe and process capacity updates
    //  - Each time capacity changes, broadcast new value
    //  Request-reply flow
    //  - Poll primary and process local/cloud replies
    //  - While worker available, route localfe to local or cloud

    //  Queue of available workers
    int local_capacity = 0;
    int cloud_capacity = 0;
    zlist_t *workers = zlist_new ();

    while (1) {
        zmq_pollitem_t primary [] = {
            { localbe, 0, ZMQ_POLLIN, 0 },
            { cloudbe, 0, ZMQ_POLLIN, 0 },
            { statefe, 0, ZMQ_POLLIN, 0 },
            { monitor, 0, ZMQ_POLLIN, 0 }
        };
        //  If we have no workers anyhow, wait indefinitely
        int rc = zmq_poll (primary, 4,
                           local_capacity? 1000 * ZMQ_POLL_MSEC: -1);
        if (rc == -1)
            break;              //  Interrupted

        //  Track if capacity changes during this iteration
        int previous = local_capacity;

        //  Handle reply from local worker
        zmsg_t *msg = NULL;

        if (primary [0].revents & ZMQ_POLLIN) {
            msg = zmsg_recv (localbe);
            if (!msg)
                break;          //  Interrupted
            zframe_t *address = zmsg_unwrap (msg);
            zlist_append (workers, address);
            local_capacity++;

            //  If it's READY, don't route the message any further
            zframe_t *frame = zmsg_first (msg);
            if (memcmp (zframe_data (frame), LRU_READY, 1) == 0)
                zmsg_destroy (&msg);
        }
        //  Or handle reply from peer broker
        else if (primary [1].revents & ZMQ_POLLIN) {
            msg = zmsg_recv (cloudbe);
            if (!msg)
                break;          //  Interrupted
            //  We don't use peer broker address for anything
            zframe_t *address = zmsg_unwrap (msg);
            zframe_destroy (&address);
        }
        //  Route reply to cloud if it's addressed to a broker
        for (argn = 2; msg && argn < argc; argn++) {
            char *data = (char *) zframe_data (zmsg_first (msg));
            size_t size = zframe_size (zmsg_first (msg));
            if (size == strlen (argv [argn])
                    &&  memcmp (data, argv [argn], size) == 0)
                zmsg_send (&msg, cloudfe);
        }
        //  Route reply to client if we still need to
        if (msg)
            zmsg_send (&msg, localfe);

        //  Handle capacity updates
        if (primary [2].revents & ZMQ_POLLIN) {
            char *status = zstr_recv (statefe);
            cloud_capacity = atoi (status);
            free (status);
        }
        //  Handle monitor message
        if (primary [3].revents & ZMQ_POLLIN) {
            char *status = zstr_recv (monitor);
            printf ("%s\n", status);
            free (status);
        }

        //  Now route as many clients requests as we can handle
        //  - If we have local capacity we poll both localfe and cloudfe
        //  - If we have cloud capacity only, we poll just localfe
        //  - Route any request locally if we can, else to cloud
        //
        while (local_capacity + cloud_capacity) {
            zmq_pollitem_t secondary [] = {
                { localfe, 0, ZMQ_POLLIN, 0 },
                { cloudfe, 0, ZMQ_POLLIN, 0 }
            };
            if (local_capacity)
                rc = zmq_poll (secondary, 2, 0);
            else
                rc = zmq_poll (secondary, 1, 0);
            assert (rc >= 0);

            if (secondary [0].revents & ZMQ_POLLIN)
                msg = zmsg_recv (localfe);
            else if (secondary [1].revents & ZMQ_POLLIN)
                msg = zmsg_recv (cloudfe);
            else
                break;      //  No work, go back to primary

            if (local_capacity) {
                zframe_t *frame = (zframe_t *) zlist_pop (workers);
                zmsg_wrap (msg, frame);
                zmsg_send (&msg, localbe);
                local_capacity--;
            }
            else {
                //  Route to random broker peer
                int random_peer = randof (argc - 2) + 2;
                zmsg_pushmem (msg, argv [random_peer], strlen (argv [random_peer]));
                zmsg_send (&msg, cloudbe);
            }
        }
        if (local_capacity != previous) {
            //  We stick our own address onto the envelope
            zstr_sendm (statebe, self);
            //  Broadcast new capacity
            zstr_sendf (statebe, "%d", local_capacity);
        }
    }
    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        zframe_t *frame = (zframe_t *) zlist_pop (workers);
        zframe_destroy (&frame);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return EXIT_SUCCESS;
}
Пример #24
0
int main (int argc, char *argv [])
{
    //  First argument is this broker's name
    //  Other arguments are our peers' names
    //
    if (argc < 2) {
        printf ("syntax: peering2 me {you}...\n");
        return 0;
    }
    self = argv [1];
    printf ("I: preparing broker at %s...\n", self);
    srandom ((unsigned) time (NULL));

    zctx_t *ctx = zctx_new ();

    //  Bind cloud frontend to endpoint
    void *cloudfe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_set_identity (cloudfe, self);
    zsocket_bind (cloudfe, "ipc://%s-cloud.ipc", self);

    //  Connect cloud backend to all peers
    void *cloudbe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_set_identity (cloudbe, self);
    int argn;
    for (argn = 2; argn < argc; argn++) {
        char *peer = argv [argn];
        printf ("I: connecting to cloud frontend at '%s'\n", peer);
        zsocket_connect (cloudbe, "ipc://%s-cloud.ipc", peer);
    }
    //  Prepare local frontend and backend
    void *localfe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (localfe, "ipc://%s-localfe.ipc", self);
    void *localbe = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (localbe, "ipc://%s-localbe.ipc", self);

    //  Get user to tell us when we can start...
    printf ("Press Enter when all brokers are started: ");
    getchar ();

    //  Start local workers
    int worker_nbr;
    for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++)
        zthread_new (worker_task, NULL);

    //  Start local clients
    int client_nbr;
    for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++)
        zthread_new (client_task, NULL);

    //  .split request-reply handling
    //  Here, we handle the request-reply flow. We're using load-balancing
    //  to poll workers at all times, and clients only when there are one 
    //  or more workers available.

    //  Least recently used queue of available workers
    int capacity = 0;
    zlist_t *workers = zlist_new ();

    while (true) {
        //  First, route any waiting replies from workers
        zmq_pollitem_t backends [] = {
            { localbe, 0, ZMQ_POLLIN, 0 },
            { cloudbe, 0, ZMQ_POLLIN, 0 }
        };
        //  If we have no workers, wait indefinitely
        int rc = zmq_poll (backends, 2,
            capacity? 1000 * ZMQ_POLL_MSEC: -1);
        if (rc == -1)
            break;              //  Interrupted

        //  Handle reply from local worker
        zmsg_t *msg = NULL;
        if (backends [0].revents & ZMQ_POLLIN) {
            msg = zmsg_recv (localbe);
            if (!msg)
                break;          //  Interrupted
            zframe_t *identity = zmsg_unwrap (msg);
            zlist_append (workers, identity);
            capacity++;

            //  If it's READY, don't route the message any further
            zframe_t *frame = zmsg_first (msg);
            if (memcmp (zframe_data (frame), WORKER_READY, 1) == 0)
                zmsg_destroy (&msg);
        }
        //  Or handle reply from peer broker
        else
        if (backends [1].revents & ZMQ_POLLIN) {
            msg = zmsg_recv (cloudbe);
            if (!msg)
                break;          //  Interrupted
            //  We don't use peer broker identity for anything
            zframe_t *identity = zmsg_unwrap (msg);
            zframe_destroy (&identity);
        }
        //  Route reply to cloud if it's addressed to a broker
        for (argn = 2; msg && argn < argc; argn++) {
            char *data = (char *) zframe_data (zmsg_first (msg));
            size_t size = zframe_size (zmsg_first (msg));
            if (size == strlen (argv [argn])
            &&  memcmp (data, argv [argn], size) == 0)
                zmsg_send (&msg, cloudfe);
        }
        //  Route reply to client if we still need to
        if (msg)
            zmsg_send (&msg, localfe);

        //  .split route client requests
        //  Now we route as many client requests as we have worker capacity
        //  for. We may reroute requests from our local frontend, but not from 
        //  the cloud frontend. We reroute randomly now, just to test things
        //  out. In the next version, we'll do this properly by calculating
        //  cloud capacity:

        while (capacity) {
            zmq_pollitem_t frontends [] = {
                { localfe, 0, ZMQ_POLLIN, 0 },
                { cloudfe, 0, ZMQ_POLLIN, 0 }
            };
            rc = zmq_poll (frontends, 2, 0);
            assert (rc >= 0);
            int reroutable = 0;
            //  We'll do peer brokers first, to prevent starvation
            if (frontends [1].revents & ZMQ_POLLIN) {
                msg = zmsg_recv (cloudfe);
                reroutable = 0;
            }
            else
            if (frontends [0].revents & ZMQ_POLLIN) {
                msg = zmsg_recv (localfe);
                reroutable = 1;
            }
            else
                break;      //  No work, go back to backends

            //  If reroutable, send to cloud 20% of the time
            //  Here we'd normally use cloud status information
            //
            if (reroutable && argc > 2 && randof (5) == 0) {
                //  Route to random broker peer
                int peer = randof (argc - 2) + 2;
                zmsg_pushmem (msg, argv [peer], strlen (argv [peer]));
                zmsg_send (&msg, cloudbe);
            }
            else {
                zframe_t *frame = (zframe_t *) zlist_pop (workers);
                zmsg_wrap (msg, frame);
                zmsg_send (&msg, localbe);
                capacity--;
            }
        }
    }
    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        zframe_t *frame = (zframe_t *) zlist_pop (workers);
        zframe_destroy (&frame);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return EXIT_SUCCESS;
}
Пример #25
0
int main(void)
{
	zctx_t *ctx = zctx_new();
	void *frontend = zsocket_new(ctx, ZMQ_ROUTER);
	void *backend = zsocket_new(ctx, ZMQ_ROUTER);

	// IPC doesn't yet work on MS Windows.
#if (defined (WIN32))
	zsocket_bind(frontend, "tcp://*:5672");
	zsocket_bind(backend, "tcp://*:5673");
#else
	zsocket_bind(frontend, "ipc://frontend.ipc");
	zsocket_bind(backend, "ipc://backend.ipc");
#endif

	int client_nbr;
	for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++)
		zthread_new(client_task, NULL);
	int worker_nbr;
	for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++)
		zthread_new(worker_task, NULL);

	//  Queue of available workers
	zlist_t *workers = zlist_new();

	//  .split main load-balancer loop
	//  Here is the main loop for the load balancer. It works the same way
	//  as the previous example, but is a lot shorter because CZMQ gives
	//  us an API that does more with fewer calls:
	while (1) {
		zmq_pollitem_t items[] = {
				{ backend, 0, ZMQ_POLLIN, 0 },
				{ frontend, 0, ZMQ_POLLIN, 0 }
		};
		//  Poll frontend only if we have available workers
		int rc = zmq_poll(items, zlist_size(workers) ? 2 : 1, -1);
		if (rc == -1)
			break;              //  Interrupted

		//  Handle worker activity on backend
		if (items[0].revents & ZMQ_POLLIN) {
			//  Use worker identity for load-balancing
			zmsg_t *msg = zmsg_recv(backend);
			if (!msg)
				break;          //  Interrupted

#if 0
			// zmsg_unwrap is DEPRECATED as over-engineered, poor style
			zframe_t *identity = zmsg_unwrap(msg);
#else
			zframe_t *identity = zmsg_pop(msg);
			zframe_t *delimiter = zmsg_pop(msg);
			zframe_destroy(&delimiter); 
#endif

			zlist_append(workers, identity);

			//  Forward message to client if it's not a READY
			zframe_t *frame = zmsg_first(msg);
			if (memcmp(zframe_data(frame), WORKER_READY, strlen(WORKER_READY)) == 0) {
				zmsg_destroy(&msg);
			} else {
				zmsg_send(&msg, frontend);
				if (--client_nbr == 0)
					break; // Exit after N messages
			}
		}
		if (items[1].revents & ZMQ_POLLIN) {
			//  Get client request, route to first available worker
			zmsg_t *msg = zmsg_recv(frontend);
			if (msg) {
#if 0
				// zmsg_wrap is DEPRECATED as unsafe
				zmsg_wrap(msg, (zframe_t *)zlist_pop(workers));
#else
				zmsg_pushmem(msg, NULL, 0); // delimiter
				zmsg_push(msg, (zframe_t *)zlist_pop(workers));
#endif

				zmsg_send(&msg, backend);
			}
		}
	}
	//  When we're done, clean up properly
	while (zlist_size(workers)) {
		zframe_t *frame = (zframe_t *)zlist_pop(workers);
		zframe_destroy(&frame);
	}
	zlist_destroy(&workers);
	zctx_destroy(&ctx);
	return 0;
}
Пример #26
0
int main(void){
  zctx_t *ctx=zctx_new();
  void *worker=_worker_socket(ctx);

  size_t liveness=HEARTBEAT_LIVENESS;
  size_t interval=INTERVAL_INIT;

  uint64_t heartbeat_at=zclock_time()+HEARTBEAT_INTERVAL;

  srandom((unsigned)time(NULL));
  int cycles=0;
  while (true){
    zmq_pollitem_t items[]={{worker, 0, ZMQ_POLLIN, 0}};
    int rc=zmq_poll(items, 1, HEARTBEAT_INTERVAL*ZMQ_POLL_MSEC);
    if (rc==-1){
      break;
    }

    if (items[0].revents & ZMQ_POLLIN){
      zmsg_t *msg=zmsg_recv(worker);
      if (!msg){
        break;
      }

      if (zmsg_size(msg)==3){
        ++cycles;
        if (cycles>3 && randof(5)==0){
          debug_log("I: simulating a crash\n");
          zmsg_destroy(&msg);
          break;
        } else if (cycles>3 && randof(5)==0){
          debug_log("I: simulating CPU overload\n");
          sleep(3);
          if (zctx_interrupted){
            break;
          }
        } else{
          debug_log("I: normal reply\n");
          zmsg_send(&msg, worker);
          sleep(1);
          if (zctx_interrupted){
            break;
          }
        }
      } else if (zmsg_size(msg)==1){
        zframe_t *frame=zmsg_first(msg);
        if (memcmp(zframe_data(frame), PPP_HEARTBEAT, 1)==0){
          liveness=HEARTBEAT_LIVENESS;
        } else{
          debug_log(ERROR_COLOR"E: inval message\n"NORMAL_COLOR);
          zmsg_dump(msg);
        }
        zmsg_destroy(&msg);
      } else{
        debug_log(ERROR_COLOR"E: invalid message\n"NORMAL_COLOR);
        zmsg_dump(msg);
      }
      interval=INTERVAL_INIT;
    } else if (--liveness==0){
      debug_log(WARN_COLOR"W: heartbeat failure, can't reach queue\n"
                NORMAL_COLOR);
      debug_log(WARN_COLOR"W: reconnecting in %zd msec"STR_ELLIPSIS"\n"
                NORMAL_COLOR, interval);
      zclock_sleep(interval);

      if (interval<INTERVAL_MAX){
        interval*=2;
      }

      zsocket_destroy(ctx, worker);
      worker=_worker_socket(ctx);
      liveness=HEARTBEAT_LIVENESS;
    }

    if (zclock_time()>heartbeat_at){
      heartbeat_at=zclock_time()+HEARTBEAT_INTERVAL;
      debug_log("I: worker heartbeat\n");
      zframe_t *frame=zframe_new(PPP_HEARTBEAT, 1);
      zframe_send(&frame, worker, 0);
    }
  }
  
  zctx_destroy(&ctx);
  return 0;
}
Пример #27
0
void
zmsg_test (bool verbose)
{
    printf (" * zmsg: ");

    int rc = 0;
    //  @selftest
    //  Create two PAIR sockets and connect over inproc
    zsock_t *output = zsock_new_pair ("@inproc://zmsg.test");
    assert (output);
    zsock_t *input = zsock_new_pair (">inproc://zmsg.test");
    assert (input);

    //  Test send and receive of single-frame message
    zmsg_t *msg = zmsg_new ();
    assert (msg);
    zframe_t *frame = zframe_new ("Hello", 5);
    assert (frame);
    zmsg_prepend (msg, &frame);
    assert (zmsg_size (msg) == 1);
    assert (zmsg_content_size (msg) == 5);
    rc = zmsg_send (&msg, output);
    assert (msg == NULL);
    assert (rc == 0);

    msg = zmsg_recv (input);
    assert (msg);
    assert (zmsg_size (msg) == 1);
    assert (zmsg_content_size (msg) == 5);
    zmsg_destroy (&msg);

    //  Test send and receive of multi-frame message
    msg = zmsg_new ();
    assert (msg);
    rc = zmsg_addmem (msg, "Frame0", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame1", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame2", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame3", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame4", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame5", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame6", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame7", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame8", 6);
    assert (rc == 0);
    rc = zmsg_addmem (msg, "Frame9", 6);
    assert (rc == 0);
    zmsg_t *copy = zmsg_dup (msg);
    assert (copy);
    rc = zmsg_send (&copy, output);
    assert (rc == 0);
    rc = zmsg_send (&msg, output);
    assert (rc == 0);

    copy = zmsg_recv (input);
    assert (copy);
    assert (zmsg_size (copy) == 10);
    assert (zmsg_content_size (copy) == 60);
    zmsg_destroy (&copy);

    msg = zmsg_recv (input);
    assert (msg);
    assert (zmsg_size (msg) == 10);
    assert (zmsg_content_size (msg) == 60);

    // create empty file for null test
    FILE *file = fopen ("zmsg.test", "w");
    assert (file);
    fclose (file);

    file = fopen ("zmsg.test", "r");
    zmsg_t *null_msg = zmsg_load (NULL, file);
    assert (null_msg == NULL);
    fclose (file);
    remove ("zmsg.test");

    //  Save to a file, read back
    file = fopen ("zmsg.test", "w");
    assert (file);
    rc = zmsg_save (msg, file);
    assert (rc == 0);
    fclose (file);

    file = fopen ("zmsg.test", "r");
    rc = zmsg_save (msg, file);
    assert (rc == -1);
    fclose (file);
    zmsg_destroy (&msg);

    file = fopen ("zmsg.test", "r");
    msg = zmsg_load (NULL, file);
    assert (msg);
    fclose (file);
    remove ("zmsg.test");
    assert (zmsg_size (msg) == 10);
    assert (zmsg_content_size (msg) == 60);

    //  Remove all frames except first and last
    int frame_nbr;
    for (frame_nbr = 0; frame_nbr < 8; frame_nbr++) {
        zmsg_first (msg);
        frame = zmsg_next (msg);
        zmsg_remove (msg, frame);
        zframe_destroy (&frame);
    }
    //  Test message frame manipulation
    assert (zmsg_size (msg) == 2);
    frame = zmsg_last (msg);
    assert (zframe_streq (frame, "Frame9"));
    assert (zmsg_content_size (msg) == 12);
    frame = zframe_new ("Address", 7);
    assert (frame);
    zmsg_prepend (msg, &frame);
    assert (zmsg_size (msg) == 3);
    rc = zmsg_addstr (msg, "Body");
    assert (rc == 0);
    assert (zmsg_size (msg) == 4);
    frame = zmsg_pop (msg);
    zframe_destroy (&frame);
    assert (zmsg_size (msg) == 3);
    char *body = zmsg_popstr (msg);
    assert (streq (body, "Frame0"));
    free (body);
    zmsg_destroy (&msg);

    //  Test encoding/decoding
    msg = zmsg_new ();
    assert (msg);
    byte *blank = (byte *) zmalloc (100000);
    assert (blank);
    rc = zmsg_addmem (msg, blank, 0);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 1);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 253);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 254);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 255);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 256);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 65535);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 65536);
    assert (rc == 0);
    rc = zmsg_addmem (msg, blank, 65537);
    assert (rc == 0);
    free (blank);
    assert (zmsg_size (msg) == 9);
    byte *buffer;
    size_t buffer_size = zmsg_encode (msg, &buffer);
    zmsg_destroy (&msg);
    msg = zmsg_decode (buffer, buffer_size);
    assert (msg);
    free (buffer);
    zmsg_destroy (&msg);

    //  Test submessages
    msg = zmsg_new ();
    assert (msg);
    zmsg_t *submsg = zmsg_new ();
    zmsg_pushstr (msg, "matr");
    zmsg_pushstr (submsg, "joska");
    rc = zmsg_addmsg (msg, &submsg);
    assert (rc == 0);
    assert (submsg == NULL);
    submsg = zmsg_popmsg (msg);
    assert (submsg == NULL);   // string "matr" is not encoded zmsg_t, so was discarded
    submsg = zmsg_popmsg (msg);
    assert (submsg);
    body = zmsg_popstr (submsg);
    assert (streq (body, "joska"));
    free (body);
    zmsg_destroy (&submsg);
    frame = zmsg_pop (msg);
    assert (frame == NULL);
    zmsg_destroy (&msg);

    //  Test comparison of two messages
    msg = zmsg_new ();
    zmsg_addstr (msg, "One");
    zmsg_addstr (msg, "Two");
    zmsg_addstr (msg, "Three");
    zmsg_t *msg_other = zmsg_new ();
    zmsg_addstr (msg_other, "One");
    zmsg_addstr (msg_other, "Two");
    zmsg_addstr (msg_other, "One-Hundred");
    zmsg_t *msg_dup = zmsg_dup (msg);
    zmsg_t *empty_msg = zmsg_new ();
    zmsg_t *empty_msg_2 = zmsg_new ();
    assert (zmsg_eq (msg, msg_dup));
    assert (!zmsg_eq (msg, msg_other));
    assert (zmsg_eq (empty_msg, empty_msg_2));
    assert (!zmsg_eq (msg, NULL));
    assert (!zmsg_eq (NULL, empty_msg));
    assert (!zmsg_eq (NULL, NULL));
    zmsg_destroy (&msg);
    zmsg_destroy (&msg_other);
    zmsg_destroy (&msg_dup);
    zmsg_destroy (&empty_msg);
    zmsg_destroy (&empty_msg_2);

    //  Test signal messages
    msg = zmsg_new_signal (0);
    assert (zmsg_signal (msg) == 0);
    zmsg_destroy (&msg);
    msg = zmsg_new_signal (-1);
    assert (zmsg_signal (msg) == 255);
    zmsg_destroy (&msg);

    //  Now try methods on an empty message
    msg = zmsg_new ();
    assert (msg);
    assert (zmsg_size (msg) == 0);
    assert (zmsg_unwrap (msg) == NULL);
    assert (zmsg_first (msg) == NULL);
    assert (zmsg_last (msg) == NULL);
    assert (zmsg_next (msg) == NULL);
    assert (zmsg_pop (msg) == NULL);
    //  Sending an empty message is valid and destroys the message
    assert (zmsg_send (&msg, output) == 0);
    assert (!msg);

    zsock_destroy (&input);
    zsock_destroy (&output);

    //  @end
    printf ("OK\n");
}
Пример #28
0
static
int read_router_request_forward(zloop_t *loop, zsock_t *socket, void *callback_data)
{
    subscriber_state_t *state = callback_data;
    zmsg_t *msg = zmsg_recv(socket);
    assert(msg);
    bool ok = true;
    bool is_ping = false;
    state->message_count++;

    // pop the sender id added by the router socket
    zframe_t *sender_id = zmsg_pop(msg);
    zframe_t *empty = zmsg_first(msg);
    zmsg_t *reply = NULL;

    // if the second frame is not empty, we don't need to send a reply
    if (zframe_size(empty) > 0)
        zframe_destroy(&sender_id);
    else {
        // prepare reply
        reply = zmsg_new();
        zmsg_append(reply, &sender_id);
        // pop the empty frame
        empty = zmsg_pop(msg);
        zmsg_append(reply, &empty);
    }

    int n = zmsg_size(msg);
    if (n < 3 || n > 4) {
        fprintf(stderr, "[E] subscriber: (%s:%d): dropped invalid message of size %d\n", __FILE__, __LINE__, n);
        my_zmsg_fprint(msg, "[E] FRAME= ", stderr);
        ok = false;
        goto answer;
    }
    if (n == 4) {
        int is_heartbeat = process_meta_information_and_handle_heartbeat(state, msg);
        if (is_heartbeat) {
            zmsg_destroy(&msg);
            goto answer;
        }
        is_ping = zframe_streq(zmsg_first(msg), "ping");
        if (is_ping)
            goto answer;
    }

    if (PUBLISH_DUPLICATES)
        subscriber_publish_duplicate(msg, state->pub_socket);

    if (!output_socket_ready(state->push_socket, 0) && !state->message_blocks++)
        fprintf(stderr, "[W] subscriber: push socket not ready. blocking!\n");

    int rc = zmsg_send_and_destroy(&msg, state->push_socket);
    if (rc) {
        if (!state->message_drops++)
            fprintf(stderr, "[E] subscriber: dropped message on push socket (%d: %s)\n", errno, zmq_strerror(errno));
    }
 answer:
    if (reply) {
        if (is_ping) {
            if (ok) {
                zmsg_addstr(reply, "200 Pong");
                zmsg_addstr(reply, my_fqdn());
            } else {
                zmsg_addstr(reply, "400 Bad Request");
            }
        } else
            zmsg_addstr(reply, ok ? "202 Accepted" : "400 Bad Request");
        int rc = zmsg_send_and_destroy(&reply, socket);
        if (rc)
            fprintf(stderr, "[E] subscriber: could not send response (%d: %s)\n", errno, zmq_strerror(errno));
    }
    return 0;
}
Пример #29
0
int main (void)
{
    zctx_t *ctx = zctx_new ();
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    void *backend = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (frontend, "tcp://*:5555");    //  For clients
    zsocket_bind (backend,  "tcp://*:5556");    //  For workers

    //  List of available workers
    zlist_t *workers = zlist_new ();

    //  Send out heartbeats at regular intervals
    uint64_t heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;

    while (1) {
        zmq_pollitem_t items [] = {
            { backend,  0, ZMQ_POLLIN, 0 },
            { frontend, 0, ZMQ_POLLIN, 0 }
        };
        //  Poll frontend only if we have available workers
        int rc = zmq_poll (items, zlist_size (workers)? 2: 1,
            HEARTBEAT_INTERVAL * ZMQ_POLL_MSEC);
        if (rc == -1)
            break;              //  Interrupted

        //  Handle worker activity on backend
        if (items [0].revents & ZMQ_POLLIN) {
            //  Use worker address for LRU routing
            zmsg_t *msg = zmsg_recv (backend);
            if (!msg)
                break;          //  Interrupted

            //  Any sign of life from worker means it's ready
            zframe_t *address = zmsg_unwrap (msg);
            worker_t *worker = s_worker_new (address);
            s_worker_ready (worker, workers);

            //  Validate control message, or return reply to client
            if (zmsg_size (msg) == 1) {
                zframe_t *frame = zmsg_first (msg);
                if (memcmp (zframe_data (frame), PPP_READY, 1)
                &&  memcmp (zframe_data (frame), PPP_HEARTBEAT, 1)) {
                    printf ("E: invalid message from worker");
                    zmsg_dump (msg);
                }
                zmsg_destroy (&msg);
            }
            else
                zmsg_send (&msg, frontend);
        }
        if (items [1].revents & ZMQ_POLLIN) {
            //  Now get next client request, route to next worker
            zmsg_t *msg = zmsg_recv (frontend);
            if (!msg)
                break;          //  Interrupted
            zmsg_push (msg, s_workers_next (workers));
            zmsg_send (&msg, backend);
        }

        //  .split handle heartbeating
        //  We handle heartbeating after any socket activity. First we send
        //  heartbeats to any idle workers if it's time. Then we purge any
        //  dead workers:
        
        if (zclock_time () >= heartbeat_at) {
            worker_t *worker = (worker_t *) zlist_first (workers);
            while (worker) {
                zframe_send (&worker->address, backend,
                             ZFRAME_REUSE + ZFRAME_MORE);
                zframe_t *frame = zframe_new (PPP_HEARTBEAT, 1);
                zframe_send (&frame, backend, 0);
                worker = (worker_t *) zlist_next (workers);
            }
            heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;
        }
        s_workers_purge (workers);
    }

    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        worker_t *worker = (worker_t *) zlist_pop (workers);
        s_worker_destroy (&worker);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return 0;
}
Пример #30
0
int 
main(int argc, char* argv[])
{
  int i, client_num, worker_num;
  zctx_t* ctx;
  void* frontend;
  void* backend;
  zlist_t* workers;

  if (argc < 3) {
    fprintf(stderr, "arguments error ...\n");
    return 1;
  }
  client_num = atoi(argv[1]);
  worker_num = atoi(argv[2]);

  ctx = zctx_new();


  frontend = zsocket_new(ctx, ZMQ_ROUTER);
  backend = zsocket_new(ctx, ZMQ_ROUTER);
  zsocket_bind(frontend, "ipc://frontend.ipc");
  zsocket_bind(backend, "ipc://backend.ipc");

  for (i = 0; i < client_num; ++i)
    zthread_new(client_routine, NULL);
  for (i = 0; i < worker_num; ++i)
    zthread_new(worker_routine, NULL);

  workers = zlist_new();
  while (1) {
    zmq_pollitem_t items[] = {
      {backend, 0, ZMQ_POLLIN, 0}, 
      {frontend, 0, ZMQ_POLLIN, 0}, 
    };
    int rc = zmq_poll(items, zlist_size(workers) ? 2 : 1, -1);
    if (-1 == rc)
      break;

    if (items[0].revents & ZMQ_POLLIN) {
      zmsg_t* msg;
      zframe_t* identity;
      zframe_t* frame;

      msg = zmsg_recv(backend);
      if (NULL == msg)
        break;
      identity = zmsg_unwrap(msg);
      zlist_append(workers, identity);

      frame = zmsg_first(msg);
      if (0 == memcmp(zframe_data(frame), WORKER_READY, 1))
        zmsg_destroy(&msg);
      else 
        zmsg_send(&msg, frontend);
    }
    if (items[1].revents & ZMQ_POLLIN) {
      zmsg_t* msg = zmsg_recv(frontend);
      if (NULL != msg) {
        zmsg_wrap(msg, (zframe_t*)zlist_pop(workers));
        zmsg_send(&msg, backend);
      }
    }
  }

  while (zlist_size(workers)) {
    zframe_t* frame = (zframe_t*)zlist_pop(workers);
    zframe_destroy(&frame);
  }


  zlist_destroy(&workers);
  zctx_destroy(&ctx);
  return 0;
}