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