void agent_router_message (agent_t *self) { zmsg_t *reply = zmsg_recv (self->router); // Frame 0 is server that replied char *endpoint = zmsg_pop (reply); server_t *server = (server_t *) zhash_lookup (self->servers, endpoint); assert (server); free (endpoint); if (!server->alive) { zlist_append (self->actives, server); server->alive = 1; } server->ping_at = s_clock () + PING_INTERVAL; server->expires = s_clock () + SERVER_TTL; // Frame 1 may be sequence number for reply if (zmsg_parts (reply) > 1 && atoi (zmsg_address (reply)) == self->sequence) { free (zmsg_pop (reply)); zmsg_push (reply, "OK"); zmsg_send (&reply, self->control); zmsg_destroy (&self->request); } zmsg_destroy (&reply); }
int main (int argc, char *argv []) { if (argc == 1) { printf ("I: syntax: %s <endpoint> ...\n", argv [0]); exit (EXIT_SUCCESS); } // Create new freelance client object flclient_t *client = flclient_new (); // Connect to each endpoint int argn; for (argn = 1; argn < argc; argn++) flclient_connect (client, argv [argn]); // Send a bunch of name resolution 'requests', measure time int requests = 10000; uint64_t start = s_clock (); while (requests--) { zmsg_t *request = zmsg_new ("random name"); zmsg_t *reply = flclient_request (client, &request); if (!reply) { printf ("E: name service not available, aborting\n"); exit (EXIT_FAILURE); } zmsg_destroy (&reply); } printf ("Average round trip cost: %d usec\n", (int) (s_clock () - start) / 10); flclient_destroy (&client); return 0; }
void agent_control_message (agent_t *self) { zmsg_t *msg = zmsg_recv (self->control); char *command = zmsg_pop (msg); if (strcmp (command, "CONNECT") == 0) { char *endpoint = zmsg_pop (msg); printf ("I: connecting to %s...\n", endpoint); int rc = zmq_connect (self->router, endpoint); assert (rc == 0); server_t *server = server_new (endpoint); zhash_insert (self->servers, endpoint, server); zhash_freefn (self->servers, endpoint, s_server_free); zlist_append (self->actives, server); server->ping_at = s_clock () + PING_INTERVAL; server->expires = s_clock () + SERVER_TTL; free (endpoint); } else if (strcmp (command, "REQUEST") == 0) { assert (!self->request); // Strict request-reply cycle // Prefix request with sequence number and empty envelope char sequence_text [10]; sprintf (sequence_text, "%u", ++self->sequence); zmsg_push (msg, sequence_text); // Take ownership of request message self->request = msg; msg = NULL; // Request expires after global timeout self->expires = s_clock () + GLOBAL_TIMEOUT; } free (command); zmsg_destroy (&msg); }
int main(){ void* context = zmq_init(1); void* receiver = zmq_socket(context, ZMQ_PULL); zmq_bind(receiver, "tcp://*:5558"); //wait for start of batch char *string = s_recv(receiver); free(string); //start clock int64_t start_time = s_clock(); //process 100 int tasks_nbr; for( tasks_nbr = 0; tasks_nbr < 100; tasks_nbr++){ char* string = s_recv(receiver); if((tasks_nbr / 10)*10 == tasks_nbr){ printf(":"); } else{ printf("."); } fflush(stdout); } printf("Total elapsed time: %d msec\n", (int)(s_clock() - start_time)); zmq_close(receiver); zmq_term(context); return 0; }
static void * flcliapi_task (void *context) { agent_t *self = agent_new (context, "inproc://flcliapi"); zmq_pollitem_t items [] = { { self->control, 0, ZMQ_POLLIN, 0 }, { self->router, 0, ZMQ_POLLIN, 0 } }; while (!s_interrupted) { // Calculate tickless timer, up to 1 hour uint64_t tickless = s_clock () + 1000 * 3600; if (self->request && tickless > self->expires) tickless = self->expires; zhash_apply (self->servers, server_tickless, &tickless); int rc = zmq_poll (items, 2, (tickless - s_clock ()) * 1000); if (rc == -1 && errno == ETERM) break; // Context has been shut down if (items [0].revents & ZMQ_POLLIN) agent_control_message (self); if (items [1].revents & ZMQ_POLLIN) agent_router_message (self); // If we're processing a request, dispatch to next server if (self->request) { if (s_clock () >= self->expires) { // Request expired, kill it zmsg_t *reply = zmsg_new ("FAILED"); zmsg_send (&reply, self->control); zmsg_destroy (&self->request); } else { // Find server to talk to, remove any expired ones while (zlist_size (self->actives)) { server_t *server = (server_t *) zlist_first (self->actives); if (s_clock () >= server->expires) { zlist_pop (self->actives); server->alive = 0; } else { zmsg_t *request = zmsg_dup (self->request); zmsg_push (request, server->endpoint); zmsg_send (&request, self->router); break; } } } } // Disconnect and delete any expired servers // Send heartbeats to idle servers if needed zhash_apply (self->servers, server_ping, self->router); } agent_destroy (&self); return NULL; }
int main (int argc, char *argv []) { int verbose = (argc > 1 && streq (argv [1], "-v")); s_version_assert (2, 1); s_catch_signals (); broker_t *self = s_broker_new (verbose); s_broker_bind (self, "tcp://*:5555"); // Get and process messages forever or until interrupted while (!s_interrupted) { zmq_pollitem_t items [] = { { self->socket, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, HEARTBEAT_INTERVAL * 1000); // Process next input message, if any if (items [0].revents & ZMQ_POLLIN) { zmsg_t *msg = zmsg_recv (self->socket); if (self->verbose) { s_console ("I: received message:"); zmsg_dump (msg); } char *sender = zmsg_pop (msg); char *empty = zmsg_pop (msg); char *header = zmsg_pop (msg); if (streq (header, MDPC_CLIENT)) s_client_process (self, sender, msg); else if (streq (header, MDPW_WORKER)) s_worker_process (self, sender, msg); else { s_console ("E: invalid message:"); zmsg_dump (msg); zmsg_destroy (&msg); } free (sender); free (empty); free (header); } // Disconnect and delete any expired workers // Send heartbeats to idle workers if needed if (s_clock () > self->heartbeat_at) { s_broker_purge_workers (self); worker_t *worker = zlist_first (self->waiting); while (worker) { s_worker_send (self, worker, MDPW_HEARTBEAT, NULL, NULL); worker = zlist_next (self->waiting); } self->heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; } } if (s_interrupted) printf ("W: interrupt received, shutting down...\n"); s_broker_destroy (&self); return 0; }
zmsg_t * mdwrk_recv (mdwrk_t *self, zmsg_t *reply) { // Format and send the reply if we were provided one assert (reply || !self->expect_reply); if (reply) { zmsg_t *msg = zmsg_dup (reply); zmsg_push (msg, MDPS_REPLY); zmsg_push (msg, MDPS_HEADER); zmsg_send (&msg, self->worker); } self->expect_reply = 1; while (1) { zmq_pollitem_t items [] = { { self->worker, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, HEARTBEAT_INTERVAL * 1000); if (items [0].revents & ZMQ_POLLIN) { zmsg_t *msg = zmsg_recv (self->worker); self->liveness = HEARTBEAT_LIVENESS; // Don't try to handle errors, just assert noisily assert (zmsg_parts (msg) >= 3); char *header = zmsg_pop (msg); assert (strcmp (header, MDPS_HEADER) == 0); free (header); char *command = zmsg_pop (msg); if (strcmp (command, MDPS_REQUEST) == 0) return msg; // We have a request to process else if (strcmp (command, MDPS_HEARTBEAT) == 0) ; // Do nothing for heartbeats else if (strcmp (command, MDPS_DISCONNECT) == 0) break; // Return empty handed else { printf ("E: invalid input message (%d)\n", (int) command [1]); zmsg_dump (msg); } free (command); } else if (--self->liveness == 0) { s_sleep (RECONNECT_INTERVAL); s_connect_to_broker (self); } // Send HEARTBEAT if it's time if (s_clock () > self->heartbeat_at) { self->heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; s_send (self->worker, "HEARTBEAT"); } } // We exit if we've been disconnected return NULL; }
server_t * server_new (char *endpoint) { server_t *self = (server_t *) malloc (sizeof (server_t)); self->endpoint = strdup (endpoint); self->alive = 0; self->ping_at = s_clock () + PING_INTERVAL; self->expires = s_clock () + SERVER_TTL; return self; }
int server_ping (char *key, void *server, void *socket) { server_t *self = (server_t *) server; if (s_clock () >= self->ping_at) { zmsg_t *ping = zmsg_new ("PING"); zmsg_push (ping, self->endpoint); zmsg_send (&ping, socket); self->ping_at = s_clock () + PING_INTERVAL; } return 0; }
int main(void) { //Create ZMQ Socket void *context = zmq_ctx_new(); //Socket to receive messages void *receiver = zmq_socket(context, ZMQ_PULL); zmq_bind(receiver, "tcp://*:5558"); //Socket to control workers void *controller = zmq_socket(context, ZMQ_PUB); zmq_bind(controller, "tcp://*:5559"); //Waiting for start char *string = s_recv(receiver); free(string); //Start clock int64_t start_time = s_clock(); //Process messages int task_nbr; for(task_nbr = 0; task_nbr < 100; task_nbr++) { char *string = s_recv(receiver); free(string); if((task_nbr / 10) * 10 == task_nbr) { printf(":"); } else { printf("."); } fflush(stdout); } printf("Total elapsed time: %d msec\n", (int)(s_clock()-start_time)); //Send Kille signal s_send(controller, "KILL"); zmq_close(receiver); zmq_close(controller); zmq_ctx_destroy(context); return 0; }
broker (int verbose) { // Initialize broker state m_context = new zmq::context_t(1); m_socket = new zmq::socket_t(*m_context, ZMQ_ROUTER); m_verbose = verbose; m_heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; }
// Get and process messages forever or until interrupted void start_brokering() { while (!s_interrupted) { zmq::pollitem_t items [] = { { *m_socket, 0, ZMQ_POLLIN, 0 } }; zmq::poll (items, 1, HEARTBEAT_INTERVAL); // Process next input message, if any if (items [0].revents & ZMQ_POLLIN) { zmsg *msg = new zmsg(*m_socket); if (m_verbose) { s_console ("I: received message:"); msg->dump (); } std::string sender = std::string((char*)msg->pop_front ().c_str()); msg->pop_front (); //empty message std::string header = std::string((char*)msg->pop_front ().c_str()); // std::cout << "sbrok, sender: "<< sender << std::endl; // std::cout << "sbrok, header: "<< header << std::endl; // std::cout << "msg size: " << msg->parts() << std::endl; // msg->dump(); if (header.compare(MDPC_CLIENT) == 0) { client_process (sender, msg); } else if (header.compare(MDPW_WORKER) == 0) { worker_process (sender, msg); } else { s_console ("E: invalid message:"); msg->dump (); delete msg; } } // Disconnect and delete any expired workers // Send heartbeats to idle workers if needed if (s_clock () > m_heartbeat_at) { purge_workers (); for (std::vector<worker*>::iterator it = m_waiting.begin(); it != m_waiting.end() && (*it)!=0; it++) { worker_send (*it, (char*)MDPW_HEARTBEAT, "", NULL); } m_heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; } } }
void worker_process (std::string sender, zmsg *msg) { assert (msg && msg->parts() >= 1); // At least, command std::string command = (char *)msg->pop_front().c_str(); bool worker_ready = m_workers.count(sender)>0; worker *wrk = worker_require (sender); if (command.compare (MDPW_READY) == 0) { if (worker_ready) { // Not first command in session worker_delete (wrk, 1); } else { if (sender.size() >= 4 // Reserved service name && sender.find_first_of("mmi.") == 0) { worker_delete (wrk, 1); } else { // Attach worker to service and mark as idle std::string service_name = (char*)msg->pop_front ().c_str(); wrk->m_service = service_require (service_name); wrk->m_service->m_workers++; worker_waiting (wrk); } } } else { if (command.compare (MDPW_REPLY) == 0) { if (worker_ready) { // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. std::string client = msg->unwrap (); msg->wrap (MDPC_CLIENT, wrk->m_service->m_name.c_str()); msg->wrap (client.c_str(), ""); msg->send (*m_socket); worker_waiting (wrk); } else { worker_delete (wrk, 1); } } else { if (command.compare (MDPW_HEARTBEAT) == 0) { if (worker_ready) { wrk->m_expiry = s_clock () + HEARTBEAT_EXPIRY; } else { worker_delete (wrk, 1); } } else { if (command.compare (MDPW_DISCONNECT) == 0) { worker_delete (wrk, 0); } else { s_console ("E: invalid input message (%d)", (int) *command.c_str()); msg->dump (); } } } } delete msg; }
static void s_worker_process (broker_t *self, char *sender, zmsg_t *msg) { assert (zmsg_parts (msg) >= 1); // At least, command char *command = zmsg_pop (msg); int worker_ready = (zhash_lookup (self->workers, sender) != NULL); worker_t *worker = s_worker_require (self, sender); if (streq (command, MDPW_READY)) { if (worker_ready) // Not first command in session s_worker_delete (self, worker, 1); else if (strlen (sender) >= 4 // Reserved service name && memcmp (sender, "mmi.", 4) == 0) s_worker_delete (self, worker, 1); else { // Attach worker to service and mark as idle char *service_name = zmsg_pop (msg); worker->service = s_service_require (self, service_name); worker->service->workers++; s_worker_waiting (self, worker); free (service_name); } } else if (streq (command, MDPW_REPLY)) { if (worker_ready) { // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. char *client = zmsg_unwrap (msg); zmsg_wrap (msg, MDPC_CLIENT, worker->service->name); zmsg_wrap (msg, client, ""); free (client); zmsg_send (&msg, self->socket); s_worker_waiting (self, worker); } else s_worker_delete (self, worker, 1); } else if (streq (command, MDPW_HEARTBEAT)) { if (worker_ready) worker->expiry = s_clock () + HEARTBEAT_EXPIRY; else s_worker_delete (self, worker, 1); } else if (streq (command, MDPW_DISCONNECT)) s_worker_delete (self, worker, 0); else { s_console ("E: invalid input message (%d)", (int) *command); zmsg_dump (msg); } free (command); zmsg_destroy (&msg); }
static void s_worker_waiting (broker_t *self, worker_t *worker) { // Queue to broker and service waiting lists zlist_append (self->waiting, worker); zlist_append (worker->service->waiting, worker); worker->expiry = s_clock () + HEARTBEAT_EXPIRY; s_service_dispatch (self, worker->service, NULL); }
// .split main task // While this example runs in a single process, that is just to make // it easier to start and stop the example. Each thread has its own // context and conceptually acts as a separate process. int main() { zmq::context_t context(1); zmq::socket_t broker(context, ZMQ_ROUTER); broker.bind("tcp://*:5671"); srandom((unsigned)time(NULL)); const int NBR_WORKERS = 10; pthread_t workers[NBR_WORKERS]; for (int worker_nbr = 0; worker_nbr < NBR_WORKERS; ++worker_nbr) { pthread_create(workers + worker_nbr, NULL, worker_task, (void *)(intptr_t)worker_nbr); } // Run for five seconds and then tell workers to end int64_t end_time = s_clock() + 5000; int workers_fired = 0; while (1) { // Next message gives us least recently used worker std::string identity = s_recv(broker); { s_recv(broker); // Envelope delimiter s_recv(broker); // Response from worker } s_sendmore(broker, identity); s_sendmore(broker, ""); // Encourage workers until it's time to fire them if (s_clock() < end_time) s_send(broker, "Work harder"); else { s_send(broker, "Fired!"); if (++workers_fired == NBR_WORKERS) break; } } for (int worker_nbr = 0; worker_nbr < NBR_WORKERS; ++worker_nbr) { pthread_join(workers[worker_nbr], NULL); } return 0; }
// Look for & kill expired workers static void s_queue_purge (std::vector<worker_t> &queue) { int64_t clock = s_clock(); for (std::vector<worker_t>::iterator it = queue.begin(); it < queue.end(); it++) { if (clock > it->expiry) { it = queue.erase(it)-1; } } }
void worker_waiting (worker *worker) { assert (worker); // Queue to broker and service waiting lists m_waiting.push_back(worker); worker->m_service->m_waiting.push_back(worker); worker->m_expiry = s_clock () + HEARTBEAT_EXPIRY; // Attempt to process outstanding requests service_dispatch (worker->m_service, 0); }
int main (void) { // Socket to receive messages on void *context = zmq_ctx_new (); void *receiver = zmq_socket (context, ZMQ_PULL); zmq_bind (receiver, "tcp://*:5558"); // Socket for worker control void *controller = zmq_socket (context, ZMQ_PUB); zmq_bind (controller, "tcp://*:5559"); // Wait for start of batch char *string = s_recv (receiver); free (string); // Start our clock now int64_t start_time = s_clock (); // Process 100 confirmations int task_nbr; for (task_nbr = 0; task_nbr < 100; task_nbr++) { char *string = s_recv (receiver); free (string); if (task_nbr % 10 == 0) printf (":"); else printf ("."); fflush (stdout); } printf ("Total elapsed time: %d msec\n", (int) (s_clock () - start_time)); // Send kill signal to workers s_send (controller, "KILL"); zmq_close (receiver); zmq_close (controller); zmq_ctx_destroy (context); return 0; }
int main(void) { // Prepare our context and socket void *context = zmq_ctx_new(); void *receiver = zmq_socket(context, ZMQ_PULL); zmq_bind(receiver, "tcp://*:5558"); // Wait for start of batch char *string = s_recv(receiver); free(string); printf("start of batch\n"); // Start our clock now int64_t start_time = s_clock(); // Process 100 confirmations int task_nbr; for(task_nbr=0; task_nbr<100; task_nbr++) { char *string = s_recv(receiver); free(string); if(task_nbr % 10 == 0) { printf(":"); } else { printf("."); } fflush(stdout); } // Calculate and report duration of batch printf("\nTotal elapsed time: %d msec\n", (int)(s_clock() - start_time)); zmq_close(receiver); zmq_ctx_destroy(context); return 0; }
zmsg_t * flclient_request (flclient_t *self, zmsg_t **request_p) { assert (self); assert (*request_p); zmsg_t *request = *request_p; // Prefix request with sequence number and empty envelope char sequence_text [10]; sprintf (sequence_text, "%u", ++self->sequence); zmsg_push (request, sequence_text); zmsg_push (request, ""); // Blast the request to all connected servers int server; for (server = 0; server < self->servers; server++) { zmsg_t *msg = zmsg_dup (request); zmsg_send (&msg, self->socket); } // Wait for a matching reply to arrive from anywhere // Since we can poll several times, calculate each one zmsg_t *reply = NULL; uint64_t endtime = s_clock () + GLOBAL_TIMEOUT; while (s_clock () < endtime) { zmq_pollitem_t items [] = { { self->socket, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, (endtime - s_clock ()) * 1000); if (items [0].revents & ZMQ_POLLIN) { reply = zmsg_recv (self->socket); assert (zmsg_parts (reply) == 3); free (zmsg_pop (reply)); if (atoi (zmsg_address (reply)) == self->sequence) break; zmsg_destroy (&reply); } } zmsg_destroy (request_p); return reply; }
static broker_t * s_broker_new (int verbose) { broker_t *self = (broker_t *) calloc (1, sizeof (broker_t)); // Initialize broker state self->context = zmq_init (1); self->socket = zmq_socket (self->context, ZMQ_XREP); self->verbose = verbose; self->services = zhash_new (); self->workers = zhash_new (); self->waiting = zlist_new (); self->heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; return self; }
// Reset worker expiry, worker must be present static void s_worker_refresh (std::vector<worker_t> &queue, std::string &identity) { bool found = false; for (std::vector<worker_t>::iterator it = queue.begin(); it < queue.end(); it++) { if (it->identity.compare(identity) == 0) { it->expiry = s_clock () + HEARTBEAT_INTERVAL * HEARTBEAT_LIVENESS; found = true; break; } } if (!found) { std::cout << "E: worker " << identity << " not ready" << std::endl; } }
// Insert worker at end of queue, reset expiry // Worker must not already be in queue static void s_worker_append (std::vector<worker_t> &queue, std::string &identity) { bool found = false; for (std::vector<worker_t>::iterator it = queue.begin(); it < queue.end(); it++) { if (it->identity.compare(identity) == 0) { std::cout << "E: duplicate worker identity " << identity.c_str() << std::endl; found = true; break; } } if (!found) { worker_t worker; worker.identity = identity; worker.expiry = s_clock() + HEARTBEAT_INTERVAL * HEARTBEAT_LIVENESS; queue.push_back(worker); } }
int main2 (int argc, char *argv[]) { // Prepare our context and socket zmq::context_t context(1); zmq::socket_t receiver(context,ZMQ_PULL); receiver.bind("tcp://*:5558"); // Wait for start of batch zmq::message_t message; receiver.recv(&message); // Start our clock now //struct timeval tstart; //gettimeofday (&tstart, NULL); int64_t tstart = s_clock(); // Process 100 confirmations int task_nbr; int total_msec = 0; // Total calculated cost in msecs for (task_nbr = 0; task_nbr < 100; task_nbr++) { receiver.recv(&message); if ((task_nbr / 10) * 10 == task_nbr) std::cout << ":" << std::flush; else std::cout << "." << std::flush; } // Calculate and report duration of batch //struct timeval tend, tdiff; //gettimeofday (&tend, NULL); //int64_t tend = s_clock(); //if (tend.tv_usec < tstart.tv_usec) { // tdiff.tv_sec = tend.tv_sec - tstart.tv_sec - 1; // tdiff.tv_usec = 1000000 + tend.tv_usec - tstart.tv_usec; //} //else { // tdiff.tv_sec = tend.tv_sec - tstart.tv_sec; // tdiff.tv_usec = tend.tv_usec - tstart.tv_usec; //} //total_msec = tend - tstart;//stdiff.tv_sec * 1000 + tdiff.tv_usec / 1000; std::cout << "\nTotal elapsed time: " << total_msec << " msec\n" << std::endl; return 0; }
void connect_to_broker () { if (m_worker) { delete m_worker; } m_worker = new zmq::socket_t (*m_context, ZMQ_DEALER); int linger = 0; m_worker->setsockopt (ZMQ_LINGER, &linger, sizeof (linger)); m_worker->connect (m_broker.c_str()); if (m_verbose) s_console ("I: connecting to broker at %s...", m_broker.c_str()); // Register service with broker send_to_broker ((char*)MDPW_READY, m_service, NULL); // If liveness hits zero, queue is considered disconnected m_liveness = HEARTBEAT_LIVENESS; m_heartbeat_at = s_clock () + m_heartbeat; }
void purge_workers () { int64_t now = s_clock(); for (size_t i = 0; i < m_waiting.size();) { worker* wrk = m_waiting[i]; if (wrk->m_expiry > now) { ++i; continue; } if (m_verbose) { s_console ("I: deleting expired worker: %s", wrk->m_identity.c_str()); } worker_delete (wrk, 0); } }
void s_connect_to_broker (mdwrk_t *self) { if (self->worker) zmq_close (self->worker); self->worker = zmq_socket (self->context, ZMQ_XREQ); int linger = 0; zmq_setsockopt (self->worker, ZMQ_LINGER, &linger, sizeof (linger)); zmq_connect (self->worker, self->broker); // Register service with broker zmsg_t *msg = zmsg_new (); zmsg_append (msg, MDPS_HEADER); zmsg_append (msg, MDPS_READY); zmsg_append (msg, self->service); zmsg_send (&msg, self->worker); // If liveness hits zero, queue is considered disconnected self->liveness = HEARTBEAT_LIVENESS; self->heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; }
int main(int argc, char *argv[]) { char ch; char str[STR_BUFFSIZE]; char plom_help_string[] = "PLOM Kalman\n" "usage:\n" "kalman [implementation] [--no_dem_sto] [--no_white_noise] [--no_diff]\n" " [-s, --DT <float>] [--eps_abs <float>] [--eps_rel <float>]\n" " [-g, --freeze_forcing <float>]\n" " [-r, --traj] [-p, --path <path>] [-i, --id <integer>]\n" " [-b, --no_trace] [-e, --no_hat] [--prior] [--transf]\n" " [-q, --quiet] [-P, --pipe]" " [-h, --help]\n" "where implementation is 'sde' (default)\n" "options:\n" "\n" "-q, --quiet no verbosity\n" "-P, --pipe pipe mode (echo theta.json on stdout)\n" "\n" "--no_dem_sto turn off demographic stochasticity (if possible)\n" "--no_white_noise turn off environmental stochasticity (if any)\n" "--no_diff turn off drift (if any)\n" "\n" "-s, --DT Initial integration time step\n" "--eps_abs Absolute error for adaptive step-size contro\n" "--eps_rel Relative error for adaptive step-size contro\n" "-g, --freeze_forcing freeze the metadata to their value at the specified time\n" "\n" "-r, --traj print the trajectories\n" "--prior add log(prior) to the estimated loglik\n" "--transf add log(JacobianDeterminant(transf)) to the estimated loglik. (combined to --prior, gives posterior density in transformed space)\n" "-p, --path path where the outputs will be stored\n" "-b, --no_trace do not write trace_<id>.output file\n" "-h, --no_hat do not write hat_<general_id>.output file\n" "-d, --no_pred_res do not write pred_res_<general_id>.output file (prediction residuals)\n" "-i, --id general id (unique integer identifier that will be appended to the output files)\n" "-l, --LIKE_MIN particles with likelihood smaller that LIKE_MIN are considered lost\n" "-o, --nb_obs number of observations to be fitted (for tempering)" "-h, --help print the usage on stdout\n"; // general options GENERAL_ID =0; snprintf(SFR_PATH, STR_BUFFSIZE, "%s", DEFAULT_PATH); LIKE_MIN = 1e-17; LOG_LIKE_MIN = log(LIKE_MIN); enum plom_print print_opt = PLOM_PRINT_BEST | PLOM_PRINT_HAT | PLOM_PRINT_PRED_RES; // options OPTION_PRIOR = 0; OPTION_TRANSF = 0; int nb_obs = -1; double freeze_forcing = -1.0; double dt = 0.0, eps_abs = PLOM_EPS_ABS, eps_rel = PLOM_EPS_REL; J = 1; //not an option, needed for print_X enum plom_implementations implementation; enum plom_noises_off noises_off = 0; static struct option long_options[] = { {"traj", no_argument, 0, 'r'}, {"no_dem_sto", no_argument, 0, 'x'}, {"no_white_noise", no_argument, 0, 'y'}, {"no_diff", no_argument, 0, 'z'}, {"DT", required_argument, 0, 's'}, {"eps_abs", required_argument, 0, 'v'}, {"eps_rel", required_argument, 0, 'w'}, {"freeze_forcing", required_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"path", required_argument, 0, 'p'}, {"id", required_argument, 0, 'i'}, {"no_trace", no_argument, 0, 'b'}, {"no_hat", no_argument, 0, 'e'}, {"no_pred_res",no_argument, 0, 'd'}, {"prior", no_argument, &OPTION_PRIOR, 1}, {"transf", no_argument, &OPTION_TRANSF, 1}, {"nb_obs", required_argument, 0, 'o'}, {"quiet", no_argument, 0, 'q'}, {"pipe", no_argument, 0, 'P'}, {"LIKE_MIN", required_argument, 0, 'l'}, {0, 0, 0, 0} }; int option_index = 0; while ((ch = getopt_long (argc, argv, "qPxyzs:v:w:i:l:p:rbhedo:g:", long_options, &option_index)) != -1) { switch (ch) { case 0: break; case 'x': noises_off = noises_off | PLOM_NO_DEM_STO; break; case 'y': noises_off = noises_off | PLOM_NO_ENV_STO; break; case 'z': noises_off = noises_off | PLOM_NO_DRIFT; break; case 'o': nb_obs = atoi(optarg); break; case 'g': freeze_forcing = atof(optarg); break; case 's': dt = atof(optarg); break; case 'v': eps_abs = atof(optarg); break; case 'w': eps_rel = atof(optarg); break; case 'h': print_log(plom_help_string); return 1; case 'p': snprintf(SFR_PATH, STR_BUFFSIZE, "%s", optarg); break; case 'i': GENERAL_ID = atoi(optarg); break; case 'l': LIKE_MIN = atof(optarg); LOG_LIKE_MIN = log(LIKE_MIN); break; case 'r': print_opt |= PLOM_PRINT_X; break; case 'b': print_opt &= ~PLOM_PRINT_BEST; break; case 'e': print_opt &= ~PLOM_PRINT_HAT; break; case 'd': print_opt &= ~PLOM_PRINT_PRED_RES; break; case 'q': print_opt |= PLOM_QUIET; break; case 'P': print_opt |= PLOM_PIPE | PLOM_QUIET; break; case '?': /* getopt_long already printed an error message. */ return 1; default: snprintf(str, STR_BUFFSIZE, "Unknown option '-%c'\n", optopt); print_err(str); return 1; } } argc -= optind; argv += optind; if(argc == 0) { implementation = PLOM_ODE; //with Kalman the SDE uses f_pred of PLOM_ODE (OK will do better)... } else { if (!strcmp(argv[0], "sde")) { implementation = PLOM_ODE; } else { print_log(plom_help_string); return 1; } } plom_unlink_done(SFR_PATH, GENERAL_ID); json_t *settings = load_settings(PATH_SETTINGS); if (!(print_opt & PLOM_QUIET)) { snprintf(str, STR_BUFFSIZE, "Starting plom-Kalman with the following options: i = %d, LIKE_MIN = %g", GENERAL_ID, LIKE_MIN); print_log(str); } json_t *theta = load_json(); struct s_kalman *p_kalman = build_kalman(theta, settings, implementation, noises_off, OPTION_PRIOR, dt, eps_abs, eps_rel, freeze_forcing, nb_obs); json_decref(settings); int64_t time_begin, time_end; if (!(print_opt & PLOM_QUIET)) { time_begin = s_clock(); } back_transform_theta2par(p_kalman->p_par, p_kalman->p_best->mean, p_kalman->p_data->p_it_all, p_kalman->p_data); linearize_and_repeat(p_kalman->p_X, p_kalman->p_par, p_kalman->p_data, p_kalman->p_data->p_it_par_sv); prop2Xpop_size(p_kalman->p_X, p_kalman->p_data, p_kalman->calc[0]); theta_driftIC2Xdrift(p_kalman->p_X, p_kalman->p_best->mean, p_kalman->p_data); FILE *p_file_X = (print_opt & PLOM_PRINT_X) ? plom_fopen(SFR_PATH, GENERAL_ID, "X", "w", header_X, p_kalman->p_data): NULL; FILE *p_file_hat = (print_opt & PLOM_PRINT_HAT) ? plom_fopen(SFR_PATH, GENERAL_ID, "hat", "w", header_hat, p_kalman->p_data): NULL; FILE *p_file_pred_res = (print_opt & PLOM_PRINT_PRED_RES) ? plom_fopen(SFR_PATH, GENERAL_ID, "pred_res", "w", header_prediction_residuals_ekf, p_kalman->p_data): NULL; double log_like = run_kalman(p_kalman->p_X, p_kalman->p_best, p_kalman->p_par, p_kalman->p_kalman_update, p_kalman->p_data, p_kalman->calc, f_prediction_ode, 0, p_file_X, p_file_hat, p_file_pred_res, print_opt); if (print_opt & PLOM_PRINT_X) { plom_fclose(p_file_X); } if (print_opt & PLOM_PRINT_HAT) { plom_fclose(p_file_hat); } if (print_opt & PLOM_PRINT_PRED_RES) { plom_fclose(p_file_pred_res); } if (!(print_opt & PLOM_QUIET)) { time_end = s_clock(); struct s_duration t_exec = time_exec(time_begin, time_end); sprintf(str, "logV: %g", log_like); print_log(str); sprintf(str, "Done in:= %dd %dh %dm %gs", t_exec.d, t_exec.h, t_exec.m, t_exec.s); print_log(str); } if (print_opt & PLOM_PRINT_BEST) { FILE *p_file_trace = plom_fopen(SFR_PATH, GENERAL_ID, "trace", "w", header_trace, p_kalman->p_data); print_trace(p_file_trace, 0, p_kalman->p_best, p_kalman->p_data, log_like); plom_fclose(p_file_trace); } plom_print_done(theta, p_kalman->p_data, p_kalman->p_best, SFR_PATH, GENERAL_ID, print_opt); if (!(print_opt & PLOM_QUIET)) { print_log("clean up..."); } json_decref(theta); clean_kalman(p_kalman); return 0; }
int main (void) { s_version_assert (2, 1); srandom ((unsigned) time (NULL)); void *context = zmq_init (1); void *worker = s_worker_socket (context); // If liveness hits zero, queue is considered disconnected size_t liveness = HEARTBEAT_LIVENESS; size_t interval = INTERVAL_INIT; // Send out heartbeats at regular intervals uint64_t heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; int cycles = 0; while (1) { zmq_pollitem_t items [] = { { worker, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, HEARTBEAT_INTERVAL * 1000); if (items [0].revents & ZMQ_POLLIN) { // Get message // - 3-part envelope + content -> request // - 1-part "HEARTBEAT" -> heartbeat zmsg_t *msg = zmsg_recv (worker); if (msg_parts (msg) == 3) { // Simulate various problems, after a few cycles cycles++; if (cycles > 3 && randof (5) == 0) { printf ("I: (%s) simulating a crash\n", identity); zmsg_destroy (&msg); break; } else if (cycles > 3 && randof (5) == 0) { printf ("I: (%s) simulating CPU overload\n", identity); sleep (5); } printf ("I: (%s) normal reply - %s\n", identity, zmsg_body (msg)); zmsg_send (&msg, worker); liveness = HEARTBEAT_LIVENESS; sleep (1); // Do some heavy work } else if (msg_parts (msg) == 1 && strcmp (msg_body (msg), "HEARTBEAT") == 0) liveness = HEARTBEAT_LIVENESS; else { printf ("E: (%s) invalid message\n", identity); zmsg_dump (msg); } interval = INTERVAL_INIT; } else if (--liveness == 0) { printf ("W: (%s) heartbeat failure, can't reach queue\n", identity); printf ("W: (%s) reconnecting in %zd msec...\n", identity, interval); s_sleep (interval); if (interval < INTERVAL_MAX) interval *= 2; zmq_close (worker); worker = s_worker_socket (context); liveness = HEARTBEAT_LIVENESS; } // Send heartbeat to queue if it's time if (s_clock () > heartbeat_at) { heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; printf ("I: (%s) worker heartbeat\n", identity); s_send (worker, "HEARTBEAT"); } } zmq_close (worker); zmq_term (context); return 0; }