forked from lei.chen/myxce
controller.capnp declared `struct Data $C.mapname("xce_data_t")` (an
OPCode_get query-result tagged union) at file scope, which shadows
Cap'n Proto's builtin Data blob type for every later `: Data` field in
the same file. This silently miscompiled 7 fields across 6 structs as
a struct-pointer type instead of a raw byte blob: UpgradeConfigRequest
.sha256/.bytes, ReplConfigReply.sha256/.bytes, ReplConfigPushRequest
.sha256/.bytes, ReplEnvelope.payload, SnapshotTransfer's chunk
payload, WalCatchupEntry.payload/.batchPayloads, and CtrlHelloRequest
.key. Production C code had already routed around it for years via
hand-rolled raw capn_ptr manipulation (see request.c's own comments);
nothing before now needed the generated codec/accessors to actually
work for these fields.
Renamed the local struct to XceData (capnp-level name only; the
$C.mapname("xce_data_t") C typedef is unchanged) and explicitly
repointed getdata/pushmsg at XceData by name, since those two fields
correctly want the local tagged union. Updated every derived
generated-identifier reference across 19 hand-written files spanning
controller, lib, scheduler, and the Go apiserver/xcecli CGo bindings.
Fixed 5 call sites in lib/request.c that had been typed against the
old workaround alias but now legitimately receive the correct
capn_data type (a pure type-name swap -- Data_ptr/XceData_ptr and
capn_data share the identical {capn_ptr p} layout).
Verified via full rebuild+test: lib (1/1), controller (3/3, incl. the
job-array push regression tests), scheduler (15/15), Go apiserver +
xcecli (all packages green), and a direct pycapnp round-trip proving
UpgradeConfigRequest.sha256/.bytes now encode/decode correctly.
Bug: bug-1461 (.wolf/buglog.json). Unblocks admin-config-tool task 3.3.
227 lines
5.9 KiB
C
227 lines
5.9 KiB
C
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "cluster.h"
|
|
#include "controller.capnp.h"
|
|
#include "utils.h"
|
|
#include "xce/cluster_def.h"
|
|
|
|
static int do_reply_reslist(cluster_t* c, endpoint_t* ep,
|
|
xce_request_t* request)
|
|
{
|
|
xce_reply_t reply;
|
|
xce_resource_data_t resdata;
|
|
xce_data_t getdata = { .table = request->body.getmsg->table,
|
|
.data = { .resources = &resdata } };
|
|
int rc = 0;
|
|
xlist_t rlist;
|
|
|
|
init_reply_by_req(&reply, request);
|
|
xlist_init(&rlist, 512);
|
|
|
|
collect_resources(c, NULL, &rlist);
|
|
resdata.n_total = rlist.count;
|
|
resdata.resources = (xce_resource_t**)rlist.data;
|
|
|
|
reply.status = 0;
|
|
reply.data_which = RequestReply_data_getdata;
|
|
reply.data.getdata = &getdata;
|
|
|
|
rc = xce_reply_get(ep, c->myhost, &reply, NULL, NULL, -1);
|
|
|
|
xlist_fini(&rlist);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int do_reply_resvals(cluster_t* c, endpoint_t* ep,
|
|
xce_request_t* request)
|
|
{
|
|
xce_reply_t reply;
|
|
xce_resval_data_t resvaldata;
|
|
xce_get_t* getmsg = request->body.getmsg;
|
|
xce_data_t getdata = { .data = { .resvals = &resvaldata } };
|
|
int rc = 0;
|
|
xce_val_t val;
|
|
xce_resval_t resval;
|
|
xce_resval_t* vals[] = { &resval };
|
|
|
|
init_reply_by_req(&reply, request);
|
|
|
|
resvaldata.n_total = 0;
|
|
resvaldata.vals = NULL;
|
|
|
|
if (getmsg != NULL) {
|
|
xce_match_t* condition = getmsg->condition;
|
|
|
|
if (condition != NULL) {
|
|
getdata.table = getmsg->table;
|
|
rc = get_resval(c, condition->condition.reskey->resname,
|
|
condition->condition.reskey->hostname, &val);
|
|
if (rc >= 0) {
|
|
resval.val = &val;
|
|
resval.name = condition->condition.reskey->resname;
|
|
resval.host = condition->condition.reskey->hostname;
|
|
resvaldata.n_total = 1;
|
|
resvaldata.vals = vals;
|
|
}
|
|
} else {
|
|
rc = -EINVAL;
|
|
}
|
|
} else {
|
|
rc = -EINVAL;
|
|
}
|
|
|
|
reply.status = rc;
|
|
reply.data_which = RequestReply_data_getdata;
|
|
reply.data.getdata = &getdata;
|
|
|
|
rc = xce_reply_get(ep, c->myhost, &reply, NULL, NULL, -1);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int check_worker_(xce_worker_t* w)
|
|
{
|
|
if (w == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int do_reply_workerlist(cluster_t* c, endpoint_t* ep,
|
|
xce_request_t* request)
|
|
{
|
|
xce_reply_t reply;
|
|
xce_workers_data_t workerdata;
|
|
/* clang-format off */
|
|
xce_data_t getdata = {
|
|
.table = request->body.getmsg->table,
|
|
.data = {
|
|
.workers = &workerdata }
|
|
};
|
|
/* clang-format on */
|
|
int rc = 0;
|
|
int i;
|
|
xlist_t wlist;
|
|
|
|
init_reply_by_req(&reply, request);
|
|
xlist_init(&wlist, 1024);
|
|
|
|
collect_workers(c, (collect_check_fn_t)check_worker_, &wlist);
|
|
workerdata.n_total = wlist.count;
|
|
workerdata.workers = (xce_worker_t**)wlist.data;
|
|
|
|
reply.status = 0;
|
|
reply.data_which = RequestReply_data_getdata;
|
|
reply.data.getdata = &getdata;
|
|
|
|
rc = xce_reply_get(ep, c->myhost, &reply, check_controller, c, 100);
|
|
|
|
for (i = 0; i < workerdata.n_total; i++) {
|
|
xce_worker_t* w = workerdata.workers[i];
|
|
|
|
free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched));
|
|
}
|
|
|
|
unlock_collect_workers(&wlist);
|
|
|
|
xlist_fini(&wlist);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int do_reply_joblist(cluster_t* c, endpoint_t* ep,
|
|
xce_request_t* request)
|
|
{
|
|
xce_reply_t reply;
|
|
xce_jobs_data_t jobdata;
|
|
xce_data_t getdata = { .table = request->body.getmsg->table,
|
|
.data = { .jobs = &jobdata } };
|
|
int rc = 0;
|
|
xce_match_t* match = request->body.getmsg->condition;
|
|
xlist_t jlist;
|
|
|
|
init_reply_by_req(&reply, request);
|
|
|
|
xlist_init(&jlist, 1024 * 1024);
|
|
|
|
if (match->type == MatchCondition_condition_matchjid) {
|
|
job_t* j = NULL;
|
|
|
|
jobdata.n_total = 0;
|
|
jobdata.jobs = NULL;
|
|
|
|
lock(c->jobmgr, RTTI_LOCK_READ);
|
|
rc = key_find(c->jobmgr, (void*)match->condition.jobid, (void**)&j);
|
|
if (j != NULL) {
|
|
reference(j);
|
|
}
|
|
unlock(c->jobmgr);
|
|
|
|
if (rc > 0) {
|
|
lock(j, RTTI_LOCK_READ);
|
|
xlist_store(&jlist, &(j->job));
|
|
} else {
|
|
dereference(j);
|
|
}
|
|
} else {
|
|
collect_jobs(c, NULL, &jlist);
|
|
}
|
|
|
|
jobdata.n_total = jlist.count;
|
|
jobdata.jobs = (xce_job_t**)jlist.data;
|
|
|
|
reply.status = 0;
|
|
reply.data_which = RequestReply_data_getdata;
|
|
reply.data.getdata = &getdata;
|
|
|
|
rc = xce_reply_get(ep, c->myhost, &reply, check_controller, c, 100);
|
|
|
|
unlock_collect_jobs(&jlist);
|
|
|
|
FREEUP(jobdata.jobs);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int do_get_op(cluster_t* c, endpoint_t* ep, xce_request_t* request)
|
|
{
|
|
int rc = 0;
|
|
xce_reply_t reply;
|
|
|
|
TRACE("%s table %d", __func__, request->body.getmsg->table);
|
|
|
|
init_reply_by_req(&reply, request);
|
|
|
|
switch (request->body.getmsg->table) {
|
|
case XceData_data_resources:
|
|
rc = do_reply_reslist(c, ep, request);
|
|
break;
|
|
case XceData_data_workers:
|
|
case XceData_data_schedworkers:
|
|
rc = do_reply_workerlist(c, ep, request);
|
|
break;
|
|
case XceData_data_schedjobs:
|
|
case XceData_data_jobs:
|
|
rc = do_reply_joblist(c, ep, request);
|
|
break;
|
|
case XceData_data_resvals:
|
|
rc = do_reply_resvals(c, ep, request);
|
|
break;
|
|
default:
|
|
rc = -ENOENT;
|
|
|
|
reply.status = rc;
|
|
reply.data_which = RequestReply_data_nodata;
|
|
|
|
xce_reply(ep, c->myhost, &reply);
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|