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