/* don't free this char */ static const char *_set_resv_msg(resv_desc_msg_t *resv_msg, const char *new_text, int column) { char *type = ""; char *err_msg = NULL; int free_tres_license = 0; int free_tres_bb = 0; int free_tres_corecnt = 0; int free_tres_nodecnt = 0; int temp_int = 0; uint64_t f; /* need to clear global_edit_error here (just in case) */ global_edit_error = 0; if (!resv_msg) return NULL; switch (column) { case SORTID_ACCOUNTS: resv_msg->accounts = xstrdup(new_text); type = "accounts"; break; case SORTID_ACTION: xfree(got_edit_signal); if (!xstrcasecmp(new_text, "None")) got_edit_signal = NULL; else got_edit_signal = xstrdup(new_text); break; case SORTID_BURST_BUFFER: resv_msg->burst_buffer = xstrdup(new_text); type = "burst_buffer"; break; case SORTID_CORE_CNT: type = "Core Count"; if (state_control_corecnt_supported() != SLURM_SUCCESS) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup("CoreCnt or CPUCnt is only supported when SelectType includes select/cons_res or SelectTypeParameters includes OTHER_CONS_RES on a Cray."); goto return_error; } if (state_control_parse_resv_corecnt(resv_msg, (char *)new_text, &free_tres_corecnt, false, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } break; case SORTID_DURATION: temp_int = time_str2mins((char *)new_text); if (temp_int <= 0) goto return_error; resv_msg->duration = temp_int; type = "duration"; break; case SORTID_TIME_END: resv_msg->end_time = parse_time((char *)new_text, 0); type = "end time"; break; case SORTID_FEATURES: resv_msg->features = xstrdup(new_text); type = "features"; break; case SORTID_FLAGS: f = parse_resv_flags(new_text, __func__); type = "flags"; if (f == INFINITE64) goto return_error; resv_msg->flags = f; break; case SORTID_LICENSES: resv_msg->licenses = xstrdup(new_text); type = "licenses"; break; case SORTID_NAME: resv_msg->name = xstrdup(new_text); type = "name"; break; case SORTID_NODE_CNT: type = "Node Count"; if (parse_resv_nodecnt(resv_msg, (char *)new_text, &free_tres_nodecnt, false, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } break; case SORTID_NODELIST: resv_msg->node_list = xstrdup(new_text); type = "Node List"; break; case SORTID_PARTITION: resv_msg->partition = xstrdup(new_text); type = "partition"; break; case SORTID_TIME_START: resv_msg->start_time = parse_time((char *)new_text, 0); type = "start time"; break; case SORTID_USERS: resv_msg->users = xstrdup(new_text); type = "users"; break; case SORTID_TRES: if (state_control_parse_resv_tres((char *)new_text, resv_msg, &free_tres_license, &free_tres_bb, &free_tres_corecnt, &free_tres_nodecnt, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } break; case SORTID_WATTS: if (state_control_parse_resv_watts((char *) new_text, resv_msg, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } type = "watts"; break; default: type = "unknown"; break; } if (xstrcmp(type, "unknown")) global_send_update_msg = 1; return type; return_error: global_edit_error = 1; return type; }
extern int state_control_parse_resv_tres(char *val, resv_desc_msg_t *resv_msg_ptr, int *free_tres_license, int *free_tres_bb, int *free_tres_corecnt, int *free_tres_nodecnt, char **err_msg) { int i, ret, len; char *tres_bb = NULL, *tres_license = NULL, *tres_corecnt = NULL, *tres_nodecnt = NULL, *token, *type = NULL, *saveptr1 = NULL, *value_str = NULL, *name = NULL, *compound = NULL, *tmp = NULL; bool discard, first; *free_tres_license = 0; *free_tres_bb = 0; *free_tres_corecnt = 0; *free_tres_nodecnt = 0; token = strtok_r(val, ",", &saveptr1); while (token) { compound = strtok_r(token, "=", &value_str); if (!compound || !value_str || !*value_str) { xstrfmtcat(*err_msg, "invalid TRES '%s'", token); goto error; } if (strchr(compound, '/')) { tmp = xstrdup(compound); type = strtok_r(tmp, "/", &name); } else type = compound; if (state_control_configured_tres(compound) != SLURM_SUCCESS) { xstrfmtcat(*err_msg, "couldn't identify configured TRES '%s'", compound); goto error; } if (!xstrcasecmp(type, "license")) { if (tres_license && tres_license[0] != '\0') xstrcatchar(tres_license, ','); xstrfmtcat(tres_license, "%s:%s", name, value_str); token = strtok_r(NULL, ",", &saveptr1); } else if (xstrcasecmp(type, "bb") == 0) { if (tres_bb && tres_bb[0] != '\0') xstrcatchar(tres_bb, ','); xstrfmtcat(tres_bb, "%s:%s", name, value_str); token = strtok_r(NULL, ",", &saveptr1); } else if (xstrcasecmp(type, "cpu") == 0) { first = true; discard = false; do { len = strlen(value_str); for (i = 0; i < len; i++) { if (!isdigit(value_str[i])) { if (first) { xstrfmtcat(*err_msg, "invalid TRES cpu value '%s'", value_str); goto error; } else discard = true; break; } } first = false; if (!discard) { if (tres_corecnt && tres_corecnt[0] != '\0') xstrcatchar(tres_corecnt, ','); xstrcat(tres_corecnt, value_str); token = strtok_r(NULL, ",", &saveptr1); value_str = token; } } while (!discard && token); } else if (xstrcasecmp(type, "node") == 0) { if (tres_nodecnt && tres_nodecnt[0] != '\0') xstrcatchar(tres_nodecnt, ','); xstrcat(tres_nodecnt, value_str); token = strtok_r(NULL, ",", &saveptr1); } else { xstrfmtcat(*err_msg, "TRES type '%s' not supported with reservations", compound); goto error; } } if (tres_corecnt && tres_corecnt[0] != '\0') { /* only have this on a cons_res machine */ ret = state_control_corecnt_supported(); if (ret != SLURM_SUCCESS) { xstrfmtcat(*err_msg, "CoreCnt or CPUCnt is only supported when SelectType includes select/cons_res or SelectTypeParameters includes OTHER_CONS_RES on a Cray."); goto error; } ret = state_control_parse_resv_corecnt(resv_msg_ptr, tres_corecnt, free_tres_corecnt, true, err_msg); xfree(tres_corecnt); if (ret != SLURM_SUCCESS) goto error; } if (tres_nodecnt && tres_nodecnt[0] != '\0') { ret = parse_resv_nodecnt(resv_msg_ptr, tres_nodecnt, free_tres_nodecnt, true, err_msg); xfree(tres_nodecnt); if (ret != SLURM_SUCCESS) goto error; } if (tres_license && tres_license[0] != '\0') { resv_msg_ptr->licenses = tres_license; *free_tres_license = 1; } if (tres_bb && tres_bb[0] != '\0') { resv_msg_ptr->burst_buffer = tres_bb; *free_tres_bb = 1; } xfree(tmp); return SLURM_SUCCESS; error: xfree(tmp); xfree(tres_nodecnt); xfree(tres_corecnt); return SLURM_ERROR; }