/* 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__); }
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 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__); }
/* 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); }
/* sched-hello: * Scheduler obtains a list of jobs that have resources allocated. */ static void hello_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { struct alloc_ctx *ctx = arg; struct job *job; json_t *o = NULL; json_t *jobid; if (flux_request_decode (msg, NULL, NULL) < 0) goto error; flux_log (h, LOG_DEBUG, "scheduler: hello"); if (!(o = json_array ())) goto nomem; job = queue_first (ctx->queue); while (job) { if (job->has_resources) { if (!(jobid = json_integer (job->id))) goto nomem; if (json_array_append_new (o, jobid) < 0) { json_decref (jobid); goto nomem; } } job = queue_next (ctx->queue); } if (flux_respond_pack (h, msg, "{s:O}", "alloc", o) < 0) flux_log_error (h, "%s: flux_respond_pack", __FUNCTION__); /* Restart any free requests that might have been interrupted * when scheduler was last unloaded. */ job = queue_first (ctx->queue); while (job) { if (event_job_action (ctx->event_ctx, job) < 0) flux_log_error (h, "%s: event_job_action", __FUNCTION__); job = queue_next (ctx->queue); } json_decref (o); return; nomem: errno = ENOMEM; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); json_decref (o); }
static void rmmod_request_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { const char *name; if (flux_request_unpack (msg, NULL, "{s:s}", "name", &name) < 0) goto error; if (!zhash_lookup (modules, name)) { errno = ENOENT; goto error; } zhash_delete (modules, name); flux_log (h, LOG_DEBUG, "rmmod %s", name); if (flux_respond (h, msg, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); return; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); }
void list_handle_request (flux_t *h, struct queue *queue, const flux_msg_t *msg) { int max_entries; json_t *jobs; json_t *attrs; if (flux_request_unpack (msg, NULL, "{s:i s:o}", "max_entries", &max_entries, "attrs", &attrs) < 0) goto error; if (!(jobs = list_job_array (queue, max_entries, attrs))) goto error; if (flux_respond_pack (h, msg, "{s:O}", "jobs", jobs) < 0) flux_log_error (h, "%s: flux_respond_pack", __FUNCTION__); json_decref (jobs); return; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); }
static void ping_request_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { const char *json_str; char *route_str = NULL; char *full_route_str = NULL; char *resp_str = NULL; uint32_t rank, userid, rolemask; if (flux_request_decode (msg, NULL, &json_str) < 0) goto error; if (flux_msg_get_rolemask (msg, &rolemask) < 0) goto error; if (flux_msg_get_userid (msg, &userid) < 0) goto error; if (!(route_str = flux_msg_get_route_string (msg))) goto error; if (flux_get_rank (h, &rank) < 0) goto error; if (asprintf (&full_route_str, "%s!%u", route_str, rank) < 0) { errno = ENOMEM; goto error; } if (!(resp_str = make_json_response_payload (json_str, full_route_str, userid, rolemask))) { goto error; } if (flux_respond (h, msg, resp_str) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); free (route_str); free (full_route_str); free (resp_str); return; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); free (route_str); free (full_route_str); free (resp_str); }
static void insmod_request_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { const char *path; json_t *args; size_t index; json_t *value; char *argz = NULL; size_t argz_len = 0; module_t *m = NULL; error_t e; if (flux_request_unpack (msg, NULL, "{s:s s:o}", "path", &path, "args", &args) < 0) goto error; if (!json_is_array (args)) goto proto; json_array_foreach (args, index, value) { if (!json_is_string (value)) goto proto; if ((e = argz_add (&argz, &argz_len, json_string_value (value)))) { errno = e; goto error; } } if (!(m = module_create (path, argz, argz_len))) goto error; flux_log (h, LOG_DEBUG, "insmod %s", m->name); if (flux_respond (h, msg, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); free (argz); return; proto: errno = EPROTO; error: if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); free (argz); }
void store_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { sqlite_ctx_t *ctx = arg; const void *data; int size, hash_len; uint8_t hash[BLOBREF_MAX_DIGEST_SIZE]; char blobref[BLOBREF_MAX_STRING_SIZE] = "-"; int uncompressed_size = -1; int rc = -1; int old_state; //delay cancellation to ensure lock-correctness in sqlite pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state); if (flux_request_decode_raw (msg, NULL, &data, &size) < 0) { flux_log_error (h, "store: request decode failed"); goto done; } if (size > ctx->blob_size_limit) { errno = EFBIG; goto done; } if (blobref_hash (ctx->hashfun, (uint8_t *)data, size, blobref, sizeof (blobref)) < 0) goto done; if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0) goto done; if (size >= compression_threshold) { int r; int out_len = LZ4_compressBound(size); if (ctx->lzo_bufsize < out_len && grow_lzo_buf (ctx, out_len) < 0) goto done; r = LZ4_compress_default (data, ctx->lzo_buf, size, out_len); if (r == 0) { errno = EINVAL; goto done; } uncompressed_size = size; size = r; data = ctx->lzo_buf; } if (sqlite3_bind_text (ctx->store_stmt, 1, (char *)hash, hash_len, SQLITE_STATIC) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding key"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_bind_int (ctx->store_stmt, 2, uncompressed_size) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding size"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_bind_blob (ctx->store_stmt, 3, data, size, SQLITE_STATIC) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding data"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_step (ctx->store_stmt) != SQLITE_DONE && sqlite3_errcode (ctx->db) != SQLITE_CONSTRAINT) { log_sqlite_error (ctx, "store: executing stmt"); set_errno_from_sqlite_error (ctx); goto done; } rc = 0; done: if (rc < 0) { if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "store: flux_respond_error"); } else { if (flux_respond_raw (h, msg, blobref, strlen (blobref) + 1) < 0) flux_log_error (h, "store: flux_respond_raw"); } (void) sqlite3_reset (ctx->store_stmt); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state); }
void load_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { sqlite_ctx_t *ctx = arg; const char *blobref = "-"; int blobref_size; uint8_t hash[BLOBREF_MAX_DIGEST_SIZE]; int hash_len; const void *data = NULL; int size = 0; int uncompressed_size; int rc = -1; int old_state; //delay cancellation to ensure lock-correctness in sqlite pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state); if (flux_request_decode_raw (msg, NULL, (const void **)&blobref, &blobref_size) < 0) { flux_log_error (h, "load: request decode failed"); goto done; } if (!blobref || blobref[blobref_size - 1] != '\0') { errno = EPROTO; flux_log_error (h, "load: malformed blobref"); goto done; } if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0) { errno = ENOENT; flux_log_error (h, "load: unexpected foreign blobref"); goto done; } if (sqlite3_bind_text (ctx->load_stmt, 1, (char *)hash, hash_len, SQLITE_STATIC) != SQLITE_OK) { log_sqlite_error (ctx, "load: binding key"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_step (ctx->load_stmt) != SQLITE_ROW) { //log_sqlite_error (ctx, "load: executing stmt"); errno = ENOENT; goto done; } size = sqlite3_column_bytes (ctx->load_stmt, 0); if (sqlite3_column_type (ctx->load_stmt, 0) != SQLITE_BLOB && size > 0) { flux_log (h, LOG_ERR, "load: selected value is not a blob"); errno = EINVAL; goto done; } data = sqlite3_column_blob (ctx->load_stmt, 0); if (sqlite3_column_type (ctx->load_stmt, 1) != SQLITE_INTEGER) { flux_log (h, LOG_ERR, "load: selected value is not an integer"); errno = EINVAL; goto done; } uncompressed_size = sqlite3_column_int (ctx->load_stmt, 1); if (uncompressed_size != -1) { if (ctx->lzo_bufsize < uncompressed_size && grow_lzo_buf (ctx, uncompressed_size) < 0) goto done; int r = LZ4_decompress_safe (data, ctx->lzo_buf, size, uncompressed_size); if (r < 0) { errno = EINVAL; goto done; } if (r != uncompressed_size) { flux_log (h, LOG_ERR, "load: blob size mismatch"); errno = EINVAL; goto done; } data = ctx->lzo_buf; size = uncompressed_size; } rc = 0; done: if (rc < 0) { if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "load: flux_respond_error"); } else { if (flux_respond_raw (h, msg, data, size) < 0) flux_log_error (h, "load: flux_respond_raw"); } (void )sqlite3_reset (ctx->load_stmt); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state); }