void test_nsrc (flux_t *h, uint32_t nodeid) { flux_future_t *f; const int count = 10000; json_object *in = Jnew (); const char *json_str; json_object *out = NULL; int i, seq; Jadd_int (in, "count", count); if (!(f = flux_rpc (h, "req.nsrc", Jtostr (in), FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); for (i = 0; i < count; i++) { flux_msg_t *msg = flux_recv (h, FLUX_MATCH_ANY, 0); if (!msg) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode %d", __FUNCTION__, i); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_int (out, "seq", &seq)) log_msg_exit ("%s: decode %d payload", __FUNCTION__, i); if (seq != i) log_msg_exit ("%s: decode %d - seq mismatch %d", __FUNCTION__, i, seq); Jput (out); flux_msg_destroy (msg); } Jput (in); }
static void exit_event_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; barrier_t *b; const char *json_str; json_object *o = NULL; const char *name; int errnum; if (flux_event_decode (msg, NULL, &json_str) < 0) { flux_log_error (h, "%s: decoding event", __FUNCTION__); goto done; } if (!(o = Jfromstr (json_str)) || !Jget_str (o, "name", &name) || !Jget_int (o, "errnum", &errnum)) { errno = EPROTO; flux_log_error (h, "%s: decoding event", __FUNCTION__); goto done; } if ((b = zhash_lookup (ctx->barriers, name))) { b->errnum = errnum; zhash_foreach (b->clients, send_enter_response, b); zhash_delete (ctx->barriers, name); } done: Jput (o); }
/* Return 'n' sequenced responses. */ static int nsrc_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { JSON o = Jnew (); int i, count; if (flux_json_request_decode (*zmsg, &o) < 0) { if (flux_err_respond (h, errno, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } if (!Jget_int (o, "count", &count)) { if (flux_err_respond (h, EPROTO, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } for (i = 0; i < count; i++) { zmsg_t *cpy = zmsg_dup (*zmsg); if (!cpy) oom (); Jadd_int (o, "seq", i); if (flux_json_respond (h, o, &cpy) < 0) flux_log (h, LOG_ERR, "%s: flux_json_respond: %s", __FUNCTION__, strerror (errno)); zmsg_destroy (&cpy); } zmsg_destroy (zmsg); done: Jput (o); return 0; }
/* Return 'n' sequenced responses. */ void nsrc_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { const char *json_str; int saved_errno; JSON o = Jnew (); int i, count; int rc = -1; if (flux_request_decode (msg, NULL, &json_str) < 0) { saved_errno = errno; goto done; } if (!(o = Jfromstr (json_str)) || !Jget_int (o, "count", &count)) { saved_errno = errno = EPROTO; goto done; } for (i = 0; i < count; i++) { Jadd_int (o, "seq", i); if (flux_respond (h, msg, 0, Jtostr (o)) < 0) { saved_errno = errno; flux_log_error (h, "%s: flux_respond", __FUNCTION__); goto done; } } rc = 0; done: if (rc < 0) { if (flux_respond (h, msg, saved_errno, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); } Jput (o); }
/* Handle responses */ void ping_continuation (flux_rpc_t *rpc, void *arg) { struct ping_ctx *ctx = arg; const char *json_str, *route, *pad; int64_t sec, nsec; struct timespec t0; int seq; json_object *out = NULL; struct ping_data *pdata = flux_rpc_aux_get (rpc); tstat_t *tstat = pdata->tstat; if (flux_rpc_get (rpc, &json_str) < 0) { log_err ("flux_rpc_get"); goto done; } if (!(out = Jfromstr (json_str)) || !Jget_int (out, "seq", &seq) || !Jget_int64 (out, "time.tv_sec", &sec) || !Jget_int64 (out, "time.tv_nsec", &nsec) || !Jget_str (out, "pad", &pad) || !Jget_str (out, "route", &route) || strcmp (ctx->pad, pad) != 0) { log_err ("error decoding ping response"); goto done; } t0.tv_sec = sec; t0.tv_nsec = nsec; tstat_push (tstat, monotime_since (t0)); pdata->seq = seq; if (pdata->route) free (pdata->route); pdata->route = xstrdup (route); pdata->rpc_count++; done: if (flux_rpc_next (rpc) < 0 && pdata->rpc_count) { if (ctx->rank != NULL) { printf ("%s!%s pad=%lu seq=%d time=(%0.3f:%0.3f:%0.3f) ms stddev %0.3f\n", ctx->rank, ctx->topic, strlen (ctx->pad), pdata->seq, tstat_min (tstat), tstat_mean (tstat), tstat_max (tstat), tstat_stddev (tstat)); } else { char s[16]; snprintf (s, sizeof (s), "%u", ctx->nodeid); printf ("%s%s%s pad=%lu seq=%d time=%0.3f ms (%s)\n", ctx->nodeid == FLUX_NODEID_ANY ? "" : s, ctx->nodeid == FLUX_NODEID_ANY ? "" : "!", ctx->topic, strlen (ctx->pad), pdata->seq, tstat_mean (tstat), pdata->route); } flux_rpc_destroy (rpc); } Jput (out); }
/* This test is to make sure that deferred responses are handled in order. * Arrange for module to source 10K sequenced responses. Messages 5000-5499 * are "put back" on the handle using flux_putmsg(). We ensure that * the 10K messages are nonetheless received in order. */ void test_putmsg (flux_t *h, uint32_t nodeid) { flux_future_t *f; const char *json_str; const int count = 10000; const int defer_start = 5000; const int defer_count = 500; json_object *in = Jnew (); json_object *out = NULL; int seq, myseq = 0; zlist_t *defer = zlist_new (); bool popped = false; flux_msg_t *z; if (!defer) oom (); Jadd_int (in, "count", count); if (!(f = flux_rpc (h, "req.nsrc", Jtostr (in), FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); do { flux_msg_t *msg = flux_recv (h, FLUX_MATCH_ANY, 0); if (!msg) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode", __FUNCTION__); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_int (out, "seq", &seq)) log_msg_exit ("%s: decode - payload", __FUNCTION__); Jput (out); if (seq >= defer_start && seq < defer_start + defer_count && !popped) { if (zlist_append (defer, msg) < 0) oom (); if (seq == defer_start + defer_count - 1) { while ((z = zlist_pop (defer))) { if (flux_requeue (h, z, FLUX_RQ_TAIL) < 0) log_err_exit ("%s: flux_requeue", __FUNCTION__); flux_msg_destroy (z); } popped = true; } continue; } if (seq != myseq) log_msg_exit ("%s: expected %d got %d", __FUNCTION__, myseq, seq); myseq++; flux_msg_destroy (msg); } while (myseq < count); zlist_destroy (&defer); Jput (in); }
/* Proxy ping. */ void xping_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; const char *json_str; int saved_errno; int rank, seq = ctx->ping_seq++; const char *service; char *hashkey = NULL; JSON in = Jnew (); JSON o = NULL; flux_msg_t *cpy; if (flux_request_decode (msg, NULL, &json_str) < 0) { saved_errno = errno; goto error; } if (!(o = Jfromstr (json_str)) || !Jget_int (o, "rank", &rank) || !Jget_str (o, "service", &service)) { saved_errno = errno = EPROTO; goto error; } flux_log (h, LOG_DEBUG, "Rxping rank=%d service=%s", rank, service); Jadd_int (in, "seq", seq); flux_log (h, LOG_DEBUG, "Tping seq=%d %d!%s", seq, rank, service); flux_rpc_t *rpc; if (!(rpc = flux_rpc (h, service, Jtostr (in), rank, FLUX_RPC_NORESPONSE))) { saved_errno = errno; goto error; } flux_rpc_destroy (rpc); if (!(cpy = flux_msg_copy (msg, true))) { saved_errno = errno; goto error; } hashkey = xasprintf ("%d", seq); zhash_update (ctx->ping_requests, hashkey, cpy); zhash_freefn (ctx->ping_requests, hashkey, (zhash_free_fn *)flux_msg_destroy); Jput (o); Jput (in); if (hashkey) free (hashkey); return; error: if (flux_respond (h, msg, saved_errno, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); Jput (o); Jput (in); }
void get_rank (flux_rpc_t *rpc) { const char *json_str; JSON o; int rank; if (flux_rpc_get (rpc, NULL, &json_str) < 0) err_exit ("flux_rpc_get"); if (!(o = Jfromstr (json_str)) || !Jget_int (o, "rank", &rank)) msg_exit ("response protocol error"); printf ("rank is %d\n", rank); Jput (o); }
int shutdown_decode (const flux_msg_t *msg, double *grace, int *exitcode, int *rank, char *reason, int reason_len) { const char *json_str, *s; JSON in = NULL; int rc = -1; if (flux_event_decode (msg, NULL, &json_str) < 0 || !(in = Jfromstr (json_str)) || !Jget_str (in, "reason", &s) || !Jget_double (in, "grace", grace) || !Jget_int (in, "rank", rank) || !Jget_int (in, "exitcode", exitcode)) { errno = EPROTO; goto done; } snprintf (reason, reason_len, "%s", s); rc = 0; done: Jput (in); return rc; }
int kp_rgetroot_dec (JSON o, int *rootseq, const char **rootdir) { int rc = -1; if (!rootseq || !rootdir) { errno = EINVAL; goto done; } if (!Jget_int (o, "rootseq", rootseq) || !Jget_str (o, "rootdir", rootdir)){ errno = EPROTO; goto done; } rc = 0; done: return rc; }
int hello_decode (const flux_msg_t *msg, int *rank) { const char *json_str, *topic_str; JSON in = NULL; int rc = -1; if (flux_request_decode (msg, &topic_str, &json_str) < 0) goto done; if (!(in = Jfromstr (json_str)) || !Jget_int (in, "rank", rank) || strcmp (topic_str, "cmb.hello") != 0) { errno = EPROTO; goto done; } rc = 0; done: Jput (in); return rc; }
void test_src (flux_t *h, uint32_t nodeid) { flux_future_t *f; const char *json_str; json_object *out = NULL; int i; if (!(f = flux_rpc (h, "req.src", NULL, nodeid, 0)) || flux_rpc_get (f, &json_str) < 0) log_err_exit ("%s", __FUNCTION__); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_int (out, "wormz", &i) || i != 42) log_msg_exit ("%s: didn't get expected payload", __FUNCTION__); Jput (out); flux_future_destroy (f); }
int flux_heartbeat_decode (const flux_msg_t *msg, int *epoch) { const char *json_str, *topic_str; JSON out = NULL; int rc = -1; if (flux_event_decode (msg, &topic_str, &json_str) < 0) goto done; if (strcmp (topic_str, "hb") != 0 || !(out = Jfromstr (json_str)) || !Jget_int (out, "epoch", epoch)) { errno = EPROTO; goto done; } rc = 0; done: Jput (out); return rc; }
/* Handle ping response for proxy ping. */ static int ping_response_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { ctx_t *ctx = arg; JSON o = NULL; JSON out = Jnew ();; int seq; const char *route; zmsg_t *zreq = NULL; char *hashkey = NULL; if (flux_json_response_decode (*zmsg, &o) < 0) { flux_log (h, LOG_ERR, "%s: flux_json_response_decode: %s", __FUNCTION__, strerror (errno)); goto done; } if (!Jget_int (o, "seq", &seq) || !Jget_str (o, "route", &route)) { flux_log (h, LOG_ERR, "%s: protocol error", __FUNCTION__); goto done; } flux_log (h, LOG_DEBUG, "Rping seq=%d %s", seq, route); hashkey = xasprintf ("%d", seq); if (!(zreq = zhash_lookup (ctx->ping_requests, hashkey))) { flux_log (h, LOG_ERR, "%s: unsolicited ping response: %s", __FUNCTION__, hashkey); goto done; } zhash_delete (ctx->ping_requests, hashkey); flux_log (h, LOG_DEBUG, "Txping seq=%d %s", seq, route); Jadd_str (out, "route", route); if (flux_json_respond (h, out, &zreq) < 0) { flux_log (h, LOG_ERR, "%s: flux_json_respond: %s", __FUNCTION__, strerror (errno)); goto done; } done: if (hashkey) free (hashkey); Jput (o); Jput (out); //zmsg_destroy (zmsg); zmsg_destroy (&zreq); return 0; }
static int dmesg_rpc_get (flux_rpc_t *rpc, int *seq, flux_log_f fun, void *arg) { const char *json_str; const char *buf; JSON o = NULL; int rc = -1; if (flux_rpc_get (rpc, NULL, &json_str) < 0) goto done; if (!(o = Jfromstr (json_str)) || !Jget_str (o, "buf", &buf) || !Jget_int (o, "seq", seq)) { errno = EPROTO; goto done; } fun (buf, strlen (buf), arg); rc = 0; done: Jput (o); return rc; }
/* Proxy ping. */ static int xping_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { ctx_t *ctx = arg; int rank, seq = ctx->ping_seq++; const char *service; char *hashkey = NULL; JSON in = Jnew (); JSON o = NULL; if (flux_json_request_decode (*zmsg, &o) < 0) { if (flux_err_respond (h, errno, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } if (!Jget_int (o, "rank", &rank) || !Jget_str (o, "service", &service)) { if (flux_err_respond (h, EPROTO, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } flux_log (h, LOG_DEBUG, "Rxping rank=%d service=%s", rank, service); Jadd_int (in, "seq", seq); flux_log (h, LOG_DEBUG, "Tping seq=%d %d!%s", seq, rank, service); if (flux_json_request (h, rank, 0, service, in) < 0) { if (flux_err_respond (h, errno, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } hashkey = xasprintf ("%d", seq); zhash_update (ctx->ping_requests, hashkey, *zmsg); *zmsg = NULL; done: Jput (o); Jput (in); if (hashkey) free (hashkey); return 0; }
int get_watch_stats (flux_t *h, int *count) { flux_rpc_t *rpc; const char *json_str; json_object *o = NULL; int rc = -1; if (!(rpc = flux_rpc (h, "kvs.stats.get", NULL, FLUX_NODEID_ANY, 0))) goto done; if (flux_rpc_get (rpc, &json_str) < 0) goto done; if (!(o = Jfromstr (json_str)) || !Jget_int (o, "#watchers", count)) { errno = EPROTO; goto done; } rc = 0; done: flux_rpc_destroy (rpc); Jput (o); return rc; }
int kp_tsetroot_dec (JSON o, int *rootseq, const char **rootdir, JSON *root, const char **fence) { int rc = -1; if (!o || !rootseq || !rootdir || !root || !fence) { errno = EINVAL; goto done; } if (!Jget_int (o, "rootseq", rootseq) || !Jget_str (o, "rootdir", rootdir)){ errno = EPROTO; goto done; } *fence = NULL; (void)Jget_str (o, "fence", fence); *root = NULL; (void)Jget_obj (o, "rootdirval", root); rc = 0; done: return rc; }
/* Handle ping response for proxy ping. * Match it with a request and respond to that request. */ void ping_response_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; const char *json_str; JSON o = NULL; JSON out = Jnew ();; int seq; const char *route; flux_msg_t *req = NULL; char *hashkey = NULL; if (flux_response_decode (msg, NULL, &json_str) < 0) { flux_log_error (h, "%s: flux_response_decode", __FUNCTION__); goto done; } if (!(o = Jfromstr (json_str)) || !Jget_int (o, "seq", &seq) || !Jget_str (o, "route", &route)) { errno = EPROTO; flux_log_error (h, "%s: payload", __FUNCTION__); goto done; } flux_log (h, LOG_DEBUG, "Rping seq=%d %s", seq, route); hashkey = xasprintf ("%d", seq); if (!(req = zhash_lookup (ctx->ping_requests, hashkey))) { flux_log_error (h, "%s: unsolicited ping response", __FUNCTION__); goto done; } flux_log (h, LOG_DEBUG, "Txping seq=%d %s", seq, route); Jadd_str (out, "route", route); if (flux_respond (h, req, 0, Jtostr (out)) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); zhash_delete (ctx->ping_requests, hashkey); done: if (hashkey) free (hashkey); Jput (o); Jput (out); }
void test_put (void) { JSON o; bool dir = false; bool link = false; const char *key = NULL; JSON val = NULL; int i; val = Jnew (); Jadd_int (val, "i", 2); o = kp_tput_enc ("a", val, false, true); ok (o != NULL, "kp_tput_snec works"); val = NULL; ok (kp_tput_dec (o, &key, &val, &dir, &link) == 0 && !dir && link, "kp_tput_dec works"); ok (val && Jget_int (val, "i", &i) && i == 2, "kp_tput_dec returned encoded object"); Jput (o); /* owns val */ }
void test_get (void) { JSON o; bool dir = false; bool link = false; const char *key = NULL; JSON val = NULL; int i; o = kp_tget_enc ("foo", false, true); ok (o != NULL, "kp_tget_enc works"); ok (kp_tget_dec (o, &key, &dir, &link) == 0 && dir == false && link == true, "kp_tget_dec works"); like (key, "^foo$", "kp_tget_dec returned encoded key"); Jput (o); val = Jnew (); Jadd_int (val, "i", 42); o = kp_rget_enc ("foo", val); val = NULL; /* val now owned by o */ ok (o != NULL, "kp_rget_enc works"); ok (kp_rget_dec (o, &val) == 0, "kp_rget_dec works"); ok (val && Jget_int (val, "i", &i) && i == 42, "kp_rget_dec returned encoded object"); Jput (o); /* owns val */ o = kp_rget_enc ("foo", NULL); ok (o != NULL, "kp_rget_enc works with NULL value"); errno = 0; ok (kp_rget_dec (o, &val) < 0 && errno == ENOENT, "kp_rget_dec returns error with errno = ENOENT if val is NULL"); Jput (o); }
int kp_tcommit_dec (JSON o, const char **sender, JSON *ops, const char **fence, int *nprocs) { int rc = -1; if (!sender || !ops || !fence || !nprocs) { errno = EINVAL; goto done; } *ops = NULL; (void)Jget_obj (o, "ops", ops); if (*ops) Jget (*ops); *sender = NULL; (void)Jget_str (o, ".arg_sender", sender); *fence = NULL; (void)Jget_str (o, ".arg_fence", fence); *nprocs = 1; (void)Jget_int (o, ".arg_nprocs", nprocs); rc = 0; done: return rc; }
int main (int argc, char *argv[]) { struct cache *cache; struct cache_entry *e1, *e2; json_object *o1; json_object *o2; wait_t *w; int count, i; plan (NO_PLAN); cache_destroy (NULL); cache_entry_destroy (NULL); diag ("cache_destroy and cache_entry_destroy accept NULL arg"); ok ((cache = cache_create ()) != NULL, "cache_create works"); ok (cache_count_entries (cache) == 0, "cache contains 0 entries"); cache_destroy (cache); /* Play with one entry. * N.B.: json ref is NOT incremented by create or get_json. */ o1 = Jnew (); Jadd_int (o1, "foo", 42); ok ((e1 = cache_entry_create (o1)) != NULL, "cache_entry_create works"); ok (cache_entry_get_valid (e1) == true, "cache entry initially valid"); ok (cache_entry_get_dirty (e1) == false, "cache entry initially not dirty"); cache_entry_set_dirty (e1, true); ok (cache_entry_get_dirty (e1) == true, "cache entry succcessfully set dirty"); ok ((o2 = cache_entry_get_json (e1)) != NULL, "json retrieved from cache entry"); ok (Jget_int (o2, "foo", &i) == true && i == 42, "expected json object found"); cache_entry_destroy (e1); /* destroys o1 */ /* Test cache entry waiters. * N.B. waiter is destroyed when run. */ count = 0; ok ((w = wait_create (wait_cb, &count)) != NULL, "wait_create works"); ok ((e1 = cache_entry_create (NULL)) != NULL, "cache_entry_create created empty object"); ok (cache_entry_get_valid (e1) == false, "cache entry invalid, adding waiter"); o1 = Jnew (); Jadd_int (o1, "foo", 42); cache_entry_wait_valid (e1, w); cache_entry_set_json (e1, o1); ok (cache_entry_get_valid (e1) == true, "cache entry set valid with one waiter"); ok (count == 1, "waiter callback ran"); count = 0; ok ((w = wait_create (wait_cb, &count)) != NULL, "wait_create works"); cache_entry_set_dirty (e1, true); ok (cache_entry_get_dirty (e1) == true, "cache entry set dirty, adding waiter"); cache_entry_wait_notdirty (e1, w); cache_entry_set_dirty (e1, false); ok (cache_entry_get_dirty (e1) == false, "cache entry set not dirty with one waiter"); ok (count == 1, "waiter callback ran"); cache_entry_destroy (e1); /* destroys o1 */ /* Put entry in cache and test lookup, expire */ ok ((cache = cache_create ()) != NULL, "cache_create works"); ok (cache_count_entries (cache) == 0, "cache contains 0 entries"); o1 = Jnew (); Jadd_int (o1, "foo", 42); ok ((e1 = cache_entry_create (o1)) != NULL, "cache_entry_create works"); cache_insert (cache, "xxx1", e1); ok (cache_count_entries (cache) == 1, "cache contains 1 entry after insert"); ok (cache_lookup (cache, "yyy1", 0) == NULL, "cache_lookup of wrong hash fails"); ok ((e2 = cache_lookup (cache, "xxx1", 42)) != NULL, "cache_lookup of correct hash works (last use=42)"); i = 0; ok ((o2 = cache_entry_get_json (e2)) != NULL && Jget_int (o2, "foo", &i) == true && i == 42, "expected json object found"); ok (cache_count_entries (cache) == 1, "cache contains 1 entry"); ok (cache_expire_entries (cache, 43, 1) == 0, "cache_expire_entries now=43 thresh=1 expired 0"); ok (cache_count_entries (cache) == 1, "cache contains 1 entry"); ok (cache_expire_entries (cache, 44, 1) == 1, "cache_expire_entries now=44 thresh=1 expired 1"); ok (cache_count_entries (cache) == 0, "cache contains 0 entries"); cache_destroy (cache); done_testing (); return (0); }
static void enter_request_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; barrier_t *b; json_object *o = NULL; char *sender = NULL; const char *name; int count, nprocs, hopcount; const char *json_str; if (flux_request_decode (msg, NULL, &json_str) < 0 || flux_msg_get_route_first (msg, &sender) < 0) { flux_log_error (ctx->h, "%s: decoding request", __FUNCTION__); goto done; } if (!(o = Jfromstr (json_str)) || !Jget_str (o, "name", &name) || !Jget_int (o, "count", &count) || !Jget_int (o, "nprocs", &nprocs)) { errno = EPROTO; flux_log_error (ctx->h, "%s: decoding request", __FUNCTION__); goto done; } if (!(b = zhash_lookup (ctx->barriers, name))) b = barrier_create (ctx, name, nprocs); /* Distinguish client (tracked) vs downstream barrier plugin (untracked). * A client, distinguished by hopcount > 0, can only enter barrier once. */ if (!Jget_int (o, "hopcount", &hopcount)) { if (barrier_add_client (b, sender, msg) < 0) { flux_respond (ctx->h, msg, EEXIST, NULL); flux_log (ctx->h, LOG_ERR, "abort %s due to double entry by client %s", name, sender); if (exit_event_send (ctx->h, b->name, ECONNABORTED) < 0) flux_log_error (ctx->h, "exit_event_send"); goto done; } } /* If the count has been reached, terminate the barrier; * o/w set timer to pass count upstream and zero it here. */ b->count += count; if (b->count == b->nprocs) { if (exit_event_send (ctx->h, b->name, 0) < 0) flux_log_error (ctx->h, "exit_event_send"); } else if (ctx->rank > 0 && !ctx->timer_armed) { flux_timer_watcher_reset (ctx->timer, barrier_reduction_timeout_sec, 0.); flux_watcher_start (ctx->timer); ctx->timer_armed = true; } done: if (o) json_object_put (o); if (sender) free (sender); }
// Recevied a request to join the simulation ("sim.join") static void join_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { int mod_rank; json_t *request = NULL; const char *mod_name = NULL, *json_str = NULL; double *next_event = (double *)malloc (sizeof (double)); ctx_t *ctx = arg; sim_state_t *sim_state = ctx->sim_state; uint32_t size; if (flux_msg_get_json (msg, &json_str) < 0 || json_str == NULL || !(request = Jfromstr (json_str)) || !Jget_str (request, "mod_name", &mod_name) || !Jget_int (request, "rank", &mod_rank) || !Jget_double (request, "next_event", next_event)) { flux_log (h, LOG_ERR, "%s: bad join message", __FUNCTION__); goto out; } if (flux_get_size (h, &size) < 0) goto out; if (mod_rank < 0 || mod_rank >= size) { flux_log (h, LOG_ERR, "%s: bad rank in join message", __FUNCTION__); goto out; } flux_log (h, LOG_DEBUG, "join rcvd from module %s on rank %d, next event at %f", mod_name, mod_rank, *next_event); zhash_t *timers = sim_state->timers; if (zhash_insert (timers, mod_name, next_event) < 0) { // key already // exists flux_log (h, LOG_ERR, "duplicate join request from %s, module already exists in " "sim_state", mod_name); goto out; } // clear next event so it is not freed below next_event = NULL; // TODO: this is horribly hackish, improve the handshake to avoid // this hardcoded # of modules. maybe use a timeout? ZMQ provides // support for polling etc with timeouts, should try that static int num_modules = 3; num_modules--; if (num_modules <= 0) { if (handle_next_event (ctx) < 0) { flux_log (h, LOG_ERR, "failure while handling next event"); return; } } out: Jput (request); free (next_event); }