merge modifications for multiple viewer read at the same time, better expose handling...
[lttv.git] / ltt / branches / poly / lttv / lttv / tracecontext.c
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
19
20 #include <lttv/tracecontext.h>
21 #include <ltt/event.h>
22 #include <ltt/facility.h>
23 #include <ltt/trace.h>
24 #include <ltt/type.h>
25
26 void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
27 {
28 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
29 }
30
31
32 void lttv_context_fini(LttvTracesetContext *self)
33 {
34 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
35 }
36
37
38 LttvTracesetContext *
39 lttv_context_new_traceset_context(LttvTracesetContext *self)
40 {
41 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
42 }
43
44
45
46
47 LttvTraceContext *
48 lttv_context_new_trace_context(LttvTracesetContext *self)
49 {
50 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
51 }
52
53
54 LttvTracefileContext *
55 lttv_context_new_tracefile_context(LttvTracesetContext *self)
56 {
57 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
58 }
59
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 ***************************************************************************/
72 static 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
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
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
110
111 static void
112 init(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
120 LttTime null_time = {0, 0};
121
122 nb_trace = lttv_traceset_number(ts);
123 self->ts = ts;
124 self->traces = g_new(LttvTraceContext *, nb_trace);
125 self->before = lttv_hooks_new();
126 self->after = lttv_hooks_new();
127 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
128 self->ts_a = lttv_traceset_attribute(ts);
129 for(i = 0 ; i < nb_trace ; i++) {
130 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
131 self->traces[i] = tc;
132
133 tc->ts_context = self;
134 tc->index = i;
135 tc->vt = lttv_traceset_get(ts, i);
136 tc->t = lttv_trace(tc->vt);
137 tc->check = lttv_hooks_new();
138 tc->before = lttv_hooks_new();
139 tc->after = lttv_hooks_new();
140 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
141 tc->t_a = lttv_trace_attribute(tc->vt);
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;
145 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
146
147 for(j = 0 ; j < nb_tracefile ; j++) {
148 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
149 tc->tracefiles[j] = tfc;
150 tfc->index = j;
151
152 if(j < nb_control) {
153 tfc->control = TRUE;
154 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
155 }
156 else {
157 tfc->control = FALSE;
158 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
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();
169 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
170 }
171 }
172 lttv_process_traceset_seek_time(self, null_time);
173 /*CHECK why dynamically allocate the time span... and the casing is wroNg*/
174 self->Time_Span = g_new(TimeInterval,1);
175 lttv_traceset_context_compute_time_span(self, self->Time_Span);
176 self->e = NULL;
177 }
178
179
180 void fini(LttvTracesetContext *self)
181 {
182 guint i, j, nb_trace, nb_tracefile;
183
184 LttvTraceContext *tc;
185
186 LttvTracefileContext *tfc;
187
188 LttvTraceset *ts = self->ts;
189
190 g_free(self->Time_Span);
191
192 lttv_hooks_destroy(self->before);
193 lttv_hooks_destroy(self->after);
194 //FIXME : segfault
195 g_object_unref(self->a);
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);
205 g_object_unref(tc->a);
206
207 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
208 ltt_trace_per_cpu_tracefile_number(tc->t);
209
210 for(j = 0 ; j < nb_tracefile ; j++) {
211 tfc = tc->tracefiles[j];
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);
220 g_object_unref(tfc->a);
221 g_object_unref(tfc);
222 }
223 g_free(tc->tracefiles);
224 g_object_unref(tc);
225 }
226 g_free(self->traces);
227 }
228
229
230 void 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,
236 LttvHooks *check_tracefile,
237 LttvHooks *before_tracefile,
238 LttvHooks *after_tracefile,
239 LttvHooks *check_event,
240 LttvHooks *before_event,
241 LttvHooks *after_event)
242 {
243 LttvTraceset *ts = self->ts;
244
245 guint i, j, nb_trace, nb_tracefile;
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);
262 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
263 ltt_trace_per_cpu_tracefile_number(tc->t);
264
265 for(j = 0 ; j < nb_tracefile ; j++) {
266 tfc = tc->tracefiles[j];
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
278 void 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,
284 LttvHooks *check_tracefile,
285 LttvHooks *before_tracefile,
286 LttvHooks *after_tracefile,
287 LttvHooks *check_event,
288 LttvHooks *before_event,
289 LttvHooks *after_event)
290 {
291 LttvTraceset *ts = self->ts;
292
293 guint i, j, nb_trace, nb_tracefile;
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);
310 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
311 ltt_trace_per_cpu_tracefile_number(tc->t);
312
313 for(j = 0 ; j < nb_tracefile ; j++) {
314 tfc = tc->tracefiles[j];
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
325 void 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
335 void 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
345 void 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
361 void 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
377 void 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
389 void 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 }
395
396 static LttvTracesetContext *
397 new_traceset_context(LttvTracesetContext *self)
398 {
399 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
400 }
401
402
403 static LttvTraceContext *
404 new_trace_context(LttvTracesetContext *self)
405 {
406 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
407 }
408
409
410 static LttvTracefileContext *
411 new_tracefile_context(LttvTracesetContext *self)
412 {
413 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
414 }
415
416
417 static void
418 traceset_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
424 static void
425 traceset_context_finalize (LttvTracesetContext *self)
426 {
427 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
428 ->finalize(G_OBJECT(self));
429 }
430
431
432 static void
433 traceset_context_class_init (LttvTracesetContextClass *klass)
434 {
435 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
436
437 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
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
446 GType
447 lttv_traceset_context_get_type(void)
448 {
449 static GType type = 0;
450 if (type == 0) {
451 static const GTypeInfo info = {
452 sizeof (LttvTracesetContextClass),
453 NULL, /* base_init */
454 NULL, /* base_finalize */
455 (GClassInitFunc) traceset_context_class_init, /* class_init */
456 NULL, /* class_finalize */
457 NULL, /* class_data */
458 sizeof (LttvTracesetContext),
459 0, /* n_preallocs */
460 (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
461 };
462
463 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
464 &info, 0);
465 }
466 return type;
467 }
468
469
470 static void
471 trace_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
477 static void
478 trace_context_finalize (LttvTraceContext *self)
479 {
480 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
481 finalize(G_OBJECT(self));
482 }
483
484
485 static void
486 trace_context_class_init (LttvTraceContextClass *klass)
487 {
488 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
489
490 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
491 }
492
493
494 GType
495 lttv_trace_context_get_type(void)
496 {
497 static GType type = 0;
498 if (type == 0) {
499 static const GTypeInfo info = {
500 sizeof (LttvTraceContextClass),
501 NULL, /* base_init */
502 NULL, /* base_finalize */
503 (GClassInitFunc) trace_context_class_init, /* class_init */
504 NULL, /* class_finalize */
505 NULL, /* class_data */
506 sizeof (LttvTraceContext),
507 0, /* n_preallocs */
508 (GInstanceInitFunc) trace_context_instance_init /* instance_init */
509 };
510
511 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
512 &info, 0);
513 }
514 return type;
515 }
516
517
518 static void
519 tracefile_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
525 static void
526 tracefile_context_finalize (LttvTracefileContext *self)
527 {
528 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
529 ->finalize(G_OBJECT(self));
530 }
531
532
533 static void
534 tracefile_context_class_init (LttvTracefileContextClass *klass)
535 {
536 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
537
538 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
539 }
540
541
542 GType
543 lttv_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;
563 }
564
565
566 gint compare_tracefile(gconstpointer a, gconstpointer b)
567 {
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);
582 }
583
584
585 gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
586 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
587 return TRUE;
588 }
589
590
591 void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
592 {
593 guint i, j, nbi, nb_tracefile;
594
595 LttvTraceContext *tc;
596
597 LttvTracefileContext *tfc;
598
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
603 lttv_hooks_call(self->before, self);
604 nbi = lttv_traceset_number(self->ts);
605 self->pqueue = g_tree_new(compare_tracefile);
606
607 for(i = 0 ; i < nbi ; i++) {
608 tc = self->traces[i];
609
610 if(!lttv_hooks_call_check(tc->check, tc)) {
611 lttv_hooks_call(tc->before, tc);
612 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
613 ltt_trace_per_cpu_tracefile_number(tc->t);
614
615 for(j = 0 ; j < nb_tracefile ; j++) {
616 tfc = tc->tracefiles[j];
617
618 if(!lttv_hooks_call_check(tfc->check, tfc)) {
619 lttv_hooks_call(tfc->before, tfc);
620
621 if(tfc->e != NULL) {
622 if(tfc->timestamp.tv_sec < end.tv_sec ||
623 (tfc->timestamp.tv_sec == end.tv_sec &&
624 tfc->timestamp.tv_nsec <= end.tv_nsec)) {
625 g_tree_insert(self->pqueue, tfc, tfc);
626 }
627 }
628 }
629 }
630 }
631 }
632 }
633
634
635 guint 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};
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
657 while(TRUE) {
658 tfc = NULL;
659 g_tree_foreach(pqueue, get_first, &tfc);
660 if(tfc == NULL)
661 {
662 self->e = event;
663 return count;
664 }
665
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. */
669
670 if(count >= nb_events &&
671 ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
672 {
673 self->e = event;
674 return count;
675 }
676
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. */
683
684 g_tree_remove(pqueue, tfc);
685 count++;
686
687 if(!lttv_hooks_call(tfc->check_event, tfc)) {
688 id = ltt_event_eventtype_id(tfc->e);
689 lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
690 lttv_hooks_call(tfc->before_event, tfc);
691 lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
692 lttv_hooks_call(tfc->after_event, tfc);
693 }
694
695 event = ltt_tracefile_read(tfc->tf);
696 if(event != NULL) {
697 tfc->e = event;
698 tfc->timestamp = ltt_event_time(event);
699 if(tfc->timestamp.tv_sec < end.tv_sec ||
700 (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec))
701 g_tree_insert(pqueue, tfc, tfc);
702 }
703 }
704 }
705
706
707 void lttv_process_traceset_end(LttvTracesetContext *self)
708 {
709 guint i, j, nbi, nb_tracefile;
710
711 LttvTraceContext *tc;
712
713 LttvTracefileContext *tfc;
714
715 /* Call all after_traceset, after_trace, and after_tracefile hooks. */
716
717 nbi = lttv_traceset_number(self->ts);
718
719 for(i = 0 ; i < nbi ; i++) {
720 tc = self->traces[i];
721
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)) {
726 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
727 ltt_trace_per_cpu_tracefile_number(tc->t);
728
729 for(j = 0 ; j < nb_tracefile ; j++) {
730 tfc = tc->tracefiles[j];
731
732 if(!lttv_hooks_call_check(tfc->check, tfc)) {
733 lttv_hooks_call(tfc->after, tfc);
734 }
735 }
736 lttv_hooks_call(tc->after, tc);
737 }
738 }
739 lttv_hooks_call(self->after, self);
740
741 /* Empty and free the pqueue */
742
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
753 void 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);
759 }
760
761
762 void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
763 {
764 guint i, nb_tracefile;
765
766 LttvTracefileContext *tfc;
767
768 LttEvent *event;
769
770 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
771 ltt_trace_per_cpu_tracefile_number(self->t);
772
773 for(i = 0 ; i < nb_tracefile ; i++) {
774 tfc = self->tracefiles[i];
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
783 void 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
797 static LttField *
798 find_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
823 void
824 lttv_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.057491 seconds and 4 git commands to generate.