git-svn-id: http://ltt.polymtl.ca/svn@179 04897980-b3bd-0310-b5e0-8ef037075253
[lttv.git] / ltt / branches / poly / lttv / processTrace.c
1
2 #include <lttv/processTrace.h>
3 #include <ltt/event.h>
4
5 void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
6 {
7 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
8 }
9
10
11 void lttv_context_fini(LttvTracesetContext *self)
12 {
13 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
14 }
15
16
17 LttvTracesetContext *
18 lttv_context_new_traceset_context(LttvTracesetContext *self)
19 {
20 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
21 }
22
23
24
25
26 LttvTraceContext *
27 lttv_context_new_trace_context(LttvTracesetContext *self)
28 {
29 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
30 }
31
32
33 LttvTracefileContext *
34 lttv_context_new_tracefile_context(LttvTracesetContext *self)
35 {
36 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
37 }
38
39
40 static void
41 init(LttvTracesetContext *self, LttvTraceset *ts)
42 {
43 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
44
45 LttvTraceContext *tc;
46
47 LttvTracefileContext *tfc;
48
49 nb_trace = lttv_traceset_number(ts);
50 self->ts = 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);
57 self->traces[i] = tc;
58
59 tc->ts_context = self;
60 tc->index = i;
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);
71
72 for(j = 0 ; j < nb_tracefile ; j++) {
73 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
74 if(j < nb_control) {
75 tc->control_tracefiles[j] = tfc;
76 tfc->control = TRUE;
77 tfc->index = j;
78 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
79 }
80 else {
81 tc->per_cpu_tracefiles[j - nb_control] = tfc;
82 tfc->control = FALSE;
83 tfc->index = j - nb_control;
84 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
85 }
86 tfc->t_context = tc;
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);
96 }
97 }
98 }
99
100
101 void fini(LttvTracesetContext *self)
102 {
103 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
104
105 LttvTraceContext *tc;
106
107 LttvTracefileContext *tfc;
108
109 LttvTraceset *ts = self->ts;
110
111 lttv_hooks_destroy(self->before);
112 lttv_hooks_destroy(self->after);
113 g_object_unref(self->a);
114
115 nb_trace = lttv_traceset_number(ts);
116
117 for(i = 0 ; i < nb_trace ; i++) {
118 tc = self->traces[i];
119
120 lttv_hooks_destroy(tc->check);
121 lttv_hooks_destroy(tc->before);
122 lttv_hooks_destroy(tc->after);
123 g_object_unref(tc->a);
124
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;
128
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];
132
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);
142 g_object_unref(tfc);
143 }
144 g_free(tc->control_tracefiles);
145 g_free(tc->per_cpu_tracefiles);
146 g_object_unref(tc);
147 }
148 g_free(self->traces);
149 }
150
151
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)
164 {
165 LttvTraceset *ts = self->ts;
166
167 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
168
169 LttvTraceContext *tc;
170
171 LttvTracefileContext *tfc;
172
173 void *hook_data;
174
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);
178
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;
187
188 for(j = 0 ; j < nb_tracefile ; j++) {
189 if(j < nb_control) {
190 tfc = tc->control_tracefiles[j];
191 }
192 else {
193 tfc = tc->per_cpu_tracefiles[j-nb_control];
194 }
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);
201 }
202 }
203 }
204
205
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)
218 {
219 LttvTraceset *ts = self->ts;
220
221 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
222
223 LttvTraceContext *tc;
224
225 LttvTracefileContext *tfc;
226
227 void *hook_data;
228
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);
232
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;
241
242 for(j = 0 ; j < nb_tracefile ; j++) {
243 if(j < nb_control) {
244 tfc = tc->control_tracefiles[j];
245 }
246 else {
247 tfc = tc->per_cpu_tracefiles[j-nb_control];
248 }
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);
255 }
256 }
257 }
258
259
260 static LttvTracesetContext *
261 new_traceset_context(LttvTracesetContext *self)
262 {
263 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
264 }
265
266
267 static LttvTraceContext *
268 new_trace_context(LttvTracesetContext *self)
269 {
270 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
271 }
272
273
274 static LttvTracefileContext *
275 new_tracefile_context(LttvTracesetContext *self)
276 {
277 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
278 }
279
280
281 static void
282 traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
283 {
284 /* Be careful of anything which would not work well with shallow copies */
285 }
286
287
288 static void
289 traceset_context_finalize (LttvTracesetContext *self)
290 {
291 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self));
292 }
293
294
295 static void
296 traceset_context_class_init (LttvTracesetContextClass *klass)
297 {
298 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
299
300 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
301 klass->init = init;
302 klass->fini = fini;
303 klass->new_traceset_context = new_traceset_context;
304 klass->new_trace_context = new_trace_context;
305 klass->new_tracefile_context = new_tracefile_context;
306 }
307
308
309 GType
310 lttv_traceset_context_get_type(void)
311 {
312 static GType type = 0;
313 if (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),
322 0, /* n_preallocs */
323 (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
324 };
325
326 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
327 &info, 0);
328 }
329 return type;
330 }
331
332
333 static void
334 trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
335 {
336 /* Be careful of anything which would not work well with shallow copies */
337 }
338
339
340 static void
341 trace_context_finalize (LttvTraceContext *self)
342 {
343 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self));
344 }
345
346
347 static void
348 trace_context_class_init (LttvTraceContextClass *klass)
349 {
350 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
351
352 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
353 }
354
355
356 GType
357 lttv_trace_context_get_type(void)
358 {
359 static GType type = 0;
360 if (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),
369 0, /* n_preallocs */
370 (GInstanceInitFunc) trace_context_instance_init /* instance_init */
371 };
372
373 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
374 &info, 0);
375 }
376 return type;
377 }
378
379
380 static void
381 tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
382 {
383 /* Be careful of anything which would not work well with shallow copies */
384 }
385
386
387 static void
388 tracefile_context_finalize (LttvTracefileContext *self)
389 {
390 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self));
391 }
392
393
394 static void
395 tracefile_context_class_init (LttvTracefileContextClass *klass)
396 {
397 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
398
399 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
400 }
401
402
403 GType
404 lttv_tracefile_context_get_type(void)
405 {
406 static GType type = 0;
407 if (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),
416 0, /* n_preallocs */
417 (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */
418 };
419
420 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
421 &info, 0);
422 }
423 return type;
424 }
425
426
427 gint compare_tracefile(gconstpointer a, gconstpointer b)
428 {
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;
433 return 0;
434 }
435
436
437 gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
438 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
439 return TRUE;
440 }
441
442
443 void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
444 LttvTracesetContext *context)
445 {
446 GPtrArray *traces = g_ptr_array_new();
447
448 GPtrArray *tracefiles = g_ptr_array_new();
449
450 GTree *pqueue = g_tree_new(compare_tracefile);
451
452 guint i, j, nbi, nbj, id, nb_control, nb_cpu;
453
454 LttTrace *trace;
455
456 LttvTraceContext *tc;
457
458 LttTracefile *tracefile;
459
460 LttvTracefileContext *tfc;
461
462 LttEvent *event;
463
464 /* Call all before_traceset, before_trace, and before_tracefile hooks.
465 For all qualifying tracefiles, seek to the start time, create a context,
466 read one event and insert in the pqueue based on the event time. */
467
468 lttv_hooks_call(context->before, context);
469 nbi = lttv_traceset_number(traceset);
470 // nbi = ltt_trace_set_number(traceset);
471
472 for(i = 0 ; i < nbi ; i++) {
473 tc = context->traces[i];
474 trace = tc->t;
475
476 if(!lttv_hooks_call_check(tc->check, tc)) {
477 g_ptr_array_add(traces, tc);
478 lttv_hooks_call(tc->before, tc);
479 nb_control = ltt_trace_control_tracefile_number(trace);
480 nb_cpu = ltt_trace_per_cpu_tracefile_number(trace);
481 nbj = nb_control + nb_cpu;
482
483 for(j = 0 ; j < nbj ; j++) {
484 if(j < nb_control) {
485 tfc = tc->control_tracefiles[j];
486 }
487 else {
488 tfc = tc->per_cpu_tracefiles[j - nb_control];
489 }
490
491 tracefile = tfc->tf;
492
493 if(!lttv_hooks_call_check(tfc->check, tfc)) {
494 g_ptr_array_add(tracefiles, tfc);
495 lttv_hooks_call(tfc->before, tfc);
496
497 ltt_tracefile_seek_time(tracefile, start);
498 event = ltt_tracefile_read(tracefile);
499 tfc->e = event;
500
501 if(event != NULL) {
502 tfc->timestamp = ltt_event_time(event);
503 g_tree_insert(pqueue, &(tfc->timestamp), tfc);
504 }
505 }
506 }
507 }
508 }
509
510 /* Get the next event from the pqueue, call its hooks,
511 reinsert in the pqueue the following event from the same tracefile
512 unless the tracefile is finished or the event is later than the
513 start time. */
514
515 while(TRUE) {
516 tfc = NULL;
517 g_tree_foreach(pqueue, get_first, &tfc);
518 if(tfc == NULL) break;
519
520 /* Get the tracefile with an event for the smallest time found. If two
521 or more tracefiles have events for the same time, hope that lookup
522 and remove are consistent. */
523
524 tfc = g_tree_lookup(pqueue, &(tfc->timestamp));
525 g_tree_remove(pqueue, &(tfc->timestamp));
526
527 if(!lttv_hooks_call(tfc->check_event, context)) {
528 id = ltt_event_eventtype_id(tfc->e);
529 lttv_hooks_call(tfc->before_event, tfc);
530 lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
531 lttv_hooks_call(tfc->after_event, context);
532 lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
533 }
534
535 event = ltt_tracefile_read(tfc->tf);
536 if(event != NULL) {
537 tfc->e = event;
538 tfc->timestamp = ltt_event_time(event);
539 g_tree_insert(pqueue, &(tfc->timestamp), tfc);
540 }
541 }
542
543 /* Call all the after_tracefile, after_trace and after_traceset hooks. */
544
545 for(i = 0, j = 0 ; i < traces->len ; i++) {
546 tc = traces->pdata[i];
547 while(j < tracefiles->len) {
548 tfc = tracefiles->pdata[j];
549
550 if(tfc->t_context == tc) {
551 lttv_hooks_call(tfc->after, tfc);
552 j++;
553 }
554 else break;
555 }
556 lttv_hooks_call(tc->after, tc);
557 }
558
559 g_assert(j == tracefiles->len);
560 lttv_hooks_call(context->after, context);
561
562 /* Free the traces, tracefiles and pqueue */
563
564 g_ptr_array_free(tracefiles, TRUE);
565 g_ptr_array_free(traces, TRUE);
566 g_tree_destroy(pqueue);
567 }
This page took 0.041162 seconds and 4 git commands to generate.