blob: 5e175870b3211fd3226fab77036b15695df19846 [file] [log] [blame]
/*****************************************************************************\
* print.c - print functions for sstat
*****************************************************************************
* Copyright (C) 2006 The Regents of the University of California.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Danny Auble <da@llnl.gov>.
* CODE-OCEC-09-009. All rights reserved.
*
* This file is part of Slurm, a resource management program.
* For details, see <https://slurm.schedmd.com/>.
* Please also read the included file: DISCLAIMER.
*
* 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.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#include "sstat.h"
#include "src/common/cpu_frequency.h"
#include "src/common/parse_time.h"
#include "slurm/slurm.h"
#define FORMAT_STRING_SIZE 34
print_field_t *field = NULL;
int curr_inx = 1;
char outbuf[FORMAT_STRING_SIZE];
char *_elapsed_time(uint64_t secs, uint64_t usecs)
{
uint64_t days, hours, minutes, seconds, subsec = 0;
char *str = NULL;
if (secs == NO_VAL64)
return NULL;
if (usecs >= 1E6) {
secs += usecs / 1E6;
usecs = usecs % (int)1E6;
}
if (usecs > 0) {
/* give me 3 significant digits to tack onto the sec */
subsec = (usecs/1000);
}
seconds = secs % 60;
minutes = (secs / 60) % 60;
hours = (secs / 3600) % 24;
days = secs / 86400;
if (days)
str = xstrdup_printf("%"PRIu64"-%2.2"PRIu64":%2.2"PRIu64":%2.2"PRIu64"",
days, hours, minutes, seconds);
else if (hours)
str = xstrdup_printf("%2.2"PRIu64":%2.2"PRIu64":%2.2"PRIu64"",
hours, minutes, seconds);
else if (subsec)
str = xstrdup_printf("%2.2"PRIu64":%2.2"PRIu64".%3.3"PRIu64"",
minutes, seconds, subsec);
else
str = xstrdup_printf("00:%2.2"PRIu64":%2.2"PRIu64"",
minutes, seconds);
return str;
}
static void _print_small_double(
char *outbuf, int buf_size, double dub, int units)
{
if (fuzzy_equal(dub, NO_VAL))
return;
if (dub > 1)
convert_num_unit((double)dub, outbuf, buf_size, units, NO_VAL,
params.convert_flags);
else if (dub > 0)
snprintf(outbuf, buf_size, "%.2fM", dub);
else
snprintf(outbuf, buf_size, "0");
}
static void _print_tres_field(char *tres_in, char *nodes, bool convert)
{
char *tmp_char = slurmdb_make_tres_string_from_simple(
tres_in, assoc_mgr_tres_list,
convert ? params.units : NO_VAL,
convert ? params.convert_flags : CONVERT_NUM_UNIT_RAW,
TRES_STR_FLAG_BYTES,
nodes);
field->print_routine(field, tmp_char, (curr_inx == field_count));
xfree(tmp_char);
return;
}
void print_fields(slurmdb_step_rec_t *step)
{
// print_field_t *field = NULL;
// int curr_inx = 1;
// char outbuf[FORMAT_STRING_SIZE];
curr_inx = 1;
list_iterator_reset(print_fields_itr);
while ((field = list_next(print_fields_itr))) {
char *tmp_char = NULL;
uint64_t tmp_uint64 = NO_VAL64;
memset(&outbuf, 0, sizeof(outbuf));
switch(field->type) {
case PRINT_AVECPU:
tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_ave, TRES_CPU);
if (tmp_uint64 != NO_VAL64) {
tmp_uint64 /= CPU_TIME_ADJ;
tmp_char = _elapsed_time((long)tmp_uint64, 0);
}
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_ACT_CPUFREQ:
convert_num_unit2((double)step->stats.act_cpufreq,
outbuf, sizeof(outbuf), UNIT_KILO,
NO_VAL, 1000, params.convert_flags &
(~CONVERT_NUM_UNIT_EXACT));
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_CONSUMED_ENERGY:
if (!fuzzy_equal(step->stats.consumed_energy,
NO_VAL64)) {
convert_num_unit2((double)
step->stats.consumed_energy,
outbuf, sizeof(outbuf),
UNIT_NONE, NO_VAL, 1000,
params.convert_flags &
(~CONVERT_NUM_UNIT_EXACT));
}
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_CONSUMED_ENERGY_RAW:
field->print_routine(field,
&step->stats.consumed_energy,
(curr_inx == field_count));
break;
case PRINT_AVEDISKREAD:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_ave,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
_print_small_double(outbuf, sizeof(outbuf),
(double)tmp_uint64,
UNIT_NONE);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_AVEDISKWRITE:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_out_ave,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
_print_small_double(outbuf, sizeof(outbuf),
(double)tmp_uint64,
UNIT_NONE);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_AVEPAGES:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_ave,
TRES_PAGES)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_AVERSS:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_ave,
TRES_MEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_AVEVSIZE:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_ave,
TRES_VMEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_JOBID:
log_build_step_id_str(&step->step_id, outbuf,
sizeof(outbuf),
STEP_ID_FLAG_NO_PREFIX);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXDISKREAD:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_max,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
_print_small_double(outbuf, sizeof(outbuf),
(double)tmp_uint64,
UNIT_NONE);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXDISKREADNODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_nodeid,
TRES_FS_DISK),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MAXDISKREADTASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_taskid,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_MAXDISKWRITE:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_out_max,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
_print_small_double(outbuf, sizeof(outbuf),
(double)tmp_uint64,
UNIT_NONE);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXDISKWRITENODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_out_max_nodeid,
TRES_FS_DISK),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MAXDISKWRITETASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_out_max_taskid,
TRES_FS_DISK)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_MAXPAGES:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_max,
TRES_PAGES)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXPAGESNODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_nodeid,
TRES_PAGES),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MAXPAGESTASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_taskid,
TRES_PAGES)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_MAXRSS:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_max,
TRES_MEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXRSSNODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_nodeid,
TRES_MEM),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MAXRSSTASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_taskid,
TRES_MEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_MAXVSIZE:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_max,
TRES_VMEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64)
convert_num_unit((double)tmp_uint64, outbuf,
sizeof(outbuf), UNIT_NONE, NO_VAL,
params.convert_flags);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_MAXVSIZENODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_nodeid,
TRES_VMEM),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MAXVSIZETASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_max_taskid,
TRES_VMEM)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_MINCPU:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.tres_usage_in_min,
TRES_CPU)) == INFINITE64)
tmp_uint64 = NO_VAL64;
if (tmp_uint64 != NO_VAL64) {
tmp_uint64 /= CPU_TIME_ADJ;
tmp_char = _elapsed_time((long)tmp_uint64, 0);
}
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MINCPUNODE:
tmp_char = find_hostname(
slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_min_nodeid,
TRES_CPU),
step->nodes);
field->print_routine(field,
tmp_char,
(curr_inx == field_count));
xfree(tmp_char);
break;
case PRINT_MINCPUTASK:
if ((tmp_uint64 = slurmdb_find_tres_count_in_string(
step->stats.
tres_usage_in_min_taskid,
TRES_CPU)) == INFINITE64)
tmp_uint64 = NO_VAL64;
field->print_routine(field,
&tmp_uint64,
(curr_inx == field_count));
break;
case PRINT_TRESA:
tmp_char = step->tres_alloc_str;
field->print_routine(field, tmp_char,
(curr_inx == field_count));
break;
case PRINT_TRESUIA:
_print_tres_field(step->stats.tres_usage_in_ave,
NULL, 1);
break;
case PRINT_TRESUIM:
_print_tres_field(step->stats.tres_usage_in_max,
NULL, 1);
break;
case PRINT_TRESUIMN:
_print_tres_field(step->stats.tres_usage_in_max_nodeid,
step->nodes, 0);
break;
case PRINT_TRESUIMT:
_print_tres_field(step->stats.tres_usage_in_max_taskid,
NULL, 0);
break;
case PRINT_TRESUIMI:
_print_tres_field(step->stats.tres_usage_in_min,
NULL, 1);
break;
case PRINT_TRESUIMIN:
_print_tres_field(step->stats.tres_usage_in_min_nodeid,
step->nodes, 0);
break;
case PRINT_TRESUIMIT:
_print_tres_field(step->stats.tres_usage_in_min_taskid,
NULL, 0);
break;
case PRINT_TRESUIT:
_print_tres_field(step->stats.tres_usage_in_tot,
NULL, 1);
break;
case PRINT_TRESUOA:
_print_tres_field(step->stats.tres_usage_out_ave,
NULL, 1);
break;
case PRINT_TRESUOM:
_print_tres_field(step->stats.tres_usage_out_max,
NULL, 1);
break;
case PRINT_TRESUOMN:
_print_tres_field(step->stats.tres_usage_out_max_nodeid,
step->nodes, 0);
break;
case PRINT_TRESUOMT:
_print_tres_field(step->stats.tres_usage_out_max_taskid,
NULL, 0);
break;
case PRINT_TRESUOMI:
_print_tres_field(step->stats.tres_usage_out_min,
NULL, 1);
break;
case PRINT_TRESUOMIN:
_print_tres_field(step->stats.tres_usage_out_min_nodeid,
step->nodes, 0);
break;
case PRINT_TRESUOMIT:
_print_tres_field(step->stats.tres_usage_out_min_taskid,
NULL, 0);
break;
case PRINT_TRESUOT:
_print_tres_field(step->stats.tres_usage_out_tot,
NULL, 1);
break;
case PRINT_NODELIST:
field->print_routine(field,
step->nodes,
(curr_inx == field_count));
break;
case PRINT_NTASKS:
field->print_routine(field,
&step->ntasks,
(curr_inx == field_count));
break;
case PRINT_PIDS:
field->print_routine(field,
step->pid_str,
(curr_inx == field_count));
break;
case PRINT_REQ_CPUFREQ_MIN:
cpu_freq_to_string(outbuf, sizeof(outbuf),
step->req_cpufreq_min);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_REQ_CPUFREQ_MAX:
cpu_freq_to_string(outbuf, sizeof(outbuf),
step->req_cpufreq_max);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
case PRINT_REQ_CPUFREQ_GOV:
cpu_freq_to_string(outbuf, sizeof(outbuf),
step->req_cpufreq_gov);
field->print_routine(field,
outbuf,
(curr_inx == field_count));
break;
default:
break;
}
curr_inx++;
}
printf("\n");
}