729 lines
16 KiB
C
729 lines
16 KiB
C
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <stdlib.h>
|
|
#include <sys/socket.h>
|
|
|
|
#include "client.h"
|
|
#include "client_internal.h"
|
|
#include "controller.capnp.h"
|
|
#include "mylock.h"
|
|
|
|
#include "request.h"
|
|
#include "xce/types.h"
|
|
#include "xceapi.h"
|
|
#include "xcectx.h"
|
|
#include "xlist.h"
|
|
|
|
int xcecli_ctx_init(xcecli_ctx_t* c, xce_client_config_t* cfg)
|
|
{
|
|
api_ctx_t* ctx;
|
|
int rc;
|
|
|
|
if ((c == NULL) || (cfg == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (cfg->nmasters < 1) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ctx = (api_ctx_t*)calloc(1, sizeof(*ctx));
|
|
if (ctx == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ctx->conf = cfg;
|
|
rc = xce_ctx_init(&(ctx->ctx), ctx->conf->from, ctx->conf->key);
|
|
if (rc < 0) {
|
|
free(ctx);
|
|
return rc;
|
|
}
|
|
|
|
endpoint_init(&(ctx->ep), AF_INET, SOCK_STREAM, 0, 0);
|
|
|
|
/* set information for endpoint */
|
|
endpoint_set_peer(&(ctx->ep), &(ctx->ctx.myinfo));
|
|
|
|
xce_ctx_set_endpoint(&(ctx->ctx), &(ctx->ep));
|
|
|
|
*c = (void*)ctx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void xcecli_ctx_fini(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
if (ctx == NULL) {
|
|
return;
|
|
}
|
|
|
|
xce_ctx_fini(&(ctx->ctx));
|
|
endpoint_fini(&(ctx->ep));
|
|
|
|
free(ctx);
|
|
}
|
|
|
|
int xcecli_set_handler(xcecli_ctx_t c, xce_request_handler_t handler,
|
|
void* args)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if ((c == NULL) || (handler == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_ctx_set_handler(&(ctx->ctx), handler, args);
|
|
}
|
|
|
|
/*
|
|
* xcecli_set_reconnect_handler (task 4.1) — register the consumer rejoin hook
|
|
* the failover loop invokes after a transparent reconnect, before resuming the
|
|
* interrupted op. A NULL cb clears any previously registered hook (back to the
|
|
* pure-client no-op path). Stores cb+arg on the per-ctx failover state.
|
|
*/
|
|
int xcecli_set_reconnect_handler(xcecli_ctx_t c, xcecli_reconnect_cb cb,
|
|
void* arg)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ctx->failover.rejoin_cb = cb;
|
|
ctx->failover.rejoin_arg = arg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xcecli_wakeup(xcecli_ctx_t c, int status)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_wakeup(&(ctx->ctx), status);
|
|
}
|
|
|
|
int xcecli_try_wakeup(xcecli_ctx_t c, int status)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_try_wakeup(&(ctx->ctx), status);
|
|
}
|
|
|
|
int xcecli_start(xcecli_ctx_t c)
|
|
{
|
|
int rc;
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = endpoint_connect(&(ctx->ep), ctx->conf->masters[0],
|
|
ctx->conf->master_ports[0]);
|
|
if (rc < 0) {
|
|
endpoint_fini(&(ctx->ep));
|
|
return rc;
|
|
}
|
|
|
|
/* Initialize per-context failover state: sticky primary starts at
|
|
* masters[0] (the initial connect target above), retry tunables default
|
|
* to XCE_RETRY_DEFAULTS, and no rejoin hook is installed for pure clients.
|
|
*/
|
|
rc = mylock_init(&(ctx->failover.lock));
|
|
if (rc < 0) {
|
|
endpoint_fini(&(ctx->ep));
|
|
return rc;
|
|
}
|
|
ctx->failover.cur_master = 0;
|
|
ctx->failover.retry = XCE_RETRY_DEFAULTS;
|
|
ctx->failover.rejoin_cb = NULL;
|
|
ctx->failover.rejoin_arg = NULL;
|
|
|
|
rc = xce_ctx_start(&(ctx->ctx));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_stop(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
xce_ctx_stop(&(ctx->ctx));
|
|
endpoint_fini(&(ctx->ep));
|
|
mylock_fini(&(ctx->failover.lock));
|
|
|
|
return 0;
|
|
}
|
|
|
|
endpoint_t* xcecli_get_my_endpoint(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return &(ctx->ep);
|
|
}
|
|
|
|
xce_peerinfo_t* xcecli_get_myinfo(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return &(ctx->ctx.myinfo);
|
|
}
|
|
|
|
int xcecli_hello(xcecli_ctx_t c, char* msg)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_hello(&(ctx->ctx), msg));
|
|
}
|
|
|
|
int xcecli_nop(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Fire-and-forget: best-effort transport reconnect on a known-dead
|
|
* connection, then a single-shot send. No status classification, no
|
|
* no-primary backoff, no retry budget (task 5.2). */
|
|
return XCECLI_FF_CALL(ctx, xce_nop(&(ctx->ctx)));
|
|
}
|
|
|
|
int xcecli_heartbeat(xcecli_ctx_t c, int hb_interval)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Fire-and-forget: best-effort transport reconnect on a known-dead
|
|
* connection, then a single-shot send (task 5.2). A heartbeat must NEVER go
|
|
* through the no-primary backoff retry budget. */
|
|
return XCECLI_FF_CALL(ctx, xce_heartbeat(&(ctx->ctx), hb_interval));
|
|
}
|
|
|
|
int xcecli_shutdown(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_shutdown(&(ctx->ctx));
|
|
}
|
|
|
|
int xcecli_reslist(xcecli_ctx_t c, xce_resource_t*** res)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_reslist(&(ctx->ctx), res));
|
|
}
|
|
|
|
int xcecli_join(xcecli_ctx_t c, int role, hostattrs_t* attrs)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
if (ctx == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_join(&(ctx->ctx), role, attrs));
|
|
}
|
|
|
|
int xcecli_workerlist(xcecli_ctx_t c, xce_worker_t*** workers)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
if (ctx == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_workerlist(&(ctx->ctx), workers));
|
|
}
|
|
|
|
int xcecli_jobdispatch(xcecli_ctx_t c, xce_job_dispatch_t* info)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_jobdispatch(&(ctx->ctx), info));
|
|
}
|
|
|
|
int xcecli_jobsubmit(xcecli_ctx_t c, xce_job_submit_t* submit, uint64_t* jobid)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_jobsubmit(&(ctx->ctx), submit, jobid));
|
|
}
|
|
|
|
int xcecli_joblist(xcecli_ctx_t c, xce_job_t*** jobs)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_joblist(&(ctx->ctx), jobs));
|
|
}
|
|
|
|
int xcecli_clusterconf(xcecli_ctx_t c, xce_clusterconf_t** conf)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_clusterconf(&(ctx->ctx), conf));
|
|
}
|
|
|
|
int xcecli_notify_jobfinish(xcecli_ctx_t c, xce_jobfinish_t* jfinish)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_jobFinishInfo,
|
|
.data = {
|
|
.finishinfo = jfinish
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (jfinish == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_update_resvals(xcecli_ctx_t c, int nres, xce_resval_t** vals)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (vals == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_update_resvals(&(ctx->ctx), nres, vals));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_update_jusage(xcecli_ctx_t c, uint64_t jobid, int npids, int* pids,
|
|
int npgids, int* pgids, int nusage,
|
|
xce_rusage_t** usages)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (jobid == 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(
|
|
ctx, /*is_write=*/true,
|
|
xce_update_jusage(&(ctx->ctx), jobid, npids, pids, npgids, pgids, nusage,
|
|
usages));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_resval(xcecli_ctx_t c, char* host, char* res, xce_resval_t*** val)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (res == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_resval(&(ctx->ctx), host, res, val));
|
|
}
|
|
|
|
int xcecli_notify(xcecli_ctx_t c, xce_notify_data_t* data)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (data == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Fire-and-forget chokepoint: every thin notify_* wrapper delegates
|
|
* here, so applying the best-effort reconnect at this single point covers
|
|
* them all without double-wrapping/double-locking. Best-effort transport
|
|
* reconnect on a known-dead connection, then a single-shot send (task
|
|
* 5.2). */
|
|
return XCECLI_FF_CALL(ctx, xce_notify(&(ctx->ctx), data));
|
|
}
|
|
|
|
int xcecli_notify_jobstart(xcecli_ctx_t c, job_pidinfo_t* pidinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_jobPidInfo,
|
|
.data = {
|
|
.pidinfo = pidinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (pidinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_jobfail(xcecli_ctx_t c, job_failinfo_t* failinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_jobFailInfo,
|
|
.data = {
|
|
.failinfo = failinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (failinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_jobctrl(xcecli_ctx_t c, xce_jobctrl_t* ctrlinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (ctrlinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_jobctrl(&(ctx->ctx), ctrlinfo));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_notify_jobstop(xcecli_ctx_t c, uint64_t jobid)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_stoppedJob,
|
|
.data = {
|
|
.stopped_job = jobid
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (jobid == 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_jobresume(xcecli_ctx_t c, uint64_t jobid)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_resumedJob,
|
|
.data = {
|
|
.resumed_job = jobid
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (jobid == 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_jobchkpt(xcecli_ctx_t c, uint64_t jobid, char* info)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_ckptinfo_t ckptinfo = {
|
|
.jobid = jobid,
|
|
.ckptinfo = info
|
|
};
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_ckptinfo,
|
|
.data = {
|
|
.ckptinfo = &ckptinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (jobid == 0) || (info == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_jobpostdone(xcecli_ctx_t c, uint64_t jobid)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_postDoneJob,
|
|
.data = {
|
|
.pdone_job = jobid
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (jobid == 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_queuectrl(xcecli_ctx_t c, xce_queuectrl_t* ctrlinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (ctrlinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_queuectrl(&(ctx->ctx), ctrlinfo));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_hostctrl(xcecli_ctx_t c, xce_hostctrl_t* ctrlinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (ctrlinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_hostctrl(&(ctx->ctx), ctrlinfo));
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_runtask(xcecli_ctx_t c, xce_taskrun_t* info)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (info == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
info->clientidx = -1; /* this field will be used by
|
|
* controller to trace back
|
|
* client
|
|
*/
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_runtask(&(ctx->ctx), info));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_notify_taskstart(xcecli_ctx_t c, xce_task_pidinfo_t* pidinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_taskPidInfo,
|
|
.data = {
|
|
.taskinfo = pidinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (pidinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_taskfail(xcecli_ctx_t c, xce_task_failinfo_t* failinfo)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_taskFailInfo,
|
|
.data = {
|
|
.taskfailinfo = failinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (failinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
int xcecli_notify_taskfinish(xcecli_ctx_t c, xce_task_finish_t* info)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
/* clang-format off */
|
|
xce_notify_data_t data = {
|
|
.event = NotifyData_data_taskFinish,
|
|
.data = {
|
|
.taskfinish = info
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((c == NULL) || (info == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xcecli_notify(ctx, &data);
|
|
}
|
|
|
|
void xcecli_block_tasks(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
if (c == NULL) {
|
|
return;
|
|
}
|
|
|
|
xce_block_tasks(&(ctx->ctx));
|
|
}
|
|
|
|
void xcecli_unblock_tasks(xcecli_ctx_t c)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
|
|
if (c == NULL) {
|
|
return;
|
|
}
|
|
|
|
xce_unblock_tasks(&(ctx->ctx));
|
|
}
|
|
|
|
int xcecli_set_pend_reason(xcecli_ctx_t c, xce_preason_set_t* reasons)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (reasons == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_set_pend_reason(&(ctx->ctx), reasons));
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_clear_reason(xcecli_ctx_t c, int njobs, uint64_t* jobs)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
/* clang-format off */
|
|
xce_clear_reason_t reason = {
|
|
.njobs = njobs,
|
|
.jobs = jobs
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ctx == NULL) || ((njobs > 0) && (jobs == NULL))) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (njobs == 0) {
|
|
return 0;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/true,
|
|
xce_clear_reason(&(ctx->ctx), &reason));
|
|
return rc;
|
|
}
|
|
|
|
int xcecli_jobinfo(xcecli_ctx_t c, uint64_t jobid, xce_job_t** job)
|
|
{
|
|
api_ctx_t* ctx = (api_ctx_t*)c;
|
|
int rc;
|
|
|
|
if ((ctx == NULL) || (job == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = XCECLI_FAILOVER_CALL(ctx, /*is_write=*/false,
|
|
xce_jobinfo(&(ctx->ctx), jobid, job));
|
|
return rc;
|
|
}
|