merge job rusage and pending reason support

This commit is contained in:
Rongsong Shen 2025-12-16 14:36:28 +08:00
parent 30824ae5ea
commit cb0c7fe9e7
82 changed files with 4280 additions and 2561 deletions

View file

@ -178,6 +178,28 @@ int xcecli_hello(xcecli_ctx_t c, char* msg)
return 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;
}
return 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;
}
return xce_heartbeat(&(ctx->ctx), hb_interval);
}
int xcecli_shutdown(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
@ -589,3 +611,52 @@ void xcecli_unblock_tasks(xcecli_ctx_t c)
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 = 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 = 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 = xce_jobinfo(&(ctx->ctx), jobid, job);
return rc;
}

192
src/lib/delay.c Normal file
View file

@ -0,0 +1,192 @@
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "delay.h"
#include "utils.h"
static void* delay_worker(void* args)
{
delaymgr_t* mgr = (delaymgr_t*)args;
while (1) {
ordq_item_t* it;
delay_task_t* t;
time_t now;
pthread_testcancel();
sleep(mgr->precision);
it = ordq_peek(&(mgr->tasks));
if (it == NULL) {
continue;
}
now = time(NULL);
if ((time_t)it->key > now) {
continue;
}
it = ordq_get(&(mgr->tasks));
t = (delay_task_t*)it->data;
mgr->runner_fn(t->entry, t->args);
if (t->runcount > 0) {
t->runcount--;
}
if (t->runcount == 0) {
FREEUP(t);
} else {
time_t nextrun = now + t->run_period;
/* put back to taskq as it need to be run again */
ordq_put(&(mgr->tasks), (void*)nextrun, t);
}
FREEUP(it);
}
return NULL;
}
static int time_cmp(time_t k1, time_t k2)
{
if (k1 > k2) {
return 1;
}
if (k1 == k2) {
return 0;
}
return -1;
}
static void delay_task_killer(delay_task_t* t)
{
if (t == NULL) {
return;
}
FREEUP(t);
}
static int default_runner_fn(delay_task_entry_fn_t entry, void* arg)
{
if (entry == NULL) {
return 0;
}
return entry(arg);
}
int delaymgr_init(delaymgr_t* mgr, int precision, task_run_fn_t runner_fn)
{
if ((mgr == NULL) || (precision <= 0)) {
return -EINVAL;
}
if (runner_fn == NULL) {
runner_fn = default_runner_fn;
}
mgr->precision = precision;
mgr->running = 0;
mgr->runner_fn = runner_fn;
mgr->worker = 0;
ordq_init(&(mgr->tasks), (ordq_data_killer_t)delay_task_killer,
(ordq_cmp_fn_t)time_cmp);
return 0;
}
void delaymgr_stop(delaymgr_t* mgr)
{
int rc;
if (mgr == NULL) {
return;
}
if (!(mgr->running)) {
return;
}
if (mgr->worker != 0) {
rc = pthread_cancel(mgr->worker);
if (rc == 0) {
void* res = NULL;
pthread_join(mgr->worker, &res);
if (res == PTHREAD_CANCELED) {
mgr->worker = 0;
}
}
}
return;
}
void delaymgr_fini(delaymgr_t* mgr)
{
if (mgr == NULL) {
return;
}
if (mgr->running) {
delaymgr_stop(mgr);
}
ordq_fini(&(mgr->tasks));
}
int delaymgr_start(delaymgr_t* mgr)
{
int rc;
if (mgr == NULL) {
return -EINVAL;
}
rc = pthread_create(&(mgr->worker), NULL, &delay_worker, mgr);
if (rc == 0) {
mgr->running = 1;
} else {
SET_ERROR(errno);
return -errno;
}
return 0;
}
int delay_task(delaymgr_t* mgr, int delay, int runcount,
delay_task_entry_fn_t entry, void* args)
{
delay_task_t* t;
time_t now = time(NULL);
time_t ts_nextrun;
if ((mgr == NULL) || (delay <= 0) || (entry == NULL)) {
return -EINVAL;
}
t = (delay_task_t*)calloc(1, sizeof(*t));
if (t == NULL) {
return -ENOMEM;
}
ts_nextrun = now + delay;
t->runcount = runcount;
t->run_period = delay;
t->entry = entry;
t->args = args;
return ordq_put(&(mgr->tasks), (void*)ts_nextrun, t);
}

