forked from lei.chen/myxce
537 lines
11 KiB
C
537 lines
11 KiB
C
#include <errno.h>
|
|
|
|
#include "cluster.h"
|
|
#include "request.h"
|
|
#include "xce/cluster_def.h"
|
|
#include "xce/types.h"
|
|
|
|
typedef int (*check_fn_t)(void*);
|
|
|
|
int check_controller(void* arg)
|
|
{
|
|
cluster_t* c = (cluster_t*)arg;
|
|
|
|
if (!c->running) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
struct intern_array_ {
|
|
int count;
|
|
int idx;
|
|
void* data;
|
|
check_fn_t checkfn;
|
|
};
|
|
|
|
int not_null_check(void* arg)
|
|
{
|
|
if (arg == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int collect_resval_with_idx_(zarray_t* array,
|
|
int* nres,
|
|
xce_val_with_idx_t*** resvals)
|
|
{
|
|
int nc;
|
|
int i, j;
|
|
xce_val_with_idx_t** vals;
|
|
|
|
nc = 0;
|
|
|
|
for (i = 0; i < array->caps; i++) {
|
|
if (array->data[i] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
nc++;
|
|
}
|
|
|
|
if (nc == 0) {
|
|
*nres = 0;
|
|
*resvals = NULL;
|
|
return 0;
|
|
}
|
|
|
|
vals = (xce_val_with_idx_t**)calloc(nc, sizeof(xce_val_with_idx_t*));
|
|
if (vals == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; i < array->caps; i++) {
|
|
xce_val_with_idx_t* val;
|
|
xce_val_t* src = array->data[i];
|
|
|
|
if (array->data[i] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
val = (xce_val_with_idx_t*)calloc(1, sizeof(*val));
|
|
if (val == NULL) {
|
|
free_resval_with_idx_list(&vals, j);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
vals[j] = val;
|
|
j++;
|
|
|
|
val->idx = i;
|
|
val->val = (xce_val_t*)calloc(1, sizeof(xce_val_t));
|
|
if (val->val == NULL) {
|
|
free_resval_with_idx_list(&vals, j);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (src->which == Value_u_svalue) {
|
|
val->val->which = Value_u_svalue;
|
|
if (src->u.svalue != NULL) {
|
|
val->val->u.svalue = strdup(src->u.svalue);
|
|
} else {
|
|
val->val->u.svalue = strdup("-");
|
|
}
|
|
} else {
|
|
memcpy(val->val, array->data[i],
|
|
sizeof(xce_val_t));
|
|
}
|
|
}
|
|
|
|
*nres = j;
|
|
*resvals = vals;
|
|
return j;
|
|
}
|
|
|
|
int collect_resval_with_idx(zarray_t* array,
|
|
int* nres,
|
|
xce_val_with_idx_t*** resvals)
|
|
{
|
|
int rc = 0;
|
|
|
|
mylock_lock(&(array->lock));
|
|
|
|
rc = collect_resval_with_idx_(array, nres, resvals);
|
|
|
|
mylock_unlock(&(array->lock));
|
|
|
|
return rc;
|
|
}
|
|
static int count_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
|
|
if ((arg == NULL) || (arg->checkfn == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
arg->count++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int add_confvar_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
xce_config_t** p = NULL;
|
|
|
|
if ((arg == NULL) || (arg->count < 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
p = (xce_config_t**)arg->data;
|
|
if (p == NULL) {
|
|
p = (xce_config_t**)calloc(arg->count,
|
|
sizeof(xce_config_t*));
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
arg->data = p;
|
|
}
|
|
|
|
p[arg->idx] = (xce_config_t*)obj_ref(arg2, OBJREF_READ);
|
|
arg->idx++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void collect_confvars(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* nconfig,
|
|
xce_config_t*** configs)
|
|
{
|
|
xlist_t lst;
|
|
struct intern_array_ args = {
|
|
.count = 0,
|
|
.idx = 0,
|
|
.data = NULL,
|
|
.checkfn = (fn == NULL) ? not_null_check : fn
|
|
};
|
|
int rc;
|
|
|
|
*nconfig = 0;
|
|
*configs = NULL;
|
|
|
|
xlist_init(&lst, 3);
|
|
xlist_store(&lst, count_);
|
|
xlist_store(&lst, add_confvar_);
|
|
|
|
rc = kvmgr_iter(&(c->configmgr), &lst, &args);
|
|
|
|
xlist_fini(&lst);
|
|
|
|
if (rc >= 0) {
|
|
*nconfig = args.count;
|
|
*configs = args.data;
|
|
}
|
|
}
|
|
|
|
static int add_queue_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
xce_queue_t** p = NULL;
|
|
|
|
if (arg == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
p = (xce_queue_t**)arg->data;
|
|
if (p == NULL) {
|
|
p = (xce_queue_t**)calloc(arg->count,
|
|
sizeof(xce_queue_t*));
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
arg->data = p;
|
|
}
|
|
|
|
p[arg->idx] = (xce_queue_t*)obj_ref(arg2, OBJREF_READ);
|
|
arg->idx++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void collect_queues(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* nqueues,
|
|
xce_queue_t*** queues)
|
|
{
|
|
xlist_t lst;
|
|
struct intern_array_ args = {
|
|
.count = 0,
|
|
.idx = 0,
|
|
.data = NULL,
|
|
.checkfn = (fn == NULL) ? not_null_check : fn
|
|
};
|
|
int rc;
|
|
|
|
*nqueues = 0;
|
|
*queues = NULL;
|
|
|
|
xlist_init(&lst, 3);
|
|
xlist_store(&lst, count_);
|
|
xlist_store(&lst, add_queue_);
|
|
|
|
rc = qmgr_iter(&(c->qmgr), &lst, &args);
|
|
|
|
xlist_fini(&lst);
|
|
|
|
if (rc >= 0) {
|
|
*nqueues = args.count;
|
|
*queues = args.data;
|
|
}
|
|
}
|
|
|
|
static int add_resource_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
xce_resource_t** p = NULL;
|
|
|
|
if (arg == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
p = (xce_resource_t**)arg->data;
|
|
if (p == NULL) {
|
|
p = (xce_resource_t**)calloc(arg->count,
|
|
sizeof(xce_resource_t*));
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
arg->data = p;
|
|
}
|
|
|
|
p[arg->idx] = (xce_resource_t*)obj_ref(arg2, OBJREF_READ);
|
|
|
|
arg->idx++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void collect_resources(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* nresources,
|
|
xce_resource_t*** resources)
|
|
{
|
|
xlist_t lst;
|
|
struct intern_array_ args = {
|
|
.count = 0,
|
|
.idx = 0,
|
|
.data = NULL,
|
|
.checkfn = (fn == NULL) ? not_null_check : fn
|
|
};
|
|
int rc;
|
|
|
|
*nresources = 0;
|
|
*resources = NULL;
|
|
|
|
xlist_init(&lst, 3);
|
|
xlist_store(&lst, count_);
|
|
xlist_store(&lst, add_resource_);
|
|
|
|
rc = resmgr_iter(&(c->resmgr), &lst, &args);
|
|
|
|
xlist_fini(&lst);
|
|
|
|
if (rc >= 0) {
|
|
*nresources = args.count;
|
|
*resources = args.data;
|
|
}
|
|
}
|
|
|
|
static int add_job_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
xce_job_t** p = NULL;
|
|
|
|
if (arg == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
p = (xce_job_t**)arg->data;
|
|
if (p == NULL) {
|
|
p = (xce_job_t**)calloc(arg->count, sizeof(xce_job_t*));
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
arg->data = p;
|
|
}
|
|
|
|
p[arg->idx] = (xce_job_t*)obj_ref(arg2, OBJREF_READ);
|
|
arg->idx++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void collect_jobs(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* njobs,
|
|
xce_job_t*** jobs)
|
|
{
|
|
xlist_t lst;
|
|
struct intern_array_ args = {
|
|
.count = 0,
|
|
.idx = 0,
|
|
.data = NULL,
|
|
.checkfn = (check_fn_t)fn
|
|
};
|
|
int rc = 0;
|
|
|
|
*njobs = 0;
|
|
*jobs = NULL;
|
|
|
|
xlist_init(&lst, 3);
|
|
xlist_store(&lst, count_);
|
|
xlist_store(&lst, add_job_);
|
|
|
|
rc = jobmgr_iter(&(c->jobmgr), &lst, &args);
|
|
xlist_fini(&lst);
|
|
|
|
if (rc >= 0) {
|
|
*njobs = args.count;
|
|
*jobs = args.data;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int add_worker_(void* arg1,
|
|
void* arg2)
|
|
{
|
|
struct intern_array_* arg = (struct intern_array_*)arg1;
|
|
xce_worker_t** p = NULL;
|
|
xce_worker_t* w;
|
|
|
|
if (arg == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (arg->count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!(arg->checkfn(arg2))) {
|
|
return 0;
|
|
}
|
|
|
|
p = (xce_worker_t**)arg->data;
|
|
if (p == NULL) {
|
|
p = (xce_worker_t**)calloc(arg->count, sizeof(xce_worker_t*));
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
arg->data = p;
|
|
}
|
|
|
|
w = (xce_worker_t*)obj_ref(arg2, OBJREF_READ);
|
|
|
|
collect_resval_with_idx(&(w->resvals),
|
|
&(w->nresvals_to_sched),
|
|
&(w->resvals_to_sched));
|
|
|
|
p[arg->idx] = w;
|
|
arg->idx++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void collect_workers(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* nworkers,
|
|
xce_worker_t*** workers)
|
|
{
|
|
xlist_t lst;
|
|
struct intern_array_ args = {
|
|
.count = 0,
|
|
.idx = 0,
|
|
.data = NULL,
|
|
.checkfn = (check_fn_t)fn
|
|
};
|
|
int rc = 0;
|
|
|
|
*nworkers = 0;
|
|
*workers = NULL;
|
|
|
|
xlist_init(&lst, 3);
|
|
xlist_store(&lst, count_);
|
|
xlist_store(&lst, add_worker_);
|
|
|
|
rc = workermgr_iter(&(c->workermgr), &lst, &args);
|
|
|
|
xlist_fini(&lst);
|
|
|
|
if (rc >= 0) {
|
|
*nworkers = args.count;
|
|
*workers = args.data;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void collect_shared_resvals(cluster_t* c,
|
|
collect_check_fn_t fn,
|
|
int* nres,
|
|
xce_val_with_idx_t*** resvals)
|
|
{
|
|
|
|
collect_resval_with_idx(&(c->resmgr.sharedinst),
|
|
nres, resvals);
|
|
|
|
return;
|
|
}
|
|
|
|
void deref_objs(int count,
|
|
void** objs)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
void* obj = objs[i];
|
|
|
|
if (obj == NULL) {
|
|
continue;
|
|
}
|
|
|
|
DEREF_OBJ(obj);
|
|
}
|
|
}
|
|
|
|
int notify(cluster_t* c,
|
|
endpoint_t* ep,
|
|
xce_notify_data_t* data)
|
|
{
|
|
ioctx_t* ctx = NULL;
|
|
|
|
ctx = ioctx_alloc(ep, c->myhost);
|
|
if (ctx == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
return xce_notify_req(ctx, data);
|
|
}
|