Add .gitignore file
[s390-tools.git] / ziomon / ziorep_utilization.cpp
blobac4576fc7e8d3371403de15f443e4dbc6677a4a1
1 /*
2 * FCP report generators
4 * Utilization report program
6 * Copyright IBM Corp. 2008
7 * Author(s): Stefan Raspl <raspl@linux.vnet.ibm.com>
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <getopt.h>
13 #include <linux/types.h>
14 #define __STDC_LIMIT_MACROS
15 #include <stdint.h>
16 #include <assert.h>
17 #include <limits.h>
19 #include <list>
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"
28 extern "C" {
29 #include "ziomon_msg_tools.h"
33 using std::list;
36 const char *toolname = "ziorep_utilization";
37 int verbose=0;
40 struct options {
41 __u64 begin;
42 __u64 end;
43 __u32 interval;
44 list<__u32> chpids;
45 __u64 topline;
46 char* filename;
47 bool print_summary;
48 bool csv_export;
52 static void init_opts(struct options *opts)
54 opts->begin = 0;
55 opts->end = UINT64_MAX;
56 opts->interval = UINT32_MAX;
57 opts->topline = 0;
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"
80 " data.\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"
84 " E.g. '-c 32a'\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)
105 int c;
106 int index;
107 int rc;
108 __u32 tmp;
109 long tmpl;
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'},
121 { 0, 0, 0, 0 }
124 if (argc < 2) {
125 print_help();
126 return 1;
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) {
132 switch (c) {
133 case 'V':
134 verbose++;
135 break;
136 case 'h':
137 print_help();
138 return 1;
139 case 'v':
140 print_version();
141 return 1;
142 case 'b':
143 if (get_datetime_val(optarg, &opts->begin))
144 return -1;
145 break;
146 case 'e':
147 if (get_datetime_val(optarg, &opts->end))
148 return -1;
149 break;
150 case 'i':
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,
154 optarg);
155 return -1;
157 if (tmpl < 0) {
158 fprintf(stderr, "%s: Argument %s must be greater than or"
159 " equal to 0.", toolname, optarg);
160 return -1;
162 opts->interval = tmpl;
163 break;
164 case 's':
165 opts->print_summary = true;
166 break;
167 case 'c':
168 rc = sscanf(optarg, "%x", &tmp);
169 if (rc != 1) {
170 fprintf(stderr, "Error: Could not read chpid"
171 " %s\n", optarg);
172 return -1;
174 opts->chpids.push_back(tmp);
175 break;
176 case 'x':
177 opts->csv_export = true;
178 break;
179 case 't':
180 if (parse_topline_arg(optarg, &opts->topline))
181 return -1;
182 break;
183 default:
184 fprintf(stderr, "%s: Try '%s --help' for"
185 " more information.\n", toolname, toolname);
186 return -1;
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);
194 return -1;
197 return 0;
201 static int check_opts(struct options *opts, ConfigReader **cfg)
203 int rc = 0;
205 // check filename
206 if (!opts->filename) {
207 fprintf(stderr, "%s: No filename"
208 " specified.\n", toolname);
209 return -2;
211 else {
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);
231 // check config
232 *cfg = new ConfigReader(&rc, opts->filename);
233 if (rc)
234 return -1;
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);
242 rc = -2;
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);
250 opts->topline = 0;
253 if (!opts->print_summary
254 && adjust_timeframe(opts->filename, &opts->begin, &opts->end,
255 &opts->interval))
256 rc = -3;
258 return rc;
262 static int print_reports(struct options *opts, ConfigReader &cfg)
264 int rc = 0;
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;
270 list<__u32> devnos;
271 list<__u32> chpids;
272 list<MsgTypes> type_flt;
273 AggregationCollapser *col = NULL;
274 FILE *fp;
276 if (opts->chpids.size())
277 chpids = opts->chpids;
278 else
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);
300 if (!fp)
301 goto out;
303 else
304 fp = stdout;
306 if ( (rc = print_report(fp, opts->begin, opts->end,
307 opts->interval, opts->filename, opts->topline,
308 &type_flt, dev_filt, noop_col,
309 physPrnt)) < 0 ) {
310 rc = -3;
311 goto out1;
314 if (rc == 0)
315 fprintf(stderr, "%s: No eligible data found.\n", toolname);
317 if (opts->csv_export) {
318 fclose(fp);
319 fp = open_csv_output_file(opts->filename,
320 "_util_virt_adpt.csv", &rc);
321 if (!fp)
322 goto out;
324 else {
325 fp = stdout;
326 fputc('\n', fp);
329 if (print_report(fp, opts->begin, opts->end, opts->interval,
330 opts->filename, opts->topline, NULL, dev_filt,
331 *col, virtPrnt)) {
332 rc = -4;
333 goto out1;
336 out1:
337 if (opts->csv_export)
338 fclose(fp);
339 out:
340 delete col;
342 return rc;
346 int main(int argc, char **argv)
348 int rc;
349 struct options opts;
350 ConfigReader *cfg = NULL;
352 verbose = 0;
354 init_opts(&opts);
355 if ( (rc = parse_params(argc, argv, &opts)) ) {
356 if (rc == 1)
357 rc = 0;
358 goto out;
360 if ( (rc = check_opts(&opts, &cfg)) )
361 goto out;
363 if (opts.print_summary)
364 rc = print_summary_report(stdout, opts.filename, *cfg);
365 else
366 rc = print_reports(&opts, *cfg);
368 out:
369 delete cfg;
371 return rc;