static int send_state_event (flux_t *h, job_state_t st, int64_t j) { flux_msg_t *msg; char *json = NULL; char *topic = NULL; int rc = -1; if (asprintf (&topic, "jsc.state.%s", jsc_job_num2state (st)) < 0) { errno = ENOMEM; flux_log_error (h, "create state change event: %s", jsc_job_num2state (st)); goto done; } if ((msg = flux_event_pack (topic, "{ s:I }", "lwj", j)) == NULL) { flux_log_error (h, "flux_event_pack"); goto done; } if (flux_send (h, msg, 0) < 0) flux_log_error (h, "flux_send event"); flux_msg_destroy (msg); rc = 0; done: free (topic); free (json); return rc; }
static void io_cb (flux_subprocess_t *p, const char *stream) { runlevel_t *r; const char *ptr; int lenp; r = flux_subprocess_aux_get (p, "runlevel"); assert (r); assert (r->level == 1 || r->level == 3); if (!(ptr = flux_subprocess_read_line (p, stream, &lenp))) { flux_log_error (r->h, "%s: flux_subprocess_read_line", __FUNCTION__); return; } if (!lenp) { if (!(ptr = flux_subprocess_read (p, stream, -1, &lenp))) { flux_log_error (r->h, "%s: flux_subprocess_read", __FUNCTION__); return; } } if (lenp && r->io_cb) r->io_cb (r, stream, ptr, r->io_cb_arg); }
static ctx_t *getctx (flux_t *h) { ctx_t *ctx = (ctx_t *)flux_aux_get (h, "flux::barrier"); if (!ctx) { ctx = xzmalloc (sizeof (*ctx)); if (!(ctx->barriers = zhash_new ())) { errno = ENOMEM; goto error; } if (flux_get_rank (h, &ctx->rank) < 0) { flux_log_error (h, "flux_get_rank"); goto error; } if (!(ctx->timer = flux_timer_watcher_create (flux_get_reactor (h), barrier_reduction_timeout_sec, 0., timeout_cb, ctx) )) { flux_log_error (h, "flux_timer_watacher_create"); goto error; } ctx->h = h; flux_aux_set (h, "flux::barrier", ctx, freectx); } return ctx; error: freectx (ctx); return NULL; }
static void send_create_event (flux_t h, int64_t id, char *topic) { flux_msg_t *msg; char *json = NULL; if (asprintf (&json, "{\"lwj\":%ld}", id) < 0) { errno = ENOMEM; flux_log_error (h, "failed to create state change event"); goto out; } if ((msg = flux_event_encode (topic, json)) == NULL) { flux_log_error (h, "failed to create state change event"); goto out; } if (flux_send (h, msg, 0) < 0) flux_log_error (h, "reserved event failed"); flux_msg_destroy (msg); /* Workaround -- wait for our own event to be published with a * blocking recv. XXX: Remove when publish is synchronous. */ wait_for_event (h, id, topic); out: free (json); }
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); }
int mod_main (flux_t *h, int argc, char **argv) { int rc = -1; ctx_t *ctx = getctx (h); if (!ctx) goto done; if (flux_event_subscribe (h, "barrier.") < 0) { flux_log_error (h, "flux_event_subscribe"); goto done; } if (flux_msg_handler_addvec (h, htab, ctx) < 0) { flux_log_error (h, "flux_msghandler_add"); goto done; } if (flux_reactor_run (flux_get_reactor (h), 0) < 0) { flux_log_error (h, "flux_reactor_run"); goto done_unreg; } rc = 0; done_unreg: flux_msg_handler_delvec (htab); done: return rc; }
static int update_state (flux_t h, int64_t j, JSON o) { int rc = -1; int64_t st = 0; char *key; if (!Jget_int64 (o, JSC_STATE_PAIR_NSTATE, &st)) return -1; if ((st >= J_FOR_RENT) || (st < J_NULL)) return -1; key = xasprintf ("lwj.%"PRId64".state", j); if (kvs_put_string (h, key, jsc_job_num2state ((job_state_t)st)) < 0) flux_log_error (h, "update %s", key); else if (kvs_commit (h) < 0) flux_log_error (h, "commit %s", key); else { flux_log (h, LOG_DEBUG, "job (%"PRId64") assigned new state: %s", j, jsc_job_num2state ((job_state_t)st)); rc = 0; } free (key); if (send_state_event (h, st, j) < 0) flux_log_error (h, "send state event"); return rc; }
int mod_main (flux_t *h, int argc, char **argv) { flux_msg_handler_t **handlers = NULL; sqlite_ctx_t *ctx = getctx (h); if (!ctx) goto done; if (flux_event_subscribe (h, "shutdown") < 0) { flux_log_error (h, "flux_event_subscribe"); goto done; } if (flux_msg_handler_addvec (h, htab, ctx, &handlers) < 0) { flux_log_error (h, "flux_msg_handler_addvec"); goto done; } if (register_backing_store (h, true, "content-sqlite") < 0) { flux_log_error (h, "registering backing store"); goto done; } if (register_content_backing_service (h) < 0) { flux_log_error (h, "service.add: content-backing"); goto done; } if (flux_reactor_run (flux_get_reactor (h), 0) < 0) { flux_log_error (h, "flux_reactor_run"); goto done; } done: flux_msg_handler_delvec (handlers); 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); }
/* sched-ready: * Scheduler indicates what style of alloc concurrency is requires, * and tells job-manager to start allocations. job-manager tells * scheduler how many jobs are in the queue. */ static void ready_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { struct alloc_ctx *ctx = arg; const char *mode; int count; if (flux_request_unpack (msg, NULL, "{s:s}", "mode", &mode) < 0) goto error; if (!strcmp (mode, "single")) ctx->mode = SCHED_SINGLE; else if (!strcmp (mode, "unlimited")) ctx->mode = SCHED_UNLIMITED; else { errno = EPROTO; goto error; } ctx->ready = true; flux_log (h, LOG_DEBUG, "scheduler: ready %s", mode); count = queue_size (ctx->inqueue); if (flux_respond_pack (h, msg, "{s:i}", "count", count) < 0) flux_log_error (h, "%s: flux_respond_pack", __FUNCTION__); return; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); }
static int update_rdl (flux_t *h, int64_t j, const char *rs) { int rc = -1; char *key = lwj_key (h, j, ".rdl"); flux_kvs_txn_t *txn = NULL; flux_future_t *f = NULL; if (!(txn = flux_kvs_txn_create ())) { flux_log_error (h, "txn_create"); goto done; } if (flux_kvs_txn_pack (txn, 0, key, "s", rs) < 0) { flux_log_error (h, "update %s", key); goto done; } if (!(f = flux_kvs_commit (h, 0, txn)) || flux_future_get (f, NULL) < 0) { flux_log_error (h, "commit failed"); goto done; } flux_log (h, LOG_DEBUG, "job (%"PRId64") assigned new rdl.", j); rc = 0; done: flux_kvs_txn_destroy (txn); flux_future_destroy (f); free (key); return rc; }
int mod_main (flux_t h, int argc, char **argv) { int saved_errno; ctx_t *ctx = getctx (h); if (!ctx) { saved_errno = errno; flux_log_error (h, "error allocating context"); goto error; } if (flux_msg_handler_addvec (h, htab, ctx) < 0) { saved_errno = errno; flux_log_error (h, "flux_msg_handler_addvec"); goto error; } if (flux_reactor_run (flux_get_reactor (h), 0) < 0) { saved_errno = errno; flux_log_error (h, "flux_reactor_run"); flux_msg_handler_delvec (htab); goto error; } flux_msg_handler_delvec (htab); return 0; error: errno = saved_errno; return -1; }
/* Handle the simplest possible request. * Verify that everything is as expected; log it and stop the reactor if not. */ void null_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; const char *topic; int type, size; void *buf; uint32_t nodeid; int flags; if (!msg) { flux_log (h, LOG_ERR, "%s: got NULL msg!", __FUNCTION__); goto error; } if (flux_msg_get_type (msg, &type) < 0) { flux_log_error (h, "%s: flux_msg_get_type", __FUNCTION__); goto error; } if (type != FLUX_MSGTYPE_REQUEST) { flux_log (h, LOG_ERR, "%s: unexpected type %s", __FUNCTION__, flux_msg_typestr (type)); goto error; } if (flux_msg_get_nodeid (msg, &nodeid, &flags) < 0) { flux_log_error (h, "%s: flux_msg_get_nodeid", __FUNCTION__); goto error; } if (nodeid != ctx->rank && nodeid != FLUX_NODEID_ANY) { flux_log (h, LOG_ERR, "%s: unexpected nodeid: %"PRIu32"", __FUNCTION__, nodeid); goto error; } if (flux_msg_get_topic (msg, &topic) < 0) { flux_log_error (h, "%s: flux_msg_get_topic", __FUNCTION__); goto error; } if (strcmp (topic, "req.null") != 0) { flux_log (h, LOG_ERR, "%s: unexpected topic: %s", __FUNCTION__, topic); goto error; } if (flux_msg_get_payload (msg, &flags, &buf, &size) == 0) { flux_log (h, LOG_ERR, "%s: unexpected payload size %d", __FUNCTION__, size); goto error; } if (errno != EPROTO) { flux_log (h, LOG_ERR, "%s: get nonexistent payload: %s", __FUNCTION__, strerror (errno)); goto error; } if (flux_respond (h, msg, 0, NULL) < 0) { flux_log_error (h, "%s: flux_respond", __FUNCTION__); goto error; } return; error: flux_reactor_stop_error (flux_get_reactor (h)); }
void priority_handle_request (flux_t *h, struct queue *queue, struct event_ctx *event_ctx, const flux_msg_t *msg) { uint32_t userid; uint32_t rolemask; flux_jobid_t id; struct job *job; int priority; const char *errstr = NULL; if (flux_request_unpack (msg, NULL, "{s:I s:i}", "id", &id, "priority", &priority) < 0 || flux_msg_get_userid (msg, &userid) < 0 || flux_msg_get_rolemask (msg, &rolemask) < 0) goto error; if (priority < FLUX_JOB_PRIORITY_MIN || priority > FLUX_JOB_PRIORITY_MAX) { errstr = "priority value is out of range"; errno = EINVAL; goto error; } if (!(job = queue_lookup_by_id (queue, id))) { errstr = "unknown job"; goto error; } /* Security: guests can only adjust jobs that they submitted. */ if (!(rolemask & FLUX_ROLE_OWNER) && userid != job->userid) { errstr = "guests can only reprioritize their own jobs"; errno = EPERM; goto error; } /* Security: guests can only reduce priority, or increase up to default. */ if (!(rolemask & FLUX_ROLE_OWNER) && priority > MAXOF (FLUX_JOB_PRIORITY_DEFAULT, job->priority)) { errstr = "guests can only adjust priority <= default"; errno = EPERM; goto error; } /* Post event, change job's queue position, and respond. */ if (event_job_post_pack (event_ctx, job, "priority", "{ s:i s:i }", "userid", userid, "priority", priority) < 0) goto error; queue_reorder (queue, job, job->queue_handle); if (flux_respond (h, msg, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); return; error: if (flux_respond_error (h, msg, errno, errstr) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); }
static int update_rdesc (flux_t *h, int64_t j, json_object *o) { int rc = -1; int64_t nnodes = 0; int64_t ntasks = 0; int64_t walltime = 0; char *key1 = NULL; char *key2 = NULL; char *key3 = NULL; flux_kvs_txn_t *txn = NULL; flux_future_t *f = NULL; if (!Jget_int64 (o, JSC_RDESC_NNODES, &nnodes)) goto done; if (!Jget_int64 (o, JSC_RDESC_NTASKS, &ntasks)) goto done; if (!Jget_int64 (o, JSC_RDESC_WALLTIME, &walltime)) goto done; if ((nnodes < 0) || (ntasks < 0) || (walltime < 0)) goto done; key1 = lwj_key (h, j, ".nnodes"); key2 = lwj_key (h, j, ".ntasks"); key3 = lwj_key (h, j, ".walltime"); if (!key1 || !key2 || !key3) goto done; if (!(txn = flux_kvs_txn_create ())) { flux_log_error (h, "txn_create"); goto done; } if (flux_kvs_txn_pack (txn, 0, key1, "I", nnodes) < 0) { flux_log_error (h, "update %s", key1); goto done; } if (flux_kvs_txn_pack (txn, 0, key2, "I", ntasks) < 0) { flux_log_error (h, "update %s", key2); goto done; } if (flux_kvs_txn_pack (txn, 0, key3, "I", walltime) < 0) { flux_log_error (h, "update %s", key3); goto done; } if (!(f = flux_kvs_commit (h, 0, txn)) || flux_future_get (f, NULL) < 0) { flux_log_error (h, "commit failed"); goto done; } flux_log (h, LOG_DEBUG, "job (%"PRId64") assigned new resources.", j); rc = 0; done: flux_future_destroy (f); flux_kvs_txn_destroy (txn); free (key1); free (key2); free (key3); return rc; }
static void *cron_event_create (flux_t *h, cron_entry_t *e, json_t *arg) { struct cron_event *ev; int nth = 0; int after = 0; double min_interval = 0.; const char *event; struct flux_match match = FLUX_MATCH_EVENT; if (json_unpack (arg, "{ s:s, s?i, s?i, s?F }", "topic", &event, "nth", &nth, "after", &after, "min_interval", &min_interval) < 0) { flux_log_error (h, "cron event: json_unpack"); errno = EPROTO; return NULL; } if ((ev = calloc (1, sizeof (*ev))) == NULL) { flux_log_error (h, "cron event: calloc"); return NULL; } /* Call subscribe per cron entry. Multiple event subscriptions are * allowed and each cron_event entry will have a corresponding * unsubscribe */ if (flux_event_subscribe (h, event) < 0) { flux_log_error (h, "cron_event: subscribe"); goto fail; } /* Save a copy of this handle for event unsubscribe at destroy */ ev->h = h; ev->nth = nth; ev->after = after; ev->min_interval = min_interval; ev->counter = 0; if ((ev->event = strdup (event)) == NULL) { flux_log_error (h, "cron event: strdup"); goto fail; } match.topic_glob = ev->event; ev->mh = flux_msg_handler_create (h, match, event_handler, (void *)e); if (!ev->mh) { flux_log_error (h, "cron_event: flux_msg_handler_create"); goto fail; } return (ev); fail: cron_event_destroy (ev); return (NULL); }
static int update_rdl_alloc (flux_t *h, int64_t j, json_object *o) { int i = 0; int rc = -1; int size = 0; json_object *ra_e = NULL; const char *key = NULL; zhash_t *rtab = NULL; int64_t *ncores = NULL; flux_kvs_txn_t *txn = NULL; flux_future_t *f = NULL; if (!(rtab = zhash_new ())) oom (); if (!Jget_ar_len (o, &size)) goto done; for (i=0; i < (int) size; ++i) { if (!Jget_ar_obj (o, i, &ra_e)) goto done; /* 'o' represents an array of per-node core count to use. * However, becasue the same rank can appear multiple times * in this array in emulation mode, update_hash_1ra is * used to determine the total core count per rank. */ if ( (rc = update_hash_1ra (h, j, ra_e, rtab)) < 0) goto done; } if (!(txn = flux_kvs_txn_create ())) { flux_log_error (h, "txn_create"); goto done; } FOREACH_ZHASH (rtab, key, ncores) { if ( (rc = flux_kvs_txn_pack (txn, 0, key, "I", *ncores)) < 0) { flux_log_error (h, "put %s", key); goto done; } } if (!(f = flux_kvs_commit (h, 0, txn)) || flux_future_get (f, NULL) < 0) { flux_log (h, LOG_ERR, "update_pdesc commit failed"); goto done; } rc = 0; done: flux_future_destroy (f); flux_kvs_txn_destroy (txn); zhash_destroy (&rtab); return rc; }
/* Reply to all queued requests. */ void flush_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = getctx (h); flux_msg_t *req; while ((req = zlist_pop (ctx->clog_requests))) { /* send clog response */ if (flux_respond (h, req, 0, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); } /* send flush response */ if (flux_respond (h, msg, 0, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); }
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; }
/* check: * Runs right after reactor calls poll(2). * Stop idle watcher, and send next alloc request, if available. */ static void check_cb (flux_reactor_t *r, flux_watcher_t *w, int revents, void *arg) { struct alloc_ctx *ctx = arg; struct job *job; flux_watcher_stop (ctx->idle); if (!ctx->ready) return; if (ctx->mode == SCHED_SINGLE && ctx->active_alloc_count > 0) return; if ((job = queue_first (ctx->inqueue))) { if (alloc_request (ctx, job) < 0) { flux_log_error (ctx->h, "alloc_request fatal error"); flux_reactor_stop_error (flux_get_reactor (ctx->h)); return; } queue_delete (ctx->inqueue, job, job->aux_queue_handle); job->aux_queue_handle = NULL; job->alloc_pending = 1; job->alloc_queued = 0; ctx->active_alloc_count++; if ((job->flags & FLUX_JOB_DEBUG)) (void)event_job_post_pack (ctx->event_ctx, job, "debug.alloc-request", NULL); } }
static int extract_raw_rdl_alloc (flux_t h, int64_t j, JSON jcb) { int i = 0; char *key; int64_t cores = 0; JSON ra = Jnew_ar (); bool processing = true; for (i=0; processing; ++i) { key = xasprintf ("lwj.%"PRId64".rank.%"PRId32".cores", j, i); if (kvs_get_int64 (h, key, &cores) < 0) { if (errno != EINVAL) flux_log_error (h, "extract %s", key); processing = false; } else { JSON elem = Jnew (); JSON o = Jnew (); Jadd_int64 (o, JSC_RDL_ALLOC_CONTAINED_NCORES, cores); json_object_object_add (elem, JSC_RDL_ALLOC_CONTAINED, o); json_object_array_add (ra, elem); } free (key); } json_object_object_add (jcb, JSC_RDL_ALLOC, ra); return 0; }
static int update_rdl (flux_t h, int64_t j, const char *rs) { int rc = -1; char *key = xasprintf ("lwj.%"PRId64".rdl", j); if (kvs_put_string (h, key, rs) < 0) flux_log_error (h, "update %s", key); else if (kvs_commit (h) < 0) flux_log_error (h, "commit failed"); else { flux_log (h, LOG_DEBUG, "job (%"PRId64") assigned new rdl.", j); rc = 0; } free (key); return rc; }
static void rmmod_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { struct sched_plugin_loader *sploader = arg; struct sched_plugin *plugin = sched_plugin_get (sploader); const char *json_str; char *name = NULL; int rc = -1; if (flux_request_decode (msg, NULL, &json_str) < 0) goto done; if (flux_rmmod_json_decode (json_str, &name) < 0) goto done; if (!plugin || strcmp (name, plugin->name) != 0) { errno = ENOENT; goto done; } sched_plugin_unload (sploader); flux_log (h, LOG_INFO, "%s unloaded", name); rc = 0; done: if (flux_respond (h, msg, rc < 0 ? errno : 0, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); if (name) free (name); }
int mod_main (flux_t *h, int argc, char **argv) { int saved_errno; flux_msg_handler_t **handlers = NULL; if (argc == 1 && !strcmp (argv[0], "--init-failure")) { flux_log (h, LOG_INFO, "aborting during init per test request"); errno = EIO; goto error; } if (!(modules = zhash_new ())) { errno = ENOMEM; goto error; } if (flux_get_rank (h, &rank) < 0) goto error; if (flux_msg_handler_addvec (h, htab, NULL, &handlers) < 0) goto error; if (flux_reactor_run (flux_get_reactor (h), 0) < 0) { flux_log_error (h, "flux_reactor_run"); goto error; } zhash_destroy (&modules); return 0; error: saved_errno = errno; flux_msg_handler_delvec (handlers); zhash_destroy (&modules); errno = saved_errno; return -1; }
static void lsmod_request_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { json_t *mods = NULL; if (flux_request_decode (msg, NULL, NULL) < 0) goto error; mods = module_list (); if (flux_respond_pack (h, msg, "{s:O}", "mods", mods) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); json_decref (mods); return; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); }
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; }
/* Handle a sched.free response. */ static void free_response_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { struct alloc_ctx *ctx = arg; flux_jobid_t id = 0; struct job *job; if (flux_response_decode (msg, NULL, NULL) < 0) goto teardown; if (flux_msg_unpack (msg, "{s:I}", "id", &id) < 0) goto teardown; if (!(job = queue_lookup_by_id (ctx->queue, id))) { flux_log_error (h, "sched.free-response: id=%llu not active", (unsigned long long)id); goto teardown; } if (!job->has_resources) { flux_log (h, LOG_ERR, "sched.free-response: id=%lld not allocated", (unsigned long long)id); errno = EINVAL; goto teardown; } job->free_pending = 0; if (event_job_post_pack (ctx->event_ctx, job, "free", NULL) < 0) goto teardown; return; teardown: interface_teardown (ctx, "free response error", errno); }
static int extract_raw_rdl_alloc (flux_t *h, int64_t j, json_object *jcb) { int i; json_object *ra = Jnew_ar (); bool processing = true; for (i=0; processing; ++i) { char *key = lwj_key (h, j, ".rank.%d.cores", i); flux_future_t *f = NULL; int64_t cores = 0; if (!key || !(f = flux_kvs_lookup (h, 0, key)) || flux_kvs_lookup_get_unpack (f, "I", &cores) < 0) { if (errno != EINVAL) flux_log_error (h, "extract %s", key); processing = false; } else { json_object *elem = Jnew (); json_object *o = Jnew (); Jadd_int64 (o, JSC_RDL_ALLOC_CONTAINED_NCORES, cores); json_object_object_add (elem, JSC_RDL_ALLOC_CONTAINED, o); json_object_array_add (ra, elem); } free (key); flux_future_destroy (f); } json_object_object_add (jcb, JSC_RDL_ALLOC, ra); return 0; }
/* KVS commit completed. * Respond to original request which was copied and passed as 'arg'. */ static void commit_continuation (flux_future_t *f, void *arg) { flux_t *h = flux_future_get_flux (f); flux_msg_t *msg = arg; if (flux_future_get (f, NULL) < 0) { if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); } else { if (flux_respond (h, msg, 0, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); } flux_msg_destroy (msg); flux_future_destroy (f); }
/* Initiate teardown. Clear any alloc/free requests, and clear * the alloc->ready flag to stop prep/check from allocating. */ static void interface_teardown (struct alloc_ctx *ctx, char *s, int errnum) { if (ctx->ready) { struct job *job; flux_log (ctx->h, LOG_DEBUG, "alloc: stop due to %s: %s", s, flux_strerror (errnum)); job = queue_first (ctx->queue); while (job) { /* jobs with alloc pending need to go back in the queue * so they will automatically send alloc again. */ if (job->alloc_pending) { assert (job->aux_queue_handle == NULL); if (queue_insert (ctx->inqueue, job, &job->aux_queue_handle) < 0) flux_log_error (ctx->h, "%s: queue_insert", __FUNCTION__); job->alloc_pending = 0; job->alloc_queued = 1; } /* jobs with free pending (much smaller window for this to be true) * need to be picked up again after 'hello'. */ job->free_pending = 0; job = queue_next (ctx->queue); } ctx->ready = false; ctx->active_alloc_count = 0; } }