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