diff --git a/doc/man/man1/sinfo.1 b/doc/man/man1/sinfo.1 index 03e0ef2e598c046d8d2d07b71b5d7fa61e28e792..695d7218f0bd20b32ac2d9eb9dc871a1e7ddfba8 100644 --- a/doc/man/man1/sinfo.1 +++ b/doc/man/man1/sinfo.1 @@ -42,15 +42,15 @@ This is ignored if the \fB\-\-format\fR option is specified. .TP \fB\-o <output_format>\fR, \fB\-\-format=<output_format>\fR Specify the information to be displayed. -The default format is "%9P %5a %.8l %.6D %6t %N". +The default format is "%9P %5a %.9l %.5D %6t %N". If the \fB\-\-summarize\fR option is specified, the default -format is "%9P %5a %.8l %15F %N". +format is "%9P %5a %.9l %15F %N". If the \fB\-\-long\fR option is specified, the default format is -"%9P %5a %.8l %.8s %4r %5h %10g %.6D %11T %N". +"%9P %5a %.9l %.8s %4r %5h %10g %.5D %11T %N". If the \fB\-\-Node\fR option is specified, the default format is -"%#N %.6D %9P %6t". +"%#N %.5D %9P %6t". If the \fB\-\-Node\fR and \fB\-\-long\fR options are both specified, -the default format is "%#N %.6D %9P %11T %.4c %.6m %.8d %.6w %8f". +the default format is "%#N %.5D %9P %11T %.4c %.6m %.8d %.6w %8f". In the above two formats the value of "#" represents the maximum length of an node list to be printed. @@ -76,7 +76,7 @@ the different node states will be placed on separate lines. .br \fB%g\fR Groups which may use the nodes .br -\fB%h\fR Jobs may share nodes, "YES", "NO", or "FORCE" +\fB%h\fR Jobs may share nodes, "yes", "no", or "force" .br \fB%l\fR Maximum time for any job in the format "days:hours:minutes:seconds" .br @@ -86,7 +86,7 @@ the different node states will be placed on separate lines. .br \fB%P\fR Partition name .br -\fB%r\fR Only user root may initiate jobs, "YES" or "NO" +\fB%r\fR Only user root may initiate jobs, "yes" or "no" .br \fB%s\fR Maximum job size in nodes .br @@ -100,12 +100,16 @@ the different node states will be placed on separate lines. .br \fB%<Number><*>\fR size of field .TP -\fB\-t <state>\fR , \fB\-\-state=<state>\fR -List nodes of a given state. +\fB\-t <state>\fR , \fB\-\-states=<states>\fR +List nodes of given states. .TP \fB\-s\fR , \fB\-\-summarize\fR List only a partition state summary with no node state details. This is ignored if the \fB\-\-format\fR option is specified. +.TP +\fB\-S <sort>\fR , \fB\-\-sort=<sort>\fR +Sort the records in the order specified. + .TP \fB\-p <partition>\fR, \fB\-\-partition=<partition>\fR Print information only about the specified partition. @@ -130,8 +134,24 @@ through "linux07". \fBpartition\fR The name of one partition. .TP -\fBstate\fR -A valid node state. Possible values include: ALLOC, ALLOCATED, COMP, +\fBsort\fR +Specification of the order in which records should be reported. +This uses the same field specifciation as the <output_format>. +Multiple sorts may be performed by listing multiple sort fields +separated by commas. +The field specifications may be preceeded by "+" or "-" for +assending (default) and desending order respectively. +For example, a sort value of "P,-m" requests that records by +printed in order of increasing partition name and within a +partition by decreasing memory size. +The default value of sort is "P,-t" (increasing partition name +then decreasing node state). +If the "--Node" option is selected, the default sort value is +"N" (increasing node name). +.TP +\fBstates\fR +A comma separated list of valid node state (case insensitive). +Possible values include: ALLOC, ALLOCATED, COMP, COMPLETING, DOWN, DRAIN, DRAINED, DRAINING, IDLE, UNK, and UNKNOWN. A "*" suffix may be appended to any of these states to search for nodes in the specified state which are not responding. @@ -140,39 +160,39 @@ responding or not. .SH "OUTPUT" .TP \fBAVAIL\fR -Partition state, \fBUP\fR or \fBDOWN\fR. +Partition state, \fBup\fR or \fBdown\fR. .TP \fBCPUS\fR Count of CPUs (processors) on these nodes. .TP \fBGROUPS\fR Resource allocations in this partition are restricted to the named groups. -\fBALL\fR indicates that all groups may use this partition. +\fBall\fR indicates that all groups may use this partition. .TP \fBJOB_SIZE\fR Minimum and maximum node count that can be allocated to any user job. A single number indicates the minimum and maximum node count are the same. -\fBINFINITE\fR is used to identify partitions without a maximum node count. +\fBinfinite\fR is used to identify partitions without a maximum node count. .TP -\fBMAX_TIME\fR +\fBTIMELIMIT\fR Maximum time limit for any user job in days:hours:minutes:seconds. -\fBINFINITE\fR is used to identify partitions without a job time limit. +\fBinfinite\fR is used to identify partitions without a job time limit. .TP \fBMEMORY\fR Size of real memory in megabytes on these nodes. .TP -\fBNODE_LIST\fR +\fBNODELIST\fR Names of nodes associated with this configuration/partition. .TP -\fB#NODES\fR +\fBNODES\fR Count of nodes with this particular configuration. .TP -\fB#NODES(A/T)\fR +\fBNODES(A/T)\fR Count of nodes with this particular configuration by node state in the form "available/total". .TP -\fB#NODES(A/I/O/T)\fR +\fBNODES(A/I/O/T)\fR Count of nodes with this particular configuration by node state in the form "available/idle/other/total". .TP @@ -182,13 +202,13 @@ Note that the suffix "*" identifies the default partition. .TP \fBROOT\fR Is the ability to allocate resources in this partition restricted to -user root, \fBYES\fR or \fBNO\fR. +user root, \fByes\fR or \fBno\fR. .TP \fBSHARE\fR Will jobs allocated resources in this partition share those resources. -\fBNO\fR indicates resources are never shared. -\fBFORCE\fR indicates resources are always available to be shared. -\fBYES\fR indicates resource may be shared or not per job's resource +\fBno\fR indicates resources are never shared. +\fBforce\fR indicates resources are always available to be shared. +\fByes\fR indicates resource may be shared or not per job's resource allocation. .TP \fBSTATE\fR @@ -209,6 +229,9 @@ SINFO_FORMAT .TP SINFO_PARTITION \fB\-p <partition>, \-\-partition=<partition>\fR +.TP +SINFO_SORT +\fB\-S <sort>, \-\-sort=<sort>\fR .SH "EXAMPLES" .eo @@ -216,15 +239,13 @@ Report basic node and partition configurations: .br > sinfo .br -PARTITION AVAIL MAX_TIME #NODES STATE NODE_LIST -.br ------------------------------------------------- +PARTITION AVAIL TIMELIMIT NODES STATE NODELIST .br -debug UP 30:00 8 IDLE adev[0-7] +batch up infinite 2 alloc adev[8-9] .br -batch* UP INFINITE 2 ALLOC adev[8-9] +batch up infinite 6 idle adev[10-15] .br -batch* UP INFINITE 6 IDLE adev[10-15] +debug* up 30:00 8 idle adev[0-7] .br .br @@ -232,13 +253,11 @@ Report partition summary information: .br > sinfo -s .br -PARTITION AVAIL MAX_TIME #NODES(A/I/O/T) NODE_LIST +PARTITION AVAIL TIMELIMIT NODES(A/I/O/T) NODELIST .br ---------------------------------------------------- +batch up infinite 2/6/0/8 adev[8-15] .br -debug UP 30:00 0/8/0/8 adev[0-7] -.br -batch* UP INFINITE 2/6/0/8 adev[8-15] +debug* up 30:00 0/8/0/8 adev[0-7] .br .br @@ -246,23 +265,19 @@ Report more complete information about the partition debug: .br > sinfo --long --partition=debug .br -PARTITION AVAIL MAX_TIME JOB_SIZE ROOT SHARE GROUPS #NODES STATE NODE_LIST -.br --------------------------------------------------------------------------- +PARTITION AVAIL TIMELIMIT JOB_SIZE ROOT SHARE GROUPS NODES STATE NODELIST .br -debug UP 30:00 8 NO NO ALL 8 IDLE dev[0-7] +debug* up 30:00 8 no no all 8 idle dev[0-7] .br .br Report only those nodes that are in state DRAINED: .br -> sinfo --state=DRAINED +> sinfo --state=drained .br -PARTITION AVAIL NODES STATE NODE_LIST +PARTITION AVAIL NODES TIMELIMIT STATE NODELIST .br --------------------------------------- -.br -debug UP 2 DRAIN adev[6-7] +debug* up 2 30:00 drain adev[6-7] .br .br @@ -270,19 +285,17 @@ Report node-oriented information with details and exact matches: .br > sinfo -Nel .br -NODE_LIST #NODES PARTITION STATE CPUS MEMORY TMP_DISK WEIGHT FEATURES -.br ------------------------------------------------------------------------ +NODELIST NODES PARTITION STATE CPUS MEMORY TMP_DISK WEIGHT FEATURES .br -adev[0-1] 2 debug IDLE 2 3448 38536 16 (null) +adev[0-1] 2 debug* idle 2 3448 38536 16 (null) .br -adev[2,4-7] 5 debug IDLE 2 3384 38536 16 (null) +adev[2,4-7] 5 debug* idle 2 3384 38536 16 (null) .br -adev3 1 debug IDLE 2 3394 38536 16 (null) +adev3 1 debug* idle 2 3394 38536 16 (null) .br -adev[8-9] 2 batch ALLOCATED 2 246 82306 16 (null) +adev[8-9] 2 batch allocated 2 246 82306 16 (null) .br -adev[10-15] 6 batch IDLE 2 246 82306 16 (null) +adev[10-15] 6 batch idle 2 246 82306 16 (null) .ec .SH "COPYING" diff --git a/src/sinfo/Makefile.am b/src/sinfo/Makefile.am index 8688e4edd61f911812428f660828a9576ccd67d2..d23ef52bf2642e1a8b426b84cad597194e2f4970 100644 --- a/src/sinfo/Makefile.am +++ b/src/sinfo/Makefile.am @@ -14,7 +14,7 @@ sinfo_LDADD = \ $(POPT_LIBS) noinst_HEADERS = sinfo.h print.h -sinfo_SOURCES = sinfo.c opts.c print.c +sinfo_SOURCES = sinfo.c opts.c print.c sort.c force: $(sinfo_LDADD) : force diff --git a/src/sinfo/opts.c b/src/sinfo/opts.c index 7de226e3952e86ee80f816dd84bdca18d08d1f2a..b168e0e60bb8dad48b9aec88339e762535c4cf5f 100644 --- a/src/sinfo/opts.c +++ b/src/sinfo/opts.c @@ -47,16 +47,18 @@ #define OPT_VERBOSE 0x07 #define OPT_ITERATE 0x08 #define OPT_EXACT 0x09 -#define OPT_LONG 0x0a -#define OPT_SHORT 0x0b +#define OPT_LONG 0x0a +#define OPT_SHORT 0x0b #define OPT_NO_HEAD 0x0c #define OPT_VERSION 0x0d - +#define OPT_SORT 0x0e /* FUNCTIONS */ +static List _build_state_list( char* str ); +static List _build_all_states_list( void ); static char *_get_prefix(char *token); static int _parse_format( char* ); -static int _parse_state(char *str, enum node_states *states); +static int _parse_state(char *str, uint16_t *states); static void _parse_token( char *token, char *field, int *field_size, bool *right_justify, char **suffix); static void _print_options( void ); @@ -74,34 +76,39 @@ int parse_command_line(int argc, char *argv[]) int curr_opt; int rc = 0; char *env_val = NULL; - static char *temp_state = NULL; /* Declare the Options */ static const struct poptOption options[] = { {"exact", 'e', POPT_ARG_NONE, ¶ms.exact_match, OPT_EXACT, - "group nodes only on exact match of configuration",NULL}, + "group nodes only on exact match of configuration", + NULL}, {"iterate", 'i', POPT_ARG_INT, ¶ms.iterate, - OPT_ITERATE, "specify an interation period", "seconds"}, - {"state", 't', POPT_ARG_STRING, &temp_state, - OPT_NODE_STATE, "specify the what state of nodes to view", - "node_state"}, + OPT_ITERATE, "specify an interation period", + "seconds"}, + {"states", 't', POPT_ARG_STRING, ¶ms.states, + OPT_NODE_STATE, + "specify the what states of nodes to view", + "node_state"}, {"partition", 'p', POPT_ARG_STRING, ¶ms.partition, - OPT_PARTITION, "report on specific partition", "PARTITION"}, + OPT_PARTITION, "report on specific partition", + "PARTITION"}, {"nodes", 'n', POPT_ARG_STRING, ¶ms.nodes, OPT_NODES, - "report on specific node(s)", "NODES"}, + "report on specific node(s)", "NODES"}, {"Node", 'N', POPT_ARG_NONE, ¶ms.node_flag, OPT_NODE, - "Node-centric format", NULL}, + "Node-centric format", NULL}, {"long", 'l', POPT_ARG_NONE, ¶ms.long_output, - OPT_LONG, "long output - displays more information", - NULL}, + OPT_LONG, "long output - displays more information", + NULL}, + {"sort", 'S', POPT_ARG_STRING, ¶ms.sort, OPT_SORT, + "comma seperated list of fields to sort on", "fields"}, {"summarize", 's', POPT_ARG_NONE, ¶ms.summarize, - OPT_SHORT,"report state summary only", NULL}, + OPT_SHORT,"report state summary only", NULL}, {"verbose", 'v', POPT_ARG_NONE, ¶ms.verbose, - OPT_VERBOSE, "verbosity level", "level"}, + OPT_VERBOSE, "verbosity level", "level"}, {"noheader", 'h', POPT_ARG_NONE, ¶ms.no_header, - OPT_NO_HEAD, "no headers on output", NULL}, + OPT_NO_HEAD, "no headers on output", NULL}, {"format", 'o', POPT_ARG_STRING, ¶ms.format, OPT_FORMAT, - "format specification", "format"}, + "format specification", "format"}, {"version", 'V', POPT_ARG_NONE, 0, OPT_VERSION, "output version information and exit", NULL}, POPT_AUTOHELP @@ -118,14 +125,7 @@ int parse_command_line(int argc, char *argv[]) switch ( curr_opt ) { case OPT_NODE_STATE: - params.state_flag = true; - if (_parse_state(temp_state, ¶ms.state) - == SLURM_ERROR) { - fprintf(stderr, - "%s: %s is invalid node state\n", - argv[0], temp_state); - exit(1); - } + params.state_list = _build_state_list( params.states ); break; case OPT_VERSION: _print_version(); @@ -146,28 +146,32 @@ int parse_command_line(int argc, char *argv[]) } if ( ( params.format == NULL ) && - ( env_val = getenv("SINFO_FORMAT") ) ) + ( env_val = getenv("SINFO_FORMAT") ) ) params.format = xstrdup(env_val); if ( ( params.partition == NULL ) && - ( env_val = getenv("SINFO_PARTITION") ) ) + ( env_val = getenv("SINFO_PARTITION") ) ) params.partition = xstrdup(env_val); + if ( ( params.partition == NULL ) && + ( env_val = getenv("SINFO_SORT") ) ) + params.sort = xstrdup(env_val); + if ( params.format == NULL ) { if ( params.summarize ) - params.format = "%9P %5a %.8l %15F %N"; + params.format = "%9P %5a %.9l %15F %N"; else if ( params.node_flag ) { params.node_field_flag = true; /* compute size later */ if ( params.long_output ) { - params.format = "%N %.6D %9P %11T %.4c %.6m %.8d %.6w %8f"; + params.format = "%N %.5D %9P %11T %.4c %.6m %.8d %.6w %8f"; } else { - params.format = "%N %.6D %9P %6t"; + params.format = "%N %.5D %9P %6t"; } } else { if ( params.long_output ) - params.format = "%9P %5a %.8l %.8s %4r %5h %10g %.6D %11T %N"; + params.format = "%9P %5a %.9l %.8s %4r %5h %10g %.5D %11T %N"; else - params.format = "%9P %5a %.8l %.6D %6t %N"; + params.format = "%9P %5a %.9l %.5D %6t %N"; } } _parse_format( params.format ); @@ -177,14 +181,66 @@ int parse_command_line(int argc, char *argv[]) return rc; } +/* + * _build_state_list - build a list of job states + * IN str - comma separated list of job states + * RET List of enum job_states values + */ +static List +_build_state_list( char* str ) +{ + List my_list; + char *state, *tmp_char, *my_state_list; + uint16_t *state_id; + + if ( str == NULL) + return NULL; + if ( strcasecmp( str, "all" ) == 0 ) + return _build_all_states_list (); + + my_list = list_create( NULL ); + my_state_list = xstrdup( str ); + state = strtok_r( my_state_list, ",", &tmp_char ); + while (state) + { + state_id = xmalloc( sizeof( uint16_t ) ); + if ( _parse_state( state, state_id ) != SLURM_SUCCESS ) + exit( 1 ); + list_append( my_list, state_id ); + state = strtok_r( NULL, ",", &tmp_char ); + } + xfree( my_state_list ); + return my_list; +} + +/* + * _build_all_states_list - build a list containing all possible job states + * RET List of enum job_states values + */ +static List +_build_all_states_list( void ) +{ + List my_list; + int i; + uint16_t *state_id; + + my_list = list_create( NULL ); + for (i = 0; i<NODE_STATE_END; i++) { + state_id = xmalloc( sizeof( uint16_t ) ); + *state_id = (uint16_t) i; + list_append( my_list, state_id ); + } + return my_list; +} + /* * _parse_state - convert node state name string to numeric value * IN str - state name - * OUT states - enum node_states value corresponding to str + * OUT states - node_state value corresponding to str * RET 0 or error code */ static int -_parse_state( char* str, enum node_states* states ) +_parse_state( char* str, uint16_t* states ) { int i; char *state_names; @@ -230,10 +286,7 @@ _parse_format( char* format ) if ((prefix = _get_prefix(format))) format_add_prefix( params.format_list, 0, 0, prefix); - field_size = strlen( format ); - tmp_format = xmalloc( field_size + 1 ); - strcpy( tmp_format, format ); - + tmp_format = xstrdup( format ); token = strtok_r( tmp_format, "%", &tmp_char); if (token && (format[0] != '%')) /* toss header */ token = strtok_r( NULL, "%", &tmp_char ); @@ -408,13 +461,6 @@ _parse_token( char *token, char *field, int *field_size, bool *right_justify, /* print the parameters specified */ void _print_options( void ) { - char *node_state; - - if (params.state_flag) - node_state = node_state_string(params.state); - else - node_state = "N/A"; - printf("-----------------------------\n"); printf("exact = %d\n", params.exact_match); printf("format = %s\n", params.format); @@ -424,18 +470,19 @@ void _print_options( void ) printf("node_field = %s\n", params.node_field_flag ? "true" : "false"); printf("node_format = %s\n", params.node_flag ? "true" : "false"); - printf("nodes = %s\n", params.nodes ? params.nodes : "N/A"); + printf("nodes = %s\n", params.nodes ? params.nodes : "n/a"); printf("partition = %s\n", params.partition ? - params.partition: "N/A"); - printf("state = %s\n", node_state); + params.partition: "n/a"); + printf("states = %s\n", params.states); + printf("sort = %s\n", params.sort); printf("summarize = %s\n", params.summarize ? "true" : "false"); printf("verbose = %d\n", params.verbose); printf("-----------------------------\n\n"); } + static void _print_version(void) { printf("%s %s\n", PACKAGE, SLURM_VERSION); } - diff --git a/src/sinfo/print.c b/src/sinfo/print.c index 1f4e608ef687df8181508ab9a2ece5a3b47d69a9..63739392572ccf3667eeea8e7bd7742d2cb525d7 100644 --- a/src/sinfo/print.c +++ b/src/sinfo/print.c @@ -24,6 +24,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. \*****************************************************************************/ +#include <ctype.h> #include <time.h> #include <stdio.h> #include <string.h> @@ -39,11 +40,12 @@ #define MIN_NODE_FIELD_SIZE 9 -static int _build_min_max_string(char *buffer, int buf_size, int min, - int max, bool range); -static int _print_secs(long time, int width, bool right, bool cut_output); -static int _print_str(char *str, int width, bool right, bool cut_output); -static void _set_node_field_size(List sinfo_list); +static int _build_min_max_string(char *buffer, int buf_size, int min, + int max, bool range); +static int _print_secs(long time, int width, bool right, bool cut_output); +static int _print_str(char *str, int width, bool right, bool cut_output); +static void _set_node_field_size(List sinfo_list); +static char *_str_tolower(char *upper_str); /***************************************************************************** * Global Print Functions @@ -56,7 +58,7 @@ void print_date(void) printf("%s", ctime(&now)); } -int print_sinfo_list(List sinfo_list, List format) +int print_sinfo_list(List sinfo_list) { ListIterator i = list_iterator_create(sinfo_list); sinfo_data_t *current; @@ -65,20 +67,19 @@ int print_sinfo_list(List sinfo_list, List format) _set_node_field_size(sinfo_list); if (!params.no_header) - print_sinfo_entry(NULL, format); + print_sinfo_entry(NULL); while ((current = list_next(i)) != NULL) - print_sinfo_entry(current, format); + print_sinfo_entry(current); list_iterator_destroy(i); return SLURM_SUCCESS; } -int print_sinfo_entry(sinfo_data_t *sinfo_data , List format) +int print_sinfo_entry(sinfo_data_t *sinfo_data) { - ListIterator i = list_iterator_create(format); + ListIterator i = list_iterator_create(params.format_list); sinfo_format_t *current; - int total_width = 0, inx; while ((current = (sinfo_format_t *) list_next(i)) != NULL) { if (current-> @@ -86,23 +87,10 @@ int print_sinfo_entry(sinfo_data_t *sinfo_data , List format) current->right_justify, current->suffix) != SLURM_SUCCESS) return SLURM_ERROR; - if (current->width) - total_width += (current->width + 1); - else if ((current->function == _print_node_list) && - (params.node_field_flag)) - total_width += (params.node_field_size + 1); - else - total_width += 10; } list_iterator_destroy(i); printf("\n"); - if (sinfo_data == NULL) { - /* one-origin for no trailing space */ - for (inx=1; inx<total_width; inx++) - printf("-"); - printf("\n"); - } return SLURM_SUCCESS; } @@ -175,7 +163,7 @@ _build_min_max_string(char *buffer, int buf_size, int min, int max, bool range) return snprintf(buffer, buf_size, "%d", max); else if (range) { if (max == INFINITE) - return snprintf(buffer, buf_size, "%d-INFINITE", min); + return snprintf(buffer, buf_size, "%d-infinite", min); else return snprintf(buffer, buf_size, "%d-%d", min, max); } else @@ -216,6 +204,22 @@ static void _set_node_field_size(List sinfo_list) params.node_field_size = max_width; } +/* + * _str_tolower - convert string to all lower case + * upper_str IN - upper case input string + * RET - lower case version of upper_str, caller must be xfree + */ +static char *_str_tolower(char *upper_str) +{ + int i = strlen(upper_str) + 1; + char *lower_str = xmalloc(i); + + for (i=0; upper_str[i]; i++) + lower_str[i] = tolower((int) upper_str[i]); + + return lower_str; +} + /***************************************************************************** * Sinfo Print Functions *****************************************************************************/ @@ -225,11 +229,11 @@ int _print_avail(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else if (sinfo_data->part_info->state_up) - _print_str("UP", width, right_justify, true); + _print_str("up", width, right_justify, true); else - _print_str("DOWN", width, right_justify, true); + _print_str("down", width, right_justify, true); } else _print_str("AVAIL", width, right_justify, true); @@ -290,12 +294,12 @@ int _print_groups(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else if (sinfo_data->part_info->allow_groups) _print_str(sinfo_data->part_info->allow_groups, width, right_justify, true); else - _print_str("ALL", width, right_justify, true); + _print_str("all", width, right_justify, true); } else _print_str("GROUPS", width, right_justify, true); @@ -333,7 +337,7 @@ int _print_node_list(sinfo_data_t * sinfo_data, int width, sizeof(tmp), tmp); _print_str(tmp, width, right_justify, true); } else - _print_str("NODE_LIST", width, right_justify, true); + _print_str("NODELIST", width, right_justify, true); if (suffix) printf("%s", suffix); @@ -348,7 +352,7 @@ int _print_nodes_t(sinfo_data_t * sinfo_data, int width, snprintf(id, FORMAT_STRING_SIZE, "%u", sinfo_data->nodes_tot); _print_str(id, width, right_justify, true); } else - _print_str("#NODES", width, right_justify, true); + _print_str("NODES", width, right_justify, true); if (suffix) printf("%s", suffix); @@ -364,7 +368,7 @@ int _print_nodes_at(sinfo_data_t * sinfo_data, int width, sinfo_data->nodes_alloc, sinfo_data->nodes_tot); _print_str(id, width, right_justify, true); } else - _print_str("#NODES(A/T)", width, right_justify, true); + _print_str("NODES(A/T)", width, right_justify, true); if (suffix) printf("%s", suffix); @@ -381,7 +385,7 @@ int _print_nodes_aiot(sinfo_data_t * sinfo_data, int width, sinfo_data->nodes_other, sinfo_data->nodes_tot); _print_str(id, width, right_justify, true); } else - _print_str("#NODES(A/I/O/T)", width, right_justify, true); + _print_str("NODES(A/I/O/T)", width, right_justify, true); if (suffix) printf("%s", suffix); @@ -393,7 +397,7 @@ int _print_partition(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else { char *tmp; tmp = xstrdup(sinfo_data->part_info->name); @@ -423,11 +427,11 @@ int _print_root(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else if (sinfo_data->part_info->root_only) - _print_str("YES", width, right_justify, true); + _print_str("yes", width, right_justify, true); else - _print_str("NO", width, right_justify, true); + _print_str("no", width, right_justify, true); } else _print_str("ROOT", width, right_justify, true); @@ -441,13 +445,13 @@ int _print_share(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else if (sinfo_data->part_info->shared > 1) - _print_str("FORCE", width, right_justify, true); + _print_str("force", width, right_justify, true); else if (sinfo_data->part_info->shared) - _print_str("YES", width, right_justify, true); + _print_str("yes", width, right_justify, true); else - _print_str("NO", width, right_justify, true); + _print_str("no", width, right_justify, true); } else _print_str("SHARE", width, right_justify, true); @@ -462,8 +466,11 @@ int _print_size(sinfo_data_t * sinfo_data, int width, char id[FORMAT_STRING_SIZE]; if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else { + if ((sinfo_data->part_info->min_nodes < 1) && + (sinfo_data->part_info->max_nodes > 0)) + sinfo_data->part_info->min_nodes = 1; _build_min_max_string(id, FORMAT_STRING_SIZE, sinfo_data->part_info->min_nodes, sinfo_data->part_info->max_nodes, @@ -481,10 +488,15 @@ int _print_size(sinfo_data_t * sinfo_data, int width, int _print_state_compact(sinfo_data_t * sinfo_data, int width, bool right_justify, char *suffix) { - if (sinfo_data) { - _print_str(node_state_string_compact(sinfo_data->node_state), - width, right_justify, true); - } else + if (sinfo_data && sinfo_data->nodes_tot) { + char *upper_state = node_state_string_compact( + sinfo_data->node_state); + char *lower_state = _str_tolower(upper_state); + _print_str(lower_state, width, right_justify, true); + xfree(lower_state); + } else if (sinfo_data) + _print_str("n/a", width, right_justify, true); + else _print_str("STATE", width, right_justify, true); if (suffix) @@ -495,10 +507,14 @@ int _print_state_compact(sinfo_data_t * sinfo_data, int width, int _print_state_long(sinfo_data_t * sinfo_data, int width, bool right_justify, char *suffix) { - if (sinfo_data) { - _print_str(node_state_string(sinfo_data->node_state), - width, right_justify, true); - } else + if (sinfo_data && sinfo_data->nodes_tot) { + char *upper_state = node_state_string(sinfo_data->node_state); + char *lower_state = _str_tolower(upper_state); + _print_str(lower_state, width, right_justify, true); + xfree(lower_state); + } else if (sinfo_data) + _print_str("n/a", width, right_justify, true); + else _print_str("STATE", width, right_justify, true); if (suffix) @@ -512,14 +528,14 @@ int _print_time(sinfo_data_t * sinfo_data, int width, { if (sinfo_data) { if (sinfo_data->part_info == NULL) - _print_str("N/A", width, right_justify, true); + _print_str("n/a", width, right_justify, true); else if (sinfo_data->part_info->max_time == INFINITE) - _print_str("INFINITE", width, right_justify, true); + _print_str("infinite", width, right_justify, true); else _print_secs((sinfo_data->part_info->max_time * 60L), width, right_justify, true); } else - _print_str("MAX_TIME", width, right_justify, true); + _print_str("TIMELIMIT", width, right_justify, true); if (suffix) printf("%s", suffix); diff --git a/src/sinfo/print.h b/src/sinfo/print.h index d63231fd4af3171b20292d77d3f2e1fea536b8e8..b36d3f25b051f928c73563dafcbd5e0f4eda0a37 100644 --- a/src/sinfo/print.h +++ b/src/sinfo/print.h @@ -50,7 +50,10 @@ typedef struct sinfo_format { int format_add_function(List list, int width, bool right_justify, char * suffix, int (*function) (sinfo_data_t *, int, bool, char *)); + void print_date(void); +int print_sinfo_entry(sinfo_data_t *sinfo_data); +int print_sinfo_list(List sinfo_list); #define format_add_avail(list,wid,right,suffix) \ format_add_function(list,wid,right,suffix,_print_avail) diff --git a/src/sinfo/sinfo.c b/src/sinfo/sinfo.c index 1dadf5f1f51581c5b525d24754410d3b9e902a8f..e3c05713bfb4e0ef7360e60b07b860a72f51187d 100644 --- a/src/sinfo/sinfo.c +++ b/src/sinfo/sinfo.c @@ -44,22 +44,24 @@ static void _sinfo_list_delete(void *data); static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt); static partition_info_t *_find_part(char *part_name, partition_info_msg_t *partition_msg); +static bool _match_node_data(sinfo_data_t *sinfo_ptr, + node_info_t *node_ptr); +static bool _match_part_data(sinfo_data_t *sinfo_ptr, + partition_info_t* part_ptr); static int _query_server(partition_info_msg_t ** part_pptr, node_info_msg_t ** node_pptr); -static int _part_order (void *data1, void *data2); -static void _sort_sinfo_data(List sinfo_list); static int _strcmp(char *data1, char *data2); static void _swap_char(char **from, char **to); static void _swap_node_rec(node_info_t *from_node, node_info_t *to_node); -static void _update_sinfo(sinfo_data_t *sinfo_ptr, partition_info_t* part_ptr, - node_info_t *node_ptr); +static void _update_sinfo(sinfo_data_t *sinfo_ptr, + partition_info_t* part_ptr, node_info_t *node_ptr); int main(int argc, char *argv[]) { log_options_t opts = LOG_OPTS_STDERR_ONLY; partition_info_msg_t *partition_msg = NULL; node_info_msg_t *node_msg = NULL; - List sinfo_list; + List sinfo_list = NULL; int node_rec_cnt = 0; log_init("sinfo", opts, SYSLOG_FACILITY_DAEMON, NULL); @@ -77,8 +79,8 @@ int main(int argc, char *argv[]) sinfo_list = list_create(_sinfo_list_delete); _build_sinfo_data(sinfo_list, partition_msg, node_msg, node_rec_cnt); - _sort_sinfo_data(sinfo_list); - print_sinfo_list(sinfo_list, params.format_list); + sort_sinfo_list(sinfo_list); + print_sinfo_list(sinfo_list); if (params.iterate) { list_destroy(sinfo_list); @@ -123,7 +125,6 @@ _query_server(partition_info_msg_t ** part_pptr, return error_code; } - old_part_ptr = new_part_ptr; *part_pptr = new_part_ptr; @@ -161,12 +162,14 @@ static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt) if (((params.nodes == NULL) && (params.partition == NULL) && - (!params.state_flag)) || + (params.state_list == NULL)) || params.summarize) { + params.filtering = false; /* Nothing to filter out */ *node_rec_cnt = node_msg->record_count; return; } + params.filtering = true; if (params.nodes) hosts = hostlist_create(params.nodes); @@ -179,12 +182,26 @@ static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt) (node_msg->node_array[i].partition, params.partition)) continue; - if (params.state_flag && - (node_msg->node_array[i].node_state != - params.state) && - ((node_msg->node_array[i].node_state & - (~NODE_STATE_NO_RESPOND)) != params.state)) - continue; + if (params.state_list) { + int *node_state; + bool match = false; + ListIterator iterator; + iterator = list_iterator_create(params.state_list); + while ((node_state = list_next(iterator))) { + if ((node_msg->node_array[i].node_state == + *node_state) || + ((node_msg->node_array[i].node_state & + (~NODE_STATE_NO_RESPOND)) == + *node_state)) { + match = true; + break; + } + } + list_iterator_destroy(iterator); + if (!match) + continue; + } + _swap_node_rec(&node_msg->node_array[i], &node_msg->node_array[new_rec_cnt]); new_rec_cnt++; @@ -238,7 +255,13 @@ static int _build_sinfo_data(List sinfo_list, ListIterator i; int j; - /* remove any existing sinfo_list entries */ + /* by default every partition is shown, even if no nodes */ + if ((!params.filtering) && (!params.node_flag)) { + for (j=0; j<partition_msg->record_count; j++) { + part_ptr = partition_msg->partition_array + j; + _create_sinfo(sinfo_list, part_ptr, NULL); + } + } /* make sinfo_list entries for each node */ for (j=0; j<node_cnt; j++) { @@ -249,42 +272,11 @@ static int _build_sinfo_data(List sinfo_list, /* test if node can be added to existing sinfo_data entry */ while ((sinfo_ptr = list_next(i))) { - if (params.match_flags.avail_flag && - (part_ptr->state_up != sinfo_ptr->part_info->state_up)) - continue; - if (params.match_flags.features_flag && - (_strcmp(node_ptr->features, sinfo_ptr->features))) - continue; - - if (params.match_flags.groups_flag && - (_strcmp(part_ptr->allow_groups, - sinfo_ptr->part_info->allow_groups))) - continue; - if (params.match_flags.job_size_flag && - (part_ptr->min_nodes != - sinfo_ptr->part_info->min_nodes)) - continue; - if (params.match_flags.job_size_flag && - (part_ptr->max_nodes != - sinfo_ptr->part_info->max_nodes)) - continue; - if (params.match_flags.max_time_flag && - (part_ptr->max_time != sinfo_ptr->part_info->max_time)) - continue; - if (params.match_flags.partition_flag && - (_strcmp(part_ptr->name, sinfo_ptr->part_info->name))) - continue; - if (params.match_flags.root_flag && - (part_ptr->root_only != - sinfo_ptr->part_info->root_only)) - continue; - if (params.match_flags.share_flag && - (part_ptr->shared != - sinfo_ptr->part_info->shared)) - continue; - if (params.match_flags.state_flag && - (node_ptr->node_state != sinfo_ptr->node_state)) - continue; + if (!_match_part_data(sinfo_ptr, part_ptr)) + continue; + if (sinfo_ptr->nodes_tot && + (!_match_node_data(sinfo_ptr, node_ptr))) + continue; /* This node has the same configuration as this * sinfo_data, just add to this record */ @@ -301,9 +293,112 @@ static int _build_sinfo_data(List sinfo_list, return SLURM_SUCCESS; } +static bool _match_node_data(sinfo_data_t *sinfo_ptr, + node_info_t *node_ptr) +{ + if (sinfo_ptr->nodes && + params.match_flags.features_flag && + (_strcmp(node_ptr->features, sinfo_ptr->features))) + return false; + + if (params.match_flags.state_flag && + (node_ptr->node_state != sinfo_ptr->node_state)) + return false; + + /* If no need to exactly match sizes, just return here + * otherwise check cpu count, memory, disk, etc. */ + if (!params.exact_match) + return true; + if (node_ptr->cpus != sinfo_ptr->min_cpus) + return false; + if (node_ptr->tmp_disk != sinfo_ptr->min_disk) + return false; + if (node_ptr->real_memory != sinfo_ptr->min_mem) + return false; + if (node_ptr->weight != sinfo_ptr->min_weight) + return false; + + return true; +} + +static bool _match_part_data(sinfo_data_t *sinfo_ptr, + partition_info_t* part_ptr) +{ + if (part_ptr == sinfo_ptr->part_info) /* identical partition */ + return true; + + if (params.match_flags.avail_flag && + (part_ptr->state_up != sinfo_ptr->part_info->state_up)) + return false; + + if (params.match_flags.groups_flag && + (_strcmp(part_ptr->allow_groups, + sinfo_ptr->part_info->allow_groups))) + return false; + + if (params.match_flags.job_size_flag && + (part_ptr->min_nodes != sinfo_ptr->part_info->min_nodes)) + return false; + + if (params.match_flags.job_size_flag && + (part_ptr->max_nodes != sinfo_ptr->part_info->max_nodes)) + return false; + + if (params.match_flags.max_time_flag && + (part_ptr->max_time != sinfo_ptr->part_info->max_time)) + return false; + + if (params.match_flags.partition_flag && + (_strcmp(part_ptr->name, sinfo_ptr->part_info->name))) + return false; + + if (params.match_flags.root_flag && + (part_ptr->root_only != sinfo_ptr->part_info->root_only)) + return false; + + if (params.match_flags.share_flag && + (part_ptr->shared != sinfo_ptr->part_info->shared)) + return false; + + return true; +} + static void _update_sinfo(sinfo_data_t *sinfo_ptr, partition_info_t* part_ptr, node_info_t *node_ptr) { + if (sinfo_ptr->nodes_tot == 0) { /* first node added */ + sinfo_ptr->node_state = node_ptr->node_state; + sinfo_ptr->features = node_ptr->features; + sinfo_ptr->min_cpus = node_ptr->cpus; + sinfo_ptr->max_cpus = node_ptr->cpus; + sinfo_ptr->min_disk = node_ptr->tmp_disk; + sinfo_ptr->max_disk = node_ptr->tmp_disk; + sinfo_ptr->min_mem = node_ptr->real_memory; + sinfo_ptr->max_mem = node_ptr->real_memory; + sinfo_ptr->min_weight = node_ptr->weight; + sinfo_ptr->max_weight = node_ptr->weight; + } else { + if (sinfo_ptr->min_cpus > node_ptr->cpus) + sinfo_ptr->min_cpus = node_ptr->cpus; + if (sinfo_ptr->max_cpus < node_ptr->cpus) + sinfo_ptr->max_cpus = node_ptr->cpus; + + if (sinfo_ptr->min_disk > node_ptr->tmp_disk) + sinfo_ptr->min_disk = node_ptr->tmp_disk; + if (sinfo_ptr->max_disk < node_ptr->tmp_disk) + sinfo_ptr->max_disk = node_ptr->tmp_disk; + + if (sinfo_ptr->min_mem > node_ptr->real_memory) + sinfo_ptr->min_mem = node_ptr->real_memory; + if (sinfo_ptr->max_mem < node_ptr->real_memory) + sinfo_ptr->max_mem = node_ptr->real_memory; + + if (sinfo_ptr->min_weight> node_ptr->weight) + sinfo_ptr->min_weight = node_ptr->weight; + if (sinfo_ptr->max_weight < node_ptr->weight) + sinfo_ptr->max_weight = node_ptr->weight; + } + if (node_ptr->node_state == NODE_STATE_ALLOCATED) sinfo_ptr->nodes_alloc++; else if (node_ptr->node_state == NODE_STATE_IDLE) @@ -312,26 +407,6 @@ static void _update_sinfo(sinfo_data_t *sinfo_ptr, partition_info_t* part_ptr, sinfo_ptr->nodes_other++; sinfo_ptr->nodes_tot++; - if (sinfo_ptr->min_cpus > node_ptr->cpus) - sinfo_ptr->min_cpus = node_ptr->cpus; - if (sinfo_ptr->max_cpus < node_ptr->cpus) - sinfo_ptr->max_cpus = node_ptr->cpus; - - if (sinfo_ptr->min_disk > node_ptr->tmp_disk) - sinfo_ptr->min_disk = node_ptr->tmp_disk; - if (sinfo_ptr->max_disk < node_ptr->tmp_disk) - sinfo_ptr->max_disk = node_ptr->tmp_disk; - - if (sinfo_ptr->min_mem > node_ptr->real_memory) - sinfo_ptr->min_mem = node_ptr->real_memory; - if (sinfo_ptr->max_mem < node_ptr->real_memory) - sinfo_ptr->max_mem = node_ptr->real_memory; - - if (sinfo_ptr->min_weight> node_ptr->weight) - sinfo_ptr->min_weight = node_ptr->weight; - if (sinfo_ptr->max_weight < node_ptr->weight) - sinfo_ptr->max_weight = node_ptr->weight; - hostlist_push(sinfo_ptr->nodes, node_ptr->name); } @@ -343,31 +418,36 @@ static void _create_sinfo(List sinfo_list, partition_info_t* part_ptr, /* create an entry */ sinfo_ptr = xmalloc(sizeof(sinfo_data_t)); - sinfo_ptr->node_state = node_ptr->node_state; - if (node_ptr->node_state == NODE_STATE_ALLOCATED) - sinfo_ptr->nodes_alloc++; - else if (node_ptr->node_state == NODE_STATE_IDLE) - sinfo_ptr->nodes_idle++; - else - sinfo_ptr->nodes_other++; - sinfo_ptr->nodes_tot++; + sinfo_ptr->part_info = part_ptr; - sinfo_ptr->min_cpus = node_ptr->cpus; - sinfo_ptr->max_cpus = node_ptr->cpus; + if (node_ptr) { + sinfo_ptr->node_state = node_ptr->node_state; + if (node_ptr->node_state == NODE_STATE_ALLOCATED) + sinfo_ptr->nodes_alloc++; + else if (node_ptr->node_state == NODE_STATE_IDLE) + sinfo_ptr->nodes_idle++; + else + sinfo_ptr->nodes_other++; + sinfo_ptr->nodes_tot++; - sinfo_ptr->min_disk = node_ptr->tmp_disk; - sinfo_ptr->max_disk = node_ptr->tmp_disk; + sinfo_ptr->min_cpus = node_ptr->cpus; + sinfo_ptr->max_cpus = node_ptr->cpus; - sinfo_ptr->min_mem = node_ptr->real_memory; - sinfo_ptr->max_mem = node_ptr->real_memory; + sinfo_ptr->min_disk = node_ptr->tmp_disk; + sinfo_ptr->max_disk = node_ptr->tmp_disk; - sinfo_ptr->min_weight = node_ptr->weight; - sinfo_ptr->max_weight = node_ptr->weight; + sinfo_ptr->min_mem = node_ptr->real_memory; + sinfo_ptr->max_mem = node_ptr->real_memory; - sinfo_ptr->features = node_ptr->features; - sinfo_ptr->part_info = part_ptr; + sinfo_ptr->min_weight = node_ptr->weight; + sinfo_ptr->max_weight = node_ptr->weight; - sinfo_ptr->nodes = hostlist_create(node_ptr->name); + sinfo_ptr->features = node_ptr->features; + + sinfo_ptr->nodes = hostlist_create(node_ptr->name); + } else { + sinfo_ptr->nodes = hostlist_create(""); + } list_append(sinfo_list, sinfo_ptr); } @@ -378,34 +458,19 @@ static partition_info_t *_find_part(char *part_name, { int i; for (i=0; i<partition_msg->record_count; i++) { - if (_strcmp(part_name, partition_msg->partition_array[i].name)) + if (_strcmp(part_name, + partition_msg->partition_array[i].name)) continue; return &(partition_msg->partition_array[i]); } return NULL; } -static void _sort_sinfo_data(List sinfo_list) -{ - if (params.node_field_flag) /* already in node order */ - return; - - /* sort list in partition order */ - list_sort(sinfo_list, _part_order); -} -static int _part_order (void *data1, void *data2) -{ - sinfo_data_t *sinfo_ptr1 = data1; - sinfo_data_t *sinfo_ptr2 = data2; - - return _strcmp(sinfo_ptr1->part_info->name, - sinfo_ptr2->part_info->name); -} - static void _sinfo_list_delete(void *data) { sinfo_data_t *sinfo_ptr = data; + xfree(sinfo_ptr->features); hostlist_destroy(sinfo_ptr->nodes); xfree(sinfo_ptr); } diff --git a/src/sinfo/sinfo.h b/src/sinfo/sinfo.h index e0cf35751a21642d75c68b5595774249fe8dc3a9..97ba870e31bd7bda8c770fb0e9a528925e787a06 100644 --- a/src/sinfo/sinfo.h +++ b/src/sinfo/sinfo.h @@ -98,33 +98,33 @@ struct sinfo_match_flags { /* Input parameters */ struct sinfo_parameters { bool exact_match; + bool filtering; bool long_output; bool line_wrap; bool no_header; bool node_field_flag; bool node_flag; - bool state_flag; bool summarize; struct sinfo_match_flags match_flags; char* format; char* nodes; char* partition; + char* sort; + char* states; int iterate; int node_field_size; - enum node_states state; int verbose; List format_list; + List state_list; }; extern struct sinfo_parameters params; int parse_command_line( int argc, char* argv[] ); -int parse_state( char* str, enum job_states* states ); -void print_date(void); -int print_sinfo_entry(sinfo_data_t *sinfo_data , List format); -int print_sinfo_list(List sinfo_list, List format); +int parse_state( char* str, uint16_t* states ); +void sort_sinfo_list( List sinfo_list ); #endif diff --git a/src/sinfo/sort.c b/src/sinfo/sort.c new file mode 100644 index 0000000000000000000000000000000000000000..644a7fcdebf740c77baabe0dc9808744d5574941 --- /dev/null +++ b/src/sinfo/sort.c @@ -0,0 +1,408 @@ +/*****************************************************************************\ + * sort.c - sinfo sorting functions + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Joey Ekstrom <ekstrom1@llnl.gov>, + * Moe Jette <jette1@llnl.gov>, et. al. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * SLURM is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#include <ctype.h> +#include "src/common/xstring.h" +#include "src/sinfo/sinfo.h" +#include "src/squeue/print.h" + +/* If you want "linux12" to sort before "linux2", then set PURE_ALPHA_SORT */ +#define PURE_ALPHA_SORT 0 + +static bool reverse_order; + +static int _sort_by_avail(void *void1, void *void2); +static int _sort_by_cpus(void *void1, void *void2); +static int _sort_by_disk(void *void1, void *void2); +static int _sort_by_features(void *void1, void *void2); +static int _sort_by_groups(void *void1, void *void2); +static int _sort_by_job_size(void *void1, void *void2); +static int _sort_by_max_time(void *void1, void *void2); +static int _sort_by_memory(void *void1, void *void2); +static int _sort_by_node_list(void *void1, void *void2); +static int _sort_by_nodes_at(void *void1, void *void2); +static int _sort_by_nodes(void *void1, void *void2); +static int _sort_by_partition(void *void1, void *void2); +static int _sort_by_root(void *void1, void *void2); +static int _sort_by_share(void *void1, void *void2); +static int _sort_by_state(void *void1, void *void2); +static int _sort_by_weight(void *void1, void *void2); + +/***************************************************************************** + * Global Sort Function + *****************************************************************************/ +void sort_sinfo_list(List sinfo_list) +{ + int i; + + if (params.sort == NULL) { + if (params.node_flag) + params.sort = xstrdup("N"); + else + params.sort = xstrdup("P,-t"); + } + + for (i=(strlen(params.sort)-1); i >= 0; i--) { + reverse_order = false; + if ((params.sort[i] == ',') || + (params.sort[i] == '+') || params.sort[i] == '-') + continue; + if ((i > 0) && (params.sort[i-1] == '-')) + reverse_order = true; + if (params.sort[i] == 'a') + list_sort(sinfo_list, _sort_by_avail); + else if (params.sort[i] == 'A') + list_sort(sinfo_list, _sort_by_nodes_at); + else if (params.sort[i] == 'c') + list_sort(sinfo_list, _sort_by_cpus); + else if (params.sort[i] == 'd') + list_sort(sinfo_list, _sort_by_disk); + else if (params.sort[i] == 'D') + list_sort(sinfo_list, _sort_by_nodes); + else if (params.sort[i] == 'f') + list_sort(sinfo_list, _sort_by_features); + else if (params.sort[i] == 'F') + list_sort(sinfo_list, _sort_by_nodes_at); + else if (params.sort[i] == 'g') + list_sort(sinfo_list, _sort_by_groups); + else if (params.sort[i] == 'h') + list_sort(sinfo_list, _sort_by_share); + else if (params.sort[i] == 'l') + list_sort(sinfo_list, _sort_by_max_time); + else if (params.sort[i] == 'm') + list_sort(sinfo_list, _sort_by_memory); + else if (params.sort[i] == 'N') + list_sort(sinfo_list, _sort_by_node_list); + else if (params.sort[i] == 'P') + list_sort(sinfo_list, _sort_by_partition); + else if (params.sort[i] == 'r') + list_sort(sinfo_list, _sort_by_root); + else if (params.sort[i] == 's') + list_sort(sinfo_list, _sort_by_job_size); + else if (params.sort[i] == 't') + list_sort(sinfo_list, _sort_by_state); + else if (params.sort[i] == 'T') + list_sort(sinfo_list, _sort_by_state); + else if (params.sort[i] == 'w') + list_sort(sinfo_list, _sort_by_weight); + } +} + +/***************************************************************************** + * Local Sort Functions + *****************************************************************************/ +static int _sort_by_avail(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + int val1 = 0, val2 = 0; + + if (sinfo1->part_info) + val1 = sinfo1->part_info->state_up; + if (sinfo2->part_info) + val2 = sinfo2->part_info->state_up; + diff = val1 - val2; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_cpus(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->min_cpus - sinfo2->min_cpus; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_disk(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->min_disk - sinfo2->min_disk; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_features(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + char *val1 = "", *val2 = ""; + + if (sinfo1->features) + val1 = sinfo1->features; + if (sinfo2->features) + val2 = sinfo2->features; + diff = strcmp(val1, val2); + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_groups(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + char *val1 = "", *val2 = ""; + + if (sinfo1->part_info && sinfo1->part_info->allow_groups) + val1 = sinfo1->part_info->allow_groups; + if (sinfo2->part_info && sinfo2->part_info->allow_groups) + val2 = sinfo2->part_info->allow_groups; + diff = strcmp(val1, val2); + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_job_size(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + uint32_t val1 = 0, val2 = 0; + + if (sinfo1->part_info) { + val1 = sinfo1->part_info->max_nodes; + if (val1 != INFINITE) + val1 += sinfo1->part_info->min_nodes; + } + if (sinfo2->part_info) { + val2 = sinfo2->part_info->max_nodes; + if (val2 != INFINITE) + val2 += sinfo2->part_info->min_nodes; + } + diff = val1 - val2; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_max_time(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + uint32_t val1 = 0, val2 = 0; + + if (sinfo1->part_info) + val1 = sinfo1->part_info->max_time; + if (sinfo2->part_info) + val2 = sinfo2->part_info->max_time; + diff = val1 - val2; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_memory(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->min_mem - sinfo2->min_mem; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_node_list(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + char *val1, *val2; +#if PURE_ALPHA_SORT == 0 + int inx; +#endif + + hostlist_sort(sinfo1->nodes); + hostlist_sort(sinfo2->nodes); + val1 = hostlist_shift(sinfo1->nodes); + if (val1) + hostlist_push_host(sinfo1->nodes, val1); + else + val1 = ""; + val2 = hostlist_shift(sinfo2->nodes); + if (val2) + hostlist_push_host(sinfo2->nodes, val2); + else + val2 = ""; +#if PURE_ALPHA_SORT + diff = strcmp(val1, val2); +#else + for (inx=0; ; inx++) { + if (val1[inx] == val2[inx]) + continue; + if ((isdigit((int)val1[inx])) && + (isdigit((int)val2[inx]))) { + int num1, num2; + num1 = atoi(val1+inx); + num2 = atoi(val2+inx); + diff = num1 - num2; + } else + diff = strcmp(val1, val2); + break; + } +#endif + if (strlen(val1)) + free(val1); + if (strlen(val2)) + free(val2); + + if (reverse_order) + diff = -diff; + + return diff; +} + +static int _sort_by_nodes_at(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->nodes_alloc - sinfo2->nodes_alloc; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_nodes(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->nodes_tot - sinfo2->nodes_tot; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_partition(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + char *val1 = "", *val2 = ""; + + if (sinfo1->part_info && sinfo1->part_info->name) + val1 = sinfo1->part_info->name; + if (sinfo2->part_info && sinfo2->part_info->name) + val2 = sinfo2->part_info->name; + diff = strcmp(val1, val2); + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_root(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + int val1 = 0, val2 = 0; + + if (sinfo1->part_info) + val1 = sinfo1->part_info->root_only; + if (sinfo2->part_info) + val2 = sinfo2->part_info->root_only; + diff = val1 - val2; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_share(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + int val1 = 0, val2 = 0; + + if (sinfo1->part_info) + val1 = sinfo1->part_info->shared; + if (sinfo2->part_info) + val2 = sinfo2->part_info->shared; + diff = val1 - val2; + + if (reverse_order) + diff = -diff; + return diff; +} + +static int _sort_by_state(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->node_state - sinfo2->node_state; + + if (reverse_order) + diff = -diff; + + return diff; +} + +static int _sort_by_weight(void *void1, void *void2) +{ + int diff; + sinfo_data_t *sinfo1 = (sinfo_data_t *) void1; + sinfo_data_t *sinfo2 = (sinfo_data_t *) void2; + + diff = sinfo1->min_weight - sinfo2->min_weight; + + if (reverse_order) + diff = -diff; + return diff; +}