Skip to content
Snippets Groups Projects
Commit 77559b0f authored by Moe Jette's avatar Moe Jette
Browse files

Major changes in sinfo, output format changes and environment variables added.

Major restructuring of the sinfo code.
parent e11277ab
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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, &params.partition,
OPT_PARTITION, "report on specific partition", "PARTITION"},
{"nodes", 'n', POPT_ARG_STRING, &params.nodes, OPT_NODE,
{"nodes", 'n', POPT_ARG_STRING, &params.nodes, OPT_NODES,
"report on specific node(s)", "NODES"},
{"Node", 'N', POPT_ARG_NONE, &params.node_flag, OPT_FORMAT,
{"Node", 'N', POPT_ARG_NONE, &params.node_flag, OPT_NODE,
"Node-centric format", NULL},
{"long", 'l', POPT_ARG_NONE, &params.long_output,
OPT_FORMAT, "long output - displays more information",
OPT_LONG, "long output - displays more information",
NULL},
{"summarize", 's', POPT_ARG_NONE, &params.summarize,
OPT_FORMAT,"report state summary only", NULL},
OPT_SHORT,"report state summary only", NULL},
{"verbose", 'v', POPT_ARG_NONE, &params.verbose,
OPT_VERBOSE, "verbosity level", "level"},
{"noheader", 'h', POPT_ARG_NONE, &params.no_header,
OPT_NO_HEAD, "no headers on output", NULL},
{"format", 'o', POPT_ARG_STRING, &params.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");
}
/*****************************************************************************\
* 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;
}
/*****************************************************************************\
* 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
......@@ -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);
}
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment