Moving files around to get rid of the shared include tree. Some other
[lttv.git] / ltt / branches / poly / lttv / lttv / processTrace.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 }
177
178
179 void fini(LttvTracesetContext *self)
180 {
181 guint i, j, nb_trace, nb_tracefile;
182
183 LttvTraceContext *tc;
184
185 LttvTracefileContext *tfc;
186
187 LttvTraceset *ts = self->ts;
188
189 g_free(self->Time_Span);
190
191 lttv_hooks_destroy(self->before);
192 lttv_hooks_destroy(self->after);
193 //FIXME : segfault
194 g_object_unref(self->a);
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);
204 g_object_unref(tc->a);
205
206 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
207 ltt_trace_per_cpu_tracefile_number(tc->t);
208
209 for(j = 0 ; j < nb_tracefile ; j++) {
210 tfc = tc->tracefiles[j];
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);
219 g_object_unref(tfc->a);
220 g_object_unref(tfc);
221 }
222 g_free(tc->tracefiles);
223 g_object_unref(tc);
224 }
225 g_free(self->traces);
226 }
227
228
229 void 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,
235 LttvHooks *check_tracefile,
236 LttvHooks *before_tracefile,
237 LttvHooks *after_tracefile,
238 LttvHooks *check_event,
239 LttvHooks *before_event,
240 LttvHooks *after_event)
241 {
242 LttvTraceset *ts = self->ts;
243
244 guint i, j, nb_trace, nb_tracefile;
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);
261 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
262 ltt_trace_per_cpu_tracefile_number(tc->t);
263
264 for(j = 0 ; j < nb_tracefile ; j++) {
265 tfc = tc->tracefiles[j];
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
277 void 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,
283 LttvHooks *check_tracefile,
284 LttvHooks *before_tracefile,
285 LttvHooks *after_tracefile,
286 LttvHooks *check_event,
287 LttvHooks *before_event,
288 LttvHooks *after_event)
289 {
290 LttvTraceset *ts = self->ts;
291
292 guint i, j, nb_trace, nb_tracefile;
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);
309 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
310 ltt_trace_per_cpu_tracefile_number(tc->t);
311
312 for(j = 0 ; j < nb_tracefile ; j++) {
313 tfc = tc->tracefiles[j];
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
324 void 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
334 void 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
344 void 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
360 void 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
376 void 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
388 void 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 }
394
395 static LttvTracesetContext *
396 new_traceset_context(LttvTracesetContext *self)
397 {
398 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
399 }
400
401
402 static LttvTraceContext *
403 new_trace_context(LttvTracesetContext *self)
404 {
405 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
406 }
407
408
409 static LttvTracefileContext *
410 new_tracefile_context(LttvTracesetContext *self)
411 {
412 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
413 }
414
415
416 static void
417 traceset_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
423 static void
424 traceset_context_finalize (LttvTracesetContext *self)
425 {
426 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
427 ->finalize(G_OBJECT(self));
428 }
429
430
431 static void
432 traceset_context_class_init (LttvTracesetContextClass *klass)
433 {
434 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
435
436 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
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
445 GType
446 lttv_traceset_context_get_type(void)
447 {
448 static GType type = 0;
449 if (type == 0) {
450 static const GTypeInfo info = {
451 sizeof (LttvTracesetContextClass),
452 NULL, /* base_init */
453 NULL, /* base_finalize */
454 (GClassInitFunc) traceset_context_class_init, /* class_init */
455 NULL, /* class_finalize */
456 NULL, /* class_data */
457 sizeof (LttvTracesetContext),
458 0, /* n_preallocs */
459 (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
460 };
461
462 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
463 &info, 0);
464 }
465 return type;
466 }
467
468
469 static void
470 trace_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
476 static void
477 trace_context_finalize (LttvTraceContext *self)
478 {
479 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
480 finalize(G_OBJECT(self));
481 }
482
483
484 static void
485 trace_context_class_init (LttvTraceContextClass *klass)
486 {
487 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
488
489 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
490 }
491
492
493 GType
494 lttv_trace_context_get_type(void)
495 {
496 static GType type = 0;
497 if (type == 0) {
498 static const GTypeInfo info = {
499 sizeof (LttvTraceContextClass),
500 NULL, /* base_init */
501 NULL, /* base_finalize */
502 (GClassInitFunc) trace_context_class_init, /* class_init */
503 NULL, /* class_finalize */
504 NULL, /* class_data */
505 sizeof (LttvTraceContext),
506 0, /* n_preallocs */
507 (GInstanceInitFunc) trace_context_instance_init /* instance_init */
508 };
509
510 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
511 &info, 0);
512 }
513 return type;
514 }
515
516
517 static void
518 tracefile_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
524 static void
525 tracefile_context_finalize (LttvTracefileContext *self)
526 {
527 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
528 ->finalize(G_OBJECT(self));
529 }
530
531
532 static void
533 tracefile_context_class_init (LttvTracefileContextClass *klass)
534 {
535 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
536
537 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
538 }
539
540
541 GType
542 lttv_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;
562 }
563
564
565 gint compare_tracefile(gconstpointer a, gconstpointer b)
566 {
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);
581 }
582
583
584 gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
585 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
586 return TRUE;
587 }
588
589
590 void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
591 {
592 guint i, j, nbi, nb_tracefile;
593
594 LttvTraceContext *tc;
595
596 LttvTracefileContext *tfc;
597
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
602 lttv_hooks_call(self->before, self);
603 nbi = lttv_traceset_number(self->ts);
604 self->pqueue = g_tree_new(compare_tracefile);
605
606 for(i = 0 ; i < nbi ; i++) {
607 tc = self->traces[i];
608
609 if(!lttv_hooks_call_check(tc->check, tc)) {
610 lttv_hooks_call(tc->before, tc);
611 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
612 ltt_trace_per_cpu_tracefile_number(tc->t);
613
614 for(j = 0 ; j < nb_tracefile ; j++) {
615 tfc = tc->tracefiles[j];
616
617 if(!lttv_hooks_call_check(tfc->check, tfc)) {
618 lttv_hooks_call(tfc->before, tfc);
619
620 if(tfc->e != NULL) {
621 if(tfc->timestamp.tv_sec < end.tv_sec ||
622 (tfc->timestamp.tv_sec == end.tv_sec &&
623 tfc->timestamp.tv_nsec <= end.tv_nsec)) {
624 g_tree_insert(self->pqueue, tfc, tfc);
625 }
626 }
627 }
628 }
629 }
630 }
631 }
632
633
634 guint 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};
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
656 while(TRUE) {
657 tfc = NULL;
658 g_tree_foreach(pqueue, get_first, &tfc);
659 if(tfc == NULL) return count;
660
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. */
664
665 if(count >= nb_events &&
666 ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
667 return count;
668
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. */
675
676 g_tree_remove(pqueue, tfc);
677 count++;
678
679 if(!lttv_hooks_call(tfc->check_event, tfc)) {
680 id = ltt_event_eventtype_id(tfc->e);
681 lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
682 lttv_hooks_call(tfc->before_event, tfc);
683 lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
684 lttv_hooks_call(tfc->after_event, tfc);
685 }
686
687 event = ltt_tracefile_read(tfc->tf);
688 if(event != NULL) {
689 tfc->e = event;
690 tfc->timestamp = ltt_event_time(event);
691 if(tfc->timestamp.tv_sec < end.tv_sec ||
692 (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec))
693 g_tree_insert(pqueue, tfc, tfc);
694 }
695 }
696 }
697
698
699 void lttv_process_traceset_end(LttvTracesetContext *self)
700 {
701 guint i, j, nbi, nb_tracefile;
702
703 LttvTraceContext *tc;
704
705 LttvTracefileContext *tfc;
706
707 /* Call all after_traceset, after_trace, and after_tracefile hooks. */
708
709 nbi = lttv_traceset_number(self->ts);
710
711 for(i = 0 ; i < nbi ; i++) {
712 tc = self->traces[i];
713
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)) {
718 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
719 ltt_trace_per_cpu_tracefile_number(tc->t);
720
721 for(j = 0 ; j < nb_tracefile ; j++) {
722 tfc = tc->tracefiles[j];
723
724 if(!lttv_hooks_call_check(tfc->check, tfc)) {
725 lttv_hooks_call(tfc->after, tfc);
726 }
727 }
728 lttv_hooks_call(tc->after, tc);
729 }
730 }
731 lttv_hooks_call(self->after, self);
732
733 /* Empty and free the pqueue */
734
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
745 void 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);
751 }
752
753
754 void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
755 {
756 guint i, nb_tracefile;
757
758 LttvTracefileContext *tfc;
759
760 LttEvent *event;
761
762 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
763 ltt_trace_per_cpu_tracefile_number(self->t);
764
765 for(i = 0 ; i < nb_tracefile ; i++) {
766 tfc = self->tracefiles[i];
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
775 void 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
789 static LttField *
790 find_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
815 void
816 lttv_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.045602 seconds and 4 git commands to generate.