iowatcher: Make seconds unsigned
[blktrace.git] / iowatcher / fio.c
CommitLineData
24e48e03
CM
1/*
2 * Copyright (C) 2013 Fusion-io
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
660b0411 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24e48e03
CM
16 */
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <unistd.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <math.h>
24#include <inttypes.h>
25#include <string.h>
26#include <asm/types.h>
27#include <errno.h>
28#include <sys/mman.h>
29#include <time.h>
30#include <math.h>
31
32#include "plot.h"
33#include "blkparse.h"
34#include "list.h"
35#include "tracers.h"
36#include "fio.h"
37
38static int past_eof(struct trace *trace, char *cur)
39{
40 if (cur >= trace->fio_start + trace->fio_len)
41 return 1;
42 return 0;
43}
44
45static int parse_fio_line(struct trace *trace, int *time, int *rate, int *dir, int *bs)
46{
47 char *cur = trace->fio_cur;
48 char *p;
49 int *res[] = { time, rate, dir, bs, NULL };
50 int val;
51 int i = 0;
52 int *t;
53 char *end = index(cur, '\n');
54 char *tmp;
55
56 if (!end)
57 return 1;
58
59 tmp = strndup(cur, end - cur);
60 if (!tmp)
61 return 1;
62 p = strtok(tmp, ",");
63 while (p && *res) {
64 val = atoi(p);
65 t = res[i++];
66 *t = val;
67 p = strtok(NULL, ",");
68 }
69
70 free(tmp);
71
72 if (i < 3)
73 return 1;
74 return 0;
75}
76
77int next_fio_line(struct trace *trace)
78{
79 char *next;
80 char *cur = trace->fio_cur;
81
82 next = strchr(cur, '\n');
83 if (!next)
84 return 1;
85 next++;
86 if (past_eof(trace, next))
87 return 1;
88 trace->fio_cur = next;
89 return 0;
90}
91
92char *first_fio(struct trace *trace)
93{
94 trace->fio_cur = trace->fio_start;
95 return trace->fio_cur;
96}
97
98static void find_last_fio_time(struct trace *trace)
99{
100 double d;
101 int time, rate, dir, bs;
102 int ret;
103 int last_time = 0;
104
105 if (trace->fio_len == 0)
106 return;
107
108 first_fio(trace);
109 while (1) {
110 ret = parse_fio_line(trace, &time, &rate, &dir, &bs);
111 if (ret)
112 break;
113 if (dir <= 1 && time > last_time)
114 last_time = time;
115 ret = next_fio_line(trace);
116 if (ret)
117 break;
118 }
119 d = (double)time / 1000;
120 trace->fio_seconds = ceil(d);
121 return;
122}
123
124int read_fio(struct trace *trace, char *trace_name)
125{
126 int fd;
127 struct stat st;
128 int ret;
129 char *p;
130
131 fd = open(trace_name, O_RDONLY);
132 if (fd < 0)
133 return 1;
134
135 ret = fstat(fd, &st);
136 if (ret < 0) {
137 fprintf(stderr, "stat failed on %s err %s\n",
138 trace_name, strerror(errno));
139 goto fail_fd;
140 }
141 p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
142 if (p == MAP_FAILED) {
143 fprintf(stderr, "Unable to mmap trace file %s, err %s\n",
144 trace_name, strerror(errno));
145 goto fail_fd;
146 }
147 trace->fio_start = p;
148 trace->fio_len = st.st_size;
149 trace->fio_cur = p;
150 trace->fio_fd = fd;
151 find_last_fio_time(trace);
152 first_fio(trace);
153 return 0;
154
155fail_fd:
156 close(fd);
157 return 1;
158}
159
160struct trace *open_fio_trace(char *path)
161{
162 int ret;
163 struct trace *trace;
164
165 trace = calloc(1, sizeof(*trace));
166 if (!trace) {
167 fprintf(stderr, "unable to allocate memory for trace\n");
168 exit(1);
169 }
170
171 ret = read_fio(trace, path);
172 if (ret) {
173 free(trace);
174 return NULL;
175 }
176
177 return trace;
178}
179
180int read_fio_event(struct trace *trace, int *time_ret, u64 *bw_ret, int *dir_ret)
181{
182 char *cur = trace->fio_cur;
183 int time, rate, dir, bs;
184 int ret;
185
186 if (past_eof(trace, cur))
187 return 1;
188
189 ret = parse_fio_line(trace, &time, &rate, &dir, &bs);
190 if (ret)
191 return 1;
192
193 time = floor((double)time / 1000);
194 *time_ret = time;
195 *bw_ret = (u64)rate * 1024;
196
197 *dir_ret = dir;
198 return 0;
199}
200
22dd439a 201int add_fio_gld(unsigned int time, u64 bw, struct graph_line_data *gld)
24e48e03
CM
202{
203 double val;
204
205 if (time > gld->max_seconds)
206 return 0;
207
208 gld->data[time].sum += bw;
209 gld->data[time].count++;
210
211 val = ((double)gld->data[time].sum) / gld->data[time].count;
212
213 if (val > gld->max)
214 gld->max = ceil(val);
215 return 0;
216
217}