Add reference counts to state and stats saved attributes. This way, the
[lttv.git] / ltt / branches / poly / lttv / main / processTrace.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
20#include <lttv/processTrace.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);
dc877563 176}
177
178
179void fini(LttvTracesetContext *self)
180{
dbb7bb09 181 guint i, j, nb_trace, nb_tracefile;
dc877563 182
183 LttvTraceContext *tc;
184
185 LttvTracefileContext *tfc;
186
ffd54a90 187 LttvTraceset *ts = self->ts;
dc877563 188
f7afe191 189 g_free(self->Time_Span);
190
dc877563 191 lttv_hooks_destroy(self->before);
192 lttv_hooks_destroy(self->after);
f7afe191 193 //FIXME : segfault
2061e03d 194 g_object_unref(self->a);
dc877563 195
196 nb_trace = lttv_traceset_number(ts);
197
198 for(i = 0 ; i < nb_trace ; i++) {
199 tc = self->traces[i];
200
201 lttv_hooks_destroy(tc->check);
202 lttv_hooks_destroy(tc->before);
203 lttv_hooks_destroy(tc->after);
ffd54a90 204 g_object_unref(tc->a);
dc877563 205
dbb7bb09 206 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
207 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 208
209 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 210 tfc = tc->tracefiles[j];
dc877563 211 lttv_hooks_destroy(tfc->check);
212 lttv_hooks_destroy(tfc->before);
213 lttv_hooks_destroy(tfc->after);
214 lttv_hooks_destroy(tfc->check_event);
215 lttv_hooks_destroy(tfc->before_event);
216 lttv_hooks_by_id_destroy(tfc->before_event_by_id);
217 lttv_hooks_destroy(tfc->after_event);
218 lttv_hooks_by_id_destroy(tfc->after_event_by_id);
ffd54a90 219 g_object_unref(tfc->a);
dc877563 220 g_object_unref(tfc);
221 }
dbb7bb09 222 g_free(tc->tracefiles);
dc877563 223 g_object_unref(tc);
224 }
225 g_free(self->traces);
226}
227
228
229void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
230 LttvHooks *before_traceset,
231 LttvHooks *after_traceset,
232 LttvHooks *check_trace,
233 LttvHooks *before_trace,
234 LttvHooks *after_trace,
ffd54a90 235 LttvHooks *check_tracefile,
236 LttvHooks *before_tracefile,
237 LttvHooks *after_tracefile,
dc877563 238 LttvHooks *check_event,
239 LttvHooks *before_event,
240 LttvHooks *after_event)
241{
242 LttvTraceset *ts = self->ts;
243
dbb7bb09 244 guint i, j, nb_trace, nb_tracefile;
dc877563 245
246 LttvTraceContext *tc;
247
248 LttvTracefileContext *tfc;
249
250 void *hook_data;
251
252 lttv_hooks_add_list(self->before, before_traceset);
253 lttv_hooks_add_list(self->after, after_traceset);
254 nb_trace = lttv_traceset_number(ts);
255
256 for(i = 0 ; i < nb_trace ; i++) {
257 tc = self->traces[i];
258 lttv_hooks_add_list(tc->check, check_trace);
259 lttv_hooks_add_list(tc->before, before_trace);
260 lttv_hooks_add_list(tc->after, after_trace);
dbb7bb09 261 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
262 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 263
264 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 265 tfc = tc->tracefiles[j];
dc877563 266 lttv_hooks_add_list(tfc->check, check_tracefile);
267 lttv_hooks_add_list(tfc->before, before_tracefile);
268 lttv_hooks_add_list(tfc->after, after_tracefile);
269 lttv_hooks_add_list(tfc->check_event, check_event);
270 lttv_hooks_add_list(tfc->before_event, before_event);
271 lttv_hooks_add_list(tfc->after_event, after_event);
272 }
273 }
274}
275
276
277void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
278 LttvHooks *before_traceset,
279 LttvHooks *after_traceset,
280 LttvHooks *check_trace,
281 LttvHooks *before_trace,
282 LttvHooks *after_trace,
ffd54a90 283 LttvHooks *check_tracefile,
284 LttvHooks *before_tracefile,
285 LttvHooks *after_tracefile,
dc877563 286 LttvHooks *check_event,
287 LttvHooks *before_event,
288 LttvHooks *after_event)
289{
290 LttvTraceset *ts = self->ts;
291
dbb7bb09 292 guint i, j, nb_trace, nb_tracefile;
dc877563 293
294 LttvTraceContext *tc;
295
296 LttvTracefileContext *tfc;
297
298 void *hook_data;
299
300 lttv_hooks_remove_list(self->before, before_traceset);
301 lttv_hooks_remove_list(self->after, after_traceset);
302 nb_trace = lttv_traceset_number(ts);
303
304 for(i = 0 ; i < nb_trace ; i++) {
305 tc = self->traces[i];
306 lttv_hooks_remove_list(tc->check, check_trace);
307 lttv_hooks_remove_list(tc->before, before_trace);
308 lttv_hooks_remove_list(tc->after, after_trace);
dbb7bb09 309 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
310 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 311
312 for(j = 0 ; j < nb_tracefile ; j++) {
dbb7bb09 313 tfc = tc->tracefiles[j];
dc877563 314 lttv_hooks_remove_list(tfc->check, check_tracefile);
315 lttv_hooks_remove_list(tfc->before, before_tracefile);
316 lttv_hooks_remove_list(tfc->after, after_tracefile);
317 lttv_hooks_remove_list(tfc->check_event, check_event);
318 lttv_hooks_remove_list(tfc->before_event, before_event);
319 lttv_hooks_remove_list(tfc->after_event, after_event);
320 }
321 }
322}
323
a8c0f09d 324void lttv_trace_context_add_hooks(LttvTraceContext *tc,
325 LttvHooks *check_trace,
326 LttvHooks *before_trace,
327 LttvHooks *after_trace)
328{
329 lttv_hooks_add_list(tc->check, check_trace);
330 lttv_hooks_add_list(tc->before, before_trace);
331 lttv_hooks_add_list(tc->after, after_trace);
332}
333
334void lttv_trace_context_remove_hooks(LttvTraceContext *tc,
335 LttvHooks *check_trace,
336 LttvHooks *before_trace,
337 LttvHooks *after_trace)
338{
339 lttv_hooks_remove_list(tc->check, check_trace);
340 lttv_hooks_remove_list(tc->before, before_trace);
341 lttv_hooks_remove_list(tc->after, after_trace);
342}
343
344void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc,
345 LttvHooks *check_tracefile,
346 LttvHooks *before_tracefile,
347 LttvHooks *after_tracefile,
348 LttvHooks *check_event,
349 LttvHooks *before_event,
350 LttvHooks *after_event)
351{
352 lttv_hooks_add_list(tfc->check, check_tracefile);
353 lttv_hooks_add_list(tfc->before, before_tracefile);
354 lttv_hooks_add_list(tfc->after, after_tracefile);
355 lttv_hooks_add_list(tfc->check_event, check_event);
356 lttv_hooks_add_list(tfc->before_event, before_event);
357 lttv_hooks_add_list(tfc->after_event, after_event);
358}
359
360void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc,
361 LttvHooks *check_tracefile,
362 LttvHooks *before_tracefile,
363 LttvHooks *after_tracefile,
364 LttvHooks *check_event,
365 LttvHooks *before_event,
366 LttvHooks *after_event)
367{
368 lttv_hooks_remove_list(tfc->check, check_tracefile);
369 lttv_hooks_remove_list(tfc->before, before_tracefile);
370 lttv_hooks_remove_list(tfc->after, after_tracefile);
371 lttv_hooks_remove_list(tfc->check_event, check_event);
372 lttv_hooks_remove_list(tfc->before_event, before_event);
373 lttv_hooks_remove_list(tfc->after_event, after_event);
374}
375
376void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
377 unsigned i,
378 LttvHooks *before_event_by_id,
379 LttvHooks *after_event_by_id)
380{
381 LttvHooks * h;
382 h = lttv_hooks_by_id_find(tfc->before_event_by_id, i);
383 lttv_hooks_add_list(h, before_event_by_id);
384 h = lttv_hooks_by_id_find(tfc->after_event_by_id, i);
385 lttv_hooks_add_list(h, after_event_by_id);
386}
387
388void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
389 unsigned i)
390{
391 lttv_hooks_by_id_remove(tfc->before_event_by_id, i);
392 lttv_hooks_by_id_remove(tfc->after_event_by_id, i);
393}
dc877563 394
ba576a78 395static LttvTracesetContext *
dc877563 396new_traceset_context(LttvTracesetContext *self)
397{
ffd54a90 398 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
dc877563 399}
400
401
ba576a78 402static LttvTraceContext *
dc877563 403new_trace_context(LttvTracesetContext *self)
404{
ffd54a90 405 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
dc877563 406}
407
408
ba576a78 409static LttvTracefileContext *
dc877563 410new_tracefile_context(LttvTracesetContext *self)
411{
ffd54a90 412 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
dc877563 413}
414
415
416static void
417traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
418{
419 /* Be careful of anything which would not work well with shallow copies */
420}
421
422
423static void
424traceset_context_finalize (LttvTracesetContext *self)
425{
b445142a 426 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
427 ->finalize(G_OBJECT(self));
dc877563 428}
429
430
431static void
432traceset_context_class_init (LttvTracesetContextClass *klass)
433{
434 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
435
ffd54a90 436 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
dc877563 437 klass->init = init;
438 klass->fini = fini;
439 klass->new_traceset_context = new_traceset_context;
440 klass->new_trace_context = new_trace_context;
441 klass->new_tracefile_context = new_tracefile_context;
442}
443
444
445GType
ffd54a90 446lttv_traceset_context_get_type(void)
dc877563 447{
448 static GType type = 0;
449 if (type == 0) {
450 static const GTypeInfo info = {
ffd54a90 451 sizeof (LttvTracesetContextClass),
dc877563 452 NULL, /* base_init */
453 NULL, /* base_finalize */
ffd54a90 454 (GClassInitFunc) traceset_context_class_init, /* class_init */
dc877563 455 NULL, /* class_finalize */
456 NULL, /* class_data */
ffd54a90 457 sizeof (LttvTracesetContext),
dc877563 458 0, /* n_preallocs */
ffd54a90 459 (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
dc877563 460 };
461
ffd54a90 462 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
dc877563 463 &info, 0);
464 }
465 return type;
466}
467
468
469static void
470trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
471{
472 /* Be careful of anything which would not work well with shallow copies */
473}
474
475
476static void
477trace_context_finalize (LttvTraceContext *self)
478{
b445142a 479 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
480 finalize(G_OBJECT(self));
dc877563 481}
482
483
484static void
485trace_context_class_init (LttvTraceContextClass *klass)
486{
487 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
488
ffd54a90 489 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
dc877563 490}
491
492
493GType
ffd54a90 494lttv_trace_context_get_type(void)
dc877563 495{
496 static GType type = 0;
497 if (type == 0) {
498 static const GTypeInfo info = {
ffd54a90 499 sizeof (LttvTraceContextClass),
dc877563 500 NULL, /* base_init */
501 NULL, /* base_finalize */
ffd54a90 502 (GClassInitFunc) trace_context_class_init, /* class_init */
dc877563 503 NULL, /* class_finalize */
504 NULL, /* class_data */
c6bc9cb9 505 sizeof (LttvTraceContext),
dc877563 506 0, /* n_preallocs */
ffd54a90 507 (GInstanceInitFunc) trace_context_instance_init /* instance_init */
dc877563 508 };
509
ffd54a90 510 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
dc877563 511 &info, 0);
512 }
513 return type;
514}
515
516
517static void
518tracefile_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
525tracefile_context_finalize (LttvTracefileContext *self)
526{
b445142a 527 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
528 ->finalize(G_OBJECT(self));
dc877563 529}
530
531
532static void
533tracefile_context_class_init (LttvTracefileContextClass *klass)
534{
535 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
536
ffd54a90 537 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
538}
539
540
541GType
542lttv_tracefile_context_get_type(void)
543{
544 static GType type = 0;
545 if (type == 0) {
546 static const GTypeInfo info = {
547 sizeof (LttvTracefileContextClass),
548 NULL, /* base_init */
549 NULL, /* base_finalize */
550 (GClassInitFunc) tracefile_context_class_init, /* class_init */
551 NULL, /* class_finalize */
552 NULL, /* class_data */
553 sizeof (LttvTracefileContext),
554 0, /* n_preallocs */
555 (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */
556 };
557
558 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
559 &info, 0);
560 }
561 return type;
dc877563 562}
563
564
ffd54a90 565gint compare_tracefile(gconstpointer a, gconstpointer b)
dc877563 566{
f95bc830 567 gint comparison;
568
569 LttvTracefileContext *trace_a = (LttvTracefileContext *)a;
570
571 LttvTracefileContext *trace_b = (LttvTracefileContext *)b;
572
573 if(trace_a == trace_b) return 0;
574 comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
575 if(comparison != 0) return comparison;
576 if(trace_a->index < trace_b->index) return -1;
577 else if(trace_a->index > trace_b->index) return 1;
578 if(trace_a->t_context->index < trace_b->t_context->index) return -1;
579 else if(trace_a->t_context->index > trace_b->t_context->index) return 1;
580 g_assert(FALSE);
dc877563 581}
582
583
584gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
585 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
586 return TRUE;
587}
588
589
2a2fa4f0 590void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
dc877563 591{
dbb7bb09 592 guint i, j, nbi, nb_tracefile;
dc877563 593
594 LttvTraceContext *tc;
595
dc877563 596 LttvTracefileContext *tfc;
597
dc877563 598 /* Call all before_traceset, before_trace, and before_tracefile hooks.
599 For all qualifying tracefiles, seek to the start time, create a context,
600 read one event and insert in the pqueue based on the event time. */
601
308711e5 602 lttv_hooks_call(self->before, self);
603 nbi = lttv_traceset_number(self->ts);
2a2fa4f0 604 self->pqueue = g_tree_new(compare_tracefile);
dc877563 605
606 for(i = 0 ; i < nbi ; i++) {
308711e5 607 tc = self->traces[i];
dc877563 608
609 if(!lttv_hooks_call_check(tc->check, tc)) {
dc877563 610 lttv_hooks_call(tc->before, tc);
dbb7bb09 611 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
612 ltt_trace_per_cpu_tracefile_number(tc->t);
dc877563 613
dbb7bb09 614 for(j = 0 ; j < nb_tracefile ; j++) {
615 tfc = tc->tracefiles[j];
dc877563 616
dc877563 617 if(!lttv_hooks_call_check(tfc->check, tfc)) {
dc877563 618 lttv_hooks_call(tfc->before, tfc);
619
a8c0f09d 620 if(tfc->e != NULL) {
621 if(tfc->timestamp.tv_sec < end.tv_sec ||
dbb7bb09 622 (tfc->timestamp.tv_sec == end.tv_sec &&
623 tfc->timestamp.tv_nsec <= end.tv_nsec)) {
f95bc830 624 g_tree_insert(self->pqueue, tfc, tfc);
a8c0f09d 625 }
dc877563 626 }
627 }
628 }
629 }
630 }
2a2fa4f0 631}
632
633
634guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
635 unsigned nb_events)
636{
637 GTree *pqueue = self->pqueue;
638
639 guint id;
640
641 LttvTraceContext *tc;
642
643 LttvTracefileContext *tfc;
644
645 LttEvent *event;
646
647 unsigned count = 0;
648
649 LttTime previous_timestamp = {0, 0};
dc877563 650
651 /* Get the next event from the pqueue, call its hooks,
652 reinsert in the pqueue the following event from the same tracefile
653 unless the tracefile is finished or the event is later than the
654 start time. */
655
ffd54a90 656 while(TRUE) {
dc877563 657 tfc = NULL;
658 g_tree_foreach(pqueue, get_first, &tfc);
2a2fa4f0 659 if(tfc == NULL) return count;
dc877563 660
308711e5 661 /* Have we reached the maximum number of events specified? However,
662 continue for all the events with the same time stamp (CHECK?). Then,
663 empty the queue and break from the loop. */
dc877563 664
2a2fa4f0 665 if(count >= nb_events &&
666 ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
667 return count;
668
308711e5 669 previous_timestamp = tfc->timestamp;
670
671
672 /* Get the tracefile with an event for the smallest time found. If two
673 or more tracefiles have events for the same time, hope that lookup
674 and remove are consistent. */
270e7cc5 675
f95bc830 676 g_tree_remove(pqueue, tfc);
2a2fa4f0 677 count++;
dc877563 678
b445142a 679 if(!lttv_hooks_call(tfc->check_event, tfc)) {
cbe7c836 680 id = ltt_event_eventtype_id(tfc->e);
dc877563 681 lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
60b53e4f 682 lttv_hooks_call(tfc->before_event, tfc);
dc877563 683 lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
60b53e4f 684 lttv_hooks_call(tfc->after_event, tfc);
dc877563 685 }
686
687 event = ltt_tracefile_read(tfc->tf);
688 if(event != NULL) {
689 tfc->e = event;
ffd54a90 690 tfc->timestamp = ltt_event_time(event);
270e7cc5 691 if(tfc->timestamp.tv_sec < end.tv_sec ||
692 (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec))
f95bc830 693 g_tree_insert(pqueue, tfc, tfc);
dc877563 694 }
695 }
2a2fa4f0 696}
697
698
699void lttv_process_traceset_end(LttvTracesetContext *self)
700{
dbb7bb09 701 guint i, j, nbi, nb_tracefile;
2a2fa4f0 702
703 LttvTraceContext *tc;
704
705 LttvTracefileContext *tfc;
706
707 /* Call all after_traceset, after_trace, and after_tracefile hooks. */
dc877563 708
2a2fa4f0 709 nbi = lttv_traceset_number(self->ts);
dc877563 710
2a2fa4f0 711 for(i = 0 ; i < nbi ; i++) {
712 tc = self->traces[i];
dc877563 713
2a2fa4f0 714 /* The check hooks are called again to avoid memorizing the results
715 obtained at the beginning. CHECK if it poses a problem */
716
717 if(!lttv_hooks_call_check(tc->check, tc)) {
dbb7bb09 718 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
719 ltt_trace_per_cpu_tracefile_number(tc->t);
2a2fa4f0 720
dbb7bb09 721 for(j = 0 ; j < nb_tracefile ; j++) {
722 tfc = tc->tracefiles[j];
2a2fa4f0 723
724 if(!lttv_hooks_call_check(tfc->check, tfc)) {
725 lttv_hooks_call(tfc->after, tfc);
726 }
dc877563 727 }
2a2fa4f0 728 lttv_hooks_call(tc->after, tc);
dc877563 729 }
dc877563 730 }
308711e5 731 lttv_hooks_call(self->after, self);
dc877563 732
2a2fa4f0 733 /* Empty and free the pqueue */
dc877563 734
2a2fa4f0 735 while(TRUE){
736 tfc = NULL;
737 g_tree_foreach(self->pqueue, get_first, &tfc);
738 if(tfc == NULL) break;
739 g_tree_remove(self->pqueue, &(tfc->timestamp));
740 }
741 g_tree_destroy(self->pqueue);
742}
743
744
745void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
746 unsigned nb_events)
747{
748 lttv_process_traceset_begin(self, end);
749 lttv_process_traceset_middle(self, end, nb_events);
750 lttv_process_traceset_end(self);
dc877563 751}
b445142a 752
308711e5 753
754void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
755{
dbb7bb09 756 guint i, nb_tracefile;
308711e5 757
758 LttvTracefileContext *tfc;
759
760 LttEvent *event;
761
dbb7bb09 762 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
763 ltt_trace_per_cpu_tracefile_number(self->t);
308711e5 764
dbb7bb09 765 for(i = 0 ; i < nb_tracefile ; i++) {
766 tfc = self->tracefiles[i];
308711e5 767 ltt_tracefile_seek_time(tfc->tf, start);
768 event = ltt_tracefile_read(tfc->tf);
769 tfc->e = event;
770 if(event != NULL) tfc->timestamp = ltt_event_time(event);
771 }
772}
773
774
775void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
776{
777 guint i, nb_trace;
778
779 LttvTraceContext *tc;
780
781 nb_trace = lttv_traceset_number(self->ts);
782 for(i = 0 ; i < nb_trace ; i++) {
783 tc = self->traces[i];
784 lttv_process_trace_seek_time(tc, start);
785 }
786}
787
788
b445142a 789static LttField *
790find_field(LttEventType *et, const char *field)
791{
792 LttType *t;
793
794 LttField *f;
795
796 guint i, nb;
797
798 char *name;
799
800 if(field == NULL) return NULL;
801
802 f = ltt_eventtype_field(et);
803 t = ltt_eventtype_type(et);
804 g_assert(ltt_type_class(t) == LTT_STRUCT);
805 nb = ltt_type_member_number(t);
806 for(i = 0 ; i < nb ; i++) {
807 ltt_type_member_type(t, i, &name);
808 if(strcmp(name, field) == 0) break;
809 }
810 g_assert(i < nb);
811 return ltt_field_member(f, i);
812}
813
814
815void
816lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
817 char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
818{
819 LttFacility *f;
820
821 LttEventType *et;
822
823 guint nb, pos, i;
824
825 char *name;
826
827 nb = ltt_trace_facility_find(t, facility, &pos);
828 if(nb < 1) g_error("No %s facility", facility);
829 f = ltt_trace_facility_get(t, pos);
830 et = ltt_facility_eventtype_get_by_name(f, event_type);
831 if(et == NULL) g_error("Event %s does not exist", event_type);
832
833 th->h = h;
834 th->id = ltt_eventtype_id(et);
835 th->f1 = find_field(et, field1);
836 th->f2 = find_field(et, field2);
837 th->f3 = find_field(et, field3);
838}
839
840
This page took 0.072981 seconds and 4 git commands to generate.