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 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;
88 for(i
=0; i
<numTraces
;i
++){
92 ltt_trace_time_span_get(trace
, &s
, &e
);
95 Time_Span
->startTime
= s
;
96 Time_Span
->endTime
= e
;
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
;
112 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
114 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
116 LttvTraceContext
*tc
;
118 LttvTracefileContext
*tfc
;
120 LttTime null_time
= {0, 0};
122 nb_trace
= lttv_traceset_number(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
;
133 tc
->ts_context
= self
;
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
);
148 for(j
= 0 ; j
< nb_tracefile
; j
++) {
149 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
151 tc
->control_tracefiles
[j
] = tfc
;
154 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
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
);
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
);
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
);
181 void fini(LttvTracesetContext
*self
)
183 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
185 LttvTraceContext
*tc
;
187 LttvTracefileContext
*tfc
;
189 LttvTraceset
*ts
= self
->ts
;
191 g_free(self
->Time_Span
);
193 lttv_hooks_destroy(self
->before
);
194 lttv_hooks_destroy(self
->after
);
196 g_object_unref(self
->a
);
198 nb_trace
= lttv_traceset_number(ts
);
200 for(i
= 0 ; i
< nb_trace
; i
++) {
201 tc
= self
->traces
[i
];
203 lttv_hooks_destroy(tc
->check
);
204 lttv_hooks_destroy(tc
->before
);
205 lttv_hooks_destroy(tc
->after
);
206 g_object_unref(tc
->a
);
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
;
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
];
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
);
227 g_free(tc
->control_tracefiles
);
228 g_free(tc
->per_cpu_tracefiles
);
231 g_free(self
->traces
);
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
)
248 LttvTraceset
*ts
= self
->ts
;
250 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
252 LttvTraceContext
*tc
;
254 LttvTracefileContext
*tfc
;
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
);
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
;
271 for(j
= 0 ; j
< nb_tracefile
; j
++) {
273 tfc
= tc
->control_tracefiles
[j
];
276 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
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
);
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
)
302 LttvTraceset
*ts
= self
->ts
;
304 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
306 LttvTraceContext
*tc
;
308 LttvTracefileContext
*tfc
;
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
);
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
;
325 for(j
= 0 ; j
< nb_tracefile
; j
++) {
327 tfc
= tc
->control_tracefiles
[j
];
330 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
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
);
342 void lttv_trace_context_add_hooks(LttvTraceContext
*tc
,
343 LttvHooks
*check_trace
,
344 LttvHooks
*before_trace
,
345 LttvHooks
*after_trace
)
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
);
352 void lttv_trace_context_remove_hooks(LttvTraceContext
*tc
,
353 LttvHooks
*check_trace
,
354 LttvHooks
*before_trace
,
355 LttvHooks
*after_trace
)
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
);
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
)
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
);
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
)
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
);
394 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
396 LttvHooks
*before_event_by_id
,
397 LttvHooks
*after_event_by_id
)
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
);
406 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
409 lttv_hooks_by_id_remove(tfc
->before_event_by_id
, i
);
410 lttv_hooks_by_id_remove(tfc
->after_event_by_id
, i
);
413 static LttvTracesetContext
*
414 new_traceset_context(LttvTracesetContext
*self
)
416 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
420 static LttvTraceContext
*
421 new_trace_context(LttvTracesetContext
*self
)
423 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
427 static LttvTracefileContext
*
428 new_tracefile_context(LttvTracesetContext
*self
)
430 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
435 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
437 /* Be careful of anything which would not work well with shallow copies */
442 traceset_context_finalize (LttvTracesetContext
*self
)
444 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
445 ->finalize(G_OBJECT(self
));
450 traceset_context_class_init (LttvTracesetContextClass
*klass
)
452 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
454 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
457 klass
->new_traceset_context
= new_traceset_context
;
458 klass
->new_trace_context
= new_trace_context
;
459 klass
->new_tracefile_context
= new_tracefile_context
;
464 lttv_traceset_context_get_type(void)
466 static GType 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
),
477 (GInstanceInitFunc
) traceset_context_instance_init
/* instance_init */
480 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
488 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
490 /* Be careful of anything which would not work well with shallow copies */
495 trace_context_finalize (LttvTraceContext
*self
)
497 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
498 finalize(G_OBJECT(self
));
503 trace_context_class_init (LttvTraceContextClass
*klass
)
505 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
507 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
512 lttv_trace_context_get_type(void)
514 static GType 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
),
525 (GInstanceInitFunc
) trace_context_instance_init
/* instance_init */
528 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
536 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
538 /* Be careful of anything which would not work well with shallow copies */
543 tracefile_context_finalize (LttvTracefileContext
*self
)
545 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
546 ->finalize(G_OBJECT(self
));
551 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
553 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
555 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
560 lttv_tracefile_context_get_type(void)
562 static GType 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
),
573 (GInstanceInitFunc
) tracefile_context_instance_init
/* instance_init */
576 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
583 gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
585 return ltt_time_compare(*((LttTime
*)a
), *((LttTime
*)b
));
589 gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
590 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
595 void lttv_process_traceset_begin(LttvTracesetContext
*self
, LttTime end
)
597 guint i
, j
, nbi
, nbj
, nb_control
, nb_cpu
;
599 LttvTraceContext
*tc
;
601 LttvTracefileContext
*tfc
;
603 /* Call all before_traceset, before_trace, and before_tracefile hooks.
604 For all qualifying tracefiles, seek to the start time, create a context,
605 read one event and insert in the pqueue based on the event time. */
607 lttv_hooks_call(self
->before
, self
);
608 nbi
= lttv_traceset_number(self
->ts
);
609 self
->pqueue
= g_tree_new(compare_tracefile
);
611 for(i
= 0 ; i
< nbi
; i
++) {
612 tc
= self
->traces
[i
];
614 if(!lttv_hooks_call_check(tc
->check
, tc
)) {
615 lttv_hooks_call(tc
->before
, tc
);
616 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
617 nb_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
618 nbj
= nb_control
+ nb_cpu
;
620 for(j
= 0 ; j
< nbj
; j
++) {
622 tfc
= tc
->control_tracefiles
[j
];
625 tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
628 if(!lttv_hooks_call_check(tfc
->check
, tfc
)) {
629 lttv_hooks_call(tfc
->before
, tfc
);
632 if(tfc
->timestamp
.tv_sec
< end
.tv_sec
||
633 (tfc
->timestamp
.tv_sec
== end
.tv_sec
&& tfc
->timestamp
.tv_nsec
<= end
.tv_nsec
)){
634 g_tree_insert(self
->pqueue
, &(tfc
->timestamp
), tfc
);
644 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
, LttTime end
,
647 GTree
*pqueue
= self
->pqueue
;
651 LttvTraceContext
*tc
;
653 LttvTracefileContext
*tfc
;
659 LttTime previous_timestamp
= {0, 0};
661 /* Get the next event from the pqueue, call its hooks,
662 reinsert in the pqueue the following event from the same tracefile
663 unless the tracefile is finished or the event is later than the
668 g_tree_foreach(pqueue
, get_first
, &tfc
);
669 if(tfc
== NULL
) return count
;
671 /* Have we reached the maximum number of events specified? However,
672 continue for all the events with the same time stamp (CHECK?). Then,
673 empty the queue and break from the loop. */
675 if(count
>= nb_events
&&
676 ltt_time_compare(tfc
->timestamp
, previous_timestamp
) != 0)
679 previous_timestamp
= tfc
->timestamp
;
682 /* Get the tracefile with an event for the smallest time found. If two
683 or more tracefiles have events for the same time, hope that lookup
684 and remove are consistent. */
686 tfc
= g_tree_lookup(pqueue
, &(tfc
->timestamp
));
687 g_tree_remove(pqueue
, &(tfc
->timestamp
));
690 if(!lttv_hooks_call(tfc
->check_event
, tfc
)) {
691 id
= ltt_event_eventtype_id(tfc
->e
);
692 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->before_event_by_id
, id
), tfc
);
693 lttv_hooks_call(tfc
->before_event
, tfc
);
694 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->after_event_by_id
, id
), tfc
);
695 lttv_hooks_call(tfc
->after_event
, tfc
);
698 event
= ltt_tracefile_read(tfc
->tf
);
701 tfc
->timestamp
= ltt_event_time(event
);
702 if(tfc
->timestamp
.tv_sec
< end
.tv_sec
||
703 (tfc
->timestamp
.tv_sec
== end
.tv_sec
&& tfc
->timestamp
.tv_nsec
<= end
.tv_nsec
))
704 g_tree_insert(pqueue
, &(tfc
->timestamp
), tfc
);
710 void lttv_process_traceset_end(LttvTracesetContext
*self
)
712 guint i
, j
, nbi
, nbj
, nb_control
, nb_cpu
;
714 LttvTraceContext
*tc
;
716 LttvTracefileContext
*tfc
;
718 /* Call all after_traceset, after_trace, and after_tracefile hooks. */
720 nbi
= lttv_traceset_number(self
->ts
);
722 for(i
= 0 ; i
< nbi
; i
++) {
723 tc
= self
->traces
[i
];
725 /* The check hooks are called again to avoid memorizing the results
726 obtained at the beginning. CHECK if it poses a problem */
728 if(!lttv_hooks_call_check(tc
->check
, tc
)) {
729 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
730 nb_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
731 nbj
= nb_control
+ nb_cpu
;
733 for(j
= 0 ; j
< nbj
; j
++) {
735 tfc
= tc
->control_tracefiles
[j
];
738 tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
741 if(!lttv_hooks_call_check(tfc
->check
, tfc
)) {
742 lttv_hooks_call(tfc
->after
, tfc
);
745 lttv_hooks_call(tc
->after
, tc
);
748 lttv_hooks_call(self
->after
, self
);
750 /* Empty and free the pqueue */
754 g_tree_foreach(self
->pqueue
, get_first
, &tfc
);
755 if(tfc
== NULL
) break;
756 g_tree_remove(self
->pqueue
, &(tfc
->timestamp
));
758 g_tree_destroy(self
->pqueue
);
762 void lttv_process_traceset(LttvTracesetContext
*self
, LttTime end
,
765 lttv_process_traceset_begin(self
, end
);
766 lttv_process_traceset_middle(self
, end
, nb_events
);
767 lttv_process_traceset_end(self
);
771 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
773 guint i
, nb_control
, nb_per_cpu
, nb_tracefile
;
775 LttvTracefileContext
*tfc
;
779 nb_control
= ltt_trace_control_tracefile_number(self
->t
);
780 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(self
->t
);
781 nb_tracefile
= nb_control
+ nb_per_cpu
;
782 for(i
= 0 ; i
< nb_tracefile
; i
++) {
783 if(i
< nb_control
) tfc
= self
->control_tracefiles
[i
];
784 else tfc
= self
->per_cpu_tracefiles
[i
- nb_control
];
786 ltt_tracefile_seek_time(tfc
->tf
, start
);
787 event
= ltt_tracefile_read(tfc
->tf
);
789 if(event
!= NULL
) tfc
->timestamp
= ltt_event_time(event
);
794 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
798 LttvTraceContext
*tc
;
800 nb_trace
= lttv_traceset_number(self
->ts
);
801 for(i
= 0 ; i
< nb_trace
; i
++) {
802 tc
= self
->traces
[i
];
803 lttv_process_trace_seek_time(tc
, start
);
809 find_field(LttEventType
*et
, const char *field
)
819 if(field
== NULL
) return NULL
;
821 f
= ltt_eventtype_field(et
);
822 t
= ltt_eventtype_type(et
);
823 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
824 nb
= ltt_type_member_number(t
);
825 for(i
= 0 ; i
< nb
; i
++) {
826 ltt_type_member_type(t
, i
, &name
);
827 if(strcmp(name
, field
) == 0) break;
830 return ltt_field_member(f
, i
);
835 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
836 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
846 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
847 if(nb
< 1) g_error("No %s facility", facility
);
848 f
= ltt_trace_facility_get(t
, pos
);
849 et
= ltt_facility_eventtype_get_by_name(f
, event_type
);
850 if(et
== NULL
) g_error("Event %s does not exist", event_type
);
853 th
->id
= ltt_eventtype_id(et
);
854 th
->f1
= find_field(et
, field1
);
855 th
->f2
= find_field(et
, field2
);
856 th
->f3
= find_field(et
, field3
);