1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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;
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.
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,
20 #include <lttv/processTrace.h>
21 #include <ltt/event.h>
22 #include <ltt/facility.h>
23 #include <ltt/trace.h>
26 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
28 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
32 void lttv_context_fini(LttvTracesetContext
*self
)
34 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
39 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
41 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
48 lttv_context_new_trace_context(LttvTracesetContext
*self
)
50 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
54 LttvTracefileContext
*
55 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
57 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
60 /****************************************************************************
61 * lttv_traceset_context_compute_time_span
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
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
)
76 LttvTraceset
* traceset
= self
->ts
;
77 int numTraces
= lttv_traceset_number(traceset
);
83 for(i
=0; i
<numTraces
;i
++){
87 ltt_trace_time_span_get(trace
, &s
, &e
);
90 Time_Span
->startTime
= s
;
91 Time_Span
->endTime
= e
;
93 if(s
.tv_sec
< Time_Span
->startTime
.tv_sec
||
94 (s
.tv_sec
== Time_Span
->startTime
.tv_sec
95 && s
.tv_nsec
< Time_Span
->startTime
.tv_nsec
))
96 Time_Span
->startTime
= s
;
97 if(e
.tv_sec
> Time_Span
->endTime
.tv_sec
||
98 (e
.tv_sec
== Time_Span
->endTime
.tv_sec
&&
99 e
.tv_nsec
> Time_Span
->endTime
.tv_nsec
))
100 Time_Span
->endTime
= e
;
107 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
109 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
111 LttvTraceContext
*tc
;
113 LttvTracefileContext
*tfc
;
115 LttTime null_time
= {0, 0};
117 nb_trace
= lttv_traceset_number(ts
);
119 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
120 self
->before
= lttv_hooks_new();
121 self
->after
= lttv_hooks_new();
122 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
123 self
->ts_a
= lttv_traceset_attribute(ts
);
124 for(i
= 0 ; i
< nb_trace
; i
++) {
125 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
126 self
->traces
[i
] = tc
;
128 tc
->ts_context
= self
;
130 tc
->vt
= lttv_traceset_get(ts
, i
);
131 tc
->t
= lttv_trace(tc
->vt
);
132 tc
->check
= lttv_hooks_new();
133 tc
->before
= lttv_hooks_new();
134 tc
->after
= lttv_hooks_new();
135 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
136 tc
->t_a
= lttv_trace_attribute(tc
->vt
);
137 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
138 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
139 nb_tracefile
= nb_control
+ nb_per_cpu
;
140 tc
->control_tracefiles
= g_new(LttvTracefileContext
*, nb_control
);
141 tc
->per_cpu_tracefiles
= g_new(LttvTracefileContext
*, nb_per_cpu
);
143 for(j
= 0 ; j
< nb_tracefile
; j
++) {
144 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
146 tc
->control_tracefiles
[j
] = tfc
;
149 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
152 tc
->per_cpu_tracefiles
[j
- nb_control
] = tfc
;
153 tfc
->control
= FALSE
;
154 tfc
->index
= j
- nb_control
;
155 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
158 tfc
->check
= lttv_hooks_new();
159 tfc
->before
= lttv_hooks_new();
160 tfc
->after
= lttv_hooks_new();
161 tfc
->check_event
= lttv_hooks_new();
162 tfc
->before_event
= lttv_hooks_new();
163 tfc
->before_event_by_id
= lttv_hooks_by_id_new();
164 tfc
->after_event
= lttv_hooks_new();
165 tfc
->after_event_by_id
= lttv_hooks_by_id_new();
166 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
169 lttv_process_traceset_seek_time(self
, null_time
);
170 /*CHECK why dynamically allocate the time span... and the casing is wroNg*/
171 self
->Time_Span
= g_new(TimeInterval
,1);
172 lttv_traceset_context_compute_time_span(self
, self
->Time_Span
);
176 void fini(LttvTracesetContext
*self
)
178 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
180 LttvTraceContext
*tc
;
182 LttvTracefileContext
*tfc
;
184 LttvTraceset
*ts
= self
->ts
;
186 g_free(self
->Time_Span
);
188 lttv_hooks_destroy(self
->before
);
189 lttv_hooks_destroy(self
->after
);
191 g_object_unref(self
->a
);
193 nb_trace
= lttv_traceset_number(ts
);
195 for(i
= 0 ; i
< nb_trace
; i
++) {
196 tc
= self
->traces
[i
];
198 lttv_hooks_destroy(tc
->check
);
199 lttv_hooks_destroy(tc
->before
);
200 lttv_hooks_destroy(tc
->after
);
201 g_object_unref(tc
->a
);
203 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
204 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
205 nb_tracefile
= nb_control
+ nb_per_cpu
;
207 for(j
= 0 ; j
< nb_tracefile
; j
++) {
208 if(j
< nb_control
) tfc
= tc
->control_tracefiles
[j
];
209 else tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
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
);
222 g_free(tc
->control_tracefiles
);
223 g_free(tc
->per_cpu_tracefiles
);
226 g_free(self
->traces
);
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
)
243 LttvTraceset
*ts
= self
->ts
;
245 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
247 LttvTraceContext
*tc
;
249 LttvTracefileContext
*tfc
;
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
);
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_control
= ltt_trace_control_tracefile_number(tc
->t
);
263 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
264 nb_tracefile
= nb_control
+ nb_per_cpu
;
266 for(j
= 0 ; j
< nb_tracefile
; j
++) {
268 tfc
= tc
->control_tracefiles
[j
];
271 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
273 lttv_hooks_add_list(tfc
->check
, check_tracefile
);
274 lttv_hooks_add_list(tfc
->before
, before_tracefile
);
275 lttv_hooks_add_list(tfc
->after
, after_tracefile
);
276 lttv_hooks_add_list(tfc
->check_event
, check_event
);
277 lttv_hooks_add_list(tfc
->before_event
, before_event
);
278 lttv_hooks_add_list(tfc
->after_event
, after_event
);
284 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
285 LttvHooks
*before_traceset
,
286 LttvHooks
*after_traceset
,
287 LttvHooks
*check_trace
,
288 LttvHooks
*before_trace
,
289 LttvHooks
*after_trace
,
290 LttvHooks
*check_tracefile
,
291 LttvHooks
*before_tracefile
,
292 LttvHooks
*after_tracefile
,
293 LttvHooks
*check_event
,
294 LttvHooks
*before_event
,
295 LttvHooks
*after_event
)
297 LttvTraceset
*ts
= self
->ts
;
299 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
301 LttvTraceContext
*tc
;
303 LttvTracefileContext
*tfc
;
307 lttv_hooks_remove_list(self
->before
, before_traceset
);
308 lttv_hooks_remove_list(self
->after
, after_traceset
);
309 nb_trace
= lttv_traceset_number(ts
);
311 for(i
= 0 ; i
< nb_trace
; i
++) {
312 tc
= self
->traces
[i
];
313 lttv_hooks_remove_list(tc
->check
, check_trace
);
314 lttv_hooks_remove_list(tc
->before
, before_trace
);
315 lttv_hooks_remove_list(tc
->after
, after_trace
);
316 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
317 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
318 nb_tracefile
= nb_control
+ nb_per_cpu
;
320 for(j
= 0 ; j
< nb_tracefile
; j
++) {
322 tfc
= tc
->control_tracefiles
[j
];
325 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
327 lttv_hooks_remove_list(tfc
->check
, check_tracefile
);
328 lttv_hooks_remove_list(tfc
->before
, before_tracefile
);
329 lttv_hooks_remove_list(tfc
->after
, after_tracefile
);
330 lttv_hooks_remove_list(tfc
->check_event
, check_event
);
331 lttv_hooks_remove_list(tfc
->before_event
, before_event
);
332 lttv_hooks_remove_list(tfc
->after_event
, after_event
);
337 void lttv_trace_context_add_hooks(LttvTraceContext
*tc
,
338 LttvHooks
*check_trace
,
339 LttvHooks
*before_trace
,
340 LttvHooks
*after_trace
)
342 lttv_hooks_add_list(tc
->check
, check_trace
);
343 lttv_hooks_add_list(tc
->before
, before_trace
);
344 lttv_hooks_add_list(tc
->after
, after_trace
);
347 void lttv_trace_context_remove_hooks(LttvTraceContext
*tc
,
348 LttvHooks
*check_trace
,
349 LttvHooks
*before_trace
,
350 LttvHooks
*after_trace
)
352 lttv_hooks_remove_list(tc
->check
, check_trace
);
353 lttv_hooks_remove_list(tc
->before
, before_trace
);
354 lttv_hooks_remove_list(tc
->after
, after_trace
);
357 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*tfc
,
358 LttvHooks
*check_tracefile
,
359 LttvHooks
*before_tracefile
,
360 LttvHooks
*after_tracefile
,
361 LttvHooks
*check_event
,
362 LttvHooks
*before_event
,
363 LttvHooks
*after_event
)
365 lttv_hooks_add_list(tfc
->check
, check_tracefile
);
366 lttv_hooks_add_list(tfc
->before
, before_tracefile
);
367 lttv_hooks_add_list(tfc
->after
, after_tracefile
);
368 lttv_hooks_add_list(tfc
->check_event
, check_event
);
369 lttv_hooks_add_list(tfc
->before_event
, before_event
);
370 lttv_hooks_add_list(tfc
->after_event
, after_event
);
373 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*tfc
,
374 LttvHooks
*check_tracefile
,
375 LttvHooks
*before_tracefile
,
376 LttvHooks
*after_tracefile
,
377 LttvHooks
*check_event
,
378 LttvHooks
*before_event
,
379 LttvHooks
*after_event
)
381 lttv_hooks_remove_list(tfc
->check
, check_tracefile
);
382 lttv_hooks_remove_list(tfc
->before
, before_tracefile
);
383 lttv_hooks_remove_list(tfc
->after
, after_tracefile
);
384 lttv_hooks_remove_list(tfc
->check_event
, check_event
);
385 lttv_hooks_remove_list(tfc
->before_event
, before_event
);
386 lttv_hooks_remove_list(tfc
->after_event
, after_event
);
389 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
391 LttvHooks
*before_event_by_id
,
392 LttvHooks
*after_event_by_id
)
395 h
= lttv_hooks_by_id_find(tfc
->before_event_by_id
, i
);
396 lttv_hooks_add_list(h
, before_event_by_id
);
397 h
= lttv_hooks_by_id_find(tfc
->after_event_by_id
, i
);
398 lttv_hooks_add_list(h
, after_event_by_id
);
401 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
404 lttv_hooks_by_id_remove(tfc
->before_event_by_id
, i
);
405 lttv_hooks_by_id_remove(tfc
->after_event_by_id
, i
);
408 static LttvTracesetContext
*
409 new_traceset_context(LttvTracesetContext
*self
)
411 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
415 static LttvTraceContext
*
416 new_trace_context(LttvTracesetContext
*self
)
418 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
422 static LttvTracefileContext
*
423 new_tracefile_context(LttvTracesetContext
*self
)
425 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
430 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
432 /* Be careful of anything which would not work well with shallow copies */
437 traceset_context_finalize (LttvTracesetContext
*self
)
439 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
440 ->finalize(G_OBJECT(self
));
445 traceset_context_class_init (LttvTracesetContextClass
*klass
)
447 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
449 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
452 klass
->new_traceset_context
= new_traceset_context
;
453 klass
->new_trace_context
= new_trace_context
;
454 klass
->new_tracefile_context
= new_tracefile_context
;
459 lttv_traceset_context_get_type(void)
461 static GType type
= 0;
463 static const GTypeInfo info
= {
464 sizeof (LttvTracesetContextClass
),
465 NULL
, /* base_init */
466 NULL
, /* base_finalize */
467 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
468 NULL
, /* class_finalize */
469 NULL
, /* class_data */
470 sizeof (LttvTracesetContext
),
472 (GInstanceInitFunc
) traceset_context_instance_init
/* instance_init */
475 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
483 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
485 /* Be careful of anything which would not work well with shallow copies */
490 trace_context_finalize (LttvTraceContext
*self
)
492 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
493 finalize(G_OBJECT(self
));
498 trace_context_class_init (LttvTraceContextClass
*klass
)
500 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
502 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
507 lttv_trace_context_get_type(void)
509 static GType type
= 0;
511 static const GTypeInfo info
= {
512 sizeof (LttvTraceContextClass
),
513 NULL
, /* base_init */
514 NULL
, /* base_finalize */
515 (GClassInitFunc
) trace_context_class_init
, /* class_init */
516 NULL
, /* class_finalize */
517 NULL
, /* class_data */
518 sizeof (LttvTraceContext
),
520 (GInstanceInitFunc
) trace_context_instance_init
/* instance_init */
523 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
531 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
533 /* Be careful of anything which would not work well with shallow copies */
538 tracefile_context_finalize (LttvTracefileContext
*self
)
540 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
541 ->finalize(G_OBJECT(self
));
546 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
548 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
550 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
555 lttv_tracefile_context_get_type(void)
557 static GType type
= 0;
559 static const GTypeInfo info
= {
560 sizeof (LttvTracefileContextClass
),
561 NULL
, /* base_init */
562 NULL
, /* base_finalize */
563 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
564 NULL
, /* class_finalize */
565 NULL
, /* class_data */
566 sizeof (LttvTracefileContext
),
568 (GInstanceInitFunc
) tracefile_context_instance_init
/* instance_init */
571 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
578 gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
580 return ltt_time_compare(*((LttTime
*)a
), *((LttTime
*)b
));
584 gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
585 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
590 void lttv_process_traceset(LttvTracesetContext
*self
, LttTime end
,
591 unsigned maxNumEvents
)
593 GPtrArray
*traces
= g_ptr_array_new();
595 GPtrArray
*tracefiles
= g_ptr_array_new();
597 GTree
*pqueue
= g_tree_new(compare_tracefile
);
599 guint i
, j
, nbi
, nbj
, id
, nb_control
, nb_cpu
;
603 LttvTraceContext
*tc
;
605 LttTracefile
*tracefile
;
607 LttvTracefileContext
*tfc
;
613 LttTime previous_timestamp
= {0, 0};
615 /* Call all before_traceset, before_trace, and before_tracefile hooks.
616 For all qualifying tracefiles, seek to the start time, create a context,
617 read one event and insert in the pqueue based on the event time. */
619 lttv_hooks_call(self
->before
, self
);
620 nbi
= lttv_traceset_number(self
->ts
);
622 for(i
= 0 ; i
< nbi
; i
++) {
623 tc
= self
->traces
[i
];
626 if(!lttv_hooks_call_check(tc
->check
, tc
)) {
627 g_ptr_array_add(traces
, tc
);
628 lttv_hooks_call(tc
->before
, tc
);
629 nb_control
= ltt_trace_control_tracefile_number(trace
);
630 nb_cpu
= ltt_trace_per_cpu_tracefile_number(trace
);
631 nbj
= nb_control
+ nb_cpu
;
633 for(j
= 0 ; j
< nbj
; j
++) {
635 tfc
= tc
->control_tracefiles
[j
];
638 tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
643 if(!lttv_hooks_call_check(tfc
->check
, tfc
)) {
644 g_ptr_array_add(tracefiles
, tfc
);
645 lttv_hooks_call(tfc
->before
, tfc
);
648 if(tfc
->timestamp
.tv_sec
< end
.tv_sec
||
649 (tfc
->timestamp
.tv_sec
== end
.tv_sec
&& tfc
->timestamp
.tv_nsec
<= end
.tv_nsec
)){
650 g_tree_insert(pqueue
, &(tfc
->timestamp
), tfc
);
658 /* Get the next event from the pqueue, call its hooks,
659 reinsert in the pqueue the following event from the same tracefile
660 unless the tracefile is finished or the event is later than the
665 g_tree_foreach(pqueue
, get_first
, &tfc
);
666 if(tfc
== NULL
) break;
668 /* Have we reached the maximum number of events specified? However,
669 continue for all the events with the same time stamp (CHECK?). Then,
670 empty the queue and break from the loop. */
673 if(count
> maxNumEvents
){
674 if(tfc
->timestamp
.tv_sec
== previous_timestamp
.tv_sec
&&
675 tfc
->timestamp
.tv_nsec
== previous_timestamp
.tv_nsec
) {
680 g_tree_foreach(pqueue
, get_first
, &tfc
);
681 if(tfc
== NULL
) break;
682 g_tree_remove(pqueue
, &(tfc
->timestamp
));
687 previous_timestamp
= tfc
->timestamp
;
690 /* Get the tracefile with an event for the smallest time found. If two
691 or more tracefiles have events for the same time, hope that lookup
692 and remove are consistent. */
694 tfc
= g_tree_lookup(pqueue
, &(tfc
->timestamp
));
695 g_tree_remove(pqueue
, &(tfc
->timestamp
));
697 if(!lttv_hooks_call(tfc
->check_event
, tfc
)) {
698 id
= ltt_event_eventtype_id(tfc
->e
);
699 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->before_event_by_id
, id
), tfc
);
700 lttv_hooks_call(tfc
->before_event
, tfc
);
701 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->after_event_by_id
, id
), tfc
);
702 lttv_hooks_call(tfc
->after_event
, tfc
);
705 event
= ltt_tracefile_read(tfc
->tf
);
708 tfc
->timestamp
= ltt_event_time(event
);
709 if(tfc
->timestamp
.tv_sec
< end
.tv_sec
||
710 (tfc
->timestamp
.tv_sec
== end
.tv_sec
&& tfc
->timestamp
.tv_nsec
<= end
.tv_nsec
))
711 g_tree_insert(pqueue
, &(tfc
->timestamp
), tfc
);
715 /* Call all the after_tracefile, after_trace and after_traceset hooks. */
717 for(i
= 0, j
= 0 ; i
< traces
->len
; i
++) {
718 tc
= traces
->pdata
[i
];
719 while(j
< tracefiles
->len
) {
720 tfc
= tracefiles
->pdata
[j
];
722 if(tfc
->t_context
== tc
) {
723 lttv_hooks_call(tfc
->after
, tfc
);
728 lttv_hooks_call(tc
->after
, tc
);
731 g_assert(j
== tracefiles
->len
);
732 lttv_hooks_call(self
->after
, self
);
734 /* Free the traces, tracefiles and pqueue */
736 g_ptr_array_free(tracefiles
, TRUE
);
737 g_ptr_array_free(traces
, TRUE
);
738 g_tree_destroy(pqueue
);
742 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
744 guint i
, nb_control
, nb_per_cpu
, nb_tracefile
;
746 LttvTracefileContext
*tfc
;
750 nb_control
= ltt_trace_control_tracefile_number(self
->t
);
751 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(self
->t
);
752 nb_tracefile
= nb_control
+ nb_per_cpu
;
753 for(i
= 0 ; i
< nb_tracefile
; i
++) {
754 if(i
< nb_control
) tfc
= self
->control_tracefiles
[i
];
755 else tfc
= self
->per_cpu_tracefiles
[i
- nb_control
];
757 ltt_tracefile_seek_time(tfc
->tf
, start
);
758 event
= ltt_tracefile_read(tfc
->tf
);
760 if(event
!= NULL
) tfc
->timestamp
= ltt_event_time(event
);
765 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
769 LttvTraceContext
*tc
;
771 nb_trace
= lttv_traceset_number(self
->ts
);
772 for(i
= 0 ; i
< nb_trace
; i
++) {
773 tc
= self
->traces
[i
];
774 lttv_process_trace_seek_time(tc
, start
);
780 find_field(LttEventType
*et
, const char *field
)
790 if(field
== NULL
) return NULL
;
792 f
= ltt_eventtype_field(et
);
793 t
= ltt_eventtype_type(et
);
794 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
795 nb
= ltt_type_member_number(t
);
796 for(i
= 0 ; i
< nb
; i
++) {
797 ltt_type_member_type(t
, i
, &name
);
798 if(strcmp(name
, field
) == 0) break;
801 return ltt_field_member(f
, i
);
806 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
807 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
817 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
818 if(nb
< 1) g_error("No %s facility", facility
);
819 f
= ltt_trace_facility_get(t
, pos
);
820 et
= ltt_facility_eventtype_get_by_name(f
, event_type
);
821 if(et
== NULL
) g_error("Event %s does not exist", event_type
);
824 th
->id
= ltt_eventtype_id(et
);
825 th
->f1
= find_field(et
, field1
);
826 th
->f2
= find_field(et
, field2
);
827 th
->f3
= find_field(et
, field3
);