add eventdefs exclusion in open_tracefiles
[lttv.git] / ltt / branches / poly / lttv / lttv / tracecontext.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
22
00e74b69 23#include <string.h>
d8f124de 24#include <lttv/tracecontext.h>
ffd54a90 25#include <ltt/event.h>
b445142a 26#include <ltt/facility.h>
a5dcde2f 27#include <ltt/trace.h>
28#include <ltt/type.h>
27304273 29#include <errno.h>
dc877563 30
8697a616 31
32
33
27304273 34gint compare_tracefile(gconstpointer a, gconstpointer b)
8697a616 35{
cf94ff67 36 gint comparison = 0;
8697a616 37
00e74b69 38 const LttvTracefileContext *trace_a = (const LttvTracefileContext *)a;
00e74b69 39 const LttvTracefileContext *trace_b = (const LttvTracefileContext *)b;
8697a616 40
1d1df11d 41 if(likely(trace_a != trace_b)) {
77199e93 42 comparison = ltt_time_compare(trace_b->timestamp, trace_a->timestamp);
1d1df11d 43 if(unlikely(comparison == 0)) {
a855f059 44 if(trace_a->index < trace_b->index) comparison = -1;
45 else if(trace_a->index > trace_b->index) comparison = 1;
46 else if(trace_a->t_context->index < trace_b->t_context->index)
47 comparison = -1;
48 else if(trace_a->t_context->index > trace_b->t_context->index)
49 comparison = 1;
50 }
cf94ff67 51 }
cf94ff67 52 return comparison;
8697a616 53}
54
8697a616 55struct _LttvTracesetContextPosition {
27304273 56 GArray *ep; /* Array of LttEventPosition */
57 GArray *tfc; /* Array of corresponding
58 TracefileContext* */
2d262115 59 LttTime timestamp; /* Current time at the saved position */
8697a616 60};
61
ffd54a90 62void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
dc877563 63{
ffd54a90 64 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
dc877563 65}
66
67
68void lttv_context_fini(LttvTracesetContext *self)
69{
70 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
71}
72
73
74LttvTracesetContext *
75lttv_context_new_traceset_context(LttvTracesetContext *self)
76{
77 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
78}
79
80
81
82
83LttvTraceContext *
84lttv_context_new_trace_context(LttvTracesetContext *self)
85{
86 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
87}
88
89
90LttvTracefileContext *
91lttv_context_new_tracefile_context(LttvTracesetContext *self)
92{
c6bc9cb9 93 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dc877563 94}
95
f7afe191 96/****************************************************************************
97 * lttv_traceset_context_compute_time_span
98 *
8697a616 99 * Keep the time span is sync with on the fly addition and removal of traces
f7afe191 100 * in a trace set. It must be called each time a trace is added/removed from
101 * the traceset. It could be more efficient to call it only once a bunch
102 * of traces are loaded, but the calculation is not long, so it's not
103 * critical.
104 *
105 * Author : Xang Xiu Yang
f7afe191 106 ***************************************************************************/
107static void lttv_traceset_context_compute_time_span(
108 LttvTracesetContext *self,
33f7a12c 109 TimeInterval *time_span)
f7afe191 110{
111 LttvTraceset * traceset = self->ts;
112 int numTraces = lttv_traceset_number(traceset);
113 int i;
114 LttTime s, e;
115 LttvTraceContext *tc;
116 LttTrace * trace;
117
33f7a12c 118 time_span->start_time.tv_sec = 0;
119 time_span->start_time.tv_nsec = 0;
120 time_span->end_time.tv_sec = 0;
121 time_span->end_time.tv_nsec = 0;
912be9a5 122
f7afe191 123 for(i=0; i<numTraces;i++){
124 tc = self->traces[i];
125 trace = tc->t;
126
127 ltt_trace_time_span_get(trace, &s, &e);
128
129 if(i==0){
33f7a12c 130 time_span->start_time = s;
131 time_span->end_time = e;
f7afe191 132 }else{
33f7a12c 133 if(s.tv_sec < time_span->start_time.tv_sec
134 || (s.tv_sec == time_span->start_time.tv_sec
135 && s.tv_nsec < time_span->start_time.tv_nsec))
136 time_span->start_time = s;
137 if(e.tv_sec > time_span->end_time.tv_sec
138 || (e.tv_sec == time_span->end_time.tv_sec
139 && e.tv_nsec > time_span->end_time.tv_nsec))
140 time_span->end_time = e;
f7afe191 141 }
142 }
143}
144
eed2ef37 145static void init_tracefile_context(LttTracefile *tracefile,
146 LttvTraceContext *tc)
147{
148 LttvTracefileContext *tfc;
149 LttvTracesetContext *tsc = tc->ts_context;
150
151 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->new_tracefile_context(tsc);
152
153 tfc->index = tc->tracefiles->len;
154 tc->tracefiles = g_array_append_val(tc->tracefiles, tfc);
155
156 tfc->tf = tracefile;
157
158 tfc->t_context = tc;
159 tfc->event = lttv_hooks_new();
160 tfc->event_by_id = lttv_hooks_by_id_new();
161 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
162}
163
dc877563 164
165static void
166init(LttvTracesetContext *self, LttvTraceset *ts)
167{
327a4314 168 guint i, nb_trace;
dc877563 169
170 LttvTraceContext *tc;
171
3865ea09 172 GData **tracefiles_groups;
dc877563 173
eed2ef37 174 struct compute_tracefile_group_args args;
308711e5 175
dc877563 176 nb_trace = lttv_traceset_number(ts);
177 self->ts = ts;
ffd54a90 178 self->traces = g_new(LttvTraceContext *, nb_trace);
ffd54a90 179 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 180 self->ts_a = lttv_traceset_attribute(ts);
dc877563 181 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 182 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
dc877563 183 self->traces[i] = tc;
184
185 tc->ts_context = self;
186 tc->index = i;
308711e5 187 tc->vt = lttv_traceset_get(ts, i);
188 tc->t = lttv_trace(tc->vt);
ffd54a90 189 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 190 tc->t_a = lttv_trace_attribute(tc->vt);
3865ea09 191 tc->tracefiles = g_array_sized_new(FALSE, TRUE,
192 sizeof(LttvTracefileContext*), 10);
eed2ef37 193
194 tracefiles_groups = ltt_trace_get_tracefiles_groups(tc->t);
e45551ac 195 if(tracefiles_groups != NULL) {
196 args.func = (ForEachTraceFileFunc)init_tracefile_context;
197 args.func_args = tc;
eed2ef37 198
e45551ac 199 g_datalist_foreach(tracefiles_groups,
200 (GDataForeachFunc)compute_tracefile_group,
201 &args);
202 }
eed2ef37 203
204#if 0
dc877563 205 nb_control = ltt_trace_control_tracefile_number(tc->t);
206 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
207 nb_tracefile = nb_control + nb_per_cpu;
dbb7bb09 208 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
dc877563 209
210 for(j = 0 ; j < nb_tracefile ; j++) {
ffd54a90 211 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dbb7bb09 212 tc->tracefiles[j] = tfc;
213 tfc->index = j;
214
dc877563 215 if(j < nb_control) {
dc877563 216 tfc->control = TRUE;
ffd54a90 217 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
dc877563 218 }
219 else {
dc877563 220 tfc->control = FALSE;
ffd54a90 221 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
dc877563 222 }
eed2ef37 223
dc877563 224 tfc->t_context = tc;
d3e01c7a 225 tfc->e = ltt_event_new();
8697a616 226 tfc->event = lttv_hooks_new();
227 tfc->event_by_id = lttv_hooks_by_id_new();
ffd54a90 228 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
dc877563 229 }
eed2ef37 230#endif //0
231
dc877563 232 }
2d262115 233 self->pqueue = g_tree_new(compare_tracefile);
eed2ef37 234 lttv_process_traceset_seek_time(self, ltt_time_zero);
33f7a12c 235 lttv_traceset_context_compute_time_span(self, &self->time_span);
8697a616 236
dc877563 237}
238
239
240void fini(LttvTracesetContext *self)
241{
dbb7bb09 242 guint i, j, nb_trace, nb_tracefile;
dc877563 243
244 LttvTraceContext *tc;
245
1986f254 246 LttvTracefileContext **tfc;
dc877563 247
ffd54a90 248 LttvTraceset *ts = self->ts;
dc877563 249
8697a616 250 g_tree_destroy(self->pqueue);
2061e03d 251 g_object_unref(self->a);
dc877563 252
253 nb_trace = lttv_traceset_number(ts);
254
255 for(i = 0 ; i < nb_trace ; i++) {
256 tc = self->traces[i];
257
ffd54a90 258 g_object_unref(tc->a);
dc877563 259
eed2ef37 260 nb_tracefile = tc->tracefiles->len;
dc877563 261
262 for(j = 0 ; j < nb_tracefile ; j++) {
1986f254 263 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext*, j);
264 lttv_hooks_destroy((*tfc)->event);
265 lttv_hooks_by_id_destroy((*tfc)->event_by_id);
266 g_object_unref((*tfc)->a);
267 g_object_unref(*tfc);
dc877563 268 }
eed2ef37 269 g_array_free(tc->tracefiles, TRUE);
dc877563 270 g_object_unref(tc);
271 }
272 g_free(self->traces);
273}
274
275
276void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
8697a616 277 LttvHooks *before_traceset,
dc877563 278 LttvHooks *before_trace,
ffd54a90 279 LttvHooks *before_tracefile,
8697a616 280 LttvHooks *event,
281 LttvHooksById *event_by_id)
dc877563 282{
283 LttvTraceset *ts = self->ts;
284
8697a616 285 guint i, nb_trace;
dc877563 286
287 LttvTraceContext *tc;
288
8697a616 289 lttv_hooks_call(before_traceset, self);
dc877563 290
dc877563 291 nb_trace = lttv_traceset_number(ts);
292
293 for(i = 0 ; i < nb_trace ; i++) {
294 tc = self->traces[i];
8697a616 295 lttv_trace_context_add_hooks(tc,
296 before_trace,
297 before_tracefile,
298 event,
299 event_by_id);
dc877563 300 }
301}
302
303
304void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
dc877563 305 LttvHooks *after_traceset,
dc877563 306 LttvHooks *after_trace,
ffd54a90 307 LttvHooks *after_tracefile,
8697a616 308 LttvHooks *event,
309 LttvHooksById *event_by_id)
dc877563 310{
8697a616 311
dc877563 312 LttvTraceset *ts = self->ts;
313
8697a616 314 guint i, nb_trace;
dc877563 315
316 LttvTraceContext *tc;
317
dc877563 318 nb_trace = lttv_traceset_number(ts);
319
320 for(i = 0 ; i < nb_trace ; i++) {
321 tc = self->traces[i];
8697a616 322 lttv_trace_context_remove_hooks(tc,
323 after_trace,
324 after_tracefile,
325 event,
326 event_by_id);
dc877563 327 }
8697a616 328
329 lttv_hooks_call(after_traceset, self);
330
331
dc877563 332}
333
8697a616 334void lttv_trace_context_add_hooks(LttvTraceContext *self,
335 LttvHooks *before_trace,
336 LttvHooks *before_tracefile,
337 LttvHooks *event,
338 LttvHooksById *event_by_id)
a8c0f09d 339{
8697a616 340 guint i, nb_tracefile;
341
1986f254 342 LttvTracefileContext **tfc;
8697a616 343
344 lttv_hooks_call(before_trace, self);
eed2ef37 345
346 nb_tracefile = self->tracefiles->len;
8697a616 347
348 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 349 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
350 lttv_tracefile_context_add_hooks(*tfc,
8697a616 351 before_tracefile,
352 event,
353 event_by_id);
354 }
a8c0f09d 355}
356
8697a616 357
358
359void lttv_trace_context_remove_hooks(LttvTraceContext *self,
360 LttvHooks *after_trace,
361 LttvHooks *after_tracefile,
362 LttvHooks *event,
363 LttvHooksById *event_by_id)
a8c0f09d 364{
8697a616 365 guint i, nb_tracefile;
366
1986f254 367 LttvTracefileContext **tfc;
8697a616 368
eed2ef37 369 nb_tracefile = self->tracefiles->len;
8697a616 370
371 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 372 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
373 lttv_tracefile_context_remove_hooks(*tfc,
8697a616 374 after_tracefile,
375 event,
376 event_by_id);
377 }
378
379 lttv_hooks_call(after_trace, self);
a8c0f09d 380}
381
8697a616 382void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
383 LttvHooks *before_tracefile,
384 LttvHooks *event,
385 LttvHooksById *event_by_id)
a8c0f09d 386{
9d239bd9 387 guint i, index;
8697a616 388
389 LttvHooks *hook;
390
391 lttv_hooks_call(before_tracefile, self);
392 lttv_hooks_add_list(self->event, event);
9d239bd9 393 if(event_by_id != NULL) {
394 for(i = 0; i < event_by_id->array->len; i++) {
395 index = g_array_index(event_by_id->array, guint, i);
396 hook = lttv_hooks_by_id_find(self->event_by_id, index);
397 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 398 }
9d239bd9 399 }
a8c0f09d 400}
401
8697a616 402void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
403 LttvHooks *after_tracefile,
404 LttvHooks *event,
405 LttvHooksById *event_by_id)
a8c0f09d 406{
9d239bd9 407 guint i, index;
8697a616 408
409 LttvHooks *hook;
410
8697a616 411 lttv_hooks_remove_list(self->event, event);
9d239bd9 412 if(event_by_id != NULL) {
413 for(i = 0; i < event_by_id->array->len; i++) {
414 index = g_array_index(event_by_id->array, guint, i);
415 hook = lttv_hooks_by_id_get(self->event_by_id, index);
41a9e0c3 416 if(hook != NULL)
9d239bd9 417 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 418 }
9d239bd9 419 }
8697a616 420
421 lttv_hooks_call(after_tracefile, self);
a8c0f09d 422}
423
8697a616 424
425
a8c0f09d 426void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
427 unsigned i,
8697a616 428 LttvHooks *event_by_id)
a8c0f09d 429{
430 LttvHooks * h;
8697a616 431 h = lttv_hooks_by_id_find(tfc->event_by_id, i);
432 lttv_hooks_add_list(h, event_by_id);
a8c0f09d 433}
434
435void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
436 unsigned i)
437{
8697a616 438 lttv_hooks_by_id_remove(tfc->event_by_id, i);
a8c0f09d 439}
dc877563 440
ba576a78 441static LttvTracesetContext *
dc877563 442new_traceset_context(LttvTracesetContext *self)
443{
ffd54a90 444 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
dc877563 445}
446
447
ba576a78 448static LttvTraceContext *
dc877563 449new_trace_context(LttvTracesetContext *self)
450{
ffd54a90 451 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
dc877563 452}
453
454
ba576a78 455static LttvTracefileContext *
dc877563 456new_tracefile_context(LttvTracesetContext *self)
457{
ffd54a90 458 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
dc877563 459}
460
461
462static void
463traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
464{
465 /* Be careful of anything which would not work well with shallow copies */
466}
467
468
469static void
470traceset_context_finalize (LttvTracesetContext *self)
471{
b445142a 472 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
473 ->finalize(G_OBJECT(self));
dc877563 474}
475
476
477static void
478traceset_context_class_init (LttvTracesetContextClass *klass)
479{
480 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
481
ffd54a90 482 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
dc877563 483 klass->init = init;
484 klass->fini = fini;
485 klass->new_traceset_context = new_traceset_context;
486 klass->new_trace_context = new_trace_context;
487 klass->new_tracefile_context = new_tracefile_context;
488}
489
490
491GType
ffd54a90 492lttv_traceset_context_get_type(void)
dc877563 493{
494 static GType type = 0;
495 if (type == 0) {
496 static const GTypeInfo info = {
ffd54a90 497 sizeof (LttvTracesetContextClass),
dc877563 498 NULL, /* base_init */
499 NULL, /* base_finalize */
ffd54a90 500 (GClassInitFunc) traceset_context_class_init, /* class_init */
dc877563 501 NULL, /* class_finalize */
502 NULL, /* class_data */
ffd54a90 503 sizeof (LttvTracesetContext),
dc877563 504 0, /* n_preallocs */
00e74b69 505 (GInstanceInitFunc) traceset_context_instance_init, /* instance_init */
506 NULL /* Value handling */
dc877563 507 };
508
ffd54a90 509 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
dc877563 510 &info, 0);
511 }
512 return type;
513}
514
515
516static void
517trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
518{
519 /* Be careful of anything which would not work well with shallow copies */
520}
521
522
523static void
524trace_context_finalize (LttvTraceContext *self)
525{
b445142a 526 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
527 finalize(G_OBJECT(self));
dc877563 528}
529
530
531static void
532trace_context_class_init (LttvTraceContextClass *klass)
533{
534 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
535
ffd54a90 536 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
dc877563 537}
538
539
540GType
ffd54a90 541lttv_trace_context_get_type(void)
dc877563 542{
543 static GType type = 0;
544 if (type == 0) {
545 static const GTypeInfo info = {
ffd54a90 546 sizeof (LttvTraceContextClass),
dc877563 547 NULL, /* base_init */
548 NULL, /* base_finalize */
ffd54a90 549 (GClassInitFunc) trace_context_class_init, /* class_init */
dc877563 550 NULL, /* class_finalize */
551 NULL, /* class_data */
c6bc9cb9 552 sizeof (LttvTraceContext),
dc877563 553 0, /* n_preallocs */
00e74b69 554 (GInstanceInitFunc) trace_context_instance_init, /* instance_init */
555 NULL /* Value handling */
dc877563 556 };
557
ffd54a90 558 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
dc877563 559 &info, 0);
560 }
561 return type;
562}
563
564
565static void
566tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
567{
568 /* Be careful of anything which would not work well with shallow copies */
569}
570
571
572static void
573tracefile_context_finalize (LttvTracefileContext *self)
574{
b445142a 575 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
576 ->finalize(G_OBJECT(self));
dc877563 577}
578
579
580static void
581tracefile_context_class_init (LttvTracefileContextClass *klass)
582{
583 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
584
ffd54a90 585 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
586}
587
588
589GType
590lttv_tracefile_context_get_type(void)
591{
592 static GType type = 0;
593 if (type == 0) {
594 static const GTypeInfo info = {
595 sizeof (LttvTracefileContextClass),
596 NULL, /* base_init */
597 NULL, /* base_finalize */
598 (GClassInitFunc) tracefile_context_class_init, /* class_init */
599 NULL, /* class_finalize */
600 NULL, /* class_data */
601 sizeof (LttvTracefileContext),
602 0, /* n_preallocs */
00e74b69 603 (GInstanceInitFunc) tracefile_context_instance_init, /* instance_init */
604 NULL /* Value handling */
ffd54a90 605 };
606
607 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
608 &info, 0);
609 }
610 return type;
dc877563 611}
612
613
dc877563 614
6843100a 615static gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
77199e93 616 g_assert(key == value);
dc877563 617 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
618 return TRUE;
619}
620
698e81c2 621static gboolean test_tree(gpointer key, gpointer value, gpointer user_data) {
622
77199e93 623 LttvTracefileContext *tfc = (LttvTracefileContext *)key;
624
625 g_debug("Tracefile name %s, time %lu.%lu, tfi %u, ti %u",
626 g_quark_to_string(ltt_tracefile_name(tfc->tf)),
627 tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec,
628 tfc->index, tfc->t_context->index);
629
630 if(((LttvTracefileContext *)user_data) == (LttvTracefileContext *)value) {
631 g_assert(compare_tracefile(user_data, value) == 0);
632 } else
633 g_assert(compare_tracefile(user_data, value) != 0);
634
635 //g_assert(((LttvTracefileContext *)user_data) != (LttvTracefileContext *)value);
698e81c2 636 return FALSE;
637}
638
639
dc877563 640
8697a616 641void lttv_process_traceset_begin(LttvTracesetContext *self,
642 LttvHooks *before_traceset,
643 LttvHooks *before_trace,
644 LttvHooks *before_tracefile,
645 LttvHooks *event,
646 LttvHooksById *event_by_id)
647{
dc877563 648
8697a616 649 /* simply add hooks in context. _before hooks are called by add_hooks. */
650 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
651 lttv_traceset_context_add_hooks(self,
652 before_traceset,
653 before_trace,
654 before_tracefile,
655 event,
656 event_by_id);
657
2a2fa4f0 658}
659
8697a616 660/* Note : a _middle must be preceded from a _seek or another middle */
661guint lttv_process_traceset_middle(LttvTracesetContext *self,
662 LttTime end,
b8eccacd 663 guint nb_events,
8697a616 664 const LttvTracesetContextPosition *end_position)
2a2fa4f0 665{
666 GTree *pqueue = self->pqueue;
667
698e81c2 668 guint fac_id, ev_id, id;
2a2fa4f0 669
2a2fa4f0 670 LttvTracefileContext *tfc;
671
eed2ef37 672 LttEvent *e;
673
2a2fa4f0 674 unsigned count = 0;
675
698e81c2 676 guint read_ret = FALSE;
677
a54f091a 678 gboolean last_ret = FALSE; /* return value of the last hook list called */
679
dc877563 680 /* Get the next event from the pqueue, call its hooks,
681 reinsert in the pqueue the following event from the same tracefile
682 unless the tracefile is finished or the event is later than the
8697a616 683 end time. */
dc877563 684
ffd54a90 685 while(TRUE) {
dc877563 686 tfc = NULL;
687 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 688 /* End of traceset : tfc is NULL */
1d1df11d 689 if(unlikely(tfc == NULL))
a43d67ba 690 {
a43d67ba 691 return count;
692 }
dc877563 693
8697a616 694 /* Have we reached :
695 * - the maximum number of events specified?
696 * - the end position ?
697 * - the end time ?
698 * then the read is finished. We leave the queue in the same state and
699 * break the loop.
700 */
701
1d1df11d 702 if(unlikely(last_ret == TRUE ||
d052ffc3 703 ((count >= nb_events) && (nb_events != G_MAXULONG)) ||
8b0bbe19 704 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
705 end_position) == 0)||
1d1df11d 706 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 707 {
a43d67ba 708 return count;
709 }
2a2fa4f0 710
308711e5 711 /* Get the tracefile with an event for the smallest time found. If two
712 or more tracefiles have events for the same time, hope that lookup
713 and remove are consistent. */
1986f254 714
715#ifdef DEBUG
77199e93 716 g_debug("test tree before remove");
717 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 718#endif //DEBUG
f95bc830 719 g_tree_remove(pqueue, tfc);
698e81c2 720
1986f254 721#ifdef DEBUG
77199e93 722 g_debug("test tree after remove");
698e81c2 723 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 724#endif //DEBUG
77199e93 725
2a2fa4f0 726 count++;
eed2ef37 727
728 e = ltt_tracefile_get_event(tfc->tf);
698e81c2 729 fac_id = ltt_event_facility_id(e);
730 ev_id = ltt_event_eventtype_id(e);
731 id = GET_HOOK_ID(fac_id, ev_id);
a54f091a 732 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
8697a616 733 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
dc877563 734
698e81c2 735 read_ret = ltt_tracefile_read(tfc->tf);
736
737 if(likely(!read_ret)) {
77199e93 738 g_debug("An event is ready");
eed2ef37 739 tfc->timestamp = ltt_event_time(e);
77199e93 740
33f7a12c 741 g_tree_insert(pqueue, tfc, tfc);
698e81c2 742 } else {
1986f254 743 tfc->timestamp = ltt_time_infinite;
744
698e81c2 745 if(read_ret == ERANGE)
746 g_debug("End of trace");
747 else
748 g_error("Error happened in lttv_process_traceset_middle");
dc877563 749 }
750 }
2a2fa4f0 751}
752
753
8697a616 754void lttv_process_traceset_end(LttvTracesetContext *self,
755 LttvHooks *after_traceset,
756 LttvHooks *after_trace,
757 LttvHooks *after_tracefile,
758 LttvHooks *event,
759 LttvHooksById *event_by_id)
2a2fa4f0 760{
8697a616 761 /* Remove hooks from context. _after hooks are called by remove_hooks. */
762 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
763 lttv_traceset_context_remove_hooks(self,
764 after_traceset,
765 after_trace,
766 after_tracefile,
767 event,
768 event_by_id);
769}
2a2fa4f0 770
27304273 771/* Subtile modification :
772 * if tracefile has no event at or after the time requested, it is not put in
773 * the queue, as the next read would fail. */
8697a616 774void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
775{
776 guint i, nb_tracefile;
2a2fa4f0 777
eed2ef37 778 gint ret;
779
1986f254 780 LttvTracefileContext **tfc;
2a2fa4f0 781
a5ba1787 782 GTree *pqueue = self->ts_context->pqueue;
783
eed2ef37 784 nb_tracefile = self->tracefiles->len;
dc877563 785
8697a616 786 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 787 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
77199e93 788
1986f254 789 g_tree_remove(pqueue, *tfc);
77199e93 790
1986f254 791 ret = ltt_tracefile_seek_time((*tfc)->tf, start);
27304273 792 if(ret == EPERM) g_error("error in lttv_process_trace_seek_time seek");
27304273 793
794 if(ret == 0) { /* not ERANGE especially */
1986f254 795 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
796 g_tree_insert(pqueue, (*tfc), (*tfc));
797 } else {
798 (*tfc)->timestamp = ltt_time_infinite;
27304273 799 }
8697a616 800 }
801}
dc877563 802
2a2fa4f0 803
8697a616 804void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
805{
806 guint i, nb_trace;
2a2fa4f0 807
8697a616 808 LttvTraceContext *tc;
2a2fa4f0 809
8697a616 810 nb_trace = lttv_traceset_number(self->ts);
811 for(i = 0 ; i < nb_trace ; i++) {
812 tc = self->traces[i];
813 lttv_process_trace_seek_time(tc, start);
814 }
dc877563 815}
b445142a 816
308711e5 817
8697a616 818gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
819 const LttvTracesetContextPosition *pos)
308711e5 820{
27304273 821 guint i;
308711e5 822
27304273 823 g_tree_destroy(self->pqueue);
824 self->pqueue = g_tree_new(compare_tracefile);
8697a616 825
27304273 826 for(i=0;i<pos->ep->len; i++) {
1986f254 827 LttEventPosition **ep = &g_array_index(pos->ep, LttEventPosition*, i);
828 LttvTracefileContext **tfc =
829 &g_array_index(pos->tfc, LttvTracefileContext*, i);
830 if(*ep != NULL) {
831 g_assert(ltt_tracefile_seek_position((*tfc)->tf, *ep) == 0);
832 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
833 g_tree_insert(self->pqueue, (*tfc), (*tfc));
834 } else {
835 (*tfc)->timestamp = ltt_time_infinite;
836 }
308711e5 837 }
27304273 838 return TRUE;
308711e5 839}
840
841
8697a616 842
b445142a 843static LttField *
eed2ef37 844find_field(LttEventType *et, const GQuark field)
b445142a 845{
846 LttType *t;
847
848 LttField *f;
849
850 guint i, nb;
851
eed2ef37 852 GQuark name;
b445142a 853
eed2ef37 854 /* Field is unset */
855 if(field == 0) return NULL;
856
b445142a 857 f = ltt_eventtype_field(et);
858 t = ltt_eventtype_type(et);
859 g_assert(ltt_type_class(t) == LTT_STRUCT);
860 nb = ltt_type_member_number(t);
861 for(i = 0 ; i < nb ; i++) {
862 ltt_type_member_type(t, i, &name);
eed2ef37 863 if(name == field) break;
b445142a 864 }
865 g_assert(i < nb);
866 return ltt_field_member(f, i);
867}
868
eed2ef37 869LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
870 guint facility_id)
871{
872 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
873}
874
875/* Get the first facility corresponding to the name. As the types must be
876 * compatible, it is relevant to use the field name and sizes of the first
877 * facility to create data structures and assume the data will be compatible
878 * thorough the trace */
879LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
880{
881 g_assert(th->fac_list->len > 0);
882 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
883}
884
b445142a 885
eed2ef37 886/* Returns 0 on success, -1 if fails. */
887gint
888lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
889 GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th)
b445142a 890{
891 LttFacility *f;
892
eed2ef37 893 LttEventType *et, *first_et;
894
895 GArray *facilities;
896
d052ffc3 897 guint i, fac_id, ev_id;
b445142a 898
eed2ef37 899 LttvTraceHookByFacility *thf, *first_thf;
b445142a 900
eed2ef37 901 facilities = ltt_trace_facility_get_by_name(t, facility);
021eeb41 902
eed2ef37 903 if(unlikely(facilities == NULL)) goto facility_error;
904
905 th->fac_index = g_array_sized_new(FALSE, TRUE,
906 sizeof(LttvTraceHookByFacility),
907 NUM_FACILITIES);
908 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
b445142a 909
eed2ef37 910 th->fac_list = g_array_sized_new(FALSE, TRUE,
911 sizeof(LttvTraceHookByFacility*),
912 facilities->len);
913 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
914
915 fac_id = g_array_index(facilities, guint, 0);
916 f = ltt_trace_get_facility_by_num(t, fac_id);
917
cb03932a 918 et = ltt_facility_eventtype_get_by_name(f, event);
eed2ef37 919 if(unlikely(et == NULL)) goto event_error;
920
921 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 922 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0) = thf;
9d239bd9 923
d052ffc3 924 ev_id = ltt_eventtype_id(et);
925
eed2ef37 926 thf->h = h;
d052ffc3 927 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 928 thf->f1 = find_field(et, field1);
929 thf->f2 = find_field(et, field2);
930 thf->f3 = find_field(et, field3);
931
932 first_thf = thf;
826f1ab2 933 first_et = et;
eed2ef37 934
935 /* Check for type compatibility too */
936 for(i=1;i<facilities->len;i++) {
937 fac_id = g_array_index(facilities, guint, i);
938 f = ltt_trace_get_facility_by_num(t, fac_id);
939
940 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
941 if(unlikely(et == NULL)) goto event_error;
942
943 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 944 g_array_index(th->fac_list, LttvTraceHookByFacility*, i) = thf;
d052ffc3 945 ev_id = ltt_eventtype_id(et);
eed2ef37 946 thf->h = h;
d052ffc3 947 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 948 thf->f1 = find_field(et, field1);
949 if(check_fields_compatibility(first_et, et,
950 first_thf->f1, thf->f1))
951 goto type_error;
952
953 thf->f2 = find_field(et, field2);
954 if(check_fields_compatibility(first_et, et,
955 first_thf->f2, thf->f2))
956 goto type_error;
957
958 thf->f3 = find_field(et, field3);
959 if(check_fields_compatibility(first_et, et,
960 first_thf->f3, thf->f3))
961 goto type_error;
962 }
963
964 return 0;
965
966type_error:
967 goto free;
968event_error:
969 g_error("Event type %s does not exist",
970 g_quark_to_string(ltt_eventtype_name(et)));
971 goto free;
972facility_error:
973 g_error("No %s facility", g_quark_to_string(facility));
974 goto free;
975free:
976 g_array_free(th->fac_index, TRUE);
977 g_array_free(th->fac_list, TRUE);
978 th->fac_index = NULL;
979 th->fac_list = NULL;
980 return -1;
981}
982
983void lttv_trace_hook_destroy(LttvTraceHook *th)
984{
985 g_array_free(th->fac_index, TRUE);
986 g_array_free(th->fac_list, TRUE);
b445142a 987}
988
989
8b0bbe19 990LttvTracesetContextPosition *lttv_traceset_context_position_new()
5e2c04a2 991{
27304273 992 LttvTracesetContextPosition *pos = g_new(LttvTracesetContextPosition,1);
993 pos->ep = g_array_sized_new(FALSE, TRUE, sizeof(LttEventPosition*),
994 10);
995 pos->tfc = g_array_sized_new(FALSE, TRUE, sizeof(LttvTracefileContext*),
996 10);
997 pos->timestamp = ltt_time_infinite;
998 return pos;
5e2c04a2 999}
1000
1986f254 1001/* Save all positions, the ones not in the pqueue will have NULL
1002 * ep. */
27304273 1003void lttv_traceset_context_position_save(const LttvTracesetContext *self,
1004 LttvTracesetContextPosition *pos)
1005{
1986f254 1006 guint i;
1007 guint num_traces = lttv_traceset_number(self->ts);
1008
1009 for(i=0; i<num_traces;i++) {
1010 GArray * tracefiles = self->traces[i]->tracefiles;
1011 guint j;
1012 guint num_tracefiles = tracefiles->len;
1013
1014 for(j=0;j<num_tracefiles;j++) {
1015 LttvTracefileContext **tfc = &g_array_index(tracefiles,
1016 LttvTracefileContext*, j);
1017
1018 LttEvent *event = ltt_tracefile_get_event((*tfc)->tf);
1019 LttEventPosition *ep;
1020
1021 if(ltt_time_compare((*tfc)->timestamp, ltt_time_infinite) != 0) {
1022 ep = ltt_event_position_new();
1023 ltt_event_position(event, ep);
1024 if(ltt_time_compare((*tfc)->timestamp, pos->timestamp) < 0)
1025 pos->timestamp = (*tfc)->timestamp;
1026 } else {
1027 ep = NULL;
1028 }
1029 g_array_append_val(pos->tfc, *tfc);
1030 g_array_append_val(pos->ep, ep);
1031 }
1032
1033 }
8697a616 1034}
1035
1036void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1037{
27304273 1038 int i;
1986f254 1039 LttEventPosition **ep;
1040
1041 for(i=0;i<pos->ep->len;i++) {
1042 ep = &g_array_index(pos->ep, LttEventPosition*, i);
1043 if(*ep != NULL)
1044 g_free(*ep);
1045 }
27304273 1046 g_array_free(pos->ep, TRUE);
1047 g_array_free(pos->tfc, TRUE);
1048 g_free(pos);
8697a616 1049}
1050
5e2c04a2 1051void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1052 const LttvTracesetContextPosition *src)
1053{
27304273 1054 int i;
1986f254 1055 LttEventPosition **src_ep, **dest_ep;
5e2c04a2 1056
27304273 1057 g_array_set_size(dest->ep, src->ep->len);
1058 g_array_set_size(dest->tfc, src->tfc->len);
1059
1060 for(i=0;i<src->ep->len;i++) {
1986f254 1061 src_ep = &g_array_index(src->ep, LttEventPosition*, i);
1062 dest_ep = &g_array_index(dest->ep, LttEventPosition*, i);
1063 if(*src_ep != NULL) {
1064 *dest_ep = ltt_event_position_new();
1065 ltt_event_position_copy(
1066 *dest_ep,
1067 *src_ep);
1068 } else
1069 *dest_ep = NULL;
27304273 1070 }
1071 for(i=0;i<src->tfc->len;i++) {
1072 g_array_index(dest->tfc, LttvTracefileContext*, i) =
1073 g_array_index(src->tfc, LttvTracefileContext*, i);
5e2c04a2 1074 }
5e2c04a2 1075 dest->timestamp = src->timestamp;
1076}
1077
8697a616 1078gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1079 const LttvTracesetContextPosition *pos)
1080{
27304273 1081 int i;
826f1ab2 1082 int ret = 0;
8697a616 1083
27304273 1084 for(i=0;i<pos->ep->len;i++) {
1085 LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
1086 LttvTracefileContext *tfc =
1087 g_array_index(pos->tfc, LttvTracefileContext*, i);
1986f254 1088
1089 if(ep == NULL) {
1090 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0) {
1091 ret = -1;
1092 }
1093 } else {
1094 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) == 0) {
1095 ret = 1;
1096 } else {
1097 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
8697a616 1098
1986f254 1099 ret = ltt_event_position_compare((LttEventPosition*)event,
1100 ep);
1101 }
1102 }
27304273 1103 if(ret != 0) return ret;
8697a616 1104
8697a616 1105 }
1106 return 0;
1107}
1108
1109
1110gint lttv_traceset_context_pos_pos_compare(
1111 const LttvTracesetContextPosition *pos1,
1112 const LttvTracesetContextPosition *pos2)
1113{
27304273 1114 int i, j;
1115 int ret;
8697a616 1116
27304273 1117 for(i=0;i<pos1->ep->len;i++) {
1118 LttEventPosition *ep1 = g_array_index(pos1->ep, LttEventPosition*, i);
1986f254 1119 LttvTracefileContext *tfc1 = g_array_index(pos1->tfc,
1120 LttvTracefileContext*, i);
27304273 1121
1986f254 1122 if(ep1 != NULL) {
1123 for(j=0;j<pos2->ep->len;j++) {
1124 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1125 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1126 LttvTracefileContext*, j);
1127 if(tfc1 == tfc2) {
1128 if(ep2 != NULL)
1129 ret = ltt_event_position_compare(ep1, ep2);
1130 else
1131 ret = -1;
1132
1133 if(ret != 0) return ret;
1134 }
1135 }
1136 } else {
1137 for(j=0;j<pos2->ep->len;j++) {
1138 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1139 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1140 LttvTracefileContext*, j);
1141 if(tfc1 == tfc2) {
1142 if(ep2 != NULL) ret = 1;
1143 }
27304273 1144 }
8697a616 1145 }
1146 }
1147 return 0;
1148}
1149
1150
2d262115 1151LttTime lttv_traceset_context_position_get_time(
1152 const LttvTracesetContextPosition *pos)
1153{
1154 return pos->timestamp;
1155}
1156
1157
1158LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1159{
1160 GTree *pqueue = self->pqueue;
b56b5fec 1161 LttvTracefileContext *tfc = NULL;
2d262115 1162
1163 g_tree_foreach(pqueue, get_first, &tfc);
1164
1165 return tfc;
1166}
This page took 0.091978 seconds and 4 git commands to generate.