void WorkerAgent::actorTask(zsock_t *pipe, void *args) { assert(pipe); assert(args); const WorkerAgent &agent = *static_cast<WorkerAgent *>(args); const auto worker = detail::makeSock(zsock_new_router(agent._localEndpoint.c_str())); assert(worker.get()); const auto poller = detail::makePoller(zpoller_new(pipe, worker.get(), nullptr)); assert(poller.get()); int rc = zsock_signal(pipe, 0); UNUSED(rc); assert(rc == 0); bool terminated = false; while (!terminated && !zsys_interrupted) { zsock_t *sock = static_cast<zsock_t *>(zpoller_wait(poller.get(), -1)); if (sock == pipe) { std::unique_ptr<char> command(zstr_recv(sock)); if (streq(command.get(), "$TERM")) { terminated = true; } } else if (sock == worker.get()) { auto request = detail::makeMsg(zmsg_recv(sock)); assert(zmsg_size(request.get()) == 3); auto identity = detail::makeFrame(zmsg_pop(request.get())); auto id = detail::makeFrame(zmsg_pop(request.get())); static const auto respond = []( auto &&identity, auto &&id, const char *status, auto &&data, zsock_t *sock) { zmsg_t *response = zmsg_new(); // Identity for ROUTER zframe_t *f = identity.release(); zmsg_append(response, &f); // Caller local ID f = id.release(); zmsg_append(response, &f); // Status f = zframe_new(status, std::strlen(status)); zmsg_append(response, &f); // Result f = data.release(); zmsg_append(response, &f); zmsg_send(&response, sock); }; try { auto argsFrame = detail::makeFrame(zmsg_pop(request.get())); msgpack::unpacked msg; msgpack::unpack( &msg, reinterpret_cast<const char *>(zframe_data(argsFrame.get())), zframe_size(argsFrame.get())); msgpack::sbuffer sbuf; agent._callback(msg, sbuf); auto resultFrame = detail::makeFrame(zframe_new(sbuf.data(), sbuf.size())); respond(identity, id, "", resultFrame, sock); } catch (const msgpack::type_error &e) { respond(identity, id, "I", detail::makeFrame(zframe_new_empty()), sock); } catch (const InvalidArgument &e) { respond(identity, id, "I", detail::makeFrame(zframe_new_empty()), sock); } catch (const UndefinedReference &e) { respond(identity, id, "U", detail::makeFrame(zframe_new_empty()), sock); } catch (const NetworkError &e) { respond(identity, id, "N", detail::makeFrame(zframe_new_empty()), sock); } catch (...) { respond(identity, id, "?", detail::makeFrame(zframe_new_empty()), sock); } } } zsys_debug("Cleaned up worker agent."); }
/// // Remove first frame from message, if any. Returns frame, or NULL. QZframe * QZmsg::pop () { QZframe *rv = new QZframe (zmsg_pop (self)); return rv; }
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 (©, 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 (©); 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"); }
/// // Remove first frame from message, if any. Returns frame, or NULL. QmlZframe *QmlZmsg::pop () { QmlZframe *retQ_ = new QmlZframe (); retQ_->self = zmsg_pop (self); return retQ_; };
int main (int argc, char *argv[]) { if (argc != 4) { exit (-1); } int numb_msgs = atoi (argv[2]); int numb_unimp_threads = atoi (argv[3]); zctx_t *ctx = zctx_new (); void *router_imp = zsocket_new (ctx, ZMQ_ROUTER); zsocket_set_rcvhwm (router_imp, 500000000); zsocket_bind (router_imp, "%s:9000", argv[1]); void *router_unimp = zsocket_new (ctx, ZMQ_ROUTER); zsocket_set_rcvhwm (router_unimp, 500000000); zsocket_bind (router_unimp, "%s:9001", argv[1]); void *pub = zsocket_new (ctx, ZMQ_PUB); zsocket_bind (pub, "%s:9002", argv[1]); int64_t time[3]; int64_t idle=0; int64_t diff; zclock_sleep (1000); //send the signal to start zmsg_t *amsg = zmsg_new (); zmsg_add (amsg, zframe_new ("all", 4)); zmsg_send (&amsg, pub); zmq_pollitem_t pollitem[2] = { {router_imp, 0, ZMQ_POLLIN} , {router_unimp, 0, ZMQ_POLLIN} }; unsigned long av_dropped_priority=0; unsigned long dropped=0; unsigned long av_processed_priority=0; unsigned long processed=0; int i; int imp_counter = 0; int once = 1; int ndiffs = 0; unsigned char drop_priority = 0; for (i = 0; i < 2 * numb_msgs; i++) { diff = zclock_time (); if (zmq_poll (pollitem, 2, -1) == -1) { exit (-1); } diff = zclock_time () - diff; idle = idle + diff; update_drop_rate(&diff,&drop_priority,&ndiffs); if (pollitem[0].revents & ZMQ_POLLIN) { zmsg_t *msg = zmsg_recv (router_imp); if (!msg) { exit (-1); } zmsg_destroy (&msg); imp_counter++; if (imp_counter == numb_msgs) { time[0] = zclock_time (); } } else { if (pollitem[1].revents & ZMQ_POLLIN) { if (once) { time[1] = zclock_time (); once = 0; } zmsg_t *msg = zmsg_recv (router_unimp); if (!msg) { exit (-1); } zframe_t *frame = zmsg_unwrap (msg); zframe_destroy (&frame); unsigned char priority; memcpy (&priority, zframe_data (zmsg_first (msg)), 1); if (priority < drop_priority) { av_dropped_priority+=priority; dropped++; // printf ("dropped:%u\n", priority); zmsg_destroy (&msg); } else { av_processed_priority+=priority; processed++; // printf ("received:%u\n", priority); zmsg_destroy (&msg); } } } } time[2] = zclock_time (); printf ("msgs received:%d\n", i); amsg = zmsg_new (); zmsg_add (amsg, zframe_new ("all", 4)); zmsg_send (&amsg, pub); zmsg_t *msg = zmsg_recv (router_imp); zframe_t *frame = zmsg_unwrap (msg); zframe_destroy (&frame); int64_t time_imp[2]; frame = zmsg_pop (msg); memcpy (time_imp, zframe_data (frame), zframe_size (frame)); zframe_destroy (&frame); zmsg_destroy (&msg); int64_t time_unimp[numb_unimp_threads][2]; for(i=0; i<numb_unimp_threads; i++){ msg = zmsg_recv (router_unimp); frame = zmsg_unwrap (msg); zframe_destroy (&frame); frame = zmsg_pop (msg); memcpy (time_unimp[i], zframe_data (frame), zframe_size (frame)); zframe_destroy (&frame); zmsg_destroy (&msg); } //compute average latency printf ("\nTime when important msgs started to be sent: %lld\n", time_imp[0]); printf ("\nTime when important msgs were processed: %lld\n", time[0]); printf ("\nDifference: %lld\n", time[0] - time_imp[0]); for(i=0; i<numb_unimp_threads; i++){ printf ("\nTime when unimportant msgs started to be sent: %lld\n", time_unimp[i][0]); printf ("\nTime when unimportant msgs were processed: %lld\n", time[2]); printf ("\nDifference: %lld\n", time[2] - time_unimp[i][0]); } printf ("\nTime when unimportant msgs started to be processed: %lld\n", time[1]); printf ("idle time:%llu\n",idle); printf ("dropped msgs:%llu\n",dropped); printf ("av_dropped_priority:%llu\n",av_dropped_priority/dropped); printf ("processed msgs:%llu\n",processed); printf ("av_processed_priority:%llu\n",av_processed_priority/processed); }
zmsg_t * mdp_client_send (mdp_client_t *self, char *service, zmsg_t **request_p) { assert (self); assert (request_p); zmsg_t *request = *request_p; // Prefix request with protocol frames // Frame 1: "MDPCxy" (six bytes, MDP/Client x.y) // Frame 2: Service name (printable string) zmsg_pushstr (request, service); zmsg_pushstr (request, MDPC_CLIENT); if (self->verbose) { zclock_log ("I: send request to '%s' service:", service); zmsg_dump (request); } int retries_left = self->retries; while (retries_left && !zctx_interrupted) { zmsg_t *msg = zmsg_dup (request); zmsg_send (&msg, self->client); zmq_pollitem_t items [] = { { self->client, 0, ZMQ_POLLIN, 0 } }; // On any blocking call, libzmq will return -1 if there was // an error; we could in theory check for different error codes // but in practice it's OK to assume it was EINTR (Ctrl-C) int rc = zmq_poll (items, 1, self->timeout * ZMQ_POLL_MSEC); if (rc == -1) break; // Interrupted // If we got a reply, process it if (items [0].revents & ZMQ_POLLIN) { zmsg_t *msg = zmsg_recv (self->client); if (self->verbose) { zclock_log ("I: received reply:"); zmsg_dump (msg); } // We would handle malformed replies better in real code assert (zmsg_size (msg) >= 3); zframe_t *header = zmsg_pop (msg); assert (zframe_streq (header, MDPC_CLIENT)); zframe_destroy (&header); zframe_t *reply_service = zmsg_pop (msg); assert (zframe_streq (reply_service, service)); zframe_destroy (&reply_service); zmsg_destroy (&request); return msg; // Success } else if (--retries_left) { if (self->verbose) zclock_log ("W: no reply, reconnecting..."); s_mdp_client_connect_to_broker (self); } else { if (self->verbose) zclock_log ("W: permanent error, abandoning"); break; // Give up } } if (zctx_interrupted) printf ("W: interrupt received, killing client...\n"); zmsg_destroy (&request); return NULL; }
void watch_port(void *cvoid, zctx_t * context, void * pipe ) { zclock_log("watch_port started!"); monitorconfig_t * config = (monitorconfig_t*) cvoid; dump_monitorconfig(config); void * linein = zsocket_new(context, ZMQ_SUB); char * listen_socket = to_linesocket(config->line_id); char line_id[16]; sprintf(line_id, "%d", config->line_id); zsocket_connect(linein, listen_socket); zsockopt_set_unsubscribe(linein, ""); zsockopt_set_subscribe(linein, "CLEAR_MONITORS"); zsockopt_set_subscribe(linein, "VALUE"); // have set up subscription, can signal parent that we're ok. child_handshake(pipe); zsocket_destroy(context, pipe); // no longer require pipe void * lineout = zsocket_new(context, ZMQ_PUB); zsocket_connect(lineout, config->out_socket); time_t until = time(NULL) + 60; while(time(NULL)<until) { zmsg_t * msg = zmsg_recv(linein); if(!msg) { zclock_log("monitor quitting!"); return; } zframe_t * cmd = zmsg_pop(msg); if(zframe_streq(cmd, "CLEAR_MONITORS")) { zclock_log("ephemeral monitor quitting"); zmsg_destroy(&msg); zframe_destroy(&cmd); break; } else if (zframe_streq(cmd, "VALUE")) { // TODO perhaps some rate limiting necessary assert(zmsg_size(msg) == 2); zframe_t * value = zmsg_pop(msg); int res = *(int*)zframe_data(value); char * new_channel = zmsg_popstr(msg); if(strcmp(new_channel, config->channel)!=0) { zclock_log("monitor on %d: listening for %s, channel changed to %s quitting", config->line_id, config->channel, new_channel); zmsg_destroy(&msg); zframe_destroy(&cmd); break; } zmsg_t * to_send = zmsg_new(); char buf[1024]; sprintf(buf, "%d", res); zmsg_pushstr(to_send, buf); zmsg_pushstr(to_send, line_id); zmsg_pushstr(to_send, config->source_worker); zclock_log("%s sending line %s -> %s", config->source_worker, line_id, buf); zmsg_send(&to_send, lineout); // don't destroy value frame, now owned by zmsg } // else ignore zmsg_destroy(&msg); zframe_destroy(&cmd); } zclock_log("monitor on %d: listening for %s, expiring naturally", config->line_id, config->channel); //cleanup zsocket_destroy(context, linein); zsocket_destroy(context, lineout); }