View file

@ -27,7 +27,10 @@ libxce_src = [ gen_srcs[0],
'xstring.c',
'zarray.c',
'wrap.c',
'idgen.c'
'idgen.c',
'delay.c',
'ordq.c',
'preason.c'
]
incdir = include_directories('../include')
@ -61,7 +64,10 @@ libxce_test_src = ['testsuite/test.c',
'testsuite/test_xstring.c',
'testsuite/test_zarray.c',
'testsuite/test_config.c',
'testsuite/test_idgen.c'
'testsuite/test_idgen.c',
'testsuite/test_delay.c',
'testsuite/test_ordq.c',
'testsuite/test_preason.c'
]
libxce_test_deps = [libxce_deps, unity_dep, libxce_dep]

View file

@ -161,6 +161,30 @@ int cbuf_get(cbuf_t* b, void* it)
return 0;
}
int cbuf_tryget(cbuf_t* b, void* it)
{
int rc = 0;
if ((b == NULL) || (it == NULL)) {
return -EINVAL;
}
pthread_mutex_lock(&(b->mutex));
if (b->len == 0) {
rc = -EAGAIN;
} else {
memcpy(it, (void*)((char*)b->data) + b->isize * b->head, b->isize);
b->head = (b->head + 1) % b->ncap;
b->len--;
pthread_cond_signal(&(b->condput));
}
pthread_mutex_unlock(&(b->mutex));
return rc;
}
int my_rwlock_init(my_rwlock_t* l)
{
if (l == NULL) {

View file

@ -9,6 +9,7 @@
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
#include "dataq.h"
@ -355,6 +356,7 @@ static int handle_input(endpoint_t* ep)
}
io_fsm_start(&(ep->fsm_in), pkt);
ep->ts_last_in = time(NULL);
}
rc = io_fsm_perform(&(ep->fsm_in));
@ -388,6 +390,8 @@ static int handle_output(endpoint_t* ep)
if (rc < 0) {
return rc;
}
ep->ts_last_out = time(NULL);
}
rc = io_fsm_perform(&(ep->fsm_out));

107
src/lib/ordq.c Normal file
View file

@ -0,0 +1,107 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "mylock.h"
#include "ordq.h"
int ordq_init(ordq_t* q, ordq_data_killer_t killer, ordq_cmp_fn_t cmp)
{
if ((q == NULL) || (cmp == NULL)) {
return -EINVAL;
}
mylock_init(&(q->lock));
q->head = NULL;
q->killer = killer;
q->cmp = cmp;
return 0;
}
static int ordq_put_(ordq_t* q, ordq_item_t* it)
{
ordq_item_t** p = &(q->head);
while ((*p) != NULL) {
if (q->cmp((*p)->key, it->key) > 0) {
/* we found the location to insert */
break;
}
p = &((*p)->next);
}
it->next = *p;
*p = it;
return 0;
}
int ordq_put(ordq_t* q, ordkey_t key, void* data)
{
int rc = 0;
ordq_item_t* it;
it = (ordq_item_t*)calloc(1, sizeof(*it));
if (it == NULL) {
return -ENOMEM;
}
it->key = key;
it->data = data;
mylock_lock(&(q->lock));
rc = ordq_put_(q, it);
mylock_unlock(&(q->lock));
return rc;
}
void ordq_fini(ordq_t* q)
{
ordq_item_t* p = q->head;
while (p != NULL) {
ordq_item_t* p1 = p->next;
if (p->data != NULL) {
q->killer(p->data);
}
p->data = NULL;
free(p);
p = p1;
}
mylock_fini(&(q->lock));
}
ordq_item_t* ordq_get(ordq_t* q)
{
ordq_item_t* it;
mylock_lock(&(q->lock));
it = q->head;
if (it != NULL) {
q->head = it->next;
}
mylock_unlock(&(q->lock));
return it;
}
ordq_item_t* ordq_peek(ordq_t* q)
{
ordq_item_t* it = NULL;
mylock_lock(&(q->lock));
it = q->head;
mylock_unlock(&(q->lock));
return it;
}

