1 /*****************************************************************************\
2  *  print.c - sprio print job functions
3  *****************************************************************************
4  *  Portions Copyright (C) 2010-2017 SchedMD LLC <https://www.schedmd.com>.
5  *  Copyright (C) 2009 Lawrence Livermore National Security.
6  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7  *  Written by Don Lipari <lipari1@llnl.gov>
8  *  CODE-OCEC-09-009. All rights reserved.
9  *
10  *  This file is part of Slurm, a resource management program.
11  *  For details, see <https://slurm.schedmd.com/>.
12  *  Please also read the included file: DISCLAIMER.
13  *
14  *  Slurm is free software; you can redistribute it and/or modify it under
15  *  the terms of the GNU General Public License as published by the Free
16  *  Software Foundation; either version 2 of the License, or (at your option)
17  *  any later version.
18  *
19  *  In addition, as a special exception, the copyright holders give permission
20  *  to link the code of portions of this program with the OpenSSL library under
21  *  certain conditions as described in each individual source file, and
22  *  distribute linked combinations including the two. You must obey the GNU
23  *  General Public License in all respects for all of the code used other than
24  *  OpenSSL. If you modify file(s) with this exception, you may extend this
25  *  exception to your version of the file(s), but you are not obligated to do
26  *  so. If you do not wish to do so, delete this exception statement from your
27  *  version.  If you delete this exception statement from all source files in
28  *  the program, then also delete it here.
29  *
30  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
31  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
32  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
33  *  details.
34  *
35  *  You should have received a copy of the GNU General Public License along
36  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
37  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
38 \*****************************************************************************/
39 
40 #include <stdio.h>
41 #include <string.h>
42 #include <time.h>
43 #include <sys/types.h>
44 
45 #include "src/common/list.h"
46 #include "src/common/macros.h"
47 #include "src/slurmctld/slurmctld.h"
48 #include "src/common/uid.h"
49 #include "src/common/xmalloc.h"
50 #include "src/common/xstring.h"
51 
52 #include "src/sprio/print.h"
53 #include "src/sprio/sprio.h"
54 
55 static int	_print_str(char *str, int width, bool right, bool cut_output);
56 
57 /*****************************************************************************
58  * Global Print Functions
59  *****************************************************************************/
60 
print_jobs_array(List jobs,List format)61 int print_jobs_array(List jobs, List format)
62 {
63 	if (!params.no_header)
64 		print_job_from_format(NULL, format);
65 
66 	if (params.weights) {
67 		print_job_from_format((priority_factors_object_t *) -1, format);
68 		return SLURM_SUCCESS;
69 	}
70 
71 	/* Print the jobs of interest */
72 	if (jobs) {
73 		sort_job_list(jobs);
74 		list_for_each (jobs, (ListForF) print_job_from_format,
75 			       (void *) format);
76 	}
77 
78 	return SLURM_SUCCESS;
79 }
80 
get_priority_from_factors(priority_factors_object_t * prio_factors)81 double get_priority_from_factors(priority_factors_object_t *prio_factors)
82 {
83 	int i = 0;
84 	double priority = prio_factors->priority_age
85 		+ prio_factors->priority_assoc
86 		+ prio_factors->priority_fs
87 		+ prio_factors->priority_js
88 		+ prio_factors->priority_part
89 		+ prio_factors->priority_qos
90 		+ (double)((int64_t)prio_factors->priority_site - NICE_OFFSET)
91 		- (double)((int64_t)prio_factors->nice - NICE_OFFSET);
92 
93 	if (prio_factors->direct_prio > 0)
94 		return prio_factors->direct_prio;
95 
96 	for (i = 0; i < prio_factors->tres_cnt; i++) {
97 		if (!prio_factors->priority_tres[i])
98 			continue;
99 		priority += prio_factors->priority_tres[i];
100 	}
101 
102 	/* Priority 0 is reserved for held jobs */
103         if (priority < 1)
104                 priority = 1;
105 
106 	return priority;
107 }
108 
_print_str(char * str,int width,bool right,bool cut_output)109 static int _print_str(char *str, int width, bool right, bool cut_output)
110 {
111 	char format[64];
112 	int printed = 0;
113 
114 	if (right == true && width != 0)
115 		snprintf(format, 64, "%%%ds", width);
116 	else if (width != 0)
117 		snprintf(format, 64, "%%.%ds", width);
118 	else {
119 		format[0] = '%';
120 		format[1] = 's';
121 		format[2] = '\0';
122 	}
123 
124 	if ((width == 0) || (cut_output == false)) {
125 		if ((printed = printf(format, str)) < 0)
126 			return printed;
127 	} else {
128 		char temp[width + 1];
129 		snprintf(temp, width + 1, format, str);
130 		if ((printed = printf("%s",temp)) < 0)
131 			return printed;
132 	}
133 
134 	while (printed++ < width)
135 		printf(" ");
136 
137 	return printed;
138 }
139 
_print_int(double number,int width,bool right,bool cut_output)140 static int _print_int(double number, int width, bool right, bool cut_output)
141 {
142 	char buf[32];
143 
144 	snprintf(buf, 32, "%.0f", number);
145 	return _print_str(buf, width, right, cut_output);
146 }
147 
_print_norm(double number,int width,bool right,bool cut_output)148 static int _print_norm(double number, int width, bool right, bool cut_output)
149 {
150 	char buf[32];
151 
152 	snprintf(buf, 32, "%.7lf", number);
153 	return _print_str(buf, width, right, cut_output);
154 }
155 
156 
157 /*****************************************************************************
158  * Job Print Functions
159  *****************************************************************************/
print_job_from_format(priority_factors_object_t * job,List list)160 int print_job_from_format(priority_factors_object_t * job, List list)
161 {
162 	ListIterator i = list_iterator_create(list);
163 	job_format_t *current;
164 	int total_width = 0;
165 
166 	while ((current = list_next(i))) {
167 		if (current->
168 		    function(job, current->width, current->right_justify,
169 			     current->suffix)
170 		    != SLURM_SUCCESS)
171 			return SLURM_ERROR;
172 		if (current->width)
173 			total_width += (current->width + 1);
174 		else
175 			total_width += 10;
176 	}
177 	list_iterator_destroy(i);
178 
179 	printf("\n");
180 
181 	return SLURM_SUCCESS;
182 }
183 
job_format_add_function(List list,int width,bool right,char * suffix,int (* function)(priority_factors_object_t *,int,bool,char *))184 int job_format_add_function(List list, int width, bool right, char *suffix,
185 			    int (*function) (priority_factors_object_t *,
186 			    int, bool, char*))
187 {
188 	job_format_t *tmp = (job_format_t *) xmalloc(sizeof(job_format_t));
189 	tmp->function = function;
190 	tmp->width = width;
191 	tmp->right_justify = right;
192 	tmp->suffix = suffix;
193 	list_append(list, tmp);
194 
195 	return SLURM_SUCCESS;
196 }
197 
198 
_print_job_job_id(priority_factors_object_t * job,int width,bool right,char * suffix)199 int _print_job_job_id(priority_factors_object_t * job, int width,
200 		      bool right, char* suffix)
201 {
202 	if (job == NULL)	/* Print the Header instead */
203 		_print_str("JOBID", width, right, true);
204 	else if (job == (priority_factors_object_t *) -1)
205 		_print_str("Weights", width, right, true);
206 	else {
207 		char id[FORMAT_STRING_SIZE];
208 		snprintf(id, FORMAT_STRING_SIZE, "%u", job->job_id);
209 		_print_str(id, width, right, true);
210 	}
211 	if (suffix)
212 		printf("%s", suffix);
213 	return SLURM_SUCCESS;
214 }
215 
_print_job_prefix(priority_factors_object_t * job,int width,bool right,char * suffix)216 int _print_job_prefix(priority_factors_object_t * job, int width,
217 		      bool right, char* suffix)
218 {
219 	if (suffix)
220 		printf("%s", suffix);
221 	return SLURM_SUCCESS;
222 }
223 
_print_age_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)224 int _print_age_priority_normalized(priority_factors_object_t * job, int width,
225 				   bool right, char* suffix)
226 {
227 	if (job == NULL)	/* Print the Header instead */
228 		_print_str("AGE", width, right, true);
229 	else if (job == (priority_factors_object_t *) -1)
230 		_print_int(weight_age, width, right, true);
231 	else {
232 		double num = 0;
233 		if (weight_age)
234 			num = job->priority_age / weight_age;
235 		_print_norm(num, width, right, true);
236 	}
237 	if (suffix)
238 		printf("%s", suffix);
239 	return SLURM_SUCCESS;
240 }
241 
_print_age_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)242 int _print_age_priority_weighted(priority_factors_object_t * job, int width,
243 				 bool right, char* suffix)
244 {
245 	if (job == NULL)	/* Print the Header instead */
246 		_print_str("AGE", width, right, true);
247 	else if (job == (priority_factors_object_t *) -1)
248 		_print_int(weight_age, width, right, true);
249 	else
250 		_print_int(job->priority_age, width, right, true);
251 	if (suffix)
252 		printf("%s", suffix);
253 	return SLURM_SUCCESS;
254 }
255 
_print_assoc_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)256 int _print_assoc_priority_normalized(priority_factors_object_t * job, int width,
257 				     bool right, char* suffix)
258 {
259 	if (job == NULL)	/* Print the Header instead */
260 		_print_str("ASSOC", width, right, true);
261 	else if (job == (priority_factors_object_t *) -1)
262 		_print_int(weight_assoc, width, right, true);
263 	else {
264 		double num = 0;
265 		if (weight_qos)
266 			num = job->priority_assoc / weight_assoc;
267 		_print_norm(num, width, right, true);
268 	}
269 
270 	if (suffix)
271 		printf("%s", suffix);
272 	return SLURM_SUCCESS;
273 }
274 
_print_assoc_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)275 int _print_assoc_priority_weighted(priority_factors_object_t * job, int width,
276 				   bool right, char* suffix)
277 {
278 	if (job == NULL)	/* Print the Header instead */
279 		_print_str("ASSOC", width, right, true);
280 	else if (job == (priority_factors_object_t *) -1)
281 		_print_int(weight_assoc, width, right, true);
282 	else
283 		_print_int(job->priority_assoc, width, right, true);
284 	if (suffix)
285 		printf("%s", suffix);
286 	return SLURM_SUCCESS;
287 }
288 
_print_cluster_name(priority_factors_object_t * job,int width,bool right,char * suffix)289 int _print_cluster_name(priority_factors_object_t *job, int width,
290 			bool right, char *suffix)
291 {
292 	if (job == NULL)	/* Print the Header instead */
293 		_print_str("CLUSTER", width, right, true);
294 	else
295 		_print_str(job->cluster_name, width, right, true);
296 	if (suffix)
297 		printf("%s", suffix);
298 	return SLURM_SUCCESS;
299 }
300 
_print_fs_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)301 int _print_fs_priority_normalized(priority_factors_object_t * job, int width,
302 				  bool right, char* suffix)
303 {
304 	if (job == NULL)	/* Print the Header instead */
305 		_print_str("FAIRSHARE", width, right, true);
306 	else if (job == (priority_factors_object_t *) -1)
307 		_print_int(weight_fs, width, right, true);
308 	else {
309 		double num = 0;
310 		if (weight_fs)
311 			num = job->priority_fs / weight_fs;
312 		_print_norm(num, width, right, true);
313 	}
314 
315 	if (suffix)
316 		printf("%s", suffix);
317 	return SLURM_SUCCESS;
318 }
319 
_print_fs_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)320 int _print_fs_priority_weighted(priority_factors_object_t * job, int width,
321 				bool right, char* suffix)
322 {
323 	if (job == NULL)	/* Print the Header instead */
324 		_print_str("FAIRSHARE", width, right, true);
325 	else if (job == (priority_factors_object_t *) -1)
326 		_print_int(weight_fs, width, right, true);
327 	else
328 		_print_int(job->priority_fs, width, right, true);
329 	if (suffix)
330 		printf("%s", suffix);
331 	return SLURM_SUCCESS;
332 }
333 
_print_job_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)334 int _print_job_priority_normalized(priority_factors_object_t * job, int width,
335 				   bool right, char* suffix)
336 {
337 	char temp[FORMAT_STRING_SIZE];
338 	if (job == NULL)	/* Print the Header instead */
339 		_print_str("PRIORITY", width, right, true);
340 	else if (job == (priority_factors_object_t *) -1)
341 		_print_str("", width, right, true);
342 	else if (job->direct_prio > 0) {
343 		sprintf(temp, "%16.14f", job->direct_prio);
344 		_print_str(temp, width, right, true);
345 	} else {
346 		double priority = get_priority_from_factors(job);
347 		double prio = priority / (double) ((uint32_t) 0xffffffff);
348 
349 		sprintf(temp, "%16.14f", prio);
350 		_print_str(temp, width, right, true);
351 	}
352 	if (suffix)
353 		printf("%s", suffix);
354 	return SLURM_SUCCESS;
355 }
356 
_print_job_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)357 int _print_job_priority_weighted(priority_factors_object_t * job, int width,
358 				 bool right, char* suffix)
359 {
360 	char temp[FORMAT_STRING_SIZE];
361 	if (job == NULL)	/* Print the Header instead */
362 		_print_str("PRIORITY", width, right, true);
363 	else if (job == (priority_factors_object_t *) -1)
364 		_print_str("", width, right, true);
365 	else {
366 		sprintf(temp, "%lld", (long long)get_priority_from_factors(job));
367 		_print_str(temp, width, right, true);
368 	}
369 	if (suffix)
370 		printf("%s", suffix);
371 	return SLURM_SUCCESS;
372 }
373 
_print_js_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)374 int _print_js_priority_normalized(priority_factors_object_t * job, int width,
375 				  bool right, char* suffix)
376 {
377 	if (job == NULL)	/* Print the Header instead */
378 		_print_str("JOBSIZE", width, right, true);
379 	else if (job == (priority_factors_object_t *) -1)
380 		_print_int(weight_js, width, right, true);
381 	else {
382 		double num = 0;
383 		if (weight_js)
384 			num = job->priority_js / weight_js;
385 		_print_norm(num, width, right, true);
386 	}
387 
388 	if (suffix)
389 		printf("%s", suffix);
390 
391 	return SLURM_SUCCESS;
392 }
393 
_print_js_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)394 int _print_js_priority_weighted(priority_factors_object_t * job, int width,
395 				bool right, char* suffix)
396 {
397 	if (job == NULL)	/* Print the Header instead */
398 		_print_str("JOBSIZE", width, right, true);
399 	else if (job == (priority_factors_object_t *) -1)
400 		_print_int(weight_js, width, right, true);
401 	else {
402 		_print_int(job->priority_js, width, right, true);
403 	}
404 	if (suffix)
405 		printf("%s", suffix);
406 
407 	return SLURM_SUCCESS;
408 }
409 
_print_part_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)410 int _print_part_priority_normalized(priority_factors_object_t * job, int width,
411 				    bool right, char* suffix)
412 {
413 	if (job == NULL)	/* Print the Header instead */
414 		_print_str("PARTITION", width, right, true);
415 	else if (job == (priority_factors_object_t *) -1)
416 		_print_int(weight_part, width, right, true);
417 	else {
418 		double num = 0;
419 		if (weight_part)
420 			num = job->priority_part / weight_part;
421 		_print_norm(num, width, right, true);
422 	}
423 
424 	if (suffix)
425 		printf("%s", suffix);
426 	return SLURM_SUCCESS;
427 }
428 
_print_part_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)429 int _print_part_priority_weighted(priority_factors_object_t * job, int width,
430 				  bool right, char* suffix)
431 {
432 	if (job == NULL)	/* Print the Header instead */
433 		_print_str("PARTITION", width, right, true);
434 	else if (job == (priority_factors_object_t *) -1)
435 		_print_int(weight_part, width, right, true);
436 	else
437 		_print_int(job->priority_part, width, right, true);
438 	if (suffix)
439 		printf("%s", suffix);
440 	return SLURM_SUCCESS;
441 }
442 
_print_partition(priority_factors_object_t * job,int width,bool right,char * suffix)443 int _print_partition(priority_factors_object_t *job, int width, bool right,
444 		     char *suffix)
445 {
446 	if (job == NULL)	/* Print the Header instead */
447 		_print_str("PARTITION", width, right, true);
448 	else if (job == (priority_factors_object_t *) -1)
449 		_print_str("", width, right, true);
450 	else
451 		_print_str(job->partition, width, right, true);
452 	if (suffix)
453 		printf("%s", suffix);
454 	return SLURM_SUCCESS;
455 }
456 
_print_qos_priority_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)457 int _print_qos_priority_normalized(priority_factors_object_t * job, int width,
458 				   bool right, char* suffix)
459 {
460 	if (job == NULL)	/* Print the Header instead */
461 		_print_str("QOS", width, right, true);
462 	else if (job == (priority_factors_object_t *) -1)
463 		_print_int(weight_qos, width, right, true);
464 	else {
465 		double num = 0;
466 		if (weight_qos)
467 			num = job->priority_qos / weight_qos;
468 		_print_norm(num, width, right, true);
469 	}
470 
471 	if (suffix)
472 		printf("%s", suffix);
473 	return SLURM_SUCCESS;
474 }
475 
_print_qos_priority_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)476 int _print_qos_priority_weighted(priority_factors_object_t * job, int width,
477 				 bool right, char* suffix)
478 {
479 	if (job == NULL)	/* Print the Header instead */
480 		_print_str("QOS", width, right, true);
481 	else if (job == (priority_factors_object_t *) -1)
482 		_print_int(weight_qos, width, right, true);
483 	else
484 		_print_int(job->priority_qos, width, right, true);
485 	if (suffix)
486 		printf("%s", suffix);
487 	return SLURM_SUCCESS;
488 }
489 
_print_site_priority(priority_factors_object_t * job,int width,bool right,char * suffix)490 int _print_site_priority(priority_factors_object_t * job, int width,
491 			 bool right, char* suffix)
492 {
493 	if (job == NULL)	/* Print the Header instead */
494 		_print_str("SITE", width, right, true);
495 	else if (job == (priority_factors_object_t *) -1)
496 		_print_int(1, width, right, true);
497 	else if (job->direct_prio > 0)
498 		_print_int(0, width, right, true);
499 	else
500 		_print_int((int64_t)job->priority_site - NICE_OFFSET, width,
501 			   right, true);
502 	if (suffix)
503 		printf("%s", suffix);
504 	return SLURM_SUCCESS;
505 }
506 
_print_job_nice(priority_factors_object_t * job,int width,bool right,char * suffix)507 int _print_job_nice(priority_factors_object_t * job, int width,
508 				bool right, char* suffix)
509 {
510 	if (job == NULL)	/* Print the Header instead */
511 		_print_str("NICE", width, right, true);
512 	else if (job == (priority_factors_object_t *) -1)
513 		_print_str("", width, right, true);
514 	else if (job->direct_prio > 0)
515 		_print_int(0, width, right, true);
516 	else
517 		_print_int((int64_t)job->nice - NICE_OFFSET, width, right, true);
518 	if (suffix)
519 		printf("%s", suffix);
520 	return SLURM_SUCCESS;
521 }
522 
_print_job_user_name(priority_factors_object_t * job,int width,bool right,char * suffix)523 int _print_job_user_name(priority_factors_object_t * job, int width,
524 			 bool right, char* suffix)
525 {
526 	if (job == NULL)	/* Print the Header instead */
527 		_print_str("USER", width, right, true);
528 	else if (job == (priority_factors_object_t *) -1)
529 		_print_str("", width, right, true);
530 	else {
531 		char *uname = uid_to_string_cached((uid_t) job->user_id);
532 		_print_str(uname, width, right, true);
533 	}
534 	if (suffix)
535 		printf("%s", suffix);
536 	return SLURM_SUCCESS;
537 }
538 
_print_tres_normalized(priority_factors_object_t * job,int width,bool right,char * suffix)539 int _print_tres_normalized(priority_factors_object_t * job, int width,
540 			   bool right, char* suffix)
541 {
542 	if (job == NULL) {	/* Print the Header instead */
543 		_print_str("TRES", width, right, true);
544 	} else if (job == (priority_factors_object_t *) -1)
545 		_print_str("", width, right, true);
546 	else {
547 		char *values = xstrdup("");
548 		int i = 0;
549 
550 		for (i = 0; i < job->tres_cnt; i++) {
551 			if (!job->priority_tres[i])
552 				continue;
553 			if (values[0])
554 				xstrcat(values, ",");
555 			xstrfmtcat(values, "%s=%.2f", job->tres_names[i],
556 				   job->priority_tres[i]/job->tres_weights[i]);
557 		}
558 
559 		_print_str(values, width, right, true);
560 		xfree(values);
561 	}
562 	if (suffix)
563 		printf("%s", suffix);
564 	return SLURM_SUCCESS;
565 }
566 
_print_tres_weighted(priority_factors_object_t * job,int width,bool right,char * suffix)567 int _print_tres_weighted(priority_factors_object_t * job, int width,
568 			 bool right, char* suffix)
569 {
570 	if (job == NULL) {	/* Print the Header instead */
571 		_print_str("TRES", width, right, true);
572 	} else if (job == (priority_factors_object_t *) -1)
573 		_print_str(weight_tres, width, right, true);
574 	else {
575 		char *values = xstrdup("");
576 		int i = 0;
577 
578 		for (i = 0; i < job->tres_cnt; i++) {
579 			if (!job->priority_tres[i])
580 				continue;
581 			if (values[0])
582 				xstrcat(values, ",");
583 			xstrfmtcat(values, "%s=%.0f", job->tres_names[i],
584 				   job->priority_tres[i]);
585 		}
586 
587 		_print_str(values, width, right, true);
588 		xfree(values);
589 	}
590 	if (suffix)
591 		printf("%s", suffix);
592 	return SLURM_SUCCESS;
593 }
594