lttv and lib ltt new compiles
[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>
dc877563 29
8697a616 30
31
32
1d1df11d 33static gint compare_tracefile(gconstpointer a, gconstpointer b)
8697a616 34{
cf94ff67 35 gint comparison = 0;
8697a616 36
00e74b69 37 const LttvTracefileContext *trace_a = (const LttvTracefileContext *)a;
00e74b69 38 const LttvTracefileContext *trace_b = (const LttvTracefileContext *)b;
8697a616 39
1d1df11d 40 if(likely(trace_a != trace_b)) {
a855f059 41 comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
1d1df11d 42 if(unlikely(comparison == 0)) {
a855f059 43 if(trace_a->index < trace_b->index) comparison = -1;
44 else if(trace_a->index > trace_b->index) comparison = 1;
45 else if(trace_a->t_context->index < trace_b->t_context->index)
46 comparison = -1;
47 else if(trace_a->t_context->index > trace_b->t_context->index)
48 comparison = 1;
49 }
cf94ff67 50 }
cf94ff67 51 return comparison;
8697a616 52}
53
54struct _LttvTraceContextPosition {
2d262115 55 LttEventPosition **tf_pos; /* Position in each tracefile */
8697a616 56 guint nb_tracefile; /* Number of tracefiles (check) */
57};
58
59struct _LttvTracesetContextPosition {
2d262115 60 LttvTraceContextPosition *t_pos; /* Position in each trace */
8697a616 61 guint nb_trace; /* Number of traces (check) */
2d262115 62 LttTime timestamp; /* Current time at the saved position */
8697a616 63};
64
ffd54a90 65void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
dc877563 66{
ffd54a90 67 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
dc877563 68}
69
70
71void lttv_context_fini(LttvTracesetContext *self)
72{
73 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
74}
75
76
77LttvTracesetContext *
78lttv_context_new_traceset_context(LttvTracesetContext *self)
79{
80 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
81}
82
83
84
85
86LttvTraceContext *
87lttv_context_new_trace_context(LttvTracesetContext *self)
88{
89 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
90}
91
92
93LttvTracefileContext *
94lttv_context_new_tracefile_context(LttvTracesetContext *self)
95{
c6bc9cb9 96 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dc877563 97}
98
f7afe191 99/****************************************************************************
100 * lttv_traceset_context_compute_time_span
101 *
8697a616 102 * Keep the time span is sync with on the fly addition and removal of traces
f7afe191 103 * in a trace set. It must be called each time a trace is added/removed from
104 * the traceset. It could be more efficient to call it only once a bunch
105 * of traces are loaded, but the calculation is not long, so it's not
106 * critical.
107 *
108 * Author : Xang Xiu Yang
f7afe191 109 ***************************************************************************/
110static void lttv_traceset_context_compute_time_span(
111 LttvTracesetContext *self,
33f7a12c 112 TimeInterval *time_span)
f7afe191 113{
114 LttvTraceset * traceset = self->ts;
115 int numTraces = lttv_traceset_number(traceset);
116 int i;
117 LttTime s, e;
118 LttvTraceContext *tc;
119 LttTrace * trace;
120
33f7a12c 121 time_span->start_time.tv_sec = 0;
122 time_span->start_time.tv_nsec = 0;
123 time_span->end_time.tv_sec = 0;
124 time_span->end_time.tv_nsec = 0;
912be9a5 125
f7afe191 126 for(i=0; i<numTraces;i++){
127 tc = self->traces[i];
128 trace = tc->t;
129
130 ltt_trace_time_span_get(trace, &s, &e);
131
132 if(i==0){
33f7a12c 133 time_span->start_time = s;
134 time_span->end_time = e;
f7afe191 135 }else{
33f7a12c 136 if(s.tv_sec < time_span->start_time.tv_sec
137 || (s.tv_sec == time_span->start_time.tv_sec
138 && s.tv_nsec < time_span->start_time.tv_nsec))
139 time_span->start_time = s;
140 if(e.tv_sec > time_span->end_time.tv_sec
141 || (e.tv_sec == time_span->end_time.tv_sec
142 && e.tv_nsec > time_span->end_time.tv_nsec))
143 time_span->end_time = e;
f7afe191 144 }
145 }
146}
147
eed2ef37 148static void init_tracefile_context(LttTracefile *tracefile,
149 LttvTraceContext *tc)
150{
151 LttvTracefileContext *tfc;
152 LttvTracesetContext *tsc = tc->ts_context;
153
154 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->new_tracefile_context(tsc);
155
156 tfc->index = tc->tracefiles->len;
157 tc->tracefiles = g_array_append_val(tc->tracefiles, tfc);
158
159 tfc->tf = tracefile;
160
161 tfc->t_context = tc;
162 tfc->event = lttv_hooks_new();
163 tfc->event_by_id = lttv_hooks_by_id_new();
164 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
165}
166
dc877563 167
168static void
169init(LttvTracesetContext *self, LttvTraceset *ts)
170{
171 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
172
173 LttvTraceContext *tc;
174
eed2ef37 175 GData *tracefiles_groups;
dc877563 176
eed2ef37 177 struct compute_tracefile_group_args args;
308711e5 178
dc877563 179 nb_trace = lttv_traceset_number(ts);
180 self->ts = ts;
ffd54a90 181 self->traces = g_new(LttvTraceContext *, nb_trace);
ffd54a90 182 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 183 self->ts_a = lttv_traceset_attribute(ts);
dc877563 184 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 185 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
dc877563 186 self->traces[i] = tc;
187
188 tc->ts_context = self;
189 tc->index = i;
308711e5 190 tc->vt = lttv_traceset_get(ts, i);
191 tc->t = lttv_trace(tc->vt);
ffd54a90 192 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 193 tc->t_a = lttv_trace_attribute(tc->vt);
eed2ef37 194
195 tracefiles_groups = ltt_trace_get_tracefiles_groups(tc->t);
196
197 args.func = (ForEachTraceFileFunc)init_tracefile_context;
198 args.func_args = tc;
199
200 g_datalist_foreach(&tracefiles_groups,
201 (GDataForeachFunc)compute_tracefile_group,
202 &args);
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
246 LttvTracefileContext *tfc;
247
ffd54a90 248 LttvTraceset *ts = self->ts;
dc877563 249
f7afe191 250 //FIXME : segfault
8697a616 251
252 g_tree_destroy(self->pqueue);
2061e03d 253 g_object_unref(self->a);
dc877563 254
255 nb_trace = lttv_traceset_number(ts);
256
257 for(i = 0 ; i < nb_trace ; i++) {
258 tc = self->traces[i];
259
ffd54a90 260 g_object_unref(tc->a);
dc877563 261
eed2ef37 262 nb_tracefile = tc->tracefiles->len;
dc877563 263
264 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 265 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, j);
8697a616 266 lttv_hooks_destroy(tfc->event);
267 lttv_hooks_by_id_destroy(tfc->event_by_id);
ffd54a90 268 g_object_unref(tfc->a);
dc877563 269 g_object_unref(tfc);
270 }
eed2ef37 271 g_array_free(tc->tracefiles, TRUE);
dc877563 272 g_object_unref(tc);
273 }
274 g_free(self->traces);
275}
276
277
278void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
8697a616 279 LttvHooks *before_traceset,
dc877563 280 LttvHooks *before_trace,
ffd54a90 281 LttvHooks *before_tracefile,
8697a616 282 LttvHooks *event,
283 LttvHooksById *event_by_id)
dc877563 284{
285 LttvTraceset *ts = self->ts;
286
8697a616 287 guint i, nb_trace;
dc877563 288
289 LttvTraceContext *tc;
290
8697a616 291 lttv_hooks_call(before_traceset, self);
dc877563 292
dc877563 293 nb_trace = lttv_traceset_number(ts);
294
295 for(i = 0 ; i < nb_trace ; i++) {
296 tc = self->traces[i];
8697a616 297 lttv_trace_context_add_hooks(tc,
298 before_trace,
299 before_tracefile,
300 event,
301 event_by_id);
dc877563 302 }
303}
304
305
306void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
dc877563 307 LttvHooks *after_traceset,
dc877563 308 LttvHooks *after_trace,
ffd54a90 309 LttvHooks *after_tracefile,
8697a616 310 LttvHooks *event,
311 LttvHooksById *event_by_id)
dc877563 312{
8697a616 313
dc877563 314 LttvTraceset *ts = self->ts;
315
8697a616 316 guint i, nb_trace;
dc877563 317
318 LttvTraceContext *tc;
319
dc877563 320 nb_trace = lttv_traceset_number(ts);
321
322 for(i = 0 ; i < nb_trace ; i++) {
323 tc = self->traces[i];
8697a616 324 lttv_trace_context_remove_hooks(tc,
325 after_trace,
326 after_tracefile,
327 event,
328 event_by_id);
dc877563 329 }
8697a616 330
331 lttv_hooks_call(after_traceset, self);
332
333
dc877563 334}
335
8697a616 336void lttv_trace_context_add_hooks(LttvTraceContext *self,
337 LttvHooks *before_trace,
338 LttvHooks *before_tracefile,
339 LttvHooks *event,
340 LttvHooksById *event_by_id)
a8c0f09d 341{
8697a616 342 guint i, nb_tracefile;
343
344 LttvTracefileContext *tfc;
345
346 lttv_hooks_call(before_trace, self);
eed2ef37 347
348 nb_tracefile = self->tracefiles->len;
8697a616 349
350 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 351 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
8697a616 352 lttv_tracefile_context_add_hooks(tfc,
353 before_tracefile,
354 event,
355 event_by_id);
356 }
a8c0f09d 357}
358
8697a616 359
360
361void lttv_trace_context_remove_hooks(LttvTraceContext *self,
362 LttvHooks *after_trace,
363 LttvHooks *after_tracefile,
364 LttvHooks *event,
365 LttvHooksById *event_by_id)
a8c0f09d 366{
8697a616 367 guint i, nb_tracefile;
368
369 LttvTracefileContext *tfc;
370
eed2ef37 371 nb_tracefile = self->tracefiles->len;
8697a616 372
373 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 374 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
8697a616 375 lttv_tracefile_context_remove_hooks(tfc,
376 after_tracefile,
377 event,
378 event_by_id);
379 }
380
381 lttv_hooks_call(after_trace, self);
a8c0f09d 382}
383
8697a616 384void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
385 LttvHooks *before_tracefile,
386 LttvHooks *event,
387 LttvHooksById *event_by_id)
a8c0f09d 388{
8697a616 389 guint i;
390
391 LttvHooks *hook;
392
393 lttv_hooks_call(before_tracefile, self);
394 lttv_hooks_add_list(self->event, event);
395 if(event_by_id != NULL)
396 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
41a9e0c3 397 hook = lttv_hooks_by_id_find(self->event_by_id, i);
398 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, i));
8697a616 399 }
400
a8c0f09d 401}
402
8697a616 403void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
404 LttvHooks *after_tracefile,
405 LttvHooks *event,
406 LttvHooksById *event_by_id)
a8c0f09d 407{
8697a616 408 guint i;
409
410 LttvHooks *hook;
411
412
413 lttv_hooks_remove_list(self->event, event);
414 if(event_by_id != NULL)
415 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
41a9e0c3 416 hook = lttv_hooks_by_id_get(self->event_by_id, i);
417 if(hook != NULL)
418 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, i));
8697a616 419 }
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) {
dc877563 616 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
617 return TRUE;
618}
619
620
8b0bbe19 621/* Put all the tracefiles at the tracefile context position */
622void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *self)
623{
624 guint iter_trace, nb_trace;
625
626 LttvTraceContext *tc;
627
628 nb_trace = lttv_traceset_number(self->ts);
629
630 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
631 tc = self->traces[iter_trace];
632 {
633 /* each trace */
634 guint iter_tf, nb_tracefile;
635
636 LttvTracefileContext *tfc;
637
eed2ef37 638 nb_tracefile = tc->tracefiles->len;
8b0bbe19 639
640 for(iter_tf = 0 ; iter_tf < nb_tracefile ; iter_tf++) {
eed2ef37 641 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, iter_tf);
8b0bbe19 642 {
643 /* each tracefile */
644 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
645 LttEventPosition *ep = ltt_event_position_new();
646
eed2ef37 647 ltt_event_position(ltt_tracefile_get_event(tfc->tf), ep);
8b0bbe19 648
649 ltt_tracefile_seek_position(tfc->tf, ep);
650 g_free(ep);
651 }
652 }
653 }
654 }
655}
656
657
dc877563 658
8697a616 659void lttv_process_traceset_begin(LttvTracesetContext *self,
660 LttvHooks *before_traceset,
661 LttvHooks *before_trace,
662 LttvHooks *before_tracefile,
663 LttvHooks *event,
664 LttvHooksById *event_by_id)
665{
dc877563 666
8697a616 667 /* simply add hooks in context. _before hooks are called by add_hooks. */
668 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
669 lttv_traceset_context_add_hooks(self,
670 before_traceset,
671 before_trace,
672 before_tracefile,
673 event,
674 event_by_id);
675
2a2fa4f0 676}
677
8697a616 678/* Note : a _middle must be preceded from a _seek or another middle */
679guint lttv_process_traceset_middle(LttvTracesetContext *self,
680 LttTime end,
b8eccacd 681 guint nb_events,
8697a616 682 const LttvTracesetContextPosition *end_position)
2a2fa4f0 683{
684 GTree *pqueue = self->pqueue;
685
686 guint id;
687
2a2fa4f0 688 LttvTracefileContext *tfc;
689
eed2ef37 690 LttEvent *e;
691
2a2fa4f0 692 unsigned count = 0;
693
a54f091a 694 gboolean last_ret = FALSE; /* return value of the last hook list called */
695
dc877563 696 /* Get the next event from the pqueue, call its hooks,
697 reinsert in the pqueue the following event from the same tracefile
698 unless the tracefile is finished or the event is later than the
8697a616 699 end time. */
dc877563 700
ffd54a90 701 while(TRUE) {
dc877563 702 tfc = NULL;
703 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 704 /* End of traceset : tfc is NULL */
1d1df11d 705 if(unlikely(tfc == NULL))
a43d67ba 706 {
a43d67ba 707 return count;
708 }
dc877563 709
8697a616 710 /* Have we reached :
711 * - the maximum number of events specified?
712 * - the end position ?
713 * - the end time ?
714 * then the read is finished. We leave the queue in the same state and
715 * break the loop.
716 */
717
1d1df11d 718 if(unlikely(last_ret == TRUE ||
719 count >= nb_events ||
8b0bbe19 720 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
721 end_position) == 0)||
1d1df11d 722 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 723 {
a43d67ba 724 return count;
725 }
2a2fa4f0 726
308711e5 727 /* Get the tracefile with an event for the smallest time found. If two
728 or more tracefiles have events for the same time, hope that lookup
729 and remove are consistent. */
270e7cc5 730
f95bc830 731 g_tree_remove(pqueue, tfc);
2a2fa4f0 732 count++;
eed2ef37 733
734 e = ltt_tracefile_get_event(tfc->tf);
735 id = ltt_event_eventtype_id(e);
a54f091a 736 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
8697a616 737 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
dc877563 738
eed2ef37 739 if(likely(!ltt_tracefile_read(tfc->tf))) {
740 tfc->timestamp = ltt_event_time(e);
33f7a12c 741 g_tree_insert(pqueue, tfc, tfc);
dc877563 742 }
743 }
2a2fa4f0 744}
745
746
8697a616 747void lttv_process_traceset_end(LttvTracesetContext *self,
748 LttvHooks *after_traceset,
749 LttvHooks *after_trace,
750 LttvHooks *after_tracefile,
751 LttvHooks *event,
752 LttvHooksById *event_by_id)
2a2fa4f0 753{
8697a616 754 /* Remove hooks from context. _after hooks are called by remove_hooks. */
755 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
756 lttv_traceset_context_remove_hooks(self,
757 after_traceset,
758 after_trace,
759 after_tracefile,
760 event,
761 event_by_id);
762}
2a2fa4f0 763
8697a616 764void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
765{
766 guint i, nb_tracefile;
2a2fa4f0 767
eed2ef37 768 gint ret;
769
2a2fa4f0 770 LttvTracefileContext *tfc;
771
a5ba1787 772 GTree *pqueue = self->ts_context->pqueue;
773
eed2ef37 774 nb_tracefile = self->tracefiles->len;
dc877563 775
8697a616 776 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 777 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
778 ret = ltt_tracefile_seek_time(tfc->tf, start);
779 if(ret) g_error("error in lttv_process_trace_seek_time seek");
a5ba1787 780 g_tree_remove(pqueue, tfc);
eed2ef37 781 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
782 g_tree_insert(pqueue, tfc, tfc);
8697a616 783 }
784}
dc877563 785
2a2fa4f0 786
8697a616 787void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
788{
789 guint i, nb_trace;
2a2fa4f0 790
8697a616 791 LttvTraceContext *tc;
2a2fa4f0 792
8697a616 793 nb_trace = lttv_traceset_number(self->ts);
794 for(i = 0 ; i < nb_trace ; i++) {
795 tc = self->traces[i];
796 lttv_process_trace_seek_time(tc, start);
797 }
dc877563 798}
b445142a 799
308711e5 800
a5ba1787 801gboolean lttv_process_tracefile_seek_position(LttvTracefileContext *self,
802 const LttEventPosition *pos)
803{
804 LttvTracefileContext *tfc = self;
805
a5ba1787 806 GTree *pqueue = self->t_context->ts_context->pqueue;
807
808 ltt_tracefile_seek_position(tfc->tf, pos);
809 g_tree_remove(pqueue, tfc);
eed2ef37 810 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
811 g_tree_insert(pqueue, tfc, tfc);
a5ba1787 812
00e74b69 813 return TRUE;
a5ba1787 814}
815
8697a616 816gboolean lttv_process_trace_seek_position(LttvTraceContext *self,
817 const LttvTraceContextPosition *pos)
308711e5 818{
dbb7bb09 819 guint i, nb_tracefile;
308711e5 820
821 LttvTracefileContext *tfc;
822
eed2ef37 823 nb_tracefile = self->tracefiles->len;
308711e5 824
8697a616 825 if(nb_tracefile != pos->nb_tracefile)
826 return FALSE; /* Error */
827
dbb7bb09 828 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 829 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
a5ba1787 830 lttv_process_tracefile_seek_position(tfc, pos->tf_pos[i]);
308711e5 831 }
8697a616 832
833 return TRUE;
308711e5 834}
835
836
8697a616 837
838gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
839 const LttvTracesetContextPosition *pos)
308711e5 840{
841 guint i, nb_trace;
8697a616 842 gboolean sum_ret = TRUE;
308711e5 843
844 LttvTraceContext *tc;
845
846 nb_trace = lttv_traceset_number(self->ts);
8697a616 847
848 if(nb_trace != pos->nb_trace)
849 return FALSE; /* Error */
850
308711e5 851 for(i = 0 ; i < nb_trace ; i++) {
852 tc = self->traces[i];
8697a616 853 sum_ret = sum_ret && lttv_process_trace_seek_position(tc, &pos->t_pos[i]);
308711e5 854 }
8697a616 855
856 return sum_ret;
308711e5 857}
858
859
8697a616 860
b445142a 861static LttField *
eed2ef37 862find_field(LttEventType *et, const GQuark field)
b445142a 863{
864 LttType *t;
865
866 LttField *f;
867
868 guint i, nb;
869
eed2ef37 870 GQuark name;
b445142a 871
eed2ef37 872 /* Field is unset */
873 if(field == 0) return NULL;
874
b445142a 875 f = ltt_eventtype_field(et);
876 t = ltt_eventtype_type(et);
877 g_assert(ltt_type_class(t) == LTT_STRUCT);
878 nb = ltt_type_member_number(t);
879 for(i = 0 ; i < nb ; i++) {
880 ltt_type_member_type(t, i, &name);
eed2ef37 881 if(name == field) break;
b445142a 882 }
883 g_assert(i < nb);
884 return ltt_field_member(f, i);
885}
886
eed2ef37 887LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
888 guint facility_id)
889{
890 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
891}
892
893/* Get the first facility corresponding to the name. As the types must be
894 * compatible, it is relevant to use the field name and sizes of the first
895 * facility to create data structures and assume the data will be compatible
896 * thorough the trace */
897LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
898{
899 g_assert(th->fac_list->len > 0);
900 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
901}
902
b445142a 903
eed2ef37 904/* Returns 0 on success, -1 if fails. */
905gint
906lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
907 GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th)
b445142a 908{
909 LttFacility *f;
910
eed2ef37 911 LttEventType *et, *first_et;
912
913 GArray *facilities;
914
915 guint i, fac_id;
b445142a 916
eed2ef37 917 LttvTraceHookByFacility *thf, *first_thf;
b445142a 918
eed2ef37 919 facilities = ltt_trace_facility_get_by_name(t, facility);
920
921 if(unlikely(facilities == NULL)) goto facility_error;
922
923 th->fac_index = g_array_sized_new(FALSE, TRUE,
924 sizeof(LttvTraceHookByFacility),
925 NUM_FACILITIES);
926 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
b445142a 927
eed2ef37 928 th->fac_list = g_array_sized_new(FALSE, TRUE,
929 sizeof(LttvTraceHookByFacility*),
930 facilities->len);
931 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
932
933 fac_id = g_array_index(facilities, guint, 0);
934 f = ltt_trace_get_facility_by_num(t, fac_id);
935
936 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
937 if(unlikely(et == NULL)) goto event_error;
938
939 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
940 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0)
941 = thf;
942 thf->h = h;
943 thf->id = ltt_eventtype_id(et);
944 thf->f1 = find_field(et, field1);
945 thf->f2 = find_field(et, field2);
946 thf->f3 = find_field(et, field3);
947
948 first_thf = thf;
949
950 /* Check for type compatibility too */
951 for(i=1;i<facilities->len;i++) {
952 fac_id = g_array_index(facilities, guint, i);
953 f = ltt_trace_get_facility_by_num(t, fac_id);
954
955 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
956 if(unlikely(et == NULL)) goto event_error;
957
958 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
959 g_array_index(th->fac_list, LttvTraceHookByFacility*, i)
960 = thf;
961 thf->h = h;
962 thf->id = ltt_eventtype_id(et);
963 thf->f1 = find_field(et, field1);
964 if(check_fields_compatibility(first_et, et,
965 first_thf->f1, thf->f1))
966 goto type_error;
967
968 thf->f2 = find_field(et, field2);
969 if(check_fields_compatibility(first_et, et,
970 first_thf->f2, thf->f2))
971 goto type_error;
972
973 thf->f3 = find_field(et, field3);
974 if(check_fields_compatibility(first_et, et,
975 first_thf->f3, thf->f3))
976 goto type_error;
977 }
978
979 return 0;
980
981type_error:
982 goto free;
983event_error:
984 g_error("Event type %s does not exist",
985 g_quark_to_string(ltt_eventtype_name(et)));
986 goto free;
987facility_error:
988 g_error("No %s facility", g_quark_to_string(facility));
989 goto free;
990free:
991 g_array_free(th->fac_index, TRUE);
992 g_array_free(th->fac_list, TRUE);
993 th->fac_index = NULL;
994 th->fac_list = NULL;
995 return -1;
996}
997
998void lttv_trace_hook_destroy(LttvTraceHook *th)
999{
1000 g_array_free(th->fac_index, TRUE);
1001 g_array_free(th->fac_list, TRUE);
b445142a 1002}
1003
1004
8b0bbe19 1005LttvTracesetContextPosition *lttv_traceset_context_position_new()
5e2c04a2 1006{
1007 return g_new(LttvTracesetContextPosition,1);
1008}
1009
1010
8697a616 1011void lttv_traceset_context_position_save(const LttvTracesetContext *self,
1012 LttvTracesetContextPosition *pos)
1013{
1014 guint nb_trace, nb_tracefile;
1015 guint iter_trace, iter_tracefile;
1016
1017 LttvTraceContext *tc;
1018
1019 LttvTracefileContext *tfc;
1020
1021 LttEvent *event;
1022
2d262115 1023 LttTime timestamp = self->time_span.end_time;
1024
8697a616 1025 pos->nb_trace = nb_trace = lttv_traceset_number(self->ts);
1026 pos->t_pos = g_new(LttvTraceContextPosition, nb_trace);
1027
1028 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1029 tc = self->traces[iter_trace];
8697a616 1030
eed2ef37 1031 nb_tracefile = tc->tracefiles->len;
1032 pos->t_pos[iter_trace].nb_tracefile = nb_tracefile;
1033
8697a616 1034 pos->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
1035 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
eed2ef37 1036 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext,
1037 iter_tracefile);
1038 event = ltt_tracefile_get_event(tfc->tf);
4d39be09 1039 if(event!=NULL) {
1040 pos->t_pos[iter_trace].tf_pos[iter_tracefile]
1041 = ltt_event_position_new();
1042 ltt_event_position(event,
1043 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1044 } else {
1045 pos->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
1046 }
2d262115 1047 if(ltt_time_compare(tfc->timestamp, timestamp) < 0)
1048 timestamp = tfc->timestamp;
8697a616 1049 }
1050 }
2d262115 1051 pos->timestamp = timestamp;
8697a616 1052}
1053
1054void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1055{
00e74b69 1056 guint nb_trace;
8697a616 1057 guint iter_trace, iter_tracefile;
1058
1059 nb_trace = pos->nb_trace;
1060
1061 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1062 for(iter_tracefile = 0; iter_tracefile <
1063 pos->t_pos[iter_trace].nb_tracefile;
1064 iter_tracefile++) {
4d39be09 1065 if(pos->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
1066 g_free(pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
8697a616 1067 }
1068 g_free(pos->t_pos[iter_trace].tf_pos);
1069 }
1070 g_free(pos->t_pos);
1071
1072}
1073
5e2c04a2 1074void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1075 const LttvTracesetContextPosition *src)
1076{
1077 guint nb_trace, nb_tracefile;
1078 guint iter_trace, iter_tracefile;
1079
1080 nb_trace = dest->nb_trace = src->nb_trace;
1081 dest->t_pos = g_new(LttvTraceContextPosition, nb_trace);
1082
1083 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1084
eed2ef37 1085 nb_tracefile = src->t_pos[iter_trace].nb_tracefile;
1086
1087 dest->t_pos[iter_trace].nb_tracefile = nb_tracefile;
1088
1089 dest->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
5e2c04a2 1090
1091 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1092 dest->t_pos[iter_trace].tf_pos[iter_tracefile] =
1093 ltt_event_position_new();
4d39be09 1094 if(src->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
1095 ltt_event_position_copy(
5e2c04a2 1096 dest->t_pos[iter_trace].tf_pos[iter_tracefile],
1097 src->t_pos[iter_trace].tf_pos[iter_tracefile]);
4d39be09 1098 else
1099 dest->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
5e2c04a2 1100 }
1101 }
1102
1103 dest->timestamp = src->timestamp;
1104}
1105
8697a616 1106gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1107 const LttvTracesetContextPosition *pos)
1108{
1109 guint nb_trace, nb_tracefile;
1110 guint iter_trace, iter_tracefile;
1111 gint ret;
1112
1113 LttvTraceContext *tc;
1114
1115 LttvTracefileContext *tfc;
1116
1117 LttEvent *event;
1118
1119 nb_trace = lttv_traceset_number(self->ts);
1120
1d1df11d 1121 if(unlikely(pos->nb_trace != nb_trace))
8697a616 1122 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
1123
1124 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1125 tc = self->traces[iter_trace];
eed2ef37 1126 nb_tracefile = tc->tracefiles->len;
8697a616 1127
1d1df11d 1128 if(unlikely(pos->t_pos[iter_trace].nb_tracefile != nb_tracefile))
8697a616 1129 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1130
1131 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
eed2ef37 1132 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext,
1133 iter_tracefile);
1134 event = ltt_tracefile_get_event(tfc->tf);
1135 ret = ltt_event_position_compare((LttEventPosition*)event,
00e74b69 1136 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1137 if(ret != 0)
8697a616 1138 return ret;
1139 }
1140 }
1141 return 0;
1142}
1143
1144
1145gint lttv_traceset_context_pos_pos_compare(
1146 const LttvTracesetContextPosition *pos1,
1147 const LttvTracesetContextPosition *pos2)
1148{
1149 guint nb_trace, nb_tracefile;
1150 guint iter_trace, iter_tracefile;
1151
1152 gint ret;
1153
1154 nb_trace = pos1->nb_trace;
1d1df11d 1155 if(unlikely(nb_trace != pos2->nb_trace))
8697a616 1156 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1157
1158 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1159
1160 nb_tracefile = pos1->t_pos[iter_trace].nb_tracefile;
1d1df11d 1161 if(unlikely(nb_tracefile != pos2->t_pos[iter_trace].nb_tracefile))
8697a616 1162 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1163
1164 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
00e74b69 1165 ret = ltt_event_position_compare(
8697a616 1166 pos1->t_pos[iter_trace].tf_pos[iter_tracefile],
00e74b69 1167 pos2->t_pos[iter_trace].tf_pos[iter_tracefile]);
1168 if(ret != 0)
8697a616 1169 return ret;
1170 }
1171 }
1172 return 0;
1173}
1174
1175
2d262115 1176LttTime lttv_traceset_context_position_get_time(
1177 const LttvTracesetContextPosition *pos)
1178{
1179 return pos->timestamp;
1180}
1181
1182
1183LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1184{
1185 GTree *pqueue = self->pqueue;
b56b5fec 1186 LttvTracefileContext *tfc = NULL;
2d262115 1187
1188 g_tree_foreach(pqueue, get_first, &tfc);
1189
1190 return tfc;
1191}
This page took 0.088112 seconds and 4 git commands to generate.