Bandwidth per process per file in detailled view
[lttngtop.git] / src / iostreamtop.c
CommitLineData
1fc22eb4
JD
1/*
2 * Copyright (C) 2011 Mathieu Bain <mathieu.bain@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * 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
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
b093de8a
MB
19#include <stdlib.h>
20#include <unistd.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <string.h>
1fc22eb4
JD
24#include <babeltrace/babeltrace.h>
25
26#include "lttngtoptypes.h"
27#include "common.h"
28#include "iostreamtop.h"
29
b093de8a
MB
30void add_file(struct processtop *proc, struct files *file, int fd)
31{
32 if (proc->process_files_table->len <= fd) {
33 g_ptr_array_set_size(proc->process_files_table, fd);
34 g_ptr_array_add(proc->process_files_table, file);
35 } else {
36 g_ptr_array_index(proc->process_files_table, fd) = file;
37 }
38 file->fd = fd;
39}
40
41
42void insert_file(struct processtop *proc, int fd)
43{
44 struct files *tmp;
45
46 if (fd >= proc->process_files_table->len) {
47 tmp = g_new0(struct files, 1);
48 tmp->name = "Unknown";
49 add_file(proc, tmp, fd);
50 } else {
51
52 tmp = g_ptr_array_index(proc->process_files_table, fd);
53 if (tmp == NULL) {
54 tmp = g_new0(struct files, 1);
55 tmp->name = "Unknown";
56 tmp->read = 0;
57 tmp->write = 0;
58 tmp->fd = fd;
59 add_file(proc, tmp, fd);
60 }
61 }
62}
63
64void close_file(struct processtop *proc, int fd)
65{
66 int len;
67
68 len = proc->process_files_table->len;
69
70 /*
71 * It is possible that a file was open before taking the trace
72 * and its fd could be greater than all of the others fd
73 * used by the process
74 */
75 if (fd < len) {
76 g_ptr_array_remove_index_fast(proc->process_files_table, fd);
77 g_ptr_array_set_size(proc->process_files_table, len + 1);
78 }
79}
80
81struct files *get_file(struct processtop *proc, int fd)
82{
83 struct files *tmp;
84 tmp = g_ptr_array_index(proc->process_files_table, fd);
85 return tmp;
86}
87
88void show_table(GPtrArray *tab)
89{
90 int i;
91 struct files *file;
92
93 for (i = 0 ; i < tab->len; i++) {
94 file = g_ptr_array_index(tab, i);
95 if (file == NULL)
96 fprintf(stderr, "NULL, ");
97 else
98 fprintf(stderr, "%s, ", file->name);
99 }
100 fprintf(stderr, "]\n\n");
101}
1fc22eb4
JD
102
103int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
104 unsigned long timestamp, int cpu_id, int ret)
105{
106 struct processtop *tmp;
b093de8a 107 struct files *tmpfile;
1fc22eb4
JD
108 int err = 0;
109
110 tmp = get_proc(ctx, tid, comm, timestamp);
b093de8a
MB
111
112 if (tmp->syscall_info != NULL) {
113 if (tmp->syscall_info->type == __NR_read
114 && ret > 0) {
115 tmp->totalfileread += ret;
116 tmp->fileread += ret;
117 tmpfile = get_file(tmp, tmp->syscall_info->fd);
118 tmpfile->read += ret;
119 } else if (tmp->syscall_info->type == __NR_write
120 && ret > 0) {
121 tmp->totalfilewrite += ret;
122 tmp->filewrite += ret;
123 tmpfile = get_file(tmp, tmp->syscall_info->fd);
124 tmpfile->write += ret;
125 } else if (tmp->syscall_info->type == __NR_open
126 && ret > 0) {
127 add_file(tmp, tmp->files_history->file, ret);
128 } else {
1fc22eb4
JD
129 err = -1;
130 }
b093de8a
MB
131 g_free(tmp->syscall_info);
132 tmp->syscall_info = NULL;
133 }
1fc22eb4
JD
134 return err;
135}
136
b093de8a
MB
137struct syscalls *create_syscall_info(unsigned int type, unsigned int cpu_id,
138 unsigned int tid, int fd)
139{
140 struct syscalls *syscall_info;
141
142 syscall_info = g_new0(struct syscalls, 1);
143 syscall_info->type = type;
144 syscall_info->cpu_id = cpu_id;
145 syscall_info->tid = tid;
146 syscall_info->fd = fd;
147
148 return syscall_info;
149}
150
151struct file_history *create_file(struct file_history *history, char *file_name)
152{
153 struct files *new_file;
154 struct file_history *new_history;
155
156 new_file = g_new0(struct files, 1);
157 new_history = g_new0(struct file_history, 1);
158 new_file->name = strdup(file_name);
159 new_file->read = 0;
160 new_file->write = 0;
161 new_history->file = new_file;
162 new_history->next = history;
163
164 return new_history;
165}
166
1fc22eb4
JD
167enum bt_cb_ret handle_exit_syscall(struct bt_ctf_event *call_data,
168 void *private_data)
169{
170 struct definition *scope;
171 unsigned long timestamp;
172 char *comm;
173 uint64_t ret, tid;
174 int64_t cpu_id;
175
176 timestamp = bt_ctf_get_timestamp(call_data);
177 if (timestamp == -1ULL)
178 goto error;
179
180 scope = bt_ctf_get_top_level_scope(call_data,
181 BT_STREAM_EVENT_CONTEXT);
182 comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
183 scope, "_procname"));
184 if (bt_ctf_field_get_error()) {
185 fprintf(stderr, "Missing procname context info\n");
186 goto error;
187 }
188
189 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
190 scope, "_tid"));
191 if (bt_ctf_field_get_error()) {
192 fprintf(stderr, "Missing tid context info\n");
193 goto error;
194 }
195
196 scope = bt_ctf_get_top_level_scope(call_data,
197 BT_EVENT_FIELDS);
198 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
199 scope, "_ret"));
200 if (bt_ctf_field_get_error()) {
201 fprintf(stderr, "Missing ret context info\n");
202 goto error;
203 }
204
205 scope = bt_ctf_get_top_level_scope(call_data,
206 BT_STREAM_PACKET_CONTEXT);
207 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
208 scope, "cpu_id"));
209 if (bt_ctf_field_get_error()) {
210 fprintf(stderr, "Missing cpu_id context info\n");
211 goto error;
212 }
213
214 /*
b093de8a
MB
215 * if we encounter an exit_syscall and
216 * it is not for a syscall read or write
1fc22eb4
JD
217 * we just abort the execution of this callback
218 */
219 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id, ret)) < 0)
220 return BT_CB_ERROR_CONTINUE;
221
222 return BT_CB_OK;
223
224error:
225 return BT_CB_ERROR_STOP;
226}
227
228
229enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
230 void *private_data)
231{
232 struct definition *scope;
233 struct processtop *tmp;
1fc22eb4
JD
234 unsigned long timestamp;
235 uint64_t cpu_id;
236 char *comm;
237 int64_t tid;
b093de8a 238 int fd;
1fc22eb4
JD
239
240 timestamp = bt_ctf_get_timestamp(call_data);
241 if (timestamp == -1ULL)
242 goto error;
243
244 scope = bt_ctf_get_top_level_scope(call_data,
245 BT_STREAM_EVENT_CONTEXT);
246 comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
247 scope, "_procname"));
248 if (bt_ctf_field_get_error()) {
249 fprintf(stderr, "Missing procname context info\n");
250 goto error;
251 }
252
253 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
254 scope, "_tid"));
255 if (bt_ctf_field_get_error()) {
256 fprintf(stderr, "Missing tid context info\n");
257 goto error;
258 }
259
260 scope = bt_ctf_get_top_level_scope(call_data,
261 BT_STREAM_PACKET_CONTEXT);
262 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
263 scope, "cpu_id"));
264 if (bt_ctf_field_get_error()) {
265 fprintf(stderr, "Missing cpu_id context info\n");
266 goto error;
267 }
268
b093de8a
MB
269 scope = bt_ctf_get_top_level_scope(call_data,
270 BT_EVENT_FIELDS);
271 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
272 scope, "_fd"));
273 if (bt_ctf_field_get_error()) {
274 fprintf(stderr, "Missing fd context info\n");
275 goto error;
276 }
277
1fc22eb4 278 tmp = get_proc(&lttngtop, tid, comm, timestamp);
b093de8a
MB
279 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
280
281 insert_file(tmp, fd);
1fc22eb4
JD
282
283 return BT_CB_OK;
284
285error:
286 return BT_CB_ERROR_STOP;
287}
288
289enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
290 void *private_data)
291{
292 struct processtop *tmp;
293 struct definition *scope;
1fc22eb4
JD
294 unsigned long timestamp;
295 uint64_t cpu_id;
296 char *comm;
297 int64_t tid;
b093de8a 298 int fd;
1fc22eb4
JD
299
300 timestamp = bt_ctf_get_timestamp(call_data);
301 if (timestamp == -1ULL)
302 goto error;
303
304 scope = bt_ctf_get_top_level_scope(call_data,
305 BT_STREAM_EVENT_CONTEXT);
306 comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
307 scope, "_procname"));
308 if (bt_ctf_field_get_error()) {
309 fprintf(stderr, "Missing procname context info\n");
310 goto error;
311 }
312
313 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
314 scope, "_tid"));
315 if (bt_ctf_field_get_error()) {
316 fprintf(stderr, "Missing tid context info\n");
317 goto error;
318 }
319
320 scope = bt_ctf_get_top_level_scope(call_data,
321 BT_STREAM_PACKET_CONTEXT);
322 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
323 scope, "cpu_id"));
324 if (bt_ctf_field_get_error()) {
325 fprintf(stderr, "Missing cpu_id context info\n");
326 goto error;
327 }
328
b093de8a
MB
329 scope = bt_ctf_get_top_level_scope(call_data,
330 BT_EVENT_FIELDS);
331 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
332 scope, "_fd"));
333 if (bt_ctf_field_get_error()) {
334 fprintf(stderr, "Missing fd context info\n");
335 goto error;
336 }
337
338 tmp = get_proc(&lttngtop, tid, comm, timestamp);
339 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
340
341 insert_file(tmp, fd);
342
343 return BT_CB_OK;
344
345error:
346 return BT_CB_ERROR_STOP;
347}
348
349
350enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
351 void *private_data)
352{
353
354 struct processtop *tmp;
355 struct definition *scope;
356 unsigned long timestamp;
357 uint64_t cpu_id;
358 char *comm;
359 int64_t tid;
360 char *file;
361
362 timestamp = bt_ctf_get_timestamp(call_data);
363 if (timestamp == -1ULL)
364 goto error;
365
366 scope = bt_ctf_get_top_level_scope(call_data,
367 BT_STREAM_EVENT_CONTEXT);
368 comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
369 scope, "_procname"));
370 if (bt_ctf_field_get_error()) {
371 fprintf(stderr, "Missing procname context info\n");
372 goto error;
373 }
374
375 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
376 scope, "_tid"));
377 if (bt_ctf_field_get_error()) {
378 fprintf(stderr, "Missing tid context info\n");
379 goto error;
380 }
381
382 scope = bt_ctf_get_top_level_scope(call_data,
383 BT_STREAM_PACKET_CONTEXT);
384 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
385 scope, "cpu_id"));
386 if (bt_ctf_field_get_error()) {
387 fprintf(stderr, "Missing cpu_id context info\n");
388 goto error;
389 }
390
391 scope = bt_ctf_get_top_level_scope(call_data,
392 BT_EVENT_FIELDS);
393 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
394 scope, "_filename"));
395 if (bt_ctf_field_get_error()) {
396 fprintf(stderr, "Missing fd context info\n");
397 goto error;
398 }
399
1fc22eb4 400 tmp = get_proc(&lttngtop, tid, comm, timestamp);
b093de8a
MB
401 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
402
403 tmp->files_history = create_file(tmp->files_history, file);
1fc22eb4
JD
404
405 return BT_CB_OK;
406
407error:
408 return BT_CB_ERROR_STOP;
409}
410
b093de8a
MB
411
412enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
413 void *private_data)
414{
415 struct definition *scope;
416 unsigned long timestamp;
417 int64_t tid;
418 struct processtop *tmp;
419 char *comm;
420 int fd;
421
422 timestamp = bt_ctf_get_timestamp(call_data);
423 if (timestamp == -1ULL)
424 goto error;
425
426 scope = bt_ctf_get_top_level_scope(call_data,
427 BT_STREAM_EVENT_CONTEXT);
428 comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
429 scope, "_procname"));
430 if (bt_ctf_field_get_error()) {
431 fprintf(stderr, "Missing procname context info\n");
432 goto error;
433 }
434
435 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
436 scope, "_tid"));
437 if (bt_ctf_field_get_error()) {
438 fprintf(stderr, "Missing tid context info\n");
439 goto error;
440 }
441
442 scope = bt_ctf_get_top_level_scope(call_data,
443 BT_EVENT_FIELDS);
444 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
445 scope, "_fd"));
446 if (bt_ctf_field_get_error()) {
447 fprintf(stderr, "Missing fd context info\n");
448 goto error;
449 }
450
451 tmp = get_proc(&lttngtop, tid, comm, timestamp);
452 close_file(tmp, fd);
453
454 return BT_CB_OK;
455
456error:
457 return BT_CB_ERROR_STOP;
458}
This page took 0.038369 seconds and 4 git commands to generate.