merge job rusage and pending reason support
This commit is contained in:
parent
30824ae5ea
commit
cb0c7fe9e7
82 changed files with 4280 additions and 2561 deletions
|
|
@ -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
192
src/lib/delay.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
107
src/lib/ordq.c
Normal 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
151
src/lib/preason.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
56
src/lib/testsuite/test_delay.c
Normal file
56
src/lib/testsuite/test_delay.c
Normal 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);
|
||||
}
|
||||
82
src/lib/testsuite/test_ordq.c
Normal file
82
src/lib/testsuite/test_ordq.c
Normal 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);
|
||||
}
|
||||
168
src/lib/testsuite/test_preason.c
Normal file
168
src/lib/testsuite/test_preason.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
158
src/lib/xceapi.c
158
src/lib/xceapi.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue