diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c index d54dce49fdb6b1da138e73fdedb6bee7088e33e9..f2429b1d00642d412aab77f066449d360a00fd59 100644 --- a/src/common/assoc_mgr.c +++ b/src/common/assoc_mgr.c @@ -50,8 +50,8 @@ #define ASSOC_USAGE_VERSION 1 acct_association_rec_t *assoc_mgr_root_assoc = NULL; -uint32_t qos_max_priority = 0; - +uint32_t g_qos_max_priority = 0; +uint32_t g_qos_count = 0; List assoc_mgr_association_list = NULL; List assoc_mgr_qos_list = NULL; List assoc_mgr_user_list = NULL; @@ -287,6 +287,19 @@ static int _set_assoc_parent_and_user(acct_association_rec_t *assoc, assoc->uid = (uint32_t)NO_VAL; else assoc->uid = pw_uid; + + /* get the qos bitmap here */ + if(g_qos_count > 0) { + if(!assoc->valid_qos + || (bit_size(assoc->valid_qos) != g_qos_count)) { + FREE_NULL_BITMAP(assoc->valid_qos); + assoc->valid_qos = bit_alloc(g_qos_count); + } else + bit_nclear(assoc->valid_qos, 0, + (bit_size(assoc->valid_qos) - 1)); + set_qos_bitstr_from_list(assoc->valid_qos, + assoc->qos_list); + } } else { assoc->uid = (uint32_t)NO_VAL; } @@ -304,7 +317,7 @@ static int _post_association_list(List assoc_list) if(!assoc_list) return SLURM_ERROR; - + itr = list_iterator_create(assoc_list); //START_TIMER; while((assoc = list_next(itr))) { @@ -452,16 +465,27 @@ static int _get_assoc_mgr_qos_list(void *db_conn, int enforce) ListIterator itr = list_iterator_create(assoc_mgr_qos_list); acct_qos_rec_t *qos = NULL; while((qos = list_next(itr))) { - if(qos->priority > qos_max_priority) - qos_max_priority = qos->priority; + /* get the highest qos value to create bitmaps + from */ + if(qos->id > g_qos_count) + g_qos_count = qos->id; + + if(qos->priority > g_qos_max_priority) + g_qos_max_priority = qos->priority; } + /* Since in the database id's don't start at 1 + instead of 0 we need to ignore the 0 bit and start + with 1 so increase the count by 1. + */ + if(g_qos_count > 0) + g_qos_count++; - if(qos_max_priority) { + if(g_qos_max_priority) { list_iterator_reset(itr); while((qos = list_next(itr))) { qos->norm_priority = (double)qos->priority - / (double)qos_max_priority; + / (double)g_qos_max_priority; } } list_iterator_destroy(itr); @@ -772,16 +796,17 @@ extern int assoc_mgr_init(void *db_conn, assoc_init_args_t *args) if(errno == ESLURM_ACCESS_DENIED) return SLURM_ERROR; + /* get qos before association since it is used there */ + if((!assoc_mgr_qos_list) && (cache_level & ASSOC_MGR_CACHE_QOS)) + if(_get_assoc_mgr_qos_list(db_conn, enforce) == SLURM_ERROR) + return SLURM_ERROR; + if((!assoc_mgr_association_list) && (cache_level & ASSOC_MGR_CACHE_ASSOC)) if(_get_assoc_mgr_association_list(db_conn, enforce) == SLURM_ERROR) return SLURM_ERROR; - if((!assoc_mgr_qos_list) && (cache_level & ASSOC_MGR_CACHE_QOS)) - if(_get_assoc_mgr_qos_list(db_conn, enforce) == SLURM_ERROR) - return SLURM_ERROR; - if((!assoc_mgr_user_list) && (cache_level & ASSOC_MGR_CACHE_USER)) if(_get_assoc_mgr_user_list(db_conn, enforce) == SLURM_ERROR) return SLURM_ERROR; @@ -1158,10 +1183,8 @@ extern int assoc_mgr_fill_in_qos(void *db_conn, acct_qos_rec_t *qos, qos->norm_priority = found_qos->norm_priority; - if(!qos->preemptee_list) - qos->preemptee_list = found_qos->preemptee_list; - if(!qos->preemptor_list) - qos->preemptor_list = found_qos->preemptor_list; + if(!qos->preempt_bitstr) + qos->preempt_bitstr = found_qos->preempt_bitstr; qos->priority = found_qos->priority; @@ -2025,10 +2048,11 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update) acct_association_rec_t *assoc = NULL; int rc = SLURM_SUCCESS; + bool resize_qos_bitstr = 0; - if(!assoc_mgr_qos_list) + if(!assoc_mgr_qos_list) return SLURM_SUCCESS; - + slurm_mutex_lock(&assoc_mgr_qos_lock); itr = list_iterator_create(assoc_mgr_qos_list); while((object = list_pop(update->objects))) { @@ -2047,7 +2071,12 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update) break; } list_append(assoc_mgr_qos_list, object); - object = NULL; + if(object->id+1 > g_qos_count) { + resize_qos_bitstr = 1; + g_qos_count = object->id+1; + } + object = NULL; + break; case ACCT_MODIFY_QOS: /* FIX ME: fill in here the qos changes stuff */ @@ -2088,6 +2117,18 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update) } destroy_acct_qos_rec(object); } + + if(resize_qos_bitstr) { + list_iterator_reset(itr); + while((rec = list_next(itr))) { + if(!object->preempt_bitstr) + continue; + + object->preempt_bitstr = + bit_realloc(object->preempt_bitstr, + g_qos_count); + } + } list_iterator_destroy(itr); slurm_mutex_unlock(&assoc_mgr_qos_lock); diff --git a/src/common/pack.h b/src/common/pack.h index a3980de6e2294abe852e318f18dc59924e070016..3b16d15adcdba1cc9b6c661e2cb6929f26fb8988 100644 --- a/src/common/pack.h +++ b/src/common/pack.h @@ -320,6 +320,38 @@ int unpackmem_array(char *valp, uint32_t size_valp, Buf buffer); packmem(_tmp_str,_size,buf); \ } else \ packmem(NULL,(uint32_t)0,buf); \ +} while (0) + +#define pack_bit_str(bitmap,buf) do { \ + assert(buf->magic == BUF_MAGIC); \ + if (bitmap) { \ + char _tmp_str[0xfffe]; \ + uint32_t _size; \ + bit_fmt(_tmp_str,0xfffe,bitmap); \ + _size = bit_size(bitmap); \ + pack32(_size, buf); \ + _size = strlen(_tmp_str)+1; \ + packmem(_tmp_str,_size,buf); \ + } else \ + pack32(NO_VAL, buf); \ +} while (0) + +#define unpack_bit_str(bitmap,buf) do { \ + assert(bitmap != NULL); \ + assert(*bitmap == NULL); \ + assert(buf->magic == BUF_MAGIC); \ + if (bitmap) { \ + char *tmp_str = NULL; \ + uint32_t _size = NO_VAL; \ + safe_unpack32(&_size, buf); \ + if(_size != NO_VAL) { \ + *bitmap = bit_alloc(_size); \ + safe_unpackstr_xmalloc(&tmp_str, &_size, buf); \ + bit_unfmt(*bitmap, tmp_str); \ + xfree(tmp_str); \ + } else \ + *bitmap = NULL; \ + } \ } while (0) #define unpackstr_ptr \ diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c index 2d5d79a41665761d29f28e4d97bcd081aea1b669..22287e56d54119ff06f16db7ff0acd1f384f07ce 100644 --- a/src/common/slurm_accounting_storage.c +++ b/src/common/slurm_accounting_storage.c @@ -553,6 +553,7 @@ extern void destroy_acct_association_rec(void *object) if(acct_association->qos_list) list_destroy(acct_association->qos_list); xfree(acct_association->user); + FREE_NULL_BITMAP(acct_association->valid_qos); xfree(acct_association); } } @@ -566,10 +567,9 @@ extern void destroy_acct_qos_rec(void *object) if(acct_qos->job_list) list_destroy(acct_qos->job_list); xfree(acct_qos->name); - if(acct_qos->preemptee_list) - list_destroy(acct_qos->preemptee_list); - if(acct_qos->preemptor_list) - list_destroy(acct_qos->preemptor_list); + FREE_NULL_BITMAP(acct_qos->preempt_bitstr); + if(acct_qos->preempt_list) + list_destroy(acct_qos->preempt_list); if(acct_qos->user_limit_list) list_destroy(acct_qos->user_limit_list); xfree(acct_qos); @@ -2362,8 +2362,8 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) acct_qos_rec_t *object = (acct_qos_rec_t *)in; uint32_t count = NO_VAL; char *tmp_info = NULL; - - if(rpc_version >= 5) { + + if(rpc_version >= 6) { if(!object) { packnull(buffer); pack32(0, buffer); @@ -2385,7 +2385,7 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) packnull(buffer); - pack32(NO_VAL, buffer); + pack_bit_str(NULL, buffer); pack32(NO_VAL, buffer); pack32(0, buffer); @@ -2414,34 +2414,22 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) packstr(object->name, buffer); - if(object->preemptee_list) - count = list_count(object->preemptee_list); - - pack32(count, buffer); - - if(count && count != NO_VAL) { - itr = list_iterator_create(object->preemptee_list); - while((tmp_info = list_next(itr))) { - packstr(tmp_info, buffer); - } - list_iterator_destroy(itr); - } - count = NO_VAL; + pack_bit_str(object->preempt_bitstr, buffer); - if(object->preemptor_list) - count = list_count(object->preemptor_list); + if(object->preempt_list) + count = list_count(object->preempt_list); pack32(count, buffer); if(count && count != NO_VAL) { - itr = list_iterator_create(object->preemptor_list); + itr = list_iterator_create(object->preempt_list); while((tmp_info = list_next(itr))) { packstr(tmp_info, buffer); } list_iterator_destroy(itr); } count = NO_VAL; - + pack32(object->priority, buffer); packdouble(object->usage_factor, buffer); @@ -2461,7 +2449,7 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) list_iterator_destroy(itr); } count = NO_VAL; - } else if(rpc_version >= 3) { + } else if(rpc_version >= 5) { if(!object) { packnull(buffer); pack32(0, buffer); @@ -2488,6 +2476,8 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) pack32(0, buffer); + packdouble(NO_VAL, buffer); + pack32(NO_VAL, buffer); return; } @@ -2510,33 +2500,87 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer) packstr(object->name, buffer); - if(object->preemptee_list) - count = list_count(object->preemptee_list); + /* These are here for the old preemptee preemptor + lists we could figure this out from the + preempt_bitstr, but qos wasn't used for anything + before rpc_version 6 so just send NO_VALS */ + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + + pack32(object->priority, buffer); + + packdouble(object->usage_factor, buffer); + + if(object->user_limit_list) + count = list_count(object->user_limit_list); pack32(count, buffer); if(count && count != NO_VAL) { - itr = list_iterator_create(object->preemptee_list); - while((tmp_info = list_next(itr))) { - packstr(tmp_info, buffer); + acct_used_limits_t *used_limits = NULL; + itr = list_iterator_create(object->user_limit_list); + while((used_limits = list_next(itr))) { + pack_acct_used_limits(used_limits, + rpc_version, buffer); } list_iterator_destroy(itr); } count = NO_VAL; - - if(object->preemptor_list) - count = list_count(object->preemptor_list); + } else if(rpc_version >= 3) { + if(!object) { + packnull(buffer); + pack32(0, buffer); + packnull(buffer); - pack32(count, buffer); + pack64(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); - if(count && count != NO_VAL) { - itr = list_iterator_create(object->preemptor_list); - while((tmp_info = list_next(itr))) { - packstr(tmp_info, buffer); - } - list_iterator_destroy(itr); + pack64(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + + packnull(buffer); + + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); + + pack32(0, buffer); + + pack32(NO_VAL, buffer); + return; } - count = NO_VAL; + packstr(object->description, buffer); + pack32(object->id, buffer); + + pack64(object->grp_cpu_mins, buffer); + pack32(object->grp_cpus, buffer); + pack32(object->grp_jobs, buffer); + pack32(object->grp_nodes, buffer); + pack32(object->grp_submit_jobs, buffer); + pack32(object->grp_wall, buffer); + + pack64(object->max_cpu_mins_pu, buffer); + pack32(object->max_cpus_pu, buffer); + pack32(object->max_jobs_pu, buffer); + pack32(object->max_nodes_pu, buffer); + pack32(object->max_submit_jobs_pu, buffer); + pack32(object->max_wall_pu, buffer); + + packstr(object->name, buffer); + + /* These are here for the old preemptee preemptor + lists we could figure this out from the + preempt_bitstr, but qos wasn't used for anything + before rpc_version 6 so just send NO_VALS */ + pack32(NO_VAL, buffer); + pack32(NO_VAL, buffer); pack32(object->priority, buffer); @@ -2580,7 +2624,7 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer) init_acct_qos_rec(object_ptr); - if(rpc_version >= 5) { + if(rpc_version >= 6) { safe_unpackstr_xmalloc(&object_ptr->description, &uint32_tmp, buffer); safe_unpack32(&object_ptr->id, buffer); @@ -2601,30 +2645,83 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer) safe_unpackstr_xmalloc(&object_ptr->name, &uint32_tmp, buffer); + unpack_bit_str(&object_ptr->preempt_bitstr, buffer); + safe_unpack32(&count, buffer); if(count != NO_VAL) { - object_ptr->preemptee_list = + object_ptr->preempt_list = list_create(slurm_destroy_char); for(i=0; i<count; i++) { safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp, buffer); - list_append(object_ptr->preemptee_list, + list_append(object_ptr->preempt_list, tmp_info); } } + + safe_unpack32(&object_ptr->priority, buffer); + + safe_unpackdouble(&object_ptr->usage_factor, buffer); + + safe_unpack32(&count, buffer); + if(count != NO_VAL) { + void *used_limits = NULL; + + object_ptr->user_limit_list = + list_create(slurm_destroy_char); + for(i=0; i<count; i++) { + unpack_acct_used_limits(&used_limits, + rpc_version, buffer); + list_append(object_ptr->user_limit_list, + used_limits); + } + } + + } else if(rpc_version >= 5) { + safe_unpackstr_xmalloc(&object_ptr->description, + &uint32_tmp, buffer); + safe_unpack32(&object_ptr->id, buffer); + + safe_unpack64(&object_ptr->grp_cpu_mins, buffer); + safe_unpack32(&object_ptr->grp_cpus, buffer); + safe_unpack32(&object_ptr->grp_jobs, buffer); + safe_unpack32(&object_ptr->grp_nodes, buffer); + safe_unpack32(&object_ptr->grp_submit_jobs, buffer); + safe_unpack32(&object_ptr->grp_wall, buffer); + + safe_unpack64(&object_ptr->max_cpu_mins_pu, buffer); + safe_unpack32(&object_ptr->max_cpus_pu, buffer); + safe_unpack32(&object_ptr->max_jobs_pu, buffer); + safe_unpack32(&object_ptr->max_nodes_pu, buffer); + safe_unpack32(&object_ptr->max_submit_jobs_pu, buffer); + safe_unpack32(&object_ptr->max_wall_pu, buffer); + + safe_unpackstr_xmalloc(&object_ptr->name, &uint32_tmp, buffer); safe_unpack32(&count, buffer); if(count != NO_VAL) { - object_ptr->preemptor_list = + object_ptr->preempt_list = list_create(slurm_destroy_char); for(i=0; i<count; i++) { safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp, buffer); - list_append(object_ptr->preemptor_list, + list_append(object_ptr->preempt_list, tmp_info); } } + /* this is here for the old preemptor list. which was + never used so just throw anything here away. + */ + safe_unpack32(&count, buffer); + if(count != NO_VAL) { + for(i=0; i<count; i++) { + safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp, + buffer); + xfree(tmp_info); + } + } + safe_unpack32(&object_ptr->priority, buffer); safe_unpackdouble(&object_ptr->usage_factor, buffer); @@ -2666,25 +2763,25 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer) safe_unpack32(&count, buffer); if(count != NO_VAL) { - object_ptr->preemptee_list = + object_ptr->preempt_list = list_create(slurm_destroy_char); for(i=0; i<count; i++) { safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp, buffer); - list_append(object_ptr->preemptee_list, + list_append(object_ptr->preempt_list, tmp_info); } } + /* this is here for the old preemptor list. which was + never used so just throw anything here away. + */ safe_unpack32(&count, buffer); if(count != NO_VAL) { - object_ptr->preemptor_list = - list_create(slurm_destroy_char); for(i=0; i<count; i++) { safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp, buffer); - list_append(object_ptr->preemptor_list, - tmp_info); + xfree(tmp_info); } } @@ -7194,6 +7291,78 @@ extern char *get_tree_acct_name(char *name, char *parent, List tree_list) return acct_print_tree->print_name; } +extern int set_qos_bitstr_from_list(bitstr_t *valid_qos, List qos_list) +{ + ListIterator itr = NULL; + bitoff_t bit = 0; + int rc = SLURM_SUCCESS; + char *temp_char = NULL; + void (*my_function) (bitstr_t *b, bitoff_t bit); + + xassert(valid_qos); + + if(!qos_list) + return SLURM_ERROR; + + itr = list_iterator_create(qos_list); + while((temp_char = list_next(itr))) { + if(temp_char[0] == '-') { + temp_char++; + my_function = bit_clear; + } else if(temp_char[0] == '+') { + temp_char++; + my_function = bit_set; + } else + my_function = bit_set; + bit = atoi(temp_char); + if(bit >= bit_size(valid_qos)) { + rc = SLURM_ERROR; + break; + } + (*(my_function))(valid_qos, bit); + } + list_iterator_destroy(itr); + + return rc; +} + +extern char *get_qos_complete_str_bitstr(List qos_list, bitstr_t *valid_qos) +{ + List temp_list = NULL; + char *temp_char = NULL; + char *print_this = NULL; + ListIterator itr = NULL; + int i = 0; + + if(!qos_list || !list_count(qos_list) + || !valid_qos || (bit_ffs(valid_qos) == -1)) + return xstrdup(""); + + temp_list = list_create(NULL); + + for(i=0; i<bit_size(valid_qos); i++) { + if(!bit_test(valid_qos, i)) + continue; + if((temp_char = acct_qos_str(qos_list, i))) + list_append(temp_list, temp_char); + } + list_sort(temp_list, (ListCmpF)slurm_sort_char_list_asc); + itr = list_iterator_create(temp_list); + while((temp_char = list_next(itr))) { + if(print_this) + xstrfmtcat(print_this, ",%s", temp_char); + else + print_this = xstrdup(temp_char); + } + list_iterator_destroy(itr); + list_destroy(temp_list); + + if(!print_this) + return xstrdup(""); + + return print_this; +} + extern char *get_qos_complete_str(List qos_list, List num_qos_list) { List temp_list = NULL; diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h index 23b862391b7626b8c6f494edd8bceb78a3233cb2..fbe7b53a335d713ba964fc31f47ff9da0d8b6307 100644 --- a/src/common/slurm_accounting_storage.h +++ b/src/common/slurm_accounting_storage.h @@ -244,6 +244,8 @@ typedef struct acct_association_rec { * (DON'T PACK) */ char *user; /* user associated to association */ + bitstr_t *valid_qos; /* qos available for this association + * (DON'T PACK) */ } acct_association_rec_t; typedef struct { @@ -340,10 +342,8 @@ typedef struct { char *name; double norm_priority;/* normalized priority (DON'T PACK) */ - List preemptee_list; /* list of char * list of qos's that this - qos can preempt */ - List preemptor_list; /* list of char * list of qos's that this - * qos is preempted by */ + bitstr_t *preempt_bitstr; /* other qos' this qos can preempt */ + List preempt_list; /* list of char *'s */ uint32_t priority; /* ranged int needs to be a unint for * heterogeneous systems */ double usage_factor; /* factor to apply to usage in this qos */ @@ -553,7 +553,8 @@ typedef struct { insert of jobs since past */ } acct_archive_rec_t; -extern uint32_t qos_max_priority; /* max priority in all qos's */ +extern uint32_t g_qos_max_priority; /* max priority in all qos's */ +extern uint32_t g_qos_count; /* count used for generating qos bitstr's */ extern void destroy_acct_user_rec(void *object); extern void destroy_acct_account_rec(void *object); @@ -689,6 +690,8 @@ extern List get_acct_hierarchical_rec_list(List assoc_list); /* IN/OUT: tree_list a list of acct_print_tree_t's */ extern char *get_tree_acct_name(char *name, char *parent, List tree_list); +extern int set_qos_bitstr_from_list(bitstr_t *valid_qos, List qos_list); +extern char *get_qos_complete_str_bitstr(List qos_list, bitstr_t *valid_qos); extern char *get_qos_complete_str(List qos_list, List num_qos_list); extern char *get_classification_str(uint16_t class); diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index a01f26918fab3a473f38c2561167c665ae0a0d6b..afff3df0fa5e4e6a19fb2b43044425c33d8eea74 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -161,6 +161,34 @@ extern List acct_storage_p_remove_wckeys(mysql_conn_t *mysql_conn, uint32_t uid, acct_wckey_cond_t *wckey_cond); +static int _set_qos_cnt(MYSQL *db_conn) +{ + MYSQL_RES *result = NULL; + MYSQL_ROW row; + char *query = xstrdup_printf("select MAX(id) from %s", qos_table); + + if(!(result = mysql_db_query_ret(db_conn, query, 0))) { + xfree(query); + return SLURM_ERROR; + } + xfree(query); + + if(!(row = mysql_fetch_row(result))) { + mysql_free_result(result); + return SLURM_ERROR; + } + + /* Set the current qos_count on the system for + generating bitstr of that length. Since 0 isn't + possible as an id we add 1 to the total to burn 0 and + start at the 1 bit. + */ + g_qos_count = atoi(row[0]) + 1; + mysql_free_result(result); + + return SLURM_SUCCESS; +} + static char *_get_cluster_from_associd(mysql_conn_t *mysql_conn, uint32_t associd) { @@ -670,7 +698,7 @@ end_qos: static int _setup_qos_limits(acct_qos_rec_t *qos, char **cols, char **vals, - char **extra, qos_level_t qos_level) + char **extra) { if(!qos) return SLURM_ERROR; @@ -822,44 +850,43 @@ static int _setup_qos_limits(acct_qos_rec_t *qos, xstrcat(*extra, ", max_wall_duration_per_user=NULL"); } - if((qos_level != QOS_LEVEL_MODIFY) - && qos->preemptee_list && list_count(qos->preemptee_list)) { - char *qos_val = NULL; - char *tmp_char = NULL; - ListIterator qos_itr = - list_iterator_create(qos->preemptee_list); - - xstrcat(*cols, ", qos"); - - while((tmp_char = list_next(qos_itr))) - xstrfmtcat(qos_val, ",%s", tmp_char); + 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); - list_iterator_destroy(qos_itr); - - xstrfmtcat(*vals, ", \"%s\"", qos_val); - xstrfmtcat(*extra, ", preemptees=\"%s\"", qos_val); - xfree(qos_val); - } + 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); + xfree(begin_preempt); + begin_preempt = preempt_val; + } else if(tmp_char[0]) + xstrfmtcat(preempt_val, ",%s", tmp_char); + else + xstrcat(preempt_val, ""); + } + list_iterator_destroy(preempt_itr); - if((qos_level != QOS_LEVEL_MODIFY) - && qos->preemptor_list && list_count(qos->preemptor_list)) { - char *qos_val = NULL; - char *tmp_char = NULL; - ListIterator qos_itr = - list_iterator_create(qos->preemptor_list); - - xstrcat(*cols, ", qos"); - - while((tmp_char = list_next(qos_itr))) - xstrfmtcat(qos_val, ",%s", tmp_char); - - list_iterator_destroy(qos_itr); - - xstrfmtcat(*vals, ", \"%s\"", qos_val); - xstrfmtcat(*extra, ", preemptors=\"%s\"", qos_val); - xfree(qos_val); + xstrfmtcat(*vals, ", \"%s\"", preempt_val); + xstrfmtcat(*extra, ", preempt=\"%s\"", preempt_val); + xfree(preempt_val); } - + if(qos->job_flags) { xstrcat(*cols, ", job_flags"); xstrfmtcat(*vals, ", \"%s\"", qos->job_flags); @@ -2990,8 +3017,7 @@ static int _mysql_acct_check_tables(MYSQL *db_conn) { "grp_wall", "int default NULL" }, { "grp_cpu_mins", "bigint default NULL" }, { "job_flags", "text" }, - { "preemptees", "text not null default ''" }, - { "preemptors", "text not null default ''" }, + { "preempt", "text not null default ''" }, { "priority", "int default 0" }, { "usage_factor", "double default 1.0 not null" }, { NULL, NULL} @@ -3296,10 +3322,15 @@ static int _mysql_acct_check_tables(MYSQL *db_conn) qos_id = mysql_insert_ret_id(db_conn, query); if(!qos_id) fatal("problem added qos 'normal"); + xstrfmtcat(default_qos_str, ",%d", qos_id); xfree(query); } + + if(_set_qos_cnt(db_conn) != SLURM_SUCCESS) + return SLURM_ERROR; } + if(mysql_db_create_table(db_conn, step_table, step_table_fields, ", primary key (id, stepid))") == SLURM_ERROR) @@ -3517,7 +3548,8 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit) slurm_msg_t resp; ListIterator itr = NULL; acct_update_object_t *object = NULL; - + bool get_qos_count = 0; + memset(&msg, 0, sizeof(accounting_update_msg_t)); msg.update_list = mysql_conn->update_list; @@ -3599,6 +3631,9 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit) rc = assoc_mgr_update_assocs(object); break; case ACCT_ADD_QOS: + /* we need to check the qos's here to + * get the correct count */ + get_qos_count = 1; case ACCT_MODIFY_QOS: case ACCT_REMOVE_QOS: rc = assoc_mgr_update_qos(object); @@ -3618,7 +3653,11 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit) list_delete_item(itr); } list_iterator_destroy(itr); + + if(get_qos_count) + _set_qos_cnt(mysql_conn->db_conn); } + list_flush(mysql_conn->update_list); return SLURM_SUCCESS; @@ -4617,8 +4656,7 @@ extern int acct_storage_p_add_qos(mysql_conn_t *mysql_conn, uint32_t uid, now, now, object->name); xstrfmtcat(extra, ", mod_time=%d", now); - _setup_qos_limits(object, &cols, &vals, &extra, - QOS_LEVEL_NONE); + _setup_qos_limits(object, &cols, &vals, &extra); xstrfmtcat(query, "insert into %s (%s) values (%s) " "on duplicate key update deleted=0, " @@ -5785,8 +5823,8 @@ end_it: } extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, - acct_qos_cond_t *qos_cond, - acct_qos_rec_t *qos) + acct_qos_cond_t *qos_cond, + acct_qos_rec_t *qos) { ListIterator itr = NULL; List ret_list = NULL; @@ -5799,7 +5837,6 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, MYSQL_RES *result = NULL; MYSQL_ROW row; char *tmp_char1=NULL, *tmp_char2=NULL; - int replace_preemptor = 0, replace_preemptee = 0; if(!qos_cond || !qos) { error("we need something to change"); @@ -5856,85 +5893,19 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, xstrcat(extra, ")"); } - _setup_qos_limits(qos, &tmp_char1, &tmp_char2, - &vals, QOS_LEVEL_MODIFY); + _setup_qos_limits(qos, &tmp_char1, &tmp_char2, &vals); xfree(tmp_char1); xfree(tmp_char2); - if(qos->preemptee_list && list_count(qos->preemptee_list)) { - char *tmp_qos = NULL; - set = 0; - itr = list_iterator_create(qos->preemptee_list); - while((object = list_next(itr))) { - /* when adding we need to make sure we don't - * already have it so we remove it and then add - * it. - */ - if(object[0] == '-') { - xstrfmtcat(vals, - ", preemptees=" - "replace(qos, ',%s', '')", - object+1); - } else if(object[0] == '+') { - xstrfmtcat(vals, - ", preemptees=concat_ws(',', " - "replace(preemptees, ',%s', ''), " - "\"%s\")", - object+1, object+1); - } else { - xstrfmtcat(tmp_qos, ",%s", object); - } - } - list_iterator_destroy(itr); - if(tmp_qos) { - xstrfmtcat(vals, ", preemptees='%s'", tmp_qos); - xfree(tmp_qos); - replace_preemptee = 1; - } - } - - if(qos->preemptor_list && list_count(qos->preemptor_list)) { - char *tmp_qos = NULL; - set = 0; - itr = list_iterator_create(qos->preemptor_list); - while((object = list_next(itr))) { - /* when adding we need to make sure we don't - * already have it so we remove it and then add - * it. - */ - if(object[0] == '-') { - xstrfmtcat(vals, - ", preemptors=" - "replace(qos, ',%s', '')", - object+1); - } else if(object[0] == '+') { - xstrfmtcat(vals, - ", preemptors=concat_ws(',', " - "replace(preemptors, ',%s', ''), " - "\"%s\")", - object+1, object+1); - } else { - xstrfmtcat(tmp_qos, ",%s", object); - } - } - list_iterator_destroy(itr); - if(tmp_qos) { - xstrfmtcat(vals, ", preemptors='%s'", tmp_qos); - xfree(tmp_qos); - replace_preemptor = 1; - } - } - if(!extra || !vals) { errno = SLURM_NO_CHANGE_IN_DATA; error("Nothing to change"); return NULL; } - query = xstrdup_printf("select name, preemptees, preemptors " - "from %s %s;", qos_table, extra); + query = xstrdup_printf("select name, preempt from %s %s;", + qos_table, extra); xfree(extra); - if(!(result = mysql_db_query_ret( - mysql_conn->db_conn, query, 0))) { + if(!(result = mysql_db_query_ret(mysql_conn->db_conn, query, 0))) { xfree(query); return NULL; } @@ -5971,112 +5942,36 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, qos_rec->priority = qos->priority; - if(qos->preemptee_list) { - ListIterator new_qos_itr = - list_iterator_create(qos->preemptee_list); - ListIterator curr_qos_itr = NULL; - char *new_qos = NULL, *curr_qos = NULL; - - qos_rec->preemptee_list = - list_create(slurm_destroy_char); - if(!replace_preemptee) - slurm_addto_char_list(qos_rec->preemptee_list, - row[1]); - curr_qos_itr = - list_iterator_create(qos_rec->preemptee_list); - - while((new_qos = list_next(new_qos_itr))) { - char *tmp_char = NULL; - if(new_qos[0] == '-') { - tmp_char = xstrdup(new_qos+1); - while((curr_qos = - list_next(curr_qos_itr))) { - if(!strcmp(curr_qos, - tmp_char)) { - list_delete_item( - curr_qos_itr); - break; - } - } - xfree(tmp_char); - list_iterator_reset(curr_qos_itr); - } else if(new_qos[0] == '+') { - tmp_char = xstrdup(new_qos+1); - while((curr_qos = - list_next(curr_qos_itr))) { - if(!strcmp(curr_qos, - tmp_char)) { - break; - } - } - if(!curr_qos) - list_append( - qos_rec->preemptee_list, - tmp_char); - else - xfree(tmp_char); - list_iterator_reset(curr_qos_itr); + if(qos->preempt_list) { + ListIterator new_preempt_itr = + list_iterator_create(qos->preempt_list); + char *new_preempt = NULL; + + qos->preempt_bitstr = bit_alloc(g_qos_count); + if(row[1] && row[1][0]) + bit_unfmt(qos->preempt_bitstr, row[1]+1); + + while((new_preempt = list_next(new_preempt_itr))) { + bool cleared = 0; + if(new_preempt[0] == '-') { + bit_clear(qos->preempt_bitstr, + atoi(new_preempt+1)); + } else if(new_preempt[0] == '+') { + bit_set(qos->preempt_bitstr, + atoi(new_preempt+1)); } else { - list_append(qos_rec->preemptee_list, - xstrdup(new_qos)); - } - } - list_iterator_destroy(curr_qos_itr); - list_iterator_destroy(new_qos_itr); - } - - if(qos->preemptor_list) { - ListIterator new_qos_itr = - list_iterator_create(qos->preemptor_list); - ListIterator curr_qos_itr = NULL; - char *new_qos = NULL, *curr_qos = NULL; - - qos_rec->preemptor_list = - list_create(slurm_destroy_char); - if(!replace_preemptor) - slurm_addto_char_list(qos_rec->preemptor_list, - row[2]); - curr_qos_itr = - list_iterator_create(qos_rec->preemptor_list); - - while((new_qos = list_next(new_qos_itr))) { - char *tmp_char = NULL; - if(new_qos[0] == '-') { - tmp_char = xstrdup(new_qos+1); - while((curr_qos = - list_next(curr_qos_itr))) { - if(!strcmp(curr_qos, - tmp_char)) { - list_delete_item( - curr_qos_itr); - break; - } - } - xfree(tmp_char); - list_iterator_reset(curr_qos_itr); - } else if(new_qos[0] == '+') { - tmp_char = xstrdup(new_qos+1); - while((curr_qos = - list_next(curr_qos_itr))) { - if(!strcmp(curr_qos, - tmp_char)) { - break; - } + if(!cleared) { + cleared = 1; + bit_nclear(qos->preempt_bitstr, + 0, + bit_size(qos->preempt_bitstr)-1); } - if(!curr_qos) - list_append( - qos_rec->preemptor_list, - tmp_char); - else - xfree(tmp_char); - list_iterator_reset(curr_qos_itr); - } else { - list_append(qos_rec->preemptor_list, - xstrdup(new_qos)); + + bit_set(qos->preempt_bitstr, + atoi(new_preempt)); } } - list_iterator_destroy(curr_qos_itr); - list_iterator_destroy(new_qos_itr); + list_iterator_destroy(new_preempt_itr); } _addto_update_list(mysql_conn->update_list, ACCT_MODIFY_QOS, @@ -8614,9 +8509,9 @@ empty: list_iterator_destroy(curr_qos_itr); list_flush(delta_qos_list); } - + assoc->parent_id = parent_id; - + //info("parent id is %d", assoc->parent_id); //log_assoc_rec(assoc); } @@ -8700,8 +8595,7 @@ extern List acct_storage_p_get_qos(mysql_conn_t *mysql_conn, uid_t uid, "max_submit_jobs_per_user", "max_wall_duration_per_user", "job_flags", - "preemptees", - "preemptors", + "preempt", "priority", "usage_factor", }; @@ -8723,7 +8617,6 @@ extern List acct_storage_p_get_qos(mysql_conn_t *mysql_conn, uid_t uid, QOS_REQ_MWPU, QOS_REQ_JOBF, QOS_REQ_PREE, - QOS_REQ_PREO, QOS_REQ_PRIO, QOS_REQ_UF, QOS_REQ_COUNT @@ -8820,7 +8713,7 @@ empty: qos->description = xstrdup(row[QOS_REQ_DESC]); qos->id = atoi(row[QOS_REQ_ID]); - + if(row[QOS_REQ_NAME] && row[QOS_REQ_NAME][0]) qos->name = xstrdup(row[QOS_REQ_NAME]); @@ -8877,18 +8770,9 @@ empty: else qos->max_wall_pu = INFINITE; - if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) { - qos->preemptee_list = list_create(slurm_destroy_char); - slurm_addto_char_list(qos->preemptee_list, - row[QOS_REQ_PREE]+1); - } - - if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) { - qos->preemptee_list = list_create(slurm_destroy_char); - slurm_addto_char_list(qos->preemptee_list, - row[QOS_REQ_PREE]+1); - } - + if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) + bit_unfmt(qos->preempt_bitstr, row[QOS_REQ_PREE]+1); + if(row[QOS_REQ_PRIO]) qos->priority = atoi(row[QOS_REQ_PRIO]); diff --git a/src/sacctmgr/common.c b/src/sacctmgr/common.c index 99819ca56930795a29079fa6f5ba3fb3138c341d..df8dc5896000b5caffdfbc15c7e92f3e5117310b 100644 --- a/src/sacctmgr/common.c +++ b/src/sacctmgr/common.c @@ -1060,6 +1060,31 @@ extern void sacctmgr_print_qos_list(print_field_t *field, List qos_list, xfree(print_this); } +extern void sacctmgr_print_qos_bitstr(print_field_t *field, List qos_list, + bitstr_t *value, int last) +{ + int abs_len = abs(field->len); + char *print_this = NULL; + + print_this = get_qos_complete_str_bitstr(qos_list, value); + + if(print_fields_parsable_print == PRINT_FIELDS_PARSABLE_NO_ENDING + && last) + printf("%s", print_this); + else if(print_fields_parsable_print) + printf("%s|", print_this); + else { + if(strlen(print_this) > abs_len) + print_this[abs_len-1] = '+'; + + if(field->len == abs_len) + printf("%*.*s ", abs_len, abs_len, print_this); + else + printf("%-*.*s ", abs_len, abs_len, print_this); + } + xfree(print_this); +} + extern void sacctmgr_print_assoc_limits(acct_association_rec_t *assoc) { if(!assoc) @@ -1161,7 +1186,7 @@ extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos) if(!qos) return; - if(qos->preemptee_list || qos->preemptor_list) + if(qos->preempt_list) qos_list = acct_storage_g_get_qos(db_conn, my_uid, NULL); if(qos->job_flags) @@ -1239,19 +1264,11 @@ extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos) printf(" MaxWall = %s\n", time_buf); } - if(qos->preemptee_list) { - char *temp_char = get_qos_complete_str(qos_list, - qos->preemptee_list); - if(temp_char) { - printf(" Preemptable by = %s\n", temp_char); - xfree(temp_char); - } - } - if(qos->preemptor_list) { + if(qos->preempt_list) { char *temp_char = get_qos_complete_str(qos_list, - qos->preemptee_list); + qos->preempt_list); if(temp_char) { - printf(" Can Preempt = %s\n", temp_char); + printf(" Preempt = %s\n", temp_char); xfree(temp_char); } } diff --git a/src/sacctmgr/qos_functions.c b/src/sacctmgr/qos_functions.c index a936b2dbf510c62d81215ce95989105b460f8d38..413b73c075754042912782279082d992a6ea73e3 100644 --- a/src/sacctmgr/qos_functions.c +++ b/src/sacctmgr/qos_functions.c @@ -281,38 +281,20 @@ static int _set_rec(int *start, int argc, char *argv[], " Bad MaxWall time format: %s\n", argv[i]); } - } else if (!strncasecmp (argv[i], "Preemptee", + } else if (!strncasecmp (argv[i], "Preempt", MAX(command_len, 9))) { if(!qos) continue; - if(!qos->preemptee_list) - qos->preemptee_list = + if(!qos->preempt_list) + qos->preempt_list = list_create(slurm_destroy_char); if(!qos_list) qos_list = acct_storage_g_get_qos( db_conn, my_uid, NULL); - if(addto_qos_char_list(qos->preemptee_list, - qos_list, argv[i]+end, option)) - set = 1; - else - exit_code = 1; - } else if (!strncasecmp (argv[i], "Preemptor", - MAX(command_len, 9))) { - if(!qos) - continue; - - if(!qos->preemptor_list) - qos->preemptor_list = - list_create(slurm_destroy_char); - - if(!qos_list) - qos_list = acct_storage_g_get_qos( - db_conn, my_uid, NULL); - - if(addto_qos_char_list(qos->preemptor_list, + if(addto_qos_char_list(qos->preempt_list, qos_list, argv[i]+end, option)) set = 1; else diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c index 459637807706638e4696d9e14c1c8c797349ddca..d7ed1517e5781f6a5fd4f26c6521db5e9cfbd05c 100644 --- a/src/sacctmgr/sacctmgr.c +++ b/src/sacctmgr/sacctmgr.c @@ -838,7 +838,7 @@ sacctmgr [<OPTION>] [<COMMAND>] \n\ add qos - Description=, GrpCPUMins=, GrpCPUs=, GrpJobs=, \n\ GrpNodes=, GrpSubmitJob=, GrpWall=, JobFlags=, \n\ MaxCPUMins=, MaxJobs=, MaxNodes=, MaxWall=, \n\ - Preemptee=, Preemptor=, Priority=, and Names= \n\ + Preempt=, Priority=, and Names= \n\ delete qos - Descriptions=, IDs=, and Names= \n\ \n\ list transactions - Accounts=, Action=, Actor=, Clusters=, End=, \n\ diff --git a/src/sacctmgr/sacctmgr.h b/src/sacctmgr/sacctmgr.h index 66af91003b2c1ef5f551a032d69b7c168eee30e4..d106c74f56dcb36b768f0f8bf11bf1aed088889b 100644 --- a/src/sacctmgr/sacctmgr.h +++ b/src/sacctmgr/sacctmgr.h @@ -150,6 +150,8 @@ extern void sacctmgr_print_coord_list( print_field_t *field, List value, int last); extern void sacctmgr_print_qos_list(print_field_t *field, List qos_list, List value, int last); +extern void sacctmgr_print_qos_bitstr(print_field_t *field, List qos_list, + bitstr_t *value, int last); extern void sacctmgr_print_assoc_limits(acct_association_rec_t *assoc); extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos);