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