2 #include <lttv/processTrace.h>
5 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
7 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
11 void lttv_context_fini(LttvTracesetContext
*self
)
13 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
18 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
20 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
27 lttv_context_new_trace_context(LttvTracesetContext
*self
)
29 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
33 LttvTracefileContext
*
34 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
36 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
41 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
43 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
47 LttvTracefileContext
*tfc
;
49 nb_trace
= lttv_traceset_number(ts
);
51 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
52 self
->before
= lttv_hooks_new();
53 self
->after
= lttv_hooks_new();
54 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
55 for(i
= 0 ; i
< nb_trace
; i
++) {
56 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
59 tc
->ts_context
= self
;
61 tc
->t
= lttv_traceset_get(ts
, i
);
62 tc
->check
= lttv_hooks_new();
63 tc
->before
= lttv_hooks_new();
64 tc
->after
= lttv_hooks_new();
65 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
66 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
67 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
68 nb_tracefile
= nb_control
+ nb_per_cpu
;
69 tc
->control_tracefiles
= g_new(LttvTracefileContext
*, nb_control
);
70 tc
->per_cpu_tracefiles
= g_new(LttvTracefileContext
*, nb_per_cpu
);
72 for(j
= 0 ; j
< nb_tracefile
; j
++) {
73 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
75 tc
->control_tracefiles
[j
] = tfc
;
78 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
81 tc
->per_cpu_tracefiles
[j
- nb_control
] = tfc
;
83 tfc
->index
= j
- nb_control
;
84 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
87 tfc
->check
= lttv_hooks_new();
88 tfc
->before
= lttv_hooks_new();
89 tfc
->after
= lttv_hooks_new();
90 tfc
->check_event
= lttv_hooks_new();
91 tfc
->before_event
= lttv_hooks_new();
92 tfc
->before_event_by_id
= lttv_hooks_by_id_new();
93 tfc
->after_event
= lttv_hooks_new();
94 tfc
->after_event_by_id
= lttv_hooks_by_id_new();
95 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
101 void fini(LttvTracesetContext
*self
)
103 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
105 LttvTraceContext
*tc
;
107 LttvTracefileContext
*tfc
;
109 LttvTraceset
*ts
= self
->ts
;
111 lttv_hooks_destroy(self
->before
);
112 lttv_hooks_destroy(self
->after
);
113 g_object_unref(self
->a
);
115 nb_trace
= lttv_traceset_number(ts
);
117 for(i
= 0 ; i
< nb_trace
; i
++) {
118 tc
= self
->traces
[i
];
120 lttv_hooks_destroy(tc
->check
);
121 lttv_hooks_destroy(tc
->before
);
122 lttv_hooks_destroy(tc
->after
);
123 g_object_unref(tc
->a
);
125 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
126 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
127 nb_tracefile
= nb_control
+ nb_per_cpu
;
129 for(j
= 0 ; j
< nb_tracefile
; j
++) {
130 if(j
< nb_control
) tfc
= tc
->control_tracefiles
[j
];
131 else tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
133 lttv_hooks_destroy(tfc
->check
);
134 lttv_hooks_destroy(tfc
->before
);
135 lttv_hooks_destroy(tfc
->after
);
136 lttv_hooks_destroy(tfc
->check_event
);
137 lttv_hooks_destroy(tfc
->before_event
);
138 lttv_hooks_by_id_destroy(tfc
->before_event_by_id
);
139 lttv_hooks_destroy(tfc
->after_event
);
140 lttv_hooks_by_id_destroy(tfc
->after_event_by_id
);
141 g_object_unref(tfc
->a
);
144 g_free(tc
->control_tracefiles
);
145 g_free(tc
->per_cpu_tracefiles
);
148 g_free(self
->traces
);
152 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
153 LttvHooks
*before_traceset
,
154 LttvHooks
*after_traceset
,
155 LttvHooks
*check_trace
,
156 LttvHooks
*before_trace
,
157 LttvHooks
*after_trace
,
158 LttvHooks
*check_tracefile
,
159 LttvHooks
*before_tracefile
,
160 LttvHooks
*after_tracefile
,
161 LttvHooks
*check_event
,
162 LttvHooks
*before_event
,
163 LttvHooks
*after_event
)
165 LttvTraceset
*ts
= self
->ts
;
167 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
169 LttvTraceContext
*tc
;
171 LttvTracefileContext
*tfc
;
175 lttv_hooks_add_list(self
->before
, before_traceset
);
176 lttv_hooks_add_list(self
->after
, after_traceset
);
177 nb_trace
= lttv_traceset_number(ts
);
179 for(i
= 0 ; i
< nb_trace
; i
++) {
180 tc
= self
->traces
[i
];
181 lttv_hooks_add_list(tc
->check
, check_trace
);
182 lttv_hooks_add_list(tc
->before
, before_trace
);
183 lttv_hooks_add_list(tc
->after
, after_trace
);
184 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
185 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
186 nb_tracefile
= nb_control
+ nb_per_cpu
;
188 for(j
= 0 ; j
< nb_tracefile
; j
++) {
190 tfc
= tc
->control_tracefiles
[j
];
193 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
195 lttv_hooks_add_list(tfc
->check
, check_tracefile
);
196 lttv_hooks_add_list(tfc
->before
, before_tracefile
);
197 lttv_hooks_add_list(tfc
->after
, after_tracefile
);
198 lttv_hooks_add_list(tfc
->check_event
, check_event
);
199 lttv_hooks_add_list(tfc
->before_event
, before_event
);
200 lttv_hooks_add_list(tfc
->after_event
, after_event
);
206 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
207 LttvHooks
*before_traceset
,
208 LttvHooks
*after_traceset
,
209 LttvHooks
*check_trace
,
210 LttvHooks
*before_trace
,
211 LttvHooks
*after_trace
,
212 LttvHooks
*check_tracefile
,
213 LttvHooks
*before_tracefile
,
214 LttvHooks
*after_tracefile
,
215 LttvHooks
*check_event
,
216 LttvHooks
*before_event
,
217 LttvHooks
*after_event
)
219 LttvTraceset
*ts
= self
->ts
;
221 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
223 LttvTraceContext
*tc
;
225 LttvTracefileContext
*tfc
;
229 lttv_hooks_remove_list(self
->before
, before_traceset
);
230 lttv_hooks_remove_list(self
->after
, after_traceset
);
231 nb_trace
= lttv_traceset_number(ts
);
233 for(i
= 0 ; i
< nb_trace
; i
++) {
234 tc
= self
->traces
[i
];
235 lttv_hooks_remove_list(tc
->check
, check_trace
);
236 lttv_hooks_remove_list(tc
->before
, before_trace
);
237 lttv_hooks_remove_list(tc
->after
, after_trace
);
238 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
239 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
240 nb_tracefile
= nb_control
+ nb_per_cpu
;
242 for(j
= 0 ; j
< nb_tracefile
; j
++) {
244 tfc
= tc
->control_tracefiles
[j
];
247 tfc
= tc
->per_cpu_tracefiles
[j
-nb_control
];
249 lttv_hooks_remove_list(tfc
->check
, check_tracefile
);
250 lttv_hooks_remove_list(tfc
->before
, before_tracefile
);
251 lttv_hooks_remove_list(tfc
->after
, after_tracefile
);
252 lttv_hooks_remove_list(tfc
->check_event
, check_event
);
253 lttv_hooks_remove_list(tfc
->before_event
, before_event
);
254 lttv_hooks_remove_list(tfc
->after_event
, after_event
);
260 static LttvTracesetContext
*
261 new_traceset_context(LttvTracesetContext
*self
)
263 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
267 static LttvTraceContext
*
268 new_trace_context(LttvTracesetContext
*self
)
270 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
274 static LttvTracefileContext
*
275 new_tracefile_context(LttvTracesetContext
*self
)
277 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
282 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
284 /* Be careful of anything which would not work well with shallow copies */
289 traceset_context_finalize (LttvTracesetContext
*self
)
291 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_CONTEXT_GET_CLASS(self
)))->finalize(G_OBJECT(self
));
296 traceset_context_class_init (LttvTracesetContextClass
*klass
)
298 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
300 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
303 klass
->new_traceset_context
= new_traceset_context
;
304 klass
->new_trace_context
= new_trace_context
;
305 klass
->new_tracefile_context
= new_tracefile_context
;
310 lttv_traceset_context_get_type(void)
312 static GType type
= 0;
314 static const GTypeInfo info
= {
315 sizeof (LttvTracesetContextClass
),
316 NULL
, /* base_init */
317 NULL
, /* base_finalize */
318 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
319 NULL
, /* class_finalize */
320 NULL
, /* class_data */
321 sizeof (LttvTracesetContext
),
323 (GInstanceInitFunc
) traceset_context_instance_init
/* instance_init */
326 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
334 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
336 /* Be careful of anything which would not work well with shallow copies */
341 trace_context_finalize (LttvTraceContext
*self
)
343 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_CONTEXT_GET_CLASS(self
)))->finalize(G_OBJECT(self
));
348 trace_context_class_init (LttvTraceContextClass
*klass
)
350 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
352 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
357 lttv_trace_context_get_type(void)
359 static GType type
= 0;
361 static const GTypeInfo info
= {
362 sizeof (LttvTraceContextClass
),
363 NULL
, /* base_init */
364 NULL
, /* base_finalize */
365 (GClassInitFunc
) trace_context_class_init
, /* class_init */
366 NULL
, /* class_finalize */
367 NULL
, /* class_data */
368 sizeof (LttvTraceContext
),
370 (GInstanceInitFunc
) trace_context_instance_init
/* instance_init */
373 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
381 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
383 /* Be careful of anything which would not work well with shallow copies */
388 tracefile_context_finalize (LttvTracefileContext
*self
)
390 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_CONTEXT_GET_CLASS(self
)))->finalize(G_OBJECT(self
));
395 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
397 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
399 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
404 lttv_tracefile_context_get_type(void)
406 static GType type
= 0;
408 static const GTypeInfo info
= {
409 sizeof (LttvTracefileContextClass
),
410 NULL
, /* base_init */
411 NULL
, /* base_finalize */
412 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
413 NULL
, /* class_finalize */
414 NULL
, /* class_data */
415 sizeof (LttvTracefileContext
),
417 (GInstanceInitFunc
) tracefile_context_instance_init
/* instance_init */
420 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
427 gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
429 if(((LttvTime
*)a
)->tv_sec
> ((LttvTime
*)b
)->tv_sec
) return 1;
430 if(((LttvTime
*)a
)->tv_sec
< ((LttvTime
*)b
)->tv_sec
) return -1;
431 if(((LttvTime
*)a
)->tv_nsec
> ((LttvTime
*)b
)->tv_nsec
) return 1;
432 if(((LttvTime
*)a
)->tv_nsec
< ((LttvTime
*)b
)->tv_nsec
) return -1;
437 gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
438 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
443 void lttv_process_trace(LttTime start
, LttTime end
, LttvTraceset
*traceset
,
444 LttvTracesetContext
*context
, unsigned maxNumEvents
)
446 GPtrArray
*traces
= g_ptr_array_new();
448 GPtrArray
*tracefiles
= g_ptr_array_new();
450 GTree
*pqueue
= g_tree_new(compare_tracefile
);
452 guint i
, j
, nbi
, nbj
, id
, nb_control
, nb_cpu
;
456 LttvTraceContext
*tc
;
458 LttTracefile
*tracefile
;
460 LttvTracefileContext
*tfc
;
464 LttTime preTimestamp
;
466 /* Call all before_traceset, before_trace, and before_tracefile hooks.
467 For all qualifying tracefiles, seek to the start time, create a context,
468 read one event and insert in the pqueue based on the event time. */
470 lttv_hooks_call(context
->before
, context
);
471 nbi
= lttv_traceset_number(traceset
);
472 // nbi = ltt_trace_set_number(traceset);
474 for(i
= 0 ; i
< nbi
; i
++) {
475 tc
= context
->traces
[i
];
478 if(!lttv_hooks_call_check(tc
->check
, tc
)) {
479 g_ptr_array_add(traces
, tc
);
480 lttv_hooks_call(tc
->before
, tc
);
481 nb_control
= ltt_trace_control_tracefile_number(trace
);
482 nb_cpu
= ltt_trace_per_cpu_tracefile_number(trace
);
483 nbj
= nb_control
+ nb_cpu
;
485 for(j
= 0 ; j
< nbj
; j
++) {
487 tfc
= tc
->control_tracefiles
[j
];
490 tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
495 if(!lttv_hooks_call_check(tfc
->check
, tfc
)) {
496 g_ptr_array_add(tracefiles
, tfc
);
497 lttv_hooks_call(tfc
->before
, tfc
);
499 ltt_tracefile_seek_time(tracefile
, start
);
500 event
= ltt_tracefile_read(tracefile
);
504 tfc
->timestamp
= ltt_event_time(event
);
505 g_tree_insert(pqueue
, &(tfc
->timestamp
), tfc
);
512 /* Get the next event from the pqueue, call its hooks,
513 reinsert in the pqueue the following event from the same tracefile
514 unless the tracefile is finished or the event is later than the
519 g_tree_foreach(pqueue
, get_first
, &tfc
);
520 if(tfc
== NULL
) break;
522 /* Get the tracefile with an event for the smallest time found. If two
523 or more tracefiles have events for the same time, hope that lookup
524 and remove are consistent. */
527 if(count
> maxNumEvents
){
528 if(tfc
->timestamp
.tv_sec
== preTimestamp
.tv_sec
&&
529 tfc
->timestamp
.tv_nsec
== preTimestamp
.tv_nsec
) {
534 g_tree_foreach(pqueue
, get_first
, &tfc
);
535 if(tfc
== NULL
) break;
536 g_tree_remove(pqueue
, &(tfc
->timestamp
));
541 preTimestamp
= tfc
->timestamp
;
543 tfc
= g_tree_lookup(pqueue
, &(tfc
->timestamp
));
544 g_tree_remove(pqueue
, &(tfc
->timestamp
));
546 if(!lttv_hooks_call(tfc
->check_event
, context
)) {
547 id
= ltt_event_eventtype_id(tfc
->e
);
548 lttv_hooks_call(tfc
->before_event
, tfc
);
549 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->before_event_by_id
, id
), tfc
);
550 lttv_hooks_call(tfc
->after_event
, context
);
551 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->after_event_by_id
, id
), tfc
);
554 event
= ltt_tracefile_read(tfc
->tf
);
557 tfc
->timestamp
= ltt_event_time(event
);
558 if(tfc
->timestamp
.tv_sec
< end
.tv_sec
||
559 (tfc
->timestamp
.tv_sec
== end
.tv_sec
&& tfc
->timestamp
.tv_nsec
<= end
.tv_nsec
))
560 g_tree_insert(pqueue
, &(tfc
->timestamp
), tfc
);
564 /* Call all the after_tracefile, after_trace and after_traceset hooks. */
566 for(i
= 0, j
= 0 ; i
< traces
->len
; i
++) {
567 tc
= traces
->pdata
[i
];
568 while(j
< tracefiles
->len
) {
569 tfc
= tracefiles
->pdata
[j
];
571 if(tfc
->t_context
== tc
) {
572 lttv_hooks_call(tfc
->after
, tfc
);
577 lttv_hooks_call(tc
->after
, tc
);
580 g_assert(j
== tracefiles
->len
);
581 lttv_hooks_call(context
->after
, context
);
583 /* Free the traces, tracefiles and pqueue */
585 g_ptr_array_free(tracefiles
, TRUE
);
586 g_ptr_array_free(traces
, TRUE
);
587 g_tree_destroy(pqueue
);