Fix FSF address in license headers
[lttngtop.git] / src / iostreamtop.c
CommitLineData
1fc22eb4
JD
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 *
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{
31 if (proc->process_files_table->len <= fd) {
32 g_ptr_array_set_size(proc->process_files_table, fd);
33 g_ptr_array_add(proc->process_files_table, file);
34 } else {
35 g_ptr_array_index(proc->process_files_table, fd) = file;
36 }
37 file->fd = fd;
38}
39
40
41void insert_file(struct processtop *proc, int fd)
42{
43 struct files *tmp;
44
45 if (fd >= proc->process_files_table->len) {
46 tmp = g_new0(struct files, 1);
47 tmp->name = "Unknown";
48 add_file(proc, tmp, fd);
49 } else {
50
51 tmp = g_ptr_array_index(proc->process_files_table, fd);
52 if (tmp == NULL) {
53 tmp = g_new0(struct files, 1);
54 tmp->name = "Unknown";
55 tmp->read = 0;
56 tmp->write = 0;
57 tmp->fd = fd;
58 add_file(proc, tmp, fd);
59 }
60 }
61}
62
63void close_file(struct processtop *proc, int fd)
64{
65 int len;
66
67 len = proc->process_files_table->len;
68
69 /*
70 * It is possible that a file was open before taking the trace
71 * and its fd could be greater than all of the others fd
72 * used by the process
73 */
74 if (fd < len) {
75 g_ptr_array_remove_index_fast(proc->process_files_table, fd);
76 g_ptr_array_set_size(proc->process_files_table, len + 1);
77 }
78}
79
80struct files *get_file(struct processtop *proc, int fd)
81{
82 struct files *tmp;
83 tmp = g_ptr_array_index(proc->process_files_table, fd);
84 return tmp;
85}
86
87void show_table(GPtrArray *tab)
88{
89 int i;
90 struct files *file;
91
92 for (i = 0 ; i < tab->len; i++) {
93 file = g_ptr_array_index(tab, i);
94 if (file == NULL)
95 fprintf(stderr, "NULL, ");
96 else
97 fprintf(stderr, "%s, ", file->name);
98 }
99 fprintf(stderr, "]\n\n");
100}
1fc22eb4
JD
101
102int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
d67167cd 103 unsigned long timestamp, uint64_t cpu_id, int ret)
1fc22eb4
JD
104{
105 struct processtop *tmp;
b093de8a 106 struct files *tmpfile;
1fc22eb4
JD
107 int err = 0;
108
109 tmp = get_proc(ctx, tid, comm, timestamp);
b093de8a
MB
110
111 if (tmp->syscall_info != NULL) {
112 if (tmp->syscall_info->type == __NR_read
113 && ret > 0) {
114 tmp->totalfileread += ret;
115 tmp->fileread += ret;
116 tmpfile = get_file(tmp, tmp->syscall_info->fd);
117 tmpfile->read += ret;
118 } else if (tmp->syscall_info->type == __NR_write
119 && ret > 0) {
120 tmp->totalfilewrite += ret;
121 tmp->filewrite += ret;
122 tmpfile = get_file(tmp, tmp->syscall_info->fd);
123 tmpfile->write += ret;
124 } else if (tmp->syscall_info->type == __NR_open
125 && ret > 0) {
126 add_file(tmp, tmp->files_history->file, ret);
127 } else {
1fc22eb4
JD
128 err = -1;
129 }
b093de8a
MB
130 g_free(tmp->syscall_info);
131 tmp->syscall_info = NULL;
132 }
1fc22eb4
JD
133 return err;
134}
135
d67167cd 136struct syscalls *create_syscall_info(unsigned int type, uint64_t cpu_id,
b093de8a
MB
137 unsigned int tid, int fd)
138{
139 struct syscalls *syscall_info;
140
141 syscall_info = g_new0(struct syscalls, 1);
142 syscall_info->type = type;
143 syscall_info->cpu_id = cpu_id;
144 syscall_info->tid = tid;
145 syscall_info->fd = fd;
146
147 return syscall_info;
148}
149
150struct file_history *create_file(struct file_history *history, char *file_name)
151{
152 struct files *new_file;
153 struct file_history *new_history;
154
155 new_file = g_new0(struct files, 1);
156 new_history = g_new0(struct file_history, 1);
157 new_file->name = strdup(file_name);
158 new_file->read = 0;
159 new_file->write = 0;
160 new_history->file = new_file;
161 new_history->next = history;
162
163 return new_history;
164}
165
1fc22eb4
JD
166enum bt_cb_ret handle_exit_syscall(struct bt_ctf_event *call_data,
167 void *private_data)
168{
169 struct definition *scope;
170 unsigned long timestamp;
171 char *comm;
172 uint64_t ret, tid;
d67167cd 173 uint64_t cpu_id;
1fc22eb4
JD
174
175 timestamp = bt_ctf_get_timestamp(call_data);
176 if (timestamp == -1ULL)
177 goto error;
178
1dec520a
JD
179 comm = get_context_comm(call_data);
180 tid = get_context_tid(call_data);
1fc22eb4
JD
181
182 scope = bt_ctf_get_top_level_scope(call_data,
183 BT_EVENT_FIELDS);
184 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
185 scope, "_ret"));
186 if (bt_ctf_field_get_error()) {
187 fprintf(stderr, "Missing ret context info\n");
188 goto error;
189 }
190
d67167cd 191 cpu_id = get_cpu_id(call_data);
1fc22eb4
JD
192
193 /*
b093de8a
MB
194 * if we encounter an exit_syscall and
195 * it is not for a syscall read or write
1fc22eb4
JD
196 * we just abort the execution of this callback
197 */
198 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id, ret)) < 0)
199 return BT_CB_ERROR_CONTINUE;
200
201 return BT_CB_OK;
202
203error:
204 return BT_CB_ERROR_STOP;
205}
206
207
208enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
209 void *private_data)
210{
211 struct definition *scope;
212 struct processtop *tmp;
1fc22eb4
JD
213 unsigned long timestamp;
214 uint64_t cpu_id;
215 char *comm;
216 int64_t tid;
b093de8a 217 int fd;
1fc22eb4
JD
218
219 timestamp = bt_ctf_get_timestamp(call_data);
220 if (timestamp == -1ULL)
221 goto error;
222
1dec520a
JD
223 comm = get_context_comm(call_data);
224 tid = get_context_tid(call_data);
d67167cd 225 cpu_id = get_cpu_id(call_data);
1fc22eb4 226
b093de8a
MB
227 scope = bt_ctf_get_top_level_scope(call_data,
228 BT_EVENT_FIELDS);
229 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
230 scope, "_fd"));
231 if (bt_ctf_field_get_error()) {
232 fprintf(stderr, "Missing fd context info\n");
233 goto error;
234 }
235
1fc22eb4 236 tmp = get_proc(&lttngtop, tid, comm, timestamp);
b093de8a
MB
237 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
238
239 insert_file(tmp, fd);
1fc22eb4
JD
240
241 return BT_CB_OK;
242
243error:
244 return BT_CB_ERROR_STOP;
245}
246
247enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
248 void *private_data)
249{
250 struct processtop *tmp;
251 struct definition *scope;
1fc22eb4
JD
252 unsigned long timestamp;
253 uint64_t cpu_id;
254 char *comm;
255 int64_t tid;
b093de8a 256 int fd;
1fc22eb4
JD
257
258 timestamp = bt_ctf_get_timestamp(call_data);
259 if (timestamp == -1ULL)
260 goto error;
261
1dec520a
JD
262 comm = get_context_comm(call_data);
263 tid = get_context_tid(call_data);
d67167cd 264 cpu_id = get_cpu_id(call_data);
1fc22eb4 265
b093de8a
MB
266 scope = bt_ctf_get_top_level_scope(call_data,
267 BT_EVENT_FIELDS);
268 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
269 scope, "_fd"));
270 if (bt_ctf_field_get_error()) {
271 fprintf(stderr, "Missing fd context info\n");
272 goto error;
273 }
274
275 tmp = get_proc(&lttngtop, tid, comm, timestamp);
276 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
277
278 insert_file(tmp, fd);
279
280 return BT_CB_OK;
281
282error:
283 return BT_CB_ERROR_STOP;
284}
285
286
287enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
288 void *private_data)
289{
290
291 struct processtop *tmp;
292 struct definition *scope;
293 unsigned long timestamp;
294 uint64_t cpu_id;
295 char *comm;
296 int64_t tid;
297 char *file;
298
299 timestamp = bt_ctf_get_timestamp(call_data);
300 if (timestamp == -1ULL)
301 goto error;
302
1dec520a
JD
303 comm = get_context_comm(call_data);
304 tid = get_context_tid(call_data);
d67167cd 305 cpu_id = get_cpu_id(call_data);
b093de8a
MB
306
307 scope = bt_ctf_get_top_level_scope(call_data,
308 BT_EVENT_FIELDS);
309 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
310 scope, "_filename"));
311 if (bt_ctf_field_get_error()) {
312 fprintf(stderr, "Missing fd context info\n");
313 goto error;
314 }
315
1fc22eb4 316 tmp = get_proc(&lttngtop, tid, comm, timestamp);
b093de8a
MB
317 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
318
319 tmp->files_history = create_file(tmp->files_history, file);
1fc22eb4
JD
320
321 return BT_CB_OK;
322
323error:
324 return BT_CB_ERROR_STOP;
325}
326
b093de8a
MB
327
328enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
329 void *private_data)
330{
331 struct definition *scope;
332 unsigned long timestamp;
333 int64_t tid;
334 struct processtop *tmp;
335 char *comm;
336 int fd;
337
338 timestamp = bt_ctf_get_timestamp(call_data);
339 if (timestamp == -1ULL)
340 goto error;
341
1dec520a
JD
342 comm = get_context_comm(call_data);
343 tid = get_context_tid(call_data);
b093de8a
MB
344
345 scope = bt_ctf_get_top_level_scope(call_data,
346 BT_EVENT_FIELDS);
347 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
348 scope, "_fd"));
349 if (bt_ctf_field_get_error()) {
350 fprintf(stderr, "Missing fd context info\n");
351 goto error;
352 }
353
354 tmp = get_proc(&lttngtop, tid, comm, timestamp);
355 close_file(tmp, fd);
356
357 return BT_CB_OK;
358
359error:
360 return BT_CB_ERROR_STOP;
361}
This page took 0.055862 seconds and 4 git commands to generate.