2 * FCP report generators
4 * Utilization report program
6 * Copyright IBM Corp. 2008
7 * Author(s): Stefan Raspl <raspl@linux.vnet.ibm.com>
13 #include <linux/types.h>
14 #define __STDC_LIMIT_MACROS
21 #include "zt_common.h"
22 #include "ziorep_framer.hpp"
23 #include "ziorep_printers.hpp"
24 #include "ziorep_frameset.hpp"
25 #include "ziorep_utils.hpp"
26 #include "ziorep_collapser.hpp"
29 #include "ziomon_msg_tools.h"
36 const char *toolname
= "ziorep_utilization";
52 static void init_opts(struct options
*opts
)
55 opts
->end
= UINT64_MAX
;
56 opts
->interval
= UINT32_MAX
;
58 opts
->filename
= NULL
;
59 opts
->print_summary
= false;
60 opts
->csv_export
= false;
64 static const char help_text
[] =
65 "Usage: ziorep_utilization [-V] [-v] [-h] [-b <begin>] [-e <end>] [-i <time>]\n"
66 " [-x] [-s] [-c <chpid>] [-t <num>] <filename>\n\n"
67 "-h, --help Print usage information and exit.\n"
68 "-v, --version Print version information and exit.\n"
69 "-V, --verbose Be verbose.\n"
70 "-b, --begin <begin> Do not consider data earlier than 'begin'.\n"
71 " Defaults to begin of available data.\n"
72 " Format is YYYY-MM-DD HH:MM[:SS],\n"
73 " e.g. '-b \"2008-03-21 09:08\"\n"
74 "-e, --end <end> Do not consider data later than 'end'.\n"
75 " Defaults to end of available data.\n"
76 " Format is YYYY-MM-DD HH:MM[:SS],\n"
77 " e.g. '-e \"2008-03-21 09:08:57\"\n"
78 "-i, --interval <time> Set aggregation interval to 'time' in seconds.\n"
79 " Must be a multiple of the interval size of the source\n"
81 " Set to 0 to aggregate over all data.\n"
82 "-s, --summary Show a summary of the data.\n"
83 "-c, --chpid <chpid> Select physical adapter in hex.\n"
85 "-x, --export-csv Export data to files in CSV format.\n"
86 "-t, --topline <num> Repeat topline after every 'num' frames.\n"
87 " 0 for no repeat (default).\n";
90 static void print_help()
92 printf("%s", help_text
);
96 static void print_version()
98 printf("%s: Utilization report generator version %s\n"
99 "Copyright IBM Corp. 2008\n", toolname
, RELEASE_STRING
);
103 static int parse_params(int argc
, char **argv
, struct options
*opts
)
110 static struct option long_options
[] = {
111 { "version", no_argument
, NULL
, 'v'},
112 { "help", no_argument
, NULL
, 'h'},
113 { "verbose", no_argument
, NULL
, 'V'},
114 { "begin", required_argument
, NULL
, 'b'},
115 { "end", required_argument
, NULL
, 'e'},
116 { "interval", required_argument
, NULL
, 'i'},
117 { "summary", no_argument
, NULL
, 's'},
118 { "chpid", required_argument
, NULL
, 'c'},
119 { "export-csv", no_argument
, NULL
, 'x'},
120 { "topline", required_argument
, NULL
, 't'},
129 assert(sizeof(long long int) == sizeof(__u64
));
130 while ((c
= getopt_long(argc
, argv
, "b:e:i:c:t:xshvV",
131 long_options
, &index
)) != EOF
) {
143 if (get_datetime_val(optarg
, &opts
->begin
))
147 if (get_datetime_val(optarg
, &opts
->end
))
151 if (sscanf(optarg
, "%lu", &tmpl
) != 1) {
152 fprintf(stderr
, "%s: Cannot parse %s as an integer value."
153 " Please correct and try again.\n", toolname
,
158 fprintf(stderr
, "%s: Argument %s must be greater than or"
159 " equal to 0.", toolname
, optarg
);
162 opts
->interval
= tmpl
;
165 opts
->print_summary
= true;
168 rc
= sscanf(optarg
, "%x", &tmp
);
170 fprintf(stderr
, "Error: Could not read chpid"
174 opts
->chpids
.push_back(tmp
);
177 opts
->csv_export
= true;
180 if (parse_topline_arg(optarg
, &opts
->topline
))
184 fprintf(stderr
, "%s: Try '%s --help' for"
185 " more information.\n", toolname
, toolname
);
189 if (optind
== argc
- 1)
190 opts
->filename
= argv
[optind
];
191 if (optind
< argc
- 1) {
192 fprintf(stderr
, "%s: Multiple filenames"
193 " specified. Specify only a single one at a time.\n", toolname
);
201 static int check_opts(struct options
*opts
, ConfigReader
**cfg
)
206 if (!opts
->filename
) {
207 fprintf(stderr
, "%s: No filename"
208 " specified.\n", toolname
);
212 if (strncmp(opts
->filename
+ strlen(opts
->filename
)
213 - strlen(DACC_FILE_EXT_LOG
), DACC_FILE_EXT_LOG
,
214 strlen(DACC_FILE_EXT_LOG
)) == 0) {
215 verbose_msg("Filename carries " DACC_FILE_EXT_LOG
216 " extension - stripping\n");
217 opts
->filename
[strlen(opts
->filename
)
218 - strlen(DACC_FILE_EXT_LOG
)] = '\0';
220 if (strncmp(opts
->filename
+ strlen(opts
->filename
)
221 - strlen(DACC_FILE_EXT_AGG
), DACC_FILE_EXT_AGG
,
222 strlen(DACC_FILE_EXT_AGG
)) == 0) {
223 verbose_msg("Filename carries " DACC_FILE_EXT_AGG
224 " extension - stripping\n");
225 opts
->filename
[strlen(opts
->filename
)
226 - strlen(DACC_FILE_EXT_AGG
)] = '\0';
228 verbose_msg("Filename is %s\n", opts
->filename
);
232 *cfg
= new ConfigReader(&rc
, opts
->filename
);
236 // check optional chpids
237 for (list
<__u32
>::const_iterator i
= opts
->chpids
.begin();
238 i
!= opts
->chpids
.end(); ++i
) {
239 if (!(*cfg
)->verify_chpid(*i
)) {
240 fprintf(stderr
, "Error: Could not find chpid %x in"
241 " configuration.\n", *i
);
246 if (opts
->csv_export
&& opts
->topline
> 0) {
247 fprintf(stderr
, "%s: Warning: Both, topline"
248 " repeat and CSV export activated, deactivating"
249 " topline repeat.\n", toolname
);
253 if (!opts
->print_summary
254 && adjust_timeframe(opts
->filename
, &opts
->begin
, &opts
->end
,
262 static int print_reports(struct options
*opts
, ConfigReader
&cfg
)
265 PhysAdapterPrinter
physPrnt(&cfg
, opts
->csv_export
);
266 VirtAdapterPrinter
virtPrnt(&cfg
, opts
->csv_export
);
267 Aggregator agg
= devno
;
268 StagedDeviceFilter dev_filt
;
269 NoopCollapser noop_col
;
272 list
<MsgTypes
> type_flt
;
273 AggregationCollapser
*col
= NULL
;
276 if (opts
->chpids
.size())
277 chpids
= opts
->chpids
;
279 cfg
.get_unique_chpids(chpids
);
281 cfg
.get_unique_mms(devnos
);
283 // add all HBAs and all devices connected to them
284 for (list
<__u32
>::const_iterator i
= chpids
.begin();
285 i
!= chpids
.end(); ++i
) {
286 cfg
.get_devnos_by_chpid(devnos
, *i
);
287 for (list
<__u32
>::const_iterator j
= devnos
.begin();
288 j
!= devnos
.end(); ++j
)
289 dev_filt
.stage_devno(*j
);
291 dev_filt
.finish(cfg
, false);
293 col
= new AggregationCollapser(cfg
, agg
, dev_filt
, &rc
);
295 type_flt
.push_back(utilization
);
297 if (opts
->csv_export
) {
298 fp
= open_csv_output_file(opts
->filename
,
299 "_util_phys_adpt.csv", &rc
);
306 if ( (rc
= print_report(fp
, opts
->begin
, opts
->end
,
307 opts
->interval
, opts
->filename
, opts
->topline
,
308 &type_flt
, dev_filt
, noop_col
,
315 fprintf(stderr
, "%s: No eligible data found.\n", toolname
);
317 if (opts
->csv_export
) {
319 fp
= open_csv_output_file(opts
->filename
,
320 "_util_virt_adpt.csv", &rc
);
329 if (print_report(fp
, opts
->begin
, opts
->end
, opts
->interval
,
330 opts
->filename
, opts
->topline
, NULL
, dev_filt
,
337 if (opts
->csv_export
)
346 int main(int argc
, char **argv
)
350 ConfigReader
*cfg
= NULL
;
355 if ( (rc
= parse_params(argc
, argv
, &opts
)) ) {
360 if ( (rc
= check_opts(&opts
, &cfg
)) )
363 if (opts
.print_summary
)
364 rc
= print_summary_report(stdout
, opts
.filename
, *cfg
);
366 rc
= print_reports(&opts
, *cfg
);