diff --git a/src/sinfo/Makefile.am b/src/sinfo/Makefile.am index 7a4f2ef90603cb92c1af6ebb434559508918f049..8688e4edd61f911812428f660828a9576ccd67d2 100644 --- a/src/sinfo/Makefile.am +++ b/src/sinfo/Makefile.am @@ -13,8 +13,8 @@ sinfo_LDADD = \ $(top_builddir)/src/api/libslurm.la \ $(POPT_LIBS) -noinst_HEADERS = sinfo.h -sinfo_SOURCES = sinfo.c opts.c +noinst_HEADERS = sinfo.h print.h +sinfo_SOURCES = sinfo.c opts.c print.c force: $(sinfo_LDADD) : force diff --git a/src/sinfo/opts.c b/src/sinfo/opts.c index 10bacb106dc15ece1d5434edcdef8e1e1a7ab58a..7f5fdc74d45af0c764b3a097e4866fe497cc6c5d 100644 --- a/src/sinfo/opts.c +++ b/src/sinfo/opts.c @@ -34,20 +34,30 @@ # include "src/popt/popt.h" #endif + +#include "src/common/xstring.h" +#include "src/sinfo/print.h" #include "src/sinfo/sinfo.h" #define OPT_NODE_STATE 0x02 #define OPT_PARTITION 0x03 #define OPT_NODE 0x04 -#define OPT_FORMAT 0x05 -#define OPT_VERBOSE 0x06 -#define OPT_ITERATE 0x07 -#define OPT_EXACT 0x08 - -static int _parse_state(char *str, enum node_states *states); +#define OPT_NODES 0x05 +#define OPT_FORMAT 0x06 +#define OPT_VERBOSE 0x07 +#define OPT_ITERATE 0x08 +#define OPT_EXACT 0x09 +#define OPT_LONG 0x0a +#define OPT_SHORT 0x0b +#define OPT_NO_HEAD 0x0c -extern struct sinfo_parameters params; -char *temp_state; +/* FUNCTIONS */ +static char *_get_prefix(char *token); +static int _parse_format( char* ); +static int _parse_state(char *str, enum node_states *states); +static void _parse_token( char *token, char *field, int *field_size, + bool *right_justify, char **suffix); +static void _print_options( void ); /* * parse_command_line @@ -59,7 +69,9 @@ int parse_command_line(int argc, char *argv[]) poptContext context; int curr_opt; - int rc = 0; + int i = 0, rc = 0; + char *env_val = NULL; + static char *temp_state = NULL; /* Declare the Options */ static const struct poptOption options[] = { @@ -72,17 +84,21 @@ int parse_command_line(int argc, char *argv[]) "node_state"}, {"partition", 'p', POPT_ARG_STRING, ¶ms.partition, OPT_PARTITION, "report on specific partition", "PARTITION"}, - {"nodes", 'n', POPT_ARG_STRING, ¶ms.nodes, OPT_NODE, + {"nodes", 'n', POPT_ARG_STRING, ¶ms.nodes, OPT_NODES, "report on specific node(s)", "NODES"}, - {"Node", 'N', POPT_ARG_NONE, ¶ms.node_flag, OPT_FORMAT, + {"Node", 'N', POPT_ARG_NONE, ¶ms.node_flag, OPT_NODE, "Node-centric format", NULL}, {"long", 'l', POPT_ARG_NONE, ¶ms.long_output, - OPT_FORMAT, "long output - displays more information", + OPT_LONG, "long output - displays more information", NULL}, {"summarize", 's', POPT_ARG_NONE, ¶ms.summarize, - OPT_FORMAT,"report state summary only", NULL}, + OPT_SHORT,"report state summary only", NULL}, {"verbose", 'v', POPT_ARG_NONE, ¶ms.verbose, OPT_VERBOSE, "verbosity level", "level"}, + {"noheader", 'h', POPT_ARG_NONE, ¶ms.no_header, + OPT_NO_HEAD, "no headers on output", NULL}, + {"format", 'o', POPT_ARG_STRING, ¶ms.format, OPT_FORMAT, + "format specification", "format"}, POPT_AUTOHELP {NULL, '\0', 0, NULL, 0, NULL, NULL} /* end */ }; @@ -115,52 +131,274 @@ int parse_command_line(int argc, char *argv[]) exit(1); } + if ( ( params.format == NULL ) && + ( env_val = getenv("SINFO_FORMAT") ) ) { + i = strlen(env_val); + params.format = xmalloc(i); + strcpy(params.format, env_val); + } + + if ( ( params.partition == NULL ) && + ( env_val = getenv("SINFO_PARTITION") ) ) { + i = strlen(env_val); + params.partition = xmalloc(i); + strcpy(params.partition, env_val); + } + + if ( params.format == NULL ) { + if ( params.summarize ) + params.format = "%9P %5a %.8l %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"; + } else { + params.format = "%N %.6D %9P %6t"; + } + } else { + if ( params.long_output ) + params.format = "%9P %5a %.8l %.8s %4r %5h %10g %.6D %11T %N"; + else + params.format = "%9P %5a %.8l %.6D %6t %N"; + } + } + _parse_format( params.format ); + if (params.verbose) - print_options(); + _print_options(); return rc; } /* - * _parse_state - parse state information - * IN str - name of a job states - * OUT states - numeric equivalent sjob state + * _parse_state - convert node state name string to numeric value + * IN str - state name + * OUT states - enum node_states value corresponding to str * RET 0 or error code */ -static int _parse_state(char *str, enum node_states *states) -{ +static int +_parse_state( char* str, enum node_states* states ) +{ int i; + char *state_names; - for (i = 0; i <= NODE_STATE_END; i++) { - if (strcasecmp(node_state_string(i), "END") == 0) - break; - - if (strcasecmp(node_state_string(i), str) == 0) { + for (i = 0; i<NODE_STATE_END; i++) { + if (strcasecmp (node_state_string(i), str) == 0) { *states = i; return SLURM_SUCCESS; - } - - if (strcasecmp(node_state_string(i | NODE_STATE_NO_RESPOND), - str) == 0) { - *states = i | NODE_STATE_NO_RESPOND; - return SLURM_SUCCESS; - } - - if (strcasecmp(node_state_string_compact(i), str) == 0) { + } + if (strcasecmp (node_state_string_compact(i), str) == 0) { *states = i; return SLURM_SUCCESS; - } + } + } - if (strcasecmp(node_state_string_compact(i | - NODE_STATE_NO_RESPOND), str) == 0) { - *states = i | NODE_STATE_NO_RESPOND; - return SLURM_SUCCESS; - } + fprintf (stderr, "Invalid node state specified: %s\n", str); + state_names = xstrdup(node_state_string(0)); + for (i=1; i<NODE_STATE_END; i++) { + xstrcat(state_names, ","); + xstrcat(state_names, node_state_string(i)); } + fprintf (stderr, "Valid node states include: %s\n", state_names); + xfree (state_names); return SLURM_ERROR; } +/* Take the user's format specification and use it to build build the + * format specifications (internalize it to print.c data structures) */ +static int +_parse_format( char* format ) +{ + int field_size; + bool right_justify; + char *prefix, *suffix, *token, *tmp_char, *tmp_format; + char field[1]; + + if (format == NULL) { + fprintf( stderr, "Format option lacks specification\n" ); + exit( 1 ); + } + + params.format_list = list_create( NULL ); + 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 ); + + token = strtok_r( tmp_format, "%", &tmp_char); + if (token && (format[0] != '%')) /* toss header */ + token = strtok_r( NULL, "%", &tmp_char ); + while (token) { + _parse_token( token, field, &field_size, &right_justify, + &suffix); + if (field[0] == 'a') { + params.match_flags.avail_flag = true; + format_add_avail( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'A') { + format_add_nodes_at( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'c') { + format_add_cpus( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'd') { + format_add_disk( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'D') { + format_add_nodes( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'f') { + params.match_flags.features_flag = true; + format_add_features( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'F') { + format_add_nodes_aiot( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'g') { + params.match_flags.groups_flag = true; + format_add_groups( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'h') { + params.match_flags.share_flag = true; + format_add_share( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'l') { + params.match_flags.max_time_flag = true; + format_add_time( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'm') { + format_add_memory( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'N') { + format_add_node_list( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'P') { + params.match_flags.partition_flag = true; + format_add_partition( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'r') { + params.match_flags.root_flag = true; + format_add_root( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 's') { + params.match_flags.job_size_flag = true; + format_add_size( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 't') { + params.match_flags.state_flag = true; + format_add_state_compact( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'T') { + params.match_flags.state_flag = true; + format_add_state_long( params.format_list, + field_size, + right_justify, + suffix ); + } else if (field[0] == 'w') { + format_add_weight( params.format_list, + field_size, + right_justify, + suffix ); + } else + fprintf(stderr, "Invalid node format specification: %c\n", + field[0] ); + token = strtok_r( NULL, "%", &tmp_char); + } + + xfree( tmp_format ); + return SLURM_SUCCESS; +} + +/* Take a format specification and copy out it's prefix + * IN/OUT token - input specification, everything before "%" is removed + * RET - everything before "%" in the token + */ +static char * +_get_prefix( char *token ) +{ + char *pos, *prefix; + + if (token == NULL) + return NULL; + + pos = strchr(token, (int) '%'); + if (pos == NULL) /* everything is prefix */ + return xstrdup(token); + if (pos == token) /* no prefix */ + return NULL; + + pos[0] = '\0'; /* some prefix */ + prefix = xstrdup(token); + pos[0] = '%'; + memmove(token, pos, (strlen(pos)+1)); + return prefix; +} + +/* Take a format specification and break it into its components + * IN token - input specification without leading "%", eg. ".5u" + * OUT field - the letter code for the data type + * OUT field_size - byte count + * OUT right_justify - true of field to be right justified + * OUT suffix - tring containing everthing after the field specification + */ +static void +_parse_token( char *token, char *field, int *field_size, bool *right_justify, + char **suffix) +{ + int i = 0; + + assert (token != NULL); + + if (token[i] == '.') { + *right_justify = true; + i++; + } else + *right_justify = false; + + *field_size = 0; + while ((token[i] >= '0') && (token[i] <= '9')) + *field_size = (*field_size * 10) + (token[i++] - '0'); + + field[0] = token[i++]; + + *suffix = xstrdup(&token[i]); +} + /* print the parameters specified */ -void print_options( void ) +void _print_options( void ) { char *node_state; @@ -171,13 +409,20 @@ void print_options( void ) printf("-----------------------------\n"); printf("exact = %d\n", params.exact_match); - printf("long format = %s\n", params.long_output ? "true" : "false"); + printf("format = %s\n", params.format); + printf("iterate = %d\n", params.iterate ); + printf("long = %s\n", params.long_output ? "true" : "false"); + printf("no_header = %s\n", params.no_header ? "true" : "false"); + 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("Node format = %s\n", params.node_flag ? "true" : "false"); printf("partition = %s\n", params.partition ? - params.partition: "N/A"); + params.partition: "N/A"); printf("state = %s\n", node_state); printf("summarize = %s\n", params.summarize ? "true" : "false"); printf("verbose = %d\n", params.verbose); printf("-----------------------------\n\n"); } + + diff --git a/src/sinfo/print.c b/src/sinfo/print.c new file mode 100644 index 0000000000000000000000000000000000000000..8c191d297bcba033ae7a01f859403e32e704a4ca --- /dev/null +++ b/src/sinfo/print.c @@ -0,0 +1,544 @@ +/*****************************************************************************\ + * print.c - sinfo print job 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> + * 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 <time.h> +#include <stdio.h> +#include <string.h> +#include <pwd.h> +#include <sys/types.h> + +#include "src/common/list.h" +#include "src/common/hostlist.h" +#include "src/common/xmalloc.h" +#include "src/sinfo/print.h" +#include "src/sinfo/sinfo.h" + +#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); + +/***************************************************************************** + * Global Print Functions + *****************************************************************************/ +void print_date(void) +{ + time_t now; + + now = time(NULL); + printf("%s", ctime(&now)); +} + +int print_sinfo_list(List sinfo_list, List format) +{ + ListIterator i = list_iterator_create(sinfo_list); + sinfo_data_t *current; + + if (params.node_field_flag) + _set_node_field_size(sinfo_list); + + if (!params.no_header) + print_sinfo_entry(NULL, format); + + while ((current = list_next(i)) != NULL) + print_sinfo_entry(current, format); + + list_iterator_destroy(i); + return SLURM_SUCCESS; +} + +int print_sinfo_entry(sinfo_data_t *sinfo_data , List format) +{ + ListIterator i = list_iterator_create(format); + sinfo_format_t *current; + int total_width = 0, inx; + + while ((current = (sinfo_format_t *) list_next(i)) != NULL) { + if (current-> + function(sinfo_data, current->width, + 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; +} + +/***************************************************************************** + * Local Print Functions + *****************************************************************************/ + +static int _print_str(char *str, int width, bool right, bool cut_output) +{ + char format[64]; + int printed = 0; + + if (right == true && width != 0) + snprintf(format, 64, "%%%ds", width); + else if (width != 0) + snprintf(format, 64, "%%.%ds", width); + else { + format[0] = '%'; + format[1] = 's'; + format[2] = '\0'; + } + + if ((width == 0) || (cut_output == false)) { + if ((printed = printf(format, str)) < 0) + return printed; + } else { + char temp[width + 1]; + snprintf(temp, width + 1, format, str); + if ((printed = printf(temp)) < 0) + return printed; + } + + while (printed++ < width) + printf(" "); + + return printed; +} + +static int _print_secs(long time, int width, bool right, bool cut_output) +{ + char str[FORMAT_STRING_SIZE]; + long days, hours, minutes, seconds; + + seconds = time % 60; + minutes = (time / 60) % 60; + hours = (time / 3600) % 24; + days = time / 86400; + + if (days) + snprintf(str, FORMAT_STRING_SIZE, + "%ld:%2.2ld:%2.2ld:%2.2ld", + days, hours, minutes, seconds); + else if (hours) + snprintf(str, FORMAT_STRING_SIZE, + "%ld:%2.2ld:%2.2ld", + hours, minutes, seconds); + else + snprintf(str, FORMAT_STRING_SIZE, + "%ld:%2.2ld", + minutes, seconds); + + _print_str(str, width, right, cut_output); + return SLURM_SUCCESS; +} + +static int +_build_min_max_string(char *buffer, int buf_size, int min, int max, bool range) +{ + if (max == min) + return snprintf(buffer, buf_size, "%d", max); + else if (range) { + if (max == INFINITE) + return snprintf(buffer, buf_size, "%d-INFINITE", min); + else + return snprintf(buffer, buf_size, "%d-%d", min, max); + } else + return snprintf(buffer, buf_size, "%d+", min); +} + +int +format_add_function(List list, int width, bool right, char *suffix, + int (*function) (sinfo_data_t *, int, bool, char*)) +{ + sinfo_format_t *tmp = + (sinfo_format_t *) xmalloc(sizeof(sinfo_format_t)); + tmp->function = function; + tmp->width = width; + tmp->right_justify = right; + tmp->suffix = suffix; + + if (list_append(list, tmp) == NULL) { + fprintf(stderr, "Memory exhausted\n"); + exit(1); + } + return SLURM_SUCCESS; +} + +static void _set_node_field_size(List sinfo_list) +{ + char tmp[1024]; + ListIterator i = list_iterator_create(sinfo_list); + sinfo_data_t *current; + int max_width = MIN_NODE_FIELD_SIZE, this_width = 0; + + while ((current = (sinfo_data_t *) list_next(i)) != NULL) { + this_width = hostlist_ranged_string(current->nodes, + sizeof(tmp), tmp); + max_width = MAX(max_width, this_width); + } + list_iterator_destroy(i); + params.node_field_size = max_width; +} + +/***************************************************************************** + * Sinfo Print Functions + *****************************************************************************/ + +int _print_avail(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else if (sinfo_data->part_info->state_up) + _print_str("UP", width, right_justify, true); + else + _print_str("DOWN", width, right_justify, true); + } else + _print_str("AVAIL", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_cpus(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + _build_min_max_string(id, FORMAT_STRING_SIZE, + sinfo_data->min_cpus, + sinfo_data->max_cpus, false); + _print_str(id, width, right_justify, true); + } else + _print_str("CPUS", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_disk(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + _build_min_max_string(id, FORMAT_STRING_SIZE, + sinfo_data->min_disk, + sinfo_data->max_disk, false); + _print_str(id, width, right_justify, true); + } else + _print_str("TMP_DISK", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_features(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) + _print_str(sinfo_data->features, width, right_justify, true); + else + _print_str("FEATURES", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_groups(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _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); + } else + _print_str("GROUPS", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_memory(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + _build_min_max_string(id, FORMAT_STRING_SIZE, + sinfo_data->min_mem, + sinfo_data->max_mem, false); + _print_str(id, width, right_justify, true); + } else + _print_str("MEMORY", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_node_list(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (params.node_field_flag) + width = params.node_field_size; + + if (sinfo_data) { + char tmp[1024]; + hostlist_ranged_string(sinfo_data->nodes, + sizeof(tmp), tmp); + _print_str(tmp, width, right_justify, true); + } else + _print_str("NODE_LIST", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_nodes_t(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + 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); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_nodes_at(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + snprintf(id, FORMAT_STRING_SIZE, "%u/%u", + 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); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_nodes_aiot(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + snprintf(id, FORMAT_STRING_SIZE, "%u/%u/%u/%u", + sinfo_data->nodes_alloc, sinfo_data->nodes_idle, + 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); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_partition(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else { + char *tmp; + tmp = xmalloc(strlen(sinfo_data->part_info->name)+2); + strcpy(tmp, sinfo_data->part_info->name); + if (sinfo_data->part_info->default_part) + strcat(tmp, "*"); + _print_str(tmp, width, right_justify, true); + xfree(tmp); + } + } else + _print_str("PARTITION", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_prefix(sinfo_data_t * job, int width, bool right_justify, + char* suffix) +{ + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_root(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else if (sinfo_data->part_info->root_only) + _print_str("YES", width, right_justify, true); + else + _print_str("NO", width, right_justify, true); + } else + _print_str("ROOT", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_share(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else if (sinfo_data->part_info->shared > 1) + _print_str("FORCE", width, right_justify, true); + else if (sinfo_data->part_info->shared) + _print_str("YES", width, right_justify, true); + else + _print_str("NO", width, right_justify, true); + } else + _print_str("SHARE", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_size(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else { + _build_min_max_string(id, FORMAT_STRING_SIZE, + sinfo_data->part_info->min_nodes, + sinfo_data->part_info->max_nodes, + true); + _print_str(id, width, right_justify, true); + } + } else + _print_str("JOB_SIZE", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +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 + _print_str("STATE", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +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 + _print_str("STATE", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + + +int _print_time(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + if (sinfo_data) { + if (sinfo_data->part_info == NULL) + _print_str("N/A", width, right_justify, true); + else if (sinfo_data->part_info->max_time == INFINITE) + _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); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_weight(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix) +{ + char id[FORMAT_STRING_SIZE]; + if (sinfo_data) { + _build_min_max_string(id, FORMAT_STRING_SIZE, + sinfo_data->min_weight, + sinfo_data->max_weight, false); + _print_str(id, width, right_justify, true); + } else + _print_str("WEIGHT", width, right_justify, true); + + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} diff --git a/src/sinfo/print.h b/src/sinfo/print.h new file mode 100644 index 0000000000000000000000000000000000000000..d63231fd4af3171b20292d77d3f2e1fea536b8e8 --- /dev/null +++ b/src/sinfo/print.h @@ -0,0 +1,137 @@ +/*****************************************************************************\ + * print.h - sinfo print job definitions + ***************************************************************************** + * 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> + * 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. +\*****************************************************************************/ + +#ifndef _SINFO_PRINT_H_ +#define _SINFO_PRINT_H_ + +#include <slurm/slurm.h> + +#include "src/common/list.h" +#include "src/sinfo/sinfo.h" + +#define FORMAT_STRING_SIZE 32 + +/***************************************************************************** + * Format Structures + *****************************************************************************/ +typedef struct sinfo_format { + int (*function) (sinfo_data_t *, int, bool, char*); + uint32_t width; + bool right_justify; + char *suffix; +} sinfo_format_t; + +/***************************************************************************** + * Print Format Functions + *****************************************************************************/ +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); + +#define format_add_avail(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_avail) +#define format_add_cpus(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_cpus) +#define format_add_disk(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_disk) +#define format_add_features(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_features) +#define format_add_groups(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_groups) +#define format_add_memory(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_memory) +#define format_add_node_list(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_node_list) +#define format_add_nodes(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_nodes_t) +#define format_add_nodes_aiot(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_nodes_aiot) +#define format_add_nodes_at(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_nodes_at) +#define format_add_partition(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_partition) +#define format_add_prefix(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_prefix) +#define format_add_root(list,wid,right,prefix) \ + format_add_function(list,wid,right,prefix,_print_root) +#define format_add_share(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_share) +#define format_add_size(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_size) +#define format_add_state_compact(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_state_compact) +#define format_add_state_long(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_state_long) +#define format_add_time(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_time) +#define format_add_weight(list,wid,right,suffix) \ + format_add_function(list,wid,right,suffix,_print_weight) + +/***************************************************************************** + * Print Field Functions + *****************************************************************************/ + +int _print_avail(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_cpus(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_disk(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_features(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_groups(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_memory(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_node_list(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_nodes_t(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_nodes_at(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_nodes_aiot(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_partition(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_prefix(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_root(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_share(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_size(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_state_compact(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_state_long(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_time(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); +int _print_weight(sinfo_data_t * sinfo_data, int width, + bool right_justify, char *suffix); + +#endif diff --git a/src/sinfo/sinfo.c b/src/sinfo/sinfo.c index 9e7cf10e250a4ea48b5bb997d9882628accbb41f..1dadf5f1f51581c5b525d24754410d3b9e902a8f 100644 --- a/src/sinfo/sinfo.c +++ b/src/sinfo/sinfo.c @@ -25,132 +25,63 @@ \*****************************************************************************/ #include "src/sinfo/sinfo.h" -#include "src/common/hostlist.h" -#include "src/common/list.h" - -#define NODE_SIZE_PART 9 -#define NODE_SIZE_STATE 6 -#define NODE_SIZE_STATE_LONG 11 -#define NODE_SIZE_NODES 5 -#define NODE_SIZE_CPUS 4 -#define NODE_SIZE_MEM 6 -#define NODE_SIZE_DISK 8 -#define NODE_SIZE_WEIGHT 6 -#define NODE_SIZE_FEATURES 8 -#define NODE_SIZE_NAME 9 - -#define PART_SIZE_NODES 0 -#define PART_SIZE_NUM 5 -#define PART_SIZE_PART 9 -#define PART_SIZE_STATE 6 -#define PART_SIZE_STATE_LONG 11 -#define PART_SIZE_AVAIL 5 -#define PART_SIZE_TIME 8 -#define PART_SIZE_JOB_SIZE 8 -#define PART_SIZE_ROOT_ONLY 4 -#define PART_SIZE_SHARE 5 -#define PART_SIZE_GROUPS 20 +#include "src/sinfo/print.h" /******************** * Global Variables * ********************/ -static char *command_name; -struct sinfo_parameters params = - { partition:NULL, state_flag:false, - node_flag:false, nodes:NULL, summarize:false, long_output:false, - line_wrap:false, verbose:false, iterate:0, exact_match:false -}; -static int node_sz_cpus, node_sz_name, node_sz_mem, node_sz_state; -static int node_sz_disk, node_sz_part, node_sz_weight, node_sz_features; -static int node_sz_nodes; -static int part_sz_num, part_sz_nodes, part_sz_part, part_sz_state; -static int part_sz_avail, part_sz_time, part_sz_job_nodes; -static int part_sz_root, part_sz_share, part_size_groups; -static const char dash_line_20[] = "--------------------"; -static const char dash_line_40[] = "----------------------------------------"; +struct sinfo_parameters params; /************ * Funtions * ************/ -static int _query_server(partition_info_msg_t ** part_pptr, - node_info_msg_t ** node_pptr); - - -/* Node Functions */ -static void _display_all_nodes(node_info_msg_t * node_msg, int node_rec_cnt); -static void _display_node_info_header(void); -static void _display_node_info(List nodes); +static int _build_sinfo_data(List sinfo_list, + partition_info_msg_t *partition_msg, + node_info_msg_t *node_msg, int node_cnt); +static void _create_sinfo(List sinfo_list, partition_info_t* part_ptr, + node_info_t *node_ptr); +static void _sinfo_list_delete(void *data); static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt); -static bool _exact_node_match(node_info_t *node1, node_info_t *node2); -static List _group_node_list(node_info_msg_t * msg, int node_rec_cnt); -static void _node_cpus_string_from_list(List nodes, char *buffer); -static void _node_mem_string_from_list(List nodes, char *buffer); -static void _node_disk_string_from_list(List nodes, char *buffer); -static void _node_weight_string_from_list(List nodes, char *buffer); -static int _node_name_string_from_list(List nodes, char *buffer, - int buf_size, int *node_count); +static partition_info_t *_find_part(char *part_name, + partition_info_msg_t *partition_msg); +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); - -/* Partition Functions */ -static void _display_all_partition_summary(partition_info_msg_t * part_ptr, - node_info_msg_t * node_ptr, - int node_rec_cnt); -static void _display_partition_node_info(struct partition_summary - *partition); -static void _display_all_partition_info(List partitions); -static void _print_summary_header(void); -static void _display_partition_node_summary(struct partition_summary - *partition); -static void _display_partition_summaries(List partitions); - -/* Misc Display functions */ -static int _build_min_max_string(char *buffer, int max, int min, bool range); -static void _print_date(void); -static int _print_int(int number, int width, bool right); -static int _print_str(char *number, int width, bool right); -static void _set_node_field_sizes(List nodes); -static void _set_part_field_sizes(void); - -/* Display partition functions */ -static struct partition_summary *_find_partition_summary(List l, char *name); -static struct node_state_summary *_find_node_state_summary( - List l, node_info_t *ninfo); -static List _setup_partition_summary(partition_info_msg_t * part_ptr, - node_info_msg_t * node_ptr, - int node_rec_cnt); -static void _print_partition_header(void); - +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; - int node_rec_cnt; - - command_name = argv[0]; + List sinfo_list; + int node_rec_cnt = 0; log_init("sinfo", opts, SYSLOG_FACILITY_DAEMON, NULL); parse_command_line(argc, argv); while (1) { - if (params.iterate - && (params.verbose || params.long_output)) - _print_date(); + if ( params.iterate && (params.verbose || params.long_output )) + print_date(); if (_query_server(&partition_msg, &node_msg) != 0) exit(1); _filter_nodes(node_msg, &node_rec_cnt); - if (params.node_flag && (!params.summarize)) - _display_all_nodes(node_msg, node_rec_cnt); - else - _display_all_partition_summary(partition_msg, - node_msg, node_rec_cnt); + 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); if (params.iterate) { + list_destroy(sinfo_list); printf("\n"); sleep(params.iterate); } else @@ -160,7 +91,12 @@ int main(int argc, char *argv[]) exit(0); } -/* download the current server state */ +/* + * _query_server - download the current server state + * part_pptr IN/OUT - partition information message + * node_pptr IN/OUT - node information message + * RET zero or error code + */ static int _query_server(partition_info_msg_t ** part_pptr, node_info_msg_t ** node_pptr) @@ -210,10 +146,14 @@ _query_server(partition_info_msg_t ** part_pptr, old_node_ptr = new_node_ptr; *node_pptr = new_node_ptr; - return 0; + return SLURM_SUCCESS; } -/* Filter the node list based upon user options */ +/* + * _filter_nodes - Filter the node list based upon user options + * node_msg IN/OUT - node info message with usable entries at the front + * node_rec_cnt OUT - number of usable node records + */ static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt) { int i, new_rec_cnt = 0; @@ -235,7 +175,7 @@ static void _filter_nodes(node_info_msg_t *node_msg, int *node_rec_cnt) if (params.nodes && hostlist_find (hosts, node_msg->node_array[i].name) == -1) continue; - if (params.partition && strcmp + if (params.partition && _strcmp (node_msg->node_array[i].partition, params.partition)) continue; @@ -263,7 +203,9 @@ static void _swap_char(char **from, char **to) *from = tmp; } -/* Swap *char values, just overwrite the numbers in moving node info */ +/* _swap_node_rec - Swap the data associated with two node records. + * trade type *char values, just overwrite the numbers (from_node + * data is not used) */ static void _swap_node_rec(node_info_t *from_node, node_info_t *to_node) { if (from_node != to_node) { @@ -278,767 +220,203 @@ static void _swap_node_rec(node_info_t *from_node, node_info_t *to_node) } } - -/***************************************************************************** - * DISPLAY NODE INFO FUNCTIONS - *****************************************************************************/ - -static void _display_all_nodes(node_info_msg_t * node_msg, int node_rec_cnt) -{ - List nodes = _group_node_list(node_msg, node_rec_cnt); - ListIterator i = list_iterator_create(nodes); - List current; - - _set_node_field_sizes(nodes); - _display_node_info_header(); - - while ((current = list_next(i)) != NULL) { - _display_node_info(current); - list_destroy(current); - } - list_iterator_destroy(i); - list_destroy(nodes); -} - -static void _set_node_field_sizes(List nodes) -{ - int name_len = 1024, node_cnt, len; - char *name_buf; - List current; - ListIterator i = list_iterator_create(nodes); - - node_sz_features = NODE_SIZE_FEATURES; - node_sz_part = NODE_SIZE_PART; - node_sz_weight = NODE_SIZE_WEIGHT; - node_sz_cpus = NODE_SIZE_CPUS; - node_sz_disk = NODE_SIZE_DISK; - node_sz_mem = NODE_SIZE_MEM; - node_sz_nodes = NODE_SIZE_NODES; - if (params.long_output) - node_sz_state = NODE_SIZE_STATE_LONG; - else - node_sz_state = NODE_SIZE_STATE; - - node_sz_name = NODE_SIZE_NAME; - name_buf = malloc(name_len); - while ((current = list_next(i)) != NULL) { - while (_node_name_string_from_list(current, name_buf, - name_len, &node_cnt)) { - name_len *= 2; - name_buf = realloc(name_buf, name_len); - } - len = strlen(name_buf); - if (len > node_sz_name) - node_sz_name = len; - } - free(name_buf); - list_iterator_destroy(i); -} - -static void _display_node_info_header() -{ - _print_str("NODE_LIST", node_sz_name, false); - printf(" "); - _print_str("NODES", node_sz_nodes, false); - printf(" "); - _print_str("PARTITION", node_sz_part, false); - printf(" "); - _print_str("STATE", node_sz_state, false); - - if (params.long_output) { - printf(" "); - _print_str("CPUS", node_sz_cpus, true); - printf(" "); - _print_str("MEMORY", node_sz_mem, true); - printf(" "); - _print_str("TMP_DISK", node_sz_disk, true); - printf(" "); - _print_str("WEIGHT", node_sz_weight, true); - printf(" "); - _print_str("FEATURES", node_sz_features, false); - } - printf("\n%s%s\n", dash_line_40, dash_line_40); - -} - -static void _display_node_info(List nodes) -{ - char node_names[64]; - int node_cnt; - node_info_t *node = list_peek(nodes); - - _node_name_string_from_list(nodes, node_names, sizeof(node_names), - &node_cnt); - _print_str(node_names, node_sz_name, false); - printf(" "); - _print_int(node_cnt, node_sz_nodes, true); - printf(" "); - _print_str(node->partition, node_sz_part, false); - printf(" "); - if (params.long_output) - _print_str(node_state_string(node->node_state), - node_sz_state, false); - else - _print_str(node_state_string_compact(node->node_state), - node_sz_state, false); - - if (params.long_output) { - int tmp_feature_size; - char str_buf[64]; - - printf(" "); - _node_cpus_string_from_list(nodes, str_buf); - _print_str(str_buf, node_sz_cpus, true); - printf(" "); - _node_mem_string_from_list(nodes, str_buf); - _print_str(str_buf, node_sz_mem, true); - printf(" "); - _node_disk_string_from_list(nodes, str_buf); - _print_str(str_buf, node_sz_disk, true); - printf(" "); - _node_weight_string_from_list(nodes, str_buf); - _print_str(str_buf, node_sz_weight, true); - - printf(" "); - tmp_feature_size = node_sz_features; - if (node->features && - (strlen(node->features) > tmp_feature_size)) - tmp_feature_size = 0; - _print_str(node->features, tmp_feature_size, false); - } - - printf("\n"); -} - - -/* group similar nodes together, return a list of lists containing nodes - * with similar configurations */ -static List _group_node_list(node_info_msg_t * msg, int node_rec_cnt) -{ - List node_lists = list_create(NULL); - node_info_t *nodes = msg->node_array; - int i; - - for (i = 0; i < node_rec_cnt; i++) { - ListIterator list_i = NULL; - List curr_list = NULL; - - list_i = list_iterator_create(node_lists); - while ((curr_list = list_next(list_i)) != NULL) { - node_info_t *curr = list_peek(curr_list); - - if ((curr->partition != NULL) && - (nodes[i].partition != NULL) && - (strcmp(nodes[i].partition, - curr->partition) != 0)) - continue; - - if (!_exact_node_match(curr, &nodes[i])) - continue; - - list_append(curr_list, &(nodes[i])); - break; - } - list_iterator_destroy(list_i); - - if (curr_list == NULL) { - List temp = list_create(NULL); - list_append(temp, &(nodes[i])); - list_append(node_lists, temp); - } - } - - return node_lists; -} - -/* Return true if all of the nodes' configurations match */ -static bool _exact_node_match(node_info_t *node1, node_info_t *node2) -{ - if (node1->node_state != node2->node_state) - return false; - else if ((!params.exact_match) || (!params.long_output)) - return true; - - if (node1->features && node2->features && - strcmp(node1->features, node2->features)) - return false; - else if (node1->features != node2->features) - return false; - - if ((node1->cpus != node2->cpus) || - (node1->real_memory != node2->real_memory) || - (node1->tmp_disk != node2->tmp_disk)) - return false; - else - return true; -} - -/***************************************************************************** - * DISPLAY PARTITION INFO FUNCTIONS - *****************************************************************************/ - -static struct partition_summary *_find_partition_summary(List l, char *name) +/* + * _build_sinfo_data - make a sinfo_data entry for each unique node + * configuration and add it to the sinfo_list for later printing. + * sinfo_list IN/OUT - list of unique sinfo_dataa records to report + * partition_msg IN - partition info message + * node_msg IN - node info message + * node_cnt IN - number of usable records in node_msg (others filtered out) + * RET zero or error code + */ +static int _build_sinfo_data(List sinfo_list, + partition_info_msg_t *partition_msg, + node_info_msg_t *node_msg, int node_cnt) { + node_info_t *node_ptr; + partition_info_t* part_ptr; ListIterator i; - struct partition_summary *current = NULL; - - if (name == NULL) - return current; - - i = list_iterator_create(l); - while ((current = list_next(i)) != NULL) { - if (strcmp(current->info->name, name) == 0) - break; - } - - list_iterator_destroy(i); - return current; -} - -/* Return a pointer to the node in the supplied list that contains - * the same configuration (just node_state at present). If none - * found then return NULL */ -static struct node_state_summary * -_find_node_state_summary(List l, node_info_t *ninfo) -{ - ListIterator i = list_iterator_create(l); - struct node_state_summary *current; - - while ((current = list_next(i)) != NULL) { - if ((params.summarize) || - (ninfo->node_state == current->state)) - break; - /* Since both DRAINED and DRAINING nodes are shown as - * state "DRAIN" by default, this will combine them */ - if ((!params.long_output) && - (strcmp(node_state_string_compact(ninfo->node_state), - node_state_string_compact(current->state)) == 0)) + int j; + + /* remove any existing sinfo_list entries */ + + /* make sinfo_list entries for each node */ + for (j=0; j<node_cnt; j++) { + sinfo_data_t *sinfo_ptr; + i = list_iterator_create(sinfo_list); + node_ptr = &(node_msg->node_array[j]); + part_ptr = _find_part(node_ptr->partition, partition_msg); + + /* 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; + + /* This node has the same configuration as this + * sinfo_data, just add to this record */ + _update_sinfo(sinfo_ptr, part_ptr, node_ptr); break; - } - - list_iterator_destroy(i); - return current; -} - -/* Construct a list of partitions containing the configuration - * of that partition along with configuration about the nodes - * in that partition */ -static List -_setup_partition_summary(partition_info_msg_t * part_ptr, - node_info_msg_t * node_ptr, int node_rec_cnt) -{ - int i = 0; - List partitions = list_create(NULL); - - /* create a data structure for each partition */ - for (i = 0; i < part_ptr->record_count; i++) { - struct partition_summary *sum; - - sum = (struct partition_summary *) - malloc(sizeof(struct partition_summary)); - sum->info = &part_ptr->partition_array[i]; - sum->states = list_create(NULL); - list_append(partitions, sum); - } - - for (i = 0; i < node_rec_cnt; i++) { - node_info_t *ninfo = &node_ptr->node_array[i]; - struct partition_summary *part_sum; - struct node_state_summary *node_sum = NULL; - - if (ninfo->partition == NULL) { - if (params.verbose) - fprintf(stderr, - "Node %s is not in any partition\n\n", - ninfo->name); - continue; - } - part_sum = _find_partition_summary(partitions, - ninfo->partition); - if (part_sum == NULL) { - /* This should never happen */ - fprintf(stderr, "Couldn't find partition %s", - ninfo->partition); - fprintf(stderr,"Please notify system administators\n"); - continue; - } - - if ((node_sum = _find_node_state_summary(part_sum->states, - ninfo))) { - node_sum->state = (enum node_states) ninfo->node_state; - hostlist_push(node_sum->nodes, ninfo->name); - node_sum->node_count++; - } else { - node_sum = (struct node_state_summary *) - malloc(sizeof(struct node_state_summary)); - node_sum->state = - (enum node_states) ninfo->node_state; - node_sum->node_count = 1; - node_sum->nodes = hostlist_create(ninfo->name); - list_append(part_sum->states, node_sum); - } - } - - return partitions; -} - -static void -_display_all_partition_summary(partition_info_msg_t * part_ptr, - node_info_msg_t * node_ptr, int node_rec_cnt) -{ - List partitions = _setup_partition_summary(part_ptr, - node_ptr, node_rec_cnt); - _set_part_field_sizes(); - if (params.summarize) - _display_partition_summaries(partitions); - else - _display_all_partition_info(partitions); - list_destroy(partitions); -} - -static void _set_part_field_sizes(void) -{ - part_sz_part = PART_SIZE_PART; - part_sz_num = PART_SIZE_NUM; - part_sz_nodes = PART_SIZE_NODES; - if (params.long_output) - part_sz_state = PART_SIZE_STATE_LONG; - else - part_sz_state = PART_SIZE_STATE; - part_sz_avail = PART_SIZE_AVAIL; - part_sz_time = PART_SIZE_TIME; - part_sz_job_nodes = PART_SIZE_JOB_SIZE; - part_sz_root = PART_SIZE_ROOT_ONLY; - part_sz_share = PART_SIZE_SHARE; - part_size_groups = PART_SIZE_GROUPS; -} - -/* Formating for partiton display headers... */ -static void _print_summary_header(void) -{ - _print_str("PARTITION", part_sz_part, false); - printf(" "); - _print_str("AVAIL", part_sz_avail, false); - printf(" "); - _print_str("NODES", part_sz_num, true); - printf(" "); - _print_str("NODE_LIST", part_sz_nodes, false); - printf("\n%s%s\n", dash_line_40, dash_line_20); -} - -static void -_display_partition_node_summary(struct partition_summary *partition) -{ - int line_cnt = 0, name_len = 1024; - char *name_buf, part_name[64]; - - ListIterator node_i = list_iterator_create(partition->states); - struct node_state_summary *state_sum = NULL; - - strcpy(part_name, partition->info->name); - if (partition->info->default_part) - strcat(part_name, "*"); - - name_buf = malloc(name_len); - while ((state_sum = list_next(node_i)) != NULL) { - line_cnt++; - while ((int)hostlist_ranged_string(state_sum->nodes, - name_len, name_buf) < 0) { - name_len *= 2; - name_buf = realloc(name_buf, name_len); } - _print_str(part_name, part_sz_part, false); - printf(" "); - _print_str(partition->info->state_up ? "UP" : "DOWN", - part_sz_avail, false); - printf(" "); - _print_int(state_sum->node_count, part_sz_num, true); - printf(" "); - _print_str(name_buf, part_sz_nodes, false); - printf("\n"); - } - list_iterator_destroy(node_i); - free(name_buf); - - if (line_cnt == 0) { - _print_str(part_name, part_sz_part, false); - printf(" "); - _print_str(partition->info->state_up ? "UP" : "DOWN", - part_sz_avail, false); - printf(" "); - _print_int(0, part_sz_num, true); - printf("\n"); - } -} - -static void _display_partition_summaries(List partitions) -{ - struct partition_summary *partition; - ListIterator part_i = list_iterator_create(partitions); - - _print_summary_header(); - while ((partition = list_next(part_i)) != NULL) { - if (params.partition == NULL - || strcmp(partition->info->name, - params.partition) == 0) - _display_partition_node_summary(partition); - } - list_iterator_destroy(part_i); -} - - -/* Formating for partiton display headers... */ -static void _print_partition_header(void) -{ - _print_str("PARTITION", part_sz_part, false); - printf(" "); - _print_str("AVAIL", part_sz_avail, false); - printf(" "); - _print_str("NODES", part_sz_num, true); - printf(" "); - _print_str("STATE", part_sz_state, false); - if (params.long_output) { - printf(" "); - _print_str("MAX_TIME", part_sz_time, true); - printf(" "); - _print_str("JOB_SIZE", part_sz_job_nodes, true); - printf(" "); - _print_str("ROOT", part_sz_root, false); - printf(" "); - _print_str("SHARE", part_sz_share, false); - printf(" "); - _print_str("GROUPS", part_size_groups, false); + + /* no match, create new sinfo_data entry */ + if (sinfo_ptr == NULL) + _create_sinfo(sinfo_list, part_ptr, node_ptr); + list_iterator_destroy(i); } - printf(" "); - _print_str("NODE_LIST", part_sz_nodes, false); - if (params.long_output) - printf("\n%s%s%s\n", dash_line_40, dash_line_40, dash_line_20); - else - printf("\n%s%s\n", dash_line_40, dash_line_40); -} - -static void _display_all_partition_info(List partitions) -{ - struct partition_summary *partition; - ListIterator part_i = list_iterator_create(partitions); - _print_partition_header(); - while ((partition = list_next(part_i)) != NULL) { - if (params.partition == NULL - || strcmp(partition->info->name, - params.partition) == 0) - _display_partition_node_info(partition); - } - list_iterator_destroy(part_i); + return SLURM_SUCCESS; } - -static void -_display_partition_node_info(struct partition_summary *partition) +static void _update_sinfo(sinfo_data_t *sinfo_ptr, partition_info_t* part_ptr, + node_info_t *node_ptr) { - char *no_name = ""; - char *name_buf = NULL, part_name[64], part_time[20], part_job_size[30]; - char part_root[10], part_share[10], *part_groups; - int line_cnt = 0, name_len = 1024; - - ListIterator node_i = list_iterator_create(partition->states); - struct node_state_summary *state_sum = NULL; - char *part_state = partition->info->state_up ? "UP" : "DOWN"; - - strcpy(part_name, partition->info->name); - if (partition->info->default_part) - strcat(part_name, "*"); - if (partition->info->max_time == -1) - strcpy(part_time, "NONE"); - else - sprintf(part_time, "%d", partition->info->max_time); - (void) _build_min_max_string(part_job_size, - partition->info->min_nodes, - partition->info->max_nodes, true); - if (partition->info->root_only) - strcpy(part_root, "YES"); - else - strcpy(part_root, "NO"); - if (partition->info->shared == 2) - strcpy(part_share, "FORCE"); - else if(partition->info->shared) - strcpy(part_share, "YES"); - else - strcpy(part_share, "NO"); - if (partition->info->allow_groups) - part_groups = partition->info->allow_groups; + 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 - part_groups = "ALL"; - - name_buf = malloc(name_len); - while ((state_sum = list_next(node_i)) != NULL) { - line_cnt++; - while ((int)hostlist_ranged_string(state_sum->nodes, - name_len, name_buf) < 0) { - name_len *= 2; - name_buf = realloc(name_buf, name_len); - } - - _print_str(part_name, part_sz_part, false); - printf(" "); - _print_str(part_state, part_sz_avail, false); - printf(" "); - _print_int(state_sum->node_count, part_sz_num, true); - printf(" "); - if (params.long_output) - _print_str(node_state_string(state_sum->state), - part_sz_state, false); - else - _print_str(node_state_string_compact(state_sum->state), - part_sz_state, false); - if (params.long_output) { - printf(" "); - _print_str(part_time, part_sz_time, true); - printf(" "); - _print_str(part_job_size, part_sz_job_nodes, true); - printf(" "); - _print_str(part_root, part_sz_root, false); - printf(" "); - _print_str(part_share, part_sz_share, false); - printf(" "); - _print_str(part_groups, part_size_groups, false); - } - printf(" "); - _print_str(name_buf, part_sz_nodes, false); - printf("\n"); - strcpy(part_name, ""); - strcpy(part_time, ""); - strcpy(part_job_size, ""); - strcpy(part_root, ""); - strcpy(part_share, ""); - part_state = no_name; - part_groups = no_name; - } - list_iterator_destroy(node_i); - - if (line_cnt == 0) { - _print_str(part_name, part_sz_part, false); - printf(" "); - _print_str(part_state, part_sz_avail, false); - printf(" "); - _print_int(0, part_sz_num, true); - printf(" "); - _print_str("N/A", part_sz_state, false); - if (params.long_output) { - printf(" "); - _print_str(part_time, part_sz_time, true); - printf(" "); - _print_str(part_job_size, part_sz_job_nodes, true); - printf(" "); - _print_str(part_root, part_sz_root, false); - printf(" "); - _print_str(part_share, part_sz_share, false); - printf(" "); - _print_str(part_groups, part_size_groups, false); - } - printf(" "); - _print_str("", part_sz_nodes, false); - printf("\n"); - } - free(name_buf); -} - -static int _build_min_max_string(char *buffer, int min, int max, bool range) -{ - if (max == min) - return sprintf(buffer, "%d", max); - else if (range) - return sprintf(buffer, "%d-%d", min, max); - else - return sprintf(buffer, "%d+", min); + 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); } -int _print_str(char *str, int width, bool right) +static void _create_sinfo(List sinfo_list, partition_info_t* part_ptr, + node_info_t *node_ptr) { - char format[64]; - int printed = 0; + sinfo_data_t *sinfo_ptr; - if (right == true && width != 0) - snprintf(format, 64, "%%%ds", width); - else if (width != 0) - snprintf(format, 64, "%%.%ds", width); - else { - format[0] = '%'; - format[1] = 's'; - format[2] = '\0'; - } - if ((printed = printf(format, str)) < 0) - return printed; + /* create an entry */ + sinfo_ptr = xmalloc(sizeof(sinfo_data_t)); - while (printed++ < width) - printf(" "); + 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++; - return printed; + 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; -int _print_int(int number, int width, bool right) -{ - char buf[32]; + sinfo_ptr->min_weight = node_ptr->weight; + sinfo_ptr->max_weight = node_ptr->weight; - snprintf(buf, 32, "%d", number); - return _print_str(buf, width, right); -} + sinfo_ptr->features = node_ptr->features; + sinfo_ptr->part_info = part_ptr; -static void _print_date(void) -{ - time_t now; + sinfo_ptr->nodes = hostlist_create(node_ptr->name); - now = time(NULL); - printf("%s", ctime(&now)); + list_append(sinfo_list, sinfo_ptr); } - -/* _node_name_string_from_list - analyzes a list of node_info_t* and - * fills in a buffer with the appropriate nodename in a - * prefix[001-100] type format. - * IN nodes - list of node_info_t* to analyze - * OUT buffer - a char buffer to store the string in - * IN buf_size - byte size of buffer - * OUT node_count - count of nodes found - * RET 0 on success, -1 on failure - */ -static int _node_name_string_from_list(List nodes, char *buffer, - int buf_size, int *node_count) +/* Return a pointer to the given partition name or NULL on error */ +static partition_info_t *_find_part(char *part_name, + partition_info_msg_t *partition_msg) { - node_info_t *curr_node = NULL; - ListIterator i = list_iterator_create(nodes); - hostlist_t list = hostlist_create(NULL); - int err; - - *node_count = 0; - while ((curr_node = list_next(i)) != NULL) { - hostlist_push(list, curr_node->name); - (*node_count)++; + int i; + for (i=0; i<partition_msg->record_count; i++) { + if (_strcmp(part_name, partition_msg->partition_array[i].name)) + continue; + return &(partition_msg->partition_array[i]); } - list_iterator_destroy(i); - - err = hostlist_ranged_string(list, buf_size, buffer); - hostlist_destroy(list); - if (err < 0) - return -1; - else - return 0; + return NULL; } -/* _node_cpus_string_from_list - analyzes a list of node_info_t* and - * fills in a buffer with CPU count, "123+" if a range. - * IN nodes - list of node_info_t* to analyze - * OUT buffer - a char buffer to store the string in. - */ -static void _node_cpus_string_from_list(List nodes, char *buffer) +static void _sort_sinfo_data(List sinfo_list) { - node_info_t *curr_node = NULL; - int min_cpus=0, max_cpus=0; - bool first = true; - ListIterator i = list_iterator_create(nodes); + if (params.node_field_flag) /* already in node order */ + return; - while ((curr_node = list_next(i)) != NULL) { - if (first) { - first = false; - min_cpus = max_cpus = curr_node->cpus; - } - else if (min_cpus > curr_node->cpus) - min_cpus = curr_node->cpus; - else if (max_cpus < curr_node->cpus) - max_cpus = curr_node->cpus; - } - list_iterator_destroy(i); - if (first) - strcpy(buffer, ""); - else - _build_min_max_string(buffer, min_cpus, max_cpus, false); + /* sort list in partition order */ + list_sort(sinfo_list, _part_order); } - -/* _node_mem_string_from_list - analyzes a list of node_info_t* and - * fills in a buffer with real memory size, "123+" if a range. - * IN nodes - list of node_info_t* to analyze - * OUT buffer - a char buffer to store the string in. - */ -static void _node_mem_string_from_list(List nodes, char *buffer) +static int _part_order (void *data1, void *data2) { - node_info_t *curr_node = NULL; - int min_mem=0, max_mem=0; - bool first = true; - ListIterator i = list_iterator_create(nodes); + sinfo_data_t *sinfo_ptr1 = data1; + sinfo_data_t *sinfo_ptr2 = data2; - while ((curr_node = list_next(i)) != NULL) { - if (first) { - first = false; - min_mem = max_mem = curr_node->real_memory; - } - else if (min_mem > curr_node->real_memory) - min_mem = curr_node->real_memory; - else if (max_mem < curr_node->real_memory) - max_mem = curr_node->real_memory; - } - list_iterator_destroy(i); - if (first) - strcpy(buffer, ""); - else - _build_min_max_string(buffer, min_mem, max_mem, false); + return _strcmp(sinfo_ptr1->part_info->name, + sinfo_ptr2->part_info->name); } -/* _node_disk_string_from_list - analyzes a list of node_info_t* and - * fills in a buffer with temporary disk size, "123+" if a range. - * IN nodes - list of node_info_t* to analyze - * OUT buffer - a char buffer to store the string in. - */ -static void _node_disk_string_from_list(List nodes, char *buffer) +static void _sinfo_list_delete(void *data) { - node_info_t *curr_node = NULL; - int min_disk=0, max_disk=0; - bool first = true; - ListIterator i = list_iterator_create(nodes); + sinfo_data_t *sinfo_ptr = data; - while ((curr_node = list_next(i)) != NULL) { - if (first) { - first = false; - min_disk = max_disk = curr_node->tmp_disk; - } - else if (min_disk > curr_node->tmp_disk) - min_disk = curr_node->tmp_disk; - else if (max_disk < curr_node->tmp_disk) - max_disk = curr_node->tmp_disk; - } - list_iterator_destroy(i); - if (first) - strcpy(buffer, ""); - else - _build_min_max_string(buffer, min_disk, max_disk, false); + hostlist_destroy(sinfo_ptr->nodes); + xfree(sinfo_ptr); } -/* _node_weight_string_from_list - analyzes a list of node_info_t* and - * fills in a buffer with their weights, "123+" if a range. - * IN nodes - list of node_info_t* to analyze - * OUT buffer - a char buffer to store the string in. - */ -static void _node_weight_string_from_list(List nodes, char *buffer) +/* like strcmp, but works with NULL pointers */ +static int _strcmp(char *data1, char *data2) { - node_info_t *curr_node = NULL; - int min_weight=0, max_weight=0; - bool first = true; - ListIterator i = list_iterator_create(nodes); - - while ((curr_node = list_next(i)) != NULL) { - if (first) { - first = false; - min_weight = max_weight = curr_node->weight; - } - else if (min_weight > curr_node->weight) - min_weight = curr_node->weight; - else if (min_weight < curr_node->weight) - max_weight = curr_node->weight; - } - list_iterator_destroy(i); - if (first) - strcpy(buffer, ""); - else - _build_min_max_string(buffer, min_weight, max_weight, false); + if (data1 == NULL) + data1 = ""; + if (data2 == NULL) + data2 = ""; + return strcmp(data1, data2); } + diff --git a/src/sinfo/sinfo.h b/src/sinfo/sinfo.h index a0b4b5c2c24e29dd57a4b110fd3ecac401cd4328..e0cf35751a21642d75c68b5595774249fe8dc3a9 100644 --- a/src/sinfo/sinfo.h +++ b/src/sinfo/sinfo.h @@ -22,9 +22,10 @@ * 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. -\*****************************************************************************/ +\****************************************************************************/ -#ifndef __SINFO_H__ +#ifndef _SINFO_H +#define _SINFO_H #if HAVE_CONFIG_H # include "config.h" @@ -32,6 +33,10 @@ #include <ctype.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> #if HAVE_INTTYPES_H # include <inttypes.h> @@ -41,47 +46,85 @@ # endif #endif /* HAVE_INTTYPES_H */ -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - #include <slurm/slurm.h> #include "src/common/hostlist.h" #include "src/common/list.h" #include "src/common/log.h" +#include "src/common/macros.h" #include "src/common/slurm_protocol_api.h" #include "src/common/xmalloc.h" +/* Collection of data for printing reports. Like data is combined here */ +typedef struct { + uint16_t node_state; -struct sinfo_parameters { - char* partition; + uint32_t nodes_alloc; + uint32_t nodes_idle; + uint32_t nodes_other; + uint32_t nodes_tot; + uint32_t min_cpus; + uint32_t max_cpus; + uint32_t min_disk; + uint32_t max_disk; + uint32_t min_mem; + uint32_t max_mem; + uint32_t min_weight; + uint32_t max_weight; + + char *features; + + hostlist_t nodes; + + /* part_info contains partition, avail, max_time, job_size, + * root, share, groups */ + partition_info_t* part_info; +} sinfo_data_t; + +/* Identify what fields must match for a node's information to be + * combined into a single sinfo_data entry based upon output format */ +struct sinfo_match_flags { + bool avail_flag; + bool features_flag; + bool groups_flag; + bool job_size_flag; + bool max_time_flag; + bool partition_flag; + bool root_flag; + bool share_flag; bool state_flag; - enum node_states state; - bool node_flag; - char* nodes; - bool summarize; +}; + +/* Input parameters */ +struct sinfo_parameters { + bool exact_match; bool long_output; bool line_wrap; - int verbose; - int iterate; - bool exact_match; -}; + bool no_header; + bool node_field_flag; + bool node_flag; + bool state_flag; + bool summarize; + struct sinfo_match_flags match_flags; -struct node_state_summary { - hostlist_t nodes; + char* format; + char* nodes; + char* partition; + + int iterate; + int node_field_size; enum node_states state; - uint32_t node_count; -}; + int verbose; -struct partition_summary { - partition_info_t* info; - List states; + List format_list; }; -int parse_state( char* str, enum job_states* states ); -int parse_command_line( int argc, char* argv[] ); -void print_options( void ); +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); #endif