1 /*****************************************************************************\
2  *  sort.c - sinfo sorting functions
3  *****************************************************************************
4  *  Copyright (C) 2002-2007 The Regents of the University of California.
5  *  Copyright (C) 2008-2010 Lawrence Livermore National Security.
6  *  Portions Copyright (C) 2010-2017 SchedMD <https://www.schedmd.com>.
7  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8  *  Written by Joey Ekstrom <ekstrom1@llnl.gov>,
9  *             Morris Jette <jette1@llnl.gov>, et. al.
10  *  CODE-OCEC-09-009. All rights reserved.
11  *
12  *  This file is part of Slurm, a resource management program.
13  *  For details, see <https://slurm.schedmd.com/>.
14  *  Please also read the included file: DISCLAIMER.
15  *
16  *  Slurm is free software; you can redistribute it and/or modify it under
17  *  the terms of the GNU General Public License as published by the Free
18  *  Software Foundation; either version 2 of the License, or (at your option)
19  *  any later version.
20  *
21  *  In addition, as a special exception, the copyright holders give permission
22  *  to link the code of portions of this program with the OpenSSL library under
23  *  certain conditions as described in each individual source file, and
24  *  distribute linked combinations including the two. You must obey the GNU
25  *  General Public License in all respects for all of the code used other than
26  *  OpenSSL. If you modify file(s) with this exception, you may extend this
27  *  exception to your version of the file(s), but you are not obligated to do
28  *  so. If you do not wish to do so, delete this exception statement from your
29  *  version.  If you delete this exception statement from all source files in
30  *  the program, then also delete it here.
31  *
32  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
33  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
35  *  details.
36  *
37  *  You should have received a copy of the GNU General Public License along
38  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
39  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
40 \*****************************************************************************/
41 
42 #include <ctype.h>
43 #include "src/common/xstring.h"
44 #include "src/sinfo/sinfo.h"
45 #include "src/squeue/print.h"
46 
47 /* If you want "linux12" to sort before "linux2", then set PURE_ALPHA_SORT */
48 #define PURE_ALPHA_SORT 0
49 
50 static bool reverse_order;
51 static bool part_order;		/* order same as in part table */
52 
53 static void _get_sinfo_from_void(sinfo_data_t **s1, sinfo_data_t **s2,
54 				 void *v1, void *v2);
55 static int _sort_by_avail(void *void1, void *void2);
56 static int _sort_by_cluster_name(void *void1, void *void2);
57 static int _sort_by_cpu_load(void *void1, void *void2);
58 static int _sort_by_free_mem(void *void1, void *void2);
59 static int _sort_by_cpus(void *void1, void *void2);
60 static int _sort_by_sct(void *void1, void *void2);
61 static int _sort_by_sockets(void *void1, void *void2);
62 static int _sort_by_cores(void *void1, void *void2);
63 static int _sort_by_threads(void *void1, void *void2);
64 static int _sort_by_disk(void *void1, void *void2);
65 static int _sort_by_features(void *void1, void *void2);
66 static int _sort_by_features_act(void *void1, void *void2);
67 static int _sort_by_groups(void *void1, void *void2);
68 static int _sort_by_hostnames(void *void1, void *void2);
69 static int _sort_by_job_size(void *void1, void *void2);
70 static int _sort_by_max_time(void *void1, void *void2);
71 static int _sort_by_memory(void *void1, void *void2);
72 static int _sort_by_node_list(void *void1, void *void2);
73 static int _sort_by_node_addr(void *void1, void *void2);
74 static int _sort_by_nodelist_nodeaddr_hostnames(void *void1, void *void2,
75 						int type);
76 static int _sort_by_nodes_ai(void *void1, void *void2);
77 static int _sort_by_nodes(void *void1, void *void2);
78 static int _sort_by_oversubscribe(void *void1, void *void2);
79 static int _sort_by_partition(void *void1, void *void2);
80 static int _sort_by_preempt_mode(void *void1, void *void2);
81 static int _sort_by_priority_job_factor(void *void1, void *void2);
82 static int _sort_by_priority_tier(void *void1, void *void2);
83 static int _sort_by_reason(void *void1, void *void2);
84 static int _sort_by_reason_time(void *void1, void *void2);
85 static int _sort_by_reason_user(void *void1, void *void2);
86 static int _sort_by_root(void *void1, void *void2);
87 static int _sort_by_state(void *void1, void *void2);
88 static int _sort_by_weight(void *void1, void *void2);
89 
90 /*****************************************************************************
91  * Global Sort Function
92  *****************************************************************************/
sort_sinfo_list(List sinfo_list)93 void sort_sinfo_list(List sinfo_list)
94 {
95 	int i;
96 
97 	if (params.sort == NULL) {
98 		if (params.node_flag)
99 			params.sort = xstrdup("N");
100 		else
101 			params.sort = xstrdup("#P,-t");
102 	}
103 
104 	for (i=(strlen(params.sort)-1); i >= 0; i--) {
105 		reverse_order = false;
106 		part_order    = false;
107 
108 		if ((params.sort[i] == ',') || (params.sort[i] == '#') ||
109 		    (params.sort[i] == '+') || (params.sort[i] == '-'))
110 			continue;
111 		if ((i > 0) && (params.sort[i-1] == '-'))
112 			reverse_order = true;
113 		if ((i > 0) && (params.sort[i-1] == '#'))
114 			part_order = true;
115 
116 		if (params.sort[i] == 'a')
117 			list_sort(sinfo_list, _sort_by_avail);
118 		else if (params.sort[i] == 'A')
119 			list_sort(sinfo_list, _sort_by_nodes_ai);
120 		else if (params.sort[i] == 'b')
121 			list_sort(sinfo_list, _sort_by_features_act);
122 		else if (params.sort[i] == 'c')
123 			list_sort(sinfo_list, _sort_by_cpus);
124 		else if (params.sort[i] == 'd')
125 			list_sort(sinfo_list, _sort_by_disk);
126 		else if (params.sort[i] == 'D')
127 			list_sort(sinfo_list, _sort_by_nodes);
128 		else if (params.sort[i] == 'E')
129 			list_sort(sinfo_list, _sort_by_reason);
130 		else if (params.sort[i] == 'f')
131 			list_sort(sinfo_list, _sort_by_features);
132 		else if (params.sort[i] == 'F')
133 			list_sort(sinfo_list, _sort_by_nodes_ai);
134 		else if (params.sort[i] == 'g')
135 			list_sort(sinfo_list, _sort_by_groups);
136 		else if (params.sort[i] == 'h')
137 			list_sort(sinfo_list, _sort_by_oversubscribe);
138 		else if (params.sort[i] == 'H')
139 			list_sort(sinfo_list, _sort_by_reason_time);
140 		else if (params.sort[i] == 'l')
141 			list_sort(sinfo_list, _sort_by_max_time);
142 		else if (params.sort[i] == 'm')
143 			list_sort(sinfo_list, _sort_by_memory);
144 		else if (params.sort[i] == 'M')
145 			list_sort(sinfo_list, _sort_by_preempt_mode);
146 		else if (params.sort[i] == 'n')
147 			list_sort(sinfo_list, _sort_by_hostnames);
148 		else if (params.sort[i] == 'N')
149 			list_sort(sinfo_list, _sort_by_node_list);
150 		else if (params.sort[i] == 'o')
151 			list_sort(sinfo_list, _sort_by_node_addr);
152 		else if (params.sort[i] == 'O')
153 			list_sort(sinfo_list, _sort_by_cpu_load);
154 		else if (params.sort[i] == 'e')
155 			list_sort(sinfo_list, _sort_by_free_mem);
156 		else if (params.sort[i] == 'p')
157 			list_sort(sinfo_list, _sort_by_priority_tier);
158 		else if (params.sort[i] == 'P')
159 			list_sort(sinfo_list, _sort_by_partition);
160 		else if (params.sort[i] == 'r')
161 			list_sort(sinfo_list, _sort_by_root);
162 		else if (params.sort[i] == 'R')
163 			list_sort(sinfo_list, _sort_by_partition);
164 		else if (params.sort[i] == 's')
165 			list_sort(sinfo_list, _sort_by_job_size);
166 		else if (params.sort[i] == 'S')
167 			list_sort(sinfo_list, _sort_by_priority_job_factor);
168 		else if (params.sort[i] == 't')
169 			list_sort(sinfo_list, _sort_by_state);
170 		else if (params.sort[i] == 'T')
171 			list_sort(sinfo_list, _sort_by_state);
172 		else if (params.sort[i] == 'u')
173 			list_sort(sinfo_list, _sort_by_reason_user);
174 		else if (params.sort[i] == 'U')
175 			list_sort(sinfo_list, _sort_by_reason_user);
176 		else if (params.sort[i] == 'V')
177 			list_sort(sinfo_list, _sort_by_cluster_name);
178 		else if (params.sort[i] == 'w')
179 			list_sort(sinfo_list, _sort_by_weight);
180 		else if (params.sort[i] == 'X')
181 			list_sort(sinfo_list, _sort_by_sockets);
182 		else if (params.sort[i] == 'Y')
183 			list_sort(sinfo_list, _sort_by_cores);
184 		else if (params.sort[i] == 'Z')
185 			list_sort(sinfo_list, _sort_by_threads);
186 		else if (params.sort[i] == 'z')
187 			list_sort(sinfo_list, _sort_by_sct);
188 	}
189 }
190 
191 /*****************************************************************************
192  * Local Sort Functions
193  *****************************************************************************/
_diff_uint32(uint32_t value_1,uint32_t value_2)194 static inline int _diff_uint32(uint32_t value_1, uint32_t value_2)
195 {
196 	if (value_1 > value_2)
197 		return 1;
198 	if (value_1 < value_2)
199 		return -1;
200 	return 0;
201 }
_diff_uint64(uint64_t value_1,uint64_t value_2)202 static inline int _diff_uint64(uint64_t value_1, uint64_t value_2)
203 {
204 	if (value_1 > value_2)
205 		return 1;
206 	if (value_1 < value_2)
207 		return -1;
208 	return 0;
209 }
210 static void
_get_sinfo_from_void(sinfo_data_t ** s1,sinfo_data_t ** s2,void * v1,void * v2)211 _get_sinfo_from_void(sinfo_data_t **s1, sinfo_data_t **s2, void *v1, void *v2)
212 {
213 	*s1 = *(sinfo_data_t **) v1;
214 	*s2 = *(sinfo_data_t **) v2;
215 }
216 
_sort_by_avail(void * void1,void * void2)217 static int _sort_by_avail(void *void1, void *void2)
218 {
219 	int diff;
220 	int val1 = 0, val2 = 0;
221 	sinfo_data_t *sinfo1;
222 	sinfo_data_t *sinfo2;
223 
224 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
225 
226 	if (sinfo1->part_info)
227 		val1 = sinfo1->part_info->state_up;
228 	if (sinfo2->part_info)
229 		val2 = sinfo2->part_info->state_up;
230 	diff = val1 - val2;
231 
232 	if (reverse_order)
233 		diff = -diff;
234 	return diff;
235 }
236 
237 
_sort_by_cluster_name(void * void1,void * void2)238 static int _sort_by_cluster_name(void *void1, void *void2)
239 {
240 	int diff;
241 	sinfo_data_t *sinfo1;
242 	sinfo_data_t *sinfo2;
243 
244 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
245 
246 	diff = xstrcmp(sinfo1->cluster_name, sinfo2->cluster_name);
247 
248 	if (reverse_order)
249 		diff = -diff;
250 	return diff;
251 }
252 
_sort_by_cpu_load(void * void1,void * void2)253 static int _sort_by_cpu_load(void *void1, void *void2)
254 {
255 	int diff;
256 	sinfo_data_t *sinfo1;
257 	sinfo_data_t *sinfo2;
258 
259 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
260 
261 	diff = _diff_uint32(sinfo1->min_cpu_load, sinfo2->min_cpu_load);
262 
263 	if (reverse_order)
264 		diff = -diff;
265 	return diff;
266 }
267 
_sort_by_free_mem(void * void1,void * void2)268 static int _sort_by_free_mem(void *void1, void *void2)
269 {
270 	int diff;
271 	sinfo_data_t *sinfo1;
272 	sinfo_data_t *sinfo2;
273 
274 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
275 
276 	diff = _diff_uint64(sinfo1->min_free_mem, sinfo2->min_free_mem);
277 
278 	if (reverse_order)
279 		diff = -diff;
280 	return diff;
281 }
282 
_sort_by_cpus(void * void1,void * void2)283 static int _sort_by_cpus(void *void1, void *void2)
284 {
285 	int diff;
286 	sinfo_data_t *sinfo1;
287 	sinfo_data_t *sinfo2;
288 
289 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
290 
291 	diff = _diff_uint32(sinfo1->min_cpus, sinfo2->min_cpus);
292 
293 	if (reverse_order)
294 		diff = -diff;
295 	return diff;
296 }
297 
_sort_by_sct(void * void1,void * void2)298 static int _sort_by_sct(void *void1, void *void2)
299 {
300 	int diffs, diffc, difft;
301 	sinfo_data_t *sinfo1;
302 	sinfo_data_t *sinfo2;
303 
304 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
305 
306 	diffs = _diff_uint32(sinfo1->min_sockets, sinfo2->min_sockets);
307 	diffc = _diff_uint32(sinfo1->min_cores,   sinfo2->min_cores);
308 	difft = _diff_uint32(sinfo1->min_threads, sinfo2->min_threads);
309 
310 	if (reverse_order) {
311 		diffs = -diffs;
312 		diffc = -diffc;
313 		difft = -difft;
314 	}
315 	if (diffs)
316 		return diffs;
317 	else if (diffc)
318 		return diffc;
319 	else
320 		return difft;
321 }
322 
_sort_by_sockets(void * void1,void * void2)323 static int _sort_by_sockets(void *void1, void *void2)
324 {
325 	int diff;
326 	sinfo_data_t *sinfo1;
327 	sinfo_data_t *sinfo2;
328 
329 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
330 
331 	diff = _diff_uint32(sinfo1->min_sockets, sinfo2->min_sockets);
332 
333 	if (reverse_order)
334 		diff = -diff;
335 	return diff;
336 }
337 
_sort_by_cores(void * void1,void * void2)338 static int _sort_by_cores(void *void1, void *void2)
339 {
340 	int diff;
341 	sinfo_data_t *sinfo1;
342 	sinfo_data_t *sinfo2;
343 
344 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
345 
346 	diff = _diff_uint32(sinfo1->min_cores, sinfo2->min_cores);
347 
348 	if (reverse_order)
349 		diff = -diff;
350 	return diff;
351 }
352 
_sort_by_threads(void * void1,void * void2)353 static int _sort_by_threads(void *void1, void *void2)
354 {
355 	int diff;
356 	sinfo_data_t *sinfo1;
357 	sinfo_data_t *sinfo2;
358 
359 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
360 
361 	diff = _diff_uint32(sinfo1->min_threads, sinfo2->min_threads);
362 
363 	if (reverse_order)
364 		diff = -diff;
365 	return diff;
366 }
367 
_sort_by_disk(void * void1,void * void2)368 static int _sort_by_disk(void *void1, void *void2)
369 {
370 	int diff;
371 	sinfo_data_t *sinfo1;
372 	sinfo_data_t *sinfo2;
373 
374 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
375 
376 	diff = _diff_uint32(sinfo1->min_disk, sinfo2->min_disk);
377 
378 	if (reverse_order)
379 		diff = -diff;
380 	return diff;
381 }
382 
_sort_by_features(void * void1,void * void2)383 static int _sort_by_features(void *void1, void *void2)
384 {
385 	int diff;
386 	sinfo_data_t *sinfo1;
387 	sinfo_data_t *sinfo2;
388 	char *val1 = "", *val2 = "";
389 
390 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
391 
392 	if (sinfo1->features)
393 		val1 = sinfo1->features;
394 	if (sinfo2->features)
395 		val2 = sinfo2->features;
396 	diff = xstrcmp(val1, val2);
397 
398 	if (reverse_order)
399 		diff = -diff;
400 	return diff;
401 }
402 
_sort_by_features_act(void * void1,void * void2)403 static int _sort_by_features_act(void *void1, void *void2)
404 {
405 	int diff;
406 	sinfo_data_t *sinfo1;
407 	sinfo_data_t *sinfo2;
408 	char *val1 = "", *val2 = "";
409 
410 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
411 
412 	if (sinfo1->features_act)
413 		val1 = sinfo1->features_act;
414 	if (sinfo2->features_act)
415 		val2 = sinfo2->features_act;
416 	diff = xstrcmp(val1, val2);
417 
418 	if (reverse_order)
419 		diff = -diff;
420 	return diff;
421 }
422 
_sort_by_groups(void * void1,void * void2)423 static int _sort_by_groups(void *void1, void *void2)
424 {
425 	int diff;
426 	sinfo_data_t *sinfo1;
427 	sinfo_data_t *sinfo2;
428 	char *val1 = "", *val2 = "";
429 
430 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
431 
432 	if (sinfo1->part_info && sinfo1->part_info->allow_groups)
433 		val1 = sinfo1->part_info->allow_groups;
434 	if (sinfo2->part_info && sinfo2->part_info->allow_groups)
435 		val2 = sinfo2->part_info->allow_groups;
436 	diff = xstrcmp(val1, val2);
437 
438 	if (reverse_order)
439 		diff = -diff;
440 	return diff;
441 }
442 
_sort_by_job_size(void * void1,void * void2)443 static int _sort_by_job_size(void *void1, void *void2)
444 {
445 	int diff;
446 	sinfo_data_t *sinfo1;
447 	sinfo_data_t *sinfo2;
448 	uint32_t val1 = 0, val2 = 0;
449 
450 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
451 
452 	if (sinfo1->part_info) {
453 		val1 = sinfo1->part_info->max_nodes;
454 		if (val1 != INFINITE)
455 			val1 += sinfo1->part_info->min_nodes;
456 	}
457 	if (sinfo2->part_info) {
458 		val2 = sinfo2->part_info->max_nodes;
459 		if (val2 != INFINITE)
460 			val2 += sinfo2->part_info->min_nodes;
461 	}
462 	diff = _diff_uint32(val1, val2);
463 
464 	if (reverse_order)
465 		diff = -diff;
466 	return diff;
467 }
468 
_sort_by_max_time(void * void1,void * void2)469 static int _sort_by_max_time(void *void1, void *void2)
470 {
471 	int diff;
472 	sinfo_data_t *sinfo1;
473 	sinfo_data_t *sinfo2;
474 	uint32_t val1 = 0, val2 = 0;
475 
476 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
477 
478 	if (sinfo1->part_info)
479 		val1 = sinfo1->part_info->max_time;
480 	if (sinfo2->part_info)
481 		val2 = sinfo2->part_info->max_time;
482 	diff = _diff_uint32(val1, val2);
483 
484 	if (reverse_order)
485 		diff = -diff;
486 	return diff;
487 }
488 
_sort_by_memory(void * void1,void * void2)489 static int _sort_by_memory(void *void1, void *void2)
490 {
491 	int diff;
492 	sinfo_data_t *sinfo1;
493 	sinfo_data_t *sinfo2;
494 
495 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
496 
497 	diff = _diff_uint64(sinfo1->min_mem, sinfo2->min_mem);
498 
499 	if (reverse_order)
500 		diff = -diff;
501 	return diff;
502 }
503 
504 /*
505  * Sorts an sinfo_data_t list by nodelist, hostnames, or node_addr.
506  *
507  * type:	0 for nodelist, 1 for node_addr, and 2 for hostname.
508  */
_sort_by_nodelist_nodeaddr_hostnames(void * void1,void * void2,int type)509 static int _sort_by_nodelist_nodeaddr_hostnames(void *void1, void *void2,
510 						int type)
511 {
512 	int diff = 0;
513 	sinfo_data_t *sinfo1;
514 	sinfo_data_t *sinfo2;
515 	hostlist_t hl1 = NULL;
516 	hostlist_t hl2 = NULL;
517 #if	PURE_ALPHA_SORT
518 	char *val1, *val2;
519 	char *ptr1, *ptr2;
520 #endif
521 
522 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
523 
524 	switch (type) {
525 	case 0:
526 		hl1 = sinfo1->nodes;
527 		hl2 = sinfo2->nodes;
528 		break;
529 	case 1:
530 		hl1 = sinfo1->node_addr;
531 		hl2 = sinfo2->node_addr;
532 		break;
533 	case 2:
534 		hl1 = sinfo1->hostnames;
535 		hl2 = sinfo2->hostnames;
536 		break;
537 	default:
538 		fatal("%s: invalid type `%d` specified", __func__, type);
539 	}
540 
541 #if	PURE_ALPHA_SORT
542 	val1 = hostlist_shift(hl1);
543 	if (val1) {
544 		hostlist_push_host(hl1, val1);
545 		hostlist_sort(hl1);
546 		ptr1 = val1;
547 	} else
548 		ptr1 = "";
549 
550 	val2 = hostlist_shift(hl2);
551 	if (val2) {
552 		hostlist_push_host(hl2, val2);
553 		hostlist_sort(hl2);
554 		ptr2 = val2;
555 	} else
556 		ptr2 = "";
557 	diff = xstrcmp(ptr1, ptr2);
558 	if (val1)
559 		free(val1);
560 	if (val2)
561 		free(val2);
562 #else
563 	/*
564 	 * The hostlist in sinfo_data_t should each only have one hostrange, and
565 	 * each hostrange should only have one node name/host name
566 	 */
567 	diff = hostlist_cmp_first(hl1, hl2);
568 #endif
569 
570 	if (reverse_order)
571 		diff = -diff;
572 
573 	return diff;
574 }
575 
_sort_by_node_list(void * void1,void * void2)576 static int _sort_by_node_list(void *void1, void *void2)
577 {
578 	return _sort_by_nodelist_nodeaddr_hostnames(void1, void2, 0);
579 }
580 
_sort_by_node_addr(void * void1,void * void2)581 static int _sort_by_node_addr(void *void1, void *void2)
582 {
583 	return _sort_by_nodelist_nodeaddr_hostnames(void1, void2, 1);
584 }
585 
_sort_by_hostnames(void * void1,void * void2)586 static int _sort_by_hostnames(void *void1, void *void2)
587 {
588 	return _sort_by_nodelist_nodeaddr_hostnames(void1, void2, 2);
589 }
590 
591 
_sort_by_nodes_ai(void * void1,void * void2)592 static int _sort_by_nodes_ai(void *void1, void *void2)
593 {
594 	int diff;
595 	sinfo_data_t *sinfo1;
596 	sinfo_data_t *sinfo2;
597 
598 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
599 
600 	diff = _diff_uint32(sinfo1->nodes_alloc, sinfo2->nodes_alloc);
601 
602 	if (reverse_order)
603 		diff = -diff;
604 	return diff;
605 }
606 
_sort_by_nodes(void * void1,void * void2)607 static int _sort_by_nodes(void *void1, void *void2)
608 {
609 	int diff;
610 	sinfo_data_t *sinfo1;
611 	sinfo_data_t *sinfo2;
612 
613 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
614 
615 	diff = _diff_uint32(sinfo1->nodes_total, sinfo2->nodes_total);
616 
617 	if (reverse_order)
618 		diff = -diff;
619 	return diff;
620 }
621 
_sort_by_partition(void * void1,void * void2)622 static int _sort_by_partition(void *void1, void *void2)
623 {
624 	int diff;
625 	sinfo_data_t *sinfo1;
626 	sinfo_data_t *sinfo2;
627 	char *val1 = "", *val2 = "";
628 
629 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
630 
631 	if (part_order) {
632 		diff = (int)sinfo1->part_inx - (int)sinfo2->part_inx;
633 	} else {
634 		if (sinfo1->part_info && sinfo1->part_info->name)
635 			val1 = sinfo1->part_info->name;
636 		if (sinfo2->part_info && sinfo2->part_info->name)
637 			val2 = sinfo2->part_info->name;
638 		diff = xstrcmp(val1, val2);
639 	}
640 
641 	if (reverse_order)
642 		diff = -diff;
643 	return diff;
644 }
645 
_sort_by_reason(void * void1,void * void2)646 static int _sort_by_reason(void *void1, void *void2)
647 {
648 	int diff;
649 	sinfo_data_t *sinfo1;
650 	sinfo_data_t *sinfo2;
651 	char *val1 = "", *val2 = "";
652 
653 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
654 
655 	if (sinfo1->reason)
656 		val1 = sinfo1->reason;
657 	if (sinfo2->reason)
658 		val2 = sinfo2->reason;
659 	diff = xstrcmp(val1, val2);
660 
661 	if (reverse_order)
662 		diff = -diff;
663 	return diff;
664 }
665 
_sort_by_reason_time(void * void1,void * void2)666 static int _sort_by_reason_time(void *void1, void *void2)
667 {
668 	int diff;
669 	sinfo_data_t *sinfo1;
670 	sinfo_data_t *sinfo2;
671 
672 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
673 
674 	if (sinfo1->reason_time > sinfo2->reason_time)
675 		diff = 1;
676 	else if (sinfo1->reason_time < sinfo2->reason_time)
677 		diff = -1;
678 	else
679 		diff = 0;
680 
681 	if (reverse_order)
682 		diff = -diff;
683 	return diff;
684 }
685 
_sort_by_reason_user(void * void1,void * void2)686 static int _sort_by_reason_user(void *void1, void *void2)
687 {
688 	int diff;
689 	sinfo_data_t *sinfo1;
690 	sinfo_data_t *sinfo2;
691 
692 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
693 
694 	if (sinfo1->reason_uid > sinfo2->reason_uid)
695 		diff = 1;
696 	else if (sinfo1->reason_uid < sinfo2->reason_uid)
697 		diff = -1;
698 	else
699 		diff = 0;
700 
701 	if (reverse_order)
702 		diff = -diff;
703 	return diff;
704 }
705 
_sort_by_root(void * void1,void * void2)706 static int _sort_by_root(void *void1, void *void2)
707 {
708 	int diff;
709 	sinfo_data_t *sinfo1;
710 	sinfo_data_t *sinfo2;
711 	int val1 = 0, val2 = 0;
712 
713 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
714 
715 	if (sinfo1->part_info)
716 		val1 = sinfo1->part_info->flags & PART_FLAG_ROOT_ONLY;
717 	if (sinfo2->part_info)
718 		val2 = sinfo2->part_info->flags & PART_FLAG_ROOT_ONLY;
719 	diff = val1 - val2;
720 
721 	if (reverse_order)
722 		diff = -diff;
723 	return diff;
724 }
725 
_sort_by_oversubscribe(void * void1,void * void2)726 static int _sort_by_oversubscribe(void *void1, void *void2)
727 {
728 	int diff;
729 	sinfo_data_t *sinfo1;
730 	sinfo_data_t *sinfo2;
731 	int val1 = 0, val2 = 0;
732 
733 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
734 
735 	if (sinfo1->part_info)
736 		val1 = sinfo1->part_info->max_share;
737 	if (sinfo2->part_info)
738 		val2 = sinfo2->part_info->max_share;
739 	diff = val1 - val2;
740 
741 	if (reverse_order)
742 		diff = -diff;
743 	return diff;
744 }
745 
_sort_by_preempt_mode(void * void1,void * void2)746 static int _sort_by_preempt_mode(void *void1, void *void2)
747 {
748 	int diff;
749 	sinfo_data_t *sinfo1;
750 	sinfo_data_t *sinfo2;
751 	int val1 = 0, val2 = 0;
752 
753 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
754 
755 	if (sinfo1->part_info)
756 		val1 = sinfo1->part_info->preempt_mode;
757 	if (sinfo2->part_info)
758 		val2 = sinfo2->part_info->preempt_mode;
759 	diff = val1 - val2;
760 
761 	if (reverse_order)
762 		diff = -diff;
763 	return diff;
764 }
765 
_sort_by_priority_job_factor(void * void1,void * void2)766 static int _sort_by_priority_job_factor(void *void1, void *void2)
767 {
768 	int diff;
769 	sinfo_data_t *sinfo1;
770 	sinfo_data_t *sinfo2;
771 	uint32_t val1 = 0, val2 = 0;
772 
773 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
774 
775 	if (sinfo1->part_info)
776 		val1 = sinfo1->part_info->priority_job_factor;
777 	if (sinfo2->part_info)
778 		val2 = sinfo2->part_info->priority_job_factor;
779 	diff = _diff_uint32(val1, val2);
780 
781 	if (reverse_order)
782 		diff = -diff;
783 	return diff;
784 }
785 
_sort_by_priority_tier(void * void1,void * void2)786 static int _sort_by_priority_tier(void *void1, void *void2)
787 {
788 	int diff;
789 	sinfo_data_t *sinfo1;
790 	sinfo_data_t *sinfo2;
791 	uint32_t val1 = 0, val2 = 0;
792 
793 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
794 
795 	if (sinfo1->part_info)
796 		val1 = sinfo1->part_info->priority_tier;
797 	if (sinfo2->part_info)
798 		val2 = sinfo2->part_info->priority_tier;
799 	diff = _diff_uint32(val1, val2);
800 
801 	if (reverse_order)
802 		diff = -diff;
803 	return diff;
804 }
805 
_sort_by_state(void * void1,void * void2)806 static int _sort_by_state(void *void1, void *void2)
807 {
808 	int diff;
809 	sinfo_data_t *sinfo1;
810 	sinfo_data_t *sinfo2;
811 
812 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
813 
814 	diff = (int)sinfo1->node_state - (int)sinfo2->node_state;
815 
816 	if (reverse_order)
817 		diff = -diff;
818 
819 	return diff;
820 }
821 
_sort_by_weight(void * void1,void * void2)822 static int _sort_by_weight(void *void1, void *void2)
823 {
824 	int diff;
825 	sinfo_data_t *sinfo1;
826 	sinfo_data_t *sinfo2;
827 
828 	_get_sinfo_from_void(&sinfo1, &sinfo2, void1, void2);
829 
830 	diff = _diff_uint32(sinfo1->min_weight, sinfo2->min_weight);
831 
832 	if (reverse_order)
833 		diff = -diff;
834 	return diff;
835 }
836