1 /*****************************************************************************\
2 * slurmdb_defs.c - definitions used by slurmdb api
3 ******************************************************************************
4 * Copyright (C) 2010 Lawrence Livermore National Security.
5 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
6 * Written by Danny Auble da@llnl.gov, et. al.
7 * CODE-OCEC-09-009. All rights reserved.
8 *
9 * This file is part of Slurm, a resource management program.
10 * For details, see <https://slurm.schedmd.com/>.
11 * Please also read the included file: DISCLAIMER.
12 *
13 * Slurm is free software; you can redistribute it and/or modify it under
14 * the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
16 * any later version.
17 *
18 * In addition, as a special exception, the copyright holders give permission
19 * to link the code of portions of this program with the OpenSSL library under
20 * certain conditions as described in each individual source file, and
21 * distribute linked combinations including the two. You must obey the GNU
22 * General Public License in all respects for all of the code used other than
23 * OpenSSL. If you modify file(s) with this exception, you may extend this
24 * exception to your version of the file(s), but you are not obligated to do
25 * so. If you do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source files in
27 * the program, then also delete it here.
28 *
29 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
30 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
32 * details.
33 *
34 * You should have received a copy of the GNU General Public License along
35 * with Slurm; if not, write to the Free Software Foundation, Inc.,
36 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 \*****************************************************************************/
38
39 #include <stdlib.h>
40
41 #include "src/common/assoc_mgr.h"
42 #include "src/common/log.h"
43 #include "src/common/node_select.h"
44 #include "src/common/parse_time.h"
45 #include "src/common/slurm_auth.h"
46 #include "src/common/slurm_protocol_defs.h"
47 #include "src/common/slurm_jobacct_gather.h"
48 #include "src/common/slurm_time.h"
49 #include "src/common/slurmdb_defs.h"
50 #include "src/common/xmalloc.h"
51 #include "src/common/xstring.h"
52 #include "src/slurmdbd/read_config.h"
53
54 #define FORMAT_STRING_SIZE 34
55
56 slurmdb_cluster_rec_t *working_cluster_rec = NULL;
57
58 static char *local_cluster_name; /* name of local_cluster */
59
60 static void _free_res_cond_members(slurmdb_res_cond_t *res_cond);
61 static void _free_res_rec_members(slurmdb_res_rec_t *res);
62
63 strong_alias(get_qos_complete_str_bitstr, slurmdb_get_qos_complete_str_bitstr);
64
_free_clus_res_rec_members(slurmdb_clus_res_rec_t * clus_res)65 static void _free_clus_res_rec_members(slurmdb_clus_res_rec_t *clus_res)
66 {
67 if (clus_res) {
68 xfree(clus_res->cluster);
69 }
70 }
71
_free_cluster_rec_members(slurmdb_cluster_rec_t * cluster)72 static void _free_cluster_rec_members(slurmdb_cluster_rec_t *cluster)
73 {
74 if (cluster) {
75 FREE_NULL_LIST(cluster->accounting_list);
76 xfree(cluster->control_host);
77 xfree(cluster->dim_size);
78 FREE_NULL_LIST(cluster->fed.feature_list);
79 xfree(cluster->fed.name);
80 slurm_persist_conn_destroy(cluster->fed.recv);
81 slurm_persist_conn_destroy(cluster->fed.send);
82 slurm_mutex_destroy(&cluster->lock);
83 xfree(cluster->name);
84 xfree(cluster->nodes);
85 slurmdb_destroy_assoc_rec(cluster->root_assoc);
86 FREE_NULL_LIST(cluster->send_rpc);
87 xfree(cluster->tres_str);
88 }
89 }
90
_free_federation_rec_members(slurmdb_federation_rec_t * federation)91 static void _free_federation_rec_members(slurmdb_federation_rec_t *federation)
92 {
93 if (federation) {
94 xfree(federation->name);
95 FREE_NULL_LIST(federation->cluster_list);
96 }
97 }
98
_free_wckey_rec_members(slurmdb_wckey_rec_t * wckey)99 static void _free_wckey_rec_members(slurmdb_wckey_rec_t *wckey)
100 {
101 if (wckey) {
102 FREE_NULL_LIST(wckey->accounting_list);
103 xfree(wckey->cluster);
104 xfree(wckey->name);
105 xfree(wckey->user);
106 }
107 }
108
_free_cluster_cond_members(slurmdb_cluster_cond_t * cluster_cond)109 static void _free_cluster_cond_members(slurmdb_cluster_cond_t *cluster_cond)
110 {
111 if (cluster_cond) {
112 FREE_NULL_LIST(cluster_cond->cluster_list);
113 FREE_NULL_LIST(cluster_cond->federation_list);
114 FREE_NULL_LIST(cluster_cond->format_list);
115 FREE_NULL_LIST(cluster_cond->plugin_id_select_list);
116 FREE_NULL_LIST(cluster_cond->rpc_version_list);
117 }
118 }
119
_free_federation_cond_members(slurmdb_federation_cond_t * fed_cond)120 static void _free_federation_cond_members(slurmdb_federation_cond_t *fed_cond)
121 {
122 if (fed_cond) {
123 FREE_NULL_LIST(fed_cond->cluster_list);
124 FREE_NULL_LIST(fed_cond->federation_list);
125 }
126 }
127
_free_tres_cond_members(slurmdb_tres_cond_t * tres_cond)128 static void _free_tres_cond_members(slurmdb_tres_cond_t *tres_cond)
129 {
130 if (tres_cond) {
131 FREE_NULL_LIST(tres_cond->id_list);
132 FREE_NULL_LIST(tres_cond->name_list);
133 FREE_NULL_LIST(tres_cond->type_list);
134 }
135 }
136
_free_res_cond_members(slurmdb_res_cond_t * res_cond)137 static void _free_res_cond_members(slurmdb_res_cond_t *res_cond)
138 {
139 if (res_cond) {
140 FREE_NULL_LIST(res_cond->cluster_list);
141 FREE_NULL_LIST(res_cond->description_list);
142 FREE_NULL_LIST(res_cond->id_list);
143 FREE_NULL_LIST(res_cond->manager_list);
144 FREE_NULL_LIST(res_cond->name_list);
145 FREE_NULL_LIST(res_cond->percent_list);
146 FREE_NULL_LIST(res_cond->server_list);
147 FREE_NULL_LIST(res_cond->type_list);
148 }
149 }
150
_free_res_rec_members(slurmdb_res_rec_t * res)151 static void _free_res_rec_members(slurmdb_res_rec_t *res)
152 {
153 if (res) {
154 FREE_NULL_LIST(res->clus_res_list);
155 slurmdb_destroy_clus_res_rec(res->clus_res_rec);
156 xfree(res->description);
157 xfree(res->manager);
158 xfree(res->name);
159 xfree(res->server);
160 }
161 }
162
163
164 /*
165 * Comparator used for sorting immediate children of acct_hierarchical_recs
166 *
167 * returns: -1 assoc_a < assoc_b 0: assoc_a == assoc_b 1: assoc_a > assoc_b
168 *
169 */
170
_sort_children_list(void * v1,void * v2)171 static int _sort_children_list(void *v1, void *v2)
172 {
173 int diff = 0;
174 slurmdb_hierarchical_rec_t *assoc_a;
175 slurmdb_hierarchical_rec_t *assoc_b;
176
177 assoc_a = *(slurmdb_hierarchical_rec_t **)v1;
178 assoc_b = *(slurmdb_hierarchical_rec_t **)v2;
179
180 /* Since all these associations are on the same level we don't
181 * have to check the lfts
182 */
183
184 /* check to see if this is a user association or an account.
185 * We want the accounts at the bottom
186 */
187 if (assoc_a->assoc->user && !assoc_b->assoc->user)
188 return -1;
189 else if (!assoc_a->assoc->user && assoc_b->assoc->user)
190 return 1;
191
192 /* Sort by alpha */
193 diff = xstrcmp(assoc_a->sort_name, assoc_b->sort_name);
194
195 if (diff < 0)
196 return -1;
197 else if (diff > 0)
198 return 1;
199
200 return 0;
201
202 }
203
204 /*
205 * Comparator used for sorting immediate children of acct_hierarchical_recs
206 *
207 * returns: -1 assoc_a < assoc_b 0: assoc_a == assoc_b 1: assoc_a > assoc_b
208 *
209 */
_sort_assoc_by_lft_dec(void * v1,void * v2)210 static int _sort_assoc_by_lft_dec(void *v1, void *v2)
211 {
212 slurmdb_assoc_rec_t *assoc_a;
213 slurmdb_assoc_rec_t *assoc_b;
214
215 assoc_a = *(slurmdb_assoc_rec_t **)v1;
216 assoc_b = *(slurmdb_assoc_rec_t **)v2;
217
218 if (assoc_a->lft == assoc_b->lft)
219 return 0;
220 if (assoc_a->lft > assoc_b->lft)
221 return 1;
222 return -1;
223 }
224
_sort_slurmdb_hierarchical_rec_list(List slurmdb_hierarchical_rec_list)225 static int _sort_slurmdb_hierarchical_rec_list(
226 List slurmdb_hierarchical_rec_list)
227 {
228 slurmdb_hierarchical_rec_t *slurmdb_hierarchical_rec = NULL;
229 ListIterator itr;
230
231 if (!list_count(slurmdb_hierarchical_rec_list))
232 return SLURM_SUCCESS;
233
234 list_sort(slurmdb_hierarchical_rec_list, (ListCmpF)_sort_children_list);
235
236 itr = list_iterator_create(slurmdb_hierarchical_rec_list);
237 while((slurmdb_hierarchical_rec = list_next(itr))) {
238 if (list_count(slurmdb_hierarchical_rec->children))
239 _sort_slurmdb_hierarchical_rec_list(
240 slurmdb_hierarchical_rec->children);
241 }
242 list_iterator_destroy(itr);
243
244 return SLURM_SUCCESS;
245 }
246
_append_hierarchical_children_ret_list(List ret_list,List slurmdb_hierarchical_rec_list)247 static int _append_hierarchical_children_ret_list(
248 List ret_list, List slurmdb_hierarchical_rec_list)
249 {
250 slurmdb_hierarchical_rec_t *slurmdb_hierarchical_rec = NULL;
251 ListIterator itr;
252
253 if (!ret_list)
254 return SLURM_ERROR;
255
256 if (!list_count(slurmdb_hierarchical_rec_list))
257 return SLURM_SUCCESS;
258
259 itr = list_iterator_create(slurmdb_hierarchical_rec_list);
260 while((slurmdb_hierarchical_rec = list_next(itr))) {
261 list_append(ret_list, slurmdb_hierarchical_rec->assoc);
262
263 if (list_count(slurmdb_hierarchical_rec->children))
264 _append_hierarchical_children_ret_list(
265 ret_list, slurmdb_hierarchical_rec->children);
266 }
267 list_iterator_destroy(itr);
268
269 return SLURM_SUCCESS;
270 }
271
_get_qos_list_str(List qos_list)272 static char *_get_qos_list_str(List qos_list)
273 {
274 char *qos_char = NULL;
275 ListIterator itr = NULL;
276 slurmdb_qos_rec_t *qos = NULL;
277
278 if (!qos_list)
279 return NULL;
280
281 itr = list_iterator_create(qos_list);
282 while((qos = list_next(itr))) {
283 if (qos_char)
284 xstrfmtcat(qos_char, ",%s", qos->name);
285 else
286 xstrcat(qos_char, qos->name);
287 }
288 list_iterator_destroy(itr);
289
290 return qos_char;
291 }
292
slurmdb_setup_cluster_rec(slurmdb_cluster_rec_t * cluster_rec)293 extern int slurmdb_setup_cluster_rec(slurmdb_cluster_rec_t *cluster_rec)
294 {
295 int plugin_id_select = 0;
296
297 xassert(cluster_rec);
298
299 if (!cluster_rec->control_port) {
300 debug("Slurmctld on '%s' hasn't registered yet.",
301 cluster_rec->name);
302 return SLURM_ERROR;
303 }
304
305 if ((plugin_id_select = select_get_plugin_id_pos(
306 cluster_rec->plugin_id_select)) == SLURM_ERROR) {
307 error("Cluster '%s' has an unknown select plugin_id %u",
308 cluster_rec->name,
309 cluster_rec->plugin_id_select);
310 return SLURM_ERROR;
311 }
312 cluster_rec->plugin_id_select = plugin_id_select;
313
314 slurm_set_addr(&cluster_rec->control_addr,
315 cluster_rec->control_port,
316 cluster_rec->control_host);
317 if (cluster_rec->control_addr.sin_port == 0) {
318 error("Unable to establish control "
319 "machine address for '%s'(%s:%u)",
320 cluster_rec->name,
321 cluster_rec->control_host,
322 cluster_rec->control_port);
323 return SLURM_ERROR;
324 }
325
326 if (cluster_rec->dimensions > 1) {
327 int number, i, len;
328 char *nodes = cluster_rec->nodes;
329
330 cluster_rec->dim_size = xmalloc(sizeof(int) *
331 cluster_rec->dimensions);
332 len = strlen(nodes);
333 i = len - cluster_rec->dimensions;
334 if (nodes[len-1] == ']')
335 i--;
336
337 if (i > 0) {
338 number = xstrntol(nodes + i, NULL,
339 cluster_rec->dimensions, 36);
340 hostlist_parse_int_to_array(
341 number, cluster_rec->dim_size,
342 cluster_rec->dimensions, 36);
343 /* all calculations this is for should
344 * be expecting 0 not to count as a
345 * number so add 1 to it. */
346 for (i=0; i<cluster_rec->dimensions; i++)
347 cluster_rec->dim_size[i]++;
348 }
349 }
350
351 return SLURM_SUCCESS;
352 }
353
slurmdb_job_cond_def_start_end(slurmdb_job_cond_t * job_cond)354 extern void slurmdb_job_cond_def_start_end(slurmdb_job_cond_t *job_cond)
355 {
356 if (!job_cond ||
357 (job_cond->flags & JOBCOND_FLAG_RUNAWAY) ||
358 (job_cond->flags & JOBCOND_FLAG_NO_DEFAULT_USAGE))
359 return;
360 /*
361 * Defaults for start and end times...
362 * - with -j and -s:
363 * -S defaults to Epoch 0
364 * -E defaults to -S (unless no -S then Now)
365 * - with only -j (NOT -s)
366 * -S defaults to Epoch 0
367 * -E defaults to Now
368 * - with only -s (NOT -j):
369 * -S defaults to Now
370 * -E defaults to -S
371 * - without either -j nor -s:
372 * -S defaults to Midnight
373 * -E defaults to Now
374 */
375 if (job_cond->state_list && list_count(job_cond->state_list)) {
376 if (!job_cond->usage_start &&
377 (!job_cond->step_list || !list_count(job_cond->step_list)))
378 job_cond->usage_start = time(NULL);
379
380 if (job_cond->usage_start && !job_cond->usage_end)
381 job_cond->usage_end = job_cond->usage_start;
382 } else if (!job_cond->step_list || !list_count(job_cond->step_list)) {
383 if (!job_cond->usage_start) {
384 struct tm start_tm;
385 job_cond->usage_start = time(NULL);
386 if (!localtime_r(&job_cond->usage_start, &start_tm)) {
387 error("Couldn't get localtime from %ld",
388 (long)job_cond->usage_start);
389 } else {
390 start_tm.tm_sec = 0;
391 start_tm.tm_min = 0;
392 start_tm.tm_hour = 0;
393 job_cond->usage_start = slurm_mktime(&start_tm);
394 }
395 }
396 }
397
398 if (!job_cond->usage_end)
399 job_cond->usage_end = time(NULL);
400 }
401
_str_2_qos_flags(char * flags)402 static uint32_t _str_2_qos_flags(char *flags)
403 {
404 if (xstrcasestr(flags, "DenyOnLimit"))
405 return QOS_FLAG_DENY_LIMIT;
406
407 if (xstrcasestr(flags, "EnforceUsageThreshold"))
408 return QOS_FLAG_ENFORCE_USAGE_THRES;
409
410 if (xstrcasestr(flags, "PartitionMinNodes"))
411 return QOS_FLAG_PART_MIN_NODE;
412
413 if (xstrcasestr(flags, "PartitionMaxNodes"))
414 return QOS_FLAG_PART_MAX_NODE;
415
416 if (xstrcasestr(flags, "PartitionTimeLimit"))
417 return QOS_FLAG_PART_TIME_LIMIT;
418
419 if (xstrcasestr(flags, "RequiresReservation"))
420 return QOS_FLAG_REQ_RESV;
421
422 if (xstrcasestr(flags, "OverPartQOS"))
423 return QOS_FLAG_OVER_PART_QOS;
424
425 if (xstrcasestr(flags, "NoReserve"))
426 return QOS_FLAG_NO_RESERVE;
427
428 if (xstrcasestr(flags, "NoDecay"))
429 return QOS_FLAG_NO_DECAY;
430
431 if (xstrcasestr(flags, "UsageFactorSafe"))
432 return QOS_FLAG_USAGE_FACTOR_SAFE;
433
434 return 0;
435 }
436
_str_2_res_flags(char * flags)437 static uint32_t _str_2_res_flags(char *flags)
438 {
439 return 0;
440 }
441
_str_2_job_flags(char * flags)442 static uint32_t _str_2_job_flags(char *flags)
443 {
444 if (xstrcasestr(flags, "None"))
445 return SLURMDB_JOB_FLAG_NONE;
446
447 if (xstrcasestr(flags, "SchedSubmit"))
448 return SLURMDB_JOB_FLAG_SUBMIT;
449
450 if (xstrcasestr(flags, "SchedMain"))
451 return SLURMDB_JOB_FLAG_SCHED;
452
453 if (xstrcasestr(flags, "SchedBackfill"))
454 return SLURMDB_JOB_FLAG_BACKFILL;
455
456 return SLURMDB_JOB_FLAG_NOTSET;
457 }
458
_sort_local_cluster(void * v1,void * v2)459 static int _sort_local_cluster(void *v1, void *v2)
460 {
461 local_cluster_rec_t* rec_a = *(local_cluster_rec_t**)v1;
462 local_cluster_rec_t* rec_b = *(local_cluster_rec_t**)v2;
463
464 if (rec_a->start_time < rec_b->start_time)
465 return -1;
466 else if (rec_a->start_time > rec_b->start_time)
467 return 1;
468
469 if (rec_a->preempt_cnt < rec_b->preempt_cnt)
470 return -1;
471 else if (rec_a->preempt_cnt > rec_b->preempt_cnt)
472 return 1;
473
474 if (!xstrcmp(local_cluster_name, rec_a->cluster_rec->name))
475 return -1;
476 else if (!xstrcmp(local_cluster_name, rec_b->cluster_rec->name))
477 return 1;
478
479 return 0;
480 }
481
_job_will_run(job_desc_msg_t * req)482 static local_cluster_rec_t * _job_will_run (job_desc_msg_t *req)
483 {
484 local_cluster_rec_t *local_cluster = NULL;
485 will_run_response_msg_t *will_run_resp;
486 char buf[64];
487 int rc;
488
489 rc = slurm_job_will_run2(req, &will_run_resp);
490
491 if (rc >= 0) {
492 slurm_make_time_str(&will_run_resp->start_time,
493 buf, sizeof(buf));
494 debug("Job %u to start at %s on cluster %s using %u processors on nodes %s in partition %s",
495 will_run_resp->job_id, buf, working_cluster_rec->name,
496 will_run_resp->proc_cnt, will_run_resp->node_list,
497 will_run_resp->part_name);
498
499 local_cluster = xmalloc(sizeof(local_cluster_rec_t));
500 local_cluster->cluster_rec = working_cluster_rec;
501 local_cluster->start_time = will_run_resp->start_time;
502
503 if (will_run_resp->preemptee_job_id) {
504 ListIterator itr;
505 uint32_t *job_id_ptr;
506 char *job_list = NULL, *sep = "";
507 local_cluster->preempt_cnt = list_count(
508 will_run_resp->preemptee_job_id);
509 itr = list_iterator_create(will_run_resp->
510 preemptee_job_id);
511 while ((job_id_ptr = list_next(itr))) {
512 if (job_list)
513 sep = ",";
514 xstrfmtcat(job_list, "%s%u",
515 sep, *job_id_ptr);
516 }
517 list_iterator_destroy(itr);
518 debug(" Preempts: %s", job_list);
519 xfree(job_list);
520 }
521
522 slurm_free_will_run_response_msg(will_run_resp);
523 }
524
525 return local_cluster;
526 }
527
_set_qos_bit_from_string(bitstr_t * valid_qos,char * name)528 static int _set_qos_bit_from_string(bitstr_t *valid_qos, char *name)
529 {
530 void (*my_function) (bitstr_t *b, bitoff_t bit);
531 bitoff_t bit = 0;
532
533 xassert(valid_qos);
534
535 if (!name)
536 return SLURM_ERROR;
537
538 if (name[0] == '-') {
539 name++;
540 my_function = bit_clear;
541 } else if (name[0] == '+') {
542 name++;
543 my_function = bit_set;
544 } else
545 my_function = bit_set;
546
547 if ((bit = atoi(name)) >= bit_size(valid_qos))
548 return SLURM_ERROR;
549
550 (*(my_function))(valid_qos, bit);
551
552 return SLURM_SUCCESS;
553 }
554
_find_arch_in_list(void * x,void * key)555 static int _find_arch_in_list(void *x, void *key)
556 {
557 slurmdb_hierarchical_rec_t *arch_rec = (slurmdb_hierarchical_rec_t *)x;
558 slurmdb_assoc_rec_t *assoc_rec = (slurmdb_assoc_rec_t *)key;
559
560 if ((assoc_rec->parent_id == arch_rec->assoc->id) &&
561 !xstrcmp(assoc_rec->cluster, arch_rec->assoc->cluster))
562 return 1;
563
564 return 0;
565 }
566
_add_arch_rec(slurmdb_assoc_rec_t * assoc_rec,List arch_rec_list,List total_arch_list)567 static void _add_arch_rec(slurmdb_assoc_rec_t *assoc_rec,
568 List arch_rec_list, List total_arch_list)
569 {
570 slurmdb_hierarchical_rec_t *arch_rec =
571 xmalloc(sizeof(slurmdb_hierarchical_rec_t));
572
573 arch_rec->children =
574 list_create(slurmdb_destroy_hierarchical_rec);
575 arch_rec->assoc = assoc_rec;
576
577 if (!assoc_rec->parent_id)
578 arch_rec->sort_name = assoc_rec->cluster;
579 else if (assoc_rec->user)
580 arch_rec->sort_name = assoc_rec->user;
581 else
582 arch_rec->sort_name = assoc_rec->acct;
583
584 assoc_rec->rgt = 0;
585 list_append(arch_rec_list, arch_rec);
586 list_append(total_arch_list, arch_rec);
587 }
588
_find_create_parent(slurmdb_assoc_rec_t * assoc_rec,List assoc_list,List arch_rec_list,List total_arch_list)589 static void _find_create_parent(slurmdb_assoc_rec_t *assoc_rec, List assoc_list,
590 List arch_rec_list, List total_arch_list)
591 {
592 slurmdb_assoc_rec_t *par_assoc_rec = NULL;
593 slurmdb_hierarchical_rec_t *par_arch_rec = NULL;
594
595 if (assoc_rec->parent_id) {
596 if ((par_arch_rec = list_find_first(
597 total_arch_list, _find_arch_in_list,
598 assoc_rec))) {
599
600 _add_arch_rec(assoc_rec, par_arch_rec->children,
601 total_arch_list);
602 return;
603 }
604
605 if (!(par_assoc_rec = list_find_first(
606 assoc_list, slurmdb_find_assoc_in_list,
607 &assoc_rec->parent_id))) {
608
609 /* This means we weren't starting at root */
610 _add_arch_rec(assoc_rec, arch_rec_list,
611 total_arch_list);
612 return;
613 }
614
615 _find_create_parent(par_assoc_rec, assoc_list, arch_rec_list,
616 total_arch_list);
617 /* Now that it has been added lets try again */
618 if ((par_arch_rec = list_find_first(
619 total_arch_list, _find_arch_in_list,
620 assoc_rec))) {
621
622 _add_arch_rec(assoc_rec, par_arch_rec->children,
623 total_arch_list);
624 return;
625 }
626 error("%s: no parent found, this should never happen",
627 __func__);
628 } else
629 _add_arch_rec(assoc_rec, arch_rec_list, total_arch_list);
630
631 return;
632 }
633
slurmdb_create_job_rec()634 extern slurmdb_job_rec_t *slurmdb_create_job_rec()
635 {
636 slurmdb_job_rec_t *job = xmalloc(sizeof(slurmdb_job_rec_t));
637 memset(&job->stats, 0, sizeof(slurmdb_stats_t));
638 job->array_task_id = NO_VAL;
639 job->derived_ec = NO_VAL;
640 job->state = JOB_PENDING;
641 job->steps = list_create(slurmdb_destroy_step_rec);
642 job->requid = -1;
643 job->lft = NO_VAL;
644 job->resvid = NO_VAL;
645
646 return job;
647 }
648
slurmdb_create_step_rec()649 extern slurmdb_step_rec_t *slurmdb_create_step_rec()
650 {
651 slurmdb_step_rec_t *step = xmalloc(sizeof(slurmdb_step_rec_t));
652 memset(&step->stats, 0, sizeof(slurmdb_stats_t));
653 step->stepid = NO_VAL;
654 step->state = NO_VAL;
655 step->exitcode = NO_VAL;
656 step->elapsed = NO_VAL;
657 step->tot_cpu_sec = NO_VAL;
658 step->tot_cpu_usec = NO_VAL;
659 step->requid = -1;
660
661 return step;
662 }
663
slurmdb_create_assoc_usage(int tres_cnt)664 extern slurmdb_assoc_usage_t *slurmdb_create_assoc_usage(int tres_cnt)
665 {
666 slurmdb_assoc_usage_t *usage;
667 int alloc_size;
668
669 if (!tres_cnt)
670 fatal("%s: You need to give a tres_cnt to call this function",
671 __func__);
672
673 usage = xmalloc(sizeof(slurmdb_assoc_usage_t));
674
675 usage->level_shares = NO_VAL;
676 usage->shares_norm = NO_VAL64;
677 usage->usage_efctv = 0;
678 usage->usage_norm = (long double)NO_VAL;
679 usage->usage_raw = 0;
680 usage->level_fs = 0;
681 usage->fs_factor = 0;
682
683 usage->tres_cnt = tres_cnt;
684
685 alloc_size = sizeof(uint64_t) * tres_cnt;
686 usage->grp_used_tres = xmalloc(alloc_size);
687 usage->grp_used_tres_run_secs = xmalloc(alloc_size);
688
689 usage->usage_tres_raw = xmalloc(sizeof(long double) * tres_cnt);
690
691 return usage;
692 }
693
slurmdb_create_qos_usage(int tres_cnt)694 extern slurmdb_qos_usage_t *slurmdb_create_qos_usage(int tres_cnt)
695 {
696 slurmdb_qos_usage_t *usage =
697 xmalloc(sizeof(slurmdb_qos_usage_t));
698
699 if (tres_cnt) {
700 int alloc_size = sizeof(uint64_t) * tres_cnt;
701 usage->tres_cnt = tres_cnt;
702 usage->grp_used_tres_run_secs = xmalloc(alloc_size);
703 usage->grp_used_tres = xmalloc(alloc_size);
704 usage->usage_tres_raw = xmalloc(sizeof(long double) * tres_cnt);
705 }
706
707 return usage;
708 }
709
slurmdb_destroy_assoc_usage(void * object)710 extern void slurmdb_destroy_assoc_usage(void *object)
711 {
712 slurmdb_assoc_usage_t *usage =
713 (slurmdb_assoc_usage_t *)object;
714
715 if (usage) {
716 FREE_NULL_LIST(usage->children_list);
717 FREE_NULL_BITMAP(usage->grp_node_bitmap);
718 xfree(usage->grp_node_job_cnt);
719 xfree(usage->grp_used_tres_run_secs);
720 xfree(usage->grp_used_tres);
721 xfree(usage->usage_tres_raw);
722 FREE_NULL_BITMAP(usage->valid_qos);
723 xfree(usage);
724 }
725 }
726
slurmdb_destroy_bf_usage(void * object)727 extern void slurmdb_destroy_bf_usage(void *object)
728 {
729 slurmdb_destroy_bf_usage_members(object);
730 xfree(object);
731 }
732
slurmdb_destroy_bf_usage_members(void * object)733 extern void slurmdb_destroy_bf_usage_members(void *object)
734 {
735 return;
736 }
737
slurmdb_destroy_qos_usage(void * object)738 extern void slurmdb_destroy_qos_usage(void *object)
739 {
740 slurmdb_qos_usage_t *usage =
741 (slurmdb_qos_usage_t *)object;
742
743 if (usage) {
744 FREE_NULL_LIST(usage->acct_limit_list);
745 FREE_NULL_BITMAP(usage->grp_node_bitmap);
746 xfree(usage->grp_node_job_cnt);
747 xfree(usage->grp_used_tres_run_secs);
748 xfree(usage->grp_used_tres);
749 FREE_NULL_LIST(usage->job_list);
750 xfree(usage->usage_tres_raw);
751 FREE_NULL_LIST(usage->user_limit_list);
752 xfree(usage);
753 }
754 }
755
756
slurmdb_destroy_user_rec(void * object)757 extern void slurmdb_destroy_user_rec(void *object)
758 {
759 slurmdb_user_rec_t *slurmdb_user = (slurmdb_user_rec_t *)object;
760
761 if (slurmdb_user) {
762 FREE_NULL_LIST(slurmdb_user->assoc_list);
763 FREE_NULL_LIST(slurmdb_user->coord_accts);
764 xfree(slurmdb_user->default_acct);
765 xfree(slurmdb_user->default_wckey);
766 xfree(slurmdb_user->name);
767 xfree(slurmdb_user->old_name);
768 FREE_NULL_LIST(slurmdb_user->wckey_list);
769 slurmdb_destroy_bf_usage(slurmdb_user->bf_usage);
770 xfree(slurmdb_user);
771 }
772 }
773
slurmdb_destroy_account_rec(void * object)774 extern void slurmdb_destroy_account_rec(void *object)
775 {
776 slurmdb_account_rec_t *slurmdb_account =
777 (slurmdb_account_rec_t *)object;
778
779 if (slurmdb_account) {
780 FREE_NULL_LIST(slurmdb_account->assoc_list);
781 FREE_NULL_LIST(slurmdb_account->coordinators);
782 xfree(slurmdb_account->description);
783 xfree(slurmdb_account->name);
784 xfree(slurmdb_account->organization);
785 xfree(slurmdb_account);
786 }
787 }
788
slurmdb_destroy_coord_rec(void * object)789 extern void slurmdb_destroy_coord_rec(void *object)
790 {
791 slurmdb_coord_rec_t *slurmdb_coord =
792 (slurmdb_coord_rec_t *)object;
793
794 if (slurmdb_coord) {
795 xfree(slurmdb_coord->name);
796 xfree(slurmdb_coord);
797 }
798 }
799
slurmdb_destroy_cluster_accounting_rec(void * object)800 extern void slurmdb_destroy_cluster_accounting_rec(void *object)
801 {
802 slurmdb_cluster_accounting_rec_t *clusteracct_rec =
803 (slurmdb_cluster_accounting_rec_t *)object;
804
805 if (clusteracct_rec) {
806 slurmdb_destroy_tres_rec_noalloc(
807 &clusteracct_rec->tres_rec);
808 xfree(clusteracct_rec);
809 }
810 }
811
slurmdb_destroy_clus_res_rec(void * object)812 extern void slurmdb_destroy_clus_res_rec(void *object)
813 {
814 slurmdb_clus_res_rec_t *slurmdb_clus_res =
815 (slurmdb_clus_res_rec_t *)object;
816
817 if (slurmdb_clus_res) {
818 _free_clus_res_rec_members(slurmdb_clus_res);
819 xfree(slurmdb_clus_res);
820 }
821 }
822
slurmdb_destroy_cluster_rec(void * object)823 extern void slurmdb_destroy_cluster_rec(void *object)
824 {
825 slurmdb_cluster_rec_t *slurmdb_cluster =
826 (slurmdb_cluster_rec_t *)object;
827
828 if (slurmdb_cluster) {
829 _free_cluster_rec_members(slurmdb_cluster);
830 xfree(slurmdb_cluster);
831 }
832 }
833
slurmdb_destroy_federation_rec(void * object)834 extern void slurmdb_destroy_federation_rec(void *object)
835 {
836 slurmdb_federation_rec_t *slurmdb_federation =
837 (slurmdb_federation_rec_t *)object;
838
839 if (slurmdb_federation) {
840 _free_federation_rec_members(slurmdb_federation);
841 xfree(slurmdb_federation);
842 }
843 }
844
slurmdb_destroy_accounting_rec(void * object)845 extern void slurmdb_destroy_accounting_rec(void *object)
846 {
847 slurmdb_accounting_rec_t *slurmdb_accounting =
848 (slurmdb_accounting_rec_t *)object;
849
850 if (slurmdb_accounting) {
851 slurmdb_destroy_tres_rec_noalloc(
852 &slurmdb_accounting->tres_rec);
853 xfree(slurmdb_accounting);
854 }
855 }
856
slurmdb_free_assoc_rec_members(slurmdb_assoc_rec_t * assoc)857 extern void slurmdb_free_assoc_rec_members(slurmdb_assoc_rec_t *assoc)
858 {
859 if (assoc) {
860 FREE_NULL_LIST(assoc->accounting_list);
861 xfree(assoc->acct);
862 xfree(assoc->cluster);
863 xfree(assoc->grp_tres);
864 xfree(assoc->grp_tres_ctld);
865 xfree(assoc->grp_tres_mins);
866 xfree(assoc->grp_tres_mins_ctld);
867 xfree(assoc->grp_tres_run_mins);
868 xfree(assoc->grp_tres_run_mins_ctld);
869 xfree(assoc->max_tres_mins_pj);
870 xfree(assoc->max_tres_mins_ctld);
871 xfree(assoc->max_tres_run_mins);
872 xfree(assoc->max_tres_run_mins_ctld);
873 xfree(assoc->max_tres_pj);
874 xfree(assoc->max_tres_ctld);
875 xfree(assoc->max_tres_pn);
876 xfree(assoc->max_tres_pn_ctld);
877 xfree(assoc->parent_acct);
878 xfree(assoc->partition);
879 FREE_NULL_LIST(assoc->qos_list);
880 xfree(assoc->user);
881
882 slurmdb_destroy_assoc_usage(assoc->usage);
883 /* NOTE assoc->user_rec is a soft reference, do not free here */
884 assoc->user_rec = NULL;
885 slurmdb_destroy_bf_usage(assoc->bf_usage);
886 }
887 }
888
slurmdb_destroy_assoc_rec(void * object)889 extern void slurmdb_destroy_assoc_rec(void *object)
890 {
891 slurmdb_assoc_rec_t *slurmdb_assoc =
892 (slurmdb_assoc_rec_t *)object;
893
894 if (slurmdb_assoc) {
895 slurmdb_free_assoc_rec_members(slurmdb_assoc);
896 xfree(slurmdb_assoc);
897 }
898 }
899
slurmdb_destroy_event_rec(void * object)900 extern void slurmdb_destroy_event_rec(void *object)
901 {
902 slurmdb_event_rec_t *slurmdb_event =
903 (slurmdb_event_rec_t *)object;
904
905 if (slurmdb_event) {
906 xfree(slurmdb_event->cluster);
907 xfree(slurmdb_event->cluster_nodes);
908 xfree(slurmdb_event->node_name);
909 xfree(slurmdb_event->reason);
910 xfree(slurmdb_event->tres_str);
911
912 xfree(slurmdb_event);
913 }
914 }
915
slurmdb_destroy_job_rec(void * object)916 extern void slurmdb_destroy_job_rec(void *object)
917 {
918 slurmdb_job_rec_t *job = (slurmdb_job_rec_t *)object;
919 if (job) {
920 xfree(job->account);
921 xfree(job->admin_comment);
922 xfree(job->alloc_gres);
923 xfree(job->array_task_str);
924 xfree(job->blockid);
925 xfree(job->cluster);
926 xfree(job->constraints);
927 xfree(job->derived_es);
928 xfree(job->jobname);
929 xfree(job->mcs_label);
930 xfree(job->partition);
931 xfree(job->nodes);
932 xfree(job->req_gres);
933 xfree(job->resv_name);
934 slurmdb_free_slurmdb_stats_members(&job->stats);
935 FREE_NULL_LIST(job->steps);
936 xfree(job->system_comment);
937 xfree(job->tres_alloc_str);
938 xfree(job->tres_req_str);
939 xfree(job->user);
940 xfree(job->wckey);
941 xfree(job->work_dir);
942 xfree(job);
943 }
944 }
945
slurmdb_free_qos_rec_members(slurmdb_qos_rec_t * qos)946 extern void slurmdb_free_qos_rec_members(slurmdb_qos_rec_t *qos)
947 {
948 if (qos) {
949 xfree(qos->description);
950 xfree(qos->grp_tres);
951 xfree(qos->grp_tres_ctld);
952 xfree(qos->grp_tres_mins);
953 xfree(qos->grp_tres_mins_ctld);
954 xfree(qos->grp_tres_run_mins);
955 xfree(qos->grp_tres_run_mins_ctld);
956 xfree(qos->max_tres_mins_pj);
957 xfree(qos->max_tres_mins_pj_ctld);
958 xfree(qos->max_tres_run_mins_pa);
959 xfree(qos->max_tres_run_mins_pa_ctld);
960 xfree(qos->max_tres_run_mins_pu);
961 xfree(qos->max_tres_run_mins_pu_ctld);
962 xfree(qos->max_tres_pa);
963 xfree(qos->max_tres_pa_ctld);
964 xfree(qos->max_tres_pj);
965 xfree(qos->max_tres_pj_ctld);
966 xfree(qos->max_tres_pn);
967 xfree(qos->max_tres_pn_ctld);
968 xfree(qos->max_tres_pu);
969 xfree(qos->max_tres_pu_ctld);
970 xfree(qos->min_tres_pj);
971 xfree(qos->min_tres_pj_ctld);
972 xfree(qos->name);
973 FREE_NULL_BITMAP(qos->preempt_bitstr);
974 FREE_NULL_LIST(qos->preempt_list);
975 slurmdb_destroy_qos_usage(qos->usage);
976 }
977 }
978
slurmdb_destroy_qos_rec(void * object)979 extern void slurmdb_destroy_qos_rec(void *object)
980 {
981 slurmdb_qos_rec_t *slurmdb_qos = (slurmdb_qos_rec_t *)object;
982 if (slurmdb_qos) {
983 slurmdb_free_qos_rec_members(slurmdb_qos);
984 xfree(slurmdb_qos);
985 }
986 }
987
slurmdb_destroy_reservation_rec(void * object)988 extern void slurmdb_destroy_reservation_rec(void *object)
989 {
990 slurmdb_reservation_rec_t *slurmdb_resv =
991 (slurmdb_reservation_rec_t *)object;
992 if (slurmdb_resv) {
993 xfree(slurmdb_resv->assocs);
994 xfree(slurmdb_resv->cluster);
995 xfree(slurmdb_resv->name);
996 xfree(slurmdb_resv->nodes);
997 xfree(slurmdb_resv->node_inx);
998 xfree(slurmdb_resv->tres_str);
999 xfree(slurmdb_resv);
1000 }
1001 }
1002
slurmdb_destroy_step_rec(void * object)1003 extern void slurmdb_destroy_step_rec(void *object)
1004 {
1005 slurmdb_step_rec_t *step = (slurmdb_step_rec_t *)object;
1006 if (step) {
1007 xfree(step->nodes);
1008 xfree(step->pid_str);
1009 slurmdb_free_slurmdb_stats_members(&step->stats);
1010 xfree(step->stepname);
1011 xfree(step->tres_alloc_str);
1012 xfree(step);
1013 }
1014 }
1015
slurmdb_destroy_res_rec(void * object)1016 extern void slurmdb_destroy_res_rec(void *object)
1017 {
1018 slurmdb_res_rec_t *slurmdb_res =
1019 (slurmdb_res_rec_t *)object;
1020
1021 if (slurmdb_res) {
1022 _free_res_rec_members(slurmdb_res);
1023 xfree(slurmdb_res);
1024 }
1025 }
1026
slurmdb_destroy_txn_rec(void * object)1027 extern void slurmdb_destroy_txn_rec(void *object)
1028 {
1029 slurmdb_txn_rec_t *slurmdb_txn = (slurmdb_txn_rec_t *)object;
1030 if (slurmdb_txn) {
1031 xfree(slurmdb_txn->accts);
1032 xfree(slurmdb_txn->actor_name);
1033 xfree(slurmdb_txn->clusters);
1034 xfree(slurmdb_txn->set_info);
1035 xfree(slurmdb_txn->users);
1036 xfree(slurmdb_txn->where_query);
1037 xfree(slurmdb_txn);
1038 }
1039 }
1040
slurmdb_destroy_wckey_rec(void * object)1041 extern void slurmdb_destroy_wckey_rec(void *object)
1042 {
1043 slurmdb_wckey_rec_t *wckey = (slurmdb_wckey_rec_t *)object;
1044
1045 if (wckey) {
1046 _free_wckey_rec_members(wckey);
1047 xfree(wckey);
1048 }
1049 }
1050
slurmdb_destroy_archive_rec(void * object)1051 extern void slurmdb_destroy_archive_rec(void *object)
1052 {
1053 slurmdb_archive_rec_t *arch_rec = (slurmdb_archive_rec_t *)object;
1054
1055 if (arch_rec) {
1056 xfree(arch_rec->archive_file);
1057 xfree(arch_rec->insert);
1058 xfree(arch_rec);
1059 }
1060 }
1061
slurmdb_destroy_tres_rec_noalloc(void * object)1062 extern void slurmdb_destroy_tres_rec_noalloc(void *object)
1063 {
1064 slurmdb_tres_rec_t *tres_rec = (slurmdb_tres_rec_t *)object;
1065
1066 if (!tres_rec)
1067 return;
1068
1069 xfree(tres_rec->name);
1070 xfree(tres_rec->type);
1071 }
1072
slurmdb_destroy_tres_rec(void * object)1073 extern void slurmdb_destroy_tres_rec(void *object)
1074 {
1075 slurmdb_tres_rec_t *tres_rec = (slurmdb_tres_rec_t *)object;
1076
1077 if (tres_rec) {
1078 slurmdb_destroy_tres_rec_noalloc(tres_rec);
1079 xfree(tres_rec);
1080 }
1081 }
1082
slurmdb_destroy_report_assoc_rec(void * object)1083 extern void slurmdb_destroy_report_assoc_rec(void *object)
1084 {
1085 slurmdb_report_assoc_rec_t *slurmdb_report_assoc =
1086 (slurmdb_report_assoc_rec_t *)object;
1087 if (slurmdb_report_assoc) {
1088 xfree(slurmdb_report_assoc->acct);
1089 xfree(slurmdb_report_assoc->cluster);
1090 xfree(slurmdb_report_assoc->parent_acct);
1091 FREE_NULL_LIST(slurmdb_report_assoc->tres_list);
1092 xfree(slurmdb_report_assoc->user);
1093 xfree(slurmdb_report_assoc);
1094 }
1095 }
1096
slurmdb_destroy_report_user_rec(void * object)1097 extern void slurmdb_destroy_report_user_rec(void *object)
1098 {
1099 slurmdb_report_user_rec_t *slurmdb_report_user =
1100 (slurmdb_report_user_rec_t *)object;
1101 if (slurmdb_report_user) {
1102 xfree(slurmdb_report_user->acct);
1103 FREE_NULL_LIST(slurmdb_report_user->acct_list);
1104 FREE_NULL_LIST(slurmdb_report_user->assoc_list);
1105 xfree(slurmdb_report_user->name);
1106 FREE_NULL_LIST(slurmdb_report_user->tres_list);
1107 xfree(slurmdb_report_user);
1108 }
1109 }
1110
slurmdb_destroy_report_cluster_rec(void * object)1111 extern void slurmdb_destroy_report_cluster_rec(void *object)
1112 {
1113 slurmdb_report_cluster_rec_t *slurmdb_report_cluster =
1114 (slurmdb_report_cluster_rec_t *)object;
1115 if (slurmdb_report_cluster) {
1116 FREE_NULL_LIST(slurmdb_report_cluster->assoc_list);
1117 xfree(slurmdb_report_cluster->name);
1118 FREE_NULL_LIST(slurmdb_report_cluster->tres_list);
1119 FREE_NULL_LIST(slurmdb_report_cluster->user_list);
1120 xfree(slurmdb_report_cluster);
1121 }
1122 }
1123
slurmdb_destroy_user_cond(void * object)1124 extern void slurmdb_destroy_user_cond(void *object)
1125 {
1126 slurmdb_user_cond_t *slurmdb_user = (slurmdb_user_cond_t *)object;
1127
1128 if (slurmdb_user) {
1129 slurmdb_destroy_assoc_cond(slurmdb_user->assoc_cond);
1130 FREE_NULL_LIST(slurmdb_user->def_acct_list);
1131 FREE_NULL_LIST(slurmdb_user->def_wckey_list);
1132 xfree(slurmdb_user);
1133 }
1134 }
1135
slurmdb_destroy_account_cond(void * object)1136 extern void slurmdb_destroy_account_cond(void *object)
1137 {
1138 slurmdb_account_cond_t *slurmdb_account =
1139 (slurmdb_account_cond_t *)object;
1140
1141 if (slurmdb_account) {
1142 slurmdb_destroy_assoc_cond(slurmdb_account->assoc_cond);
1143 FREE_NULL_LIST(slurmdb_account->description_list);
1144 FREE_NULL_LIST(slurmdb_account->organization_list);
1145 xfree(slurmdb_account);
1146 }
1147 }
1148
slurmdb_destroy_cluster_cond(void * object)1149 extern void slurmdb_destroy_cluster_cond(void *object)
1150 {
1151 slurmdb_cluster_cond_t *slurmdb_cluster =
1152 (slurmdb_cluster_cond_t *)object;
1153
1154 if (slurmdb_cluster) {
1155 _free_cluster_cond_members(slurmdb_cluster);
1156 xfree(slurmdb_cluster);
1157 }
1158 }
1159
slurmdb_destroy_federation_cond(void * object)1160 extern void slurmdb_destroy_federation_cond(void *object)
1161 {
1162 slurmdb_federation_cond_t *slurmdb_federation =
1163 (slurmdb_federation_cond_t *)object;
1164
1165 if (slurmdb_federation) {
1166 _free_federation_cond_members(slurmdb_federation);
1167 xfree(slurmdb_federation);
1168 }
1169 }
1170
slurmdb_destroy_tres_cond(void * object)1171 extern void slurmdb_destroy_tres_cond(void *object)
1172 {
1173 slurmdb_tres_cond_t *slurmdb_tres =
1174 (slurmdb_tres_cond_t *)object;
1175
1176 if (slurmdb_tres) {
1177 _free_tres_cond_members(slurmdb_tres);
1178 xfree(slurmdb_tres);
1179 }
1180 }
1181
slurmdb_destroy_assoc_cond(void * object)1182 extern void slurmdb_destroy_assoc_cond(void *object)
1183 {
1184 slurmdb_assoc_cond_t *slurmdb_assoc =
1185 (slurmdb_assoc_cond_t *)object;
1186
1187 if (slurmdb_assoc) {
1188 FREE_NULL_LIST(slurmdb_assoc->acct_list);
1189 FREE_NULL_LIST(slurmdb_assoc->cluster_list);
1190 FREE_NULL_LIST(slurmdb_assoc->def_qos_id_list);
1191 FREE_NULL_LIST(slurmdb_assoc->id_list);
1192 FREE_NULL_LIST(slurmdb_assoc->partition_list);
1193 FREE_NULL_LIST(slurmdb_assoc->parent_acct_list);
1194 FREE_NULL_LIST(slurmdb_assoc->qos_list);
1195 FREE_NULL_LIST(slurmdb_assoc->user_list);
1196 xfree(slurmdb_assoc);
1197 }
1198 }
1199
slurmdb_destroy_event_cond(void * object)1200 extern void slurmdb_destroy_event_cond(void *object)
1201 {
1202 slurmdb_event_cond_t *slurmdb_event =
1203 (slurmdb_event_cond_t *)object;
1204
1205 if (slurmdb_event) {
1206 FREE_NULL_LIST(slurmdb_event->cluster_list);
1207 FREE_NULL_LIST(slurmdb_event->reason_list);
1208 FREE_NULL_LIST(slurmdb_event->reason_uid_list);
1209 FREE_NULL_LIST(slurmdb_event->state_list);
1210 xfree(slurmdb_event->node_list);
1211 xfree(slurmdb_event);
1212 }
1213 }
1214
slurmdb_destroy_job_cond(void * object)1215 extern void slurmdb_destroy_job_cond(void *object)
1216 {
1217 slurmdb_job_cond_t *job_cond =
1218 (slurmdb_job_cond_t *)object;
1219
1220 if (job_cond) {
1221 FREE_NULL_LIST(job_cond->acct_list);
1222 FREE_NULL_LIST(job_cond->associd_list);
1223 FREE_NULL_LIST(job_cond->cluster_list);
1224 FREE_NULL_LIST(job_cond->constraint_list);
1225 FREE_NULL_LIST(job_cond->groupid_list);
1226 FREE_NULL_LIST(job_cond->jobname_list);
1227 FREE_NULL_LIST(job_cond->partition_list);
1228 FREE_NULL_LIST(job_cond->qos_list);
1229 FREE_NULL_LIST(job_cond->reason_list);
1230 FREE_NULL_LIST(job_cond->resv_list);
1231 FREE_NULL_LIST(job_cond->resvid_list);
1232 FREE_NULL_LIST(job_cond->step_list);
1233 FREE_NULL_LIST(job_cond->state_list);
1234 xfree(job_cond->used_nodes);
1235 FREE_NULL_LIST(job_cond->userid_list);
1236 FREE_NULL_LIST(job_cond->wckey_list);
1237 xfree(job_cond);
1238 }
1239 }
1240
slurmdb_destroy_qos_cond(void * object)1241 extern void slurmdb_destroy_qos_cond(void *object)
1242 {
1243 slurmdb_qos_cond_t *slurmdb_qos = (slurmdb_qos_cond_t *)object;
1244 if (slurmdb_qos) {
1245 FREE_NULL_LIST(slurmdb_qos->id_list);
1246 FREE_NULL_LIST(slurmdb_qos->name_list);
1247 xfree(slurmdb_qos);
1248 }
1249 }
1250
slurmdb_destroy_res_cond(void * object)1251 extern void slurmdb_destroy_res_cond(void *object)
1252 {
1253 slurmdb_res_cond_t *slurmdb_res =
1254 (slurmdb_res_cond_t *)object;
1255 if (slurmdb_res) {
1256 _free_res_cond_members(slurmdb_res);
1257 xfree(slurmdb_res);
1258 }
1259 }
1260
slurmdb_destroy_reservation_cond(void * object)1261 extern void slurmdb_destroy_reservation_cond(void *object)
1262 {
1263 slurmdb_reservation_cond_t *slurmdb_resv =
1264 (slurmdb_reservation_cond_t *)object;
1265 if (slurmdb_resv) {
1266 FREE_NULL_LIST(slurmdb_resv->cluster_list);
1267 FREE_NULL_LIST(slurmdb_resv->id_list);
1268 FREE_NULL_LIST(slurmdb_resv->name_list);
1269 xfree(slurmdb_resv->nodes);
1270 xfree(slurmdb_resv);
1271 }
1272 }
1273
slurmdb_destroy_txn_cond(void * object)1274 extern void slurmdb_destroy_txn_cond(void *object)
1275 {
1276 slurmdb_txn_cond_t *slurmdb_txn = (slurmdb_txn_cond_t *)object;
1277 if (slurmdb_txn) {
1278 FREE_NULL_LIST(slurmdb_txn->acct_list);
1279 FREE_NULL_LIST(slurmdb_txn->action_list);
1280 FREE_NULL_LIST(slurmdb_txn->actor_list);
1281 FREE_NULL_LIST(slurmdb_txn->cluster_list);
1282 FREE_NULL_LIST(slurmdb_txn->id_list);
1283 FREE_NULL_LIST(slurmdb_txn->info_list);
1284 FREE_NULL_LIST(slurmdb_txn->name_list);
1285 FREE_NULL_LIST(slurmdb_txn->user_list);
1286 xfree(slurmdb_txn);
1287 }
1288 }
1289
slurmdb_destroy_wckey_cond(void * object)1290 extern void slurmdb_destroy_wckey_cond(void *object)
1291 {
1292 slurmdb_wckey_cond_t *wckey = (slurmdb_wckey_cond_t *)object;
1293
1294 if (wckey) {
1295 FREE_NULL_LIST(wckey->cluster_list);
1296 FREE_NULL_LIST(wckey->id_list);
1297 FREE_NULL_LIST(wckey->name_list);
1298 FREE_NULL_LIST(wckey->user_list);
1299 xfree(wckey);
1300 }
1301 }
1302
slurmdb_destroy_archive_cond(void * object)1303 extern void slurmdb_destroy_archive_cond(void *object)
1304 {
1305 slurmdb_archive_cond_t *arch_cond = (slurmdb_archive_cond_t *)object;
1306
1307 if (arch_cond) {
1308 xfree(arch_cond->archive_dir);
1309 xfree(arch_cond->archive_script);
1310 slurmdb_destroy_job_cond(arch_cond->job_cond);
1311 xfree(arch_cond);
1312
1313 }
1314 }
1315
slurmdb_destroy_update_object(void * object)1316 extern void slurmdb_destroy_update_object(void *object)
1317 {
1318 slurmdb_update_object_t *slurmdb_update =
1319 (slurmdb_update_object_t *) object;
1320
1321 if (slurmdb_update) {
1322 FREE_NULL_LIST(slurmdb_update->objects);
1323 xfree(slurmdb_update);
1324 }
1325 }
1326
slurmdb_destroy_used_limits(void * object)1327 extern void slurmdb_destroy_used_limits(void *object)
1328 {
1329 slurmdb_used_limits_t *slurmdb_used_limits =
1330 (slurmdb_used_limits_t *)object;
1331
1332 if (slurmdb_used_limits) {
1333 xfree(slurmdb_used_limits->acct);
1334 FREE_NULL_BITMAP(slurmdb_used_limits->node_bitmap);
1335 xfree(slurmdb_used_limits->node_job_cnt);
1336 xfree(slurmdb_used_limits->tres);
1337 xfree(slurmdb_used_limits->tres_run_mins);
1338 xfree(slurmdb_used_limits);
1339 }
1340 }
1341
slurmdb_destroy_print_tree(void * object)1342 extern void slurmdb_destroy_print_tree(void *object)
1343 {
1344 slurmdb_print_tree_t *slurmdb_print_tree =
1345 (slurmdb_print_tree_t *)object;
1346
1347 if (slurmdb_print_tree) {
1348 xfree(slurmdb_print_tree->name);
1349 xfree(slurmdb_print_tree->print_name);
1350 xfree(slurmdb_print_tree->spaces);
1351 xfree(slurmdb_print_tree);
1352 }
1353 }
1354
slurmdb_destroy_hierarchical_rec(void * object)1355 extern void slurmdb_destroy_hierarchical_rec(void *object)
1356 {
1357 /* Most of this is pointers to something else that will be
1358 * destroyed elsewhere.
1359 */
1360 slurmdb_hierarchical_rec_t *slurmdb_hierarchical_rec =
1361 (slurmdb_hierarchical_rec_t *)object;
1362 if (slurmdb_hierarchical_rec) {
1363 FREE_NULL_LIST(slurmdb_hierarchical_rec->children);
1364 xfree(slurmdb_hierarchical_rec);
1365 }
1366 }
1367
slurmdb_destroy_selected_step(void * object)1368 extern void slurmdb_destroy_selected_step(void *object)
1369 {
1370 slurmdb_selected_step_t *step = (slurmdb_selected_step_t *)object;
1371 xfree(step);
1372 }
1373
slurmdb_destroy_report_job_grouping(void * object)1374 extern void slurmdb_destroy_report_job_grouping(void *object)
1375 {
1376 slurmdb_report_job_grouping_t *job_grouping =
1377 (slurmdb_report_job_grouping_t *)object;
1378 if (job_grouping) {
1379 FREE_NULL_LIST(job_grouping->jobs);
1380 FREE_NULL_LIST(job_grouping->tres_list);
1381 xfree(job_grouping);
1382 }
1383 }
1384
slurmdb_destroy_report_acct_grouping(void * object)1385 extern void slurmdb_destroy_report_acct_grouping(void *object)
1386 {
1387 slurmdb_report_acct_grouping_t *acct_grouping =
1388 (slurmdb_report_acct_grouping_t *)object;
1389 if (acct_grouping) {
1390 xfree(acct_grouping->acct);
1391 FREE_NULL_LIST(acct_grouping->groups);
1392 FREE_NULL_LIST(acct_grouping->tres_list);
1393 xfree(acct_grouping);
1394 }
1395 }
1396
slurmdb_destroy_report_cluster_grouping(void * object)1397 extern void slurmdb_destroy_report_cluster_grouping(void *object)
1398 {
1399 slurmdb_report_cluster_grouping_t *cluster_grouping =
1400 (slurmdb_report_cluster_grouping_t *)object;
1401 if (cluster_grouping) {
1402 xfree(cluster_grouping->cluster);
1403 FREE_NULL_LIST(cluster_grouping->acct_list);
1404 FREE_NULL_LIST(cluster_grouping->tres_list);
1405 xfree(cluster_grouping);
1406 }
1407 }
1408
slurmdb_get_info_cluster(char * cluster_names)1409 extern List slurmdb_get_info_cluster(char *cluster_names)
1410 {
1411 slurmdb_cluster_rec_t *cluster_rec = NULL;
1412 slurmdb_cluster_cond_t cluster_cond;
1413 List temp_list = NULL;
1414 char *cluster_name = NULL;
1415 void *db_conn = NULL;
1416 ListIterator itr, itr2;
1417 bool all_clusters = 0;
1418
1419 if (cluster_names && !xstrcasecmp(cluster_names, "all"))
1420 all_clusters = 1;
1421
1422 cluster_name = slurm_get_cluster_name();
1423 db_conn = acct_storage_g_get_connection(NULL, 0, NULL, 1, cluster_name);
1424 xfree(cluster_name);
1425
1426 slurmdb_init_cluster_cond(&cluster_cond, 0);
1427 if (cluster_names && !all_clusters) {
1428 cluster_cond.cluster_list = list_create(xfree_ptr);
1429 slurm_addto_char_list(cluster_cond.cluster_list, cluster_names);
1430 }
1431
1432 if (!(temp_list = acct_storage_g_get_clusters(db_conn, getuid(),
1433 &cluster_cond))) {
1434 error("Problem talking to database");
1435 goto end_it;
1436 }
1437 itr = list_iterator_create(temp_list);
1438 if (!cluster_names || all_clusters) {
1439 while ((cluster_rec = list_next(itr))) {
1440 if (slurmdb_setup_cluster_rec(cluster_rec) !=
1441 SLURM_SUCCESS) {
1442 list_delete_item(itr);
1443 }
1444 }
1445 } else {
1446 itr2 = list_iterator_create(cluster_cond.cluster_list);
1447 while ((cluster_name = list_next(itr2))) {
1448 while ((cluster_rec = list_next(itr))) {
1449 if (!xstrcmp(cluster_name, cluster_rec->name))
1450 break;
1451 }
1452 if (!cluster_rec) {
1453 error("No cluster '%s' known by database.",
1454 cluster_name);
1455 goto next;
1456 }
1457
1458 if (slurmdb_setup_cluster_rec(cluster_rec) !=
1459 SLURM_SUCCESS) {
1460 list_delete_item(itr);
1461 }
1462 next:
1463 list_iterator_reset(itr);
1464 }
1465 list_iterator_destroy(itr2);
1466 }
1467 list_iterator_destroy(itr);
1468
1469 end_it:
1470 FREE_NULL_LIST(cluster_cond.cluster_list);
1471 acct_storage_g_close_connection(&db_conn);
1472
1473 if (temp_list && !list_count(temp_list)) {
1474 FREE_NULL_LIST(temp_list);
1475 }
1476
1477 return temp_list;
1478 }
1479
slurmdb_init_assoc_rec(slurmdb_assoc_rec_t * assoc,bool free_it)1480 extern void slurmdb_init_assoc_rec(slurmdb_assoc_rec_t *assoc,
1481 bool free_it)
1482 {
1483 if (!assoc)
1484 return;
1485
1486 if (free_it)
1487 slurmdb_free_assoc_rec_members(assoc);
1488 memset(assoc, 0, sizeof(slurmdb_assoc_rec_t));
1489
1490 assoc->def_qos_id = NO_VAL;
1491 assoc->is_def = NO_VAL16;
1492
1493 /* assoc->grp_tres_mins = NULL; */
1494 /* assoc->grp_tres_run_mins = NULL; */
1495 /* assoc->grp_tres = NULL; */
1496 assoc->grp_jobs = NO_VAL;
1497 assoc->grp_jobs_accrue = NO_VAL;
1498 assoc->grp_submit_jobs = NO_VAL;
1499 assoc->grp_wall = NO_VAL;
1500
1501 assoc->lft = NO_VAL;
1502 assoc->rgt = NO_VAL;
1503 /* assoc->level_shares = NO_VAL; */
1504
1505 /* assoc->max_tres_mins_pj = NULL; */
1506 /* assoc->max_tres_run_mins = NULL; */
1507 /* assoc->max_tres_pj = NULL; */
1508 assoc->max_jobs = NO_VAL;
1509 assoc->max_jobs_accrue = NO_VAL;
1510 assoc->min_prio_thresh = NO_VAL;
1511 assoc->max_submit_jobs = NO_VAL;
1512 assoc->max_wall_pj = NO_VAL;
1513
1514 assoc->priority = NO_VAL;
1515
1516 /* assoc->shares_norm = NO_VAL64; */
1517 assoc->shares_raw = NO_VAL;
1518
1519 /* assoc->usage_efctv = 0; */
1520 /* assoc->usage_norm = (long double)NO_VAL; */
1521 /* assoc->usage_raw = 0; */
1522 }
1523
slurmdb_init_clus_res_rec(slurmdb_clus_res_rec_t * clus_res,bool free_it)1524 extern void slurmdb_init_clus_res_rec(slurmdb_clus_res_rec_t *clus_res,
1525 bool free_it)
1526 {
1527 if (!clus_res)
1528 return;
1529
1530 if (free_it)
1531 _free_clus_res_rec_members(clus_res);
1532 memset(clus_res, 0, sizeof(slurmdb_clus_res_rec_t));
1533 clus_res->percent_allowed = NO_VAL16;
1534 }
1535
slurmdb_init_cluster_rec(slurmdb_cluster_rec_t * cluster,bool free_it)1536 extern void slurmdb_init_cluster_rec(slurmdb_cluster_rec_t *cluster,
1537 bool free_it)
1538 {
1539 if (!cluster)
1540 return;
1541
1542 if (free_it)
1543 _free_cluster_rec_members(cluster);
1544 memset(cluster, 0, sizeof(slurmdb_cluster_rec_t));
1545 cluster->flags = NO_VAL;
1546 cluster->fed.state = NO_VAL;
1547 slurm_mutex_init(&cluster->lock);
1548 }
1549
slurmdb_init_federation_rec(slurmdb_federation_rec_t * federation,bool free_it)1550 extern void slurmdb_init_federation_rec(slurmdb_federation_rec_t *federation,
1551 bool free_it)
1552 {
1553 if (!federation)
1554 return;
1555
1556 if (free_it)
1557 _free_federation_rec_members(federation);
1558 memset(federation, 0, sizeof(slurmdb_federation_rec_t));
1559 federation->flags = FEDERATION_FLAG_NOTSET;
1560 }
1561
slurmdb_init_qos_rec(slurmdb_qos_rec_t * qos,bool free_it,uint32_t init_val)1562 extern void slurmdb_init_qos_rec(slurmdb_qos_rec_t *qos, bool free_it,
1563 uint32_t init_val)
1564 {
1565 if (!qos)
1566 return;
1567
1568 if (free_it)
1569 slurmdb_free_qos_rec_members(qos);
1570 memset(qos, 0, sizeof(slurmdb_qos_rec_t));
1571
1572 qos->flags = QOS_FLAG_NOTSET;
1573
1574 qos->grace_time = init_val;
1575 qos->preempt_mode = (uint16_t)init_val;
1576 qos->preempt_exempt_time = init_val;
1577 qos->priority = init_val;
1578
1579 /* qos->grp_tres_mins = NULL; */
1580 /* qos->grp_tres_run_mins = NULL; */
1581 /* qos->grp_tres = NULL; */
1582 qos->grp_jobs = init_val;
1583 qos->grp_jobs_accrue = init_val;
1584 qos->grp_submit_jobs = init_val;
1585 qos->grp_wall = init_val;
1586
1587 /* qos->max_tres_mins_pj = NULL; */
1588 /* qos->max_tres_run_mins_pa = NULL; */
1589 /* qos->max_tres_run_mins_pu = NULL; */
1590 /* qos->max_tres_pa = NULL; */
1591 /* qos->max_tres_pj = NULL; */
1592 /* qos->max_tres_pu = NULL; */
1593 qos->max_jobs_pa = init_val;
1594 qos->max_jobs_pu = init_val;
1595 qos->max_jobs_accrue_pa = init_val;
1596 qos->max_jobs_accrue_pu = init_val;
1597 qos->min_prio_thresh = init_val;
1598 qos->max_submit_jobs_pa = init_val;
1599 qos->max_submit_jobs_pu = init_val;
1600 qos->max_wall_pj = init_val;
1601
1602 /* qos->min_tres_pj = NULL; */
1603
1604 qos->usage_factor = (double)init_val;
1605 qos->usage_thres = (double)init_val;
1606 }
1607
slurmdb_init_res_rec(slurmdb_res_rec_t * res,bool free_it)1608 extern void slurmdb_init_res_rec(slurmdb_res_rec_t *res,
1609 bool free_it)
1610 {
1611 if (!res)
1612 return;
1613
1614 if (free_it)
1615 _free_res_rec_members(res);
1616 memset(res, 0, sizeof(slurmdb_res_rec_t));
1617 res->count = NO_VAL;
1618 res->flags = SLURMDB_RES_FLAG_NOTSET;
1619 res->id = NO_VAL;
1620 res->percent_used = NO_VAL16;
1621 res->type = SLURMDB_RESOURCE_NOTSET;
1622 }
1623
slurmdb_init_wckey_rec(slurmdb_wckey_rec_t * wckey,bool free_it)1624 extern void slurmdb_init_wckey_rec(slurmdb_wckey_rec_t *wckey, bool free_it)
1625 {
1626 if (!wckey)
1627 return;
1628
1629 if (free_it)
1630 _free_wckey_rec_members(wckey);
1631 memset(wckey, 0, sizeof(slurmdb_wckey_rec_t));
1632 wckey->is_def = NO_VAL16;
1633 }
1634
slurmdb_init_tres_cond(slurmdb_tres_cond_t * tres,bool free_it)1635 extern void slurmdb_init_tres_cond(slurmdb_tres_cond_t *tres,
1636 bool free_it)
1637 {
1638 if (!tres)
1639 return;
1640
1641 if (free_it)
1642 _free_tres_cond_members(tres);
1643 memset(tres, 0, sizeof(slurmdb_tres_cond_t));
1644 tres->count = NO_VAL;
1645 }
1646
slurmdb_init_cluster_cond(slurmdb_cluster_cond_t * cluster,bool free_it)1647 extern void slurmdb_init_cluster_cond(slurmdb_cluster_cond_t *cluster,
1648 bool free_it)
1649 {
1650 if (!cluster)
1651 return;
1652
1653 if (free_it)
1654 _free_cluster_cond_members(cluster);
1655 memset(cluster, 0, sizeof(slurmdb_cluster_cond_t));
1656 cluster->flags = NO_VAL;
1657 }
1658
slurmdb_init_federation_cond(slurmdb_federation_cond_t * federation,bool free_it)1659 extern void slurmdb_init_federation_cond(slurmdb_federation_cond_t *federation,
1660 bool free_it)
1661 {
1662 if (!federation)
1663 return;
1664
1665 if (free_it)
1666 _free_federation_cond_members(federation);
1667 memset(federation, 0, sizeof(slurmdb_federation_cond_t));
1668 }
1669
slurmdb_init_res_cond(slurmdb_res_cond_t * res,bool free_it)1670 extern void slurmdb_init_res_cond(slurmdb_res_cond_t *res,
1671 bool free_it)
1672 {
1673 if (!res)
1674 return;
1675
1676 if (free_it)
1677 _free_res_cond_members(res);
1678 memset(res, 0, sizeof(slurmdb_res_cond_t));
1679 res->flags = SLURMDB_RES_FLAG_NOTSET;
1680 }
1681
slurmdb_qos_str(List qos_list,uint32_t level)1682 extern char *slurmdb_qos_str(List qos_list, uint32_t level)
1683 {
1684 slurmdb_qos_rec_t *qos = NULL;
1685
1686 if (!qos_list) {
1687 error("We need a qos list to translate");
1688 return NULL;
1689 } else if (!level) {
1690 debug2("no level");
1691 return "";
1692 }
1693
1694 qos = list_find_first(qos_list, slurmdb_find_qos_in_list, &level);
1695 if (qos)
1696 return qos->name;
1697 else
1698 return NULL;
1699 }
1700
str_2_slurmdb_qos(List qos_list,char * level)1701 extern uint32_t str_2_slurmdb_qos(List qos_list, char *level)
1702 {
1703 ListIterator itr = NULL;
1704 slurmdb_qos_rec_t *qos = NULL;
1705 char *working_level = NULL;
1706
1707 if (!qos_list) {
1708 error("We need a qos list to translate");
1709 return NO_VAL;
1710 } else if (!level) {
1711 debug2("no level");
1712 return 0;
1713 }
1714 if (level[0] == '+' || level[0] == '-')
1715 working_level = level+1;
1716 else
1717 working_level = level;
1718
1719 itr = list_iterator_create(qos_list);
1720 while((qos = list_next(itr))) {
1721 if (!xstrcasecmp(working_level, qos->name))
1722 break;
1723 }
1724 list_iterator_destroy(itr);
1725 if (qos)
1726 return qos->id;
1727 else
1728 return NO_VAL;
1729 }
1730
slurmdb_federation_flags_str(uint32_t flags)1731 extern char *slurmdb_federation_flags_str(uint32_t flags)
1732 {
1733 char *federation_flags = NULL;
1734
1735 if (flags & FEDERATION_FLAG_NOTSET)
1736 return xstrdup("NotSet");
1737
1738 #if 0
1739 /* Remove when there are actually flags since the flags will be
1740 * comma-separated. */
1741 if (federation_flags)
1742 federation_flags[strlen(federation_flags)-1] = '\0';
1743 #endif
1744
1745 return federation_flags;
1746 }
1747
_str_2_federation_flags(char * flags)1748 static uint32_t _str_2_federation_flags(char *flags)
1749 {
1750 return 0;
1751 }
1752
str_2_federation_flags(char * flags,int option)1753 extern uint32_t str_2_federation_flags(char *flags, int option)
1754 {
1755 uint32_t federation_flags = 0;
1756 char *token, *my_flags, *last = NULL;
1757
1758 if (!flags) {
1759 error("We need a federation flags string to translate");
1760 return FEDERATION_FLAG_NOTSET;
1761 } else if (atoi(flags) == -1) {
1762 /* clear them all */
1763 federation_flags = INFINITE;
1764 federation_flags &= (~FEDERATION_FLAG_NOTSET &
1765 ~FEDERATION_FLAG_ADD);
1766 return federation_flags;
1767 }
1768
1769 my_flags = xstrdup(flags);
1770 token = strtok_r(my_flags, ",", &last);
1771 while (token) {
1772 federation_flags |= _str_2_federation_flags(token);
1773 token = strtok_r(NULL, ",", &last);
1774 }
1775 xfree(my_flags);
1776
1777 if (!federation_flags)
1778 federation_flags = FEDERATION_FLAG_NOTSET;
1779 else if (option == '+')
1780 federation_flags |= FEDERATION_FLAG_ADD;
1781 else if (option == '-')
1782 federation_flags |= FEDERATION_FLAG_REMOVE;
1783
1784 return federation_flags;
1785 }
1786
slurmdb_cluster_fed_states_str(uint32_t state)1787 extern char *slurmdb_cluster_fed_states_str(uint32_t state)
1788 {
1789 int base = (state & CLUSTER_FED_STATE_BASE);
1790 bool drain_flag = (state & CLUSTER_FED_STATE_DRAIN);
1791 bool remove_flag = (state & CLUSTER_FED_STATE_REMOVE);
1792
1793 if (base == CLUSTER_FED_STATE_ACTIVE) {
1794 if (remove_flag && drain_flag)
1795 return "DRAIN+REMOVE";
1796 else if (drain_flag)
1797 return "DRAIN";
1798 else
1799 return "ACTIVE";
1800 } else if (base == CLUSTER_FED_STATE_INACTIVE) {
1801 if (remove_flag && drain_flag)
1802 return "DRAINED+REMOVE";
1803 else if (drain_flag)
1804 return "DRAINED";
1805 else
1806 return "INACTIVE";
1807 } else if (base == CLUSTER_FED_STATE_NA)
1808 return "NA";
1809
1810 return "?";
1811 }
1812
str_2_cluster_fed_states(char * state)1813 extern uint32_t str_2_cluster_fed_states(char *state)
1814 {
1815 uint32_t fed_state = 0;
1816
1817 if (!state) {
1818 error("We need a cluster federation state string to translate");
1819 return SLURM_ERROR;
1820 }
1821
1822 if (!xstrncasecmp(state, "Active", strlen(state)))
1823 fed_state = CLUSTER_FED_STATE_ACTIVE;
1824 else if (!xstrncasecmp(state, "Inactive", strlen(state)))
1825 fed_state = CLUSTER_FED_STATE_INACTIVE;
1826 else if (!xstrncasecmp(state, "DRAIN", strlen(state))) {
1827 fed_state = CLUSTER_FED_STATE_ACTIVE;
1828 fed_state |= CLUSTER_FED_STATE_DRAIN;
1829 } else if (!xstrncasecmp(state, "DRAIN+REMOVE", strlen(state))) {
1830 fed_state = CLUSTER_FED_STATE_ACTIVE;
1831 fed_state |= (CLUSTER_FED_STATE_DRAIN |
1832 CLUSTER_FED_STATE_REMOVE);
1833 }
1834
1835 return fed_state;
1836 }
1837
slurmdb_job_flags_str(uint32_t flags)1838 extern char *slurmdb_job_flags_str(uint32_t flags)
1839 {
1840 char *job_flags = NULL;
1841
1842 if (flags == SLURMDB_JOB_FLAG_NONE)
1843 return xstrdup("None");
1844
1845 if (flags & SLURMDB_JOB_FLAG_NOTSET)
1846 return xstrdup("NotSet");
1847
1848 if (flags & SLURMDB_JOB_FLAG_SUBMIT)
1849 xstrcat(job_flags, "SchedSubmit");
1850 else if (flags & SLURMDB_JOB_FLAG_SCHED)
1851 xstrcat(job_flags, "SchedMain");
1852 else if (flags & SLURMDB_JOB_FLAG_BACKFILL)
1853 xstrcat(job_flags, "SchedBackfill");
1854
1855 /*
1856 * In the future if there are more flags we will need to add comma's to
1857 * the end of Backfilled and NormalSched above and uncomment this code
1858 * below.
1859 */
1860 /* if (job_flags) */
1861 /* job_flags[strlen(job_flags)-1] = '\0'; */
1862
1863 return job_flags;
1864 }
1865
str_2_job_flags(char * flags)1866 extern uint32_t str_2_job_flags(char *flags)
1867 {
1868 uint32_t job_flags = 0;
1869 char *token, *my_flags, *last = NULL;
1870
1871 if (!flags) {
1872 error("We need a server job flags string to translate");
1873 return SLURMDB_JOB_FLAG_NONE;
1874 }
1875
1876 my_flags = xstrdup(flags);
1877 token = strtok_r(my_flags, ",", &last);
1878 while (token) {
1879 job_flags |= _str_2_job_flags(token);
1880 if (job_flags & SLURMDB_JOB_FLAG_NOTSET) {
1881 error("%s: Invalid job flag %s", __func__, token);
1882 xfree(my_flags);
1883 return SLURMDB_JOB_FLAG_NOTSET;
1884 }
1885 token = strtok_r(NULL, ",", &last);
1886 }
1887 xfree(my_flags);
1888
1889 return job_flags;
1890 }
1891
slurmdb_qos_flags_str(uint32_t flags)1892 extern char *slurmdb_qos_flags_str(uint32_t flags)
1893 {
1894 char *qos_flags = NULL;
1895
1896 if (flags & QOS_FLAG_NOTSET)
1897 return xstrdup("NotSet");
1898
1899 if (flags & QOS_FLAG_ADD)
1900 xstrcat(qos_flags, "Add,");
1901 if (flags & QOS_FLAG_REMOVE)
1902 xstrcat(qos_flags, "Remove,");
1903 if (flags & QOS_FLAG_DENY_LIMIT)
1904 xstrcat(qos_flags, "DenyOnLimit,");
1905 if (flags & QOS_FLAG_ENFORCE_USAGE_THRES)
1906 xstrcat(qos_flags, "EnforceUsageThreshold,");
1907 if (flags & QOS_FLAG_NO_RESERVE)
1908 xstrcat(qos_flags, "NoReserve,");
1909 if (flags & QOS_FLAG_PART_MAX_NODE)
1910 xstrcat(qos_flags, "PartitionMaxNodes,");
1911 if (flags & QOS_FLAG_PART_MIN_NODE)
1912 xstrcat(qos_flags, "PartitionMinNodes,");
1913 if (flags & QOS_FLAG_OVER_PART_QOS)
1914 xstrcat(qos_flags, "OverPartQOS,");
1915 if (flags & QOS_FLAG_PART_TIME_LIMIT)
1916 xstrcat(qos_flags, "PartitionTimeLimit,");
1917 if (flags & QOS_FLAG_REQ_RESV)
1918 xstrcat(qos_flags, "RequiresReservation,");
1919 if (flags & QOS_FLAG_NO_DECAY)
1920 xstrcat(qos_flags, "NoDecay,");
1921 if (flags & QOS_FLAG_USAGE_FACTOR_SAFE)
1922 xstrcat(qos_flags, "UsageFactorSafe,");
1923
1924 if (qos_flags)
1925 qos_flags[strlen(qos_flags)-1] = '\0';
1926
1927 return qos_flags;
1928 }
1929
str_2_qos_flags(char * flags,int option)1930 extern uint32_t str_2_qos_flags(char *flags, int option)
1931 {
1932 uint32_t qos_flags = 0;
1933 char *token, *my_flags, *last = NULL;
1934
1935 if (!flags) {
1936 error("We need a qos flags string to translate");
1937 return QOS_FLAG_NOTSET;
1938 } else if (atoi(flags) == -1) {
1939 /* clear them all */
1940 qos_flags = INFINITE;
1941 qos_flags &= (~QOS_FLAG_NOTSET &
1942 ~QOS_FLAG_ADD);
1943 return qos_flags;
1944 }
1945
1946 my_flags = xstrdup(flags);
1947 token = strtok_r(my_flags, ",", &last);
1948 while (token) {
1949 qos_flags |= _str_2_qos_flags(token);
1950 token = strtok_r(NULL, ",", &last);
1951 }
1952 xfree(my_flags);
1953
1954 if (!qos_flags)
1955 qos_flags = QOS_FLAG_NOTSET;
1956 else if (option == '+')
1957 qos_flags |= QOS_FLAG_ADD;
1958 else if (option == '-')
1959 qos_flags |= QOS_FLAG_REMOVE;
1960
1961
1962 return qos_flags;
1963 }
1964
slurmdb_res_flags_str(uint32_t flags)1965 extern char *slurmdb_res_flags_str(uint32_t flags)
1966 {
1967 char *res_flags = NULL;
1968
1969 if (flags & SLURMDB_RES_FLAG_NOTSET)
1970 return xstrdup("NotSet");
1971
1972 if (flags & SLURMDB_RES_FLAG_ADD)
1973 xstrcat(res_flags, "Add,");
1974 if (flags & SLURMDB_RES_FLAG_REMOVE)
1975 xstrcat(res_flags, "Remove,");
1976
1977 if (res_flags)
1978 res_flags[strlen(res_flags)-1] = '\0';
1979
1980 return res_flags;
1981 }
1982
str_2_res_flags(char * flags,int option)1983 extern uint32_t str_2_res_flags(char *flags, int option)
1984 {
1985 uint32_t res_flags = 0;
1986 char *token, *my_flags, *last = NULL;
1987
1988 if (!flags) {
1989 error("We need a server resource flags string to translate");
1990 return SLURMDB_RES_FLAG_NOTSET;
1991 } else if (atoi(flags) == -1) {
1992 /* clear them all */
1993 res_flags = INFINITE;
1994 res_flags &= (SLURMDB_RES_FLAG_NOTSET &
1995 ~SLURMDB_RES_FLAG_ADD);
1996 return res_flags;
1997 }
1998
1999 my_flags = xstrdup(flags);
2000 token = strtok_r(my_flags, ",", &last);
2001 while (token) {
2002 res_flags |= _str_2_res_flags(token);
2003 token = strtok_r(NULL, ",", &last);
2004 }
2005 xfree(my_flags);
2006
2007 if (!res_flags)
2008 res_flags = SLURMDB_RES_FLAG_NOTSET;
2009 else if (option == '+')
2010 res_flags |= SLURMDB_RES_FLAG_ADD;
2011 else if (option == '-')
2012 res_flags |= SLURMDB_RES_FLAG_REMOVE;
2013
2014
2015 return res_flags;
2016 }
2017
slurmdb_res_type_str(slurmdb_resource_type_t type)2018 extern char *slurmdb_res_type_str(slurmdb_resource_type_t type)
2019 {
2020 switch (type) {
2021 case SLURMDB_RESOURCE_NOTSET:
2022 return "Not Set";
2023 break;
2024 case SLURMDB_RESOURCE_LICENSE:
2025 return "License";
2026 break;
2027 }
2028 return "Unknown";
2029 }
2030
slurmdb_admin_level_str(slurmdb_admin_level_t level)2031 extern char *slurmdb_admin_level_str(slurmdb_admin_level_t level)
2032 {
2033 switch(level) {
2034 case SLURMDB_ADMIN_NOTSET:
2035 return "Not Set";
2036 break;
2037 case SLURMDB_ADMIN_NONE:
2038 return "None";
2039 break;
2040 case SLURMDB_ADMIN_OPERATOR:
2041 return "Operator";
2042 break;
2043 case SLURMDB_ADMIN_SUPER_USER:
2044 return "Administrator";
2045 break;
2046 }
2047 return "Unknown";
2048 }
2049
str_2_slurmdb_admin_level(char * level)2050 extern slurmdb_admin_level_t str_2_slurmdb_admin_level(char *level)
2051 {
2052 if (!level) {
2053 return SLURMDB_ADMIN_NOTSET;
2054 } else if (!xstrncasecmp(level, "None", 1)) {
2055 return SLURMDB_ADMIN_NONE;
2056 } else if (!xstrncasecmp(level, "Operator", 1)) {
2057 return SLURMDB_ADMIN_OPERATOR;
2058 } else if (!xstrncasecmp(level, "SuperUser", 1)
2059 || !xstrncasecmp(level, "Admin", 1)) {
2060 return SLURMDB_ADMIN_SUPER_USER;
2061 } else {
2062 return SLURMDB_ADMIN_NOTSET;
2063 }
2064 }
2065
2066 /* This reorders the list into a alphabetical hierarchy returned in a
2067 * separate list. The orginal list is not affected */
slurmdb_get_hierarchical_sorted_assoc_list(List assoc_list,bool use_lft)2068 extern List slurmdb_get_hierarchical_sorted_assoc_list(
2069 List assoc_list, bool use_lft)
2070 {
2071 List slurmdb_hierarchical_rec_list;
2072 List ret_list = list_create(NULL);
2073
2074 if (use_lft)
2075 slurmdb_hierarchical_rec_list =
2076 slurmdb_get_acct_hierarchical_rec_list(assoc_list);
2077 else
2078 slurmdb_hierarchical_rec_list =
2079 slurmdb_get_acct_hierarchical_rec_list_no_lft(
2080 assoc_list);
2081
2082 _append_hierarchical_children_ret_list(ret_list,
2083 slurmdb_hierarchical_rec_list);
2084 FREE_NULL_LIST(slurmdb_hierarchical_rec_list);
2085
2086 return ret_list;
2087 }
2088
2089 /* This reorders the list into a alphabetical hierarchy. */
slurmdb_sort_hierarchical_assoc_list(List assoc_list,bool use_lft)2090 extern void slurmdb_sort_hierarchical_assoc_list(
2091 List assoc_list, bool use_lft)
2092 {
2093 List slurmdb_hierarchical_rec_list;
2094
2095 if (use_lft)
2096 slurmdb_hierarchical_rec_list =
2097 slurmdb_get_acct_hierarchical_rec_list(assoc_list);
2098 else
2099 slurmdb_hierarchical_rec_list =
2100 slurmdb_get_acct_hierarchical_rec_list_no_lft(
2101 assoc_list);
2102
2103 /* Clear all the pointers out of the list without freeing the
2104 memory since we will just add them back in later.
2105 */
2106 while (list_pop(assoc_list)) {
2107 }
2108
2109 _append_hierarchical_children_ret_list(assoc_list,
2110 slurmdb_hierarchical_rec_list);
2111 FREE_NULL_LIST(slurmdb_hierarchical_rec_list);
2112 }
2113
2114 /* Build a hierarchical list using only association id's along with
2115 * parent id's. This method is slower than the non _no_lft function
2116 * below, but it is needed if the lft and rgt's ever get messed up.
2117 * Each association in here will result in a 0 rgt afterwards.
2118 */
slurmdb_get_acct_hierarchical_rec_list_no_lft(List assoc_list)2119 extern List slurmdb_get_acct_hierarchical_rec_list_no_lft(List assoc_list)
2120 {
2121 slurmdb_assoc_rec_t *assoc = NULL;
2122 List total_arch_list = list_create(NULL);
2123 List arch_rec_list = list_create(slurmdb_destroy_hierarchical_rec);
2124 ListIterator itr;
2125 /* DEF_TIMERS; */
2126 /* START_TIMER; */
2127
2128 itr = list_iterator_create(assoc_list);
2129 while ((assoc = list_next(itr))) {
2130 if (assoc->rgt == 0) // already processed
2131 continue;
2132
2133 _find_create_parent(assoc, assoc_list,
2134 arch_rec_list, total_arch_list);
2135 }
2136 list_iterator_destroy(itr);
2137 /* END_TIMER; */
2138 /* info("took %s", TIME_STR); */
2139 FREE_NULL_LIST(total_arch_list);
2140 // info("got %d", list_count(arch_rec_list));
2141 _sort_slurmdb_hierarchical_rec_list(arch_rec_list);
2142
2143 return arch_rec_list;
2144 }
2145
slurmdb_get_acct_hierarchical_rec_list(List assoc_list)2146 extern List slurmdb_get_acct_hierarchical_rec_list(List assoc_list)
2147 {
2148 slurmdb_hierarchical_rec_t *par_arch_rec = NULL;
2149 slurmdb_hierarchical_rec_t *last_acct_parent = NULL;
2150 slurmdb_hierarchical_rec_t *last_parent = NULL;
2151 slurmdb_hierarchical_rec_t *arch_rec = NULL;
2152 slurmdb_assoc_rec_t *assoc = NULL;
2153 List total_assoc_list = list_create(NULL);
2154 List arch_rec_list =
2155 list_create(slurmdb_destroy_hierarchical_rec);
2156 ListIterator itr, itr2;
2157
2158 /* The list should already be sorted by lfts, do it anyway
2159 * just to make sure it is correct. */
2160 list_sort(assoc_list, (ListCmpF)_sort_assoc_by_lft_dec);
2161 itr = list_iterator_create(assoc_list);
2162 itr2 = list_iterator_create(total_assoc_list);
2163
2164 while((assoc = list_next(itr))) {
2165 arch_rec = xmalloc(sizeof(slurmdb_hierarchical_rec_t));
2166 arch_rec->children =
2167 list_create(slurmdb_destroy_hierarchical_rec);
2168 arch_rec->assoc = assoc;
2169
2170 /* To speed things up we are first looking if we have
2171 a parent_id to look for. If that doesn't work see
2172 if the last parent we had was what we are looking
2173 for. Then if that isn't panning out look at the
2174 last account parent. If still we don't have it we
2175 will look for it in the list. If it isn't there we
2176 will just add it to the parent and call it good
2177 */
2178 if (!assoc->parent_id) {
2179 arch_rec->sort_name = assoc->cluster;
2180
2181 list_append(arch_rec_list, arch_rec);
2182 list_append(total_assoc_list, arch_rec);
2183
2184 continue;
2185 }
2186
2187 if (assoc->user)
2188 arch_rec->sort_name = assoc->user;
2189 else
2190 arch_rec->sort_name = assoc->acct;
2191
2192 if (last_parent && assoc->parent_id == last_parent->assoc->id
2193 && !xstrcmp(assoc->cluster, last_parent->assoc->cluster)) {
2194 par_arch_rec = last_parent;
2195 } else if (last_acct_parent
2196 && (assoc->parent_id == last_acct_parent->assoc->id)
2197 && !xstrcmp(assoc->cluster,
2198 last_acct_parent->assoc->cluster)) {
2199 par_arch_rec = last_acct_parent;
2200 } else {
2201 list_iterator_reset(itr2);
2202 while((par_arch_rec = list_next(itr2))) {
2203 if (assoc->parent_id == par_arch_rec->assoc->id
2204 && !xstrcmp(assoc->cluster,
2205 par_arch_rec->assoc->cluster)) {
2206 if (assoc->user)
2207 last_parent = par_arch_rec;
2208 else
2209 last_parent
2210 = last_acct_parent
2211 = par_arch_rec;
2212 break;
2213 }
2214 }
2215 }
2216
2217 if (!par_arch_rec) {
2218 list_append(arch_rec_list, arch_rec);
2219 last_parent = last_acct_parent = arch_rec;
2220 } else
2221 list_append(par_arch_rec->children, arch_rec);
2222
2223 list_append(total_assoc_list, arch_rec);
2224 }
2225 list_iterator_destroy(itr);
2226 list_iterator_destroy(itr2);
2227
2228 FREE_NULL_LIST(total_assoc_list);
2229 // info("got %d", list_count(arch_rec_list));
2230 _sort_slurmdb_hierarchical_rec_list(arch_rec_list);
2231
2232 return arch_rec_list;
2233 }
2234
2235 /* IN/OUT: tree_list a list of slurmdb_print_tree_t's */
slurmdb_tree_name_get(char * name,char * parent,List tree_list)2236 extern char *slurmdb_tree_name_get(char *name, char *parent, List tree_list)
2237 {
2238 ListIterator itr = NULL;
2239 slurmdb_print_tree_t *slurmdb_print_tree = NULL;
2240 slurmdb_print_tree_t *par_slurmdb_print_tree = NULL;
2241
2242 if (!tree_list)
2243 return NULL;
2244
2245 itr = list_iterator_create(tree_list);
2246 while((slurmdb_print_tree = list_next(itr))) {
2247 /* we don't care about users in this list. They are
2248 only there so we don't leak memory */
2249 if (slurmdb_print_tree->user)
2250 continue;
2251
2252 if (!xstrcmp(name, slurmdb_print_tree->name))
2253 break;
2254 else if (parent && !xstrcmp(parent, slurmdb_print_tree->name))
2255 par_slurmdb_print_tree = slurmdb_print_tree;
2256
2257 }
2258 list_iterator_destroy(itr);
2259
2260 if (parent && slurmdb_print_tree)
2261 return slurmdb_print_tree->print_name;
2262
2263 slurmdb_print_tree = xmalloc(sizeof(slurmdb_print_tree_t));
2264 slurmdb_print_tree->name = xstrdup(name);
2265 if (par_slurmdb_print_tree)
2266 slurmdb_print_tree->spaces =
2267 xstrdup_printf(" %s", par_slurmdb_print_tree->spaces);
2268 else
2269 slurmdb_print_tree->spaces = xstrdup("");
2270
2271 /* user account */
2272 if (name[0] == '|') {
2273 slurmdb_print_tree->print_name = xstrdup_printf(
2274 "%s%s", slurmdb_print_tree->spaces, parent);
2275 slurmdb_print_tree->user = 1;
2276 } else
2277 slurmdb_print_tree->print_name = xstrdup_printf(
2278 "%s%s", slurmdb_print_tree->spaces, name);
2279
2280 list_append(tree_list, slurmdb_print_tree);
2281
2282 return slurmdb_print_tree->print_name;
2283 }
2284
set_qos_bitstr_from_list(bitstr_t * valid_qos,List qos_list)2285 extern int set_qos_bitstr_from_list(bitstr_t *valid_qos, List qos_list)
2286 {
2287 ListIterator itr = NULL;
2288 int rc = SLURM_SUCCESS;
2289 char *temp_char = NULL;
2290
2291 xassert(valid_qos);
2292
2293 if (!qos_list)
2294 return SLURM_ERROR;
2295
2296 itr = list_iterator_create(qos_list);
2297 while((temp_char = list_next(itr)))
2298 _set_qos_bit_from_string(valid_qos, temp_char);
2299 list_iterator_destroy(itr);
2300
2301 return rc;
2302 }
2303
rollup_interval_to_string(int interval)2304 extern const char *rollup_interval_to_string(int interval)
2305 {
2306 switch (interval) {
2307 case DBD_ROLLUP_HOUR:
2308 return "Hour";
2309 case DBD_ROLLUP_DAY:
2310 return "Day";
2311 case DBD_ROLLUP_MONTH:
2312 return "Month";
2313 default:
2314 return "Unknown";
2315 }
2316 }
2317
set_qos_bitstr_from_string(bitstr_t * valid_qos,char * names)2318 extern int set_qos_bitstr_from_string(bitstr_t *valid_qos, char *names)
2319 {
2320 int rc = SLURM_SUCCESS;
2321 int i=0, start=0;
2322 char *name = NULL;
2323
2324 xassert(valid_qos);
2325
2326 if (!names)
2327 return SLURM_ERROR;
2328
2329 /* skip the first comma if it is one */
2330 if (names[i] == ',')
2331 i++;
2332
2333 start = i;
2334 while (names[i]) {
2335 //info("got %d - %d = %d", i, start, i-start);
2336 if (names[i] == ',') {
2337 /* If there is a comma at the end just
2338 ignore it */
2339 if (!names[i+1])
2340 break;
2341
2342 name = xstrndup(names+start, (i-start));
2343 /* info("got %s %d", name, i-start); */
2344 _set_qos_bit_from_string(valid_qos, name);
2345 xfree(name);
2346 i++;
2347 start = i;
2348 }
2349 i++;
2350 }
2351
2352 name = xstrndup(names+start, (i-start));
2353 /* info("got %s %d", name, i-start); */
2354 _set_qos_bit_from_string(valid_qos, name);
2355 xfree(name);
2356
2357 return rc;
2358 }
2359
get_qos_complete_str_bitstr(List qos_list,bitstr_t * valid_qos)2360 extern char *get_qos_complete_str_bitstr(List qos_list, bitstr_t *valid_qos)
2361 {
2362 List temp_list = NULL;
2363 char *temp_char = NULL;
2364 char *print_this = NULL;
2365 int i = 0;
2366
2367 if (!qos_list || !list_count(qos_list)
2368 || !valid_qos || (bit_ffs(valid_qos) == -1))
2369 return xstrdup("");
2370
2371 temp_list = list_create(NULL);
2372
2373 for(i=0; i<bit_size(valid_qos); i++) {
2374 if (!bit_test(valid_qos, i))
2375 continue;
2376 if ((temp_char = slurmdb_qos_str(qos_list, i)))
2377 list_append(temp_list, temp_char);
2378 }
2379 print_this = slurm_char_list_to_xstr(temp_list);
2380 FREE_NULL_LIST(temp_list);
2381
2382 if (!print_this)
2383 return xstrdup("");
2384
2385 return print_this;
2386 }
2387
get_qos_complete_str(List qos_list,List num_qos_list)2388 extern char *get_qos_complete_str(List qos_list, List num_qos_list)
2389 {
2390 List temp_list = NULL;
2391 char *temp_char = NULL;
2392 char *print_this = NULL;
2393 ListIterator itr = NULL;
2394 int option = 0;
2395
2396 if (!qos_list || !list_count(qos_list)
2397 || !num_qos_list || !list_count(num_qos_list))
2398 return xstrdup("");
2399
2400 temp_list = list_create(xfree_ptr);
2401
2402 itr = list_iterator_create(num_qos_list);
2403 while((temp_char = list_next(itr))) {
2404 option = 0;
2405 if (temp_char[0] == '+' || temp_char[0] == '-') {
2406 option = temp_char[0];
2407 temp_char++;
2408 }
2409 temp_char = slurmdb_qos_str(qos_list, atoi(temp_char));
2410 if (temp_char) {
2411 if (option)
2412 list_append(temp_list, xstrdup_printf(
2413 "%c%s", option, temp_char));
2414 else
2415 list_append(temp_list, xstrdup(temp_char));
2416 }
2417 }
2418 list_iterator_destroy(itr);
2419
2420 print_this = slurm_char_list_to_xstr(temp_list);
2421 FREE_NULL_LIST(temp_list);
2422
2423 if (!print_this)
2424 return xstrdup("");
2425
2426 return print_this;
2427 }
2428
get_classification_str(uint16_t class)2429 extern char *get_classification_str(uint16_t class)
2430 {
2431 bool classified = class & SLURMDB_CLASSIFIED_FLAG;
2432 slurmdb_classification_type_t type = class & SLURMDB_CLASS_BASE;
2433
2434 switch(type) {
2435 case SLURMDB_CLASS_NONE:
2436 return NULL;
2437 break;
2438 case SLURMDB_CLASS_CAPACITY:
2439 if (classified)
2440 return "*Capacity";
2441 else
2442 return "Capacity";
2443 break;
2444 case SLURMDB_CLASS_CAPABILITY:
2445 if (classified)
2446 return "*Capability";
2447 else
2448 return "Capability";
2449 break;
2450 case SLURMDB_CLASS_CAPAPACITY:
2451 if (classified)
2452 return "*Capapacity";
2453 else
2454 return "Capapacity";
2455 break;
2456 default:
2457 if (classified)
2458 return "*Unknown";
2459 else
2460 return "Unknown";
2461 break;
2462 }
2463 }
2464
str_2_classification(char * class)2465 extern uint16_t str_2_classification(char *class)
2466 {
2467 uint16_t type = 0;
2468 if (!class)
2469 return type;
2470
2471 if (xstrcasestr(class, "capac"))
2472 type = SLURMDB_CLASS_CAPACITY;
2473 else if (xstrcasestr(class, "capab"))
2474 type = SLURMDB_CLASS_CAPABILITY;
2475 else if (xstrcasestr(class, "capap"))
2476 type = SLURMDB_CLASS_CAPAPACITY;
2477
2478 if (xstrcasestr(class, "*"))
2479 type |= SLURMDB_CLASSIFIED_FLAG;
2480 else if (xstrcasestr(class, "class"))
2481 type |= SLURMDB_CLASSIFIED_FLAG;
2482
2483 return type;
2484 }
2485
slurmdb_problem_str_get(uint16_t problem)2486 extern char *slurmdb_problem_str_get(uint16_t problem)
2487 {
2488 slurmdb_problem_type_t type = problem;
2489
2490 switch(type) {
2491 case SLURMDB_PROBLEM_NOT_SET:
2492 return NULL;
2493 break;
2494 case SLURMDB_PROBLEM_ACCT_NO_ASSOC:
2495 return "Account has no Associations";
2496 break;
2497 case SLURMDB_PROBLEM_ACCT_NO_USERS:
2498 return "Account has no users";
2499 break;
2500 case SLURMDB_PROBLEM_USER_NO_ASSOC:
2501 return "User has no Associations";
2502 break;
2503 case SLURMDB_PROBLEM_USER_NO_UID:
2504 return "User does not have a uid";
2505 break;
2506 default:
2507 return "Unknown";
2508 break;
2509 }
2510 }
2511
str_2_slurmdb_problem(char * problem)2512 extern uint16_t str_2_slurmdb_problem(char *problem)
2513 {
2514 uint16_t type = 0;
2515
2516 if (!problem)
2517 return type;
2518
2519 if (xstrcasestr(problem, "account no assocs"))
2520 type = SLURMDB_PROBLEM_USER_NO_ASSOC;
2521 else if (xstrcasestr(problem, "account no users"))
2522 type = SLURMDB_PROBLEM_ACCT_NO_USERS;
2523 else if (xstrcasestr(problem, "user no assocs"))
2524 type = SLURMDB_PROBLEM_USER_NO_ASSOC;
2525 else if (xstrcasestr(problem, "user no uid"))
2526 type = SLURMDB_PROBLEM_USER_NO_UID;
2527
2528 return type;
2529 }
2530
log_assoc_rec(slurmdb_assoc_rec_t * assoc_ptr,List qos_list)2531 extern void log_assoc_rec(slurmdb_assoc_rec_t *assoc_ptr,
2532 List qos_list)
2533 {
2534 xassert(assoc_ptr);
2535
2536 debug2("association rec id : %u", assoc_ptr->id);
2537 debug2(" acct : %s", assoc_ptr->acct);
2538 debug2(" cluster : %s", assoc_ptr->cluster);
2539
2540 if (assoc_ptr->shares_raw == INFINITE)
2541 debug2(" RawShares : NONE");
2542 else if (assoc_ptr->shares_raw != NO_VAL)
2543 debug2(" RawShares : %u", assoc_ptr->shares_raw);
2544
2545 if (assoc_ptr->def_qos_id)
2546 debug2(" Default QOS : %s",
2547 slurmdb_qos_str(qos_list, assoc_ptr->def_qos_id));
2548 else
2549 debug2(" Default QOS : NONE");
2550
2551 debug2(" GrpTRESMins : %s",
2552 assoc_ptr->grp_tres_mins ?
2553 assoc_ptr->grp_tres_mins : "NONE");
2554 debug2(" GrpTRESRunMins : %s",
2555 assoc_ptr->grp_tres_run_mins ?
2556 assoc_ptr->grp_tres_run_mins : "NONE");
2557 debug2(" GrpTRES : %s",
2558 assoc_ptr->grp_tres ?
2559 assoc_ptr->grp_tres : "NONE");
2560
2561 if (assoc_ptr->grp_jobs == INFINITE)
2562 debug2(" GrpJobs : NONE");
2563 else if (assoc_ptr->grp_jobs != NO_VAL)
2564 debug2(" GrpJobs : %u", assoc_ptr->grp_jobs);
2565
2566 if (assoc_ptr->grp_jobs_accrue == INFINITE)
2567 debug2(" GrpJobsAccrue : NONE");
2568 else if (assoc_ptr->grp_jobs_accrue != NO_VAL)
2569 debug2(" GrpJobsAccrue : %u", assoc_ptr->grp_jobs_accrue);
2570
2571 if (assoc_ptr->grp_submit_jobs == INFINITE)
2572 debug2(" GrpSubmitJobs : NONE");
2573 else if (assoc_ptr->grp_submit_jobs != NO_VAL)
2574 debug2(" GrpSubmitJobs : %u", assoc_ptr->grp_submit_jobs);
2575
2576 if (assoc_ptr->grp_wall == INFINITE)
2577 debug2(" GrpWall : NONE");
2578 else if (assoc_ptr->grp_wall != NO_VAL) {
2579 char time_buf[32];
2580 mins2time_str((time_t) assoc_ptr->grp_wall,
2581 time_buf, sizeof(time_buf));
2582 debug2(" GrpWall : %s", time_buf);
2583 }
2584
2585 debug2(" MaxTRESMins : %s",
2586 assoc_ptr->max_tres_mins_pj ?
2587 assoc_ptr->max_tres_mins_pj : "NONE");
2588 debug2(" MaxTRESRunMins : %s",
2589 assoc_ptr->max_tres_run_mins ?
2590 assoc_ptr->max_tres_run_mins : "NONE");
2591 debug2(" MaxTRESPerJob : %s",
2592 assoc_ptr->max_tres_pj ?
2593 assoc_ptr->max_tres_pj : "NONE");
2594 debug2(" MaxTRESPerNode : %s",
2595 assoc_ptr->max_tres_pn ?
2596 assoc_ptr->max_tres_pn : "NONE");
2597
2598 if (assoc_ptr->max_jobs == INFINITE)
2599 debug2(" MaxJobs : NONE");
2600 else if (assoc_ptr->max_jobs != NO_VAL)
2601 debug2(" MaxJobs : %u", assoc_ptr->max_jobs);
2602
2603 if (assoc_ptr->max_jobs_accrue == INFINITE)
2604 debug2(" MaxJobsAccrue : NONE");
2605 else if (assoc_ptr->max_jobs_accrue != NO_VAL)
2606 debug2(" MaxJobsAccrue : %u", assoc_ptr->max_jobs_accrue);
2607
2608 if (assoc_ptr->min_prio_thresh == INFINITE)
2609 debug2(" MinPrioThresh : NONE");
2610 else if (assoc_ptr->min_prio_thresh != NO_VAL)
2611 debug2(" MinPrioThresh : %u", assoc_ptr->min_prio_thresh);
2612
2613 if (assoc_ptr->max_submit_jobs == INFINITE)
2614 debug2(" MaxSubmitJobs : NONE");
2615 else if (assoc_ptr->max_submit_jobs != NO_VAL)
2616 debug2(" MaxSubmitJobs : %u", assoc_ptr->max_submit_jobs);
2617
2618 if (assoc_ptr->max_wall_pj == INFINITE)
2619 debug2(" MaxWall : NONE");
2620 else if (assoc_ptr->max_wall_pj != NO_VAL) {
2621 char time_buf[32];
2622 mins2time_str((time_t) assoc_ptr->max_wall_pj,
2623 time_buf, sizeof(time_buf));
2624 debug2(" MaxWall : %s", time_buf);
2625 }
2626
2627 if (assoc_ptr->qos_list) {
2628 char *temp_char = get_qos_complete_str(qos_list,
2629 assoc_ptr->qos_list);
2630 if (temp_char) {
2631 debug2(" Qos : %s", temp_char);
2632 xfree(temp_char);
2633 if (assoc_ptr->usage && assoc_ptr->usage->valid_qos) {
2634 temp_char = get_qos_complete_str_bitstr(
2635 qos_list, assoc_ptr->usage->valid_qos);
2636 debug3(" Valid Qos : %s", temp_char);
2637 xfree(temp_char);
2638 }
2639 }
2640 } else {
2641 debug2(" Qos : %s", "Normal");
2642 }
2643
2644 if (assoc_ptr->parent_acct)
2645 debug2(" ParentAccount : %s", assoc_ptr->parent_acct);
2646 if (assoc_ptr->partition)
2647 debug2(" Partition : %s", assoc_ptr->partition);
2648 if (assoc_ptr->user)
2649 debug2(" User : %s(%u)",
2650 assoc_ptr->user, assoc_ptr->uid);
2651
2652 if (assoc_ptr->usage) {
2653 if (!fuzzy_equal(assoc_ptr->usage->shares_norm, NO_VAL))
2654 debug2(" NormalizedShares : %f",
2655 assoc_ptr->usage->shares_norm);
2656
2657 if (assoc_ptr->usage->level_shares != NO_VAL)
2658 debug2(" LevelShares : %u",
2659 assoc_ptr->usage->level_shares);
2660
2661
2662 debug2(" UsedJobs : %u", assoc_ptr->usage->used_jobs);
2663 debug2(" RawUsage : %Lf", assoc_ptr->usage->usage_raw);
2664 }
2665 }
2666
slurmdb_report_set_start_end_time(time_t * start,time_t * end)2667 extern int slurmdb_report_set_start_end_time(time_t *start, time_t *end)
2668 {
2669 time_t my_time = time(NULL);
2670 time_t temp_time;
2671 struct tm start_tm;
2672 struct tm end_tm;
2673 int sent_start = (*start), sent_end = (*end);
2674
2675 // info("now got %d and %d sent", (*start), (*end));
2676 /* Default is going to be the last day */
2677 if (!sent_end) {
2678 if (!localtime_r(&my_time, &end_tm)) {
2679 error("Couldn't get localtime from end %ld",
2680 (long)my_time);
2681 return SLURM_ERROR;
2682 }
2683 end_tm.tm_hour = 0;
2684 //(*end) = slurm_mktime(&end_tm);
2685 } else {
2686 temp_time = sent_end;
2687 if (!localtime_r(&temp_time, &end_tm)) {
2688 error("Couldn't get localtime from user end %ld",
2689 (long)my_time);
2690 return SLURM_ERROR;
2691 }
2692 if (end_tm.tm_sec >= 30)
2693 end_tm.tm_min++;
2694 if (end_tm.tm_min >= 30)
2695 end_tm.tm_hour++;
2696 }
2697
2698 end_tm.tm_sec = 0;
2699 end_tm.tm_min = 0;
2700 (*end) = slurm_mktime(&end_tm);
2701
2702 if (!sent_start) {
2703 if (!localtime_r(&my_time, &start_tm)) {
2704 error("Couldn't get localtime from start %ld",
2705 (long)my_time);
2706 return SLURM_ERROR;
2707 }
2708 start_tm.tm_hour = 0;
2709 start_tm.tm_mday--;
2710 //(*start) = slurm_mktime(&start_tm);
2711 } else {
2712 temp_time = sent_start;
2713 if (!localtime_r(&temp_time, &start_tm)) {
2714 error("Couldn't get localtime from user start %ld",
2715 (long)my_time);
2716 return SLURM_ERROR;
2717 }
2718 if (start_tm.tm_sec >= 30)
2719 start_tm.tm_min++;
2720 if (start_tm.tm_min >= 30)
2721 start_tm.tm_hour++;
2722 }
2723 start_tm.tm_sec = 0;
2724 start_tm.tm_min = 0;
2725 (*start) = slurm_mktime(&start_tm);
2726
2727 if ((*end)-(*start) < 3600)
2728 (*end) = (*start) + 3600;
2729 /* info("now got %d and %d sent", (*start), (*end)); */
2730 /* char start_char[20]; */
2731 /* char end_char[20]; */
2732 /* time_t my_start = (*start); */
2733 /* time_t my_end = (*end); */
2734
2735 /* slurm_make_time_str(&my_start, */
2736 /* start_char, sizeof(start_char)); */
2737 /* slurm_make_time_str(&my_end, */
2738 /* end_char, sizeof(end_char)); */
2739 /* info("which is %s - %s", start_char, end_char); */
2740 return SLURM_SUCCESS;
2741 }
2742
2743 /* Convert a string to a duration in Months or Days
2744 * input formats:
2745 * <integer> defaults to Months
2746 * <integer>Months
2747 * <integer>Days
2748 * <integer>Hours
2749 *
2750 * output:
2751 * SLURMDB_PURGE_MONTHS | <integer> if input is in Months
2752 * SLURMDB_PURGE_DAYS | <integer> if input is in Days
2753 * SLURMDB_PURGE_HOURS | <integer> if input in in Hours
2754 * 0 on error
2755 */
slurmdb_parse_purge(char * string)2756 extern uint32_t slurmdb_parse_purge(char *string)
2757 {
2758 int i = 0;
2759 uint32_t purge = NO_VAL;
2760
2761 xassert(string);
2762
2763 while(string[i]) {
2764 if ((string[i] >= '0') && (string[i] <= '9')) {
2765 if (purge == NO_VAL)
2766 purge = 0;
2767 purge = (purge * 10) + (string[i] - '0');
2768 } else
2769 break;
2770 i++;
2771 }
2772
2773 if (purge != NO_VAL) {
2774 int len = strlen(string+i);
2775 if (!len || !xstrncasecmp("months", string+i, MAX(len, 1))) {
2776 purge |= SLURMDB_PURGE_MONTHS;
2777 } else if (!xstrncasecmp("hours", string+i, MAX(len, 1))) {
2778 purge |= SLURMDB_PURGE_HOURS;
2779 } else if (!xstrncasecmp("days", string+i, MAX(len, 1))) {
2780 purge |= SLURMDB_PURGE_DAYS;
2781 } else {
2782 error("Invalid purge unit '%s', valid options "
2783 "are hours, days, or months", string+i);
2784 purge = NO_VAL;
2785 }
2786 } else
2787 error("Invalid purge string '%s'", string);
2788
2789 return purge;
2790 }
2791
slurmdb_purge_string(uint32_t purge,char * string,int len,bool with_archive)2792 extern char *slurmdb_purge_string(uint32_t purge, char *string, int len,
2793 bool with_archive)
2794 {
2795 uint32_t units;
2796
2797 if (purge == NO_VAL) {
2798 snprintf(string, len, "NONE");
2799 return string;
2800 }
2801
2802 units = SLURMDB_PURGE_GET_UNITS(purge);
2803 if (SLURMDB_PURGE_IN_HOURS(purge)) {
2804 if (with_archive && SLURMDB_PURGE_ARCHIVE_SET(purge))
2805 snprintf(string, len, "%u hours*", units);
2806 else
2807 snprintf(string, len, "%u hours", units);
2808 } else if (SLURMDB_PURGE_IN_DAYS(purge)) {
2809 if (with_archive && SLURMDB_PURGE_ARCHIVE_SET(purge))
2810 snprintf(string, len, "%u days*", units);
2811 else
2812 snprintf(string, len, "%u days", units);
2813 } else {
2814 if (with_archive && SLURMDB_PURGE_ARCHIVE_SET(purge))
2815 snprintf(string, len, "%u months*", units);
2816 else
2817 snprintf(string, len, "%u months", units);
2818 }
2819
2820 return string;
2821 }
2822
slurmdb_addto_qos_char_list(List char_list,List qos_list,char * names,int option)2823 extern int slurmdb_addto_qos_char_list(List char_list, List qos_list,
2824 char *names, int option)
2825 {
2826 int i=0, start=0;
2827 char *name = NULL, *tmp_char = NULL;
2828 ListIterator itr = NULL;
2829 char quote_c = '\0';
2830 int quote = 0;
2831 uint32_t id=0;
2832 int count = 0;
2833 int equal_set = 0;
2834 int add_set = 0;
2835
2836 if (!char_list) {
2837 error("No list was given to fill in");
2838 return 0;
2839 }
2840
2841 if (!qos_list || !list_count(qos_list)) {
2842 debug2("No real qos_list");
2843 return 0;
2844 }
2845
2846 itr = list_iterator_create(char_list);
2847 if (names) {
2848 if (names[i] == '\"' || names[i] == '\'') {
2849 quote_c = names[i];
2850 quote = 1;
2851 i++;
2852 }
2853 start = i;
2854 while(names[i]) {
2855 if (quote && names[i] == quote_c)
2856 break;
2857 else if (names[i] == '\"' || names[i] == '\'')
2858 names[i] = '`';
2859 else if (names[i] == ',') {
2860 if ((i-start) > 0) {
2861 int tmp_option = option;
2862 if (names[start] == '+'
2863 || names[start] == '-') {
2864 tmp_option = names[start];
2865 start++;
2866 }
2867 name = xmalloc((i-start+1));
2868 memcpy(name, names+start, (i-start));
2869
2870 id = str_2_slurmdb_qos(qos_list, name);
2871 if (id == NO_VAL) {
2872 char *tmp = _get_qos_list_str(
2873 qos_list);
2874 error("You gave a bad qos "
2875 "'%s'. Valid QOS's are "
2876 "%s",
2877 name, tmp);
2878 xfree(tmp);
2879 xfree(name);
2880 break;
2881 }
2882 xfree(name);
2883
2884 if (tmp_option) {
2885 if (equal_set) {
2886 error("You can't set "
2887 "qos equal to "
2888 "something and "
2889 "then add or "
2890 "subtract from "
2891 "it in the same "
2892 "line");
2893 break;
2894 }
2895 add_set = 1;
2896 name = xstrdup_printf(
2897 "%c%u", tmp_option, id);
2898 } else {
2899 if (add_set) {
2900 error("You can't set "
2901 "qos equal to "
2902 "something and "
2903 "then add or "
2904 "subtract from "
2905 "it in the same "
2906 "line");
2907 break;
2908 }
2909 equal_set = 1;
2910 name = xstrdup_printf("%u", id);
2911 }
2912 while((tmp_char = list_next(itr))) {
2913 if (!xstrcasecmp(tmp_char,
2914 name))
2915 break;
2916 }
2917 list_iterator_reset(itr);
2918
2919 if (!tmp_char) {
2920 list_append(char_list, name);
2921 count++;
2922 } else
2923 xfree(name);
2924 } else if (!(i-start)) {
2925 list_append(char_list, xstrdup(""));
2926 count++;
2927 }
2928
2929 i++;
2930 start = i;
2931 if (!names[i]) {
2932 error("There is a problem with "
2933 "your request. It appears you "
2934 "have spaces inside your list.");
2935 break;
2936 }
2937 }
2938 i++;
2939 }
2940 if ((i-start) > 0) {
2941 int tmp_option = option;
2942 if (names[start] == '+' || names[start] == '-') {
2943 tmp_option = names[start];
2944 start++;
2945 }
2946 name = xmalloc((i-start)+1);
2947 memcpy(name, names+start, (i-start));
2948
2949 id = str_2_slurmdb_qos(qos_list, name);
2950 if (id == NO_VAL) {
2951 char *tmp = _get_qos_list_str(qos_list);
2952 error("You gave a bad qos "
2953 "'%s'. Valid QOS's are "
2954 "%s",
2955 name, tmp);
2956 xfree(tmp);
2957 xfree(name);
2958 goto end_it;
2959 }
2960 xfree(name);
2961
2962 if (tmp_option) {
2963 if (equal_set) {
2964 error("You can't set "
2965 "qos equal to "
2966 "something and "
2967 "then add or "
2968 "subtract from "
2969 "it in the same "
2970 "line");
2971 goto end_it;
2972 }
2973 name = xstrdup_printf(
2974 "%c%u", tmp_option, id);
2975 } else {
2976 if (add_set) {
2977 error("You can't set "
2978 "qos equal to "
2979 "something and "
2980 "then add or "
2981 "subtract from "
2982 "it in the same "
2983 "line");
2984 goto end_it;
2985 }
2986 name = xstrdup_printf("%u", id);
2987 }
2988 while((tmp_char = list_next(itr))) {
2989 if (!xstrcasecmp(tmp_char, name))
2990 break;
2991 }
2992
2993 if (!tmp_char) {
2994 list_append(char_list, name);
2995 count++;
2996 } else
2997 xfree(name);
2998 } else if (!(i-start)) {
2999 list_append(char_list, xstrdup(""));
3000 count++;
3001 }
3002 }
3003 if (!count) {
3004 error("You gave me an empty qos list");
3005 }
3006
3007 end_it:
3008 list_iterator_destroy(itr);
3009 return count;
3010 }
3011
3012 /*
3013 * send_accounting_update - send update to controller of cluster
3014 * IN update_list: updates to send
3015 * IN cluster: name of cluster
3016 * IN host: control host of cluster
3017 * IN port: control port of cluster
3018 * IN rpc_version: rpc version of cluster
3019 * RET: error code
3020 */
slurmdb_send_accounting_update(List update_list,char * cluster,char * host,uint16_t port,uint16_t rpc_version)3021 extern int slurmdb_send_accounting_update(List update_list, char *cluster,
3022 char *host, uint16_t port,
3023 uint16_t rpc_version)
3024 {
3025 accounting_update_msg_t msg;
3026 slurm_msg_t req;
3027 slurm_msg_t resp;
3028 int i, rc;
3029
3030 // Set highest version that we can use
3031 if (rpc_version > SLURM_PROTOCOL_VERSION) {
3032 rpc_version = SLURM_PROTOCOL_VERSION;
3033 }
3034 memset(&msg, 0, sizeof(accounting_update_msg_t));
3035 msg.rpc_version = rpc_version;
3036 msg.update_list = update_list;
3037
3038 debug("sending updates to %s at %s(%hu) ver %hu",
3039 cluster, host, port, rpc_version);
3040
3041 slurm_msg_t_init(&req);
3042 slurm_set_addr_char(&req.address, port, host);
3043
3044 req.protocol_version = rpc_version;
3045
3046 req.msg_type = ACCOUNTING_UPDATE_MSG;
3047 if (slurmdbd_conf)
3048 req.flags = SLURM_GLOBAL_AUTH_KEY;
3049 req.data = &msg;
3050 slurm_msg_t_init(&resp);
3051
3052 for (i = 0; i < 4; i++) {
3053 /* Retry if the slurmctld can connect, but is not responding */
3054 rc = slurm_send_recv_node_msg(&req, &resp, 0);
3055 if ((rc == SLURM_SUCCESS) ||
3056 (errno != SLURM_PROTOCOL_SOCKET_IMPL_TIMEOUT))
3057 break;
3058 }
3059 if ((rc != SLURM_SUCCESS) || !resp.auth_cred) {
3060 error("update cluster: %m to %s at %s(%hu)",
3061 cluster, host, port);
3062 rc = SLURM_ERROR;
3063 }
3064 if (resp.auth_cred)
3065 g_slurm_auth_destroy(resp.auth_cred);
3066
3067 switch (resp.msg_type) {
3068 case RESPONSE_SLURM_RC:
3069 rc = ((return_code_msg_t *)resp.data)->return_code;
3070 slurm_free_return_code_msg(resp.data);
3071 break;
3072 default:
3073 if (rc != SLURM_ERROR)
3074 error("Unknown response message %u", resp.msg_type);
3075 rc = SLURM_ERROR;
3076 break;
3077 }
3078 //info("got rc of %d", rc);
3079 return rc;
3080 }
3081
slurmdb_cluster_rec_2_report(slurmdb_cluster_rec_t * cluster)3082 extern slurmdb_report_cluster_rec_t *slurmdb_cluster_rec_2_report(
3083 slurmdb_cluster_rec_t *cluster)
3084 {
3085 slurmdb_report_cluster_rec_t *slurmdb_report_cluster;
3086 slurmdb_cluster_accounting_rec_t *accting = NULL;
3087 slurmdb_tres_rec_t *tres_rec;
3088 ListIterator itr = NULL;
3089 int count;
3090
3091 xassert(cluster);
3092 slurmdb_report_cluster = xmalloc(sizeof(slurmdb_report_cluster_rec_t));
3093 slurmdb_report_cluster->name = xstrdup(cluster->name);
3094
3095 if (!(count = list_count(cluster->accounting_list)))
3096 return slurmdb_report_cluster;
3097
3098 /* get the amount of time and the average count
3099 during the time we are looking at */
3100 itr = list_iterator_create(cluster->accounting_list);
3101 while ((accting = list_next(itr)))
3102 slurmdb_add_cluster_accounting_to_tres_list(
3103 accting, &slurmdb_report_cluster->tres_list);
3104 list_iterator_destroy(itr);
3105
3106 itr = list_iterator_create(slurmdb_report_cluster->tres_list);
3107 while ((tres_rec = list_next(itr)))
3108 tres_rec->count /= tres_rec->rec_count;
3109 list_iterator_destroy(itr);
3110
3111 return slurmdb_report_cluster;
3112 }
3113
slurmdb_get_selected_step_id(char * job_id_str,int len,slurmdb_selected_step_t * selected_step)3114 extern char *slurmdb_get_selected_step_id(
3115 char *job_id_str, int len,
3116 slurmdb_selected_step_t *selected_step)
3117 {
3118 char id[FORMAT_STRING_SIZE];
3119
3120 xassert(selected_step);
3121
3122 if (selected_step->array_task_id != NO_VAL) {
3123 snprintf(id, FORMAT_STRING_SIZE,
3124 "%u_%u",
3125 selected_step->jobid,
3126 selected_step->array_task_id);
3127 } else if (selected_step->het_job_offset != NO_VAL) {
3128 snprintf(id, FORMAT_STRING_SIZE,
3129 "%u+%u",
3130 selected_step->jobid,
3131 selected_step->het_job_offset);
3132 } else {
3133 snprintf(id, FORMAT_STRING_SIZE,
3134 "%u",
3135 selected_step->jobid);
3136 }
3137
3138 if (selected_step->stepid != NO_VAL)
3139 snprintf(job_id_str, len, "%s.%u",
3140 id, selected_step->stepid);
3141 else
3142 snprintf(job_id_str, len, "%s", id);
3143
3144 return job_id_str;
3145 }
3146
3147 /*
3148 * get the first cluster that will run a job
3149 * IN: req - description of resource allocation request
3150 * IN: cluster_names - comma separated string of cluster names
3151 * OUT: cluster_rec - record of selected cluster or NULL if none found or
3152 * cluster_names is NULL
3153 * RET: SLURM_SUCCESS on success SLURM_ERROR else
3154 *
3155 * Note: Cluster_rec needs to be freed with slurmdb_destroy_cluster_rec() when
3156 * called
3157 * Note: The will_runs are not threaded. Currently it relies on the
3158 * working_cluster_rec to pack the job_desc's jobinfo. See previous commit for
3159 * an example of how to thread this.
3160 */
slurmdb_get_first_avail_cluster(job_desc_msg_t * req,char * cluster_names,slurmdb_cluster_rec_t ** cluster_rec)3161 extern int slurmdb_get_first_avail_cluster(job_desc_msg_t *req,
3162 char *cluster_names, slurmdb_cluster_rec_t **cluster_rec)
3163 {
3164 local_cluster_rec_t *local_cluster = NULL;
3165 int rc = SLURM_SUCCESS;
3166 char local_hostname[64];
3167 ListIterator itr;
3168 List cluster_list = NULL;
3169 List ret_list = NULL;
3170 List tried_feds = list_create(NULL);
3171
3172 *cluster_rec = NULL;
3173 cluster_list = slurmdb_get_info_cluster(cluster_names);
3174
3175 /* return if we only have 1 or less clusters here */
3176 if (!cluster_list || !list_count(cluster_list)) {
3177 rc = SLURM_ERROR;
3178 goto end_it;
3179 } else if (list_count(cluster_list) == 1) {
3180 *cluster_rec = list_pop(cluster_list);
3181 goto end_it;
3182 }
3183
3184 if ((req->alloc_node == NULL) &&
3185 (gethostname_short(local_hostname, sizeof(local_hostname)) == 0)) {
3186 req->alloc_node = local_hostname;
3187 }
3188
3189 if (working_cluster_rec)
3190 *cluster_rec = working_cluster_rec;
3191
3192 ret_list = list_create(xfree_ptr);
3193 itr = list_iterator_create(cluster_list);
3194 while ((working_cluster_rec = list_next(itr))) {
3195 /* only try one cluster from each federation */
3196 if (working_cluster_rec->fed.id &&
3197 list_find_first(tried_feds, slurm_find_char_in_list,
3198 working_cluster_rec->fed.name))
3199 continue;
3200
3201 if ((local_cluster = _job_will_run(req))) {
3202 list_append(ret_list, local_cluster);
3203 if (working_cluster_rec->fed.id)
3204 list_append(tried_feds,
3205 working_cluster_rec->fed.name);
3206 } else {
3207 error("Problem with submit to cluster %s: %m",
3208 working_cluster_rec->name);
3209 }
3210 }
3211 list_iterator_destroy(itr);
3212 FREE_NULL_LIST(tried_feds);
3213
3214 /* restore working_cluster_rec in case it was already set */
3215 if (*cluster_rec) {
3216 working_cluster_rec = *cluster_rec;
3217 *cluster_rec = NULL;
3218 }
3219
3220 if (req->alloc_node == local_hostname)
3221 req->alloc_node = NULL;
3222
3223 if (!list_count(ret_list)) {
3224 error("Can't run on any of the specified clusters");
3225 rc = SLURM_ERROR;
3226 goto end_it;
3227 }
3228
3229 /* sort the list so the first spot is on top */
3230 local_cluster_name = slurm_get_cluster_name();
3231 list_sort(ret_list, (ListCmpF)_sort_local_cluster);
3232 xfree(local_cluster_name);
3233 local_cluster = list_peek(ret_list);
3234
3235 /* prevent cluster_rec from being freed when cluster_list is destroyed */
3236 itr = list_iterator_create(cluster_list);
3237 while ((*cluster_rec = list_next(itr))) {
3238 if (*cluster_rec == local_cluster->cluster_rec) {
3239 list_remove(itr);
3240 break;
3241 }
3242 }
3243 list_iterator_destroy(itr);
3244 end_it:
3245 FREE_NULL_LIST(ret_list);
3246 FREE_NULL_LIST(cluster_list);
3247
3248 return rc;
3249 }
3250
3251 /* Report the latest start time for any hetjob component on this cluster.
3252 * Return NULL if any component can not run here */
_het_job_will_run(List job_req_list)3253 static local_cluster_rec_t * _het_job_will_run(List job_req_list)
3254 {
3255 local_cluster_rec_t *local_cluster = NULL, *tmp_cluster;
3256 job_desc_msg_t *req;
3257 ListIterator iter;
3258
3259 iter = list_iterator_create(job_req_list);
3260 while ((req = (job_desc_msg_t *) list_next(iter))) {
3261 tmp_cluster = _job_will_run(req);
3262 if (!tmp_cluster) { /* Some het component can't run here */
3263 xfree(local_cluster);
3264 break;
3265 }
3266 if (!local_cluster) {
3267 local_cluster = tmp_cluster;
3268 tmp_cluster = NULL;
3269 } else if (local_cluster->start_time < tmp_cluster->start_time)
3270 local_cluster->start_time = tmp_cluster->start_time;
3271 xfree(tmp_cluster);
3272 }
3273 list_iterator_destroy(iter);
3274
3275 return local_cluster;
3276 }
3277
3278 /*
3279 * get the first cluster that will run a heterogeneous job
3280 * IN: req - description of resource allocation request
3281 * IN: cluster_names - comma separated string of cluster names
3282 * OUT: cluster_rec - record of selected cluster or NULL if none found or
3283 * cluster_names is NULL
3284 * RET: SLURM_SUCCESS on success SLURM_ERROR else
3285 *
3286 * Note: Cluster_rec needs to be freed with slurmdb_destroy_cluster_rec() when
3287 * called
3288 * Note: The will_runs are not threaded. Currently it relies on the
3289 * working_cluster_rec to pack the job_desc's jobinfo. See previous commit for
3290 * an example of how to thread this.
3291 */
slurmdb_get_first_het_job_cluster(List job_req_list,char * cluster_names,slurmdb_cluster_rec_t ** cluster_rec)3292 extern int slurmdb_get_first_het_job_cluster(List job_req_list,
3293 char *cluster_names, slurmdb_cluster_rec_t **cluster_rec)
3294 {
3295 job_desc_msg_t *req;
3296 local_cluster_rec_t *local_cluster = NULL;
3297 int rc = SLURM_SUCCESS;
3298 char local_hostname[64] = "";
3299 ListIterator itr;
3300 List cluster_list = NULL;
3301 List ret_list = NULL;
3302 List tried_feds = list_create(NULL);
3303
3304 *cluster_rec = NULL;
3305 cluster_list = slurmdb_get_info_cluster(cluster_names);
3306
3307 /* return if we only have 1 or less clusters here */
3308 if (!cluster_list || !list_count(cluster_list)) {
3309 rc = SLURM_ERROR;
3310 goto end_it;
3311 } else if (list_count(cluster_list) == 1) {
3312 *cluster_rec = list_pop(cluster_list);
3313 goto end_it;
3314 }
3315
3316 (void) gethostname_short(local_hostname, sizeof(local_hostname));
3317 itr = list_iterator_create(job_req_list);
3318 while ((req = (job_desc_msg_t *) list_next(itr))) {
3319 if ((req->alloc_node == NULL) && local_hostname[0])
3320 req->alloc_node = local_hostname;
3321 }
3322 list_iterator_destroy(itr);
3323
3324 if (working_cluster_rec)
3325 *cluster_rec = working_cluster_rec;
3326
3327 ret_list = list_create(xfree_ptr);
3328 itr = list_iterator_create(cluster_list);
3329 while ((working_cluster_rec = list_next(itr))) {
3330 /* only try one cluster from each federation */
3331 if (working_cluster_rec->fed.id &&
3332 list_find_first(tried_feds, slurm_find_char_in_list,
3333 working_cluster_rec->fed.name))
3334 continue;
3335 if ((local_cluster = _het_job_will_run(job_req_list))) {
3336 list_append(ret_list, local_cluster);
3337 if (working_cluster_rec->fed.id)
3338 list_append(tried_feds,
3339 working_cluster_rec->fed.name);
3340 } else {
3341 error("Problem with submit to cluster %s: %m",
3342 working_cluster_rec->name);
3343 }
3344 }
3345 list_iterator_destroy(itr);
3346
3347 /* restore working_cluster_rec in case it was already set */
3348 if (*cluster_rec) {
3349 working_cluster_rec = *cluster_rec;
3350 *cluster_rec = NULL;
3351 }
3352
3353 itr = list_iterator_create(job_req_list);
3354 while ((req = (job_desc_msg_t *) list_next(itr))) {
3355 if (req->alloc_node == local_hostname)
3356 req->alloc_node = NULL;
3357 }
3358 list_iterator_destroy(itr);
3359
3360 if (!list_count(ret_list)) {
3361 error("Can't run on any of the specified clusters");
3362 rc = SLURM_ERROR;
3363 goto end_it;
3364 }
3365
3366 /* sort the list so the first spot is on top */
3367 local_cluster_name = slurm_get_cluster_name();
3368 list_sort(ret_list, (ListCmpF)_sort_local_cluster);
3369 xfree(local_cluster_name);
3370 local_cluster = list_peek(ret_list);
3371
3372 /* prevent cluster_rec from being freed when cluster_list is destroyed */
3373 itr = list_iterator_create(cluster_list);
3374 while ((*cluster_rec = list_next(itr))) {
3375 if (*cluster_rec == local_cluster->cluster_rec) {
3376 list_remove(itr);
3377 break;
3378 }
3379 }
3380 list_iterator_destroy(itr);
3381 end_it:
3382 FREE_NULL_LIST(ret_list);
3383 FREE_NULL_LIST(cluster_list);
3384 FREE_NULL_LIST(tried_feds);
3385
3386 return rc;
3387 }
3388
slurmdb_copy_assoc_rec_limits(slurmdb_assoc_rec_t * out,slurmdb_assoc_rec_t * in)3389 extern void slurmdb_copy_assoc_rec_limits(slurmdb_assoc_rec_t *out,
3390 slurmdb_assoc_rec_t *in)
3391 {
3392 out->grp_jobs = in->grp_jobs;
3393 out->grp_jobs_accrue = in->grp_jobs_accrue;
3394 out->grp_submit_jobs = in->grp_submit_jobs;
3395 xfree(out->grp_tres);
3396 out->grp_tres = xstrdup(in->grp_tres);
3397 xfree(out->grp_tres_mins);
3398 out->grp_tres_mins = xstrdup(in->grp_tres_mins);
3399 xfree(out->grp_tres_run_mins);
3400 out->grp_tres_run_mins = xstrdup(in->grp_tres_run_mins);
3401 out->grp_wall = in->grp_wall;
3402
3403 out->max_jobs = in->max_jobs;
3404 out->max_jobs_accrue = in->max_jobs_accrue;
3405 out->min_prio_thresh = in->min_prio_thresh;
3406 out->max_submit_jobs = in->max_submit_jobs;
3407 xfree(out->max_tres_pj);
3408 out->max_tres_pj = xstrdup(in->max_tres_pj);
3409 xfree(out->max_tres_pn);
3410 out->max_tres_pn = xstrdup(in->max_tres_pn);
3411 xfree(out->max_tres_mins_pj);
3412 out->max_tres_mins_pj = xstrdup(in->max_tres_mins_pj);
3413 xfree(out->max_tres_run_mins);
3414 out->max_tres_run_mins = xstrdup(in->max_tres_run_mins);
3415 out->max_wall_pj = in->max_wall_pj;
3416
3417 out->priority = in->priority;
3418
3419 FREE_NULL_LIST(out->qos_list);
3420 out->qos_list = slurm_copy_char_list(in->qos_list);
3421 }
3422
slurmdb_copy_cluster_rec(slurmdb_cluster_rec_t * out,slurmdb_cluster_rec_t * in)3423 extern void slurmdb_copy_cluster_rec(slurmdb_cluster_rec_t *out,
3424 slurmdb_cluster_rec_t *in)
3425 {
3426 out->classification = in->classification;
3427 xfree(out->control_host);
3428 out->control_host = xstrdup(in->control_host);
3429 out->control_port = in->control_port;
3430 out->dimensions = in->dimensions;
3431 xfree(out->fed.name);
3432 out->fed.name = xstrdup(in->fed.name);
3433 out->fed.id = in->fed.id;
3434 out->fed.state = in->fed.state;
3435 out->flags = in->flags;
3436 xfree(out->name);
3437 out->name = xstrdup(in->name);
3438 xfree(out->nodes);
3439 out->nodes = xstrdup(in->nodes);
3440 out->plugin_id_select = in->plugin_id_select;
3441 out->rpc_version = in->rpc_version;
3442 xfree(out->tres_str);
3443 out->tres_str = xstrdup(in->tres_str);
3444
3445 slurmdb_destroy_assoc_rec(out->root_assoc);
3446 if (in->root_assoc) {
3447 out->root_assoc = xmalloc(sizeof(slurmdb_assoc_rec_t));
3448 slurmdb_init_assoc_rec(out->root_assoc, 0);
3449 slurmdb_copy_assoc_rec_limits( out->root_assoc, in->root_assoc);
3450 }
3451
3452 FREE_NULL_LIST(out->fed.feature_list);
3453 if (in->fed.feature_list) {
3454 out->fed.feature_list = list_create(xfree_ptr);
3455 slurm_char_list_copy(out->fed.feature_list,
3456 in->fed.feature_list);
3457 }
3458
3459 /* Not copied currently:
3460 * accounting_list
3461 * control_addr
3462 * dim_size
3463 * fed.recv
3464 * fed.send
3465 */
3466 }
3467
slurmdb_copy_federation_rec(slurmdb_federation_rec_t * out,slurmdb_federation_rec_t * in)3468 extern void slurmdb_copy_federation_rec(slurmdb_federation_rec_t *out,
3469 slurmdb_federation_rec_t *in)
3470 {
3471 xfree(out->name);
3472 out->name = xstrdup(in->name);
3473 out->flags = in->flags;
3474
3475 FREE_NULL_LIST(out->cluster_list);
3476 if (in->cluster_list) {
3477 slurmdb_cluster_rec_t *cluster_in = NULL;
3478 ListIterator itr = list_iterator_create(in->cluster_list);
3479 out->cluster_list = list_create(slurmdb_destroy_cluster_rec);
3480 while ((cluster_in = list_next(itr))) {
3481 slurmdb_cluster_rec_t *cluster_out =
3482 xmalloc(sizeof(slurmdb_cluster_rec_t));
3483 slurmdb_init_cluster_rec(cluster_out, 0);
3484 slurmdb_copy_cluster_rec(cluster_out, cluster_in);
3485 list_append(out->cluster_list, cluster_out);
3486 }
3487 list_iterator_destroy(itr);
3488 }
3489 }
3490
slurmdb_copy_qos_rec_limits(slurmdb_qos_rec_t * out,slurmdb_qos_rec_t * in)3491 extern void slurmdb_copy_qos_rec_limits(slurmdb_qos_rec_t *out,
3492 slurmdb_qos_rec_t *in)
3493 {
3494 out->flags = in->flags;
3495 out->grace_time = in->grace_time;
3496 out->grp_jobs = in->grp_jobs;
3497 out->grp_jobs_accrue = in->grp_jobs_accrue;
3498 out->grp_submit_jobs = in->grp_submit_jobs;
3499 xfree(out->grp_tres);
3500 out->grp_tres = xstrdup(in->grp_tres);
3501 xfree(out->grp_tres_mins);
3502 out->grp_tres_mins = xstrdup(in->grp_tres_mins);
3503 xfree(out->grp_tres_run_mins);
3504 out->grp_tres_run_mins = xstrdup(in->grp_tres_run_mins);
3505 out->grp_wall = in->grp_wall;
3506
3507 out->max_jobs_pa = in->max_jobs_pa;
3508 out->max_jobs_pu = in->max_jobs_pu;
3509 out->max_submit_jobs_pa = in->max_submit_jobs_pa;
3510 out->max_submit_jobs_pu = in->max_submit_jobs_pu;
3511 xfree(out->max_tres_mins_pj);
3512 out->max_tres_mins_pj = xstrdup(in->max_tres_mins_pj);
3513 xfree(out->max_tres_pa);
3514 out->max_tres_pa = xstrdup(in->max_tres_pa);
3515 xfree(out->max_tres_pj);
3516 out->max_tres_pj = xstrdup(in->max_tres_pj);
3517 xfree(out->max_tres_pn);
3518 out->max_tres_pn = xstrdup(in->max_tres_pn);
3519 xfree(out->max_tres_pu);
3520 out->max_tres_pu = xstrdup(in->max_tres_pu);
3521 xfree(out->max_tres_run_mins_pa);
3522 out->max_tres_run_mins_pa = xstrdup(in->max_tres_run_mins_pa);
3523 xfree(out->max_tres_run_mins_pu);
3524 out->max_tres_run_mins_pu = xstrdup(in->max_tres_run_mins_pu);
3525 out->max_wall_pj = in->max_wall_pj;
3526 xfree(out->min_tres_pj);
3527 out->min_tres_pj = xstrdup(in->min_tres_pj);
3528
3529 FREE_NULL_LIST(out->preempt_list);
3530 out->preempt_list = slurm_copy_char_list(in->preempt_list);
3531
3532 out->preempt_mode = in->preempt_mode;
3533 out->preempt_exempt_time = in->preempt_exempt_time;
3534
3535 out->priority = in->priority;
3536
3537 out->usage_factor = in->usage_factor;
3538 out->usage_thres = in->usage_thres;
3539
3540 }
3541
slurmdb_copy_tres_rec(slurmdb_tres_rec_t * tres)3542 extern slurmdb_tres_rec_t *slurmdb_copy_tres_rec(slurmdb_tres_rec_t *tres)
3543 {
3544 slurmdb_tres_rec_t *tres_out = NULL;
3545
3546 if (!tres)
3547 return tres_out;
3548
3549 tres_out = xmalloc_nz(sizeof(slurmdb_tres_rec_t));
3550 memcpy(tres_out, tres, sizeof(slurmdb_tres_rec_t));
3551 tres_out->name = xstrdup(tres->name);
3552 tres_out->type = xstrdup(tres->type);
3553
3554 return tres_out;
3555 }
3556
slurmdb_copy_tres_list(List tres)3557 extern List slurmdb_copy_tres_list(List tres)
3558 {
3559 slurmdb_tres_rec_t *tres_rec = NULL;
3560 ListIterator itr;
3561 List tres_out;
3562
3563 if (!tres)
3564 return NULL;
3565
3566 tres_out = list_create(slurmdb_destroy_tres_rec);
3567
3568 itr = list_iterator_create(tres);
3569 while ((tres_rec = list_next(itr)))
3570 list_append(tres_out, slurmdb_copy_tres_rec(tres_rec));
3571 list_iterator_destroy(itr);
3572
3573 return tres_out;
3574 }
3575
slurmdb_diff_tres_list(List tres_list_old,List tres_list_new)3576 extern List slurmdb_diff_tres_list(List tres_list_old, List tres_list_new)
3577 {
3578 slurmdb_tres_rec_t *tres_rec = NULL, *tres_rec_old;
3579 ListIterator itr;
3580 List tres_out;
3581
3582 if (!tres_list_new || !list_count(tres_list_new))
3583 return NULL;
3584
3585 tres_out = slurmdb_copy_tres_list(tres_list_new);
3586
3587 itr = list_iterator_create(tres_out);
3588 while ((tres_rec = list_next(itr))) {
3589 if (!(tres_rec_old = list_find_first(tres_list_old,
3590 slurmdb_find_tres_in_list,
3591 &tres_rec->id)))
3592 continue;
3593 if (tres_rec_old->count == tres_rec->count)
3594 list_delete_item(itr);
3595 }
3596 list_iterator_destroy(itr);
3597
3598 return tres_out;
3599 }
3600
slurmdb_tres_string_combine_lists(List tres_list_old,List tres_list_new)3601 extern char *slurmdb_tres_string_combine_lists(
3602 List tres_list_old, List tres_list_new)
3603 {
3604 slurmdb_tres_rec_t *tres_rec = NULL, *tres_rec_old;
3605 ListIterator itr;
3606 char *tres_str = NULL;
3607
3608 if (!tres_list_new || !list_count(tres_list_new))
3609 return NULL;
3610
3611 itr = list_iterator_create(tres_list_new);
3612 while ((tres_rec = list_next(itr))) {
3613 if (!(tres_rec_old = list_find_first(tres_list_old,
3614 slurmdb_find_tres_in_list,
3615 &tres_rec->id))
3616 || (tres_rec_old->count == INFINITE64))
3617 continue;
3618 if (tres_str)
3619 xstrcat(tres_str, ",");
3620 xstrfmtcat(tres_str, "%u=%"PRIu64,
3621 tres_rec->id, tres_rec->count);
3622 }
3623 list_iterator_destroy(itr);
3624
3625 return tres_str;
3626 }
3627
3628 /* caller must xfree this char * returned */
slurmdb_make_tres_string(List tres,uint32_t flags)3629 extern char *slurmdb_make_tres_string(List tres, uint32_t flags)
3630 {
3631 char *tres_str = NULL;
3632 ListIterator itr;
3633 slurmdb_tres_rec_t *tres_rec;
3634
3635 if (!tres)
3636 return tres_str;
3637
3638 itr = list_iterator_create(tres);
3639 while ((tres_rec = list_next(itr))) {
3640 if ((flags & TRES_STR_FLAG_REMOVE) &&
3641 (tres_rec->count == INFINITE64))
3642 continue;
3643
3644 if ((flags & TRES_STR_FLAG_SIMPLE) || !tres_rec->type)
3645 xstrfmtcat(tres_str, "%s%u=%"PRIu64,
3646 (tres_str ||
3647 (flags & TRES_STR_FLAG_COMMA1)) ? "," : "",
3648 tres_rec->id, tres_rec->count);
3649
3650 else
3651 xstrfmtcat(tres_str, "%s%s%s%s=%"PRIu64,
3652 (tres_str ||
3653 (flags & TRES_STR_FLAG_COMMA1)) ? "," : "",
3654 tres_rec->type,
3655 tres_rec->name ? "/" : "",
3656 tres_rec->name ? tres_rec->name : "",
3657 tres_rec->count);
3658 }
3659 list_iterator_destroy(itr);
3660
3661 return tres_str;
3662 }
3663
slurmdb_make_tres_string_from_arrays(char ** tres_names,uint64_t * tres_cnts,uint32_t tres_cnt,uint32_t flags)3664 extern char *slurmdb_make_tres_string_from_arrays(char **tres_names,
3665 uint64_t *tres_cnts,
3666 uint32_t tres_cnt,
3667 uint32_t flags)
3668 {
3669 char *tres_str = NULL;
3670 int i;
3671
3672 if (!tres_names || !tres_cnts)
3673 return tres_str;
3674
3675 for (i=0; i<tres_cnt; i++) {
3676 if ((tres_cnts[i] == INFINITE64) &&
3677 (flags & TRES_STR_FLAG_REMOVE))
3678 continue;
3679 xstrfmtcat(tres_str, "%s%s=%"PRIu64,
3680 tres_str ? "," : "", tres_names[i], tres_cnts[i]);
3681 }
3682
3683 return tres_str;
3684 }
3685
slurmdb_make_tres_string_from_simple(char * tres_in,List full_tres_list,int spec_unit,uint32_t convert_flags,uint32_t tres_str_flags,char * nodes)3686 extern char *slurmdb_make_tres_string_from_simple(
3687 char *tres_in, List full_tres_list, int spec_unit,
3688 uint32_t convert_flags, uint32_t tres_str_flags, char *nodes)
3689 {
3690 char *tres_str = NULL;
3691 char *tmp_str = tres_in;
3692 int id;
3693 uint64_t count;
3694 slurmdb_tres_rec_t *tres_rec;
3695 char *node_name = NULL;
3696 List char_list = NULL;
3697
3698 if (!full_tres_list || !tmp_str || !tmp_str[0]
3699 || tmp_str[0] < '0' || tmp_str[0] > '9')
3700 return tres_str;
3701
3702 while (tmp_str) {
3703 id = atoi(tmp_str);
3704 if (id <= 0) {
3705 error("slurmdb_make_tres_string_from_simple: no id "
3706 "found at %s instead", tmp_str);
3707 goto get_next;
3708 }
3709
3710 if (!(tres_rec = list_find_first(
3711 full_tres_list, slurmdb_find_tres_in_list,
3712 &id))) {
3713 debug("No tres known by id %d", id);
3714 goto get_next;
3715 }
3716
3717 if (!(tmp_str = strchr(tmp_str, '='))) {
3718 error("slurmdb_make_tres_string_from_simple: "
3719 "no value found");
3720 break;
3721 }
3722 count = slurm_atoull(++tmp_str);
3723
3724 if (count == NO_VAL64)
3725 goto get_next;
3726
3727 if (tres_str)
3728 xstrcat(tres_str, ",");
3729 if (!tres_rec->type)
3730 xstrfmtcat(tres_str, "%u=", tres_rec->id);
3731
3732 else
3733 xstrfmtcat(tres_str, "%s%s%s=",
3734 tres_rec->type,
3735 tres_rec->name ? "/" : "",
3736 tres_rec->name ? tres_rec->name : "");
3737 if (count != INFINITE64) {
3738 if (nodes) {
3739 node_name = find_hostname(count, nodes);
3740 xstrfmtcat(tres_str, "%s", node_name);
3741 xfree(node_name);
3742 } else if (tres_str_flags & TRES_STR_FLAG_BYTES) {
3743 /* This mean usage */
3744 char outbuf[FORMAT_STRING_SIZE];
3745 if (tres_rec->id == TRES_CPU) {
3746 count /= CPU_TIME_ADJ;
3747 secs2time_str((time_t)count, outbuf,
3748 FORMAT_STRING_SIZE);
3749 } else
3750 convert_num_unit((double)count, outbuf,
3751 sizeof(outbuf),
3752 UNIT_NONE,
3753 spec_unit,
3754 convert_flags);
3755 xstrfmtcat(tres_str, "%s", outbuf);
3756 } else if ((tres_rec->id == TRES_MEM) ||
3757 !xstrcasecmp(tres_rec->type, "bb")) {
3758 char outbuf[FORMAT_STRING_SIZE];
3759 convert_num_unit((double)count, outbuf,
3760 sizeof(outbuf), UNIT_MEGA,
3761 spec_unit, convert_flags);
3762 xstrfmtcat(tres_str, "%s", outbuf);
3763 } else {
3764 xstrfmtcat(tres_str, "%"PRIu64, count);
3765 }
3766 } else
3767 xstrfmtcat(tres_str, "NONE");
3768
3769 if (!(tres_str_flags & TRES_STR_FLAG_SORT_ID)) {
3770 if (!char_list)
3771 char_list = list_create(xfree_ptr);
3772 list_append(char_list, tres_str);
3773 tres_str = NULL;
3774 }
3775 get_next:
3776 if (!(tmp_str = strchr(tmp_str, ',')))
3777 break;
3778 tmp_str++;
3779 }
3780
3781 if (char_list) {
3782 tres_str = slurm_char_list_to_xstr(char_list);
3783 FREE_NULL_LIST(char_list);
3784 }
3785
3786 return tres_str;
3787 }
3788
slurmdb_format_tres_str(char * tres_in,List full_tres_list,bool simple)3789 extern char *slurmdb_format_tres_str(
3790 char *tres_in, List full_tres_list, bool simple)
3791 {
3792 char *tres_str = NULL;
3793 char *val_unit = NULL;
3794 char *tmp_str = tres_in;
3795 uint64_t count;
3796 slurmdb_tres_rec_t *tres_rec;
3797
3798 if (!full_tres_list || !tmp_str || !tmp_str[0])
3799 return tres_str;
3800
3801 if (tmp_str[0] == ',')
3802 tmp_str++;
3803
3804 while (tmp_str) {
3805 if (tmp_str[0] >= '0' && tmp_str[0] <= '9') {
3806 int id = atoi(tmp_str);
3807 if (id <= 0) {
3808 error("slurmdb_format_tres_str: "
3809 "no id found at %s instead", tmp_str);
3810 goto get_next;
3811 }
3812 if (!(tres_rec = list_find_first(
3813 full_tres_list, slurmdb_find_tres_in_list,
3814 &id))) {
3815 debug("slurmdb_format_tres_str: "
3816 "No tres known by id %d", id);
3817 goto get_next;
3818 }
3819 } else {
3820 int end = 0;
3821 char *tres_name;
3822
3823 while (tmp_str[end]) {
3824 if (tmp_str[end] == '=')
3825 break;
3826 end++;
3827 }
3828 if (!tmp_str[end]) {
3829 error("slurmdb_format_tres_str: "
3830 "no id found at %s instead", tmp_str);
3831 goto get_next;
3832 }
3833 tres_name = xstrndup(tmp_str, end);
3834 if (!(tres_rec = list_find_first(
3835 full_tres_list,
3836 slurmdb_find_tres_in_list_by_type,
3837 tres_name))) {
3838 debug("slurmdb_format_tres_str: "
3839 "No tres known by type %s", tres_name);
3840 xfree(tres_name);
3841 goto get_next;
3842 }
3843 xfree(tres_name);
3844 }
3845
3846 if (!(tmp_str = strchr(tmp_str, '='))) {
3847 error("slurmdb_format_tres_str: "
3848 "no value found");
3849 break;
3850 }
3851 count = strtoull(++tmp_str, &val_unit, 10);
3852 if (val_unit && *val_unit != ',' && *val_unit != '\0' &&
3853 tres_rec->type) {
3854 int base_unit =
3855 slurmdb_get_tres_base_unit(tres_rec->type);
3856 int convert_val =
3857 get_convert_unit_val(base_unit, *val_unit);
3858 if (convert_val > 0)
3859 count *= convert_val;
3860 }
3861
3862 if (tres_str)
3863 xstrcat(tres_str, ",");
3864 if (simple || !tres_rec->type)
3865 xstrfmtcat(tres_str, "%u=%"PRIu64"",
3866 tres_rec->id, count);
3867
3868 else
3869 xstrfmtcat(tres_str, "%s%s%s=%"PRIu64"",
3870 tres_rec->type,
3871 tres_rec->name ? "/" : "",
3872 tres_rec->name ? tres_rec->name : "",
3873 count);
3874 get_next:
3875 if (!(tmp_str = strchr(tmp_str, ',')))
3876 break;
3877 tmp_str++;
3878 }
3879
3880 return tres_str;
3881 }
3882
3883 /*
3884 * Comparator used for sorting tres by id
3885 *
3886 * returns: -1 tres_a < tres_b 0: tres_a == tres_b 1: tres_a > tres_b
3887 *
3888 */
slurmdb_sort_tres_by_id_asc(void * v1,void * v2)3889 extern int slurmdb_sort_tres_by_id_asc(void *v1, void *v2)
3890 {
3891 slurmdb_tres_rec_t *tres_a = *(slurmdb_tres_rec_t **)v1;
3892 slurmdb_tres_rec_t *tres_b = *(slurmdb_tres_rec_t **)v2;
3893
3894 if ((tres_a->id > TRES_STATIC_CNT) &&
3895 (tres_b->id > TRES_STATIC_CNT)) {
3896 int diff = xstrcmp(tres_a->type, tres_b->type);
3897
3898 if (diff < 0)
3899 return -1;
3900 else if (diff > 0)
3901 return 1;
3902
3903 diff = xstrcmp(tres_a->name, tres_b->name);
3904
3905 if (diff < 0)
3906 return -1;
3907 else if (diff > 0)
3908 return 1;
3909 }
3910
3911 if (tres_a->id < tres_b->id)
3912 return -1;
3913 else if (tres_a->id > tres_b->id)
3914 return 1;
3915
3916 return 0;
3917 }
3918
3919 /* This only works on a simple id=count list, not on a formatted list */
slurmdb_tres_list_from_string(List * tres_list,char * tres,uint32_t flags)3920 extern void slurmdb_tres_list_from_string(
3921 List *tres_list, char *tres, uint32_t flags)
3922 {
3923 char *tmp_str = tres;
3924 int id;
3925 uint64_t count;
3926 slurmdb_tres_rec_t *tres_rec;
3927 int remove_found = 0;
3928 xassert(tres_list);
3929
3930 if (!tres || !tres[0])
3931 return;
3932
3933 if (tmp_str[0] == ',')
3934 tmp_str++;
3935
3936 while (tmp_str) {
3937 id = atoi(tmp_str);
3938 /* 0 isn't a valid tres id */
3939 if (id <= 0) {
3940 error("slurmdb_tres_list_from_string: no id "
3941 "found at %s instead", tmp_str);
3942 break;
3943 }
3944 if (!(tmp_str = strchr(tmp_str, '='))) {
3945 error("slurmdb_tres_list_from_string: "
3946 "no value found %s", tres);
3947 break;
3948 }
3949 count = slurm_atoull(++tmp_str);
3950
3951 if (!*tres_list)
3952 *tres_list = list_create(slurmdb_destroy_tres_rec);
3953
3954 if (!(tres_rec = list_find_first(
3955 *tres_list, slurmdb_find_tres_in_list, &id))) {
3956 tres_rec = xmalloc(sizeof(slurmdb_tres_rec_t));
3957 tres_rec->id = id;
3958 tres_rec->count = count;
3959 list_append(*tres_list, tres_rec);
3960 if (count == INFINITE64)
3961 remove_found++;
3962 } else if (flags & TRES_STR_FLAG_REPLACE) {
3963 debug2("TRES %u was already here with count %"PRIu64", "
3964 "replacing with %"PRIu64,
3965 tres_rec->id, tres_rec->count, count);
3966 tres_rec->count = count;
3967 } else if (flags & TRES_STR_FLAG_SUM) {
3968 if (count != INFINITE64) {
3969 if (tres_rec->count == INFINITE64)
3970 tres_rec->count = count;
3971 else
3972 tres_rec->count += count;
3973 }
3974 } else if (flags & TRES_STR_FLAG_MAX) {
3975 if (count != INFINITE64) {
3976 if (tres_rec->count == INFINITE64)
3977 tres_rec->count = count;
3978 else
3979 tres_rec->count =
3980 MAX(tres_rec->count, count);
3981 }
3982 } else if (flags & TRES_STR_FLAG_MIN) {
3983 if (count != INFINITE64) {
3984 if (tres_rec->count == INFINITE64)
3985 tres_rec->count = count;
3986 else
3987 tres_rec->count =
3988 MIN(tres_rec->count, count);
3989 }
3990 }
3991
3992 if (!(tmp_str = strchr(tmp_str, ',')))
3993 break;
3994 tmp_str++;
3995 }
3996
3997 if (remove_found && (flags & TRES_STR_FLAG_REMOVE)) {
3998 /* here we will remove the tres we don't want in the
3999 string */
4000 uint64_t inf64 = INFINITE64;
4001 int removed;
4002
4003 if ((removed = list_delete_all(
4004 *tres_list,
4005 slurmdb_find_tres_in_list_by_count,
4006 &inf64)) != remove_found)
4007 debug("slurmdb_tres_list_from_string: "
4008 "was expecting to remove %d, but removed %d",
4009 remove_found, removed);
4010 }
4011
4012 if (flags & TRES_STR_FLAG_SORT_ID)
4013 list_sort(*tres_list, (ListCmpF)slurmdb_sort_tres_by_id_asc);
4014
4015 return;
4016 }
4017
slurmdb_combine_tres_strings(char ** tres_str_old,char * tres_str_new,uint32_t flags)4018 extern char *slurmdb_combine_tres_strings(
4019 char **tres_str_old, char *tres_str_new, uint32_t flags)
4020 {
4021 List tres_list = NULL;
4022
4023 xassert(tres_str_old);
4024
4025 /* If a new string is being added concat it onto the old
4026 * string, then send it to slurmdb_tres_list_from_string which
4027 * will make it a unique list if flags doesn't contain
4028 * TRES_STR_FLAG_ONLY_CONCAT.
4029 */
4030 if (tres_str_new && tres_str_new[0])
4031 xstrfmtcat(*tres_str_old, "%s%s%s",
4032 (flags & (TRES_STR_FLAG_COMMA1 |
4033 TRES_STR_FLAG_ONLY_CONCAT)) ? "," : "",
4034 (*tres_str_old && tres_str_new[0] != ',') ? "," : "",
4035 tres_str_new);
4036
4037 if (flags & TRES_STR_FLAG_ONLY_CONCAT)
4038 goto endit;
4039
4040 slurmdb_tres_list_from_string(&tres_list, *tres_str_old, flags);
4041 xfree(*tres_str_old);
4042
4043 /* Always make it a simple string */
4044 flags |= TRES_STR_FLAG_SIMPLE;
4045
4046 /* Make a new string from the combined */
4047 *tres_str_old = slurmdb_make_tres_string(tres_list, flags);
4048
4049 FREE_NULL_LIST(tres_list);
4050 endit:
4051 /* Send back a blank string instead of NULL. */
4052 if (!*tres_str_old && (flags & TRES_STR_FLAG_NO_NULL))
4053 *tres_str_old = xstrdup("");
4054
4055 return *tres_str_old;
4056 }
4057
slurmdb_find_tres_in_string(char * tres_str_in,int id)4058 extern slurmdb_tres_rec_t *slurmdb_find_tres_in_string(
4059 char *tres_str_in, int id)
4060 {
4061 slurmdb_tres_rec_t *tres_rec = NULL;
4062 char *tmp_str = tres_str_in;
4063
4064 if (!tmp_str || !tmp_str[0])
4065 return tres_rec;
4066
4067 while (tmp_str) {
4068 if (id == atoi(tmp_str)) {
4069 if (!(tmp_str = strchr(tmp_str, '='))) {
4070 error("%s: no value found", __func__);
4071 break;
4072 }
4073 tres_rec = xmalloc(sizeof(slurmdb_tres_rec_t));
4074 tres_rec->id = id;
4075 tres_rec->count = slurm_atoull(++tmp_str);
4076 return tres_rec;
4077 }
4078
4079 if (!(tmp_str = strchr(tmp_str, ',')))
4080 break;
4081 tmp_str++;
4082 }
4083
4084 return tres_rec;
4085 }
4086
slurmdb_find_tres_count_in_string(char * tres_str_in,int id)4087 extern uint64_t slurmdb_find_tres_count_in_string(char *tres_str_in, int id)
4088 {
4089 char *tmp_str = tres_str_in;
4090
4091 if (!tmp_str || !tmp_str[0])
4092 return INFINITE64;
4093
4094 while (tmp_str) {
4095 if (id == atoi(tmp_str)) {
4096 if (!(tmp_str = strchr(tmp_str, '='))) {
4097 error("slurmdb_find_tres_count_in_string: "
4098 "no value found");
4099 break;
4100 }
4101 return slurm_atoull(++tmp_str);
4102 }
4103
4104 if (!(tmp_str = strchr(tmp_str, ',')))
4105 break;
4106 tmp_str++;
4107 }
4108
4109 return INFINITE64;
4110 }
4111
slurmdb_find_qos_in_list_by_name(void * x,void * key)4112 extern int slurmdb_find_qos_in_list_by_name(void *x, void *key)
4113 {
4114 slurmdb_qos_rec_t *qos_rec = (slurmdb_qos_rec_t *)x;
4115 char *name = (char *)key;
4116
4117 if (!xstrcmp(qos_rec->name, name))
4118 return 1;
4119
4120 return 0;
4121 }
4122
slurmdb_find_qos_in_list(void * x,void * key)4123 extern int slurmdb_find_qos_in_list(void *x, void *key)
4124 {
4125 slurmdb_qos_rec_t *qos_rec = (slurmdb_qos_rec_t *)x;
4126 uint32_t qos_id = *(uint32_t *)key;
4127
4128 if (qos_rec->id == qos_id)
4129 return 1;
4130
4131 return 0;
4132 }
4133
slurmdb_find_selected_step_in_list(void * x,void * key)4134 extern int slurmdb_find_selected_step_in_list(void *x, void *key)
4135 {
4136 slurmdb_selected_step_t *selected_step = (slurmdb_selected_step_t *)x;
4137 slurmdb_selected_step_t *query_step = (slurmdb_selected_step_t *)key;
4138
4139 if ((query_step->jobid == selected_step->jobid) &&
4140 (query_step->stepid == selected_step->stepid) &&
4141 (query_step->array_task_id == selected_step->array_task_id) &&
4142 (query_step->het_job_offset == selected_step->het_job_offset))
4143 return 1;
4144
4145 return 0;
4146 }
4147
slurmdb_find_assoc_in_list(void * x,void * key)4148 extern int slurmdb_find_assoc_in_list(void *x, void *key)
4149 {
4150 slurmdb_assoc_rec_t *assoc_rec = (slurmdb_assoc_rec_t *)x;
4151 uint32_t assoc_id = *(uint32_t *)key;
4152
4153 if (assoc_rec->id == assoc_id)
4154 return 1;
4155
4156 return 0;
4157 }
4158
slurmdb_find_update_object_in_list(void * x,void * key)4159 extern int slurmdb_find_update_object_in_list(void *x, void *key)
4160 {
4161 slurmdb_update_object_t *update_object = (slurmdb_update_object_t *)x;
4162 slurmdb_update_type_t type = *(slurmdb_update_type_t *)key;
4163
4164 if (update_object->type == type)
4165 return 1;
4166
4167 return 0;
4168 }
4169
4170
slurmdb_find_tres_in_list(void * x,void * key)4171 extern int slurmdb_find_tres_in_list(void *x, void *key)
4172 {
4173 slurmdb_tres_rec_t *tres_rec = (slurmdb_tres_rec_t *)x;
4174 uint32_t tres_id = *(uint32_t *)key;
4175
4176 if (tres_rec->id == tres_id)
4177 return 1;
4178
4179 return 0;
4180 }
4181
slurmdb_find_tres_in_list_by_count(void * x,void * key)4182 extern int slurmdb_find_tres_in_list_by_count(void *x, void *key)
4183 {
4184 slurmdb_tres_rec_t *tres_rec = (slurmdb_tres_rec_t *)x;
4185 uint64_t count = *(uint64_t *)key;
4186
4187 if (tres_rec->count == count)
4188 return 1;
4189
4190 return 0;
4191 }
4192
slurmdb_find_tres_in_list_by_type(void * x,void * key)4193 extern int slurmdb_find_tres_in_list_by_type(void *x, void *key)
4194 {
4195 slurmdb_tres_rec_t *tres_rec = (slurmdb_tres_rec_t *)x;
4196 char *type = (char *)key;
4197 int end = 0;
4198 bool found = false;
4199
4200 while (type[end]) {
4201 if (type[end] == '/') {
4202 found = true;
4203 break;
4204 }
4205 end++;
4206 }
4207
4208 if (!xstrncasecmp(tres_rec->type, type, end)) {
4209 if ((!found && !tres_rec->name) ||
4210 (found && !xstrcasecmp(tres_rec->name, type + end + 1))) {
4211 return 1;
4212 }
4213 }
4214
4215 return 0;
4216 }
4217
slurmdb_find_cluster_in_list(void * x,void * key)4218 extern int slurmdb_find_cluster_in_list(void *x, void *key)
4219 {
4220 slurmdb_cluster_rec_t *object = (slurmdb_cluster_rec_t *)x;
4221 char *name = (char *)key;
4222
4223 if (!xstrcmp(object->name, name))
4224 return 1;
4225
4226 return 0;
4227 }
4228
slurmdb_find_cluster_accting_tres_in_list(void * x,void * key)4229 extern int slurmdb_find_cluster_accting_tres_in_list(void *x, void *key)
4230 {
4231 slurmdb_cluster_accounting_rec_t *object =
4232 (slurmdb_cluster_accounting_rec_t *)x;
4233 uint32_t tres_id = *(uint32_t *)key;
4234
4235 if (object->tres_rec.id == tres_id)
4236 return 1;
4237
4238 return 0;
4239 }
4240
slurmdb_add_cluster_accounting_to_tres_list(slurmdb_cluster_accounting_rec_t * accting,List * tres)4241 extern int slurmdb_add_cluster_accounting_to_tres_list(
4242 slurmdb_cluster_accounting_rec_t *accting,
4243 List *tres)
4244 {
4245 slurmdb_tres_rec_t *tres_rec = NULL;
4246
4247 if (!*tres)
4248 *tres = list_create(slurmdb_destroy_tres_rec);
4249 else
4250 tres_rec = list_find_first(*tres,
4251 slurmdb_find_tres_in_list,
4252 &accting->tres_rec.id);
4253
4254 if (!tres_rec) {
4255 tres_rec = slurmdb_copy_tres_rec(&accting->tres_rec);
4256 if (!tres_rec) {
4257 error("slurmdb_copy_tres_rec returned NULL");
4258 return SLURM_ERROR;
4259 }
4260 list_push(*tres, tres_rec);
4261 }
4262
4263 tres_rec->alloc_secs += accting->alloc_secs
4264 + accting->down_secs + accting->idle_secs
4265 + accting->resv_secs + accting->pdown_secs;
4266 tres_rec->count += accting->tres_rec.count;
4267 tres_rec->rec_count++;
4268
4269 return SLURM_SUCCESS;
4270 }
4271
slurmdb_add_accounting_to_tres_list(slurmdb_accounting_rec_t * accting,List * tres)4272 extern int slurmdb_add_accounting_to_tres_list(
4273 slurmdb_accounting_rec_t *accting,
4274 List *tres)
4275 {
4276 slurmdb_tres_rec_t *tres_rec = NULL;
4277
4278 if (!*tres)
4279 *tres = list_create(slurmdb_destroy_tres_rec);
4280 else
4281 tres_rec = list_find_first(*tres,
4282 slurmdb_find_tres_in_list,
4283 &accting->tres_rec.id);
4284
4285 if (!tres_rec) {
4286 tres_rec = slurmdb_copy_tres_rec(&accting->tres_rec);
4287 if (!tres_rec) {
4288 error("slurmdb_copy_tres_rec returned NULL");
4289 return SLURM_ERROR;
4290 }
4291 list_push(*tres, tres_rec);
4292 }
4293
4294 tres_rec->alloc_secs += accting->alloc_secs;
4295
4296 return SLURM_SUCCESS;
4297 }
4298
slurmdb_add_time_from_count_to_tres_list(slurmdb_tres_rec_t * tres_in,List * tres,time_t elapsed)4299 extern int slurmdb_add_time_from_count_to_tres_list(
4300 slurmdb_tres_rec_t *tres_in, List *tres, time_t elapsed)
4301 {
4302 slurmdb_tres_rec_t *tres_rec = NULL;
4303
4304 if (!elapsed)
4305 return SLURM_SUCCESS;
4306
4307 if (!*tres)
4308 *tres = list_create(slurmdb_destroy_tres_rec);
4309 else
4310 tres_rec = list_find_first(*tres,
4311 slurmdb_find_tres_in_list,
4312 &tres_in->id);
4313
4314 if (!tres_rec) {
4315 tres_rec = slurmdb_copy_tres_rec(tres_in);
4316 if (!tres_rec) {
4317 error("slurmdb_copy_tres_rec returned NULL");
4318 return SLURM_ERROR;
4319 }
4320 list_push(*tres, tres_rec);
4321 }
4322
4323 tres_rec->alloc_secs +=
4324 ((uint64_t)tres_in->count * (uint64_t)elapsed);
4325
4326 return SLURM_SUCCESS;
4327 }
4328
slurmdb_sum_accounting_list(slurmdb_cluster_accounting_rec_t * accting,List * total_tres_acct)4329 extern int slurmdb_sum_accounting_list(
4330 slurmdb_cluster_accounting_rec_t *accting,
4331 List *total_tres_acct)
4332 {
4333 slurmdb_cluster_accounting_rec_t *total_acct = NULL;
4334
4335 if (!*total_tres_acct)
4336 *total_tres_acct = list_create(
4337 slurmdb_destroy_cluster_accounting_rec);
4338 else
4339 total_acct = list_find_first(
4340 *total_tres_acct,
4341 slurmdb_find_cluster_accting_tres_in_list,
4342 &accting->tres_rec.id);
4343
4344 if (!total_acct) {
4345 total_acct = xmalloc(sizeof(slurmdb_cluster_accounting_rec_t));
4346 total_acct->tres_rec.id = accting->tres_rec.id;
4347 list_push(*total_tres_acct, total_acct);
4348 }
4349
4350 total_acct->alloc_secs += accting->alloc_secs;
4351 total_acct->down_secs += accting->down_secs;
4352 total_acct->idle_secs += accting->idle_secs;
4353 total_acct->resv_secs += accting->resv_secs;
4354 total_acct->over_secs += accting->over_secs;
4355 total_acct->pdown_secs += accting->pdown_secs;
4356 total_acct->tres_rec.count += accting->tres_rec.count;
4357 total_acct->tres_rec.rec_count++;
4358
4359 return SLURM_SUCCESS;
4360 }
4361
slurmdb_transfer_acct_list_2_tres(List accounting_list,List * tres)4362 extern void slurmdb_transfer_acct_list_2_tres(
4363 List accounting_list, List *tres)
4364 {
4365 ListIterator itr;
4366 slurmdb_accounting_rec_t *accting = NULL;
4367
4368 xassert(accounting_list);
4369 xassert(tres);
4370
4371 /* get the amount of time this assoc used
4372 during the time we are looking at */
4373 itr = list_iterator_create(accounting_list);
4374 while ((accting = list_next(itr)))
4375 slurmdb_add_accounting_to_tres_list(accting, tres);
4376 list_iterator_destroy(itr);
4377 }
4378
slurmdb_transfer_tres_time(List * tres_list_out,char * tres_str,int elapsed)4379 extern void slurmdb_transfer_tres_time(
4380 List *tres_list_out, char *tres_str, int elapsed)
4381 {
4382 ListIterator itr;
4383 slurmdb_tres_rec_t *tres_rec = NULL;
4384 List job_tres_list = NULL;
4385
4386 xassert(tres_list_out);
4387
4388 slurmdb_tres_list_from_string(&job_tres_list, tres_str,
4389 TRES_STR_FLAG_NONE);
4390
4391 if (!job_tres_list)
4392 return;
4393
4394 /* get the amount of time this assoc used
4395 during the time we are looking at */
4396 itr = list_iterator_create(job_tres_list);
4397 while ((tres_rec = list_next(itr)))
4398 slurmdb_add_time_from_count_to_tres_list(
4399 tres_rec, tres_list_out, elapsed);
4400 list_iterator_destroy(itr);
4401 FREE_NULL_LIST(job_tres_list);
4402 }
4403
slurmdb_get_tres_base_unit(char * tres_type)4404 extern int slurmdb_get_tres_base_unit(char *tres_type)
4405 {
4406 int ret_unit = UNIT_NONE;
4407 if ((!xstrcasecmp(tres_type, "mem")) ||
4408 (!xstrcasecmp(tres_type, "bb"))) {
4409 ret_unit = UNIT_MEGA;
4410 }
4411
4412 return ret_unit;
4413 }
4414
slurmdb_ave_tres_usage(char * tres_string,int tasks)4415 extern char *slurmdb_ave_tres_usage(char *tres_string, int tasks)
4416 {
4417 List tres_list = NULL;
4418 ListIterator itr;
4419 slurmdb_tres_rec_t *tres_rec = NULL;
4420 uint32_t flags = TRES_STR_FLAG_SIMPLE + TRES_STR_FLAG_REPLACE;
4421 char *ret_tres_str = NULL;
4422
4423 if (!tres_string || (tres_string[0] == '\0'))
4424 return NULL;
4425
4426 slurmdb_tres_list_from_string(&tres_list, tres_string, flags);
4427 if (!tres_list) {
4428 error("%s: couldn't make tres_list from \'%s\'", __func__,
4429 tres_string);
4430 return ret_tres_str;
4431 }
4432
4433 itr = list_iterator_create(tres_list);
4434 while ((tres_rec = list_next(itr)))
4435 tres_rec->count /= (uint64_t)tasks;
4436 list_iterator_destroy(itr);
4437
4438 ret_tres_str = slurmdb_make_tres_string(tres_list, flags);
4439 FREE_NULL_LIST(tres_list);
4440
4441 return ret_tres_str;
4442 }
4443
slurmdb_destroy_rpc_obj(void * object)4444 extern void slurmdb_destroy_rpc_obj(void *object)
4445 {
4446 slurmdb_rpc_obj_t *rpc_obj = (slurmdb_rpc_obj_t *)object;
4447
4448 if (!rpc_obj)
4449 return;
4450
4451 xfree(rpc_obj);
4452 }
4453
slurmdb_destroy_rollup_stats(void * object)4454 extern void slurmdb_destroy_rollup_stats(void *object)
4455 {
4456 slurmdb_rollup_stats_t *rollup_stats = (slurmdb_rollup_stats_t *)object;
4457
4458 if (!rollup_stats)
4459 return;
4460
4461 xfree(rollup_stats->cluster_name);
4462 xfree(rollup_stats);
4463 }
4464
slurmdb_free_stats_rec_members(void * object)4465 extern void slurmdb_free_stats_rec_members(void *object)
4466 {
4467 slurmdb_stats_rec_t *rpc_stats = (slurmdb_stats_rec_t *)object;
4468
4469 if (!rpc_stats)
4470 return;
4471
4472 slurmdb_destroy_rollup_stats(rpc_stats->dbd_rollup_stats);
4473
4474 FREE_NULL_LIST(rpc_stats->rollup_stats);
4475 FREE_NULL_LIST(rpc_stats->rpc_list);
4476 FREE_NULL_LIST(rpc_stats->user_list);
4477 }
4478
slurmdb_destroy_stats_rec(void * object)4479 extern void slurmdb_destroy_stats_rec(void *object)
4480 {
4481 if (!object)
4482 return;
4483
4484 slurmdb_free_stats_rec_members(object);
4485 xfree(object);
4486 }
4487
slurmdb_free_slurmdb_stats_members(slurmdb_stats_t * stats)4488 extern void slurmdb_free_slurmdb_stats_members(slurmdb_stats_t *stats)
4489 {
4490 if (stats) {
4491 xfree(stats->tres_usage_in_ave);
4492 xfree(stats->tres_usage_in_max);
4493 xfree(stats->tres_usage_in_max_nodeid);
4494 xfree(stats->tres_usage_in_max_taskid);
4495 xfree(stats->tres_usage_in_min);
4496 xfree(stats->tres_usage_in_min_nodeid);
4497 xfree(stats->tres_usage_in_min_taskid);
4498 xfree(stats->tres_usage_in_tot);
4499 xfree(stats->tres_usage_out_ave);
4500 xfree(stats->tres_usage_out_max);
4501 xfree(stats->tres_usage_out_max_nodeid);
4502 xfree(stats->tres_usage_out_max_taskid);
4503 xfree(stats->tres_usage_out_min);
4504 xfree(stats->tres_usage_out_min_nodeid);
4505 xfree(stats->tres_usage_out_min_taskid);
4506 xfree(stats->tres_usage_out_tot);
4507 }
4508 }
4509
slurmdb_destroy_slurmdb_stats(slurmdb_stats_t * stats)4510 extern void slurmdb_destroy_slurmdb_stats(slurmdb_stats_t *stats)
4511 {
4512 slurmdb_free_slurmdb_stats_members(stats);
4513 xfree(stats);
4514 }
4515
4516 /*
4517 * Comparator for sorting jobs by submit time. 0 (unknown) submit time
4518 * is mapped to INFINITE
4519 */
slurmdb_job_sort_by_submit_time(void * v1,void * v2)4520 extern int slurmdb_job_sort_by_submit_time(void *v1, void *v2)
4521 {
4522 time_t time1 = (*(slurmdb_job_rec_t **)v1)->submit;
4523 time_t time2 = (*(slurmdb_job_rec_t **)v2)->submit;
4524
4525 /*
4526 * Sanity check submits should never be 0, but if somehow that does
4527 * happen treat it as the highest number.
4528 */
4529 time1 = time1 ? time1 : INFINITE;
4530 time2 = time2 ? time2 : INFINITE;
4531
4532 if (time1 < time2)
4533 return -1;
4534 else if (time1 > time2)
4535 return 1;
4536 return 0;
4537 }
4538