fix: preserve admin-set host state across worker re-registration in makeWorker_

When a worker re-joins and already exists in workermgr, makeWorker_()
now overrides the existing slot instead of returning EEXIST. Admin-set
flags (LOCKEDU, CLOSED, HIDDEN, CLOSED_BY_ADMIN) survive the override.

Add XCE_WORKER_CLOSED_BY_ADMIN flag to distinguish admin-closed hosts
from workload-closed ones. worker_ctrl sets/clears it alongside CLOSED.

Refactor worker_init/worker_destroy into copy_worker/kill_worker helpers
shared by both fresh creation and override paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-05-13 10:38:39 +00:00
parent d47b3375e7
commit febb4a6c4d
6 changed files with 111 additions and 57 deletions

View file

@ -22,12 +22,34 @@ static size_t worker_datasize(va_list ap)
return sz;
}
static int worker_init(meta_obj_t* obj, va_list ap)
static void kill_worker(worker_t* w)
{
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*);
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;
}
@ -55,6 +77,42 @@ static int worker_init(meta_obj_t* obj, va_list ap)
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;
admin_status = dst->host.status & XCE_WORKER_ADMIN_MASK;
kill_worker(dst);
rc = copy_worker(dst, w);
if (rc >= 0) {
dst->host.status |= admin_status;
dst->ep = NULL;
}
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;
@ -66,26 +124,7 @@ 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);
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));
kill_worker(w);
my_rwlock_fini(&(priv->lock));
memset(priv, 0x0, sizeof(*priv));
@ -163,9 +202,10 @@ static typeinfo_t worker_type = {
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**)&worker);
rc = key_find(workermgr, (void*)w->name, (void**)&w1);
if ((rc < 0) && (rc != -ENOENT)) {
errno = -rc;
@ -174,20 +214,24 @@ static worker_t* makeWorker_(var workermgr, xce_worker_t* w)
}
if (rc > 0) {
errno = EEXIST;
return NULL;
}
worker = makeInstance(&worker_type, w);
if (worker != NULL) {
rc = key_add(workermgr, (void*)worker->host.name, (void*)worker);
rc = override_worker(w1, w);
if (rc < 0) {
destroy(worker);
errno = -rc;
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;
}
}
}
return worker;