print timestamp delta
[lttngtop.git] / src / iostreamtop.c
CommitLineData
1fc22eb4 1/*
aa15ac1c 2 * Copyright (C) 2011-2012 Mathieu Bain <mathieu.bain@polymtl.ca>
1fc22eb4
JD
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 *
71bd7ce1
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1fc22eb4
JD
16 */
17
b093de8a
MB
18#include <stdlib.h>
19#include <unistd.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <string.h>
1fc22eb4
JD
23#include <babeltrace/babeltrace.h>
24
25#include "lttngtoptypes.h"
26#include "common.h"
27#include "iostreamtop.h"
28
b093de8a
MB
29void add_file(struct processtop *proc, struct files *file, int fd)
30{
ceb3a221 31 struct files *tmp_file;
59288610 32 struct processtop *parent;
ceb3a221 33 int size;
32647247 34 int i;
ceb3a221
MB
35
36 size = proc->process_files_table->len;
59288610
MB
37 parent = proc->threadparent;
38 if (parent)
39 insert_file(parent, fd);
ceb3a221 40 if (size <= fd) {
32647247
JD
41 /* Add NULL file structures for undefined FDs */
42 for (i = size; i < fd; i++) {
43 g_ptr_array_add(proc->process_files_table, NULL);
44 }
b093de8a
MB
45 g_ptr_array_add(proc->process_files_table, file);
46 } else {
ceb3a221
MB
47 tmp_file = g_ptr_array_index(proc->process_files_table, fd);
48 if (tmp_file == NULL)
49 g_ptr_array_index(proc->process_files_table, fd) = file;
50 else {
51 if (strcmp(tmp_file->name, file->name) != 0) {
52 size = proc->process_files_table->len;
53 g_ptr_array_set_size(proc->process_files_table,
59288610 54 size+1);
ceb3a221
MB
55 g_ptr_array_index(proc->process_files_table,
56 size) = tmp_file;
57 g_ptr_array_index(proc->process_files_table,
58 fd) = file;
59 } else
60 tmp_file->flag = __NR_open;
61 }
b093de8a 62 }
59288610
MB
63 /*
64 * The file may have be created in the parent
65 */
66 if (file->flag == -1) {
67 file->fd = fd;
68 file->flag = __NR_open;
69 lttngtop.nbfiles++;
70 lttngtop.nbnewfiles++;
71 }
b093de8a
MB
72}
73
59288610
MB
74/*
75 * Edit the file
76 * Called by handled_statedump_filename
77 */
ceb3a221
MB
78void edit_file(struct processtop *proc, struct files *file, int fd)
79{
80 int size = proc->process_files_table->len;
81 struct files *tmpfile;
82
59288610
MB
83 if (fd >= size) {
84 add_file(proc, file, fd);
85 } else {
ceb3a221 86 tmpfile = g_ptr_array_index(proc->process_files_table, fd);
59288610
MB
87 if (tmpfile) {
88 tmpfile->name = strdup(file->name);
89 free(file);
90 } else
91 add_file(proc, file, fd);
ceb3a221
MB
92 }
93}
b093de8a
MB
94
95void insert_file(struct processtop *proc, int fd)
96{
97 struct files *tmp;
59288610
MB
98 struct files *tmp_parent;
99 struct processtop *parent;
b093de8a 100
59288610
MB
101 if (fd < 0)
102 return;
b093de8a
MB
103 if (fd >= proc->process_files_table->len) {
104 tmp = g_new0(struct files, 1);
105 tmp->name = "Unknown";
ceb3a221
MB
106 tmp->read = 0;
107 tmp->write = 0;
108 tmp->fd = fd;
59288610 109 tmp->flag = -1;
b093de8a
MB
110 add_file(proc, tmp, fd);
111 } else {
b093de8a
MB
112 tmp = g_ptr_array_index(proc->process_files_table, fd);
113 if (tmp == NULL) {
114 tmp = g_new0(struct files, 1);
115 tmp->name = "Unknown";
116 tmp->read = 0;
117 tmp->write = 0;
118 tmp->fd = fd;
59288610 119 tmp->flag = -1;
b093de8a 120 add_file(proc, tmp, fd);
59288610
MB
121 } else {
122 parent = proc->threadparent;
123 if (parent) {
124 tmp_parent = g_ptr_array_index(
125 parent->process_files_table, fd);
126 if (tmp_parent &&
127 (strcmp(tmp->name, tmp_parent->name)) != 0)
128 tmp->name = strdup(tmp_parent->name);
129 }
b093de8a
MB
130 }
131 }
132}
133
134void close_file(struct processtop *proc, int fd)
ceb3a221
MB
135{
136 struct files *file;
137
ceb3a221 138 file = get_file(proc, fd);
e05a35a6 139 if (file != NULL) {
ceb3a221 140 file->flag = __NR_close;
e05a35a6
JD
141 lttngtop.nbfiles--;
142 }
143 lttngtop.nbclosedfiles++;
ceb3a221
MB
144}
145
146struct files *get_file(struct processtop *proc, int fd)
b093de8a
MB
147{
148 int len;
ceb3a221 149 struct files *tmp = NULL;
b093de8a
MB
150
151 len = proc->process_files_table->len;
152
153 /*
154 * It is possible that a file was open before taking the trace
155 * and its fd could be greater than all of the others fd
156 * used by the process
157 */
ceb3a221
MB
158 if (fd < len && fd >= 0)
159 tmp = g_ptr_array_index(proc->process_files_table, fd);
b093de8a 160
b093de8a
MB
161 return tmp;
162}
163
164void show_table(GPtrArray *tab)
165{
166 int i;
167 struct files *file;
168
169 for (i = 0 ; i < tab->len; i++) {
170 file = g_ptr_array_index(tab, i);
171 if (file == NULL)
172 fprintf(stderr, "NULL, ");
173 else
174 fprintf(stderr, "%s, ", file->name);
175 }
176 fprintf(stderr, "]\n\n");
177}
1fc22eb4 178
ceb3a221
MB
179void show_history(struct file_history *history)
180{
181 struct file_history *tmp = history;
182
183 while (tmp != NULL) {
184 fprintf(stderr, "fd = %d, name = %s\n", tmp->file->fd,
185 tmp->file->name);
186 tmp = tmp->next;
187 }
188
189}
190
1fc22eb4 191int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
906c08f6
JD
192 unsigned long timestamp, uint64_t cpu_id, int ret,
193 char *hostname)
1fc22eb4
JD
194{
195 struct processtop *tmp;
b093de8a 196 struct files *tmpfile;
1fc22eb4
JD
197 int err = 0;
198
906c08f6 199 tmp = get_proc(ctx, tid, comm, timestamp, hostname);
b093de8a 200
96aa77de
JD
201 if (!tmp) {
202 err = -1;
203 goto end;
204 }
b093de8a
MB
205 if (tmp->syscall_info != NULL) {
206 if (tmp->syscall_info->type == __NR_read
207 && ret > 0) {
208 tmp->totalfileread += ret;
209 tmp->fileread += ret;
210 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
211 if (tmpfile)
212 tmpfile->read += ret;
b093de8a
MB
213 } else if (tmp->syscall_info->type == __NR_write
214 && ret > 0) {
215 tmp->totalfilewrite += ret;
216 tmp->filewrite += ret;
217 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
218 if (tmpfile)
219 tmpfile->write += ret;
b093de8a
MB
220 } else if (tmp->syscall_info->type == __NR_open
221 && ret > 0) {
ceb3a221
MB
222 tmpfile = tmp->files_history->file;
223 add_file(tmp, tmpfile, ret);
224 tmpfile->fd = ret;
b093de8a 225 } else {
1fc22eb4
JD
226 err = -1;
227 }
b093de8a
MB
228 g_free(tmp->syscall_info);
229 tmp->syscall_info = NULL;
230 }
96aa77de
JD
231
232end:
1fc22eb4
JD
233 return err;
234}
235
d67167cd 236struct syscalls *create_syscall_info(unsigned int type, uint64_t cpu_id,
b093de8a
MB
237 unsigned int tid, int fd)
238{
239 struct syscalls *syscall_info;
240
241 syscall_info = g_new0(struct syscalls, 1);
242 syscall_info->type = type;
243 syscall_info->cpu_id = cpu_id;
244 syscall_info->tid = tid;
245 syscall_info->fd = fd;
246
247 return syscall_info;
248}
249
250struct file_history *create_file(struct file_history *history, char *file_name)
251{
252 struct files *new_file;
253 struct file_history *new_history;
254
255 new_file = g_new0(struct files, 1);
256 new_history = g_new0(struct file_history, 1);
257 new_file->name = strdup(file_name);
258 new_file->read = 0;
259 new_file->write = 0;
59288610 260 new_file->flag = -1;
b093de8a
MB
261 new_history->file = new_file;
262 new_history->next = history;
263
264 return new_history;
265}
266
4adc8274 267enum bt_cb_ret handle_exit_syscall(struct bt_ctf_event *call_data,
1fc22eb4
JD
268 void *private_data)
269{
2e0a1190 270 const struct bt_definition *scope;
1fc22eb4
JD
271 unsigned long timestamp;
272 char *comm;
273 uint64_t ret, tid;
d67167cd 274 uint64_t cpu_id;
906c08f6 275 char *hostname;
1fc22eb4 276
c78f2cdc 277 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
278 if (timestamp == -1ULL)
279 goto error;
280
1dec520a
JD
281 comm = get_context_comm(call_data);
282 tid = get_context_tid(call_data);
1fc22eb4
JD
283
284 scope = bt_ctf_get_top_level_scope(call_data,
285 BT_EVENT_FIELDS);
286 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
287 scope, "_ret"));
288 if (bt_ctf_field_get_error()) {
289 fprintf(stderr, "Missing ret context info\n");
290 goto error;
291 }
292
d67167cd 293 cpu_id = get_cpu_id(call_data);
906c08f6 294 hostname = get_context_hostname(call_data);
1fc22eb4
JD
295
296 /*
b093de8a
MB
297 * if we encounter an exit_syscall and
298 * it is not for a syscall read or write
1fc22eb4
JD
299 * we just abort the execution of this callback
300 */
906c08f6
JD
301 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id,
302 ret, hostname)) < 0)
1fc22eb4
JD
303 return BT_CB_ERROR_CONTINUE;
304
305 return BT_CB_OK;
306
307error:
308 return BT_CB_ERROR_STOP;
309}
310
311
4adc8274 312enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
1fc22eb4
JD
313 void *private_data)
314{
2e0a1190 315 const struct bt_definition *scope;
1fc22eb4 316 struct processtop *tmp;
1fc22eb4
JD
317 unsigned long timestamp;
318 uint64_t cpu_id;
928f18a6 319 int64_t tid;
906c08f6 320 char *procname, *hostname;
b093de8a 321 int fd;
1fc22eb4 322
c78f2cdc 323 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
324 if (timestamp == -1ULL)
325 goto error;
326
1dec520a 327 tid = get_context_tid(call_data);
d67167cd 328 cpu_id = get_cpu_id(call_data);
1fc22eb4 329
928f18a6 330 procname = get_context_comm(call_data);
906c08f6 331 hostname = get_context_hostname(call_data);
59288610 332
b093de8a
MB
333 scope = bt_ctf_get_top_level_scope(call_data,
334 BT_EVENT_FIELDS);
335 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
336 scope, "_fd"));
337 if (bt_ctf_field_get_error()) {
338 fprintf(stderr, "Missing fd context info\n");
339 goto error;
340 }
341
906c08f6 342 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
343 if (!tmp)
344 goto end;
345
b093de8a
MB
346 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
347
348 insert_file(tmp, fd);
1fc22eb4 349
96aa77de 350end:
1fc22eb4
JD
351 return BT_CB_OK;
352
353error:
354 return BT_CB_ERROR_STOP;
355}
356
4adc8274 357enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
1fc22eb4
JD
358 void *private_data)
359{
360 struct processtop *tmp;
2e0a1190 361 const struct bt_definition *scope;
1fc22eb4
JD
362 unsigned long timestamp;
363 uint64_t cpu_id;
928f18a6
MB
364 int64_t tid;
365 char *procname;
b093de8a 366 int fd;
906c08f6 367 char *hostname;
1fc22eb4 368
c78f2cdc 369 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
370 if (timestamp == -1ULL)
371 goto error;
372
1dec520a 373 tid = get_context_tid(call_data);
d67167cd 374 cpu_id = get_cpu_id(call_data);
1fc22eb4 375
928f18a6 376 procname = get_context_comm(call_data);
906c08f6 377 hostname = get_context_hostname(call_data);
59288610 378
b093de8a
MB
379 scope = bt_ctf_get_top_level_scope(call_data,
380 BT_EVENT_FIELDS);
381 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
382 scope, "_fd"));
383 if (bt_ctf_field_get_error()) {
384 fprintf(stderr, "Missing fd context info\n");
385 goto error;
386 }
387
906c08f6 388 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
389 if (!tmp)
390 goto end;
391
b093de8a
MB
392 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
393
394 insert_file(tmp, fd);
395
96aa77de 396end:
b093de8a
MB
397 return BT_CB_OK;
398
399error:
400 return BT_CB_ERROR_STOP;
401}
402
403
4adc8274 404enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
b093de8a
MB
405 void *private_data)
406{
407
408 struct processtop *tmp;
2e0a1190 409 const struct bt_definition *scope;
b093de8a
MB
410 unsigned long timestamp;
411 uint64_t cpu_id;
928f18a6 412 int64_t tid;
906c08f6 413 char *procname, *hostname;
b093de8a
MB
414 char *file;
415
c78f2cdc 416 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
417 if (timestamp == -1ULL)
418 goto error;
419
1dec520a 420 tid = get_context_tid(call_data);
d67167cd 421 cpu_id = get_cpu_id(call_data);
b093de8a 422
928f18a6 423 procname = get_context_comm(call_data);
906c08f6 424 hostname = get_context_hostname(call_data);
59288610 425
b093de8a
MB
426 scope = bt_ctf_get_top_level_scope(call_data,
427 BT_EVENT_FIELDS);
428 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
429 scope, "_filename"));
430 if (bt_ctf_field_get_error()) {
ceb3a221 431 fprintf(stderr, "Missing file name context info\n");
b093de8a
MB
432 goto error;
433 }
434
906c08f6 435 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
436 if (!tmp)
437 goto end;
438
b093de8a
MB
439 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
440
441 tmp->files_history = create_file(tmp->files_history, file);
1fc22eb4 442
96aa77de 443end:
1fc22eb4
JD
444 return BT_CB_OK;
445
446error:
447 return BT_CB_ERROR_STOP;
448}
449
b093de8a 450
4adc8274 451enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
b093de8a
MB
452 void *private_data)
453{
2e0a1190 454 const struct bt_definition *scope;
b093de8a 455 struct processtop *tmp;
928f18a6
MB
456 unsigned long timestamp;
457 int64_t tid;
458 char *procname;
b093de8a 459 int fd;
906c08f6 460 char *hostname;
b093de8a 461
c78f2cdc 462 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
463 if (timestamp == -1ULL)
464 goto error;
465
1dec520a 466 tid = get_context_tid(call_data);
b093de8a 467
928f18a6 468 procname = get_context_comm(call_data);
906c08f6 469 hostname = get_context_hostname(call_data);
59288610 470
b093de8a
MB
471 scope = bt_ctf_get_top_level_scope(call_data,
472 BT_EVENT_FIELDS);
473 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
474 scope, "_fd"));
475 if (bt_ctf_field_get_error()) {
476 fprintf(stderr, "Missing fd context info\n");
477 goto error;
478 }
479
906c08f6 480 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
481 if (!tmp)
482 goto end;
ceb3a221 483
b093de8a
MB
484 close_file(tmp, fd);
485
96aa77de 486end:
b093de8a
MB
487 return BT_CB_OK;
488
489error:
490 return BT_CB_ERROR_STOP;
491}
59288610 492
4adc8274 493enum bt_cb_ret handle_statedump_file_descriptor(struct bt_ctf_event *call_data,
ceb3a221
MB
494 void *private_data)
495{
2e0a1190 496 const struct bt_definition *scope;
59288610 497 struct processtop *parent;
ceb3a221
MB
498 struct files *file;
499 unsigned long timestamp;
59288610 500 int64_t pid;
906c08f6 501 char *file_name, *hostname;
ceb3a221
MB
502 int fd;
503
c78f2cdc 504 timestamp = bt_ctf_get_timestamp(call_data);
ceb3a221
MB
505 if (timestamp == -1ULL)
506 goto error;
507
ceb3a221
MB
508 scope = bt_ctf_get_top_level_scope(call_data,
509 BT_EVENT_FIELDS);
59288610
MB
510 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
511 scope, "_pid"));
ceb3a221
MB
512 if (bt_ctf_field_get_error()) {
513 fprintf(stderr, "Missing tid context info\n");
514 goto error;
515 }
516
517 scope = bt_ctf_get_top_level_scope(call_data,
518 BT_EVENT_FIELDS);
59288610 519 fd = bt_ctf_get_int64(bt_ctf_get_field(call_data,
ceb3a221
MB
520 scope, "_fd"));
521 if (bt_ctf_field_get_error()) {
522 fprintf(stderr, "Missing fd context info\n");
523 goto error;
524 }
525
526 scope = bt_ctf_get_top_level_scope(call_data,
527 BT_EVENT_FIELDS);
528 file_name = bt_ctf_get_string(bt_ctf_get_field(call_data,
529 scope, "_filename"));
530 if (bt_ctf_field_get_error()) {
531 fprintf(stderr, "Missing file name context info\n");
532 goto error;
533 }
906c08f6 534 hostname = get_context_hostname(call_data);
ceb3a221 535
906c08f6 536 parent = get_proc_pid(&lttngtop, pid, pid, timestamp, hostname);
96aa77de
JD
537 if (!parent)
538 goto end;
539
59288610
MB
540 parent->files_history = create_file(parent->files_history, file_name);
541 file = parent->files_history->file;
542 edit_file(parent, file, fd);
ceb3a221 543
96aa77de 544end:
ceb3a221
MB
545 return BT_CB_OK;
546
547error:
548 return BT_CB_ERROR_STOP;
549}
This page took 0.057597 seconds and 4 git commands to generate.