dc877563 |
1 | |
2 | #include <lttv/processTrace.h> |
ffd54a90 |
3 | #include <ltt/event.h> |
b445142a |
4 | #include <ltt/facility.h> |
dc877563 |
5 | |
ffd54a90 |
6 | void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) |
dc877563 |
7 | { |
ffd54a90 |
8 | LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); |
dc877563 |
9 | } |
10 | |
11 | |
12 | void lttv_context_fini(LttvTracesetContext *self) |
13 | { |
14 | LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self); |
15 | } |
16 | |
17 | |
18 | LttvTracesetContext * |
19 | lttv_context_new_traceset_context(LttvTracesetContext *self) |
20 | { |
21 | return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self); |
22 | } |
23 | |
24 | |
25 | |
26 | |
27 | LttvTraceContext * |
28 | lttv_context_new_trace_context(LttvTracesetContext *self) |
29 | { |
30 | return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); |
31 | } |
32 | |
33 | |
34 | LttvTracefileContext * |
35 | lttv_context_new_tracefile_context(LttvTracesetContext *self) |
36 | { |
c6bc9cb9 |
37 | return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); |
dc877563 |
38 | } |
39 | |
f7afe191 |
40 | /**************************************************************************** |
41 | * lttv_traceset_context_compute_time_span |
42 | * |
43 | * Keep the Time_Span is sync with on the fly addition and removal of traces |
44 | * in a trace set. It must be called each time a trace is added/removed from |
45 | * the traceset. It could be more efficient to call it only once a bunch |
46 | * of traces are loaded, but the calculation is not long, so it's not |
47 | * critical. |
48 | * |
49 | * Author : Xang Xiu Yang |
50 | * Imported from gtkTraceSet.c by Mathieu Desnoyers |
51 | ***************************************************************************/ |
52 | static void lttv_traceset_context_compute_time_span( |
53 | LttvTracesetContext *self, |
54 | TimeInterval *Time_Span) |
55 | { |
56 | LttvTraceset * traceset = self->ts; |
57 | int numTraces = lttv_traceset_number(traceset); |
58 | int i; |
59 | LttTime s, e; |
60 | LttvTraceContext *tc; |
61 | LttTrace * trace; |
62 | |
63 | for(i=0; i<numTraces;i++){ |
64 | tc = self->traces[i]; |
65 | trace = tc->t; |
66 | |
67 | ltt_trace_time_span_get(trace, &s, &e); |
68 | |
69 | if(i==0){ |
70 | Time_Span->startTime = s; |
71 | Time_Span->endTime = e; |
72 | }else{ |
73 | if(s.tv_sec < Time_Span->startTime.tv_sec || |
74 | (s.tv_sec == Time_Span->startTime.tv_sec |
75 | && s.tv_nsec < Time_Span->startTime.tv_nsec)) |
76 | Time_Span->startTime = s; |
77 | if(e.tv_sec > Time_Span->endTime.tv_sec || |
78 | (e.tv_sec == Time_Span->endTime.tv_sec && |
79 | e.tv_nsec > Time_Span->endTime.tv_nsec)) |
80 | Time_Span->endTime = e; |
81 | } |
82 | } |
83 | } |
84 | |
dc877563 |
85 | |
86 | static void |
87 | init(LttvTracesetContext *self, LttvTraceset *ts) |
88 | { |
89 | guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; |
90 | |
91 | LttvTraceContext *tc; |
92 | |
93 | LttvTracefileContext *tfc; |
94 | |
308711e5 |
95 | LttTime null_time = {0, 0}; |
96 | |
dc877563 |
97 | nb_trace = lttv_traceset_number(ts); |
98 | self->ts = ts; |
ffd54a90 |
99 | self->traces = g_new(LttvTraceContext *, nb_trace); |
dc877563 |
100 | self->before = lttv_hooks_new(); |
101 | self->after = lttv_hooks_new(); |
ffd54a90 |
102 | self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); |
308711e5 |
103 | self->ts_a = lttv_traceset_attribute(ts); |
dc877563 |
104 | for(i = 0 ; i < nb_trace ; i++) { |
ffd54a90 |
105 | tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); |
dc877563 |
106 | self->traces[i] = tc; |
107 | |
108 | tc->ts_context = self; |
109 | tc->index = i; |
308711e5 |
110 | tc->vt = lttv_traceset_get(ts, i); |
111 | tc->t = lttv_trace(tc->vt); |
dc877563 |
112 | tc->check = lttv_hooks_new(); |
113 | tc->before = lttv_hooks_new(); |
114 | tc->after = lttv_hooks_new(); |
ffd54a90 |
115 | tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); |
308711e5 |
116 | tc->t_a = lttv_trace_attribute(tc->vt); |
dc877563 |
117 | nb_control = ltt_trace_control_tracefile_number(tc->t); |
118 | nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); |
119 | nb_tracefile = nb_control + nb_per_cpu; |
ffd54a90 |
120 | tc->control_tracefiles = g_new(LttvTracefileContext *, nb_control); |
121 | tc->per_cpu_tracefiles = g_new(LttvTracefileContext *, nb_per_cpu); |
dc877563 |
122 | |
123 | for(j = 0 ; j < nb_tracefile ; j++) { |
ffd54a90 |
124 | tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); |
dc877563 |
125 | if(j < nb_control) { |
126 | tc->control_tracefiles[j] = tfc; |
127 | tfc->control = TRUE; |
128 | tfc->index = j; |
ffd54a90 |
129 | tfc->tf = ltt_trace_control_tracefile_get(tc->t, j); |
dc877563 |
130 | } |
131 | else { |
132 | tc->per_cpu_tracefiles[j - nb_control] = tfc; |
133 | tfc->control = FALSE; |
134 | tfc->index = j - nb_control; |
ffd54a90 |
135 | tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); |
dc877563 |
136 | } |
137 | tfc->t_context = tc; |
138 | tfc->check = lttv_hooks_new(); |
139 | tfc->before = lttv_hooks_new(); |
140 | tfc->after = lttv_hooks_new(); |
141 | tfc->check_event = lttv_hooks_new(); |
142 | tfc->before_event = lttv_hooks_new(); |
143 | tfc->before_event_by_id = lttv_hooks_by_id_new(); |
144 | tfc->after_event = lttv_hooks_new(); |
145 | tfc->after_event_by_id = lttv_hooks_by_id_new(); |
ffd54a90 |
146 | tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); |
dc877563 |
147 | } |
148 | } |
308711e5 |
149 | lttv_process_traceset_seek_time(self, null_time); |
150 | /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ |
f7afe191 |
151 | self->Time_Span = g_new(TimeInterval,1); |
152 | lttv_traceset_context_compute_time_span(self, self->Time_Span); |
dc877563 |
153 | } |
154 | |
155 | |
156 | void fini(LttvTracesetContext *self) |
157 | { |
158 | guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; |
159 | |
160 | LttvTraceContext *tc; |
161 | |
162 | LttvTracefileContext *tfc; |
163 | |
ffd54a90 |
164 | LttvTraceset *ts = self->ts; |
dc877563 |
165 | |
f7afe191 |
166 | g_free(self->Time_Span); |
167 | |
dc877563 |
168 | lttv_hooks_destroy(self->before); |
169 | lttv_hooks_destroy(self->after); |
f7afe191 |
170 | //FIXME : segfault |
2061e03d |
171 | g_object_unref(self->a); |
dc877563 |
172 | |
173 | nb_trace = lttv_traceset_number(ts); |
174 | |
175 | for(i = 0 ; i < nb_trace ; i++) { |
176 | tc = self->traces[i]; |
177 | |
178 | lttv_hooks_destroy(tc->check); |
179 | lttv_hooks_destroy(tc->before); |
180 | lttv_hooks_destroy(tc->after); |
ffd54a90 |
181 | g_object_unref(tc->a); |
dc877563 |
182 | |
183 | nb_control = ltt_trace_control_tracefile_number(tc->t); |
184 | nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); |
185 | nb_tracefile = nb_control + nb_per_cpu; |
186 | |
187 | for(j = 0 ; j < nb_tracefile ; j++) { |
188 | if(j < nb_control) tfc = tc->control_tracefiles[j]; |
189 | else tfc = tc->per_cpu_tracefiles[j - nb_control]; |
190 | |
191 | lttv_hooks_destroy(tfc->check); |
192 | lttv_hooks_destroy(tfc->before); |
193 | lttv_hooks_destroy(tfc->after); |
194 | lttv_hooks_destroy(tfc->check_event); |
195 | lttv_hooks_destroy(tfc->before_event); |
196 | lttv_hooks_by_id_destroy(tfc->before_event_by_id); |
197 | lttv_hooks_destroy(tfc->after_event); |
198 | lttv_hooks_by_id_destroy(tfc->after_event_by_id); |
ffd54a90 |
199 | g_object_unref(tfc->a); |
dc877563 |
200 | g_object_unref(tfc); |
201 | } |
202 | g_free(tc->control_tracefiles); |
203 | g_free(tc->per_cpu_tracefiles); |
204 | g_object_unref(tc); |
205 | } |
206 | g_free(self->traces); |
207 | } |
208 | |
209 | |
210 | void lttv_traceset_context_add_hooks(LttvTracesetContext *self, |
211 | LttvHooks *before_traceset, |
212 | LttvHooks *after_traceset, |
213 | LttvHooks *check_trace, |
214 | LttvHooks *before_trace, |
215 | LttvHooks *after_trace, |
ffd54a90 |
216 | LttvHooks *check_tracefile, |
217 | LttvHooks *before_tracefile, |
218 | LttvHooks *after_tracefile, |
dc877563 |
219 | LttvHooks *check_event, |
220 | LttvHooks *before_event, |
221 | LttvHooks *after_event) |
222 | { |
223 | LttvTraceset *ts = self->ts; |
224 | |
225 | guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; |
226 | |
227 | LttvTraceContext *tc; |
228 | |
229 | LttvTracefileContext *tfc; |
230 | |
231 | void *hook_data; |
232 | |
233 | lttv_hooks_add_list(self->before, before_traceset); |
234 | lttv_hooks_add_list(self->after, after_traceset); |
235 | nb_trace = lttv_traceset_number(ts); |
236 | |
237 | for(i = 0 ; i < nb_trace ; i++) { |
238 | tc = self->traces[i]; |
239 | lttv_hooks_add_list(tc->check, check_trace); |
240 | lttv_hooks_add_list(tc->before, before_trace); |
241 | lttv_hooks_add_list(tc->after, after_trace); |
242 | nb_control = ltt_trace_control_tracefile_number(tc->t); |
d83f6739 |
243 | nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); |
dc877563 |
244 | nb_tracefile = nb_control + nb_per_cpu; |
245 | |
246 | for(j = 0 ; j < nb_tracefile ; j++) { |
247 | if(j < nb_control) { |
248 | tfc = tc->control_tracefiles[j]; |
249 | } |
250 | else { |
d83f6739 |
251 | tfc = tc->per_cpu_tracefiles[j-nb_control]; |
dc877563 |
252 | } |
253 | lttv_hooks_add_list(tfc->check, check_tracefile); |
254 | lttv_hooks_add_list(tfc->before, before_tracefile); |
255 | lttv_hooks_add_list(tfc->after, after_tracefile); |
256 | lttv_hooks_add_list(tfc->check_event, check_event); |
257 | lttv_hooks_add_list(tfc->before_event, before_event); |
258 | lttv_hooks_add_list(tfc->after_event, after_event); |
259 | } |
260 | } |
261 | } |
262 | |
263 | |
264 | void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, |
265 | LttvHooks *before_traceset, |
266 | LttvHooks *after_traceset, |
267 | LttvHooks *check_trace, |
268 | LttvHooks *before_trace, |
269 | LttvHooks *after_trace, |
ffd54a90 |
270 | LttvHooks *check_tracefile, |
271 | LttvHooks *before_tracefile, |
272 | LttvHooks *after_tracefile, |
dc877563 |
273 | LttvHooks *check_event, |
274 | LttvHooks *before_event, |
275 | LttvHooks *after_event) |
276 | { |
277 | LttvTraceset *ts = self->ts; |
278 | |
279 | guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; |
280 | |
281 | LttvTraceContext *tc; |
282 | |
283 | LttvTracefileContext *tfc; |
284 | |
285 | void *hook_data; |
286 | |
287 | lttv_hooks_remove_list(self->before, before_traceset); |
288 | lttv_hooks_remove_list(self->after, after_traceset); |
289 | nb_trace = lttv_traceset_number(ts); |
290 | |
291 | for(i = 0 ; i < nb_trace ; i++) { |
292 | tc = self->traces[i]; |
293 | lttv_hooks_remove_list(tc->check, check_trace); |
294 | lttv_hooks_remove_list(tc->before, before_trace); |
295 | lttv_hooks_remove_list(tc->after, after_trace); |
296 | nb_control = ltt_trace_control_tracefile_number(tc->t); |
d83f6739 |
297 | nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); |
dc877563 |
298 | nb_tracefile = nb_control + nb_per_cpu; |
299 | |
300 | for(j = 0 ; j < nb_tracefile ; j++) { |
301 | if(j < nb_control) { |
302 | tfc = tc->control_tracefiles[j]; |
303 | } |
304 | else { |
d83f6739 |
305 | tfc = tc->per_cpu_tracefiles[j-nb_control]; |
dc877563 |
306 | } |
307 | lttv_hooks_remove_list(tfc->check, check_tracefile); |
308 | lttv_hooks_remove_list(tfc->before, before_tracefile); |
309 | lttv_hooks_remove_list(tfc->after, after_tracefile); |
310 | lttv_hooks_remove_list(tfc->check_event, check_event); |
311 | lttv_hooks_remove_list(tfc->before_event, before_event); |
312 | lttv_hooks_remove_list(tfc->after_event, after_event); |
313 | } |
314 | } |
315 | } |
316 | |
317 | |
ba576a78 |
318 | static LttvTracesetContext * |
dc877563 |
319 | new_traceset_context(LttvTracesetContext *self) |
320 | { |
ffd54a90 |
321 | return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL); |
dc877563 |
322 | } |
323 | |
324 | |
ba576a78 |
325 | static LttvTraceContext * |
dc877563 |
326 | new_trace_context(LttvTracesetContext *self) |
327 | { |
ffd54a90 |
328 | return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL); |
dc877563 |
329 | } |
330 | |
331 | |
ba576a78 |
332 | static LttvTracefileContext * |
dc877563 |
333 | new_tracefile_context(LttvTracesetContext *self) |
334 | { |
ffd54a90 |
335 | return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL); |
dc877563 |
336 | } |
337 | |
338 | |
339 | static void |
340 | traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) |
341 | { |
342 | /* Be careful of anything which would not work well with shallow copies */ |
343 | } |
344 | |
345 | |
346 | static void |
347 | traceset_context_finalize (LttvTracesetContext *self) |
348 | { |
b445142a |
349 | G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) |
350 | ->finalize(G_OBJECT(self)); |
dc877563 |
351 | } |
352 | |
353 | |
354 | static void |
355 | traceset_context_class_init (LttvTracesetContextClass *klass) |
356 | { |
357 | GObjectClass *gobject_class = G_OBJECT_CLASS(klass); |
358 | |
ffd54a90 |
359 | gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize; |
dc877563 |
360 | klass->init = init; |
361 | klass->fini = fini; |
362 | klass->new_traceset_context = new_traceset_context; |
363 | klass->new_trace_context = new_trace_context; |
364 | klass->new_tracefile_context = new_tracefile_context; |
365 | } |
366 | |
367 | |
368 | GType |
ffd54a90 |
369 | lttv_traceset_context_get_type(void) |
dc877563 |
370 | { |
371 | static GType type = 0; |
372 | if (type == 0) { |
373 | static const GTypeInfo info = { |
ffd54a90 |
374 | sizeof (LttvTracesetContextClass), |
dc877563 |
375 | NULL, /* base_init */ |
376 | NULL, /* base_finalize */ |
ffd54a90 |
377 | (GClassInitFunc) traceset_context_class_init, /* class_init */ |
dc877563 |
378 | NULL, /* class_finalize */ |
379 | NULL, /* class_data */ |
ffd54a90 |
380 | sizeof (LttvTracesetContext), |
dc877563 |
381 | 0, /* n_preallocs */ |
ffd54a90 |
382 | (GInstanceInitFunc) traceset_context_instance_init /* instance_init */ |
dc877563 |
383 | }; |
384 | |
ffd54a90 |
385 | type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType", |
dc877563 |
386 | &info, 0); |
387 | } |
388 | return type; |
389 | } |
390 | |
391 | |
392 | static void |
393 | trace_context_instance_init (GTypeInstance *instance, gpointer g_class) |
394 | { |
395 | /* Be careful of anything which would not work well with shallow copies */ |
396 | } |
397 | |
398 | |
399 | static void |
400 | trace_context_finalize (LttvTraceContext *self) |
401 | { |
b445142a |
402 | G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> |
403 | finalize(G_OBJECT(self)); |
dc877563 |
404 | } |
405 | |
406 | |
407 | static void |
408 | trace_context_class_init (LttvTraceContextClass *klass) |
409 | { |
410 | GObjectClass *gobject_class = G_OBJECT_CLASS(klass); |
411 | |
ffd54a90 |
412 | gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize; |
dc877563 |
413 | } |
414 | |
415 | |
416 | GType |
ffd54a90 |
417 | lttv_trace_context_get_type(void) |
dc877563 |
418 | { |
419 | static GType type = 0; |
420 | if (type == 0) { |
421 | static const GTypeInfo info = { |
ffd54a90 |
422 | sizeof (LttvTraceContextClass), |
dc877563 |
423 | NULL, /* base_init */ |
424 | NULL, /* base_finalize */ |
ffd54a90 |
425 | (GClassInitFunc) trace_context_class_init, /* class_init */ |
dc877563 |
426 | NULL, /* class_finalize */ |
427 | NULL, /* class_data */ |
c6bc9cb9 |
428 | sizeof (LttvTraceContext), |
dc877563 |
429 | 0, /* n_preallocs */ |
ffd54a90 |
430 | (GInstanceInitFunc) trace_context_instance_init /* instance_init */ |
dc877563 |
431 | }; |
432 | |
ffd54a90 |
433 | type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType", |
dc877563 |
434 | &info, 0); |
435 | } |
436 | return type; |
437 | } |
438 | |
439 | |
440 | static void |
441 | tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) |
442 | { |
443 | /* Be careful of anything which would not work well with shallow copies */ |
444 | } |
445 | |
446 | |
447 | static void |
448 | tracefile_context_finalize (LttvTracefileContext *self) |
449 | { |
b445142a |
450 | G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) |
451 | ->finalize(G_OBJECT(self)); |
dc877563 |
452 | } |
453 | |
454 | |
455 | static void |
456 | tracefile_context_class_init (LttvTracefileContextClass *klass) |
457 | { |
458 | GObjectClass *gobject_class = G_OBJECT_CLASS(klass); |
459 | |
ffd54a90 |
460 | gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize; |
461 | } |
462 | |
463 | |
464 | GType |
465 | lttv_tracefile_context_get_type(void) |
466 | { |
467 | static GType type = 0; |
468 | if (type == 0) { |
469 | static const GTypeInfo info = { |
470 | sizeof (LttvTracefileContextClass), |
471 | NULL, /* base_init */ |
472 | NULL, /* base_finalize */ |
473 | (GClassInitFunc) tracefile_context_class_init, /* class_init */ |
474 | NULL, /* class_finalize */ |
475 | NULL, /* class_data */ |
476 | sizeof (LttvTracefileContext), |
477 | 0, /* n_preallocs */ |
478 | (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */ |
479 | }; |
480 | |
481 | type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType", |
482 | &info, 0); |
483 | } |
484 | return type; |
dc877563 |
485 | } |
486 | |
487 | |
ffd54a90 |
488 | gint compare_tracefile(gconstpointer a, gconstpointer b) |
dc877563 |
489 | { |
308711e5 |
490 | return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); |
dc877563 |
491 | } |
492 | |
493 | |
494 | gboolean get_first(gpointer key, gpointer value, gpointer user_data) { |
495 | *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value; |
496 | return TRUE; |
497 | } |
498 | |
499 | |
308711e5 |
500 | void lttv_process_traceset(LttvTracesetContext *self, LttTime end, |
501 | unsigned maxNumEvents) |
dc877563 |
502 | { |
503 | GPtrArray *traces = g_ptr_array_new(); |
504 | |
505 | GPtrArray *tracefiles = g_ptr_array_new(); |
506 | |
507 | GTree *pqueue = g_tree_new(compare_tracefile); |
508 | |
ffd54a90 |
509 | guint i, j, nbi, nbj, id, nb_control, nb_cpu; |
dc877563 |
510 | |
511 | LttTrace *trace; |
512 | |
513 | LttvTraceContext *tc; |
514 | |
515 | LttTracefile *tracefile; |
516 | |
517 | LttvTracefileContext *tfc; |
518 | |
519 | LttEvent *event; |
308711e5 |
520 | |
270e7cc5 |
521 | unsigned count = 0; |
308711e5 |
522 | |
523 | LttTime previous_timestamp = {0, 0}; |
dc877563 |
524 | |
525 | /* Call all before_traceset, before_trace, and before_tracefile hooks. |
526 | For all qualifying tracefiles, seek to the start time, create a context, |
527 | read one event and insert in the pqueue based on the event time. */ |
528 | |
308711e5 |
529 | lttv_hooks_call(self->before, self); |
530 | nbi = lttv_traceset_number(self->ts); |
dc877563 |
531 | |
532 | for(i = 0 ; i < nbi ; i++) { |
308711e5 |
533 | tc = self->traces[i]; |
dc877563 |
534 | trace = tc->t; |
535 | |
536 | if(!lttv_hooks_call_check(tc->check, tc)) { |
537 | g_ptr_array_add(traces, tc); |
538 | lttv_hooks_call(tc->before, tc); |
539 | nb_control = ltt_trace_control_tracefile_number(trace); |
540 | nb_cpu = ltt_trace_per_cpu_tracefile_number(trace); |
541 | nbj = nb_control + nb_cpu; |
542 | |
543 | for(j = 0 ; j < nbj ; j++) { |
544 | if(j < nb_control) { |
545 | tfc = tc->control_tracefiles[j]; |
546 | } |
547 | else { |
548 | tfc = tc->per_cpu_tracefiles[j - nb_control]; |
549 | } |
550 | |
551 | tracefile = tfc->tf; |
552 | |
553 | if(!lttv_hooks_call_check(tfc->check, tfc)) { |
554 | g_ptr_array_add(tracefiles, tfc); |
555 | lttv_hooks_call(tfc->before, tfc); |
556 | |
dc877563 |
557 | if(event != NULL) { |
ffd54a90 |
558 | g_tree_insert(pqueue, &(tfc->timestamp), tfc); |
dc877563 |
559 | } |
560 | } |
561 | } |
562 | } |
563 | } |
564 | |
565 | /* Get the next event from the pqueue, call its hooks, |
566 | reinsert in the pqueue the following event from the same tracefile |
567 | unless the tracefile is finished or the event is later than the |
568 | start time. */ |
569 | |
ffd54a90 |
570 | while(TRUE) { |
dc877563 |
571 | tfc = NULL; |
572 | g_tree_foreach(pqueue, get_first, &tfc); |
573 | if(tfc == NULL) break; |
574 | |
308711e5 |
575 | /* Have we reached the maximum number of events specified? However, |
576 | continue for all the events with the same time stamp (CHECK?). Then, |
577 | empty the queue and break from the loop. */ |
dc877563 |
578 | |
270e7cc5 |
579 | count++; |
580 | if(count > maxNumEvents){ |
308711e5 |
581 | if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec && |
582 | tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) { |
270e7cc5 |
583 | count--; |
584 | }else{ |
585 | while(TRUE){ |
586 | tfc = NULL; |
587 | g_tree_foreach(pqueue, get_first, &tfc); |
588 | if(tfc == NULL) break; |
589 | g_tree_remove(pqueue, &(tfc->timestamp)); |
590 | } |
591 | break; |
592 | } |
593 | } |
308711e5 |
594 | previous_timestamp = tfc->timestamp; |
595 | |
596 | |
597 | /* Get the tracefile with an event for the smallest time found. If two |
598 | or more tracefiles have events for the same time, hope that lookup |
599 | and remove are consistent. */ |
270e7cc5 |
600 | |
ffd54a90 |
601 | tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); |
602 | g_tree_remove(pqueue, &(tfc->timestamp)); |
dc877563 |
603 | |
b445142a |
604 | if(!lttv_hooks_call(tfc->check_event, tfc)) { |
cbe7c836 |
605 | id = ltt_event_eventtype_id(tfc->e); |
dc877563 |
606 | lttv_hooks_call(tfc->before_event, tfc); |
607 | lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc); |
b445142a |
608 | lttv_hooks_call(tfc->after_event, tfc); |
dc877563 |
609 | lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc); |
610 | } |
611 | |
612 | event = ltt_tracefile_read(tfc->tf); |
613 | if(event != NULL) { |
614 | tfc->e = event; |
ffd54a90 |
615 | tfc->timestamp = ltt_event_time(event); |
270e7cc5 |
616 | if(tfc->timestamp.tv_sec < end.tv_sec || |
617 | (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) |
618 | g_tree_insert(pqueue, &(tfc->timestamp), tfc); |
dc877563 |
619 | } |
620 | } |
621 | |
622 | /* Call all the after_tracefile, after_trace and after_traceset hooks. */ |
623 | |
624 | for(i = 0, j = 0 ; i < traces->len ; i++) { |
625 | tc = traces->pdata[i]; |
626 | while(j < tracefiles->len) { |
627 | tfc = tracefiles->pdata[j]; |
628 | |
629 | if(tfc->t_context == tc) { |
630 | lttv_hooks_call(tfc->after, tfc); |
631 | j++; |
632 | } |
633 | else break; |
634 | } |
635 | lttv_hooks_call(tc->after, tc); |
636 | } |
637 | |
638 | g_assert(j == tracefiles->len); |
308711e5 |
639 | lttv_hooks_call(self->after, self); |
dc877563 |
640 | |
641 | /* Free the traces, tracefiles and pqueue */ |
642 | |
643 | g_ptr_array_free(tracefiles, TRUE); |
644 | g_ptr_array_free(traces, TRUE); |
ffd54a90 |
645 | g_tree_destroy(pqueue); |
dc877563 |
646 | } |
b445142a |
647 | |
308711e5 |
648 | |
649 | void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) |
650 | { |
651 | guint i, nb_control, nb_per_cpu, nb_tracefile; |
652 | |
653 | LttvTracefileContext *tfc; |
654 | |
655 | LttEvent *event; |
656 | |
657 | nb_control = ltt_trace_control_tracefile_number(self->t); |
658 | nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); |
659 | nb_tracefile = nb_control + nb_per_cpu; |
660 | for(i = 0 ; i < nb_tracefile ; i++) { |
661 | if(i < nb_control) tfc = self->control_tracefiles[i]; |
662 | else tfc = self->per_cpu_tracefiles[i - nb_control]; |
663 | |
664 | ltt_tracefile_seek_time(tfc->tf, start); |
665 | event = ltt_tracefile_read(tfc->tf); |
666 | tfc->e = event; |
667 | if(event != NULL) tfc->timestamp = ltt_event_time(event); |
668 | } |
669 | } |
670 | |
671 | |
672 | void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) |
673 | { |
674 | guint i, nb_trace; |
675 | |
676 | LttvTraceContext *tc; |
677 | |
678 | nb_trace = lttv_traceset_number(self->ts); |
679 | for(i = 0 ; i < nb_trace ; i++) { |
680 | tc = self->traces[i]; |
681 | lttv_process_trace_seek_time(tc, start); |
682 | } |
683 | } |
684 | |
685 | |
b445142a |
686 | static LttField * |
687 | find_field(LttEventType *et, const char *field) |
688 | { |
689 | LttType *t; |
690 | |
691 | LttField *f; |
692 | |
693 | guint i, nb; |
694 | |
695 | char *name; |
696 | |
697 | if(field == NULL) return NULL; |
698 | |
699 | f = ltt_eventtype_field(et); |
700 | t = ltt_eventtype_type(et); |
701 | g_assert(ltt_type_class(t) == LTT_STRUCT); |
702 | nb = ltt_type_member_number(t); |
703 | for(i = 0 ; i < nb ; i++) { |
704 | ltt_type_member_type(t, i, &name); |
705 | if(strcmp(name, field) == 0) break; |
706 | } |
707 | g_assert(i < nb); |
708 | return ltt_field_member(f, i); |
709 | } |
710 | |
711 | |
712 | void |
713 | lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, |
714 | char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) |
715 | { |
716 | LttFacility *f; |
717 | |
718 | LttEventType *et; |
719 | |
720 | guint nb, pos, i; |
721 | |
722 | char *name; |
723 | |
724 | nb = ltt_trace_facility_find(t, facility, &pos); |
725 | if(nb < 1) g_error("No %s facility", facility); |
726 | f = ltt_trace_facility_get(t, pos); |
727 | et = ltt_facility_eventtype_get_by_name(f, event_type); |
728 | if(et == NULL) g_error("Event %s does not exist", event_type); |
729 | |
730 | th->h = h; |
731 | th->id = ltt_eventtype_id(et); |
732 | th->f1 = find_field(et, field1); |
733 | th->f2 = find_field(et, field2); |
734 | th->f3 = find_field(et, field3); |
735 | } |
736 | |
737 | |