255 lines
6 KiB
C
255 lines
6 KiB
C
#include <errno.h>
|
|
#include <rtti.h>
|
|
#include <stdarg.h>
|
|
#include <stdatomic.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "mylock.h"
|
|
#include "utils.h"
|
|
#include "wobj.h"
|
|
#include "xstring.h"
|
|
|
|
typedef struct {
|
|
my_rwlock_t lock;
|
|
atomic_ulong refcount;
|
|
} worker_private_t;
|
|
|
|
static size_t worker_datasize(va_list ap)
|
|
{
|
|
size_t sz = sizeof(worker_t);
|
|
|
|
return sz;
|
|
}
|
|
|
|
static void kill_worker(worker_t* w)
|
|
{
|
|
dereference(w->host.name);
|
|
|
|
if (w->host.attrs != NULL) {
|
|
dereference(w->host.attrs->hosttype);
|
|
dereference(w->host.attrs->hostmodel);
|
|
FREEUP(w->host.attrs);
|
|
}
|
|
|
|
if (w->host.dispatch_window_config != NULL) {
|
|
free_timewindow_config(w->host.dispatch_window_config);
|
|
w->host.dispatch_window_config = NULL;
|
|
}
|
|
|
|
if (w->host.thresholds != NULL) {
|
|
free_resource_thresholds(w->host.thresholds, w->host.nthresholds);
|
|
w->host.thresholds = NULL;
|
|
w->host.nthresholds = 0;
|
|
}
|
|
|
|
zarray_fini(&(w->host.resvals));
|
|
|
|
return;
|
|
}
|
|
|
|
static int copy_worker(worker_t* dst, xce_worker_t* src)
|
|
{
|
|
if ((src == NULL) || (src->attrs == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
dst->host.name = makeString(src->name);
|
|
dst->host.attrs = (hostattrs_t*)calloc(1, sizeof(hostattrs_t));
|
|
if (dst->host.attrs == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memcpy(dst->host.attrs, src->attrs, sizeof(*(dst->host.attrs)));
|
|
|
|
dst->host.attrs->hosttype = makeString(src->attrs->hosttype);
|
|
dst->host.attrs->hostmodel = makeString(src->attrs->hostmodel);
|
|
dst->host.status = src->status;
|
|
|
|
/* FIXME: */
|
|
zarray_init(&(dst->host.resvals), 64, NULL);
|
|
|
|
dst->host.dead_since = src->dead_since;
|
|
dst->host.pending_ctrl = src->pending_ctrl;
|
|
MOVE_PTR(dst->host.dispatch_window_config, src->dispatch_window_config);
|
|
dst->host.nthresholds = src->nthresholds;
|
|
MOVE_PTR(dst->host.thresholds, src->thresholds);
|
|
dst->host.nresvals_to_sched = 0;
|
|
dst->host.resvals_to_sched = NULL;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int override_worker(worker_t* dst, xce_worker_t* w)
|
|
{
|
|
#define XCE_WORKER_ADMIN_MASK \
|
|
(XCE_WORKER_LOCKEDU | XCE_WORKER_CLOSED | XCE_WORKER_HIDDEN \
|
|
| XCE_WORKER_CLOSED_BY_ADMIN)
|
|
uint32_t admin_status = 0;
|
|
int rc = 0;
|
|
int idx;
|
|
|
|
admin_status = dst->host.status & XCE_WORKER_ADMIN_MASK;
|
|
idx = dst->idx;
|
|
|
|
kill_worker(dst);
|
|
|
|
rc = copy_worker(dst, w);
|
|
if (rc >= 0) {
|
|
dst->host.status |= admin_status;
|
|
dst->ep = NULL;
|
|
dst->idx = idx;
|
|
}
|
|
|
|
return rc;
|
|
#undef XCE_WORKER_ADMIN_MASK
|
|
}
|
|
|
|
static int worker_init(meta_obj_t* obj, va_list ap)
|
|
{
|
|
worker_t* dst = RTTI_OBJ_TO_DATA(worker_t, obj);
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
xce_worker_t* src = va_arg(ap, xce_worker_t*);
|
|
int rc = 0;
|
|
|
|
rc = copy_worker(dst, src);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
my_rwlock_init(&(priv->lock));
|
|
priv->refcount = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void worker_destroy(meta_obj_t* obj)
|
|
{
|
|
worker_t* w = RTTI_OBJ_TO_DATA(worker_t, obj);
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
kill_worker(w);
|
|
|
|
my_rwlock_fini(&(priv->lock));
|
|
memset(priv, 0x0, sizeof(*priv));
|
|
|
|
return;
|
|
}
|
|
|
|
static int worker_reference(meta_obj_t* obj)
|
|
{
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
atomic_fetch_add(&(priv->refcount), 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void worker_dereference(meta_obj_t* obj)
|
|
{
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
worker_t* w = RTTI_OBJ_TO_DATA(worker_t, obj);
|
|
uint64_t count = 0;
|
|
|
|
count = atomic_fetch_sub(&(priv->refcount), 1);
|
|
|
|
if (count == 1) {
|
|
destroy_(w, (obj_destroy_fn_t)worker_destroy);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int worker_lock(meta_obj_t* obj, uint64_t option)
|
|
{
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
int rc = -EINVAL;
|
|
|
|
switch (option) {
|
|
case RTTI_LOCK_READ:
|
|
rc = my_rwlock_rlock(&(priv->lock));
|
|
break;
|
|
case RTTI_LOCK_WRITE:
|
|
rc = my_rwlock_wlock(&(priv->lock));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static void worker_unlock(meta_obj_t* obj)
|
|
{
|
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
my_rwlock_unlock(&(priv->lock));
|
|
|
|
return;
|
|
}
|
|
|
|
static typeinfo_t worker_type = {
|
|
.name = "xce worker",
|
|
.privateSize = sizeof(worker_private_t),
|
|
.dataSize = (datasize_fn_t)worker_datasize,
|
|
.init = (obj_init_fn_t)worker_init,
|
|
.destroy = NULL,
|
|
.interfaces
|
|
= { .reference
|
|
= &(intf_reference_t) { .reference = (reference_fn_t)worker_reference,
|
|
.dereference
|
|
= (dereference_fn_t)worker_dereference },
|
|
.lock = &(intf_lock_t) { .lock = (lock_fn_t)worker_lock,
|
|
.unlock = (unlock_fn_t)worker_unlock } }
|
|
};
|
|
|
|
static worker_t* makeWorker_(var workermgr, xce_worker_t* w)
|
|
{
|
|
worker_t* worker = NULL;
|
|
worker_t* w1 = NULL;
|
|
int rc = 0;
|
|
|
|
rc = key_find(workermgr, (void*)w->name, (void**)&w1);
|
|
|
|
if ((rc < 0) && (rc != -ENOENT)) {
|
|
errno = -rc;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if (rc > 0) {
|
|
rc = override_worker(w1, w);
|
|
if (rc < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
worker = w1;
|
|
} else {
|
|
worker = makeInstance(&worker_type, w);
|
|
if (worker != NULL) {
|
|
rc = key_add(workermgr, (void*)worker->host.name, (void*)worker);
|
|
|
|
if (rc < 0) {
|
|
destroy(worker);
|
|
|
|
errno = -rc;
|
|
return NULL;
|
|
}
|
|
|
|
worker->idx = rc;
|
|
}
|
|
}
|
|
|
|
return worker;
|
|
}
|
|
|
|
worker_t* makeWorker(var workermgr, xce_worker_t* w)
|
|
{
|
|
worker_t* worker = NULL;
|
|
|
|
lock(workermgr, RTTI_LOCK_WRITE);
|
|
worker = makeWorker_(workermgr, w);
|
|
unlock(workermgr);
|
|
|
|
return worker;
|
|
}
|