minor boundary change
[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
dc877563 19
d8f124de 20#include <lttv/tracecontext.h>
ffd54a90 21#include <ltt/event.h>
b445142a 22#include <ltt/facility.h>
a5dcde2f 23#include <ltt/trace.h>
24#include <ltt/type.h>
dc877563 25
ffd54a90 26void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
dc877563 27{
ffd54a90 28 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
dc877563 29}
30
31
32void lttv_context_fini(LttvTracesetContext *self)
33{
34 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
35}
36
37
38LttvTracesetContext *
39lttv_context_new_traceset_context(LttvTracesetContext *self)
40{
41 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
42}
43
44
45
46
47LttvTraceContext *
48lttv_context_new_trace_context(LttvTracesetContext *self)
49{
50 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
51}
52
53
54LttvTracefileContext *
55lttv_context_new_tracefile_context(LttvTracesetContext *self)
56{
c6bc9cb9 57 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dc877563 58}
59
f7afe191 60/****************************************************************************
61 * lttv_traceset_context_compute_time_span
62 *
63 * Keep the Time_Span is sync with on the fly addition and removal of traces
64 * in a trace set. It must be called each time a trace is added/removed from
65 * the traceset. It could be more efficient to call it only once a bunch
66 * of traces are loaded, but the calculation is not long, so it's not
67 * critical.
68 *
69 * Author : Xang Xiu Yang
70 * Imported from gtkTraceSet.c by Mathieu Desnoyers
71 ***************************************************************************/
72static void lttv_traceset_context_compute_time_span(
73 LttvTracesetContext *self,
74 TimeInterval *Time_Span)
75{
76 LttvTraceset * traceset = self->ts;
77 int numTraces = lttv_traceset_number(traceset);
78 int i;
79 LttTime s, e;
80 LttvTraceContext *tc;
81 LttTrace * trace;
82
912be9a5 83 Time_Span->startTime.tv_sec = 0;
84 Time_Span->startTime.tv_nsec = 0;
85 Time_Span->endTime.tv_sec = 0;
86 Time_Span->endTime.tv_nsec = 0;
87
f7afe191 88 for(i=0; i<numTraces;i++){
89 tc = self->traces[i];
90 trace = tc->t;
91
92 ltt_trace_time_span_get(trace, &s, &e);
93
94 if(i==0){
95 Time_Span->startTime = s;
96 Time_Span->endTime = e;
97 }else{
98 if(s.tv_sec < Time_Span->startTime.tv_sec ||
99 (s.tv_sec == Time_Span->startTime.tv_sec
100 && s.tv_nsec < Time_Span->startTime.tv_nsec))
101 Time_Span->startTime = s;
102 if(e.tv_sec > Time_Span->endTime.tv_sec ||
103 (e.tv_sec == Time_Span->endTime.tv_sec &&
104 e.tv_nsec > Time_Span->endTime.tv_nsec))
105 Time_Span->endTime = e;
106 }
107 }
108}
109
dc877563 110
111static void
112init(LttvTracesetContext *self, LttvTraceset *ts)
113{
114 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
115
116 LttvTraceContext *tc;
117
118 LttvTracefileContext *tfc;
119
308711e5 120 LttTime null_time = {0, 0};
121
dc877563 122 nb_trace = lttv_traceset_number(ts);
123 self->ts = ts;
ffd54a90 124 self->traces = g_new(LttvTraceContext *, nb_trace);
dc877563 125 self->before = lttv_hooks_new();
126 self->after = lttv_hooks_new();
ffd54a90 127 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 128 self->ts_a = lttv_traceset_attribute(ts);
dc877563 129 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 130 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
dc877563 131 self->traces[i] = tc;
132
133 tc->ts_context = self;
134 tc->index = i;
308711e5 135 tc->vt = lttv_traceset_get(ts, i);
136 tc->t = lttv_trace(tc->vt);
dc877563 137 tc->check = lttv_hooks_new();
138 tc->before = lttv_hooks_new();
139 tc->after = lttv_hooks_new();
ffd54a90 140 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 141 tc->t_a = lttv_trace_attribute(tc->vt);
dc877563 142 nb_control = ltt_trace_control_tracefile_number(tc->t);
143 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
144 nb_tracefile = nb_control + nb_per_cpu;
dbb7bb09 145 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
dc877563 146
147 for(j = 0 ; j < nb_tracefile ; j++) {
ffd54a90 148 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dbb7bb09 149 tc->tracefiles[j] = tfc;
150 tfc->index = j;
151
dc877563 152 if(j < nb_control) {
dc877563 153 tfc->control = TRUE;
ffd54a90 154 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
dc877563 155 }
156 else {
dc877563 157 tfc->control = FALSE;
ffd54a90 158 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
dc877563 159 }
160 tfc->t_context = tc;
161 tfc->check = lttv_hooks_new();
162 tfc->before = lttv_hooks_new();
163 tfc->after = lttv_hooks_new();
164 tfc->check_event = lttv_hooks_new();
165 tfc->before_event = lttv_hooks_new();
166 tfc->before_event_by_id = lttv_hooks_by_id_new();
167 tfc->after_event = lttv_hooks_new();
168 tfc->after_event_by_id = lttv_hooks_by_id_new();
ffd54a90 169 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
dc877563 170 }
171 }
308711e5 172 lttv_process_traceset_seek_time(self, null_time);
173 /*CHECK why dynamically allocate the time span... and the casing is wroNg*/
f7afe191 174 self->Time_Span = g_new(TimeInterval,1);
175 lttv_traceset_context_compute_time_span(self, self->Time_Span);
a43d67ba 176 self->e = NULL;
dc877563 177}
178
179
180void fini(LttvTracesetContext *self)
181{
dbb7bb09 182 guint i, j, nb_trace, nb_tracefile;
dc877563 183
184 LttvTraceContext *tc;
185
186 LttvTracefileContext *tfc;
187
ffd54a90 188 LttvTraceset *ts = self->ts;
dc877563 189
f7afe191 190 g_free(self->Time_Span);
191
dc877563 192 lttv_hooks_destroy(self->before);
193 lttv_hooks_destroy(self->after);
f7afe191 194 //FIXME : segfault
2061e03d 195 g_object_unref(self->a);
dc877563 196
197 nb_trace = lttv_traceset_number(ts);
198
199 for(i = 0 ; i < nb_trace ; i++) {
200 tc = self->traces[i];
201
202 lttv_hooks_destroy(tc->check);
203 lttv_hooks_destroy(tc->before);
204 lttv_hooks_destroy(tc->after);
ffd54a90 205 g_object_unref(tc->a);
dc877563 206
dbb7bb09 207 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
208 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 209
210 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 211 tfc = tc->tracefiles[j];
dc877563 212 lttv_hooks_destroy(tfc->check);
213 lttv_hooks_destroy(tfc->before);
214 lttv_hooks_destroy(tfc->after);
215 lttv_hooks_destroy(tfc->check_event);
216 lttv_hooks_destroy(tfc->before_event);
217 lttv_hooks_by_id_destroy(tfc->before_event_by_id);
218 lttv_hooks_destroy(tfc->after_event);
219 lttv_hooks_by_id_destroy(tfc->after_event_by_id);
ffd54a90 220 g_object_unref(tfc->a);
dc877563 221 g_object_unref(tfc);
222 }
dbb7bb09 223 g_free(tc->tracefiles);
dc877563 224 g_object_unref(tc);
225 }
226 g_free(self->traces);
227}
228
229
230void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
231 LttvHooks *before_traceset,
232 LttvHooks *after_traceset,
233 LttvHooks *check_trace,
234 LttvHooks *before_trace,
235 LttvHooks *after_trace,
ffd54a90 236 LttvHooks *check_tracefile,
237 LttvHooks *before_tracefile,
238 LttvHooks *after_tracefile,
dc877563 239 LttvHooks *check_event,
240 LttvHooks *before_event,
241 LttvHooks *after_event)
242{
243 LttvTraceset *ts = self->ts;
244
dbb7bb09 245 guint i, j, nb_trace, nb_tracefile;
dc877563 246
247 LttvTraceContext *tc;
248
249 LttvTracefileContext *tfc;
250
251 void *hook_data;
252
253 lttv_hooks_add_list(self->before, before_traceset);
254 lttv_hooks_add_list(self->after, after_traceset);
255 nb_trace = lttv_traceset_number(ts);
256
257 for(i = 0 ; i < nb_trace ; i++) {
258 tc = self->traces[i];
259 lttv_hooks_add_list(tc->check, check_trace);
260 lttv_hooks_add_list(tc->before, before_trace);
261 lttv_hooks_add_list(tc->after, after_trace);
dbb7bb09 262 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
263 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 264
265 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 266 tfc = tc->tracefiles[j];
dc877563 267 lttv_hooks_add_list(tfc->check, check_tracefile);
268 lttv_hooks_add_list(tfc->before, before_tracefile);
269 lttv_hooks_add_list(tfc->after, after_tracefile);
270 lttv_hooks_add_list(tfc->check_event, check_event);
271 lttv_hooks_add_list(tfc->before_event, before_event);
272 lttv_hooks_add_list(tfc->after_event, after_event);
273 }
274 }
275}
276
277
278void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
279 LttvHooks *before_traceset,
280 LttvHooks *after_traceset,
281 LttvHooks *check_trace,
282 LttvHooks *before_trace,
283 LttvHooks *after_trace,
ffd54a90 284 LttvHooks *check_tracefile,
285 LttvHooks *before_tracefile,
286 LttvHooks *after_tracefile,
dc877563 287 LttvHooks *check_event,
288 LttvHooks *before_event,
289 LttvHooks *after_event)
290{
291 LttvTraceset *ts = self->ts;
292
dbb7bb09 293 guint i, j, nb_trace, nb_tracefile;
dc877563 294
295 LttvTraceContext *tc;
296
297 LttvTracefileContext *tfc;
298
299 void *hook_data;
300
301 lttv_hooks_remove_list(self->before, before_traceset);
302 lttv_hooks_remove_list(self->after, after_traceset);
303 nb_trace = lttv_traceset_number(ts);
304
305 for(i = 0 ; i < nb_trace ; i++) {
306 tc = self->traces[i];
307 lttv_hooks_remove_list(tc->check, check_trace);
308 lttv_hooks_remove_list(tc->before, before_trace);
309 lttv_hooks_remove_list(tc->after, after_trace);
dbb7bb09 310 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
311 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 312
313 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 314 tfc = tc->tracefiles[j];
dc877563 315 lttv_hooks_remove_list(tfc->check, check_tracefile);
316 lttv_hooks_remove_list(tfc->before, before_tracefile);
317 lttv_hooks_remove_list(tfc->after, after_tracefile);
318 lttv_hooks_remove_list(tfc->check_event, check_event);
319 lttv_hooks_remove_list(tfc->before_event, before_event);
320 lttv_hooks_remove_list(tfc->after_event, after_event);
321 }
322 }
323}
324
a8c0f09d 325void lttv_trace_context_add_hooks(LttvTraceContext *tc,
326 LttvHooks *check_trace,
327 LttvHooks *before_trace,
328 LttvHooks *after_trace)
329{
330 lttv_hooks_add_list(tc->check, check_trace);
331 lttv_hooks_add_list(tc->before, before_trace);
332 lttv_hooks_add_list(tc->after, after_trace);
333}
334
335void lttv_trace_context_remove_hooks(LttvTraceContext *tc,
336 LttvHooks *check_trace,
337 LttvHooks *before_trace,
338 LttvHooks *after_trace)
339{
340 lttv_hooks_remove_list(tc->check, check_trace);
341 lttv_hooks_remove_list(tc->before, before_trace);
342 lttv_hooks_remove_list(tc->after, after_trace);
343}
344
345void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc,
346 LttvHooks *check_tracefile,
347 LttvHooks *before_tracefile,
348 LttvHooks *after_tracefile,
349 LttvHooks *check_event,
350 LttvHooks *before_event,
351 LttvHooks *after_event)
352{
353 lttv_hooks_add_list(tfc->check, check_tracefile);
354 lttv_hooks_add_list(tfc->before, before_tracefile);
355 lttv_hooks_add_list(tfc->after, after_tracefile);
356 lttv_hooks_add_list(tfc->check_event, check_event);
357 lttv_hooks_add_list(tfc->before_event, before_event);
358 lttv_hooks_add_list(tfc->after_event, after_event);
359}
360
361void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc,
362 LttvHooks *check_tracefile,
363 LttvHooks *before_tracefile,
364 LttvHooks *after_tracefile,
365 LttvHooks *check_event,
366 LttvHooks *before_event,
367 LttvHooks *after_event)
368{
369 lttv_hooks_remove_list(tfc->check, check_tracefile);
370 lttv_hooks_remove_list(tfc->before, before_tracefile);
371 lttv_hooks_remove_list(tfc->after, after_tracefile);
372 lttv_hooks_remove_list(tfc->check_event, check_event);
373 lttv_hooks_remove_list(tfc->before_event, before_event);
374 lttv_hooks_remove_list(tfc->after_event, after_event);
375}
376
377void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
378 unsigned i,
379 LttvHooks *before_event_by_id,
380 LttvHooks *after_event_by_id)
381{
382 LttvHooks * h;
383 h = lttv_hooks_by_id_find(tfc->before_event_by_id, i);
384 lttv_hooks_add_list(h, before_event_by_id);
385 h = lttv_hooks_by_id_find(tfc->after_event_by_id, i);
386 lttv_hooks_add_list(h, after_event_by_id);
387}
388
389void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
390 unsigned i)
391{
392 lttv_hooks_by_id_remove(tfc->before_event_by_id, i);
393 lttv_hooks_by_id_remove(tfc->after_event_by_id, i);
394}
dc877563 395
ba576a78 396static LttvTracesetContext *
dc877563 397new_traceset_context(LttvTracesetContext *self)
398{
ffd54a90 399 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
dc877563 400}
401
402
ba576a78 403static LttvTraceContext *
dc877563 404new_trace_context(LttvTracesetContext *self)
405{
ffd54a90 406 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
dc877563 407}
408
409
ba576a78 410static LttvTracefileContext *
dc877563 411new_tracefile_context(LttvTracesetContext *self)
412{
ffd54a90 413 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
dc877563 414}
415
416
417static void
418traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
419{
420 /* Be careful of anything which would not work well with shallow copies */
421}
422
423
424static void
425traceset_context_finalize (LttvTracesetContext *self)
426{
b445142a 427 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
428 ->finalize(G_OBJECT(self));
dc877563 429}
430
431
432static void
433traceset_context_class_init (LttvTracesetContextClass *klass)
434{
435 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
436
ffd54a90 437 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
dc877563 438 klass->init = init;
439 klass->fini = fini;
440 klass->new_traceset_context = new_traceset_context;
441 klass->new_trace_context = new_trace_context;
442 klass->new_tracefile_context = new_tracefile_context;
443}
444
445
446GType
ffd54a90 447lttv_traceset_context_get_type(void)
dc877563 448{
449 static GType type = 0;
450 if (type == 0) {
451 static const GTypeInfo info = {
ffd54a90 452 sizeof (LttvTracesetContextClass),
dc877563 453 NULL, /* base_init */
454 NULL, /* base_finalize */
ffd54a90 455 (GClassInitFunc) traceset_context_class_init, /* class_init */
dc877563 456 NULL, /* class_finalize */
457 NULL, /* class_data */
ffd54a90 458 sizeof (LttvTracesetContext),
dc877563 459 0, /* n_preallocs */
ffd54a90 460 (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
dc877563 461 };
462
ffd54a90 463 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
dc877563 464 &info, 0);
465 }
466 return type;
467}
468
469
470static void
471trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
472{
473 /* Be careful of anything which would not work well with shallow copies */
474}
475
476
477static void
478trace_context_finalize (LttvTraceContext *self)
479{
b445142a 480 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
481 finalize(G_OBJECT(self));
dc877563 482}
483
484
485static void
486trace_context_class_init (LttvTraceContextClass *klass)
487{
488 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
489
ffd54a90 490 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
dc877563 491}
492
493
494GType
ffd54a90 495lttv_trace_context_get_type(void)
dc877563 496{
497 static GType type = 0;
498 if (type == 0) {
499 static const GTypeInfo info = {
ffd54a90 500 sizeof (LttvTraceContextClass),
dc877563 501 NULL, /* base_init */
502 NULL, /* base_finalize */
ffd54a90 503 (GClassInitFunc) trace_context_class_init, /* class_init */
dc877563 504 NULL, /* class_finalize */
505 NULL, /* class_data */
c6bc9cb9 506 sizeof (LttvTraceContext),
dc877563 507 0, /* n_preallocs */
ffd54a90 508 (GInstanceInitFunc) trace_context_instance_init /* instance_init */
dc877563 509 };
510
ffd54a90 511 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
dc877563 512 &info, 0);
513 }
514 return type;
515}
516
517
518static void
519tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
520{
521 /* Be careful of anything which would not work well with shallow copies */
522}
523
524
525static void
526tracefile_context_finalize (LttvTracefileContext *self)
527{
b445142a 528 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
529 ->finalize(G_OBJECT(self));
dc877563 530}
531
532
533static void
534tracefile_context_class_init (LttvTracefileContextClass *klass)
535{
536 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
537
ffd54a90 538 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
539}
540
541
542GType
543lttv_tracefile_context_get_type(void)
544{
545 static GType type = 0;
546 if (type == 0) {
547 static const GTypeInfo info = {
548 sizeof (LttvTracefileContextClass),
549 NULL, /* base_init */
550 NULL, /* base_finalize */
551 (GClassInitFunc) tracefile_context_class_init, /* class_init */
552 NULL, /* class_finalize */
553 NULL, /* class_data */
554 sizeof (LttvTracefileContext),
555 0, /* n_preallocs */
556 (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */
557 };
558
559 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
560 &info, 0);
561 }
562 return type;
dc877563 563}
564
565
ffd54a90 566gint compare_tracefile(gconstpointer a, gconstpointer b)
dc877563 567{
f95bc830 568 gint comparison;
569
570 LttvTracefileContext *trace_a = (LttvTracefileContext *)a;
571
572 LttvTracefileContext *trace_b = (LttvTracefileContext *)b;
573
574 if(trace_a == trace_b) return 0;
575 comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
576 if(comparison != 0) return comparison;
577 if(trace_a->index < trace_b->index) return -1;
578 else if(trace_a->index > trace_b->index) return 1;
579 if(trace_a->t_context->index < trace_b->t_context->index) return -1;
580 else if(trace_a->t_context->index > trace_b->t_context->index) return 1;
581 g_assert(FALSE);
dc877563 582}
583
584
585gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
586 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
587 return TRUE;
588}
589
590
2a2fa4f0 591void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
dc877563 592{
dbb7bb09 593 guint i, j, nbi, nb_tracefile;
dc877563 594
595 LttvTraceContext *tc;
596
dc877563 597 LttvTracefileContext *tfc;
598
dc877563 599 /* Call all before_traceset, before_trace, and before_tracefile hooks.
600 For all qualifying tracefiles, seek to the start time, create a context,
601 read one event and insert in the pqueue based on the event time. */
602
308711e5 603 lttv_hooks_call(self->before, self);
604 nbi = lttv_traceset_number(self->ts);
2a2fa4f0 605 self->pqueue = g_tree_new(compare_tracefile);
dc877563 606
607 for(i = 0 ; i < nbi ; i++) {
308711e5 608 tc = self->traces[i];
dc877563 609
610 if(!lttv_hooks_call_check(tc->check, tc)) {
dc877563 611 lttv_hooks_call(tc->before, tc);
dbb7bb09 612 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
613 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 614
dbb7bb09 615 for(j = 0 ; j < nb_tracefile ; j++) {
616 tfc = tc->tracefiles[j];
dc877563 617
dc877563 618 if(!lttv_hooks_call_check(tfc->check, tfc)) {
dc877563 619 lttv_hooks_call(tfc->before, tfc);
620
a8c0f09d 621 if(tfc->e != NULL) {
622 if(tfc->timestamp.tv_sec < end.tv_sec ||
dbb7bb09 623 (tfc->timestamp.tv_sec == end.tv_sec &&
624 tfc->timestamp.tv_nsec <= end.tv_nsec)) {
f95bc830 625 g_tree_insert(self->pqueue, tfc, tfc);
a8c0f09d 626 }
dc877563 627 }
628 }
629 }
630 }
631 }
2a2fa4f0 632}
633
634
635guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
636 unsigned nb_events)
637{
638 GTree *pqueue = self->pqueue;
639
640 guint id;
641
642 LttvTraceContext *tc;
643
644 LttvTracefileContext *tfc;
645
646 LttEvent *event;
647
648 unsigned count = 0;
649
650 LttTime previous_timestamp = {0, 0};
dc877563 651
652 /* Get the next event from the pqueue, call its hooks,
653 reinsert in the pqueue the following event from the same tracefile
654 unless the tracefile is finished or the event is later than the
655 start time. */
656
ffd54a90 657 while(TRUE) {
dc877563 658 tfc = NULL;
659 g_tree_foreach(pqueue, get_first, &tfc);
a43d67ba 660 if(tfc == NULL)
661 {
662 self->e = event;
663 return count;
664 }
dc877563 665
308711e5 666 /* Have we reached the maximum number of events specified? However,
667 continue for all the events with the same time stamp (CHECK?). Then,
668 empty the queue and break from the loop. */
dc877563 669
2a2fa4f0 670 if(count >= nb_events &&
671 ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
a43d67ba 672 {
673 self->e = event;
674 return count;
675 }
2a2fa4f0 676
308711e5 677 previous_timestamp = tfc->timestamp;
678
679
680 /* Get the tracefile with an event for the smallest time found. If two
681 or more tracefiles have events for the same time, hope that lookup
682 and remove are consistent. */
270e7cc5 683
f95bc830 684 g_tree_remove(pqueue, tfc);
2a2fa4f0 685 count++;
dc877563 686
b445142a 687 if(!lttv_hooks_call(tfc->check_event, tfc)) {
cbe7c836 688 id = ltt_event_eventtype_id(tfc->e);
dc877563 689 lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
60b53e4f 690 lttv_hooks_call(tfc->before_event, tfc);
dc877563 691 lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
60b53e4f 692 lttv_hooks_call(tfc->after_event, tfc);
dc877563 693 }
694
695 event = ltt_tracefile_read(tfc->tf);
696 if(event != NULL) {
697 tfc->e = event;
ffd54a90 698 tfc->timestamp = ltt_event_time(event);
270e7cc5 699 if(tfc->timestamp.tv_sec < end.tv_sec ||
700 (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec))
f95bc830 701 g_tree_insert(pqueue, tfc, tfc);
dc877563 702 }
703 }
2a2fa4f0 704}
705
706
707void lttv_process_traceset_end(LttvTracesetContext *self)
708{
dbb7bb09 709 guint i, j, nbi, nb_tracefile;
2a2fa4f0 710
711 LttvTraceContext *tc;
712
713 LttvTracefileContext *tfc;
714
715 /* Call all after_traceset, after_trace, and after_tracefile hooks. */
dc877563 716
2a2fa4f0 717 nbi = lttv_traceset_number(self->ts);
dc877563 718
2a2fa4f0 719 for(i = 0 ; i < nbi ; i++) {
720 tc = self->traces[i];
dc877563 721
2a2fa4f0 722 /* The check hooks are called again to avoid memorizing the results
723 obtained at the beginning. CHECK if it poses a problem */
724
725 if(!lttv_hooks_call_check(tc->check, tc)) {
dbb7bb09 726 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
727 ltt_trace_per_cpu_tracefile_number(tc->t);
2a2fa4f0 728
dbb7bb09 729 for(j = 0 ; j < nb_tracefile ; j++) {
730 tfc = tc->tracefiles[j];
2a2fa4f0 731
732 if(!lttv_hooks_call_check(tfc->check, tfc)) {
733 lttv_hooks_call(tfc->after, tfc);
734 }
dc877563 735 }
2a2fa4f0 736 lttv_hooks_call(tc->after, tc);
dc877563 737 }
dc877563 738 }
308711e5 739 lttv_hooks_call(self->after, self);
dc877563 740
2a2fa4f0 741 /* Empty and free the pqueue */
dc877563 742
2a2fa4f0 743 while(TRUE){
744 tfc = NULL;
745 g_tree_foreach(self->pqueue, get_first, &tfc);
746 if(tfc == NULL) break;
747 g_tree_remove(self->pqueue, &(tfc->timestamp));
748 }
749 g_tree_destroy(self->pqueue);
750}
751
752
753void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
754 unsigned nb_events)
755{
756 lttv_process_traceset_begin(self, end);
757 lttv_process_traceset_middle(self, end, nb_events);
758 lttv_process_traceset_end(self);
dc877563 759}
b445142a 760
308711e5 761
762void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
763{
dbb7bb09 764 guint i, nb_tracefile;
308711e5 765
766 LttvTracefileContext *tfc;
767
768 LttEvent *event;
769
dbb7bb09 770 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
771 ltt_trace_per_cpu_tracefile_number(self->t);
308711e5 772
dbb7bb09 773 for(i = 0 ; i < nb_tracefile ; i++) {
774 tfc = self->tracefiles[i];
308711e5 775 ltt_tracefile_seek_time(tfc->tf, start);
776 event = ltt_tracefile_read(tfc->tf);
777 tfc->e = event;
778 if(event != NULL) tfc->timestamp = ltt_event_time(event);
779 }
780}
781
782
783void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
784{
785 guint i, nb_trace;
786
787 LttvTraceContext *tc;
788
789 nb_trace = lttv_traceset_number(self->ts);
790 for(i = 0 ; i < nb_trace ; i++) {
791 tc = self->traces[i];
792 lttv_process_trace_seek_time(tc, start);
793 }
794}
795
796
b445142a 797static LttField *
798find_field(LttEventType *et, const char *field)
799{
800 LttType *t;
801
802 LttField *f;
803
804 guint i, nb;
805
806 char *name;
807
808 if(field == NULL) return NULL;
809
810 f = ltt_eventtype_field(et);
811 t = ltt_eventtype_type(et);
812 g_assert(ltt_type_class(t) == LTT_STRUCT);
813 nb = ltt_type_member_number(t);
814 for(i = 0 ; i < nb ; i++) {
815 ltt_type_member_type(t, i, &name);
816 if(strcmp(name, field) == 0) break;
817 }
818 g_assert(i < nb);
819 return ltt_field_member(f, i);
820}
821
822
823void
824lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
825 char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
826{
827 LttFacility *f;
828
829 LttEventType *et;
830
831 guint nb, pos, i;
832
833 char *name;
834
835 nb = ltt_trace_facility_find(t, facility, &pos);
836 if(nb < 1) g_error("No %s facility", facility);
837 f = ltt_trace_facility_get(t, pos);
838 et = ltt_facility_eventtype_get_by_name(f, event_type);
839 if(et == NULL) g_error("Event %s does not exist", event_type);
840
841 th->h = h;
842 th->id = ltt_eventtype_id(et);
843 th->f1 = find_field(et, field1);
844 th->f2 = find_field(et, field2);
845 th->f3 = find_field(et, field3);
846}
847
848
This page took 0.062552 seconds and 4 git commands to generate.