wrapper to access context fields
[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
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
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <string.h>
24 #include <babeltrace/babeltrace.h>
25
26 #include "lttngtoptypes.h"
27 #include "common.h"
28 #include "iostreamtop.h"
29
30 void 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
42 void 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
64 void 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
81 struct 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
88 void 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 }
102
103 int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
104 unsigned long timestamp, uint64_t cpu_id, int ret)
105 {
106 struct processtop *tmp;
107 struct files *tmpfile;
108 int err = 0;
109
110 tmp = get_proc(ctx, tid, comm, timestamp);
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 {
129 err = -1;
130 }
131 g_free(tmp->syscall_info);
132 tmp->syscall_info = NULL;
133 }
134 return err;
135 }
136
137 struct syscalls *create_syscall_info(unsigned int type, uint64_t 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
151 struct 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
167 enum 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 uint64_t cpu_id;
175
176 timestamp = bt_ctf_get_timestamp(call_data);
177 if (timestamp == -1ULL)
178 goto error;
179
180 comm = get_context_comm(call_data);
181 tid = get_context_tid(call_data);
182
183 scope = bt_ctf_get_top_level_scope(call_data,
184 BT_EVENT_FIELDS);
185 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
186 scope, "_ret"));
187 if (bt_ctf_field_get_error()) {
188 fprintf(stderr, "Missing ret context info\n");
189 goto error;
190 }
191
192 cpu_id = get_cpu_id(call_data);
193
194 /*
195 * if we encounter an exit_syscall and
196 * it is not for a syscall read or write
197 * we just abort the execution of this callback
198 */
199 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id, ret)) < 0)
200 return BT_CB_ERROR_CONTINUE;
201
202 return BT_CB_OK;
203
204 error:
205 return BT_CB_ERROR_STOP;
206 }
207
208
209 enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
210 void *private_data)
211 {
212 struct definition *scope;
213 struct processtop *tmp;
214 unsigned long timestamp;
215 uint64_t cpu_id;
216 char *comm;
217 int64_t tid;
218 int fd;
219
220 timestamp = bt_ctf_get_timestamp(call_data);
221 if (timestamp == -1ULL)
222 goto error;
223
224 comm = get_context_comm(call_data);
225 tid = get_context_tid(call_data);
226 cpu_id = get_cpu_id(call_data);
227
228 scope = bt_ctf_get_top_level_scope(call_data,
229 BT_EVENT_FIELDS);
230 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
231 scope, "_fd"));
232 if (bt_ctf_field_get_error()) {
233 fprintf(stderr, "Missing fd context info\n");
234 goto error;
235 }
236
237 tmp = get_proc(&lttngtop, tid, comm, timestamp);
238 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
239
240 insert_file(tmp, fd);
241
242 return BT_CB_OK;
243
244 error:
245 return BT_CB_ERROR_STOP;
246 }
247
248 enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
249 void *private_data)
250 {
251 struct processtop *tmp;
252 struct definition *scope;
253 unsigned long timestamp;
254 uint64_t cpu_id;
255 char *comm;
256 int64_t tid;
257 int fd;
258
259 timestamp = bt_ctf_get_timestamp(call_data);
260 if (timestamp == -1ULL)
261 goto error;
262
263 comm = get_context_comm(call_data);
264 tid = get_context_tid(call_data);
265 cpu_id = get_cpu_id(call_data);
266
267 scope = bt_ctf_get_top_level_scope(call_data,
268 BT_EVENT_FIELDS);
269 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
270 scope, "_fd"));
271 if (bt_ctf_field_get_error()) {
272 fprintf(stderr, "Missing fd context info\n");
273 goto error;
274 }
275
276 tmp = get_proc(&lttngtop, tid, comm, timestamp);
277 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
278
279 insert_file(tmp, fd);
280
281 return BT_CB_OK;
282
283 error:
284 return BT_CB_ERROR_STOP;
285 }
286
287
288 enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
289 void *private_data)
290 {
291
292 struct processtop *tmp;
293 struct definition *scope;
294 unsigned long timestamp;
295 uint64_t cpu_id;
296 char *comm;
297 int64_t tid;
298 char *file;
299
300 timestamp = bt_ctf_get_timestamp(call_data);
301 if (timestamp == -1ULL)
302 goto error;
303
304 comm = get_context_comm(call_data);
305 tid = get_context_tid(call_data);
306 cpu_id = get_cpu_id(call_data);
307
308 scope = bt_ctf_get_top_level_scope(call_data,
309 BT_EVENT_FIELDS);
310 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
311 scope, "_filename"));
312 if (bt_ctf_field_get_error()) {
313 fprintf(stderr, "Missing fd context info\n");
314 goto error;
315 }
316
317 tmp = get_proc(&lttngtop, tid, comm, timestamp);
318 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
319
320 tmp->files_history = create_file(tmp->files_history, file);
321
322 return BT_CB_OK;
323
324 error:
325 return BT_CB_ERROR_STOP;
326 }
327
328
329 enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
330 void *private_data)
331 {
332 struct definition *scope;
333 unsigned long timestamp;
334 int64_t tid;
335 struct processtop *tmp;
336 char *comm;
337 int fd;
338
339 timestamp = bt_ctf_get_timestamp(call_data);
340 if (timestamp == -1ULL)
341 goto error;
342
343 comm = get_context_comm(call_data);
344 tid = get_context_tid(call_data);
345
346 scope = bt_ctf_get_top_level_scope(call_data,
347 BT_EVENT_FIELDS);
348 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
349 scope, "_fd"));
350 if (bt_ctf_field_get_error()) {
351 fprintf(stderr, "Missing fd context info\n");
352 goto error;
353 }
354
355 tmp = get_proc(&lttngtop, tid, comm, timestamp);
356 close_file(tmp, fd);
357
358 return BT_CB_OK;
359
360 error:
361 return BT_CB_ERROR_STOP;
362 }
This page took 0.052334 seconds and 4 git commands to generate.