Traverse a path recursively to add all traces within
[lttv.git] / lttv / lttv / traceset.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <lttv/traceset.h>
24 #include <lttv/iattribute.h>
25 #include <lttv/state.h>
26 #include <lttv/hook.h>
27 #include <stdio.h>
28 #include <babeltrace/context.h>
29 #include <babeltrace/iterator.h>
30 #include <babeltrace/ctf/events.h>
31
32 /* To traverse a tree recursively */
33 #include <fcntl.h>
34 #include <fts.h>
35
36 /* A trace is a sequence of events gathered in the same tracing session. The
37 events may be stored in several tracefiles in the same directory.
38 A trace set is defined when several traces are to be analyzed together,
39 possibly to study the interactions between events in the different traces.
40 */
41
42
43 LttvTraceset *lttv_traceset_new(void)
44 {
45 LttvTraceset *s;
46 struct bt_iter_pos begin_pos;
47
48 s = g_new(LttvTraceset, 1);
49 s->filename = NULL;
50 s->traces = g_ptr_array_new();
51 s->context = bt_context_create();
52 s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
53 //TODO remove this when we have really mecanism
54 //s->tmpState = g_new(LttvTraceState *, 1);
55 //lttv_trace_state_init(s->tmpState,0);
56 begin_pos.type = BT_SEEK_BEGIN;
57
58 //s->iter = bt_ctf_iter_create(lttv_traceset_get_context(s),
59 // &begin_pos,
60 // NULL);
61 s->iter = 0;
62 s->event_hooks = lttv_hooks_new();
63
64
65
66
67 return s;
68 }
69
70 char * lttv_traceset_name(LttvTraceset * s)
71 {
72 return s->filename;
73 }
74
75 #ifdef BABEL_CLEANUP
76 LttvTrace *lttv_trace_new(LttTrace *t)
77 {
78 LttvTrace *new_trace;
79
80 new_trace = g_new(LttvTrace, 1);
81 new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
82 new_trace->id = t;
83 new_trace->ref_count = 0;
84 return new_trace;
85 }
86 #endif
87
88 /*
89 * lttv_trace_create : Create a trace from a path
90 *
91 * ts is the traceset in which will be contained the trace
92 *
93 * path is the path where to find a trace. It is not recursive.
94 *
95 * This function is static since a trace should always be contained in a
96 * traceset.
97 *
98 * return the created trace or NULL on failure
99 */
100 static LttvTrace *lttv_trace_create(LttvTraceset *ts, const char *path)
101 {
102 int id = bt_context_add_trace(lttv_traceset_get_context(ts),
103 path,
104 "ctf",
105 NULL,
106 NULL,
107 NULL);
108 if (id < 0) {
109 return NULL;
110 }
111 // Create the trace and save the trace handle id returned by babeltrace
112 LttvTrace *new_trace;
113
114 new_trace = g_new(LttvTrace, 1);
115 new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
116 new_trace->id = id;
117 new_trace->ref_count = 0;
118 new_trace->traceset = ts;
119 new_trace->state = g_new(LttvTraceState,1);
120 lttv_trace_state_init(new_trace->state,new_trace);
121 ts->tmpState = new_trace->state;
122 return new_trace;
123 }
124
125 /*
126 * lttv_trace_create : Create and add a single trace to a traceset
127 *
128 * ts is the traceset in which will be contained the trace
129 *
130 * path is the path where to find a trace. It is not recursive.
131 *
132 * return a positive integer (>=0)on success or -1 on failure
133 */
134 static int lttv_traceset_create_trace(LttvTraceset *ts, const char *path)
135 {
136 LttvTrace *trace = lttv_trace_create(ts, path);
137 if (trace == NULL) {
138 return -1;
139 }
140 lttv_traceset_add(ts, trace);
141 return 0;
142 }
143
144 LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
145 {
146 guint i;
147 LttvTraceset *s;
148 LttvTrace * trace;
149
150 s = g_new(LttvTraceset, 1);
151 s->filename = NULL;
152 s->traces = g_ptr_array_new();
153 for(i=0;i<s_orig->traces->len;i++)
154 {
155 trace = g_ptr_array_index(s_orig->traces, i);
156 trace->ref_count++;
157
158 /* WARNING: this is an alias, not a copy. */
159 g_ptr_array_add(s->traces, trace);
160 }
161 s->context = s_orig->context;
162 bt_context_get(s->context);
163 s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
164 return s;
165 }
166
167
168 LttvTraceset *lttv_traceset_load(const gchar *filename)
169 {
170 LttvTraceset *s = g_new(LttvTraceset,1);
171 FILE *tf;
172
173 s->filename = g_strdup(filename);
174 tf = fopen(filename,"r");
175
176 g_critical("NOT IMPLEMENTED : load traceset data from a XML file");
177
178 fclose(tf);
179 return s;
180 }
181
182 gint lttv_traceset_save(LttvTraceset *s)
183 {
184 FILE *tf;
185
186 tf = fopen(s->filename, "w");
187
188 g_critical("NOT IMPLEMENTED : save traceset data in a XML file");
189
190 fclose(tf);
191 return 0;
192 }
193
194 void lttv_traceset_destroy(LttvTraceset *s)
195 {
196 guint i;
197
198 for(i=0;i<s->traces->len;i++) {
199 LttvTrace *trace = g_ptr_array_index(s->traces, i);
200 lttv_trace_unref(trace);
201 // todo mdenis 2012-03-27: uncomment when babeltrace gets fixed
202 //bt_context_remove_trace(lttv_traceset_get_context(s), trace->id);
203 if(lttv_trace_get_ref_number(trace) == 0)
204 lttv_trace_destroy(trace);
205 }
206 g_ptr_array_free(s->traces, TRUE);
207 bt_context_put(s->context);
208 g_object_unref(s->a);
209 g_free(s);
210 }
211
212 struct bt_context *lttv_traceset_get_context(LttvTraceset *s)
213 {
214 return s->context;
215 }
216
217 LttvTraceset *lttv_trace_get_traceset(LttvTrace *trace)
218 {
219 return trace->traceset;
220 }
221
222 LttvHooks *lttv_traceset_get_hooks(LttvTraceset *s)
223 {
224 return s->event_hooks;
225 }
226
227 void lttv_trace_destroy(LttvTrace *t)
228 {
229 g_object_unref(t->a);
230 g_free(t);
231 }
232
233
234 void lttv_traceset_add(LttvTraceset *s, LttvTrace *t)
235 {
236 t->ref_count++;
237 g_ptr_array_add(s->traces, t);
238 }
239
240 int lttv_traceset_add_path(LttvTraceset *ts, char *trace_path)
241 {
242 FTS *tree;
243 FTSENT *node;
244 char * const paths[2] = { trace_path, NULL };
245 int ret = -1;
246
247 tree = fts_open(paths, FTS_NOCHDIR | FTS_LOGICAL, 0);
248 if (tree == NULL) {
249 g_warning("Cannot traverse \"%s\" for reading.\n",
250 trace_path);
251 return ret;
252 }
253
254 int dirfd, metafd;
255 while ((node = fts_read(tree))) {
256
257 if (!(node->fts_info & FTS_D))
258 continue;
259
260 dirfd = open(node->fts_accpath, 0);
261 if (dirfd < 0) {
262 g_warning("Unable to open trace "
263 "directory file descriptor : %s.", node->fts_accpath);
264 ret = dirfd;
265 goto error;
266 }
267
268 // Check if a metadata file exists in the current directory
269 metafd = openat(dirfd, "metadata", O_RDONLY);
270 if (metafd < 0) {
271 ret = close(dirfd);
272 if (ret < 0) {
273 g_warning("Unable to open metadata "
274 "file descriptor : %s.", node->fts_accpath);
275 goto error;
276 }
277 } else {
278 ret = close(metafd);
279 if (ret < 0) {
280 g_warning("Unable to close metadata "
281 "file descriptor : %s.", node->fts_accpath);
282 goto error;
283 }
284 ret = close(dirfd);
285 if (ret < 0) {
286 g_warning("Unable to close trace "
287 "directory file descriptor : %s.", node->fts_accpath);
288 goto error;
289 }
290
291 ret = lttv_traceset_create_trace(ts, node->fts_accpath);
292 if (ret < 0) {
293 g_warning("Opening trace \"%s\" from %s "
294 "for reading.", node->fts_accpath, trace_path);
295 goto error;
296 }
297 }
298 }
299
300 error:
301 ret = fts_close(tree);
302 if (ret < 0) {
303 g_warning("Unable to close tree "
304 "file descriptor : %s.", trace_path);
305 }
306 return ret;
307 }
308
309 unsigned lttv_traceset_number(LttvTraceset *s)
310 {
311 return s->traces->len;
312 }
313
314
315 LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i)
316 {
317 g_assert(s->traces->len > i);
318 return ((LttvTrace *)s->traces->pdata[i]);
319 }
320
321
322 void lttv_traceset_remove(LttvTraceset *s, unsigned i)
323 {
324 LttvTrace * t;
325 g_assert(s->traces->len > i);
326 t = (LttvTrace *)s->traces->pdata[i];
327 t->ref_count--;
328 bt_context_remove_trace(lttv_traceset_get_context(s), t->id);
329 g_ptr_array_remove_index(s->traces, i);
330 }
331
332
333 /* A set of attributes is attached to each trace set, trace and tracefile
334 to store user defined data as needed. */
335
336 LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
337 {
338 return s->a;
339 }
340
341
342 LttvAttribute *lttv_trace_attribute(LttvTrace *t)
343 {
344 return t->a;
345 }
346
347 #ifdef BABEL_CLEANUP
348 LttTrace *lttv_trace(LttvTrace *t)
349 {
350 return t->t;
351 }
352 #endif
353
354 gint lttv_trace_get_id(LttvTrace *t)
355 {
356 return t->id;
357 }
358
359 guint lttv_trace_get_ref_number(LttvTrace * t)
360 {
361 // todo mdenis: adapt to babeltrace
362 return t->ref_count;
363 }
364
365 guint lttv_trace_ref(LttvTrace * t)
366 {
367 t->ref_count++;
368
369 return t->ref_count;
370 }
371
372 guint lttv_trace_unref(LttvTrace * t)
373 {
374 if(likely(t->ref_count > 0))
375 t->ref_count--;
376
377 return t->ref_count;
378 }
379
380 guint lttv_trace_get_num_cpu(LttvTrace *t)
381 {
382 #warning "TODO - Set the right number of CPU"
383 return 24;
384 }
385
386 LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset)
387 {
388 #warning "TODO"
389 return NULL;
390 }
391
392 void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos)
393 {
394 #warning "TODO"
395 return NULL;
396 }
397
398 void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos)
399 {
400 #warning "TODO"
401 }
402
403 guint lttv_traceset_get_cpuid_from_event(LttvEvent *event)
404 {
405 struct definition *scope;
406 unsigned long timestamp;
407 unsigned int cpu_id;
408
409 struct bt_ctf_event *ctf_event = event->bt_event;
410 timestamp = bt_ctf_get_timestamp(ctf_event);
411 if (timestamp == -1ULL) {
412 return 0;
413 }
414 scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT);
415 if (bt_ctf_field_get_error()) {
416 return 0;
417 }
418 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id"));
419 if (bt_ctf_field_get_error()) {
420 return 0;
421 } else {
422 return cpu_id;
423 }
424 }
425
426 const char *lttv_traceset_get_name_from_event(LttvEvent *event)
427 {
428 return bt_ctf_event_name(event->bt_event);
429 }
This page took 0.037578 seconds and 4 git commands to generate.