151
src/lib/preason.c Normal file
View file

@ -0,0 +1,151 @@
#include <errno.h>
#include "preason.h"
#include "utils.h"
void erase_job_preason(xce_job_preason_t* reasons)
{
if (reasons == NULL) {
return;
}
if (reasons->host_based_reasons != NULL) {
int i;
for (i = 0; i < reasons->nhost_reasons; i++) {
if (reasons->host_based_reasons[i] != NULL) {
FREEUP(reasons->host_based_reasons[i]->host);
FREEUP(reasons->host_based_reasons[i]);
}
}
FREEUP(reasons->host_based_reasons);
reasons->nhost_reasons = 0;
}
if (reasons->res_based_reasons != NULL) {
int i;
for (i = 0; i < reasons->nres_reasons; i++) {
if (reasons->res_based_reasons[i] == NULL) {
continue;
}
FREEUP(reasons->res_based_reasons[i]->resource);
FREEUP(reasons->res_based_reasons[i]->host);
FREEUP(reasons->res_based_reasons[i]);
}
FREEUP(reasons->res_based_reasons);
reasons->nres_reasons = 0;
}
reasons->main_reason = 0;
}
static int add_host_preason(xce_job_preason_t* reasons, int code, char* host)
{
xce_host_reason_t** p;
xce_host_reason_t* p1;
char* h;
int count;
if ((reasons == NULL) || (host == NULL)) {
return -EINVAL;
}
h = strdup(host);
if (h == NULL) {
return -ENOMEM;
}
p1 = (xce_host_reason_t*)calloc(1, sizeof(*p1));
if (p1 == NULL) {
FREEUP(h);
return -ENOMEM;
}
p1->reason = code;
p1->host = h;
count = reasons->nhost_reasons;
p = (xce_host_reason_t**)realloc(reasons->host_based_reasons,
(count + 1) * sizeof(xce_host_reason_t*));
if (p == NULL) {
FREEUP(h);
FREEUP(p1);
return -ENOMEM;
}
reasons->host_based_reasons = p;
reasons->host_based_reasons[count] = p1;
reasons->nhost_reasons++;
return reasons->nhost_reasons;
}
static int add_res_preason(xce_job_preason_t* reasons, int code, char* host,
char* res)
{
xce_res_reason_t** p;
char* h;
char* r;
int count;
xce_res_reason_t* p1;
if ((reasons == NULL) || (host == NULL) || (res == NULL)) {
return -EINVAL;
}
h = strdup(host);
r = strdup(res);
p1 = (xce_res_reason_t*)calloc(1, sizeof(*p1));
if ((h == NULL) || (r == NULL) || (p1 == NULL)) {
FREEUP(h);
FREEUP(r);
FREEUP(p1);
return -ENOMEM;
}
p1->host = h;
p1->resource = r;
p1->reason = code;
count = reasons->nres_reasons;
p = (xce_res_reason_t**)realloc(reasons->res_based_reasons,
(count + 1) * sizeof(*p));
if (p == NULL) {
FREEUP(h);
FREEUP(r);
FREEUP(p1);
return -ENOMEM;
}
reasons->res_based_reasons = p;
reasons->res_based_reasons[count] = p1;
reasons->nres_reasons++;
return reasons->nres_reasons;
}
int add_job_preason(xce_job_preason_t* reasons, int code, char* host, char* res)
{
int rc = 0;
if ((host == NULL) && (res == NULL)) {
/* set main reason */
erase_job_preason(reasons);
reasons->main_reason = code;
} else if (res == NULL) {
/* set host reason */
rc = add_host_preason(reasons, code, host);
} else {
/* set resource reason */
rc = add_res_preason(reasons, code, host, res);
}
return rc;
}

