#include #include #include #include #include #include #include "mylock.h" #include "netio.h" #include "request.h" #include "typemap.h" #include "utils.h" #include "xce/types.h" #define REQUEST_FROM(req) \ ((req)->from == NULL) \ ? "Unknown" \ : (((req)->from->name == NULL) ? "Unknown" : (req->from->name)) int xce_encode(xce_request_t* req, io_packet_t* pkt) { struct capn c; struct Request rq; struct capn_segment* cs; Request_ptr rp; int rc; TRACE("%s request op %d seq %ld from %s", __func__, req->opcode, req->seq, REQUEST_FROM(req)); capn_init_malloc(&c); cs = capn_root(&c).seg; encode_Request(cs, &rq, req); cs = capn_root(&c).seg; rp = new_Request(cs); write_Request(&rq, rp); capn_setp(capn_root(&c), 0, rp.p); pkt->sz = capn_size(&c); rc = alloc_packet(pkt); if (rc < 0) { capn_free(&c); return -errno; } capn_write_mem(&c, (uint8_t*)pkt->data, pkt->sz, 0); capn_free(&c); return 1; } int xce_decode(io_packet_t* pkt, xce_request_t* req) { struct capn c; struct Request rq; Request_ptr rp; capn_init_mem(&c, (const uint8_t*)pkt->data, pkt->sz, 0); rp.p = capn_getp(capn_root(&c), 0, 1); read_Request(&rq, rp); decode_Request(req, &rq); TRACE("%s request op %d seq %ld from %s", __func__, req->opcode, req->seq, REQUEST_FROM(req)); capn_free(&c); free_packet(pkt); FREEUP(pkt); return 0; } void init_reply_by_req(xce_reply_t* reply, xce_request_t* req) { reply->seq = req->seq; reply->opcode = req->opcode; } int xce_request(endpoint_t* ep, xce_request_t* req) { int rc; io_packet_t* pkt; pkt = (io_packet_t*)calloc(1, sizeof(*pkt)); if (pkt == NULL) { return -ENOMEM; } req->seq = endpoint_getseq(ep); req->from = ep->peer; rc = xce_encode(req, pkt); if (rc < 0) { free_packet(pkt); free(pkt); return rc; } endpoint_enq(ep, &(pkt->link)); return 0; } int xce_reply(endpoint_t* ep, xce_peerinfo_t* from, xce_reply_t* reply) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_reply, .body_which = Request_body_replymsg, }; /* clang-format on */ int rc; io_packet_t* pkt; TRACE("%s seq %lu opcode %d status %d data which %d", __func__, reply->seq, reply->opcode, reply->status, reply->data_which); pkt = (io_packet_t*)calloc(1, sizeof(*pkt)); if (pkt == NULL) { return -ENOMEM; } request.from = from; request.body.replymsg = reply; request.seq = endpoint_getseq(ep); rc = xce_encode(&request, pkt); if (rc < 0) { free_packet(pkt); free(pkt); return rc; } endpoint_enq(ep, &(pkt->link)); return 0; } int xce_nop_req(endpoint_t* ep) { xce_request_t request = { .opcode = OPCode_nop, .body_which = Request_body_nomsg }; if (ep == NULL) { return -EINVAL; } return xce_request(ep, &request); } int xce_hello_req(endpoint_t* ep, char* msg) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_hello, .body_which = Request_body_hellomsg, .body = { .hellomsg = msg } }; /* clang-format on */ if ((ep == NULL) || (msg == NULL)) { return -EINVAL; } return xce_request(ep, &request); } int xce_join_req(endpoint_t* ep, int role, hostattrs_t* attrs) { /* clang-format off */ xce_joindata_t joinmsg = { .role = role }; xce_request_t request = { .opcode = OPCode_join, .body_which = Request_body_joinmsg, .body = { .joinmsg = &joinmsg } }; if ((role != HostRole_client) && (role != HostRole_worker) && (role != HostRole_apiserver) && (role != HostRole_scheduler)) { return -EINVAL; } /* clang-format on */ if (role == HostRole_worker) { if (attrs == NULL) { return -EINVAL; } joinmsg.data_which = JoinData_data_attrs; joinmsg.data.attrs = attrs; } return xce_request(ep, &request); } int xce_shutdown_req(endpoint_t* ep) { int rc; dataq_t* outq; xce_request_t request = { .opcode = OPCode_shutdown, .body_which = Request_body_nomsg }; if (ep == NULL) { return -EINVAL; } rc = xce_request(ep, &request); if (rc < 0) { return rc; } outq = &(ep->outq); while (!DATAQ_EMPTY(outq)) { sleep(1); } return 0; } int xce_pushconfig_req(endpoint_t* ep, xce_peerinfo_t* from, xce_configdata_t* config) { int rc = 0; /* clang-format off */ xce_request_t request = { .opcode = OPCode_push, .body_which = Request_body_configpushmsg }; /* clang-format on */ if ((ep == NULL) || (config == NULL)) { return -EINVAL; } request.body.configpushmsg = config; rc = xce_request(ep, &request); return rc; } static int xce_push_req(endpoint_t* ep, xce_peerinfo_t* from, xce_data_t* data) { int rc = 0; xce_request_t request = { .opcode = OPCode_push, .body_which = Request_body_pushmsg }; if ((ep == NULL) || (from == NULL) || (data == NULL)) { return -EINVAL; } request.body.pushmsg = data; rc = xce_request(ep, &request); return rc; } int xce_push_data_req(endpoint_t* ep, xce_peerinfo_t* from, xce_data_t* data, xce_check_fn_t checkf, void* checkarg, int pktlimit) { int nrows = 0; int pos = 0; int rc = 0; xce_data_t data1; int checkstatus = 0; if ((ep == NULL) || (from == NULL) || (data == NULL)) { return -EINVAL; } data1.table = data->table; switch (data->table) { case Data_data_schedjobs: case Data_data_jobs: nrows = data->data.jobs->n_total; data1.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t)); if (data1.data.jobs == NULL) { rc = -ENOMEM; } break; case Data_data_schedworkers: case Data_data_workers: nrows = data->data.workers->n_total; data1.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t)); if (data1.data.workers == NULL) { rc = -ENOMEM; } break; case Data_data_resources: break; case Data_data_resvals: break; default: rc = -EINVAL; break; } if (rc < 0) { return rc; } if (pktlimit <= 0) { pktlimit = nrows; } do { int nc = nrows - pos; if (nc > pktlimit) { nc = pktlimit; } if (checkf != NULL) { checkstatus = (*checkf)(checkarg); if (checkstatus < 0) { nc = 0; } } switch (data->table) { case Data_data_schedjobs: case Data_data_jobs: data1.data.jobs->n_total = data->data.jobs->n_total; data1.data.jobs->pos = pos; data1.data.jobs->count = nc; if (nc == 0) { data1.data.jobs->jobs = NULL; } else { data1.data.jobs->jobs = &(data->data.jobs->jobs[pos]); } break; case Data_data_schedworkers: case Data_data_workers: data1.data.workers->n_total = data->data.workers->n_total; data1.data.workers->pos = pos; data1.data.workers->count = nc; if (nc == 0) { data1.data.workers->workers = NULL; } else { data1.data.workers->workers = &(data->data.workers->workers[pos]); } break; case Data_data_resources: break; case Data_data_resvals: break; default: break; } rc = xce_push_req(ep, from, &data1); if (rc < 0) { break; } pos += nc; } while ((pos < nrows) && (checkstatus >= 0)); switch (data->table) { case Data_data_schedjobs: case Data_data_jobs: FREEUP(data1.data.jobs); break; case Data_data_schedworkers: case Data_data_workers: FREEUP(data1.data.workers); break; default: break; } return rc; } int xce_get_req(endpoint_t* ep, xce_get_t* get) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_get, .body_which = Request_body_getmsg, .body = { .getmsg = get } }; /* clang-format on */ return xce_request(ep, &request); } int xce_reply_get(endpoint_t* ep, xce_peerinfo_t* from, xce_reply_t* reply, xce_check_fn_t checkf, void* checkarg, int pktlimit) { int rc = 0; int nrows = 0; int pos = 0; /* clang-format off */ xce_data_t getdata = { .table = reply->data.getdata->table }; xce_reply_t reply1 = { .seq = reply->seq, .opcode = reply->opcode, .status = reply->status, .data_which = reply->data_which, .data = { .getdata = &getdata } }; /* clang-format on */ int checkstatus = 0; xce_data_t* data = reply->data.getdata; if ((ep == NULL) || (from == NULL) || (reply == NULL)) { return -EINVAL; } switch (getdata.table) { case Data_data_schedjobs: case Data_data_jobs: nrows = data->data.jobs->n_total; getdata.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t)); break; case Data_data_schedworkers: case Data_data_workers: nrows = data->data.workers->n_total; getdata.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t)); break; case Data_data_resources: nrows = data->data.resources->n_total; getdata.data.resources = (xce_resource_data_t*)calloc(1, sizeof(xce_resource_data_t)); break; case Data_data_resvals: nrows = data->data.resvals->n_total; getdata.data.resvals = (xce_resval_data_t*)calloc(1, sizeof(xce_resval_data_t)); break; default: rc = -EINVAL; break; } if (rc < 0) { /* FIXME we need to reply no data */ return rc; } if (pktlimit <= 0) { pktlimit = nrows; } do { int nc = nrows - pos; if (nc > pktlimit) { nc = pktlimit; } if (checkf != NULL) { checkstatus = (*checkf)(checkarg); if (checkstatus < 0) { nc = 0; } } switch (getdata.table) { case Data_data_schedjobs: case Data_data_jobs: getdata.data.jobs->n_total = data->data.jobs->n_total; getdata.data.jobs->pos = pos; getdata.data.jobs->count = nc; if (nc == 0) { getdata.data.jobs->jobs = NULL; } else { getdata.data.jobs->jobs = &(data->data.jobs->jobs[pos]); } break; case Data_data_schedworkers: case Data_data_workers: getdata.data.workers->n_total = data->data.workers->n_total; getdata.data.workers->pos = pos; getdata.data.workers->count = nc; if (nc == 0) { getdata.data.workers->workers = NULL; } else { getdata.data.workers->workers = &(data->data.workers->workers[pos]); } break; case Data_data_resources: getdata.data.resources->n_total = data->data.resources->n_total; getdata.data.resources->pos = pos; getdata.data.workers->count = nc; if (nc == 0) { getdata.data.resources->resources = NULL; } else { getdata.data.resources->resources = &(data->data.resources->resources[pos]); } break; case Data_data_resvals: getdata.data.resvals->n_total = data->data.resvals->n_total; getdata.data.resvals->pos = pos; getdata.data.resvals->count = nc; if (nc == 0) { getdata.data.resvals->vals = NULL; } else { getdata.data.resvals->vals = &(data->data.resvals->vals[pos]); } break; default: /* should never goes here */ break; } rc = xce_reply(ep, from, &reply1); if (rc < 0) { break; } pos += nc; } while ((pos < nrows) && (checkstatus >= 0)); switch (getdata.table) { case Data_data_schedjobs: case Data_data_jobs: FREEUP(getdata.data.jobs); break; case Data_data_schedworkers: case Data_data_workers: FREEUP(getdata.data.workers); break; case Data_data_resources: FREEUP(getdata.data.resources); break; case Data_data_resvals: FREEUP(getdata.data.resvals); break; default: break; } return rc; } int extract_data(dataset_t* dataset, xce_data_t* getdata) { int ntotal; int rc = 0; int pos = 0; int count = 0; TRACE("%s ...", __func__); switch (getdata->table) { case Data_data_schedjobs: case Data_data_jobs: if (getdata->data.jobs->count <= 0) { return 1; } ntotal = getdata->data.jobs->n_total; pos = getdata->data.jobs->pos; count = getdata->data.jobs->count; if (dataset->rows == NULL) { dataset->rows = (xce_job_t**)calloc(ntotal, sizeof(xce_job_t*)); dataset->nrows = 0; } memcpy((void*)(((char*)dataset->rows) + sizeof(xce_job_t*) * pos), getdata->data.jobs->jobs, count * sizeof(xce_job_t*)); memset(getdata->data.jobs->jobs, 0x0, count * sizeof(xce_job_t*)); break; case Data_data_schedworkers: case Data_data_workers: if (getdata->data.workers->count <= 0) { return 1; } ntotal = getdata->data.workers->n_total; if (dataset->rows == NULL) { dataset->rows = (xce_worker_t**)calloc(ntotal, sizeof(xce_worker_t*)); dataset->nrows = 0; } pos = getdata->data.workers->pos; count = getdata->data.workers->count; memcpy((void*)(((char*)dataset->rows) + sizeof(xce_worker_t*) * pos), getdata->data.workers->workers, count * sizeof(xce_worker_t*)); memset(getdata->data.workers->workers, 0x0, count * sizeof(xce_worker_t*)); break; case Data_data_resources: if (getdata->data.resources->count <= 0) { return 1; } ntotal = getdata->data.resources->n_total; if (dataset->rows == NULL) { dataset->rows = (xce_resource_t**)calloc(ntotal, sizeof(xce_resource_t*)); dataset->nrows = 0; } pos = getdata->data.resources->pos; count = getdata->data.resources->count; memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resource_t*) * pos), getdata->data.resources->resources, count * sizeof(xce_resource_t*)); memset(getdata->data.resources->resources, 0x0, count * sizeof(xce_resource_t*)); break; case Data_data_resvals: if (getdata->data.resvals->count <= 0) { return 1; } ntotal = getdata->data.resvals->n_total; if (dataset->rows == NULL) { dataset->rows = (xce_resval_t**)calloc(ntotal, sizeof(xce_resval_t*)); dataset->nrows = 0; } pos = getdata->data.resvals->pos; count = getdata->data.resvals->count; memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resval_t*) * pos), getdata->data.resvals->vals, count * sizeof(xce_resval_t*)); memset(getdata->data.resvals->vals, 0x0, count * sizeof(xce_resval_t*)); break; default: rc = -EINVAL; break; } if (rc < 0) { return rc; } dataset->nrows += count; if (dataset->nrows < ntotal) { return 0; } return 1; } int xce_jobdispatch_req(endpoint_t* ep, xce_job_dispatch_t* info) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_jobdispatch, .body_which = Request_body_dispatchmsg, .body = { .dispatchmsg = info } }; /* clang-format on */ /* clang-format off */ if ((ep == NULL) || (info == NULL)) { return -EINVAL; } /* clang-format on */ return xce_request(ep, &request); } int xce_notify_req(endpoint_t* ep, xce_notify_data_t* data) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_notify, .body_which = Request_body_notifymsg, .body = { .notifymsg = data } }; /* clang-format on */ if ((ep == NULL) || (data == NULL)) { return -EINVAL; } return xce_request(ep, &request); } int xce_jobsubmit_req(endpoint_t* ep, xce_job_submit_t* submit) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_jobsub, .body_which = Request_body_jobsubmsg, .body = { .jobsubmsg = submit } }; /*clang-format on*/ /* clang-format off */ if ((ep == NULL) || (submit == NULL)) { return -EINVAL; } /* clang-format on */ return xce_request(ep, &request); } int xce_startjob_req(endpoint_t* ep, xce_job_exec_t* execinfo) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_startjob, .body_which = Request_body_jobstartmsg, .body = { .jobstartmsg = execinfo } }; /* clang-format on */ return xce_request(ep, &request); } int xce_clusterconf_req(endpoint_t* ep) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_clusterconf, .body_which = Request_body_nomsg }; /* clang-format on */ return xce_request(ep, &request); } int xce_update_req(endpoint_t* ep, xce_update_data_t* data) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_update, .body_which = Request_body_updatemsg, .body = { .updatemsg = data } }; /* clang-format on */ if ((ep == NULL) || (data == NULL)) { return -EINVAL; } return xce_request(ep, &request); } int xce_jobctrl_req(endpoint_t* ep, xce_jobctrl_t* ctrinfo) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_jobcontrol, .body_which = Request_body_jobctrlmsg, .body = { .jobctrlmsg = ctrinfo } }; /* clang-format on */ if ((ep == NULL) || (ctrinfo == NULL)) { return -EINVAL; } if (ctrinfo->jobid == 0) { return -EINVAL; } switch (ctrinfo->action) { case JobControl_u_siginfo: break; case JobControl_u_ckptoption: if (ctrinfo->u.ckptoption->method == NULL) { ctrinfo->u.ckptoption->method = "default"; } break; default: return -EINVAL; break; } return xce_request(ep, &request); } int xce_queuectrl_req(endpoint_t* ep, xce_queuectrl_t* ctrlinfo) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_queuecontrol, .body_which = Request_body_queuectrlmsg, .body = { .queuectrlmsg = ctrlinfo } }; /* clang-format on */ if ((ep == NULL) || (ctrlinfo == NULL)) { return -EINVAL; } if ((ctrlinfo->queue == NULL) || (strlen(ctrlinfo->queue) == 0)) { return -EINVAL; } if (ctrlinfo->action == QUEUE_DO_NONE) { return 0; } if ((ctrlinfo->action < 0) || (ctrlinfo->action > QUEUE_ACTIVE)) { return -EINVAL; } return xce_request(ep, &request); } int xce_hostctrl_req(endpoint_t* ep, xce_hostctrl_t* ctrlinfo) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_hostcontrol, .body_which = Request_body_hostctrlmsg, .body = { .hostctrlmsg = ctrlinfo } }; /* clang-format on */ if ((ep == NULL) || (ctrlinfo == NULL)) { return -EINVAL; } if ((ctrlinfo->hostname == NULL) || (strlen(ctrlinfo->hostname) == 0)) { return -EINVAL; } if (ctrlinfo->action == HOST_DO_NONE) { return 0; } if (ctrlinfo->action != HOST_OPEN && ctrlinfo->action != HOST_CLOSE) { return -EINVAL; } return xce_request(ep, &request); } int xce_runtask_req(endpoint_t* ep, xce_taskrun_t* runinfo) { /* clang-format off */ xce_request_t request = { .opcode = OPCode_runtasks, .body_which = Request_body_runtaskmsg, .body = { .runtaskmsg = runinfo } }; /* clang-format on */ if ((ep == NULL) || (runinfo == NULL)) { return -EINVAL; } if (runinfo->nhosts <= 0) { return -EINVAL; } 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); }