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