/* 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; }
/* Always return an error 42 */ static int err_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { if (flux_err_respond (h, 42, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); return 0; }
static int enter_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { ctx_t *ctx = arg; barrier_t *b; json_object *o = NULL; char *sender = NULL; const char *name; int count, nprocs, hopcount; if (flux_json_request_decode (*zmsg, &o) < 0 || flux_msg_get_route_first (*zmsg, &sender) < 0 || util_json_object_get_string (o, "name", &name) < 0 || util_json_object_get_int (o, "count", &count) < 0 || util_json_object_get_int (o, "nprocs", &nprocs) < 0) { flux_log (ctx->h, LOG_ERR, "%s: ignoring bad message", __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 (util_json_object_get_int (o, "hopcount", &hopcount) < 0) { if (barrier_add_client (b, sender, zmsg) < 0) { flux_err_respond (ctx->h, EEXIST, zmsg); 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 (ctx->h, LOG_ERR, "exit_event_send: %s", strerror (errno)); 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 (ctx->h, LOG_ERR, "exit_event_send: %s", strerror (errno)); } else if (ctx->rank > 0 && !ctx->timer_armed) { if (flux_tmouthandler_add (h, barrier_reduction_timeout_msec, true, timeout_cb, ctx) < 0) { flux_log (h, LOG_ERR, "flux_tmouthandler_add: %s",strerror (errno)); goto done; } ctx->timer_armed = true; } done: if (o) json_object_put (o); if (*zmsg) zmsg_destroy (zmsg); if (sender) free (sender); return 0; }
/* Reply to all queued requests. */ static int flush_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { ctx_t *ctx = getctx (h); zmsg_t *z; while ((z = zlist_pop (ctx->clog_requests))) { /* send clog response */ if (flux_err_respond (h, 0, &z) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); } /* send flush response */ if (flux_err_respond (h, 0, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); return 0; }
static int hi_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { if (flux_err_respond (h, 0, zmsg) < 0) { flux_log (h, LOG_ERR, "%s: responding: %s", __FUNCTION__, strerror (errno)); return -1; } return 0; }
static int send_enter_response (const char *key, void *item, void *arg) { zmsg_t *zmsg = item; barrier_t *b = arg; zmsg_t *cpy; if (!(cpy = zmsg_dup (zmsg))) oom (); flux_err_respond (b->ctx->h, b->errnum, &cpy); return 0; }
/* 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; }
/* The req.clog request will not be answered until req.flush is called. */ static int stuck_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { if (flux_json_rpc (h, FLUX_NODEID_ANY, "req.clog", NULL, NULL) < 0) { flux_log (h, LOG_ERR, "%s: req.clog RPC: %s", __FUNCTION__, strerror (errno)); return -1; } if (flux_err_respond (h, 0, zmsg) < 0) { flux_log (h, LOG_ERR, "%s: responding: %s", __FUNCTION__, strerror (errno)); return -1; } return 0; }
/* Accept a json payload, verify it and return error if it doesn't * match expected. */ static int sink_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { JSON o = NULL; double d; 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_double (o, "pi", &d) || d != 3.14) { if (flux_err_respond (h, EPROTO, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } if (flux_err_respond (h, 0, zmsg) < 0) flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); done: Jput (o); return 0; }
/* Echo a json payload back to requestor. */ static int echo_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { 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 (flux_json_respond (h, o, zmsg) < 0) { flux_log (h, LOG_ERR, "%s: flux_json_respond: %s", __FUNCTION__, strerror (errno)); goto done; } done: Jput (o); return 0; }
/* Handle the simplest possible request. * Verify that everything is as expected; log it and stop the reactor if not. */ static int null_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { //ctx_t *ctx = arg; const char *topic; int type, size, flags; int rc = -1; void *buf; uint32_t nodeid; if (!zmsg || !*zmsg) { flux_log (h, LOG_ERR, "%s: got NULL zmsg!", __FUNCTION__); goto done; } if (flux_msg_get_type (*zmsg, &type) < 0) { flux_log (h, LOG_ERR, "%s: flux_msg_get_type: %s", __FUNCTION__, strerror (errno)); goto done; } if (type != FLUX_MSGTYPE_REQUEST) { flux_log (h, LOG_ERR, "%s: unexpected type %s", __FUNCTION__, flux_msg_typestr (type)); goto done; } if (flux_msg_get_nodeid (*zmsg, &nodeid, &flags) < 0) { flux_log (h, LOG_ERR, "%s: flux_msg_get_nodeid: %s", __FUNCTION__, strerror (errno)); goto done; } if (nodeid != FLUX_NODEID_ANY && nodeid != flux_rank (h)) { flux_log (h, LOG_ERR, "%s: unexpected nodeid: %"PRIu32"", __FUNCTION__, nodeid); goto done; } if (flux_msg_get_topic (*zmsg, &topic) < 0) { flux_log (h, LOG_ERR, "%s: flux_msg_get_topic: %s", __FUNCTION__, strerror (errno)); goto done; } if (strcmp (topic, "req.null") != 0) { flux_log (h, LOG_ERR, "%s: unexpected topic: %s", __FUNCTION__, topic); goto done; } if (flux_msg_get_payload (*zmsg, &flags, &buf, &size) == 0) { flux_log (h, LOG_ERR, "%s: unexpected payload size %d", __FUNCTION__, size); goto done; } if (errno != EPROTO) { flux_log (h, LOG_ERR, "%s: get nonexistent payload: %s", __FUNCTION__, strerror (errno)); goto done; } errno = 0; if (flux_err_respond (h, 0, zmsg) < 0) { flux_log (h, LOG_ERR, "%s: flux_err_respond: %s", __FUNCTION__, strerror (errno)); goto done; } rc = 0; done: return rc; }
static int job_request_cb (flux_t h, int typemask, zmsg_t **zmsg, void *arg) { const char *json_str; json_object *o = NULL; const char *topic; if (flux_msg_get_topic (*zmsg, &topic) < 0) goto out; if (flux_msg_get_payload_json (*zmsg, &json_str) < 0) goto out; if (json_str && !(o = json_tokener_parse (json_str))) goto out; if (strcmp (topic, "job.shutdown") == 0) { flux_reactor_stop (h); } if (strcmp (topic, "job.next-id") == 0) { if (flux_rank (h) == 0) { unsigned long id = lwj_next_id (h); json_object *ox = json_id (id); flux_json_respond (h, ox, zmsg); json_object_put (o); } else { fprintf (stderr, "%s: forwarding request\n", topic); flux_json_request (h, FLUX_NODEID_ANY, FLUX_MATCHTAG_NONE, topic, o); } } if (strcmp (topic, "job.create") == 0) { json_object *jobinfo = NULL; unsigned long id = lwj_next_id (h); bool should_workaround = false; //"Fix" for Race Condition if (util_json_object_get_boolean (o, "race_workaround", &should_workaround) < 0) { should_workaround = false; } else if (should_workaround) { if (wait_for_lwj_watch_init (h, id) < 0) { flux_err_respond (h, errno, zmsg); goto out; } } int rc = kvs_job_new (h, id); if (rc < 0) { flux_err_respond (h, errno, zmsg); goto out; } add_jobinfo (h, id, o); kvs_commit (h); /* Generate reply with new jobid */ jobinfo = util_json_object_new_object (); util_json_object_add_int64 (jobinfo, "jobid", id); flux_json_respond (h, jobinfo, zmsg); json_object_put (jobinfo); } out: if (o) json_object_put (o); zmsg_destroy (zmsg); return 0; }