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