| /*****************************************************************************\ |
| * 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"); |
| } |