View file

@ -2,6 +2,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "mylock.h"
@ -850,3 +851,41 @@ int xce_runtask_req(endpoint_t* ep, xce_taskrun_t* runinfo)
return xce_request(ep, &request);
}
int xce_set_pend_reason_req(endpoint_t* ep, xce_preason_set_t* reasons)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_setpreason,
.body_which = Request_body_preasonmsg,
.body = {
.preasonmsg = reasons
}
};
/* clang-format on */
if ((ep == NULL) || (reasons == NULL)) {
return -EINVAL;
}
return xce_request(ep, &request);
}
int xce_clear_reason_req(endpoint_t* ep, xce_clear_reason_t* reason)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_clrpreason,
.body_which = Request_body_clrpreasonmsg,
.body = {
.clrpreasonmsg = reason
}
};
/* clang-format on */
if ((ep == NULL) || (reason == NULL)) {
return -EINVAL;
}
return xce_request(ep, &request);
}

View file

@ -12,6 +12,9 @@ extern void test_error(void);
extern void test_utils(void);
extern void test_config(void);
extern void test_idgen(void);
extern void test_preason(void);
extern void test_ordq(void);
extern void test_delay(void);
void setUp(void) { return; }
@ -28,6 +31,9 @@ int main(int argc, char* argv[])
test_xstrings();
test_error();
test_utils();
test_preason();
test_ordq();
test_delay();
return UNITY_END();
}

View file

@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "delay.h"
#include "unity.h"
static int delay_work(void* arg)
{
time_t now;
int* pcount = (int*)arg;
now = time(NULL);
(*pcount)++;
printf("delay task run at %ld\n", now);
return 0;
}
static void test_delay1()
{
delaymgr_t mgr;
int count = 0;
int runcount = 15;
int delay_period = 2;
time_t t_start = time(NULL);
delaymgr_init(&mgr, 1, NULL);
delaymgr_start(&mgr);
delay_task(&mgr, delay_period, runcount, (delay_task_entry_fn_t)delay_work,
&count);
while (1) {
time_t now = time(NULL);
if (now - t_start > (runcount + 2) * delay_period) {
break;
}
sleep(5);
}
TEST_ASSERT_TRUE(count == runcount);
delaymgr_fini(&mgr);
return;
}
void test_delay(void)
{
printf("\n>> delay test\n\n");
RUN_TEST(test_delay1);
}

View file

@ -0,0 +1,82 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ordq.h"
#include "unity.h"
#include "utils.h"
static int long_cmp(ordkey_t k1, ordkey_t k2)
{
if ((long)k1 < (long)k2) {
return -1;
} else if ((long)k1 > (long)k2) {
return 1;
}
return 0;
}
static void test_ordq_get(void)
{
int rc;
ordq_t q;
ordq_item_t* it;
int keys[8] = { 9, 8, 1, 4, 7, 2, 6, 2 };
int val[8] = { 1, 2, 2, 4, 6, 7, 8, 9 };
int i;
rc = ordq_init(&q, NULL, (ordq_cmp_fn_t)long_cmp);
TEST_ASSERT_TRUE(rc >= 0);
for (i = 0; i < 8; i++) {
ordq_put(&q, mk_ordkey(keys[i]), (void*)NULL);
}
for (i = 0; i < 8; i++) {
it = ordq_get(&q);
TEST_ASSERT_TRUE((it != NULL) && (it->key == mk_ordkey(val[i])));
free(it);
}
ordq_fini(&q);
return;
}
static void test_ordq_peek(void)
{
int rc;
ordq_t q;
ordq_item_t* it;
int keys[8] = { 9, 8, 1, 4, 7, 2, 6, 2 };
int val[8] = { 1, 2, 2, 4, 6, 7, 8, 9 };
int i;
rc = ordq_init(&q, NULL, (ordq_cmp_fn_t)long_cmp);
TEST_ASSERT_TRUE(rc >= 0);
for (i = 0; i < 8; i++) {
ordq_put(&q, mk_ordkey(keys[i]), (void*)NULL);
}
for (i = 0; i < 8; i++) {
it = ordq_peek(&q); /* ordq_peek() will not remove item from q */
TEST_ASSERT_TRUE((it != NULL) && (it->key == mk_ordkey(val[0])));
}
ordq_fini(&q);
return;
}
void test_ordq(void)
{
printf("\n>> ordq test\n\n");
RUN_TEST(test_ordq_get);
RUN_TEST(test_ordq_peek);
}

