#include #include #include #include #include #include #include "group.h" #include "kvmgr.h" #include "objmgr.h" #include "utils.h" #include "xce/types.h" #include "xcelimit.h" int fmt_consumer(char* buf, int len, xce_consumer_t* c) { struct { xce_consumer_type_t type; char* name; char* per_name; } consumer_mapping[] = { { CONSUMER_USER, "USER", "PER_USER" }, { CONSUMER_HOST, "HOST", "PER_HOST" }, { CONSUMER_PROJECT, "PROJECT", "PER_PROJECT" }, { CONSUMER_QUEUE, "QUEUE", "PER_QUEUE" }, { -1, NULL, NULL } }; int i; if ((buf == NULL) || (c == NULL) || (len <= 0)) { return -EINVAL; } for (i = 0; consumer_mapping[i].type >= 0; i++) { if (c->ctype == consumer_mapping[i].type) { char* t; int l; int rc; if (c->per_consumer) { t = consumer_mapping[i].per_name; } else { t = consumer_mapping[i].name; } snprintf(buf, len, "%s = ", t); l = strlen(buf); rc = fmt_group(buf + l, len - l, c->group); if (rc < 0) { return rc; } return strlen(buf); } } return -EINVAL; } int build_consumer(xce_consumer_t** pconsumer, groupmgr_t* mgr, xce_consumer_type_t type, int per_consumer, xce_group_config_t* g_config, char* default_name_prefix) { xce_consumer_t* c = NULL; xce_group_t* g = NULL; *pconsumer = NULL; c = (xce_consumer_t*)calloc(1, sizeof(*c)); if (c == NULL) { return -ENOMEM; } *pconsumer = c; c->ctype = type; c->per_consumer = (per_consumer != 0) ? 1 : 0; c->group = NULL; if (g_config != NULL) { char* default_g_name = NULL; char consumer_group_name[2 * XCE_MAXNAME_LEN + 1]; if ((g_config->name == NULL) || (strlen(g_config->name) == 0)) { char* suffix = NULL; switch (type) { case CONSUMER_USER: suffix = "ug"; break; case CONSUMER_PROJECT: suffix = "pg"; break; case CONSUMER_HOST: suffix = "hg"; break; case CONSUMER_QUEUE: suffix = "qg"; break; default: suffix = "unknown"; break; } sprintf(consumer_group_name, "%s-%s-group", default_name_prefix, suffix); default_g_name = consumer_group_name; } else { default_g_name = g_config->name; } g = build_group(mgr, g_config, default_g_name); if (g == NULL) { return -ENOMEM; } } else { g = get_group(mgr, "all"); } c->group = g; return 1; } void kill_consumer(xce_consumer_t* c) { if (c == NULL) { return; } /* leave c->group managed by group manager */ FREEUP(c); } int fmt_limit(char* buf, int len, xce_limit_t* limit) { int pos = 0; int i, rc; rc = snprintf(buf + pos, len - pos, "limit: %s\n", limit->name); if (rc < 0) { return rc; } pos += rc; for (i = 0; i < CONSUMER_MAX; i++) { xce_consumer_t* c = limit->consumers[i]; if (c != NULL) { rc = fmt_consumer(buf + pos, len - pos, c); if (rc < 0) { return rc; } pos += rc; rc = snprintf(buf + pos, len - pos, "\n"); if (rc < 0) { return rc; } pos += rc; } } rc = snprintf(buf + pos, len - pos, "\n%s = %f%s\n", limit->val.resname, limit->val.val, (limit->val.percent != 0) ? "%" : ""); if (rc < 0) { return rc; } return strlen(buf); } void kill_limit(xce_limit_t* limit) { int i; if (limit == NULL) { return; } FREEUP(limit->name); for (i = 0; i < CONSUMER_MAX; i++) { xce_consumer_t* c = limit->consumers[i]; if (c != NULL) { kill_consumer(c); } } FREEUP(limit->val.resname); FREEUP(limit); } int build_limit(xce_limit_t** plimit, groupmgr_t* ugmgr, groupmgr_t* qgmgr, groupmgr_t* hgmgr, groupmgr_t* pgmgr, xce_limit_config_t* config) { xce_limit_t* limit = NULL; int rc = 0; *plimit = NULL; limit = (xce_limit_t*)calloc(1, sizeof(*limit)); if (limit == NULL) { return -ENOMEM; } *plimit = limit; limit->name = strdup(config->name); rc = build_consumer(&(limit->consumers[CONSUMER_USER]), ugmgr, CONSUMER_USER, config->per_user, config->users, config->name); if (rc < 0) { return rc; } rc = build_consumer(&(limit->consumers[CONSUMER_HOST]), hgmgr, CONSUMER_HOST, config->per_host, config->hosts, config->name); if (rc < 0) { return rc; } rc = build_consumer(&(limit->consumers[CONSUMER_QUEUE]), qgmgr, CONSUMER_QUEUE, config->per_queue, config->queues, config->name); if (rc < 0) { return rc; } rc = build_consumer(&(limit->consumers[CONSUMER_PROJECT]), pgmgr, CONSUMER_PROJECT, config->per_project, config->projects, config->name); if (rc < 0) { return rc; } limit->val.resname = strdup(config->val->resname); limit->val.percent = config->val->percent; limit->val.val = config->val->val; return 1; } int match_limit(xce_limit_t* limit, int global, ...) { va_list ap; char* user = NULL; char* queue = NULL; char* project = NULL; char* host = NULL; xce_consumer_t* c = NULL; va_start(ap, global); user = va_arg(ap, char*); queue = va_arg(ap, char*); project = va_arg(ap, char*); if ((limit == NULL) || (user == NULL) || (queue == NULL) || (project == NULL)) { return -EINVAL; } if (!global) { host = va_arg(ap, char*); if (host == NULL) { return -EINVAL; } } c = limit->consumers[CONSUMER_USER]; if (c != NULL) { if (is_in_group(c->group, user) <= 0) { return 0; } } c = limit->consumers[CONSUMER_QUEUE]; if (c != NULL) { if (is_in_group(c->group, queue) <= 0) { return 0; } } c = limit->consumers[CONSUMER_PROJECT]; if (c != NULL) { if (is_in_group(c->group, project) <= 0) { return 0; } } if (!global) { c = limit->consumers[CONSUMER_HOST]; if (c != NULL) { if (is_in_group(c->group, host) <= 0) { return 0; } } } return 1; } int build_vres_name(char** vname, xce_limit_t* limit, char* user, char* queue, char* project) { char resname[2 * XCE_MAXNAME_LEN + 1]; xce_consumer_t* c = NULL; char* p = NULL; int rc = 0; *vname = NULL; if ((vname == NULL) || (limit == NULL) || (user == NULL) || (queue == NULL) || (project == NULL)) { return -EINVAL; } memset(resname, 0x0, sizeof(resname)); p = &resname[0]; rc = sprintf(p, "limit=%s", limit->name); if (rc < 0) { return rc; } p += rc; c = limit->consumers[CONSUMER_USER]; if ((c != NULL) && (c->per_consumer == 1)) { rc = sprintf(p, "/u=%s", user); if (rc < 0) { return rc; } p += rc; } c = limit->consumers[CONSUMER_QUEUE]; if ((c != NULL) && (c->per_consumer == 1)) { rc = sprintf(p, "/q=%s", queue); if (rc < 0) { return rc; } p += rc; } c = limit->consumers[CONSUMER_PROJECT]; if ((c != NULL) && (c->per_consumer == 1)) { rc = sprintf(p, "/p=%s", project); if (rc < 0) { return rc; } p += rc; } *vname = strdup(resname); if ((*vname) != NULL) { return 1; } return -ENOMEM; } int is_host_based_limit(resmgr_t* mgr, xce_limit_t* limit) { xce_consumer_t* c = NULL; xce_resource_t* r = NULL; if (limit == NULL) { return -EINVAL; } r = resmgr_lockres(mgr, limit->val.resname, OBJREF_NOP); if ((r->flags & (XCE_RESF_GLOBAL | XCE_RESF_SHARED)) == 0) { if (limit->val.percent != 0) { return 1; } } c = limit->consumers[CONSUMER_HOST]; if (c == NULL) { return 0; } return c->per_consumer; } int add_vres(xce_resource_t** pvres, resmgr_t* mgr, char* name, int global) { xce_resource_t* vres = NULL; int rc; vres = (xce_resource_t*)calloc(1, sizeof(*vres)); *pvres = vres; if (vres == NULL) { return -ENOMEM; } vres->name = strdup(name); vres->idx = -1; vres->desc = NULL; vres->valtype = XCE_VAL_NUMERIC; vres->ordtype = XCE_ORD_DECR; vres->flags = XCE_RESF_LIMIT | XCE_RESF_CONSUMABLE | XCE_RESF_RELEASE; if (global) { vres->flags |= (XCE_RESF_SHARED | XCE_RESF_GLOBAL); } else { vres->flags |= XCE_RESF_DEFAULT_HOST; } rc = resmgr_add_res(mgr, vres); if (rc < 0) { return rc; } vres->idx = rc; return rc; } int instantiate_limit(xce_vres_t** pvres, resmgr_t* mgr, xce_limit_t* limit, char* user, char* queue, char* project) { xce_vres_t* vres = NULL; int rc = 0; char* vresname = NULL; int shared = 1; if ((pvres == NULL) || (mgr == NULL) || (limit == NULL) || (user == NULL) || (queue == NULL) || (project == NULL)) { return -EINVAL; } vres = (xce_vres_t*)calloc(1, sizeof(*vres)); *pvres = vres; if (vres == NULL) { return -ENOMEM; } vres->limit = limit; if (is_host_based_limit(mgr, limit)) { shared = 0; } rc = build_vres_name(&(vresname), limit, user, queue, project); if (rc < 0) { return rc; } vres->vres = resmgr_lockres(mgr, vresname, OBJREF_NOP); if (vres->vres == NULL) { rc = add_vres(&(vres->vres), mgr, vresname, shared); if (rc < 0) { FREEUP(vresname); return rc; } } FREEUP(vresname); vres->res = resmgr_lockres(mgr, limit->val.resname, OBJREF_NOP); if (vres->res == NULL) { return -ENOENT; } return rc; } void kill_vres(xce_vres_t* vres) { if (vres == NULL) { return; } }