Traverse a path recursively to add all traces within
[lttv.git] / lttv / lttv / traceset.c
CommitLineData
9c312311 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
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
dc877563 22
23#include <lttv/traceset.h>
3e67c985 24#include <lttv/iattribute.h>
7a4bdb54
YB
25#include <lttv/state.h>
26#include <lttv/hook.h>
f7afe191 27#include <stdio.h>
cbb811b3 28#include <babeltrace/context.h>
7a4bdb54
YB
29#include <babeltrace/iterator.h>
30#include <babeltrace/ctf/events.h>
3685e022 31
32/* To traverse a tree recursively */
33#include <fcntl.h>
34#include <fts.h>
35
dc877563 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
dc877563 42
7a4bdb54 43LttvTraceset *lttv_traceset_new(void)
dc877563 44{
90e19f82 45 LttvTraceset *s;
7a4bdb54 46 struct bt_iter_pos begin_pos;
dc877563 47
90e19f82
AM
48 s = g_new(LttvTraceset, 1);
49 s->filename = NULL;
50 s->traces = g_ptr_array_new();
cbb811b3 51 s->context = bt_context_create();
90e19f82 52 s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
7a4bdb54
YB
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
90e19f82 67 return s;
dc877563 68}
69
49bf71b5 70char * lttv_traceset_name(LttvTraceset * s)
71{
90e19f82 72 return s->filename;
49bf71b5 73}
74
2bc1bcfb 75#ifdef BABEL_CLEANUP
76LttvTrace *lttv_trace_new(LttTrace *t)
308711e5 77{
90e19f82 78 LttvTrace *new_trace;
308711e5 79
90e19f82
AM
80 new_trace = g_new(LttvTrace, 1);
81 new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2bc1bcfb 82 new_trace->id = t;
90e19f82
AM
83 new_trace->ref_count = 0;
84 return new_trace;
308711e5 85}
2bc1bcfb 86#endif
308711e5 87
2bc1bcfb 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 */
100static 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;
7a4bdb54
YB
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;
2bc1bcfb 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 */
134static 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}
308711e5 143
f7afe191 144LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
145{
90e19f82
AM
146 guint i;
147 LttvTraceset *s;
148 LttvTrace * trace;
f7afe191 149
90e19f82
AM
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++;
2176f952 157
7a4bdb54 158 /* WARNING: this is an alias, not a copy. */
90e19f82
AM
159 g_ptr_array_add(s->traces, trace);
160 }
cbb811b3
YB
161 s->context = s_orig->context;
162 bt_context_get(s->context);
90e19f82
AM
163 s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
164 return s;
f7afe191 165}
dc877563 166
f7afe191 167
168LttvTraceset *lttv_traceset_load(const gchar *filename)
169{
90e19f82
AM
170 LttvTraceset *s = g_new(LttvTraceset,1);
171 FILE *tf;
f7afe191 172
90e19f82
AM
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;
f7afe191 180}
181
182gint lttv_traceset_save(LttvTraceset *s)
183{
90e19f82 184 FILE *tf;
f7afe191 185
90e19f82 186 tf = fopen(s->filename, "w");
f7afe191 187
90e19f82
AM
188 g_critical("NOT IMPLEMENTED : save traceset data in a XML file");
189
190 fclose(tf);
191 return 0;
f7afe191 192}
308711e5 193
ba576a78 194void lttv_traceset_destroy(LttvTraceset *s)
dc877563 195{
90e19f82 196 guint i;
5e2c04a2 197
90e19f82
AM
198 for(i=0;i<s->traces->len;i++) {
199 LttvTrace *trace = g_ptr_array_index(s->traces, i);
200 lttv_trace_unref(trace);
2bc1bcfb 201 // todo mdenis 2012-03-27: uncomment when babeltrace gets fixed
202 //bt_context_remove_trace(lttv_traceset_get_context(s), trace->id);
90e19f82
AM
203 if(lttv_trace_get_ref_number(trace) == 0)
204 lttv_trace_destroy(trace);
205 }
206 g_ptr_array_free(s->traces, TRUE);
cbb811b3 207 bt_context_put(s->context);
90e19f82
AM
208 g_object_unref(s->a);
209 g_free(s);
dc877563 210}
211
922581a4
YB
212struct bt_context *lttv_traceset_get_context(LttvTraceset *s)
213{
214 return s->context;
215}
216
7a4bdb54
YB
217LttvTraceset *lttv_trace_get_traceset(LttvTrace *trace)
218{
219 return trace->traceset;
220}
221
222LttvHooks *lttv_traceset_get_hooks(LttvTraceset *s)
223{
224 return s->event_hooks;
225}
226
308711e5 227void lttv_trace_destroy(LttvTrace *t)
228{
90e19f82
AM
229 g_object_unref(t->a);
230 g_free(t);
308711e5 231}
232
233
234void lttv_traceset_add(LttvTraceset *s, LttvTrace *t)
dc877563 235{
90e19f82
AM
236 t->ref_count++;
237 g_ptr_array_add(s->traces, t);
dc877563 238}
239
3685e022 240int lttv_traceset_add_path(LttvTraceset *ts, char *trace_path)
2bc1bcfb 241{
3685e022 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
300error:
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;
2bc1bcfb 307}
dc877563 308
309unsigned lttv_traceset_number(LttvTraceset *s)
310{
90e19f82 311 return s->traces->len;
dc877563 312}
313
314
308711e5 315LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i)
dc877563 316{
90e19f82
AM
317 g_assert(s->traces->len > i);
318 return ((LttvTrace *)s->traces->pdata[i]);
dc877563 319}
320
321
ba576a78 322void lttv_traceset_remove(LttvTraceset *s, unsigned i)
dc877563 323{
90e19f82
AM
324 LttvTrace * t;
325 g_assert(s->traces->len > i);
326 t = (LttvTrace *)s->traces->pdata[i];
327 t->ref_count--;
2bc1bcfb 328 bt_context_remove_trace(lttv_traceset_get_context(s), t->id);
90e19f82 329 g_ptr_array_remove_index(s->traces, i);
dc877563 330}
331
332
333/* A set of attributes is attached to each trace set, trace and tracefile
90e19f82 334 to store user defined data as needed. */
dc877563 335
336LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
337{
90e19f82 338 return s->a;
dc877563 339}
340
341
308711e5 342LttvAttribute *lttv_trace_attribute(LttvTrace *t)
343{
90e19f82 344 return t->a;
308711e5 345}
346
2bc1bcfb 347#ifdef BABEL_CLEANUP
308711e5 348LttTrace *lttv_trace(LttvTrace *t)
dc877563 349{
90e19f82 350 return t->t;
dc877563 351}
2bc1bcfb 352#endif
353
354gint lttv_trace_get_id(LttvTrace *t)
355{
356 return t->id;
357}
308711e5 358
2176f952 359guint lttv_trace_get_ref_number(LttvTrace * t)
360{
2bc1bcfb 361 // todo mdenis: adapt to babeltrace
90e19f82 362 return t->ref_count;
2176f952 363}
a43d67ba 364
365guint lttv_trace_ref(LttvTrace * t)
366{
90e19f82
AM
367 t->ref_count++;
368
369 return t->ref_count;
a43d67ba 370}
371
372guint lttv_trace_unref(LttvTrace * t)
373{
90e19f82
AM
374 if(likely(t->ref_count > 0))
375 t->ref_count--;
a43d67ba 376
90e19f82 377 return t->ref_count;
a43d67ba 378}
379
7a4bdb54
YB
380guint lttv_trace_get_num_cpu(LttvTrace *t)
381{
382#warning "TODO - Set the right number of CPU"
383 return 24;
384}
385
386LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset)
387{
388#warning "TODO"
389 return NULL;
390}
391
392void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos)
393{
394#warning "TODO"
395 return NULL;
396}
397
398void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos)
399{
400#warning "TODO"
401}
402
403guint 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
426const char *lttv_traceset_get_name_from_event(LttvEvent *event)
427{
428 return bt_ctf_event_name(event->bt_event);
429}
This page took 0.086344 seconds and 4 git commands to generate.