View file

@ -0,0 +1,168 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preason.h"
#include "unity.h"
static void test_main_reason()
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, NULL, NULL);
TEST_ASSERT_TRUE(reason.main_reason == 1);
TEST_ASSERT_TRUE((reason.nhost_reasons == 0)
&& (reason.host_based_reasons == NULL));
TEST_ASSERT_TRUE((reason.nres_reasons == 0)
&& (reason.res_based_reasons == NULL));
}
static void test_add_host_reason(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", NULL);
TEST_ASSERT_TRUE(reason.main_reason == 0);
TEST_ASSERT_TRUE((reason.nhost_reasons == 1)
&& (reason.host_based_reasons != NULL)
&& (reason.host_based_reasons[0] != NULL));
TEST_ASSERT_TRUE(
(reason.host_based_reasons[0]->reason == 1)
&& (strcmp(reason.host_based_reasons[0]->host, "h1") == 0));
TEST_ASSERT_TRUE((reason.nres_reasons == 0)
&& (reason.res_based_reasons == NULL));
erase_job_preason(&reason);
}
static void test_add_res_reason(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", "res1");
TEST_ASSERT_TRUE(reason.main_reason == 0);
TEST_ASSERT_TRUE((reason.nres_reasons == 1)
&& (reason.res_based_reasons != NULL)
&& (reason.res_based_reasons[0] != NULL));
TEST_ASSERT_TRUE(
(reason.res_based_reasons[0]->reason == 1)
&& (strcmp(reason.res_based_reasons[0]->host, "h1") == 0)
&& (strcmp(reason.res_based_reasons[0]->resource, "res1") == 0));
TEST_ASSERT_TRUE((reason.nhost_reasons == 0)
&& (reason.host_based_reasons == NULL));
erase_job_preason(&reason);
}
static void test_add_res_host_reason(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", "res1");
add_job_preason(&reason, 2, "h1", NULL);
TEST_ASSERT_TRUE(reason.main_reason == 0);
TEST_ASSERT_TRUE((reason.nres_reasons == 1)
&& (reason.res_based_reasons != NULL)
&& (reason.res_based_reasons[0] != NULL));
TEST_ASSERT_TRUE(
(reason.res_based_reasons[0]->reason == 1)
&& (strcmp(reason.res_based_reasons[0]->host, "h1") == 0)
&& (strcmp(reason.res_based_reasons[0]->resource, "res1") == 0));
TEST_ASSERT_TRUE((reason.nhost_reasons == 1)
&& (reason.host_based_reasons != NULL)
&& (reason.host_based_reasons[0] != NULL));
TEST_ASSERT_TRUE(
(reason.host_based_reasons[0]->reason == 2)
&& (strcmp(reason.host_based_reasons[0]->host, "h1") == 0));
erase_job_preason(&reason);
}
static void test_add_main_reset_other(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", "res1");
add_job_preason(&reason, 2, "h1", NULL);
add_job_preason(&reason, 3, NULL, NULL);
TEST_ASSERT_TRUE(reason.main_reason == 3);
TEST_ASSERT_TRUE((reason.nres_reasons == 0)
&& (reason.res_based_reasons == NULL));
TEST_ASSERT_TRUE((reason.nhost_reasons == 0)
&& (reason.host_based_reasons == NULL));
erase_job_preason(&reason);
}
static void test_add_more_host_reason(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", NULL);
add_job_preason(&reason, 2, "h2", NULL);
TEST_ASSERT_TRUE(reason.main_reason == 0);
TEST_ASSERT_TRUE((reason.nhost_reasons == 2)
&& (reason.host_based_reasons != NULL)
&& (reason.host_based_reasons[0] != NULL)
&& (reason.host_based_reasons[1] != NULL));
TEST_ASSERT_TRUE(
(reason.host_based_reasons[0]->reason == 1)
&& (strcmp(reason.host_based_reasons[0]->host, "h1") == 0)
&& (reason.host_based_reasons[1]->reason == 2)
&& (strcmp(reason.host_based_reasons[1]->host, "h2") == 0));
TEST_ASSERT_TRUE((reason.nres_reasons == 0)
&& (reason.res_based_reasons == NULL));
erase_job_preason(&reason);
}
static void test_add_more_res_reason(void)
{
xce_job_preason_t reason;
memset(&reason, 0x0, sizeof(reason));
add_job_preason(&reason, 1, "h1", "res1");
add_job_preason(&reason, 2, "h2", "res2");
TEST_ASSERT_TRUE(reason.main_reason == 0);
TEST_ASSERT_TRUE((reason.nres_reasons == 2)
&& (reason.res_based_reasons != NULL)
&& (reason.res_based_reasons[0] != NULL)
&& (reason.res_based_reasons[1] != NULL));
TEST_ASSERT_TRUE(
(reason.res_based_reasons[0]->reason == 1)
&& (strcmp(reason.res_based_reasons[0]->host, "h1") == 0)
&& (strcmp(reason.res_based_reasons[0]->resource, "res1") == 0));
TEST_ASSERT_TRUE(
(reason.res_based_reasons[1]->reason == 2)
&& (strcmp(reason.res_based_reasons[1]->host, "h2") == 0)
&& (strcmp(reason.res_based_reasons[1]->resource, "res2") == 0));
TEST_ASSERT_TRUE((reason.nhost_reasons == 0)
&& (reason.host_based_reasons == NULL));
erase_job_preason(&reason);
}
void test_preason(void)
{
printf("\n>> preason test\n\n");
RUN_TEST(test_main_reason);
RUN_TEST(test_add_host_reason);
RUN_TEST(test_add_res_reason);
RUN_TEST(test_add_res_host_reason);
RUN_TEST(test_add_main_reset_other);
RUN_TEST(test_add_more_host_reason);
RUN_TEST(test_add_more_res_reason);
}

