[PATCH] Correct netcat examples
[blktrace.git] / blkparse.c
CommitLineData
d956a2cd
JA
1/*
2 * block queue tracing parse application
3 *
4 * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
d0ca268b
JA
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <stdlib.h>
8fc0abbc 27#include <string.h>
d5396421 28#include <getopt.h>
412819ce
JA
29#include <errno.h>
30#include <signal.h>
d0ca268b 31
8fc0abbc
JA
32#include "blktrace.h"
33#include "rbtree.h"
d0ca268b 34
cfab07eb
AB
35#define SECONDS(x) ((unsigned long long)(x) / 1000000000)
36#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000)
37
d5396421
JA
38static int backwards;
39static unsigned long long genesis_time, last_reported_time;
40
41struct per_cpu_info {
d0ca268b
JA
42 int cpu;
43 int nelems;
d0ca268b
JA
44
45 int fd;
87b72777 46 char fname[128];
d0ca268b 47
87b72777
JA
48 FILE *ofp;
49 char ofname[128];
8fc0abbc 50
5c017e4b 51 unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites;
afd2d7ad 52 unsigned long ireads, iwrites;
5c017e4b 53 unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb;
afd2d7ad 54 unsigned long long iread_kb, iwrite_kb;
d0ca268b
JA
55};
56
79f19470 57#define S_OPTS "i:o:b:"
d5396421
JA
58static struct option l_opts[] = {
59 {
60 .name = "input",
61 .has_arg = 1,
62 .flag = NULL,
63 .val = 'i'
64 },
65 {
66 .name = "output",
67 .has_arg = 1,
68 .flag = NULL,
69 .val = 'o'
70 },
79f19470
JA
71 {
72 .name = "batch",
73 .has_arg = 1,
74 .flag = NULL,
75 .val = 'b'
76 },
d5396421
JA
77 {
78 .name = NULL,
79 .has_arg = 0,
80 .flag = NULL,
81 .val = 0
82 }
83};
84
8fc0abbc
JA
85static struct rb_root rb_root;
86
87struct trace {
88 struct blk_io_trace *bit;
89 struct rb_node rb_node;
90};
91
a718bd37
NS
92static int max_cpus;
93static struct per_cpu_info *per_cpu_info;
d0ca268b 94
87b72777
JA
95static unsigned long long events;
96
d5396421 97static char *dev, *output_name;
d0ca268b 98
79f19470
JA
99#define RB_BATCH_DEFAULT (1024)
100static int rb_batch = RB_BATCH_DEFAULT;
101
412819ce
JA
102#define is_done() (*(volatile int *)(&done))
103static volatile int done;
104
a718bd37
NS
105static void resize_cpu_info(int cpuid)
106{
107 int new_space, new_max = cpuid + 1;
108 char *new_start;
109
110 per_cpu_info = realloc(per_cpu_info, new_max * sizeof(*per_cpu_info));
111 if (!per_cpu_info) {
112 fprintf(stderr, "Cannot allocate CPU info -- %d x %d bytes\n",
113 new_max, (int) sizeof(*per_cpu_info));
114 exit(1);
115 }
116
117 new_start = (char *)per_cpu_info + (max_cpus * sizeof(*per_cpu_info));
118 new_space = (new_max - max_cpus) * sizeof(*per_cpu_info);
119 memset(new_start, 0, new_space);
120 max_cpus = new_max;
121}
122
123static struct per_cpu_info *get_cpu_info(int cpu)
124{
c499bf38
JA
125 struct per_cpu_info *pci;
126
a718bd37
NS
127 if (cpu >= max_cpus)
128 resize_cpu_info(cpu);
129
c499bf38
JA
130 /*
131 * ->cpu might already be set, but just set it unconditionally
132 */
133 pci = &per_cpu_info[cpu];
134 pci->cpu = cpu;
135
136 return pci;
a718bd37
NS
137}
138
cfab07eb
AB
139static inline void check_time(struct blk_io_trace *bit)
140{
141 unsigned long long this = bit->time;
142 unsigned long long last = last_reported_time;
143
144 backwards = (this < last) ? 'B' : ' ';
145 last_reported_time = this;
146}
147
d5396421 148static inline void account_m(struct per_cpu_info *pci, int rw,
5c017e4b 149 unsigned int bytes)
d0ca268b
JA
150{
151 if (rw) {
d5396421
JA
152 pci->mwrites++;
153 pci->qwrite_kb += bytes >> 10;
d0ca268b 154 } else {
d5396421
JA
155 pci->mreads++;
156 pci->qread_kb += bytes >> 10;
d0ca268b
JA
157 }
158}
159
d5396421 160static inline void account_q(struct per_cpu_info *pci, int rw,
5c017e4b 161 unsigned int bytes)
d0ca268b
JA
162{
163 if (rw) {
d5396421
JA
164 pci->qwrites++;
165 pci->qwrite_kb += bytes >> 10;
d0ca268b 166 } else {
d5396421
JA
167 pci->qreads++;
168 pci->qread_kb += bytes >> 10;
d0ca268b
JA
169 }
170}
171
d5396421 172static inline void account_c(struct per_cpu_info *pci, int rw,
5c017e4b 173 unsigned int bytes)
d0ca268b
JA
174{
175 if (rw) {
d5396421
JA
176 pci->cwrites++;
177 pci->cwrite_kb += bytes >> 10;
d0ca268b 178 } else {
d5396421
JA
179 pci->creads++;
180 pci->cread_kb += bytes >> 10;
d0ca268b
JA
181 }
182}
183
d5396421 184static inline void account_i(struct per_cpu_info *pci, int rw,
afd2d7ad 185 unsigned int bytes)
186{
187 if (rw) {
d5396421
JA
188 pci->iwrites++;
189 pci->iwrite_kb += bytes >> 10;
afd2d7ad 190 } else {
d5396421
JA
191 pci->ireads++;
192 pci->iread_kb += bytes >> 10;
afd2d7ad 193 }
194}
195
d5396421 196static void output(struct per_cpu_info *pci, char *s)
d0ca268b
JA
197{
198 printf("%s", s);
d5396421
JA
199
200 if (pci->ofp)
33b56019 201 fprintf(pci->ofp, "%s", s);
d0ca268b
JA
202}
203
3aabcd89
JA
204static char hstring[256];
205static char tstring[256];
d0ca268b 206
d5396421
JA
207static inline char *setup_header(struct per_cpu_info *pci,
208 struct blk_io_trace *t, char act)
d0ca268b
JA
209{
210 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
211 int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER);
212 int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
213 char rwbs[4];
214 int i = 0;
215
216 if (w)
217 rwbs[i++] = 'W';
218 else
219 rwbs[i++] = 'R';
220 if (b)
221 rwbs[i++] = 'B';
222 if (s)
223 rwbs[i++] = 'S';
224
225 rwbs[i] = '\0';
226
cfab07eb 227 sprintf(hstring, "%c %3d %15ld %5Lu.%09Lu %5u %c %3s", backwards,
d5396421 228 pci->cpu,
cfab07eb
AB
229 (unsigned long)t->sequence, SECONDS(t->time),
230 NANO_SECONDS(t->time), t->pid, act, rwbs);
d0ca268b
JA
231
232 return hstring;
233}
234
d5396421
JA
235static void log_complete(struct per_cpu_info *pci, struct blk_io_trace *t,
236 char act)
d0ca268b 237{
d5396421 238 sprintf(tstring,"%s %Lu + %u [%d]\n", setup_header(pci, t, act),
d0ca268b 239 (unsigned long long)t->sector, t->bytes >> 9, t->error);
d5396421 240 output(pci, tstring);
d0ca268b
JA
241}
242
d5396421
JA
243static void log_queue(struct per_cpu_info *pci, struct blk_io_trace *t,
244 char act)
d0ca268b 245{
2955af9d
NS
246 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
247 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 248 output(pci, tstring);
d0ca268b
JA
249}
250
d5396421
JA
251static void log_issue(struct per_cpu_info *pci, struct blk_io_trace *t,
252 char act)
d0ca268b 253{
2955af9d
NS
254 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
255 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 256 output(pci, tstring);
d0ca268b
JA
257}
258
d5396421
JA
259static void log_merge(struct per_cpu_info *pci, struct blk_io_trace *t,
260 char act)
d0ca268b 261{
2955af9d
NS
262 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
263 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 264 output(pci, tstring);
d0ca268b
JA
265}
266
d5396421
JA
267static void log_generic(struct per_cpu_info *pci, struct blk_io_trace *t,
268 char act)
d0ca268b 269{
2955af9d
NS
270 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
271 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 272 output(pci, tstring);
d0ca268b
JA
273}
274
d5396421 275static int log_pc(struct per_cpu_info *pci, struct blk_io_trace *t, char act)
d0ca268b 276{
87b72777
JA
277 unsigned char *buf;
278 int i;
d0ca268b 279
d5396421
JA
280 sprintf(tstring,"%s ", setup_header(pci, t, act));
281 output(pci, tstring);
d0ca268b 282
87b72777 283 buf = (unsigned char *) t + sizeof(*t);
d0ca268b
JA
284 for (i = 0; i < t->pdu_len; i++) {
285 sprintf(tstring,"%02x ", buf[i]);
d5396421 286 output(pci, tstring);
d0ca268b
JA
287 }
288
289 if (act == 'C') {
2955af9d
NS
290 sprintf(tstring,"[%d]\n", t->error);
291 output(pci, tstring);
292 } else {
293 sprintf(tstring,"[%s]\n", t->comm);
d5396421 294 output(pci, tstring);
d0ca268b 295 }
87b72777 296 return 0;
d0ca268b
JA
297}
298
d5396421 299static int dump_trace_pc(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b 300{
87b72777
JA
301 int ret = 0;
302
d0ca268b
JA
303 switch (t->action & 0xffff) {
304 case __BLK_TA_QUEUE:
d5396421 305 log_generic(pci, t, 'Q');
d0ca268b
JA
306 break;
307 case __BLK_TA_GETRQ:
d5396421 308 log_generic(pci, t, 'G');
d0ca268b
JA
309 break;
310 case __BLK_TA_SLEEPRQ:
d5396421 311 log_generic(pci, t, 'S');
d0ca268b
JA
312 break;
313 case __BLK_TA_REQUEUE:
d5396421 314 log_generic(pci, t, 'R');
d0ca268b
JA
315 break;
316 case __BLK_TA_ISSUE:
d5396421 317 ret = log_pc(pci, t, 'D');
d0ca268b
JA
318 break;
319 case __BLK_TA_COMPLETE:
d5396421 320 log_pc(pci, t, 'C');
d0ca268b
JA
321 break;
322 default:
323 fprintf(stderr, "Bad pc action %x\n", t->action);
87b72777
JA
324 ret = 1;
325 break;
d0ca268b
JA
326 }
327
87b72777 328 return ret;
d0ca268b
JA
329}
330
d5396421 331static void dump_trace_fs(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b
JA
332{
333 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
334
335 switch (t->action & 0xffff) {
336 case __BLK_TA_QUEUE:
d5396421
JA
337 account_q(pci, w, t->bytes);
338 log_queue(pci, t, 'Q');
d0ca268b
JA
339 break;
340 case __BLK_TA_BACKMERGE:
d5396421
JA
341 account_m(pci, w, t->bytes);
342 log_merge(pci, t, 'M');
d0ca268b
JA
343 break;
344 case __BLK_TA_FRONTMERGE:
d5396421
JA
345 account_m(pci, w, t->bytes);
346 log_merge(pci, t, 'F');
d0ca268b
JA
347 break;
348 case __BLK_TA_GETRQ:
d5396421 349 log_generic(pci, t, 'G');
d0ca268b
JA
350 break;
351 case __BLK_TA_SLEEPRQ:
d5396421 352 log_generic(pci, t, 'S');
d0ca268b
JA
353 break;
354 case __BLK_TA_REQUEUE:
d5396421
JA
355 account_c(pci, w, -t->bytes);
356 log_queue(pci, t, 'R');
d0ca268b
JA
357 break;
358 case __BLK_TA_ISSUE:
d5396421
JA
359 account_i(pci, w, t->bytes);
360 log_issue(pci, t, 'D');
d0ca268b
JA
361 break;
362 case __BLK_TA_COMPLETE:
d5396421
JA
363 account_c(pci, w, t->bytes);
364 log_complete(pci, t, 'C');
d0ca268b
JA
365 break;
366 default:
367 fprintf(stderr, "Bad fs action %x\n", t->action);
1f79c4a0 368 break;
d0ca268b 369 }
d0ca268b
JA
370}
371
d5396421 372static int dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b 373{
87b72777
JA
374 int ret = 0;
375
33b56019
JA
376 if (output_name && !pci->ofp) {
377 snprintf(pci->ofname, sizeof(pci->ofname) - 1,
378 "%s_log.%d", output_name, pci->cpu);
379
380 pci->ofp = fopen(pci->ofname, "w");
381 if (pci->ofp == NULL) {
382 perror(pci->ofname);
383 return 1;
384 }
385 }
386
d0ca268b 387 if (t->action & BLK_TC_ACT(BLK_TC_PC))
d5396421 388 ret = dump_trace_pc(t, pci);
d0ca268b 389 else
d5396421 390 dump_trace_fs(t, pci);
87b72777
JA
391
392 events++;
393 return ret;
d0ca268b
JA
394}
395
d5396421 396static void dump_pci_stats(struct per_cpu_info *pci)
5c017e4b 397{
0a6b8fc4
NS
398 printf(" Reads Queued: %'8lu, %'8LuKiB\t", pci->qreads, pci->qread_kb);
399 printf(" Writes Queued: %'8lu, %'8LuKiB\n", pci->qwrites,pci->qwrite_kb);
400
401 printf(" Read Dispatches: %'8lu, %'8LuKiB\t", pci->ireads, pci->iread_kb);
402 printf(" Write Dispatches: %'8lu, %'8LuKiB\n", pci->iwrites,pci->iwrite_kb);
403 printf(" Reads Completed: %'8lu, %'8LuKiB\t", pci->creads, pci->cread_kb);
404 printf(" Writes Completed: %'8lu, %'8LuKiB\n", pci->cwrites,pci->cwrite_kb);
405 printf(" Read Merges: %'8lu%8c\t", pci->mreads, ' ');
406
407 printf(" Write Merges: %'8lu\n", pci->mwrites);
5c017e4b
JA
408}
409
d5396421 410static void show_stats(void)
d0ca268b 411{
d5396421 412 struct per_cpu_info foo, *pci;
412819ce 413 int i, pci_events = 0;
5c017e4b
JA
414
415 memset(&foo, 0, sizeof(foo));
d0ca268b 416
a718bd37 417 for (i = 0; i < max_cpus; i++) {
d5396421 418 pci = &per_cpu_info[i];
5c017e4b 419
d5396421 420 if (!pci->nelems)
afd2d7ad 421 continue;
422
d5396421
JA
423 foo.qreads += pci->qreads;
424 foo.qwrites += pci->qwrites;
425 foo.creads += pci->creads;
426 foo.cwrites += pci->cwrites;
427 foo.mreads += pci->mreads;
428 foo.mwrites += pci->mwrites;
429 foo.qread_kb += pci->qread_kb;
430 foo.qwrite_kb += pci->qwrite_kb;
431 foo.cread_kb += pci->cread_kb;
432 foo.cwrite_kb += pci->cwrite_kb;
5c017e4b
JA
433
434 printf("CPU%d:\n", i);
d5396421 435 dump_pci_stats(pci);
412819ce 436 pci_events++;
5c017e4b
JA
437 }
438
412819ce 439 if (pci_events > 1) {
5c017e4b 440 printf("Total:\n");
d5396421 441 dump_pci_stats(&foo);
5c017e4b 442 }
d0ca268b
JA
443
444 printf("Events: %'Lu\n", events);
d0ca268b
JA
445}
446
3aabcd89 447static inline int trace_rb_insert(struct trace *t)
8fc0abbc
JA
448{
449 struct rb_node **p = &rb_root.rb_node;
450 struct rb_node *parent = NULL;
451 struct trace *__t;
452
453 while (*p) {
454 parent = *p;
455 __t = rb_entry(parent, struct trace, rb_node);
456
457 if (t->bit->sequence < __t->bit->sequence)
458 p = &(*p)->rb_left;
459 else if (t->bit->sequence > __t->bit->sequence)
460 p = &(*p)->rb_right;
461 else {
87b72777 462 fprintf(stderr, "sequence alias!\n");
8fc0abbc
JA
463 return 1;
464 }
465 }
466
467 rb_link_node(&t->rb_node, parent, p);
468 rb_insert_color(&t->rb_node, &rb_root);
469 return 0;
470}
471
412819ce 472static int sort_entries(void *traces, unsigned long offset, int nr)
8fc0abbc 473{
412819ce 474 struct per_cpu_info *pci;
8fc0abbc
JA
475 struct blk_io_trace *bit;
476 struct trace *t;
477 void *start = traces;
478 int nelems = 0;
479
6fe4709e 480 while (traces - start <= offset - sizeof(*bit)) {
412819ce
JA
481 if (!nr)
482 break;
483
8fc0abbc 484 bit = traces;
6fe4709e 485
8fc0abbc
JA
486 t = malloc(sizeof(*t));
487 t->bit = bit;
488 memset(&t->rb_node, 0, sizeof(t->rb_node));
489
6fe4709e
JA
490 trace_to_cpu(bit);
491
66fa7233
JA
492 if (verify_trace(bit))
493 break;
494
a718bd37 495 pci = get_cpu_info(bit->cpu);
412819ce
JA
496 pci->nelems++;
497
8fc0abbc
JA
498 if (trace_rb_insert(t))
499 return -1;
500
501 traces += sizeof(*bit) + bit->pdu_len;
502 nelems++;
412819ce 503 nr--;
6fe4709e 504 }
8fc0abbc
JA
505
506 return nelems;
507}
508
412819ce
JA
509static void free_entries_rb(void)
510{
511 struct rb_node *n;
512
513 while ((n = rb_first(&rb_root)) != NULL) {
514 struct trace *t = rb_entry(n, struct trace, rb_node);
515
516 rb_erase(&t->rb_node, &rb_root);
517 free(t);
518 }
519}
520
d5396421 521static void show_entries_rb(void)
8fc0abbc 522{
8fc0abbc 523 struct blk_io_trace *bit;
3aabcd89 524 struct rb_node *n;
8fc0abbc
JA
525 struct trace *t;
526 int cpu;
527
3aabcd89
JA
528 n = rb_first(&rb_root);
529 if (!n)
530 return;
8fc0abbc 531
3aabcd89 532 do {
8fc0abbc
JA
533 t = rb_entry(n, struct trace, rb_node);
534 bit = t->bit;
535
d5396421 536 cpu = bit->cpu;
87b72777 537 if (cpu > max_cpus) {
8fc0abbc 538 fprintf(stderr, "CPU number too large (%d)\n", cpu);
87b72777 539 break;
8fc0abbc
JA
540 }
541
cfab07eb
AB
542 if (genesis_time == 0)
543 genesis_time = bit->time;
544 bit->time -= genesis_time;
8fc0abbc 545
cfab07eb 546 check_time(bit);
8fc0abbc 547
d5396421 548 if (dump_trace(bit, &per_cpu_info[cpu]))
87b72777
JA
549 break;
550
8fc0abbc
JA
551 } while ((n = rb_next(n)) != NULL);
552}
553
1f79c4a0
JA
554static int read_data(int fd, void *buffer, int bytes, int block)
555{
556 int ret, bytes_left, fl;
557 void *p;
558
559 fl = fcntl(fd, F_GETFL);
560
561 if (!block)
562 fcntl(fd, F_SETFL, fl | O_NONBLOCK);
563 else
564 fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
565
566 bytes_left = bytes;
567 p = buffer;
568 while (bytes_left > 0) {
569 ret = read(fd, p, bytes_left);
570 if (!ret)
571 return 1;
572 else if (ret < 0) {
573 if (errno != EAGAIN)
574 perror("read");
575 return -1;
576 } else {
577 p += ret;
578 bytes_left -= ret;
579 }
580 }
581
582 return 0;
583}
584
d5396421 585static int do_file(void)
d0ca268b 586{
a718bd37 587 int i, nfiles;
d0ca268b 588
a718bd37
NS
589 for (i = 0, nfiles = 0;; i++, nfiles++) {
590 struct per_cpu_info *pci;
87b72777
JA
591 struct stat st;
592 void *tb;
593
a718bd37 594 pci = get_cpu_info(i);
d5396421 595 pci->ofp = NULL;
d0ca268b 596
d5396421
JA
597 snprintf(pci->fname, sizeof(pci->fname)-1,"%s_out.%d", dev, i);
598 if (stat(pci->fname, &st) < 0)
d0ca268b 599 break;
afd2d7ad 600 if (!st.st_size)
601 continue;
d0ca268b 602
d5396421 603 printf("Processing %s\n", pci->fname);
8fc0abbc 604
87b72777 605 tb = malloc(st.st_size);
8fc0abbc 606
d5396421
JA
607 pci->fd = open(pci->fname, O_RDONLY);
608 if (pci->fd < 0) {
609 perror(pci->fname);
3aabcd89 610 break;
d0ca268b 611 }
afd2d7ad 612
1f79c4a0 613 if (read_data(pci->fd, tb, st.st_size, 1))
3aabcd89 614 break;
d0ca268b 615
a718bd37 616 if (sort_entries(tb, st.st_size, ~0U) == -1)
3aabcd89 617 break;
d0ca268b 618
d5396421 619 close(pci->fd);
d5396421
JA
620 printf("\t%2d %10s %15d\n", i, pci->fname, pci->nelems);
621
622 }
623
624 if (!nfiles) {
625 fprintf(stderr, "No files found\n");
626 return 1;
627 }
628
629 show_entries_rb();
d5396421
JA
630 return 0;
631}
632
412819ce 633static void resize_buffer(void **buffer, long *old_size)
d5396421 634{
412819ce 635 long cur_size = *old_size;
d5396421
JA
636 void *ptr;
637
412819ce
JA
638 *old_size *= 2;
639 ptr = malloc(*old_size);
640 memcpy(ptr, *buffer, cur_size);
641 free(*buffer);
642 *buffer = ptr;
643}
d5396421 644
412819ce
JA
645static int read_sort_events(int fd, void **buffer)
646{
647 long offset, max_offset;
648 int events;
d5396421 649
412819ce
JA
650 max_offset = 128 * sizeof(struct blk_io_trace);
651 *buffer = malloc(max_offset);
652 events = 0;
653 offset = 0;
d5396421 654
412819ce
JA
655 do {
656 struct blk_io_trace *t;
657 int pdu_len;
d5396421 658
412819ce
JA
659 if (max_offset - offset < sizeof(*t))
660 resize_buffer(buffer, &max_offset);
d5396421 661
412819ce
JA
662 if (read_data(fd, *buffer + offset, sizeof(*t), !events)) {
663 if (events)
d5396421 664 break;
412819ce
JA
665
666 usleep(1000);
667 continue;
d5396421
JA
668 }
669
412819ce
JA
670 t = *buffer + offset;
671 offset += sizeof(*t);
d5396421 672
412819ce 673 pdu_len = be16_to_cpu(t->pdu_len);
d5396421 674
412819ce
JA
675 if (max_offset - offset < pdu_len)
676 resize_buffer(buffer, &max_offset);
d5396421 677
412819ce
JA
678 if (read_data(fd, *buffer + offset, pdu_len, 1))
679 break;
d5396421 680
412819ce
JA
681 offset += pdu_len;
682 events++;
79f19470 683 } while (!is_done() && events < rb_batch);
d5396421 684
412819ce
JA
685 return events;
686}
d5396421 687
412819ce
JA
688static int do_stdin(void)
689{
690 int fd;
691 void *ptr;
d5396421 692
1f79c4a0 693 fd = dup(STDIN_FILENO);
412819ce
JA
694 do {
695 int events;
d5396421 696
412819ce
JA
697 events = read_sort_events(fd, &ptr);
698 if (!events)
699 break;
700
701 sort_entries(ptr, ~0UL, events);
702 show_entries_rb();
703 free_entries_rb();
d5396421
JA
704 } while (1);
705
706 close(fd);
707 free(ptr);
d5396421
JA
708 return 0;
709}
d0ca268b 710
1f79c4a0 711static void flush_output(void)
412819ce
JA
712{
713 int i;
714
a718bd37 715 for (i = 0; i < max_cpus; i++) {
412819ce
JA
716 struct per_cpu_info *pci = &per_cpu_info[i];
717
718 if (pci->ofp) {
719 fflush(pci->ofp);
720 fclose(pci->ofp);
721 pci->ofp = NULL;
722 }
723 }
724}
725
1f79c4a0 726static void handle_sigint(int sig)
412819ce
JA
727{
728 done = 1;
729 flush_output();
730}
731
1f79c4a0
JA
732static void usage(char *prog)
733{
734 fprintf(stderr, "Usage: %s -i <name> [-o <output>]\n", prog);
735}
736
d5396421
JA
737int main(int argc, char *argv[])
738{
412819ce 739 int c, ret;
d5396421
JA
740
741 while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) {
742 switch (c) {
743 case 'i':
744 dev = strdup(optarg);
745 break;
746 case 'o':
747 output_name = strdup(optarg);
748 break;
79f19470
JA
749 case 'b':
750 rb_batch = atoi(optarg);
751 if (rb_batch <= 0)
752 rb_batch = RB_BATCH_DEFAULT;
753 break;
d5396421 754 default:
1f79c4a0 755 usage(argv[0]);
d5396421
JA
756 return 1;
757 }
d0ca268b
JA
758 }
759
d5396421 760 if (!dev) {
1f79c4a0 761 usage(argv[0]);
d5396421
JA
762 return 1;
763 }
764
412819ce
JA
765 memset(&rb_root, 0, sizeof(rb_root));
766
767 signal(SIGINT, handle_sigint);
768 signal(SIGHUP, handle_sigint);
769 signal(SIGTERM, handle_sigint);
d5396421
JA
770
771 if (!strcmp(dev, "-"))
772 ret = do_stdin();
773 else
774 ret = do_file();
775
412819ce
JA
776 show_stats();
777 flush_output();
d5396421 778 return ret;
d0ca268b 779}