/* 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); }
static resrc_graph_req_t *resrc_graph_req_from_json (JSON ga) { JSON go = NULL; /* graph json object */ const char *name = NULL; int i, ngraphs = 0; int64_t ssize; resrc_graph_req_t *resrc_graph_req = NULL; if (Jget_ar_len (ga, &ngraphs)) { resrc_graph_req = xzmalloc ((ngraphs + 1) * sizeof (resrc_graph_req_t)); for (i=0; i < ngraphs; i++) { Jget_ar_obj (ga, i, &go); if (Jget_str (go, "name", &name)) resrc_graph_req[i].name = xstrdup (name); else goto fail; if (Jget_int64 (go, "size", &ssize)) resrc_graph_req[i].size = (size_t) ssize; else goto fail; } /* end of the line */ resrc_graph_req[i].name = NULL; } return resrc_graph_req; fail: free (resrc_graph_req); return NULL; }
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); }
/* Note: return value of this function is ignored by libsubprocess. * Also: zio_json_decode() returns -1 on error, 0 on eof, strlen(s) on * success; caller must free 's'. */ static int subprocess_io_cb (struct subprocess *p, const char *json_str) { runlevel_t *r; json_object *o = NULL; const char *name; int len; bool eof; char *s = NULL, *argz = NULL, *line = NULL; size_t argz_len; r = subprocess_get_context (p, "runlevel_t"); assert (r != NULL); if (!r->io_cb) goto done; if (!(o = Jfromstr (json_str)) || !Jget_str (o, "name", &name)) goto done; len = zio_json_decode (json_str, (void **)&s, &eof); if (len <= 0 || !s || !*s || s[len] != '\0') goto done; if (argz_create_sep (s, '\n', &argz, &argz_len) != 0) goto done; while ((line = argz_next (argz, argz_len, line)) && *line) r->io_cb (r, name, line, r->io_cb_arg); done: if (s) free (s); if (argz) free (argz); Jput (o); return 0; }
static void rdl_update_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { json_t *o = NULL; const char *json_str = NULL, *rdl_str = NULL; ctx_t *ctx = (ctx_t *)arg; if (flux_msg_get_json (msg, &json_str) < 0 || json_str == NULL || !(o = Jfromstr (json_str))) { flux_log (h, LOG_ERR, "%s: bad message", __FUNCTION__); Jput (o); return; } Jget_str (o, "rdl_string", &rdl_str); if (rdl_str) { free (ctx->rdl_string); ctx->rdl_string = strdup (rdl_str); ctx->rdl_changed = true; } Jput (o); }
static int handle_seq_fetch (seqhash_t *s, JSON in, JSON *outp) { const char *name; bool create = false; bool created = false; int64_t v, pre, post, *valp; if (!Jget_str (in, "name", &name) || !Jget_bool (in, "create", &create) || !Jget_int64 (in, "preincrement", &pre) || !Jget_int64 (in, "postincrement", &post)) { errno = EPROTO; return (-1); } if (seq_fetch_and_add (s, name, pre, post, &v) < 0) { if (!create || (errno != ENOENT)) return (-1); /* Create and initialize */ valp = seq_create (s, name); *valp += pre; v = *valp; *valp += post; created = true; } *outp = Jnew (); Jadd_str (*outp, "name", name); Jadd_int64 (*outp, "value", v); if (create && created) Jadd_bool (*outp, "created", true); return (0); }
static int update_jcb_obj (flux_t *h, int64_t jobid, const char *key, json_object *jcb) { int rc = -1; json_object *o = NULL; if (!jcb) return -1; if (jobid_exist (h, jobid) != 0) return -1; if (is_jobid (key)) { flux_log (h, LOG_ERR, "jobid attr cannot be updated"); } else if (is_state_pair (key)) { if (Jget_obj (jcb, JSC_STATE_PAIR, &o)) rc = update_state (h, jobid, o); } else if (is_rdesc (key)) { if (Jget_obj (jcb, JSC_RDESC, &o)) rc = update_rdesc (h, jobid, o); } else if (is_rdl (key)) { const char *s = NULL; if (Jget_str (jcb, JSC_RDL, &s)) rc = update_rdl (h, jobid, s); } else if (is_rdl_alloc (key)) { if (Jget_obj (jcb, JSC_RDL_ALLOC, &o)) rc = update_rdl_alloc (h, jobid, o); } else if (is_pdesc (key)) { if (Jget_obj (jcb, JSC_PDESC, &o)) rc = update_pdesc (h, jobid, o); } else flux_log (h, LOG_ERR, "key (%s) not understood", key); return rc; }
static bool fetch_rank_pdesc (JSON src, int64_t *p, int64_t *n, const char **c) { if (!src) return false; if (!Jget_str (src, "command", c)) return false; if (!Jget_int64 (src, "pid", p)) return false; if (!Jget_int64 (src, "nodeid", n)) return false; return true; }
int kp_rcommit_dec (JSON o, int *rootseq, const char **rootdir, const char **sender) { int rc = -1; if (!rootseq || !rootdir || !sender) { errno = EINVAL; goto done; } if (!Jget_int (o, "rootseq", rootseq) || !Jget_str (o, "rootdir", rootdir) || !Jget_str (o, "sender", sender)) { errno = EPROTO; goto done; } rc = 0; done: return rc; }
static bool Jget_nodeset (JSON o, const char *name, nodeset_t *np) { nodeset_t ns; const char *s; if (!Jget_str (o, name, &s) || !(ns = nodeset_new_str (s))) return false; *np = ns; return true; }
void test_commit (void) { JSON o; const char *sender = NULL, *fence = NULL; JSON dirents = NULL, dirs; int nprocs = 0; const char *s; const char *rootdir; int rootseq; ok ((o = kp_tcommit_enc (NULL, NULL, NULL, 0)) != NULL, "kp_tcommit_enc (external commit) works"); ok (kp_tcommit_dec (o, &sender, &dirents, &fence, &nprocs) == 0 && sender == NULL && dirents == NULL && fence == NULL && nprocs == 1, "kp_tcommit_dec (external commit) works"); Jput (o); dirs = Jnew (); Jadd_str (dirs, "foo", "bar"); Jadd_str (dirs, "bar", "baz"); ok ((o = kp_tcommit_enc ("sender", dirs, "fence", 1024)) != NULL, "kp_tcommit_enc (internal commit) works"); Jput (dirs); ok (kp_tcommit_dec (o, &sender, &dirents, &fence, &nprocs) == 0 && sender != NULL && !strcmp (sender, "sender") && fence != NULL && !strcmp (fence, "fence") && nprocs == 1024, "kp_tcommit_dec (internal commit) works"); Jput (o); ok (Jget_str (dirents, "foo", &s) && !strcmp (s, "bar") && Jget_str (dirents, "bar", &s) && !strcmp (s, "baz"), "kp_tcommit_dec returned encoded dirents"); Jput (dirents); ok ((o = kp_rcommit_enc (42, "abc", "def")) != NULL, "kp_rcommit_enc works"); ok (kp_rcommit_dec (o, &rootseq, &rootdir, &sender) == 0 && rootseq == 42 && rootdir != NULL && !strcmp (rootdir, "abc") && sender != NULL && !strcmp (sender, "def"), "kp_rcommid_dec works"); Jput (o); }
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; }
/* 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 test_watch (void) { JSON o; bool dir = false; bool once = false; bool first = false; bool link = false; const char *key = NULL; const char *s = NULL; JSON val; val = Jnew (); Jadd_str (val, "s", "blatz"); o = kp_twatch_enc ("foo", val, false, true, false, true); ok (o != NULL, "kp_twatch_enc works"); val = NULL; ok (kp_twatch_dec (o, &key, &val, &once, &first, &dir, &link) == 0 && once == false && first == true && dir == false && link == true, "kp_twatch_dec works"); ok (key && !strcmp (key, "foo"), "kp_twatch_dec returned encoded key"); ok (val && Jget_str (val, "s", &s) && !strcmp (s, "blatz"), "kp_twatch_dec returned encoded value"); /* FIXME try encoding NULL value */ Jput (o); val = Jnew (); Jadd_str (val, "str", "snerg"); o = kp_rwatch_enc ("foo", val); ok (o != NULL, "kp_rwatch_enc works"); val = NULL; ok (kp_rwatch_dec (o, &val) == 0, "kp_rewatch_dec works"); ok (val && Jget_str (val, "str", &s) && !strcmp (s, "snerg"), "kp_twatch_dec returned encoded value"); Jput (o); }
static int handle_seq_destroy (seqhash_t *s, JSON in, JSON *outp) { const char *name; if (!Jget_str (in, "name", &name)) { errno = EPROTO; return (-1); } if (seq_destroy (s, name) < 0) return (-1); *outp = Jnew (); Jadd_str (*outp, "name", name); Jadd_bool (*outp, "destroyed", true); return (0); }
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 kp_tunwatch_dec (JSON o, const char **key) { int rc = -1; if (!o || !key) { errno = EINVAL; goto done; } if (!Jget_str (o, "key", key)) { errno = EPROTO; goto done; } rc = 0; done: return rc; }
/* * Gather concatenated hwloc xml topo file with resource-hwloc.topo RPC * and save results until destroyed by hwloc_topo_destroy (). */ static struct hwloc_topo * hwloc_topo_create (optparse_t *p) { const char *json_str; struct hwloc_topo *t = xzmalloc (sizeof (*t)); if (!(t->h = builtin_get_flux_handle (p))) log_err_exit ("flux_open"); t->rpc = flux_rpc (t->h, "resource-hwloc.topo", NULL, 0, 0); if (!t->rpc || (flux_rpc_get (t->rpc, NULL, &json_str) < 0)) log_err_exit ("flux_rpc"); if (!(t->o = Jfromstr (json_str)) || !Jget_str (t->o, "topology", &t->topo)) log_msg_exit ("failed to parse json topology"); return (t); }
/* 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 handle_seq_set (seqhash_t *s, JSON in, JSON *outp) { const char *name; int64_t old, v; if (!Jget_str (in, "name", &name) || !Jget_int64 (in, "value", &v)) { errno = EPROTO; return (-1); } if ((Jget_int64 (in, "oldvalue", &old) && (seq_cmp_and_set (s, name, old, v) < 0)) || (seq_set (s, name, v) < 0)) return (-1); *outp = Jnew (); Jadd_str (*outp, "name", name); Jadd_bool (*outp, "set", true); Jadd_int64 (*outp, "value", v); 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; }
void test_echo (flux_t *h, uint32_t nodeid) { json_object *in = Jnew (); json_object *out = NULL; const char *json_str; const char *s; flux_future_t *f; Jadd_str (in, "mumble", "burble"); if (!(f = flux_rpc (h, "req.echo", Jtostr (in), nodeid, 0)) || flux_rpc_get (f, &json_str) < 0) log_err_exit ("%s", __FUNCTION__); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_str (out, "mumble", &s) || strcmp (s, "burble") != 0) log_msg_exit ("%s: returned payload wasn't an echo", __FUNCTION__); Jput (in); Jput (out); flux_future_destroy (f); }
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; }
static void xping (flux_t *h, uint32_t nodeid, uint32_t xnodeid, const char *svc) { flux_future_t *f; const char *json_str; json_object *in = Jnew (); json_object *out = NULL; const char *route; Jadd_int (in, "rank", xnodeid); Jadd_str (in, "service", svc); if (!(f = flux_rpc (h, "req.xping", Jtostr (in), nodeid, 0)) || flux_rpc_get (f, &json_str) < 0) log_err_exit ("req.xping"); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_str (out, "route", &route)) log_errn_exit (EPROTO, "req.xping"); printf ("hops=%d\n", count_hops (route)); Jput (out); Jput (in); flux_future_destroy (f); }
/* 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); }
resrc_flow_t *resrc_flow_new_from_json (json_t *o, resrc_flow_t *parent) { json_t *jhierarchyo = NULL; /* json hierarchy object */ const char *basename = NULL; const char *name = NULL; const char *hierarchy = NULL; const char *path = NULL; const char *hierarchy_path = NULL; const char *tmp = NULL; const char *type = NULL; int64_t id; int64_t ssize; resrc_flow_t *resrc_flow = NULL; resrc_t *flow_resrc; resrc_t *resrc = NULL; size_t size = 1; uuid_t uuid; if (!Jget_str (o, "type", &type)) goto ret; Jget_str (o, "basename", &basename); Jget_str (o, "name", &name); if (!(Jget_int64 (o, "id", &id))) id = -1; if (Jget_str (o, "uuid", &tmp)) uuid_parse (tmp, uuid); else uuid_clear(uuid); if (Jget_int64 (o, "size", &ssize)) size = (size_t) ssize; if ((jhierarchyo = Jobj_get (o, "hierarchy"))) { /* Get first key and value from hierarchy object */ const char *key = json_object_iter_key (json_object_iter (jhierarchyo)); if (key) { hierarchy = key; Jget_str (jhierarchyo, key, &hierarchy_path); } } if (!Jget_str (o, "path", &path)) { if (hierarchy_path) path = xstrdup (hierarchy_path); } if (!path) { if (parent) path = xasprintf ("%s/%s", resrc_path (parent->flow_resrc), name); else path = xasprintf ("/%s", name); } if (!(flow_resrc = resrc_new_resource (type, path, basename, name, NULL, id, uuid, size))) goto ret; if (!strncmp (type, "node", 5)) { resrc = resrc_lookup (name); } if ((resrc_flow = resrc_flow_new (parent, flow_resrc, resrc))) { /* add time window if we are given a start time */ int64_t starttime; if (Jget_int64 (o, "starttime", &starttime)) { json_t * w = Jnew (); char *json_str; int64_t endtime; int64_t wall_time; Jadd_int64 (w, "starttime", starttime); if (!Jget_int64 (o, "endtime", &endtime)) { if (Jget_int64 (o, "walltime", &wall_time)) endtime = starttime + wall_time; else endtime = TIME_MAX; } Jadd_int64 (w, "endtime", endtime); json_str = xstrdup (Jtostr (w)); resrc_twindow_insert (resrc_flow->flow_resrc, "0", (void *) json_str); Jput (w); } } if (resrc) resrc_graph_insert (resrc, hierarchy, resrc_flow); ret: return resrc_flow; }
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); }
static void determine_all_min_bandwidth_helper (struct resource *r, double curr_min_bandwidth, zhash_t *job_hash) { struct resource *curr_child; int64_t job_id; double total_requested_bandwidth, curr_average_bandwidth, child_alloc_bandwidth, total_used_bandwidth, this_max_bandwidth, num_children, this_alloc_bandwidth; json_t *o; zlist_t *child_list; const char *type = NULL; // Check if leaf node in hierarchy (base case) rdl_resource_iterator_reset (r); curr_child = rdl_resource_next_child (r); if (curr_child == NULL) { // Check if allocated to a job if (rdl_resource_get_int (r, "lwj", &job_id) == 0) { // Determine which is less, the bandwidth currently available to // this resource, or the bandwidth allocated to it by the job // This assumes that jobs cannot share leaf nodes in the hierarchy this_alloc_bandwidth = get_alloc_bandwidth (r); curr_min_bandwidth = (curr_min_bandwidth < this_alloc_bandwidth) ? curr_min_bandwidth : this_alloc_bandwidth; double *job_min_bw = get_job_min_from_hash (job_hash, job_id); if (job_min_bw != NULL && curr_min_bandwidth < *job_min_bw) { *job_min_bw = curr_min_bandwidth; } // if job_min_bw is NULL, the tag still exists in the RDL, but // the job completed } return; } // else // Sum the bandwidths of the parent's children total_requested_bandwidth = 0; child_list = zlist_new (); while (curr_child != NULL) { o = rdl_resource_json (curr_child); Jget_str (o, "type", &type); // TODO: clean up this hardcoded value, should go away once we switch to // the real // rdl implementation (storing a bandwidth resource at every level) if (strcmp (type, "memory") != 0) { total_requested_bandwidth += get_alloc_bandwidth (curr_child); zlist_append (child_list, curr_child); } Jput (o); curr_child = rdl_resource_next_child (r); } rdl_resource_iterator_reset (r); // Sort child list based on alloc bw zlist_sort (child_list, compare_resource_alloc_bw); // const char *resource_string = Jtostr(o); // Loop over all of the children this_max_bandwidth = get_max_bandwidth (r); total_used_bandwidth = (total_requested_bandwidth > this_max_bandwidth) ? this_max_bandwidth : total_requested_bandwidth; total_used_bandwidth = (total_used_bandwidth > curr_min_bandwidth) ? curr_min_bandwidth : total_used_bandwidth; while (zlist_size (child_list) > 0) { // Determine the amount of bandwidth to allocate to each child num_children = zlist_size (child_list); curr_average_bandwidth = (total_used_bandwidth / num_children); curr_child = (struct resource *)zlist_pop (child_list); child_alloc_bandwidth = get_alloc_bandwidth (curr_child); if (child_alloc_bandwidth > 0) { if (child_alloc_bandwidth > curr_average_bandwidth) child_alloc_bandwidth = curr_average_bandwidth; // Subtract the allocated bandwidth from the parent's total total_used_bandwidth -= child_alloc_bandwidth; // Recurse on the child determine_all_min_bandwidth_helper (curr_child, child_alloc_bandwidth, job_hash); } rdl_resource_destroy (curr_child); } // Cleanup zlist_destroy ( &child_list); // no need to rdl_resource_destroy, done in above loop return; }