static int output_handler (zio_t *z, const char *json_str, int len, void *arg) { struct subprocess *p = (struct subprocess *) arg; json_object *o; if (p->io_cb) { if (!(o = json_tokener_parse (json_str))) { errno = EINVAL; return -1; } Jadd_int (o, "pid", subprocess_pid (p)); Jadd_str (o, "type", "io"); Jadd_str (o, "name", zio_name (z)); p->io_cb (p, json_object_to_json_string (o)); json_object_put (o); } else send_output_to_stream (zio_name (z), json_str); /* * Check for process completion in case EOF from I/O stream and process * already registered exit */ check_completion (p); return (0); }
static inline void create_req4allsocks (json_t *reqobj) { json_t *req1; Jadd_str (reqobj, "type", "socket"); Jadd_int (reqobj, "req_qty", 1); req1 = Jnew (); Jadd_str (req1, "type", "core"); Jadd_int (req1, "req_qty", 1); json_object_set_new (reqobj, "req_child", req1); }
JSON kp_tcommit_enc (const char *sender, JSON ops, const char *fence, int nprocs) { JSON o = Jnew (); Jadd_obj (o, "ops", ops); /* takes a ref on ops */ if (sender) Jadd_str (o, ".arg_sender", sender); if (fence) { Jadd_str (o, ".arg_fence", fence); Jadd_int (o, ".arg_nprocs", nprocs); } return o; }
JSON kp_rcommit_enc (int rootseq, const char *rootdir, const char *sender) { JSON o = NULL; if (!rootdir || !sender) { errno = EINVAL; goto done; } o = Jnew (); Jadd_int (o, "rootseq", rootseq); Jadd_str (o, "rootdir", rootdir); Jadd_str (o, "sender", sender); done: return o; }
static int64_t next_jobid (flux_t h) { int64_t ret = (int64_t) -1; const char *json_str; json_object *req, *resp; flux_rpc_t *rpc; req = Jnew (); Jadd_str (req, "name", "lwj"); Jadd_int64 (req, "preincrement", 1); Jadd_int64 (req, "postincrement", 0); Jadd_bool (req, "create", true); rpc = flux_rpc (h, "cmb.seq.fetch", json_object_to_json_string (req), 0, 0); json_object_put (req); if ((flux_rpc_get (rpc, NULL, &json_str) < 0) || !(resp = json_tokener_parse (json_str))) { flux_log_error (h, "rpc_get"); goto out; } Jget_int64 (resp, "value", &ret); json_object_put (resp); out: flux_rpc_destroy (rpc); return ret; }
void send_ping (struct ping_ctx *ctx) { struct timespec t0; json_object *in = Jnew (); flux_rpc_t *rpc; struct ping_data *pdata = xzmalloc (sizeof (*pdata)); pdata->tstat = xzmalloc (sizeof (*(pdata->tstat))); pdata->seq = 0; pdata->route = NULL; pdata->rpc_count = 0; Jadd_int (in, "seq", ctx->send_count); monotime (&t0); Jadd_int64 (in, "time.tv_sec", t0.tv_sec); Jadd_int64 (in, "time.tv_nsec", t0.tv_nsec); Jadd_str (in, "pad", ctx->pad); if (ctx->rank) rpc = flux_rpc_multi (ctx->h, ctx->topic, Jtostr (in), ctx->rank, 0); else rpc = flux_rpc (ctx->h, ctx->topic, Jtostr (in), ctx->nodeid, 0); if (!rpc) log_err_exit ("flux_rpc"); flux_rpc_aux_set (rpc, pdata, ping_data_free); if (flux_rpc_then (rpc, ping_continuation, ctx) < 0) log_err_exit ("flux_rpc_then"); Jput (in); ctx->send_count++; }
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); }
/* Route string will not include the endpoints. */ static void ping_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { module_t *p = arg; const char *json_str; JSON o = NULL; char *route = NULL; char *route_plus_uuid = NULL; int rc = -1; if (flux_request_decode (msg, NULL, &json_str) < 0) goto done; if (!(o = Jfromstr (json_str))) { errno = EPROTO; goto done; } if (!(route = flux_msg_get_route_string (msg))) goto done; route_plus_uuid = xasprintf ("%s!%.5s", route, module_get_uuid (p)); Jadd_str (o, "route", route_plus_uuid); rc = 0; done: if (flux_respond (h, msg, rc < 0 ? errno : 0, rc < 0 ? NULL : Jtostr (o)) < 0) FLUX_LOG_ERROR (h); Jput (o); if (route_plus_uuid) free (route_plus_uuid); if (route) free (route); }
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); }
JSON kp_tsetroot_enc (int rootseq, const char *rootdir, JSON root, const char *fence) { JSON o = NULL; if (!rootdir) { errno = EINVAL; goto done; } o = Jnew (); Jadd_int (o, "rootseq", rootseq); Jadd_str (o, "rootdir", rootdir); if (fence) Jadd_str (o, "fence", fence); if (root) Jadd_obj (o, "rootdirval", root); /* takes a ref */ done: return o; }
JSON kp_tunwatch_enc (const char *key) { JSON o = NULL; if (!key) { errno = EINVAL; goto done; } o = Jnew (); Jadd_str (o, "key", key); done: return o; }
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); }
JSON kp_rgetroot_enc (int rootseq, const char *rootdir) { JSON o = NULL; if (!rootdir) { errno = EINVAL; goto done; } o = Jnew (); Jadd_int (o, "rootseq", rootseq); Jadd_str (o, "rootdir", rootdir); done: return o; }
static int query_rdl (flux_t *h, int64_t j, json_object **jcb) { char *rdlstr = NULL; if (extract_raw_rdl (h, j, &rdlstr) < 0) return -1; *jcb = Jnew (); Jadd_str (*jcb, JSC_RDL, (const char *)rdlstr); /* Note: seems there is no mechanism to transfer ownership * of this string to jcb */ if (rdlstr) free (rdlstr); return 0; }
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); }
static int update_1pdesc (flux_t *h, flux_kvs_txn_t *txn, int r, int64_t j, json_object *o, json_object *ha, json_object *ea) { flux_future_t *f = NULL; int rc = -1; json_object *d = NULL; char *key; const char *json_str; const char *hn = NULL, *en = NULL; int64_t pid = 0, hindx = 0, eindx = 0, hrank = 0; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_PID, &pid)) return -1; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_HINDX, &hindx)) return -1; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_EINDX, &eindx)) return -1; if (!Jget_ar_str (ha, (int)hindx, &hn)) return -1; if (!Jget_ar_str (ea, (int)eindx, &en)) return -1; key = lwj_key (h, j, ".%d.procdesc", r); if (!key || !(f = flux_kvs_lookup (h, 0, key)) || flux_kvs_lookup_get (f, &json_str) < 0 || !(d = Jfromstr (json_str))) { flux_log_error (h, "extract %s", key); goto done; } Jadd_str (d, "command", en); Jadd_int64 (d, "pid", pid); errno = 0; if ( (hrank = strtoul (hn, NULL, 10)) && errno != 0) { flux_log (h, LOG_ERR, "invalid hostname %s", hn); goto done; } Jadd_int64 (d, "nodeid", (int64_t)hrank); if (flux_kvs_txn_put (txn, 0, key, Jtostr (d)) < 0) { flux_log_error (h, "put %s", key); goto done; } rc = 0; done: flux_future_destroy (f); free (key); if (d) Jput (d); return rc; }
flux_msg_t *shutdown_vencode (double grace, int exitcode, int rank, const char *fmt, va_list ap) { flux_msg_t *msg; JSON out = Jnew (); char reason[REASON_MAX]; vsnprintf (reason, sizeof (reason), fmt, ap); Jadd_str (out, "reason", reason); Jadd_double (out, "grace", grace); Jadd_int (out, "rank", rank); Jadd_int (out, "exitcode", exitcode); msg = flux_event_encode ("shutdown", Jtostr (out)); Jput (out); return msg; }
static int op_event_unsubscribe (void *impl, const char *topic) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); JSON in = Jnew (); int rc = -1; if (connect_socket (ctx) < 0) goto done; Jadd_str (in, "topic", topic); if (flux_json_rpc (ctx->h, FLUX_NODEID_ANY, "cmb.unsub", in, NULL) < 0) goto done; rc = 0; done: Jput (in); return rc; }
static int op_event_unsubscribe (void *impl, const char *topic) { ctx_t *c = impl; assert (c->magic == CTX_MAGIC); flux_rpc_t *rpc = NULL; JSON in = Jnew (); int rc = 0; Jadd_str (in, "topic", topic); if (!(rpc = flux_rpc (c->h, "local.unsub", Jtostr (in), FLUX_NODEID_ANY, 0)) || flux_rpc_get (rpc, NULL, NULL) < 0) goto done; rc = 0; done: flux_rpc_destroy (rpc); Jput (in); return rc; }
static int exit_event_send (flux_t h, const char *name, int errnum) { JSON o = Jnew (); zmsg_t *zmsg = NULL; int rc = -1; Jadd_str (o, "name", name); Jadd_int (o, "errnum", errnum); if (!(zmsg = flux_event_encode ("barrier.exit", Jtostr (o)))) goto done; if (flux_sendmsg (h, &zmsg) < 0) goto done; rc = 0; done: Jput (o); zmsg_destroy (&zmsg); return rc; }
static int exit_event_send (flux_t *h, const char *name, int errnum) { json_object *o = Jnew (); flux_msg_t *msg = NULL; int rc = -1; Jadd_str (o, "name", name); Jadd_int (o, "errnum", errnum); if (!(msg = flux_event_encode ("barrier.exit", Jtostr (o)))) goto done; if (flux_send (h, msg, 0) < 0) goto done; rc = 0; done: Jput (o); flux_msg_destroy (msg); return rc; }
static int update_1pdesc (flux_t h, int r, int64_t j, JSON o, JSON ha, JSON ea) { int rc = -1; JSON d = NULL; char *key; char *json_str = NULL; const char *hn = NULL, *en = NULL; int64_t pid = 0, hindx = 0, eindx = 0, hrank = 0; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_PID, &pid)) return -1; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_HINDX, &hindx)) return -1; if (!Jget_int64 (o, JSC_PDESC_RANK_PDARRAY_EINDX, &eindx)) return -1; if (!Jget_ar_str (ha, (int)hindx, &hn)) return -1; if (!Jget_ar_str (ea, (int)eindx, &en)) return -1; key = xasprintf ("lwj.%"PRId64".%"PRId32".procdesc", j, r); if (kvs_get (h, key, &json_str) < 0 || !(d = Jfromstr (json_str))) { flux_log_error (h, "extract %s", key); goto done; } Jadd_str (d, "command", en); Jadd_int64 (d, "pid", pid); errno = 0; if ( (hrank = strtoul (hn, NULL, 10)) && errno != 0) { flux_log (h, LOG_ERR, "invalid hostname %s", hn); goto done; } Jadd_int64 (d, "nodeid", (int64_t)hrank); if (kvs_put (h, key, Jtostr (d)) < 0) { flux_log_error (h, "put %s", key); goto done; } rc = 0; done: free (key); if (d) Jput (d); if (json_str) free (json_str); 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 void send_enter_request (ctx_t *ctx, barrier_t *b) { json_object *o = Jnew (); flux_rpc_t *rpc; Jadd_str (o, "name", b->name); Jadd_int (o, "count", b->count); Jadd_int (o, "nprocs", b->nprocs); Jadd_int (o, "hopcount", 1); if (!(rpc = flux_rpc (ctx->h, "barrier.enter", Jtostr (o), FLUX_NODEID_UPSTREAM, FLUX_RPC_NORESPONSE))) { flux_log_error (ctx->h, "sending barrier.enter request"); goto done; } done: if (rpc) flux_rpc_destroy (rpc); json_object_put (o); }
static int op_event_unsubscribe (void *impl, const char *topic) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); JSON in = Jnew (); flux_rpc_t *rpc = NULL; int rc = -1; if (connect_socket (ctx) < 0) goto done; Jadd_str (in, "topic", topic); if (!(rpc = flux_rpc (ctx->h, "cmb.unsub", Jtostr (in), FLUX_NODEID_ANY, 0)) || flux_rpc_get (rpc, NULL, NULL) < 0) goto done; rc = 0; done: Jput (in); flux_rpc_destroy (rpc); return rc; }
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); }
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); }
static int internal_heaptrace_dump (optparse_t *p, int ac, char *av[]) { flux_t *h; flux_rpc_t *rpc; json_object *in = Jnew (); if (optparse_optind (p) != ac - 1) { optparse_print_usage (p); exit (1); } Jadd_str (in, "reason", av[ac - 1]); if (!(h = builtin_get_flux_handle (p))) log_err_exit ("flux_open"); if (!(rpc = flux_rpc (h, "cmb.heaptrace.dump", Jtostr (in), FLUX_NODEID_ANY, 0)) || flux_rpc_get (rpc, NULL) < 0) log_err_exit ("cmb.heaptrace.dump"); flux_rpc_destroy (rpc); flux_close (h); return (0); }
static flux_msg_t *op_recv (void *impl, int flags) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); zmq_pollitem_t zp = { .events = ZMQ_POLLIN, .socket = ctx->sock, .revents = 0, .fd = -1, }; flux_msg_t *msg = NULL; if (connect_socket (ctx) < 0) goto done; if ((flags & FLUX_O_NONBLOCK)) { int n; if ((n = zmq_poll (&zp, 1, 0L)) < 0) goto done; /* likely: EWOULDBLOCK | EAGAIN */ assert (n == 1); assert (zp.revents == ZMQ_POLLIN); } msg = zmsg_recv (ctx->sock); done: return msg; } static int op_event_subscribe (void *impl, const char *topic) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); JSON in = Jnew (); int rc = -1; if (connect_socket (ctx) < 0) goto done; Jadd_str (in, "topic", topic); if (flux_json_rpc (ctx->h, FLUX_NODEID_ANY, "cmb.sub", in, NULL) < 0) goto done; rc = 0; done: Jput (in); return rc; }
static flux_msg_t *op_recv (void *impl, int flags) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); zmq_pollitem_t zp = { .events = ZMQ_POLLIN, .socket = ctx->sock, .revents = 0, .fd = -1, }; flux_msg_t *msg = NULL; if (connect_socket (ctx) < 0) goto done; if ((flags & FLUX_O_NONBLOCK)) { int n; if ((n = zmq_poll (&zp, 1, 0L)) <= 0) { if (n == 0) errno = EWOULDBLOCK; goto done; } } msg = flux_msg_recvzsock (ctx->sock); done: return msg; } static int op_event_subscribe (void *impl, const char *topic) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); json_object *in = Jnew (); flux_rpc_t *rpc = NULL; int rc = -1; if (connect_socket (ctx) < 0) goto done; Jadd_str (in, "topic", topic); if (!(rpc = flux_rpc (ctx->h, "cmb.sub", Jtostr (in), FLUX_NODEID_ANY, 0)) || flux_rpc_get (rpc, NULL) < 0) goto done; rc = 0; done: Jput (in); flux_rpc_destroy (rpc); return rc; }