genevent for 0.1.99.1
[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
dc877563 148
149static void
150init(LttvTracesetContext *self, LttvTraceset *ts)
151{
152 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
153
154 LttvTraceContext *tc;
155
156 LttvTracefileContext *tfc;
157
308711e5 158 LttTime null_time = {0, 0};
159
dc877563 160 nb_trace = lttv_traceset_number(ts);
161 self->ts = ts;
ffd54a90 162 self->traces = g_new(LttvTraceContext *, nb_trace);
ffd54a90 163 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 164 self->ts_a = lttv_traceset_attribute(ts);
dc877563 165 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 166 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
dc877563 167 self->traces[i] = tc;
168
169 tc->ts_context = self;
170 tc->index = i;
308711e5 171 tc->vt = lttv_traceset_get(ts, i);
172 tc->t = lttv_trace(tc->vt);
ffd54a90 173 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 174 tc->t_a = lttv_trace_attribute(tc->vt);
dc877563 175 nb_control = ltt_trace_control_tracefile_number(tc->t);
176 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
177 nb_tracefile = nb_control + nb_per_cpu;
dbb7bb09 178 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
dc877563 179
180 for(j = 0 ; j < nb_tracefile ; j++) {
ffd54a90 181 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dbb7bb09 182 tc->tracefiles[j] = tfc;
183 tfc->index = j;
184
dc877563 185 if(j < nb_control) {
dc877563 186 tfc->control = TRUE;
ffd54a90 187 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
dc877563 188 }
189 else {
dc877563 190 tfc->control = FALSE;
ffd54a90 191 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
dc877563 192 }
193 tfc->t_context = tc;
d3e01c7a 194 tfc->e = ltt_event_new();
8697a616 195 tfc->event = lttv_hooks_new();
196 tfc->event_by_id = lttv_hooks_by_id_new();
ffd54a90 197 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
dc877563 198 }
199 }
2d262115 200 self->pqueue = g_tree_new(compare_tracefile);
308711e5 201 lttv_process_traceset_seek_time(self, null_time);
33f7a12c 202 lttv_traceset_context_compute_time_span(self, &self->time_span);
8697a616 203
dc877563 204}
205
206
207void fini(LttvTracesetContext *self)
208{
dbb7bb09 209 guint i, j, nb_trace, nb_tracefile;
dc877563 210
211 LttvTraceContext *tc;
212
213 LttvTracefileContext *tfc;
214
ffd54a90 215 LttvTraceset *ts = self->ts;
dc877563 216
f7afe191 217 //FIXME : segfault
8697a616 218
219 g_tree_destroy(self->pqueue);
2061e03d 220 g_object_unref(self->a);
dc877563 221
222 nb_trace = lttv_traceset_number(ts);
223
224 for(i = 0 ; i < nb_trace ; i++) {
225 tc = self->traces[i];
226
ffd54a90 227 g_object_unref(tc->a);
dc877563 228
dbb7bb09 229 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
230 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 231
232 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 233 tfc = tc->tracefiles[j];
d3e01c7a 234 ltt_event_destroy(tfc->e);
8697a616 235 lttv_hooks_destroy(tfc->event);
236 lttv_hooks_by_id_destroy(tfc->event_by_id);
ffd54a90 237 g_object_unref(tfc->a);
dc877563 238 g_object_unref(tfc);
239 }
dbb7bb09 240 g_free(tc->tracefiles);
dc877563 241 g_object_unref(tc);
242 }
243 g_free(self->traces);
244}
245
246
247void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
8697a616 248 LttvHooks *before_traceset,
dc877563 249 LttvHooks *before_trace,
ffd54a90 250 LttvHooks *before_tracefile,
8697a616 251 LttvHooks *event,
252 LttvHooksById *event_by_id)
dc877563 253{
254 LttvTraceset *ts = self->ts;
255
8697a616 256 guint i, nb_trace;
dc877563 257
258 LttvTraceContext *tc;
259
8697a616 260 lttv_hooks_call(before_traceset, self);
dc877563 261
dc877563 262 nb_trace = lttv_traceset_number(ts);
263
264 for(i = 0 ; i < nb_trace ; i++) {
265 tc = self->traces[i];
8697a616 266 lttv_trace_context_add_hooks(tc,
267 before_trace,
268 before_tracefile,
269 event,
270 event_by_id);
dc877563 271 }
272}
273
274
275void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
dc877563 276 LttvHooks *after_traceset,
dc877563 277 LttvHooks *after_trace,
ffd54a90 278 LttvHooks *after_tracefile,
8697a616 279 LttvHooks *event,
280 LttvHooksById *event_by_id)
dc877563 281{
8697a616 282
dc877563 283 LttvTraceset *ts = self->ts;
284
8697a616 285 guint i, nb_trace;
dc877563 286
287 LttvTraceContext *tc;
288
dc877563 289 nb_trace = lttv_traceset_number(ts);
290
291 for(i = 0 ; i < nb_trace ; i++) {
292 tc = self->traces[i];
8697a616 293 lttv_trace_context_remove_hooks(tc,
294 after_trace,
295 after_tracefile,
296 event,
297 event_by_id);
dc877563 298 }
8697a616 299
300 lttv_hooks_call(after_traceset, self);
301
302
dc877563 303}
304
8697a616 305void lttv_trace_context_add_hooks(LttvTraceContext *self,
306 LttvHooks *before_trace,
307 LttvHooks *before_tracefile,
308 LttvHooks *event,
309 LttvHooksById *event_by_id)
a8c0f09d 310{
8697a616 311 guint i, nb_tracefile;
312
313 LttvTracefileContext *tfc;
314
315 lttv_hooks_call(before_trace, self);
316 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
317 ltt_trace_per_cpu_tracefile_number(self->t);
318
319 for(i = 0 ; i < nb_tracefile ; i++) {
320 tfc = self->tracefiles[i];
321 lttv_tracefile_context_add_hooks(tfc,
322 before_tracefile,
323 event,
324 event_by_id);
325 }
a8c0f09d 326}
327
8697a616 328
329
330void lttv_trace_context_remove_hooks(LttvTraceContext *self,
331 LttvHooks *after_trace,
332 LttvHooks *after_tracefile,
333 LttvHooks *event,
334 LttvHooksById *event_by_id)
a8c0f09d 335{
8697a616 336 guint i, nb_tracefile;
337
338 LttvTracefileContext *tfc;
339
340 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
341 ltt_trace_per_cpu_tracefile_number(self->t);
342
343 for(i = 0 ; i < nb_tracefile ; i++) {
344 tfc = self->tracefiles[i];
345 lttv_tracefile_context_remove_hooks(tfc,
346 after_tracefile,
347 event,
348 event_by_id);
349 }
350
351 lttv_hooks_call(after_trace, self);
a8c0f09d 352}
353
8697a616 354void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
355 LttvHooks *before_tracefile,
356 LttvHooks *event,
357 LttvHooksById *event_by_id)
a8c0f09d 358{
8697a616 359 guint i;
360
361 LttvHooks *hook;
362
363 lttv_hooks_call(before_tracefile, self);
364 lttv_hooks_add_list(self->event, event);
365 if(event_by_id != NULL)
366 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
41a9e0c3 367 hook = lttv_hooks_by_id_find(self->event_by_id, i);
368 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, i));
8697a616 369 }
370
a8c0f09d 371}
372
8697a616 373void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
374 LttvHooks *after_tracefile,
375 LttvHooks *event,
376 LttvHooksById *event_by_id)
a8c0f09d 377{
8697a616 378 guint i;
379
380 LttvHooks *hook;
381
382
383 lttv_hooks_remove_list(self->event, event);
384 if(event_by_id != NULL)
385 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
41a9e0c3 386 hook = lttv_hooks_by_id_get(self->event_by_id, i);
387 if(hook != NULL)
388 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, i));
8697a616 389 }
390
391 lttv_hooks_call(after_tracefile, self);
a8c0f09d 392}
393
8697a616 394
395
a8c0f09d 396void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
397 unsigned i,
8697a616 398 LttvHooks *event_by_id)
a8c0f09d 399{
400 LttvHooks * h;
8697a616 401 h = lttv_hooks_by_id_find(tfc->event_by_id, i);
402 lttv_hooks_add_list(h, event_by_id);
a8c0f09d 403}
404
405void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
406 unsigned i)
407{
8697a616 408 lttv_hooks_by_id_remove(tfc->event_by_id, i);
a8c0f09d 409}
dc877563 410
ba576a78 411static LttvTracesetContext *
dc877563 412new_traceset_context(LttvTracesetContext *self)
413{
ffd54a90 414 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
dc877563 415}
416
417
ba576a78 418static LttvTraceContext *
dc877563 419new_trace_context(LttvTracesetContext *self)
420{
ffd54a90 421 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
dc877563 422}
423
424
ba576a78 425static LttvTracefileContext *
dc877563 426new_tracefile_context(LttvTracesetContext *self)
427{
ffd54a90 428 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
dc877563 429}
430
431
432static void
433traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
434{
435 /* Be careful of anything which would not work well with shallow copies */
436}
437
438
439static void
440traceset_context_finalize (LttvTracesetContext *self)
441{
b445142a 442 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
443 ->finalize(G_OBJECT(self));
dc877563 444}
445
446
447static void
448traceset_context_class_init (LttvTracesetContextClass *klass)
449{
450 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
451
ffd54a90 452 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
dc877563 453 klass->init = init;
454 klass->fini = fini;
455 klass->new_traceset_context = new_traceset_context;
456 klass->new_trace_context = new_trace_context;
457 klass->new_tracefile_context = new_tracefile_context;
458}
459
460
461GType
ffd54a90 462lttv_traceset_context_get_type(void)
dc877563 463{
464 static GType type = 0;
465 if (type == 0) {
466 static const GTypeInfo info = {
ffd54a90 467 sizeof (LttvTracesetContextClass),
dc877563 468 NULL, /* base_init */
469 NULL, /* base_finalize */
ffd54a90 470 (GClassInitFunc) traceset_context_class_init, /* class_init */
dc877563 471 NULL, /* class_finalize */
472 NULL, /* class_data */
ffd54a90 473 sizeof (LttvTracesetContext),
dc877563 474 0, /* n_preallocs */
00e74b69 475 (GInstanceInitFunc) traceset_context_instance_init, /* instance_init */
476 NULL /* Value handling */
dc877563 477 };
478
ffd54a90 479 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
dc877563 480 &info, 0);
481 }
482 return type;
483}
484
485
486static void
487trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
488{
489 /* Be careful of anything which would not work well with shallow copies */
490}
491
492
493static void
494trace_context_finalize (LttvTraceContext *self)
495{
b445142a 496 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
497 finalize(G_OBJECT(self));
dc877563 498}
499
500
501static void
502trace_context_class_init (LttvTraceContextClass *klass)
503{
504 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
505
ffd54a90 506 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
dc877563 507}
508
509
510GType
ffd54a90 511lttv_trace_context_get_type(void)
dc877563 512{
513 static GType type = 0;
514 if (type == 0) {
515 static const GTypeInfo info = {
ffd54a90 516 sizeof (LttvTraceContextClass),
dc877563 517 NULL, /* base_init */
518 NULL, /* base_finalize */
ffd54a90 519 (GClassInitFunc) trace_context_class_init, /* class_init */
dc877563 520 NULL, /* class_finalize */
521 NULL, /* class_data */
c6bc9cb9 522 sizeof (LttvTraceContext),
dc877563 523 0, /* n_preallocs */
00e74b69 524 (GInstanceInitFunc) trace_context_instance_init, /* instance_init */
525 NULL /* Value handling */
dc877563 526 };
527
ffd54a90 528 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
dc877563 529 &info, 0);
530 }
531 return type;
532}
533
534
535static void
536tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
537{
538 /* Be careful of anything which would not work well with shallow copies */
539}
540
541
542static void
543tracefile_context_finalize (LttvTracefileContext *self)
544{
b445142a 545 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
546 ->finalize(G_OBJECT(self));
dc877563 547}
548
549
550static void
551tracefile_context_class_init (LttvTracefileContextClass *klass)
552{
553 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
554
ffd54a90 555 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
556}
557
558
559GType
560lttv_tracefile_context_get_type(void)
561{
562 static GType type = 0;
563 if (type == 0) {
564 static const GTypeInfo info = {
565 sizeof (LttvTracefileContextClass),
566 NULL, /* base_init */
567 NULL, /* base_finalize */
568 (GClassInitFunc) tracefile_context_class_init, /* class_init */
569 NULL, /* class_finalize */
570 NULL, /* class_data */
571 sizeof (LttvTracefileContext),
572 0, /* n_preallocs */
00e74b69 573 (GInstanceInitFunc) tracefile_context_instance_init, /* instance_init */
574 NULL /* Value handling */
ffd54a90 575 };
576
577 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
578 &info, 0);
579 }
580 return type;
dc877563 581}
582
583
dc877563 584
6843100a 585static gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
dc877563 586 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
587 return TRUE;
588}
589
590
8b0bbe19 591/* Put all the tracefiles at the tracefile context position */
592void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *self)
593{
594 guint iter_trace, nb_trace;
595
596 LttvTraceContext *tc;
597
598 nb_trace = lttv_traceset_number(self->ts);
599
600 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
601 tc = self->traces[iter_trace];
602 {
603 /* each trace */
604 guint iter_tf, nb_tracefile;
605
606 LttvTracefileContext *tfc;
607
608 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
609 ltt_trace_per_cpu_tracefile_number(tc->t);
610
611 for(iter_tf = 0 ; iter_tf < nb_tracefile ; iter_tf++) {
612 tfc = tc->tracefiles[iter_tf];
613 {
614 /* each tracefile */
615 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
616 LttEventPosition *ep = ltt_event_position_new();
617
618 ltt_event_position(tfc->e, ep);
619
620 ltt_tracefile_seek_position(tfc->tf, ep);
621 g_free(ep);
622 }
623 }
624 }
625 }
626}
627
628
dc877563 629
8697a616 630void lttv_process_traceset_begin(LttvTracesetContext *self,
631 LttvHooks *before_traceset,
632 LttvHooks *before_trace,
633 LttvHooks *before_tracefile,
634 LttvHooks *event,
635 LttvHooksById *event_by_id)
636{
dc877563 637
8697a616 638 /* simply add hooks in context. _before hooks are called by add_hooks. */
639 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
640 lttv_traceset_context_add_hooks(self,
641 before_traceset,
642 before_trace,
643 before_tracefile,
644 event,
645 event_by_id);
646
2a2fa4f0 647}
648
8697a616 649/* Note : a _middle must be preceded from a _seek or another middle */
650guint lttv_process_traceset_middle(LttvTracesetContext *self,
651 LttTime end,
b8eccacd 652 guint nb_events,
8697a616 653 const LttvTracesetContextPosition *end_position)
2a2fa4f0 654{
655 GTree *pqueue = self->pqueue;
656
657 guint id;
658
2a2fa4f0 659 LttvTracefileContext *tfc;
660
2a2fa4f0 661 unsigned count = 0;
662
a54f091a 663 gboolean last_ret = FALSE; /* return value of the last hook list called */
664
dc877563 665 /* Get the next event from the pqueue, call its hooks,
666 reinsert in the pqueue the following event from the same tracefile
667 unless the tracefile is finished or the event is later than the
8697a616 668 end time. */
dc877563 669
ffd54a90 670 while(TRUE) {
dc877563 671 tfc = NULL;
672 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 673 /* End of traceset : tfc is NULL */
1d1df11d 674 if(unlikely(tfc == NULL))
a43d67ba 675 {
a43d67ba 676 return count;
677 }
dc877563 678
8697a616 679 /* Have we reached :
680 * - the maximum number of events specified?
681 * - the end position ?
682 * - the end time ?
683 * then the read is finished. We leave the queue in the same state and
684 * break the loop.
685 */
686
1d1df11d 687 if(unlikely(last_ret == TRUE ||
688 count >= nb_events ||
8b0bbe19 689 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
690 end_position) == 0)||
1d1df11d 691 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 692 {
a43d67ba 693 return count;
694 }
2a2fa4f0 695
308711e5 696 /* Get the tracefile with an event for the smallest time found. If two
697 or more tracefiles have events for the same time, hope that lookup
698 and remove are consistent. */
270e7cc5 699
f95bc830 700 g_tree_remove(pqueue, tfc);
2a2fa4f0 701 count++;
dc877563 702
8697a616 703 id = ltt_event_eventtype_id(tfc->e);
a54f091a 704 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
8697a616 705 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
dc877563 706
1d1df11d 707 if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) {
d3e01c7a 708 tfc->timestamp = ltt_event_time(tfc->e);
33f7a12c 709 g_tree_insert(pqueue, tfc, tfc);
dc877563 710 }
711 }
2a2fa4f0 712}
713
714
8697a616 715void lttv_process_traceset_end(LttvTracesetContext *self,
716 LttvHooks *after_traceset,
717 LttvHooks *after_trace,
718 LttvHooks *after_tracefile,
719 LttvHooks *event,
720 LttvHooksById *event_by_id)
2a2fa4f0 721{
8697a616 722 /* Remove hooks from context. _after hooks are called by remove_hooks. */
723 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
724 lttv_traceset_context_remove_hooks(self,
725 after_traceset,
726 after_trace,
727 after_tracefile,
728 event,
729 event_by_id);
730}
2a2fa4f0 731
8697a616 732void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
733{
734 guint i, nb_tracefile;
2a2fa4f0 735
736 LttvTracefileContext *tfc;
737
a5ba1787 738 GTree *pqueue = self->ts_context->pqueue;
739
8697a616 740 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
741 ltt_trace_per_cpu_tracefile_number(self->t);
dc877563 742
8697a616 743 for(i = 0 ; i < nb_tracefile ; i++) {
744 tfc = self->tracefiles[i];
745 ltt_tracefile_seek_time(tfc->tf, start);
a5ba1787 746 g_tree_remove(pqueue, tfc);
1d1df11d 747 if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) {
d3e01c7a 748 tfc->timestamp = ltt_event_time(tfc->e);
a5ba1787 749 g_tree_insert(pqueue, tfc, tfc);
8697a616 750 }
751 }
752}
dc877563 753
2a2fa4f0 754
8697a616 755void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
756{
757 guint i, nb_trace;
2a2fa4f0 758
8697a616 759 LttvTraceContext *tc;
2a2fa4f0 760
8697a616 761 nb_trace = lttv_traceset_number(self->ts);
762 for(i = 0 ; i < nb_trace ; i++) {
763 tc = self->traces[i];
764 lttv_process_trace_seek_time(tc, start);
765 }
dc877563 766}
b445142a 767
308711e5 768
a5ba1787 769gboolean lttv_process_tracefile_seek_position(LttvTracefileContext *self,
770 const LttEventPosition *pos)
771{
772 LttvTracefileContext *tfc = self;
773
a5ba1787 774 GTree *pqueue = self->t_context->ts_context->pqueue;
775
776 ltt_tracefile_seek_position(tfc->tf, pos);
777 g_tree_remove(pqueue, tfc);
1d1df11d 778 if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) {
d3e01c7a 779 tfc->timestamp = ltt_event_time(tfc->e);
a5ba1787 780 g_tree_insert(pqueue, tfc, tfc);
781 }
782
00e74b69 783 return TRUE;
a5ba1787 784}
785
8697a616 786gboolean lttv_process_trace_seek_position(LttvTraceContext *self,
787 const LttvTraceContextPosition *pos)
308711e5 788{
dbb7bb09 789 guint i, nb_tracefile;
308711e5 790
791 LttvTracefileContext *tfc;
792
dbb7bb09 793 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
794 ltt_trace_per_cpu_tracefile_number(self->t);
308711e5 795
8697a616 796 if(nb_tracefile != pos->nb_tracefile)
797 return FALSE; /* Error */
798
dbb7bb09 799 for(i = 0 ; i < nb_tracefile ; i++) {
800 tfc = self->tracefiles[i];
a5ba1787 801 lttv_process_tracefile_seek_position(tfc, pos->tf_pos[i]);
308711e5 802 }
8697a616 803
804 return TRUE;
308711e5 805}
806
807
8697a616 808
809gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
810 const LttvTracesetContextPosition *pos)
308711e5 811{
812 guint i, nb_trace;
8697a616 813 gboolean sum_ret = TRUE;
308711e5 814
815 LttvTraceContext *tc;
816
817 nb_trace = lttv_traceset_number(self->ts);
8697a616 818
819 if(nb_trace != pos->nb_trace)
820 return FALSE; /* Error */
821
308711e5 822 for(i = 0 ; i < nb_trace ; i++) {
823 tc = self->traces[i];
8697a616 824 sum_ret = sum_ret && lttv_process_trace_seek_position(tc, &pos->t_pos[i]);
308711e5 825 }
8697a616 826
827 return sum_ret;
308711e5 828}
829
830
8697a616 831
b445142a 832static LttField *
833find_field(LttEventType *et, const char *field)
834{
835 LttType *t;
836
837 LttField *f;
838
839 guint i, nb;
840
841 char *name;
842
843 if(field == NULL) return NULL;
844
845 f = ltt_eventtype_field(et);
846 t = ltt_eventtype_type(et);
847 g_assert(ltt_type_class(t) == LTT_STRUCT);
848 nb = ltt_type_member_number(t);
849 for(i = 0 ; i < nb ; i++) {
850 ltt_type_member_type(t, i, &name);
851 if(strcmp(name, field) == 0) break;
852 }
853 g_assert(i < nb);
854 return ltt_field_member(f, i);
855}
856
857
858void
859lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
860 char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
861{
862 LttFacility *f;
863
864 LttEventType *et;
865
00e74b69 866 guint nb, pos;
b445142a 867
868 nb = ltt_trace_facility_find(t, facility, &pos);
1d1df11d 869 if(unlikely(nb < 1)) g_error("No %s facility", facility);
b445142a 870 f = ltt_trace_facility_get(t, pos);
871 et = ltt_facility_eventtype_get_by_name(f, event_type);
1d1df11d 872 if(unlikely(et == NULL)) g_error("Event %s does not exist", event_type);
b445142a 873
874 th->h = h;
875 th->id = ltt_eventtype_id(et);
876 th->f1 = find_field(et, field1);
877 th->f2 = find_field(et, field2);
878 th->f3 = find_field(et, field3);
879}
880
881
8b0bbe19 882LttvTracesetContextPosition *lttv_traceset_context_position_new()
5e2c04a2 883{
884 return g_new(LttvTracesetContextPosition,1);
885}
886
887
8697a616 888void lttv_traceset_context_position_save(const LttvTracesetContext *self,
889 LttvTracesetContextPosition *pos)
890{
891 guint nb_trace, nb_tracefile;
892 guint iter_trace, iter_tracefile;
893
894 LttvTraceContext *tc;
895
896 LttvTracefileContext *tfc;
897
898 LttEvent *event;
899
2d262115 900 LttTime timestamp = self->time_span.end_time;
901
8697a616 902 pos->nb_trace = nb_trace = lttv_traceset_number(self->ts);
903 pos->t_pos = g_new(LttvTraceContextPosition, nb_trace);
904
905 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
906 tc = self->traces[iter_trace];
907 pos->t_pos[iter_trace].nb_tracefile = nb_tracefile =
908 ltt_trace_control_tracefile_number(tc->t) +
909 ltt_trace_per_cpu_tracefile_number(tc->t);
910
911 pos->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
912 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
8697a616 913 tfc = tc->tracefiles[iter_tracefile];
914 event = tfc->e;
4d39be09 915 if(event!=NULL) {
916 pos->t_pos[iter_trace].tf_pos[iter_tracefile]
917 = ltt_event_position_new();
918 ltt_event_position(event,
919 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
920 } else {
921 pos->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
922 }
2d262115 923 if(ltt_time_compare(tfc->timestamp, timestamp) < 0)
924 timestamp = tfc->timestamp;
8697a616 925 }
926 }
2d262115 927 pos->timestamp = timestamp;
8697a616 928}
929
930void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
931{
00e74b69 932 guint nb_trace;
8697a616 933 guint iter_trace, iter_tracefile;
934
935 nb_trace = pos->nb_trace;
936
937 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
938 for(iter_tracefile = 0; iter_tracefile <
939 pos->t_pos[iter_trace].nb_tracefile;
940 iter_tracefile++) {
4d39be09 941 if(pos->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
942 g_free(pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
8697a616 943 }
944 g_free(pos->t_pos[iter_trace].tf_pos);
945 }
946 g_free(pos->t_pos);
947
948}
949
5e2c04a2 950void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
951 const LttvTracesetContextPosition *src)
952{
953 guint nb_trace, nb_tracefile;
954 guint iter_trace, iter_tracefile;
955
956 nb_trace = dest->nb_trace = src->nb_trace;
957 dest->t_pos = g_new(LttvTraceContextPosition, nb_trace);
958
959 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
960
961 nb_tracefile = dest->t_pos[iter_trace].nb_tracefile =
962 src->t_pos[iter_trace].nb_tracefile;
963
964 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
965 dest->t_pos[iter_trace].tf_pos[iter_tracefile] =
966 ltt_event_position_new();
4d39be09 967 if(src->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
968 ltt_event_position_copy(
5e2c04a2 969 dest->t_pos[iter_trace].tf_pos[iter_tracefile],
970 src->t_pos[iter_trace].tf_pos[iter_tracefile]);
4d39be09 971 else
972 dest->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
5e2c04a2 973 }
974 }
975
976 dest->timestamp = src->timestamp;
977}
978
8697a616 979gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
980 const LttvTracesetContextPosition *pos)
981{
982 guint nb_trace, nb_tracefile;
983 guint iter_trace, iter_tracefile;
984 gint ret;
985
986 LttvTraceContext *tc;
987
988 LttvTracefileContext *tfc;
989
990 LttEvent *event;
991
992 nb_trace = lttv_traceset_number(self->ts);
993
1d1df11d 994 if(unlikely(pos->nb_trace != nb_trace))
8697a616 995 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
996
997 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
998 tc = self->traces[iter_trace];
999 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
1000 ltt_trace_per_cpu_tracefile_number(tc->t);
1001
1d1df11d 1002 if(unlikely(pos->t_pos[iter_trace].nb_tracefile != nb_tracefile))
8697a616 1003 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1004
1005 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1006 tfc = tc->tracefiles[iter_tracefile];
1007 event = tfc->e;
00e74b69 1008 ret = ltt_event_event_position_compare(event,
1009 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1010 if(ret != 0)
8697a616 1011 return ret;
1012 }
1013 }
1014 return 0;
1015}
1016
1017
1018gint lttv_traceset_context_pos_pos_compare(
1019 const LttvTracesetContextPosition *pos1,
1020 const LttvTracesetContextPosition *pos2)
1021{
1022 guint nb_trace, nb_tracefile;
1023 guint iter_trace, iter_tracefile;
1024
1025 gint ret;
1026
1027 nb_trace = pos1->nb_trace;
1d1df11d 1028 if(unlikely(nb_trace != pos2->nb_trace))
8697a616 1029 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1030
1031 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1032
1033 nb_tracefile = pos1->t_pos[iter_trace].nb_tracefile;
1d1df11d 1034 if(unlikely(nb_tracefile != pos2->t_pos[iter_trace].nb_tracefile))
8697a616 1035 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1036
1037 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
00e74b69 1038 ret = ltt_event_position_compare(
8697a616 1039 pos1->t_pos[iter_trace].tf_pos[iter_tracefile],
00e74b69 1040 pos2->t_pos[iter_trace].tf_pos[iter_tracefile]);
1041 if(ret != 0)
8697a616 1042 return ret;
1043 }
1044 }
1045 return 0;
1046}
1047
1048
2d262115 1049LttTime lttv_traceset_context_position_get_time(
1050 const LttvTracesetContextPosition *pos)
1051{
1052 return pos->timestamp;
1053}
1054
1055
1056LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1057{
1058 GTree *pqueue = self->pqueue;
b56b5fec 1059 LttvTracefileContext *tfc = NULL;
2d262115 1060
1061 g_tree_foreach(pqueue, get_first, &tfc);
1062
1063 return tfc;
1064}
This page took 0.0811229999999999 seconds and 4 git commands to generate.