View file

@ -455,7 +455,7 @@ int fmt_jobid_ex(char* buf, size_t sz, uint64_t jobid, char lc, char rc)
id_idx = EXTRACT_ARRAY_IDX(jobid);
snprintf(data, sizeof(data) - 1, "%d-%d-%d-%d%c%d%c", id_cluster,
id_apiserver, id_timestamp, id_job, lc,id_idx, rc);
id_apiserver, id_timestamp, id_job, lc, id_idx, rc);
} else {
uint32_t id_seq;
@ -473,7 +473,8 @@ int fmt_jobid_ex(char* buf, size_t sz, uint64_t jobid, char lc, char rc)
return len;
}
int fmt_jobid(char* buf, size_t sz, uint64_t jobid) {
int fmt_jobid(char* buf, size_t sz, uint64_t jobid)
{
return fmt_jobid_ex(buf, sz, jobid, '[', ']');
}
@ -546,7 +547,8 @@ int parse_jobid(uint64_t* jobid, char* buf)
return -EINVAL;
}
uint64_t array_jobid(uint64_t jobid) {
uint64_t array_jobid(uint64_t jobid)
{
uint32_t tag = EXTRACT_ID_TAG(jobid);
if (tag == 0x00) {
@ -556,7 +558,8 @@ uint64_t array_jobid(uint64_t jobid) {
return EXTRACT_ARRAY_BASEID(jobid);
}
uint64_t array_idx(uint64_t jobid) {
uint64_t array_idx(uint64_t jobid)
{
uint32_t tag = EXTRACT_ID_TAG(jobid);
if (tag == 0x00) {
@ -565,3 +568,22 @@ uint64_t array_idx(uint64_t jobid) {
return EXTRACT_ARRAY_IDX(jobid);
}
void unblock_sig(int signo)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, signo);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
}
void block_sig(int signo)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, signo);
sigprocmask(SIG_BLOCK, &mask, NULL);
}

View file

@ -27,6 +27,48 @@ int xce_hello(xce_ctx_t* ctx, char* msg)
return status;
}
int xce_nop(xce_ctx_t* ctx)
{
int rc;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
rc = xce_nop_req(ctx->ep);
/* no need to wait reply, just as heartbeat */
return rc;
}
int xce_heartbeat(xce_ctx_t* ctx, int hb_interval)
{
time_t now;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
if (ctx->ep == NULL) {
return -EINVAL;
}
now = time(NULL);
if (now - ctx->ep->ts_last_out < hb_interval) {
return 0;
}
return xce_nop(ctx);
}
int xce_shutdown(xce_ctx_t* ctx)
{
int rc;
@ -45,13 +87,11 @@ int xce_shutdown(xce_ctx_t* ctx)
return rc;
}
int xce_get(xce_ctx_t* ctx, int table, void*** data)
int xce_get_with_condition(xce_ctx_t* ctx, xce_get_t* get, void*** data)
{
int rc;
int status;
xce_match_t condition = { .type = MatchCondition_condition_matchall };
xce_get_t get = { .table = table, .condition = &condition };
dataset_t getreply = { .table = table, .nrows = 0, .rows = NULL };
int rc;
int status;
dataset_t getreply;
if (ctx == NULL) {
return -EINVAL;
@ -61,8 +101,12 @@ int xce_get(xce_ctx_t* ctx, int table, void*** data)
return -EINVAL;
}
if ((get == NULL) || (data == NULL)) {
return -EINVAL;
}
ctx->reply.u.get = &getreply;
rc = xce_get_req(ctx->ep, &get);
rc = xce_get_req(ctx->ep, get);
if (rc < 0) {
return rc;
}
@ -84,6 +128,21 @@ int xce_get(xce_ctx_t* ctx, int table, void*** data)
return rc;
}
int xce_get(xce_ctx_t* ctx, int table, void*** data)
{
/* clang-format off */
xce_match_t condition = {
.type = MatchCondition_condition_matchall
};
xce_get_t get = {
.table = table,
.condition = &condition
};
/* clang-format on */
return xce_get_with_condition(ctx, &get, data);
}
int xce_reslist(xce_ctx_t* ctx, xce_resource_t*** res)
{
int table = Data_data_resources;
@ -524,3 +583,88 @@ int xce_runtask(xce_ctx_t* ctx, xce_taskrun_t* runinfo)
return status;
}
int xce_set_pend_reason(xce_ctx_t* ctx, xce_preason_set_t* reasons)
{
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
rc = xce_set_pend_reason_req(ctx->ep, reasons);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_clear_reason(xce_ctx_t* ctx, xce_clear_reason_t* reasons)
{
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
rc = xce_clear_reason_req(ctx->ep, reasons);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_jobinfo(xce_ctx_t* ctx, uint64_t jobid, xce_job_t** job)
{
/* clang-format off */
xce_match_t condition = {
.type = MatchCondition_condition_matchjid,
.condition = {
.jobid = jobid
}
};
xce_get_t get = {
.table = Data_data_jobs,
.condition = &condition
};
/* clang-format on */
int rc;
xce_job_t** jobs;
if ((ctx == NULL) || (job == NULL)) {
return -EINVAL;
}
rc = xce_get_with_condition(ctx, &get, (void***)&jobs);
if (rc <= 0) {
return rc;
}
*job = jobs[0];
FREEUP(jobs);
return 1;
}