blob: 3102e90b84ab4b599d279ea170653652ed811507 [file]
/*****************************************************************************\
* as_mysql_qos.c - functions dealing with qos.
*****************************************************************************
*
* Copyright (C) 2004-2007 The Regents of the University of California.
* Copyright (C) 2008-2010 Lawrence Livermore National Security.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Danny Auble <da@llnl.gov>
*
* This file is part of SLURM, a resource management program.
* For details, see <http://www.schedmd.com/slurmdocs/>.
* Please also read the included file: DISCLAIMER.
*
* SLURM is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with SLURM; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#include "as_mysql_qos.h"
static int _preemption_loop(mysql_conn_t *mysql_conn, int begin_qosid,
bitstr_t *preempt_bitstr)
{
slurmdb_qos_rec_t qos_rec;
int rc = 0, i=0;
xassert(preempt_bitstr);
/* check in the preempt list for all qos's preempted */
for(i=0; i<bit_size(preempt_bitstr); i++) {
if (!bit_test(preempt_bitstr, i))
continue;
memset(&qos_rec, 0, sizeof(qos_rec));
qos_rec.id = i;
assoc_mgr_fill_in_qos(mysql_conn, &qos_rec,
ACCOUNTING_ENFORCE_QOS,
NULL);
/* check if the begin_qosid is preempted by this qos
* if so we have a loop */
if (qos_rec.preempt_bitstr
&& bit_test(qos_rec.preempt_bitstr, begin_qosid)) {
error("QOS id %d has a loop at QOS %s",
begin_qosid, qos_rec.name);
rc = 1;
break;
} else if (qos_rec.preempt_bitstr) {
/* check this qos' preempt list and make sure
no loops exist there either */
if ((rc = _preemption_loop(mysql_conn, begin_qosid,
qos_rec.preempt_bitstr)))
break;
}
}
return rc;
}
static int _setup_qos_limits(slurmdb_qos_rec_t *qos,
char **cols, char **vals,
char **extra, char **added_preempt,
bool for_add)
{
if (!qos)
return SLURM_ERROR;
if (for_add) {
/* If we are adding we should make sure we don't get
old reside sitting around from a former life.
*/
if (!qos->description)
qos->description = xstrdup("");
if (qos->flags & QOS_FLAG_NOTSET)
qos->flags = 0;
if (qos->grace_time == NO_VAL)
qos->grace_time = 0;
if (qos->grp_cpu_mins == (uint64_t)NO_VAL)
qos->grp_cpu_mins = (uint64_t)INFINITE;
if (qos->grp_cpu_run_mins == (uint64_t)NO_VAL)
qos->grp_cpu_run_mins = (uint64_t)INFINITE;
if (qos->grp_cpus == NO_VAL)
qos->grp_cpus = INFINITE;
if (qos->grp_jobs == NO_VAL)
qos->grp_jobs = INFINITE;
if (qos->grp_nodes == NO_VAL)
qos->grp_nodes = INFINITE;
if (qos->grp_submit_jobs == NO_VAL)
qos->grp_submit_jobs = INFINITE;
if (qos->grp_wall == NO_VAL)
qos->grp_wall = INFINITE;
if (qos->max_cpu_mins_pj == (uint64_t)NO_VAL)
qos->max_cpu_mins_pj = (uint64_t)INFINITE;
if (qos->grp_cpu_run_mins == (uint64_t)NO_VAL)
qos->grp_cpu_run_mins = (uint64_t)INFINITE;
if (qos->max_cpus_pj == NO_VAL)
qos->max_cpus_pj = INFINITE;
if (qos->max_cpus_pu == NO_VAL)
qos->max_cpus_pu = INFINITE;
if (qos->max_jobs_pu == NO_VAL)
qos->max_jobs_pu = INFINITE;
if (qos->max_nodes_pj == NO_VAL)
qos->max_nodes_pj = INFINITE;
if (qos->max_nodes_pu == NO_VAL)
qos->max_nodes_pu = INFINITE;
if (qos->max_submit_jobs_pu == NO_VAL)
qos->max_submit_jobs_pu = INFINITE;
if (qos->max_wall_pj == NO_VAL)
qos->max_wall_pj = INFINITE;
if (qos->preempt_mode == (uint16_t)NO_VAL)
qos->preempt_mode = 0;
if (qos->priority == NO_VAL)
qos->priority = 0;
if (fuzzy_equal(qos->usage_factor, NO_VAL))
qos->usage_factor = 1;
if (fuzzy_equal(qos->usage_thres, NO_VAL))
qos->usage_thres = (double)INFINITE;
}
if (qos->description) {
xstrcat(*cols, ", description");
xstrfmtcat(*vals, ", '%s'", qos->description);
xstrfmtcat(*extra, ", description='%s'",
qos->description);
}
if (!(qos->flags & QOS_FLAG_NOTSET)) {
if (qos->flags & QOS_FLAG_REMOVE) {
if (qos->flags)
xstrfmtcat(*extra, ", flags=(flags & ~%u)",
qos->flags & ~QOS_FLAG_REMOVE);
} else {
/* If we are only removing there is no reason
to set up the cols and vals. */
if (qos->flags & QOS_FLAG_ADD) {
if (qos->flags) {
xstrfmtcat(*extra,
", flags=(flags | %u)",
qos->flags & ~QOS_FLAG_ADD);
}
} else
xstrfmtcat(*extra, ", flags=%u", qos->flags);
xstrcat(*cols, ", flags");
xstrfmtcat(*vals, ", '%u'", qos->flags & ~QOS_FLAG_ADD);
}
}
if (qos->grace_time == INFINITE) {
xstrcat(*cols, ", grace_time");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grace_time=NULL");
} else if ((qos->grace_time != NO_VAL) &&
((int32_t)qos->grace_time >= 0)) {
xstrcat(*cols, ", grace_time");
xstrfmtcat(*vals, ", %u", qos->grace_time);
xstrfmtcat(*extra, ", grace_time=%u", qos->grace_time);
}
if (qos->grp_cpu_mins == (uint64_t)INFINITE) {
xstrcat(*cols, ", grp_cpu_mins");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_cpu_mins=NULL");
} else if ((qos->grp_cpu_mins != (uint64_t)NO_VAL)
&& ((int64_t)qos->grp_cpu_mins >= 0)) {
xstrcat(*cols, ", grp_cpu_mins");
xstrfmtcat(*vals, ", %"PRIu64"",
qos->grp_cpu_mins);
xstrfmtcat(*extra, ", grp_cpu_mins=%"PRIu64"",
qos->grp_cpu_mins);
}
if (qos->grp_cpu_run_mins == (uint64_t)INFINITE) {
xstrcat(*cols, ", grp_cpu_run_mins");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_cpu_run_mins=NULL");
} else if ((qos->grp_cpu_run_mins != (uint64_t)NO_VAL)
&& (int64_t)qos->grp_cpu_run_mins >= 0) {
xstrcat(*cols, ", grp_cpu_run_mins");
xstrfmtcat(*vals, ", %"PRIu64"",
qos->grp_cpu_run_mins);
xstrfmtcat(*extra, ", grp_cpu_run_mins=%"PRIu64"",
qos->grp_cpu_run_mins);
}
if (qos->grp_cpus == INFINITE) {
xstrcat(*cols, ", grp_cpus");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_cpus=NULL");
} else if ((qos->grp_cpus != NO_VAL)
&& ((int32_t)qos->grp_cpus >= 0)) {
xstrcat(*cols, ", grp_cpus");
xstrfmtcat(*vals, ", %u", qos->grp_cpus);
xstrfmtcat(*extra, ", grp_cpus=%u", qos->grp_cpus);
}
if (qos->grp_jobs == INFINITE) {
xstrcat(*cols, ", grp_jobs");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_jobs=NULL");
} else if ((qos->grp_jobs != NO_VAL)
&& ((int32_t)qos->grp_jobs >= 0)) {
xstrcat(*cols, ", grp_jobs");
xstrfmtcat(*vals, ", %u", qos->grp_jobs);
xstrfmtcat(*extra, ", grp_jobs=%u", qos->grp_jobs);
}
if (qos->grp_nodes == INFINITE) {
xstrcat(*cols, ", grp_nodes");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_nodes=NULL");
} else if ((qos->grp_nodes != NO_VAL)
&& ((int32_t)qos->grp_nodes >= 0)) {
xstrcat(*cols, ", grp_nodes");
xstrfmtcat(*vals, ", %u", qos->grp_nodes);
xstrfmtcat(*extra, ", grp_nodes=%u", qos->grp_nodes);
}
if (qos->grp_submit_jobs == INFINITE) {
xstrcat(*cols, ", grp_submit_jobs");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_submit_jobs=NULL");
} else if ((qos->grp_submit_jobs != NO_VAL)
&& ((int32_t)qos->grp_submit_jobs >= 0)) {
xstrcat(*cols, ", grp_submit_jobs");
xstrfmtcat(*vals, ", %u", qos->grp_submit_jobs);
xstrfmtcat(*extra, ", grp_submit_jobs=%u",
qos->grp_submit_jobs);
}
if (qos->grp_wall == INFINITE) {
xstrcat(*cols, ", grp_wall");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", grp_wall=NULL");
} else if ((qos->grp_wall != NO_VAL)
&& ((int32_t)qos->grp_wall >= 0)) {
xstrcat(*cols, ", grp_wall");
xstrfmtcat(*vals, ", %u", qos->grp_wall);
xstrfmtcat(*extra, ", grp_wall=%u", qos->grp_wall);
}
if (qos->max_cpu_mins_pj == (uint64_t)INFINITE) {
xstrcat(*cols, ", max_cpu_mins_per_job");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_cpu_mins_per_job=NULL");
} else if ((qos->max_cpu_mins_pj != (uint64_t)NO_VAL)
&& ((int64_t)qos->max_cpu_mins_pj >= 0)) {
xstrcat(*cols, ", max_cpu_mins_per_job");
xstrfmtcat(*vals, ", %"PRIu64"",
qos->max_cpu_mins_pj);
xstrfmtcat(*extra, ", max_cpu_mins_per_job=%"PRIu64"",
qos->max_cpu_mins_pj);
}
if (qos->max_cpu_run_mins_pu == (uint64_t)INFINITE) {
xstrcat(*cols, ", max_cpu_run_mins_per_user");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_cpu_run_mins_per_user=NULL");
} else if ((qos->max_cpu_run_mins_pu != (uint64_t)NO_VAL)
&& ((int64_t)qos->max_cpu_run_mins_pu >= 0)) {
xstrcat(*cols, ", max_cpu_run_mins_per_user");
xstrfmtcat(*vals, ", %"PRIu64"",
qos->max_cpu_run_mins_pu);
xstrfmtcat(*extra, ", max_cpu_run_mins_per_user=%"PRIu64"",
qos->max_cpu_run_mins_pu);
}
if (qos->max_cpus_pj == INFINITE) {
xstrcat(*cols, ", max_cpus_per_job");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_cpus_per_job=NULL");
} else if ((qos->max_cpus_pj != NO_VAL)
&& ((int32_t)qos->max_cpus_pj >= 0)) {
xstrcat(*cols, ", max_cpus_per_job");
xstrfmtcat(*vals, ", %u", qos->max_cpus_pj);
xstrfmtcat(*extra, ", max_cpus_per_job=%u", qos->max_cpus_pj);
}
if (qos->max_cpus_pu == INFINITE) {
xstrcat(*cols, ", max_cpus_per_user");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_cpus_per_user=NULL");
} else if ((qos->max_cpus_pu != NO_VAL)
&& ((int32_t)qos->max_cpus_pu >= 0)) {
xstrcat(*cols, ", max_cpus_per_user");
xstrfmtcat(*vals, ", %u", qos->max_cpus_pu);
xstrfmtcat(*extra, ", max_cpus_per_user=%u", qos->max_cpus_pu);
}
if (qos->max_jobs_pu == INFINITE) {
xstrcat(*cols, ", max_jobs_per_user");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_jobs_per_user=NULL");
} else if ((qos->max_jobs_pu != NO_VAL)
&& ((int32_t)qos->max_jobs_pu >= 0)) {
xstrcat(*cols, ", max_jobs_per_user");
xstrfmtcat(*vals, ", %u", qos->max_jobs_pu);
xstrfmtcat(*extra, ", max_jobs_per_user=%u", qos->max_jobs_pu);
}
if (qos->max_nodes_pj == INFINITE) {
xstrcat(*cols, ", max_nodes_per_job");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_nodes_per_job=NULL");
} else if ((qos->max_nodes_pj != NO_VAL)
&& ((int32_t)qos->max_nodes_pj >= 0)) {
xstrcat(*cols, ", max_nodes_per_job");
xstrfmtcat(*vals, ", %u", qos->max_nodes_pj);
xstrfmtcat(*extra, ", max_nodes_per_job=%u",
qos->max_nodes_pj);
}
if (qos->max_nodes_pu == INFINITE) {
xstrcat(*cols, ", max_nodes_per_user");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_nodes_per_user=NULL");
} else if ((qos->max_nodes_pu != NO_VAL)
&& ((int32_t)qos->max_nodes_pu >= 0)) {
xstrcat(*cols, ", max_nodes_per_user");
xstrfmtcat(*vals, ", %u", qos->max_nodes_pu);
xstrfmtcat(*extra, ", max_nodes_per_user=%u",
qos->max_nodes_pu);
}
if (qos->max_submit_jobs_pu == INFINITE) {
xstrcat(*cols, ", max_submit_jobs_per_user");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_submit_jobs_per_user=NULL");
} else if ((qos->max_submit_jobs_pu != NO_VAL)
&& ((int32_t)qos->max_submit_jobs_pu >= 0)) {
xstrcat(*cols, ", max_submit_jobs_per_user");
xstrfmtcat(*vals, ", %u", qos->max_submit_jobs_pu);
xstrfmtcat(*extra, ", max_submit_jobs_per_user=%u",
qos->max_submit_jobs_pu);
}
if ((qos->max_wall_pj != NO_VAL)
&& ((int32_t)qos->max_wall_pj >= 0)) {
xstrcat(*cols, ", max_wall_duration_per_job");
xstrfmtcat(*vals, ", %u", qos->max_wall_pj);
xstrfmtcat(*extra, ", max_wall_duration_per_job=%u",
qos->max_wall_pj);
} else if (qos->max_wall_pj == INFINITE) {
xstrcat(*cols, ", max_wall_duration_per_job");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", max_wall_duration_per_job=NULL");
}
if (qos->preempt_list && list_count(qos->preempt_list)) {
char *preempt_val = NULL;
char *tmp_char = NULL, *begin_preempt = NULL;
ListIterator preempt_itr =
list_iterator_create(qos->preempt_list);
xstrcat(*cols, ", preempt");
begin_preempt = xstrdup("preempt");
while ((tmp_char = list_next(preempt_itr))) {
if (tmp_char[0] == '-') {
xstrfmtcat(preempt_val,
"replace(%s, ',%s', '')",
begin_preempt, tmp_char+1);
xfree(begin_preempt);
begin_preempt = preempt_val;
} else if (tmp_char[0] == '+') {
xstrfmtcat(preempt_val,
"concat("
"replace(%s, ',%s', ''), ',%s')",
begin_preempt,
tmp_char+1, tmp_char+1);
if (added_preempt)
xstrfmtcat(*added_preempt, ",%s",
tmp_char+1);
xfree(begin_preempt);
begin_preempt = preempt_val;
} else if (tmp_char[0]) {
xstrfmtcat(preempt_val, ",%s", tmp_char);
if (added_preempt)
xstrfmtcat(*added_preempt, ",%s",
tmp_char);
} else
xstrcat(preempt_val, "");
}
list_iterator_destroy(preempt_itr);
xfree(begin_preempt);
xstrfmtcat(*vals, ", '%s'", preempt_val);
xstrfmtcat(*extra, ", preempt='%s'", preempt_val);
xfree(preempt_val);
}
if ((qos->preempt_mode != (uint16_t)NO_VAL)
&& ((int16_t)qos->preempt_mode >= 0)) {
qos->preempt_mode &= (~PREEMPT_MODE_GANG);
xstrcat(*cols, ", preempt_mode");
xstrfmtcat(*vals, ", %u", qos->preempt_mode);
xstrfmtcat(*extra, ", preempt_mode=%u", qos->preempt_mode);
}
if (qos->priority == INFINITE) {
xstrcat(*cols, ", priority");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", priority=NULL");
} else if ((qos->priority != NO_VAL)
&& ((int32_t)qos->priority >= 0)) {
xstrcat(*cols, ", priority");
xstrfmtcat(*vals, ", %u", qos->priority);
xstrfmtcat(*extra, ", priority=%u", qos->priority);
}
if (fuzzy_equal(qos->usage_factor, INFINITE)) {
xstrcat(*cols, ", usage_factor");
xstrcat(*vals, ", 1");
xstrcat(*extra, ", usage_factor=1");
} else if (!fuzzy_equal(qos->usage_factor, NO_VAL)
&& (qos->usage_factor >= 0)) {
xstrcat(*cols, ", usage_factor");
xstrfmtcat(*vals, ", %f", qos->usage_factor);
xstrfmtcat(*extra, ", usage_factor=%f", qos->usage_factor);
}
if (fuzzy_equal(qos->usage_thres, INFINITE)) {
xstrcat(*cols, ", usage_thres");
xstrcat(*vals, ", NULL");
xstrcat(*extra, ", usage_thres=NULL");
} else if (!fuzzy_equal(qos->usage_thres, NO_VAL)
&& (qos->usage_thres >= 0)) {
xstrcat(*cols, ", usage_thres");
xstrfmtcat(*vals, ", %f", qos->usage_thres);
xstrfmtcat(*extra, ", usage_thres=%f", qos->usage_thres);
}
return SLURM_SUCCESS;
}
extern int as_mysql_add_qos(mysql_conn_t *mysql_conn, uint32_t uid,
List qos_list)
{
ListIterator itr = NULL;
int rc = SLURM_SUCCESS;
slurmdb_qos_rec_t *object = NULL;
char *cols = NULL, *extra = NULL, *vals = NULL, *query = NULL,
*tmp_extra = NULL;
time_t now = time(NULL);
char *user_name = NULL;
int affect_rows = 0;
int added = 0;
char *added_preempt = NULL;
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return ESLURM_DB_CONNECTION;
user_name = uid_to_string((uid_t) uid);
itr = list_iterator_create(qos_list);
while ((object = list_next(itr))) {
if (!object->name || !object->name[0]) {
error("We need a qos name to add.");
rc = SLURM_ERROR;
continue;
}
xstrcat(cols, "creation_time, mod_time, name");
xstrfmtcat(vals, "%ld, %ld, '%s'",
now, now, object->name);
xstrfmtcat(extra, ", mod_time=%ld", now);
_setup_qos_limits(object, &cols, &vals,
&extra, &added_preempt, 1);
if (added_preempt) {
object->preempt_bitstr = bit_alloc(g_qos_count);
bit_unfmt(object->preempt_bitstr, added_preempt+1);
xfree(added_preempt);
}
xstrfmtcat(query,
"insert into %s (%s) values (%s) "
"on duplicate key update deleted=0, "
"id=LAST_INSERT_ID(id)%s;",
qos_table, cols, vals, extra);
debug3("%d(%s:%d) query\n%s",
mysql_conn->conn, THIS_FILE, __LINE__, query);
object->id = mysql_db_insert_ret_id(mysql_conn, query);
xfree(query);
if (!object->id) {
error("Couldn't add qos %s", object->name);
added=0;
xfree(cols);
xfree(extra);
xfree(vals);
break;
}
affect_rows = last_affected_rows(mysql_conn);
if (!affect_rows) {
debug2("nothing changed %d", affect_rows);
xfree(cols);
xfree(extra);
xfree(vals);
continue;
}
/* we always have a ', ' as the first 2 chars */
tmp_extra = slurm_add_slash_to_quotes(extra+2);
xstrfmtcat(query,
"insert into %s "
"(timestamp, action, name, actor, info) "
"values (%ld, %u, '%s', '%s', '%s');",
txn_table,
now, DBD_ADD_QOS, object->name, user_name,
tmp_extra);
xfree(tmp_extra);
xfree(cols);
xfree(extra);
xfree(vals);
debug4("query\n%s",query);
rc = mysql_db_query(mysql_conn, query);
xfree(query);
if (rc != SLURM_SUCCESS) {
error("Couldn't add txn");
} else {
if (addto_update_list(mysql_conn->update_list,
SLURMDB_ADD_QOS,
object) == SLURM_SUCCESS)
list_remove(itr);
added++;
}
}
list_iterator_destroy(itr);
xfree(user_name);
if (!added) {
reset_mysql_conn(mysql_conn);
}
return rc;
}
extern List as_mysql_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid,
slurmdb_qos_cond_t *qos_cond,
slurmdb_qos_rec_t *qos)
{
ListIterator itr = NULL;
List ret_list = NULL;
int rc = SLURM_SUCCESS;
char *object = NULL;
char *vals = NULL, *extra = NULL, *query = NULL, *name_char = NULL;
time_t now = time(NULL);
char *user_name = NULL;
int set = 0;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
char *tmp_char1=NULL, *tmp_char2=NULL;
bitstr_t *preempt_bitstr = NULL;
char *added_preempt = NULL;
if (!qos_cond || !qos) {
error("we need something to change");
return NULL;
}
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
xstrcat(extra, "where deleted=0");
if (qos_cond->description_list
&& list_count(qos_cond->description_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->description_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "description='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->id_list
&& list_count(qos_cond->id_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->id_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "id='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->name_list
&& list_count(qos_cond->name_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->name_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "name='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
_setup_qos_limits(qos, &tmp_char1, &tmp_char2,
&vals, &added_preempt, 0);
if (added_preempt) {
preempt_bitstr = bit_alloc(g_qos_count);
bit_unfmt(preempt_bitstr, added_preempt+1);
xfree(added_preempt);
}
xfree(tmp_char1);
xfree(tmp_char2);
if (!extra || !vals) {
errno = SLURM_NO_CHANGE_IN_DATA;
FREE_NULL_BITMAP(preempt_bitstr);
error("Nothing to change");
return NULL;
}
query = xstrdup_printf("select name, preempt, id from %s %s;",
qos_table, extra);
xfree(extra);
if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
xfree(query);
FREE_NULL_BITMAP(preempt_bitstr);
return NULL;
}
rc = 0;
ret_list = list_create(slurm_destroy_char);
while ((row = mysql_fetch_row(result))) {
slurmdb_qos_rec_t *qos_rec = NULL;
uint32_t id = slurm_atoul(row[2]);
if (preempt_bitstr) {
if (_preemption_loop(mysql_conn, id, preempt_bitstr))
break;
}
object = xstrdup(row[0]);
list_append(ret_list, object);
if (!rc) {
xstrfmtcat(name_char, "(name='%s'", object);
rc = 1;
} else {
xstrfmtcat(name_char, " || name='%s'", object);
}
qos_rec = xmalloc(sizeof(slurmdb_qos_rec_t));
qos_rec->name = xstrdup(object);
qos_rec->id = id;
qos_rec->flags = qos->flags;
qos_rec->grp_cpus = qos->grp_cpus;
qos_rec->grace_time = qos->grace_time;
qos_rec->grp_cpu_mins = qos->grp_cpu_mins;
qos_rec->grp_cpu_run_mins = qos->grp_cpu_run_mins;
qos_rec->grp_jobs = qos->grp_jobs;
qos_rec->grp_nodes = qos->grp_nodes;
qos_rec->grp_submit_jobs = qos->grp_submit_jobs;
qos_rec->grp_wall = qos->grp_wall;
qos_rec->max_cpus_pj = qos->max_cpus_pj;
qos_rec->max_cpus_pu = qos->max_cpus_pu;
qos_rec->max_cpu_mins_pj = qos->max_cpu_mins_pj;
qos_rec->max_cpu_run_mins_pu = qos->max_cpu_run_mins_pu;
qos_rec->max_jobs_pu = qos->max_jobs_pu;
qos_rec->max_nodes_pj = qos->max_nodes_pj;
qos_rec->max_nodes_pu = qos->max_nodes_pu;
qos_rec->max_submit_jobs_pu = qos->max_submit_jobs_pu;
qos_rec->max_wall_pj = qos->max_wall_pj;
qos_rec->preempt_mode = qos->preempt_mode;
qos_rec->priority = qos->priority;
if (qos->preempt_list) {
ListIterator new_preempt_itr =
list_iterator_create(qos->preempt_list);
char *new_preempt = NULL;
qos_rec->preempt_bitstr = bit_alloc(g_qos_count);
if (row[1] && row[1][0])
bit_unfmt(qos_rec->preempt_bitstr, row[1]+1);
while ((new_preempt = list_next(new_preempt_itr))) {
bool cleared = 0;
if (new_preempt[0] == '-') {
bit_clear(qos_rec->preempt_bitstr,
atol(new_preempt+1));
} else if (new_preempt[0] == '+') {
bit_set(qos_rec->preempt_bitstr,
atol(new_preempt+1));
} else {
if (!cleared) {
cleared = 1;
bit_nclear(
qos_rec->preempt_bitstr,
0,
g_qos_count-1);
}
bit_set(qos_rec->preempt_bitstr,
atol(new_preempt));
}
}
list_iterator_destroy(new_preempt_itr);
}
qos_rec->usage_factor = qos->usage_factor;
qos_rec->usage_thres = qos->usage_thres;
if (addto_update_list(mysql_conn->update_list,
SLURMDB_MODIFY_QOS, qos_rec)
!= SLURM_SUCCESS)
slurmdb_destroy_qos_rec(qos_rec);
}
mysql_free_result(result);
FREE_NULL_BITMAP(preempt_bitstr);
if (row) {
xfree(vals);
xfree(name_char);
xfree(query);
list_destroy(ret_list);
ret_list = NULL;
errno = ESLURM_QOS_PREEMPTION_LOOP;
return ret_list;
}
if (!list_count(ret_list)) {
errno = SLURM_NO_CHANGE_IN_DATA;
debug3("didn't effect anything\n%s", query);
xfree(vals);
xfree(query);
return ret_list;
}
xfree(query);
xstrcat(name_char, ")");
user_name = uid_to_string((uid_t) uid);
rc = modify_common(mysql_conn, DBD_MODIFY_QOS, now,
user_name, qos_table, name_char, vals, NULL);
xfree(user_name);
xfree(name_char);
xfree(vals);
if (rc == SLURM_ERROR) {
error("Couldn't modify qos");
list_destroy(ret_list);
ret_list = NULL;
}
return ret_list;
}
extern List as_mysql_remove_qos(mysql_conn_t *mysql_conn, uint32_t uid,
slurmdb_qos_cond_t *qos_cond)
{
ListIterator itr = NULL;
List ret_list = NULL;
int rc = SLURM_SUCCESS;
char *object = NULL;
char *extra = NULL, *query = NULL,
*name_char = NULL, *assoc_char = NULL;
time_t now = time(NULL);
char *user_name = NULL;
int set = 0;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
if (!qos_cond) {
error("we need something to change");
return NULL;
}
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
xstrcat(extra, "where deleted=0");
if (qos_cond->description_list
&& list_count(qos_cond->description_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->description_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "description='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->id_list
&& list_count(qos_cond->id_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->id_list);
while ((object = list_next(itr))) {
if (!object[0])
continue;
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "id='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->name_list
&& list_count(qos_cond->name_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->name_list);
while ((object = list_next(itr))) {
if (!object[0])
continue;
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "name='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (!extra) {
error("Nothing to remove");
return NULL;
}
query = xstrdup_printf("select id, name from %s %s;", qos_table, extra);
xfree(extra);
if (!(result = mysql_db_query_ret(
mysql_conn, query, 0))) {
xfree(query);
return NULL;
}
name_char = NULL;
ret_list = list_create(slurm_destroy_char);
while ((row = mysql_fetch_row(result))) {
slurmdb_qos_rec_t *qos_rec = NULL;
list_append(ret_list, xstrdup(row[1]));
if (!name_char)
xstrfmtcat(name_char, "id='%s'", row[0]);
else
xstrfmtcat(name_char, " || id='%s'", row[0]);
if (!assoc_char)
xstrfmtcat(assoc_char, "id_qos='%s'", row[0]);
else
xstrfmtcat(assoc_char, " || id_qos='%s'", row[0]);
xstrfmtcat(extra,
", qos=replace(qos, ',%s', '')"
", delta_qos=replace(delta_qos, ',+%s', '')"
", delta_qos=replace(delta_qos, ',-%s', '')",
row[0], row[0], row[0]);
qos_rec = xmalloc(sizeof(slurmdb_qos_rec_t));
/* we only need id when removing no real need to init */
qos_rec->id = slurm_atoul(row[0]);
if (addto_update_list(mysql_conn->update_list,
SLURMDB_REMOVE_QOS, qos_rec)
!= SLURM_SUCCESS)
slurmdb_destroy_qos_rec(qos_rec);
}
mysql_free_result(result);
if (!list_count(ret_list)) {
errno = SLURM_NO_CHANGE_IN_DATA;
debug3("didn't effect anything\n%s", query);
xfree(query);
return ret_list;
}
xfree(query);
/* remove this qos from all the users/accts that have it */
query = xstrdup_printf("update %s set mod_time=%ld %s where deleted=0;",
assoc_table, now, extra);
xfree(extra);
debug3("%d(%s:%d) query\n%s",
mysql_conn->conn, THIS_FILE, __LINE__, query);
rc = mysql_db_query(mysql_conn, query);
xfree(query);
if (rc != SLURM_SUCCESS) {
reset_mysql_conn(mysql_conn);
list_destroy(ret_list);
return NULL;
}
user_name = uid_to_string((uid_t) uid);
slurm_mutex_lock(&as_mysql_cluster_list_lock);
itr = list_iterator_create(as_mysql_cluster_list);
while ((object = list_next(itr))) {
if ((rc = remove_common(mysql_conn, DBD_REMOVE_QOS, now,
user_name, qos_table, name_char,
assoc_char, object, NULL, NULL))
!= SLURM_SUCCESS)
break;
}
list_iterator_destroy(itr);
slurm_mutex_unlock(&as_mysql_cluster_list_lock);
xfree(assoc_char);
xfree(name_char);
xfree(user_name);
if (rc == SLURM_ERROR) {
list_destroy(ret_list);
return NULL;
}
return ret_list;
}
extern List as_mysql_get_qos(mysql_conn_t *mysql_conn, uid_t uid,
slurmdb_qos_cond_t *qos_cond)
{
char *query = NULL;
char *extra = NULL;
char *tmp = NULL;
List qos_list = NULL;
ListIterator itr = NULL;
char *object = NULL;
int set = 0;
int i=0;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
/* if this changes you will need to edit the corresponding enum */
char *qos_req_inx[] = {
"name",
"description",
"id",
"flags",
"grace_time",
"grp_cpu_mins",
"grp_cpu_run_mins",
"grp_cpus",
"grp_jobs",
"grp_nodes",
"grp_submit_jobs",
"grp_wall",
"max_cpu_mins_per_job",
"max_cpu_run_mins_per_user",
"max_cpus_per_job",
"max_cpus_per_user",
"max_jobs_per_user",
"max_nodes_per_job",
"max_nodes_per_user",
"max_submit_jobs_per_user",
"max_wall_duration_per_job",
"preempt",
"preempt_mode",
"priority",
"usage_factor",
"usage_thres",
};
enum {
QOS_REQ_NAME,
QOS_REQ_DESC,
QOS_REQ_ID,
QOS_REQ_FLAGS,
QOS_REQ_GRACE,
QOS_REQ_GCM,
QOS_REQ_GCRM,
QOS_REQ_GC,
QOS_REQ_GJ,
QOS_REQ_GN,
QOS_REQ_GSJ,
QOS_REQ_GW,
QOS_REQ_MCMPJ,
QOS_REQ_MCRM,
QOS_REQ_MCPJ,
QOS_REQ_MCPU,
QOS_REQ_MJPU,
QOS_REQ_MNPJ,
QOS_REQ_MNPU,
QOS_REQ_MSJPU,
QOS_REQ_MWPJ,
QOS_REQ_PREE,
QOS_REQ_PREEM,
QOS_REQ_PRIO,
QOS_REQ_UF,
QOS_REQ_UT,
QOS_REQ_COUNT
};
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
if (!qos_cond) {
xstrcat(extra, "where deleted=0");
goto empty;
}
if (qos_cond->with_deleted)
xstrcat(extra, "where (deleted=0 || deleted=1)");
else
xstrcat(extra, "where deleted=0");
if (qos_cond->description_list
&& list_count(qos_cond->description_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->description_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "description='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->id_list
&& list_count(qos_cond->id_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->id_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "id='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (qos_cond->name_list
&& list_count(qos_cond->name_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(qos_cond->name_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "name='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
empty:
xfree(tmp);
xstrfmtcat(tmp, "%s", qos_req_inx[i]);
for(i=1; i<QOS_REQ_COUNT; i++) {
xstrfmtcat(tmp, ", %s", qos_req_inx[i]);
}
query = xstrdup_printf("select %s from %s %s", tmp, qos_table, extra);
xfree(tmp);
xfree(extra);
debug3("%d(%s:%d) query\n%s",
mysql_conn->conn, THIS_FILE, __LINE__, query);
if (!(result = mysql_db_query_ret(
mysql_conn, query, 0))) {
xfree(query);
return NULL;
}
xfree(query);
qos_list = list_create(slurmdb_destroy_qos_rec);
while ((row = mysql_fetch_row(result))) {
slurmdb_qos_rec_t *qos = xmalloc(sizeof(slurmdb_qos_rec_t));
list_append(qos_list, qos);
if (row[QOS_REQ_DESC] && row[QOS_REQ_DESC][0])
qos->description = xstrdup(row[QOS_REQ_DESC]);
qos->id = slurm_atoul(row[QOS_REQ_ID]);
qos->flags = slurm_atoul(row[QOS_REQ_FLAGS]);
if (row[QOS_REQ_NAME] && row[QOS_REQ_NAME][0])
qos->name = xstrdup(row[QOS_REQ_NAME]);
if (row[QOS_REQ_GRACE])
qos->grace_time = slurm_atoul(row[QOS_REQ_GRACE]);
if (row[QOS_REQ_GCM])
qos->grp_cpu_mins = slurm_atoull(row[QOS_REQ_GCM]);
else
qos->grp_cpu_mins = INFINITE;
if (row[QOS_REQ_GCRM])
qos->grp_cpu_run_mins = slurm_atoull(row[QOS_REQ_GCRM]);
else
qos->grp_cpu_run_mins = INFINITE;
if (row[QOS_REQ_GC])
qos->grp_cpus = slurm_atoul(row[QOS_REQ_GC]);
else
qos->grp_cpus = INFINITE;
if (row[QOS_REQ_GJ])
qos->grp_jobs = slurm_atoul(row[QOS_REQ_GJ]);
else
qos->grp_jobs = INFINITE;
if (row[QOS_REQ_GN])
qos->grp_nodes = slurm_atoul(row[QOS_REQ_GN]);
else
qos->grp_nodes = INFINITE;
if (row[QOS_REQ_GSJ])
qos->grp_submit_jobs = slurm_atoul(row[QOS_REQ_GSJ]);
else
qos->grp_submit_jobs = INFINITE;
if (row[QOS_REQ_GW])
qos->grp_wall = slurm_atoul(row[QOS_REQ_GW]);
else
qos->grp_wall = INFINITE;
if (row[QOS_REQ_MCMPJ])
qos->max_cpu_mins_pj = slurm_atoull(row[QOS_REQ_MCMPJ]);
else
qos->max_cpu_mins_pj = (uint64_t)INFINITE;
if (row[QOS_REQ_MCRM])
qos->max_cpu_run_mins_pu =
slurm_atoull(row[QOS_REQ_MCRM]);
else
qos->max_cpu_run_mins_pu = (uint64_t)INFINITE;
if (row[QOS_REQ_MCPJ])
qos->max_cpus_pj = slurm_atoul(row[QOS_REQ_MCPJ]);
else
qos->max_cpus_pj = INFINITE;
if (row[QOS_REQ_MCPU])
qos->max_cpus_pu = slurm_atoul(row[QOS_REQ_MCPU]);
else
qos->max_cpus_pu = INFINITE;
if (row[QOS_REQ_MJPU])
qos->max_jobs_pu = slurm_atoul(row[QOS_REQ_MJPU]);
else
qos->max_jobs_pu = INFINITE;
if (row[QOS_REQ_MNPJ])
qos->max_nodes_pj = slurm_atoul(row[QOS_REQ_MNPJ]);
else
qos->max_nodes_pj = INFINITE;
if (row[QOS_REQ_MNPU])
qos->max_nodes_pu = slurm_atoul(row[QOS_REQ_MNPU]);
else
qos->max_nodes_pu = INFINITE;
if (row[QOS_REQ_MSJPU])
qos->max_submit_jobs_pu =
slurm_atoul(row[QOS_REQ_MSJPU]);
else
qos->max_submit_jobs_pu = INFINITE;
if (row[QOS_REQ_MWPJ])
qos->max_wall_pj = slurm_atoul(row[QOS_REQ_MWPJ]);
else
qos->max_wall_pj = INFINITE;
if (row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) {
if (!qos->preempt_bitstr)
qos->preempt_bitstr = bit_alloc(g_qos_count);
bit_unfmt(qos->preempt_bitstr, row[QOS_REQ_PREE]+1);
}
if (row[QOS_REQ_PREEM])
qos->preempt_mode = slurm_atoul(row[QOS_REQ_PREEM]);
if (row[QOS_REQ_PRIO])
qos->priority = slurm_atoul(row[QOS_REQ_PRIO]);
if (row[QOS_REQ_UF])
qos->usage_factor = atof(row[QOS_REQ_UF]);
if (row[QOS_REQ_UT])
qos->usage_thres = atof(row[QOS_REQ_UT]);
else
qos->usage_thres = (double)INFINITE;
}
mysql_free_result(result);
return qos_list;
}