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