Implements scrollbar in main window
[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>
451aaf27 28#include <babeltrace/babeltrace.h>
cbb811b3 29#include <babeltrace/context.h>
451aaf27 30#include <babeltrace/ctf/iterator.h>
7a4bdb54 31#include <babeltrace/ctf/events.h>
3685e022 32
33/* To traverse a tree recursively */
34#include <fcntl.h>
35#include <fts.h>
451aaf27
FD
36/* For the use of realpath*/
37#include <limits.h>
38#include <stdlib.h>
39/* For strcpy*/
40#include <string.h>
3685e022 41
dc877563 42/* A trace is a sequence of events gathered in the same tracing session. The
43 events may be stored in several tracefiles in the same directory.
44 A trace set is defined when several traces are to be analyzed together,
45 possibly to study the interactions between events in the different traces.
46*/
47
dc877563 48
7a4bdb54 49LttvTraceset *lttv_traceset_new(void)
dc877563 50{
90e19f82 51 LttvTraceset *s;
7a4bdb54 52 struct bt_iter_pos begin_pos;
dc877563 53
90e19f82
AM
54 s = g_new(LttvTraceset, 1);
55 s->filename = NULL;
56 s->traces = g_ptr_array_new();
cbb811b3 57 s->context = bt_context_create();
90e19f82 58 s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
7a4bdb54
YB
59 //TODO remove this when we have really mecanism
60 //s->tmpState = g_new(LttvTraceState *, 1);
61 //lttv_trace_state_init(s->tmpState,0);
7a4bdb54 62
7a4bdb54
YB
63 s->iter = 0;
64 s->event_hooks = lttv_hooks_new();
451aaf27 65
115c78c2 66 s->state_trace_handle_index = g_ptr_array_new();
7a4bdb54 67
90e19f82 68 return s;
dc877563 69}
70
49bf71b5 71char * lttv_traceset_name(LttvTraceset * s)
72{
90e19f82 73 return s->filename;
49bf71b5 74}
75
2bc1bcfb 76#ifdef BABEL_CLEANUP
77LttvTrace *lttv_trace_new(LttTrace *t)
308711e5 78{
90e19f82 79 LttvTrace *new_trace;
308711e5 80
90e19f82
AM
81 new_trace = g_new(LttvTrace, 1);
82 new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2bc1bcfb 83 new_trace->id = t;
90e19f82
AM
84 new_trace->ref_count = 0;
85 return new_trace;
308711e5 86}
2bc1bcfb 87#endif
451aaf27
FD
88/*
89 * get_absolute_pathname : Return the unique pathname in the system
90 *
91 * pathname is the relative path.
92 *
93 * abs_pathname is being set to the absolute path.
94 *
95 */
96void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname)
97{
98 abs_pathname[0] = '\0';
99
100 if (realpath(pathname, abs_pathname) != NULL)
101 return;
102 else
103 {
104 /* error, return the original path unmodified */
105 strcpy(abs_pathname, pathname);
106 return;
107 }
108 return;
109}
110
111
308711e5 112
2bc1bcfb 113/*
114 * lttv_trace_create : Create a trace from a path
115 *
116 * ts is the traceset in which will be contained the trace
117 *
118 * path is the path where to find a trace. It is not recursive.
119 *
120 * This function is static since a trace should always be contained in a
121 * traceset.
122 *
123 * return the created trace or NULL on failure
124 */
125static LttvTrace *lttv_trace_create(LttvTraceset *ts, const char *path)
126{
127 int id = bt_context_add_trace(lttv_traceset_get_context(ts),
128 path,
129 "ctf",
130 NULL,
131 NULL,
132 NULL);
133 if (id < 0) {
134 return NULL;
135 }
136 // Create the trace and save the trace handle id returned by babeltrace
137 LttvTrace *new_trace;
138
139 new_trace = g_new(LttvTrace, 1);
140 new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
141 new_trace->id = id;
142 new_trace->ref_count = 0;
7a4bdb54
YB
143 new_trace->traceset = ts;
144 new_trace->state = g_new(LttvTraceState,1);
145 lttv_trace_state_init(new_trace->state,new_trace);
115c78c2
YB
146
147 /* Add the state to the trace_handle to state index */
148 g_ptr_array_set_size(ts->state_trace_handle_index,id+1);
149 g_ptr_array_index(ts->state_trace_handle_index,id) = new_trace->state;
150
2bc1bcfb 151 return new_trace;
152}
153
154/*
155 * lttv_trace_create : Create and add a single trace to a traceset
156 *
157 * ts is the traceset in which will be contained the trace
158 *
159 * path is the path where to find a trace. It is not recursive.
160 *
161 * return a positive integer (>=0)on success or -1 on failure
162 */
163static int lttv_traceset_create_trace(LttvTraceset *ts, const char *path)
164{
165 LttvTrace *trace = lttv_trace_create(ts, path);
166 if (trace == NULL) {
167 return -1;
168 }
169 lttv_traceset_add(ts, trace);
170 return 0;
171}
308711e5 172
f7afe191 173LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
174{
90e19f82
AM
175 guint i;
176 LttvTraceset *s;
177 LttvTrace * trace;
f7afe191 178
90e19f82
AM
179 s = g_new(LttvTraceset, 1);
180 s->filename = NULL;
181 s->traces = g_ptr_array_new();
115c78c2 182 s->state_trace_handle_index = g_ptr_array_new();
90e19f82
AM
183 for(i=0;i<s_orig->traces->len;i++)
184 {
185 trace = g_ptr_array_index(s_orig->traces, i);
186 trace->ref_count++;
2176f952 187
7a4bdb54 188 /* WARNING: this is an alias, not a copy. */
90e19f82 189 g_ptr_array_add(s->traces, trace);
115c78c2
YB
190
191 g_ptr_array_set_size(s->state_trace_handle_index,trace->id+1);
192 g_ptr_array_index(s->state_trace_handle_index,trace->id) = trace->state;
193
90e19f82 194 }
cbb811b3
YB
195 s->context = s_orig->context;
196 bt_context_get(s->context);
90e19f82
AM
197 s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
198 return s;
f7afe191 199}
dc877563 200
f7afe191 201
202LttvTraceset *lttv_traceset_load(const gchar *filename)
203{
90e19f82
AM
204 LttvTraceset *s = g_new(LttvTraceset,1);
205 FILE *tf;
f7afe191 206
90e19f82
AM
207 s->filename = g_strdup(filename);
208 tf = fopen(filename,"r");
209
210 g_critical("NOT IMPLEMENTED : load traceset data from a XML file");
211
212 fclose(tf);
213 return s;
f7afe191 214}
215
216gint lttv_traceset_save(LttvTraceset *s)
217{
90e19f82 218 FILE *tf;
f7afe191 219
90e19f82 220 tf = fopen(s->filename, "w");
f7afe191 221
90e19f82
AM
222 g_critical("NOT IMPLEMENTED : save traceset data in a XML file");
223
224 fclose(tf);
225 return 0;
f7afe191 226}
308711e5 227
ba576a78 228void lttv_traceset_destroy(LttvTraceset *s)
dc877563 229{
90e19f82 230 guint i;
5e2c04a2 231
90e19f82
AM
232 for(i=0;i<s->traces->len;i++) {
233 LttvTrace *trace = g_ptr_array_index(s->traces, i);
234 lttv_trace_unref(trace);
2bc1bcfb 235 // todo mdenis 2012-03-27: uncomment when babeltrace gets fixed
236 //bt_context_remove_trace(lttv_traceset_get_context(s), trace->id);
90e19f82
AM
237 if(lttv_trace_get_ref_number(trace) == 0)
238 lttv_trace_destroy(trace);
239 }
240 g_ptr_array_free(s->traces, TRUE);
cbb811b3 241 bt_context_put(s->context);
90e19f82
AM
242 g_object_unref(s->a);
243 g_free(s);
dc877563 244}
245
922581a4
YB
246struct bt_context *lttv_traceset_get_context(LttvTraceset *s)
247{
248 return s->context;
249}
250
7a4bdb54
YB
251LttvTraceset *lttv_trace_get_traceset(LttvTrace *trace)
252{
253 return trace->traceset;
254}
255
256LttvHooks *lttv_traceset_get_hooks(LttvTraceset *s)
257{
258 return s->event_hooks;
259}
260
308711e5 261void lttv_trace_destroy(LttvTrace *t)
262{
90e19f82
AM
263 g_object_unref(t->a);
264 g_free(t);
308711e5 265}
266
308711e5 267void lttv_traceset_add(LttvTraceset *s, LttvTrace *t)
dc877563 268{
90e19f82
AM
269 t->ref_count++;
270 g_ptr_array_add(s->traces, t);
dc877563 271}
272
3685e022 273int lttv_traceset_add_path(LttvTraceset *ts, char *trace_path)
2bc1bcfb 274{
451aaf27 275
3685e022 276 FTS *tree;
277 FTSENT *node;
278 char * const paths[2] = { trace_path, NULL };
279 int ret = -1;
861fbe5f
FD
280
281 gboolean metaFileFound = FALSE;
451aaf27 282
3685e022 283 tree = fts_open(paths, FTS_NOCHDIR | FTS_LOGICAL, 0);
284 if (tree == NULL) {
285 g_warning("Cannot traverse \"%s\" for reading.\n",
286 trace_path);
287 return ret;
288 }
289
290 int dirfd, metafd;
291 while ((node = fts_read(tree))) {
292
293 if (!(node->fts_info & FTS_D))
294 continue;
295
296 dirfd = open(node->fts_accpath, 0);
297 if (dirfd < 0) {
298 g_warning("Unable to open trace "
299 "directory file descriptor : %s.", node->fts_accpath);
300 ret = dirfd;
301 goto error;
302 }
303
304 // Check if a metadata file exists in the current directory
305 metafd = openat(dirfd, "metadata", O_RDONLY);
306 if (metafd < 0) {
307 ret = close(dirfd);
308 if (ret < 0) {
309 g_warning("Unable to open metadata "
310 "file descriptor : %s.", node->fts_accpath);
311 goto error;
312 }
313 } else {
314 ret = close(metafd);
315 if (ret < 0) {
316 g_warning("Unable to close metadata "
317 "file descriptor : %s.", node->fts_accpath);
318 goto error;
319 }
320 ret = close(dirfd);
321 if (ret < 0) {
322 g_warning("Unable to close trace "
323 "directory file descriptor : %s.", node->fts_accpath);
324 goto error;
325 }
326
327 ret = lttv_traceset_create_trace(ts, node->fts_accpath);
328 if (ret < 0) {
329 g_warning("Opening trace \"%s\" from %s "
330 "for reading.", node->fts_accpath, trace_path);
331 goto error;
332 }
861fbe5f 333 metaFileFound = TRUE;
3685e022 334 }
335 }
336
337error:
338 ret = fts_close(tree);
339 if (ret < 0) {
340 g_warning("Unable to close tree "
341 "file descriptor : %s.", trace_path);
342 }
861fbe5f
FD
343 if(metaFileFound)
344 return ret;
345 else
346 return -1;
2bc1bcfb 347}
dc877563 348
861fbe5f 349
dc877563 350unsigned lttv_traceset_number(LttvTraceset *s)
351{
90e19f82 352 return s->traces->len;
dc877563 353}
354
355
308711e5 356LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i)
dc877563 357{
90e19f82
AM
358 g_assert(s->traces->len > i);
359 return ((LttvTrace *)s->traces->pdata[i]);
dc877563 360}
361
362
ba576a78 363void lttv_traceset_remove(LttvTraceset *s, unsigned i)
dc877563 364{
90e19f82
AM
365 LttvTrace * t;
366 g_assert(s->traces->len > i);
367 t = (LttvTrace *)s->traces->pdata[i];
368 t->ref_count--;
2bc1bcfb 369 bt_context_remove_trace(lttv_traceset_get_context(s), t->id);
90e19f82 370 g_ptr_array_remove_index(s->traces, i);
dc877563 371}
372
373
374/* A set of attributes is attached to each trace set, trace and tracefile
90e19f82 375 to store user defined data as needed. */
dc877563 376
377LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
378{
90e19f82 379 return s->a;
dc877563 380}
381
382
308711e5 383LttvAttribute *lttv_trace_attribute(LttvTrace *t)
384{
90e19f82 385 return t->a;
308711e5 386}
387
2bc1bcfb 388
389gint lttv_trace_get_id(LttvTrace *t)
390{
391 return t->id;
392}
308711e5 393
2176f952 394guint lttv_trace_get_ref_number(LttvTrace * t)
395{
2bc1bcfb 396 // todo mdenis: adapt to babeltrace
90e19f82 397 return t->ref_count;
2176f952 398}
a43d67ba 399
400guint lttv_trace_ref(LttvTrace * t)
401{
90e19f82
AM
402 t->ref_count++;
403
404 return t->ref_count;
a43d67ba 405}
406
407guint lttv_trace_unref(LttvTrace * t)
408{
90e19f82
AM
409 if(likely(t->ref_count > 0))
410 t->ref_count--;
a43d67ba 411
90e19f82 412 return t->ref_count;
a43d67ba 413}
414
7a4bdb54
YB
415guint lttv_trace_get_num_cpu(LttvTrace *t)
416{
417#warning "TODO - Set the right number of CPU"
418 return 24;
419}
420
421LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset)
422{
3d1e7ee5
YB
423 LttvTracesetPosition *traceset_pos;
424
425 traceset_pos = g_new(LttvTracesetPosition, 1);
426
427 /* Check in the new passed */
428 if(traceset_pos == NULL) {
429 return NULL;
430 }
431
432 traceset_pos->iter = traceset->iter;
433 traceset_pos->bt_pos = bt_iter_get_pos(bt_ctf_get_iter(traceset->iter));
434
435 return traceset_pos;
7a4bdb54
YB
436}
437
438void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos)
439{
3d1e7ee5
YB
440 bt_iter_free_pos(traceset_pos->bt_pos);
441 g_free(traceset_pos);
7a4bdb54
YB
442}
443
444void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos)
445{
3d1e7ee5 446 bt_iter_set_pos(traceset_pos->iter, traceset_pos->bt_pos);
7a4bdb54
YB
447}
448
449guint lttv_traceset_get_cpuid_from_event(LttvEvent *event)
450{
451 struct definition *scope;
452 unsigned long timestamp;
453 unsigned int cpu_id;
454
455 struct bt_ctf_event *ctf_event = event->bt_event;
456 timestamp = bt_ctf_get_timestamp(ctf_event);
457 if (timestamp == -1ULL) {
458 return 0;
459 }
460 scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT);
461 if (bt_ctf_field_get_error()) {
462 return 0;
463 }
464 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id"));
465 if (bt_ctf_field_get_error()) {
466 return 0;
467 } else {
468 return cpu_id;
469 }
470}
451aaf27
FD
471/*
472 * lttv_traceset_get_timestamp_begin : returns the minimum timestamp of
473 * all the traces in the traceset.
474 *
475 */
476
477guint64 lttv_traceset_get_timestamp_begin(LttvTraceset *traceset)
478{
479 struct bt_context *bt_ctx;
480 bt_ctx = lttv_traceset_get_context(traceset);
481 guint64 timestamp_min = G_MAXUINT64, timestamp_cur = 0;
482 int i;
483 int trace_count;
484 LttvTrace *currentTrace;
485 trace_count = traceset->traces->len;
486 if(trace_count == 0)
487 timestamp_min = 0;
488 else{
489 timestamp_min = G_MAXUINT64;
490
491 for(i = 0; i < trace_count;i++)
492 {
493 currentTrace = g_ptr_array_index(traceset->traces,i);
494 timestamp_cur = bt_trace_handle_get_timestamp_begin(bt_ctx, currentTrace->id);
495 if(timestamp_cur < timestamp_min)
496 timestamp_min = timestamp_cur;
497 }
498 }
499 return timestamp_min;
500}
501
502/*
503 * lttv_traceset_get_timestamp_end: returns the maximum timestamp of
504 * all the traces in the traceset.
505 *
506 */
507guint64 lttv_traceset_get_timestamp_end(LttvTraceset *traceset)
508{
509 struct bt_context *bt_ctx;
510 bt_ctx = lttv_traceset_get_context(traceset);
511 guint64 timestamp_max, timestamp_cur = 0;
512 int i;
513 int trace_count;
514 LttvTrace *currentTrace;
515 trace_count = traceset->traces->len;
516
517 if(trace_count == 0)
518 timestamp_max = 1;
519 else
520 {
521 timestamp_max = 0;
522 for(i =0; i < trace_count;i++)
523 {
524 currentTrace = g_ptr_array_index(traceset->traces,i);
525 timestamp_cur = bt_trace_handle_get_timestamp_end(bt_ctx, currentTrace->id);
526 if(timestamp_cur > timestamp_max)
527 timestamp_max = timestamp_cur;
528 }
529 }
530 return timestamp_max;
9aaa78dc
FD
531}
532
533/*
534 * lttv_traceset_get_time_span : return a TimeInterval representing the
535 * minimum timestamp dans le maximum timestamp of the traceset.
536 *
537 */
538TimeInterval lttv_traceset_get_time_span(LttvTraceset *ts)
539{
540 TimeInterval time_span;
541 time_span.start_time =ltt_time_from_uint64( lttv_traceset_get_timestamp_begin(ts));
542 time_span.end_time = ltt_time_from_uint64(lttv_traceset_get_timestamp_end(ts));
543 return time_span;
451aaf27 544}
7a4bdb54
YB
545
546const char *lttv_traceset_get_name_from_event(LttvEvent *event)
547{
548 return bt_ctf_event_name(event->bt_event);
549}
This page took 0.106103 seconds and 4 git commands to generate.