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