lttv and lib ltt new compiles
[lttv.git] / ltt / branches / poly / lttv / lttv / tracecontext.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <string.h>
24 #include <lttv/tracecontext.h>
25 #include <ltt/event.h>
26 #include <ltt/facility.h>
27 #include <ltt/trace.h>
28 #include <ltt/type.h>
29
30
31
32
33 static gint compare_tracefile(gconstpointer a, gconstpointer b)
34 {
35 gint comparison = 0;
36
37 const LttvTracefileContext *trace_a = (const LttvTracefileContext *)a;
38 const LttvTracefileContext *trace_b = (const LttvTracefileContext *)b;
39
40 if(likely(trace_a != trace_b)) {
41 comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
42 if(unlikely(comparison == 0)) {
43 if(trace_a->index < trace_b->index) comparison = -1;
44 else if(trace_a->index > trace_b->index) comparison = 1;
45 else if(trace_a->t_context->index < trace_b->t_context->index)
46 comparison = -1;
47 else if(trace_a->t_context->index > trace_b->t_context->index)
48 comparison = 1;
49 }
50 }
51 return comparison;
52 }
53
54 struct _LttvTraceContextPosition {
55 LttEventPosition **tf_pos; /* Position in each tracefile */
56 guint nb_tracefile; /* Number of tracefiles (check) */
57 };
58
59 struct _LttvTracesetContextPosition {
60 LttvTraceContextPosition *t_pos; /* Position in each trace */
61 guint nb_trace; /* Number of traces (check) */
62 LttTime timestamp; /* Current time at the saved position */
63 };
64
65 void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
66 {
67 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
68 }
69
70
71 void lttv_context_fini(LttvTracesetContext *self)
72 {
73 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
74 }
75
76
77 LttvTracesetContext *
78 lttv_context_new_traceset_context(LttvTracesetContext *self)
79 {
80 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
81 }
82
83
84
85
86 LttvTraceContext *
87 lttv_context_new_trace_context(LttvTracesetContext *self)
88 {
89 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
90 }
91
92
93 LttvTracefileContext *
94 lttv_context_new_tracefile_context(LttvTracesetContext *self)
95 {
96 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
97 }
98
99 /****************************************************************************
100 * lttv_traceset_context_compute_time_span
101 *
102 * Keep the time span is sync with on the fly addition and removal of traces
103 * in a trace set. It must be called each time a trace is added/removed from
104 * the traceset. It could be more efficient to call it only once a bunch
105 * of traces are loaded, but the calculation is not long, so it's not
106 * critical.
107 *
108 * Author : Xang Xiu Yang
109 ***************************************************************************/
110 static void lttv_traceset_context_compute_time_span(
111 LttvTracesetContext *self,
112 TimeInterval *time_span)
113 {
114 LttvTraceset * traceset = self->ts;
115 int numTraces = lttv_traceset_number(traceset);
116 int i;
117 LttTime s, e;
118 LttvTraceContext *tc;
119 LttTrace * trace;
120
121 time_span->start_time.tv_sec = 0;
122 time_span->start_time.tv_nsec = 0;
123 time_span->end_time.tv_sec = 0;
124 time_span->end_time.tv_nsec = 0;
125
126 for(i=0; i<numTraces;i++){
127 tc = self->traces[i];
128 trace = tc->t;
129
130 ltt_trace_time_span_get(trace, &s, &e);
131
132 if(i==0){
133 time_span->start_time = s;
134 time_span->end_time = e;
135 }else{
136 if(s.tv_sec < time_span->start_time.tv_sec
137 || (s.tv_sec == time_span->start_time.tv_sec
138 && s.tv_nsec < time_span->start_time.tv_nsec))
139 time_span->start_time = s;
140 if(e.tv_sec > time_span->end_time.tv_sec
141 || (e.tv_sec == time_span->end_time.tv_sec
142 && e.tv_nsec > time_span->end_time.tv_nsec))
143 time_span->end_time = e;
144 }
145 }
146 }
147
148 static void init_tracefile_context(LttTracefile *tracefile,
149 LttvTraceContext *tc)
150 {
151 LttvTracefileContext *tfc;
152 LttvTracesetContext *tsc = tc->ts_context;
153
154 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->new_tracefile_context(tsc);
155
156 tfc->index = tc->tracefiles->len;
157 tc->tracefiles = g_array_append_val(tc->tracefiles, tfc);
158
159 tfc->tf = tracefile;
160
161 tfc->t_context = tc;
162 tfc->event = lttv_hooks_new();
163 tfc->event_by_id = lttv_hooks_by_id_new();
164 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
165 }
166
167
168 static void
169 init(LttvTracesetContext *self, LttvTraceset *ts)
170 {
171 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
172
173 LttvTraceContext *tc;
174
175 GData *tracefiles_groups;
176
177 struct compute_tracefile_group_args args;
178
179 nb_trace = lttv_traceset_number(ts);
180 self->ts = ts;
181 self->traces = g_new(LttvTraceContext *, nb_trace);
182 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
183 self->ts_a = lttv_traceset_attribute(ts);
184 for(i = 0 ; i < nb_trace ; i++) {
185 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
186 self->traces[i] = tc;
187
188 tc->ts_context = self;
189 tc->index = i;
190 tc->vt = lttv_traceset_get(ts, i);
191 tc->t = lttv_trace(tc->vt);
192 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
193 tc->t_a = lttv_trace_attribute(tc->vt);
194
195 tracefiles_groups = ltt_trace_get_tracefiles_groups(tc->t);
196
197 args.func = (ForEachTraceFileFunc)init_tracefile_context;
198 args.func_args = tc;
199
200 g_datalist_foreach(&tracefiles_groups,
201 (GDataForeachFunc)compute_tracefile_group,
202 &args);
203
204 #if 0
205 nb_control = ltt_trace_control_tracefile_number(tc->t);
206 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
207 nb_tracefile = nb_control + nb_per_cpu;
208 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
209
210 for(j = 0 ; j < nb_tracefile ; j++) {
211 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
212 tc->tracefiles[j] = tfc;
213 tfc->index = j;
214
215 if(j < nb_control) {
216 tfc->control = TRUE;
217 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
218 }
219 else {
220 tfc->control = FALSE;
221 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
222 }
223
224 tfc->t_context = tc;
225 tfc->e = ltt_event_new();
226 tfc->event = lttv_hooks_new();
227 tfc->event_by_id = lttv_hooks_by_id_new();
228 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
229 }
230 #endif //0
231
232 }
233 self->pqueue = g_tree_new(compare_tracefile);
234 lttv_process_traceset_seek_time(self, ltt_time_zero);
235 lttv_traceset_context_compute_time_span(self, &self->time_span);
236
237 }
238
239
240 void fini(LttvTracesetContext *self)
241 {
242 guint i, j, nb_trace, nb_tracefile;
243
244 LttvTraceContext *tc;
245
246 LttvTracefileContext *tfc;
247
248 LttvTraceset *ts = self->ts;
249
250 //FIXME : segfault
251
252 g_tree_destroy(self->pqueue);
253 g_object_unref(self->a);
254
255 nb_trace = lttv_traceset_number(ts);
256
257 for(i = 0 ; i < nb_trace ; i++) {
258 tc = self->traces[i];
259
260 g_object_unref(tc->a);
261
262 nb_tracefile = tc->tracefiles->len;
263
264 for(j = 0 ; j < nb_tracefile ; j++) {
265 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, j);
266 lttv_hooks_destroy(tfc->event);
267 lttv_hooks_by_id_destroy(tfc->event_by_id);
268 g_object_unref(tfc->a);
269 g_object_unref(tfc);
270 }
271 g_array_free(tc->tracefiles, TRUE);
272 g_object_unref(tc);
273 }
274 g_free(self->traces);
275 }
276
277
278 void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
279 LttvHooks *before_traceset,
280 LttvHooks *before_trace,
281 LttvHooks *before_tracefile,
282 LttvHooks *event,
283 LttvHooksById *event_by_id)
284 {
285 LttvTraceset *ts = self->ts;
286
287 guint i, nb_trace;
288
289 LttvTraceContext *tc;
290
291 lttv_hooks_call(before_traceset, self);
292
293 nb_trace = lttv_traceset_number(ts);
294
295 for(i = 0 ; i < nb_trace ; i++) {
296 tc = self->traces[i];
297 lttv_trace_context_add_hooks(tc,
298 before_trace,
299 before_tracefile,
300 event,
301 event_by_id);
302 }
303 }
304
305
306 void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
307 LttvHooks *after_traceset,
308 LttvHooks *after_trace,
309 LttvHooks *after_tracefile,
310 LttvHooks *event,
311 LttvHooksById *event_by_id)
312 {
313
314 LttvTraceset *ts = self->ts;
315
316 guint i, nb_trace;
317
318 LttvTraceContext *tc;
319
320 nb_trace = lttv_traceset_number(ts);
321
322 for(i = 0 ; i < nb_trace ; i++) {
323 tc = self->traces[i];
324 lttv_trace_context_remove_hooks(tc,
325 after_trace,
326 after_tracefile,
327 event,
328 event_by_id);
329 }
330
331 lttv_hooks_call(after_traceset, self);
332
333
334 }
335
336 void lttv_trace_context_add_hooks(LttvTraceContext *self,
337 LttvHooks *before_trace,
338 LttvHooks *before_tracefile,
339 LttvHooks *event,
340 LttvHooksById *event_by_id)
341 {
342 guint i, nb_tracefile;
343
344 LttvTracefileContext *tfc;
345
346 lttv_hooks_call(before_trace, self);
347
348 nb_tracefile = self->tracefiles->len;
349
350 for(i = 0 ; i < nb_tracefile ; i++) {
351 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
352 lttv_tracefile_context_add_hooks(tfc,
353 before_tracefile,
354 event,
355 event_by_id);
356 }
357 }
358
359
360
361 void lttv_trace_context_remove_hooks(LttvTraceContext *self,
362 LttvHooks *after_trace,
363 LttvHooks *after_tracefile,
364 LttvHooks *event,
365 LttvHooksById *event_by_id)
366 {
367 guint i, nb_tracefile;
368
369 LttvTracefileContext *tfc;
370
371 nb_tracefile = self->tracefiles->len;
372
373 for(i = 0 ; i < nb_tracefile ; i++) {
374 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
375 lttv_tracefile_context_remove_hooks(tfc,
376 after_tracefile,
377 event,
378 event_by_id);
379 }
380
381 lttv_hooks_call(after_trace, self);
382 }
383
384 void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
385 LttvHooks *before_tracefile,
386 LttvHooks *event,
387 LttvHooksById *event_by_id)
388 {
389 guint i;
390
391 LttvHooks *hook;
392
393 lttv_hooks_call(before_tracefile, self);
394 lttv_hooks_add_list(self->event, event);
395 if(event_by_id != NULL)
396 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
397 hook = lttv_hooks_by_id_find(self->event_by_id, i);
398 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, i));
399 }
400
401 }
402
403 void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
404 LttvHooks *after_tracefile,
405 LttvHooks *event,
406 LttvHooksById *event_by_id)
407 {
408 guint i;
409
410 LttvHooks *hook;
411
412
413 lttv_hooks_remove_list(self->event, event);
414 if(event_by_id != NULL)
415 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
416 hook = lttv_hooks_by_id_get(self->event_by_id, i);
417 if(hook != NULL)
418 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, i));
419 }
420
421 lttv_hooks_call(after_tracefile, self);
422 }
423
424
425
426 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
427 unsigned i,
428 LttvHooks *event_by_id)
429 {
430 LttvHooks * h;
431 h = lttv_hooks_by_id_find(tfc->event_by_id, i);
432 lttv_hooks_add_list(h, event_by_id);
433 }
434
435 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
436 unsigned i)
437 {
438 lttv_hooks_by_id_remove(tfc->event_by_id, i);
439 }
440
441 static LttvTracesetContext *
442 new_traceset_context(LttvTracesetContext *self)
443 {
444 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
445 }
446
447
448 static LttvTraceContext *
449 new_trace_context(LttvTracesetContext *self)
450 {
451 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
452 }
453
454
455 static LttvTracefileContext *
456 new_tracefile_context(LttvTracesetContext *self)
457 {
458 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
459 }
460
461
462 static void
463 traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
464 {
465 /* Be careful of anything which would not work well with shallow copies */
466 }
467
468
469 static void
470 traceset_context_finalize (LttvTracesetContext *self)
471 {
472 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
473 ->finalize(G_OBJECT(self));
474 }
475
476
477 static void
478 traceset_context_class_init (LttvTracesetContextClass *klass)
479 {
480 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
481
482 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
483 klass->init = init;
484 klass->fini = fini;
485 klass->new_traceset_context = new_traceset_context;
486 klass->new_trace_context = new_trace_context;
487 klass->new_tracefile_context = new_tracefile_context;
488 }
489
490
491 GType
492 lttv_traceset_context_get_type(void)
493 {
494 static GType type = 0;
495 if (type == 0) {
496 static const GTypeInfo info = {
497 sizeof (LttvTracesetContextClass),
498 NULL, /* base_init */
499 NULL, /* base_finalize */
500 (GClassInitFunc) traceset_context_class_init, /* class_init */
501 NULL, /* class_finalize */
502 NULL, /* class_data */
503 sizeof (LttvTracesetContext),
504 0, /* n_preallocs */
505 (GInstanceInitFunc) traceset_context_instance_init, /* instance_init */
506 NULL /* Value handling */
507 };
508
509 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
510 &info, 0);
511 }
512 return type;
513 }
514
515
516 static void
517 trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
518 {
519 /* Be careful of anything which would not work well with shallow copies */
520 }
521
522
523 static void
524 trace_context_finalize (LttvTraceContext *self)
525 {
526 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
527 finalize(G_OBJECT(self));
528 }
529
530
531 static void
532 trace_context_class_init (LttvTraceContextClass *klass)
533 {
534 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
535
536 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
537 }
538
539
540 GType
541 lttv_trace_context_get_type(void)
542 {
543 static GType type = 0;
544 if (type == 0) {
545 static const GTypeInfo info = {
546 sizeof (LttvTraceContextClass),
547 NULL, /* base_init */
548 NULL, /* base_finalize */
549 (GClassInitFunc) trace_context_class_init, /* class_init */
550 NULL, /* class_finalize */
551 NULL, /* class_data */
552 sizeof (LttvTraceContext),
553 0, /* n_preallocs */
554 (GInstanceInitFunc) trace_context_instance_init, /* instance_init */
555 NULL /* Value handling */
556 };
557
558 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
559 &info, 0);
560 }
561 return type;
562 }
563
564
565 static void
566 tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
567 {
568 /* Be careful of anything which would not work well with shallow copies */
569 }
570
571
572 static void
573 tracefile_context_finalize (LttvTracefileContext *self)
574 {
575 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
576 ->finalize(G_OBJECT(self));
577 }
578
579
580 static void
581 tracefile_context_class_init (LttvTracefileContextClass *klass)
582 {
583 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
584
585 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
586 }
587
588
589 GType
590 lttv_tracefile_context_get_type(void)
591 {
592 static GType type = 0;
593 if (type == 0) {
594 static const GTypeInfo info = {
595 sizeof (LttvTracefileContextClass),
596 NULL, /* base_init */
597 NULL, /* base_finalize */
598 (GClassInitFunc) tracefile_context_class_init, /* class_init */
599 NULL, /* class_finalize */
600 NULL, /* class_data */
601 sizeof (LttvTracefileContext),
602 0, /* n_preallocs */
603 (GInstanceInitFunc) tracefile_context_instance_init, /* instance_init */
604 NULL /* Value handling */
605 };
606
607 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
608 &info, 0);
609 }
610 return type;
611 }
612
613
614
615 static gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
616 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
617 return TRUE;
618 }
619
620
621 /* Put all the tracefiles at the tracefile context position */
622 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *self)
623 {
624 guint iter_trace, nb_trace;
625
626 LttvTraceContext *tc;
627
628 nb_trace = lttv_traceset_number(self->ts);
629
630 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
631 tc = self->traces[iter_trace];
632 {
633 /* each trace */
634 guint iter_tf, nb_tracefile;
635
636 LttvTracefileContext *tfc;
637
638 nb_tracefile = tc->tracefiles->len;
639
640 for(iter_tf = 0 ; iter_tf < nb_tracefile ; iter_tf++) {
641 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, iter_tf);
642 {
643 /* each tracefile */
644 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
645 LttEventPosition *ep = ltt_event_position_new();
646
647 ltt_event_position(ltt_tracefile_get_event(tfc->tf), ep);
648
649 ltt_tracefile_seek_position(tfc->tf, ep);
650 g_free(ep);
651 }
652 }
653 }
654 }
655 }
656
657
658
659 void lttv_process_traceset_begin(LttvTracesetContext *self,
660 LttvHooks *before_traceset,
661 LttvHooks *before_trace,
662 LttvHooks *before_tracefile,
663 LttvHooks *event,
664 LttvHooksById *event_by_id)
665 {
666
667 /* simply add hooks in context. _before hooks are called by add_hooks. */
668 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
669 lttv_traceset_context_add_hooks(self,
670 before_traceset,
671 before_trace,
672 before_tracefile,
673 event,
674 event_by_id);
675
676 }
677
678 /* Note : a _middle must be preceded from a _seek or another middle */
679 guint lttv_process_traceset_middle(LttvTracesetContext *self,
680 LttTime end,
681 guint nb_events,
682 const LttvTracesetContextPosition *end_position)
683 {
684 GTree *pqueue = self->pqueue;
685
686 guint id;
687
688 LttvTracefileContext *tfc;
689
690 LttEvent *e;
691
692 unsigned count = 0;
693
694 gboolean last_ret = FALSE; /* return value of the last hook list called */
695
696 /* Get the next event from the pqueue, call its hooks,
697 reinsert in the pqueue the following event from the same tracefile
698 unless the tracefile is finished or the event is later than the
699 end time. */
700
701 while(TRUE) {
702 tfc = NULL;
703 g_tree_foreach(pqueue, get_first, &tfc);
704 /* End of traceset : tfc is NULL */
705 if(unlikely(tfc == NULL))
706 {
707 return count;
708 }
709
710 /* Have we reached :
711 * - the maximum number of events specified?
712 * - the end position ?
713 * - the end time ?
714 * then the read is finished. We leave the queue in the same state and
715 * break the loop.
716 */
717
718 if(unlikely(last_ret == TRUE ||
719 count >= nb_events ||
720 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
721 end_position) == 0)||
722 ltt_time_compare(end, tfc->timestamp) <= 0))
723 {
724 return count;
725 }
726
727 /* Get the tracefile with an event for the smallest time found. If two
728 or more tracefiles have events for the same time, hope that lookup
729 and remove are consistent. */
730
731 g_tree_remove(pqueue, tfc);
732 count++;
733
734 e = ltt_tracefile_get_event(tfc->tf);
735 id = ltt_event_eventtype_id(e);
736 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
737 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
738
739 if(likely(!ltt_tracefile_read(tfc->tf))) {
740 tfc->timestamp = ltt_event_time(e);
741 g_tree_insert(pqueue, tfc, tfc);
742 }
743 }
744 }
745
746
747 void lttv_process_traceset_end(LttvTracesetContext *self,
748 LttvHooks *after_traceset,
749 LttvHooks *after_trace,
750 LttvHooks *after_tracefile,
751 LttvHooks *event,
752 LttvHooksById *event_by_id)
753 {
754 /* Remove hooks from context. _after hooks are called by remove_hooks. */
755 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
756 lttv_traceset_context_remove_hooks(self,
757 after_traceset,
758 after_trace,
759 after_tracefile,
760 event,
761 event_by_id);
762 }
763
764 void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
765 {
766 guint i, nb_tracefile;
767
768 gint ret;
769
770 LttvTracefileContext *tfc;
771
772 GTree *pqueue = self->ts_context->pqueue;
773
774 nb_tracefile = self->tracefiles->len;
775
776 for(i = 0 ; i < nb_tracefile ; i++) {
777 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
778 ret = ltt_tracefile_seek_time(tfc->tf, start);
779 if(ret) g_error("error in lttv_process_trace_seek_time seek");
780 g_tree_remove(pqueue, tfc);
781 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
782 g_tree_insert(pqueue, tfc, tfc);
783 }
784 }
785
786
787 void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
788 {
789 guint i, nb_trace;
790
791 LttvTraceContext *tc;
792
793 nb_trace = lttv_traceset_number(self->ts);
794 for(i = 0 ; i < nb_trace ; i++) {
795 tc = self->traces[i];
796 lttv_process_trace_seek_time(tc, start);
797 }
798 }
799
800
801 gboolean lttv_process_tracefile_seek_position(LttvTracefileContext *self,
802 const LttEventPosition *pos)
803 {
804 LttvTracefileContext *tfc = self;
805
806 GTree *pqueue = self->t_context->ts_context->pqueue;
807
808 ltt_tracefile_seek_position(tfc->tf, pos);
809 g_tree_remove(pqueue, tfc);
810 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
811 g_tree_insert(pqueue, tfc, tfc);
812
813 return TRUE;
814 }
815
816 gboolean lttv_process_trace_seek_position(LttvTraceContext *self,
817 const LttvTraceContextPosition *pos)
818 {
819 guint i, nb_tracefile;
820
821 LttvTracefileContext *tfc;
822
823 nb_tracefile = self->tracefiles->len;
824
825 if(nb_tracefile != pos->nb_tracefile)
826 return FALSE; /* Error */
827
828 for(i = 0 ; i < nb_tracefile ; i++) {
829 tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i);
830 lttv_process_tracefile_seek_position(tfc, pos->tf_pos[i]);
831 }
832
833 return TRUE;
834 }
835
836
837
838 gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
839 const LttvTracesetContextPosition *pos)
840 {
841 guint i, nb_trace;
842 gboolean sum_ret = TRUE;
843
844 LttvTraceContext *tc;
845
846 nb_trace = lttv_traceset_number(self->ts);
847
848 if(nb_trace != pos->nb_trace)
849 return FALSE; /* Error */
850
851 for(i = 0 ; i < nb_trace ; i++) {
852 tc = self->traces[i];
853 sum_ret = sum_ret && lttv_process_trace_seek_position(tc, &pos->t_pos[i]);
854 }
855
856 return sum_ret;
857 }
858
859
860
861 static LttField *
862 find_field(LttEventType *et, const GQuark field)
863 {
864 LttType *t;
865
866 LttField *f;
867
868 guint i, nb;
869
870 GQuark name;
871
872 /* Field is unset */
873 if(field == 0) return NULL;
874
875 f = ltt_eventtype_field(et);
876 t = ltt_eventtype_type(et);
877 g_assert(ltt_type_class(t) == LTT_STRUCT);
878 nb = ltt_type_member_number(t);
879 for(i = 0 ; i < nb ; i++) {
880 ltt_type_member_type(t, i, &name);
881 if(name == field) break;
882 }
883 g_assert(i < nb);
884 return ltt_field_member(f, i);
885 }
886
887 LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
888 guint facility_id)
889 {
890 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
891 }
892
893 /* Get the first facility corresponding to the name. As the types must be
894 * compatible, it is relevant to use the field name and sizes of the first
895 * facility to create data structures and assume the data will be compatible
896 * thorough the trace */
897 LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
898 {
899 g_assert(th->fac_list->len > 0);
900 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
901 }
902
903
904 /* Returns 0 on success, -1 if fails. */
905 gint
906 lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
907 GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th)
908 {
909 LttFacility *f;
910
911 LttEventType *et, *first_et;
912
913 GArray *facilities;
914
915 guint i, fac_id;
916
917 LttvTraceHookByFacility *thf, *first_thf;
918
919 facilities = ltt_trace_facility_get_by_name(t, facility);
920
921 if(unlikely(facilities == NULL)) goto facility_error;
922
923 th->fac_index = g_array_sized_new(FALSE, TRUE,
924 sizeof(LttvTraceHookByFacility),
925 NUM_FACILITIES);
926 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
927
928 th->fac_list = g_array_sized_new(FALSE, TRUE,
929 sizeof(LttvTraceHookByFacility*),
930 facilities->len);
931 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
932
933 fac_id = g_array_index(facilities, guint, 0);
934 f = ltt_trace_get_facility_by_num(t, fac_id);
935
936 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
937 if(unlikely(et == NULL)) goto event_error;
938
939 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
940 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0)
941 = thf;
942 thf->h = h;
943 thf->id = ltt_eventtype_id(et);
944 thf->f1 = find_field(et, field1);
945 thf->f2 = find_field(et, field2);
946 thf->f3 = find_field(et, field3);
947
948 first_thf = thf;
949
950 /* Check for type compatibility too */
951 for(i=1;i<facilities->len;i++) {
952 fac_id = g_array_index(facilities, guint, i);
953 f = ltt_trace_get_facility_by_num(t, fac_id);
954
955 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
956 if(unlikely(et == NULL)) goto event_error;
957
958 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
959 g_array_index(th->fac_list, LttvTraceHookByFacility*, i)
960 = thf;
961 thf->h = h;
962 thf->id = ltt_eventtype_id(et);
963 thf->f1 = find_field(et, field1);
964 if(check_fields_compatibility(first_et, et,
965 first_thf->f1, thf->f1))
966 goto type_error;
967
968 thf->f2 = find_field(et, field2);
969 if(check_fields_compatibility(first_et, et,
970 first_thf->f2, thf->f2))
971 goto type_error;
972
973 thf->f3 = find_field(et, field3);
974 if(check_fields_compatibility(first_et, et,
975 first_thf->f3, thf->f3))
976 goto type_error;
977 }
978
979 return 0;
980
981 type_error:
982 goto free;
983 event_error:
984 g_error("Event type %s does not exist",
985 g_quark_to_string(ltt_eventtype_name(et)));
986 goto free;
987 facility_error:
988 g_error("No %s facility", g_quark_to_string(facility));
989 goto free;
990 free:
991 g_array_free(th->fac_index, TRUE);
992 g_array_free(th->fac_list, TRUE);
993 th->fac_index = NULL;
994 th->fac_list = NULL;
995 return -1;
996 }
997
998 void lttv_trace_hook_destroy(LttvTraceHook *th)
999 {
1000 g_array_free(th->fac_index, TRUE);
1001 g_array_free(th->fac_list, TRUE);
1002 }
1003
1004
1005 LttvTracesetContextPosition *lttv_traceset_context_position_new()
1006 {
1007 return g_new(LttvTracesetContextPosition,1);
1008 }
1009
1010
1011 void lttv_traceset_context_position_save(const LttvTracesetContext *self,
1012 LttvTracesetContextPosition *pos)
1013 {
1014 guint nb_trace, nb_tracefile;
1015 guint iter_trace, iter_tracefile;
1016
1017 LttvTraceContext *tc;
1018
1019 LttvTracefileContext *tfc;
1020
1021 LttEvent *event;
1022
1023 LttTime timestamp = self->time_span.end_time;
1024
1025 pos->nb_trace = nb_trace = lttv_traceset_number(self->ts);
1026 pos->t_pos = g_new(LttvTraceContextPosition, nb_trace);
1027
1028 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1029 tc = self->traces[iter_trace];
1030
1031 nb_tracefile = tc->tracefiles->len;
1032 pos->t_pos[iter_trace].nb_tracefile = nb_tracefile;
1033
1034 pos->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
1035 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1036 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext,
1037 iter_tracefile);
1038 event = ltt_tracefile_get_event(tfc->tf);
1039 if(event!=NULL) {
1040 pos->t_pos[iter_trace].tf_pos[iter_tracefile]
1041 = ltt_event_position_new();
1042 ltt_event_position(event,
1043 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1044 } else {
1045 pos->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
1046 }
1047 if(ltt_time_compare(tfc->timestamp, timestamp) < 0)
1048 timestamp = tfc->timestamp;
1049 }
1050 }
1051 pos->timestamp = timestamp;
1052 }
1053
1054 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1055 {
1056 guint nb_trace;
1057 guint iter_trace, iter_tracefile;
1058
1059 nb_trace = pos->nb_trace;
1060
1061 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1062 for(iter_tracefile = 0; iter_tracefile <
1063 pos->t_pos[iter_trace].nb_tracefile;
1064 iter_tracefile++) {
1065 if(pos->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
1066 g_free(pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1067 }
1068 g_free(pos->t_pos[iter_trace].tf_pos);
1069 }
1070 g_free(pos->t_pos);
1071
1072 }
1073
1074 void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1075 const LttvTracesetContextPosition *src)
1076 {
1077 guint nb_trace, nb_tracefile;
1078 guint iter_trace, iter_tracefile;
1079
1080 nb_trace = dest->nb_trace = src->nb_trace;
1081 dest->t_pos = g_new(LttvTraceContextPosition, nb_trace);
1082
1083 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1084
1085 nb_tracefile = src->t_pos[iter_trace].nb_tracefile;
1086
1087 dest->t_pos[iter_trace].nb_tracefile = nb_tracefile;
1088
1089 dest->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
1090
1091 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1092 dest->t_pos[iter_trace].tf_pos[iter_tracefile] =
1093 ltt_event_position_new();
1094 if(src->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
1095 ltt_event_position_copy(
1096 dest->t_pos[iter_trace].tf_pos[iter_tracefile],
1097 src->t_pos[iter_trace].tf_pos[iter_tracefile]);
1098 else
1099 dest->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
1100 }
1101 }
1102
1103 dest->timestamp = src->timestamp;
1104 }
1105
1106 gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1107 const LttvTracesetContextPosition *pos)
1108 {
1109 guint nb_trace, nb_tracefile;
1110 guint iter_trace, iter_tracefile;
1111 gint ret;
1112
1113 LttvTraceContext *tc;
1114
1115 LttvTracefileContext *tfc;
1116
1117 LttEvent *event;
1118
1119 nb_trace = lttv_traceset_number(self->ts);
1120
1121 if(unlikely(pos->nb_trace != nb_trace))
1122 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
1123
1124 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1125 tc = self->traces[iter_trace];
1126 nb_tracefile = tc->tracefiles->len;
1127
1128 if(unlikely(pos->t_pos[iter_trace].nb_tracefile != nb_tracefile))
1129 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1130
1131 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1132 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext,
1133 iter_tracefile);
1134 event = ltt_tracefile_get_event(tfc->tf);
1135 ret = ltt_event_position_compare((LttEventPosition*)event,
1136 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1137 if(ret != 0)
1138 return ret;
1139 }
1140 }
1141 return 0;
1142 }
1143
1144
1145 gint lttv_traceset_context_pos_pos_compare(
1146 const LttvTracesetContextPosition *pos1,
1147 const LttvTracesetContextPosition *pos2)
1148 {
1149 guint nb_trace, nb_tracefile;
1150 guint iter_trace, iter_tracefile;
1151
1152 gint ret;
1153
1154 nb_trace = pos1->nb_trace;
1155 if(unlikely(nb_trace != pos2->nb_trace))
1156 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1157
1158 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1159
1160 nb_tracefile = pos1->t_pos[iter_trace].nb_tracefile;
1161 if(unlikely(nb_tracefile != pos2->t_pos[iter_trace].nb_tracefile))
1162 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1163
1164 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1165 ret = ltt_event_position_compare(
1166 pos1->t_pos[iter_trace].tf_pos[iter_tracefile],
1167 pos2->t_pos[iter_trace].tf_pos[iter_tracefile]);
1168 if(ret != 0)
1169 return ret;
1170 }
1171 }
1172 return 0;
1173 }
1174
1175
1176 LttTime lttv_traceset_context_position_get_time(
1177 const LttvTracesetContextPosition *pos)
1178 {
1179 return pos->timestamp;
1180 }
1181
1182
1183 LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1184 {
1185 GTree *pqueue = self->pqueue;
1186 LttvTracefileContext *tfc = NULL;
1187
1188 g_tree_foreach(pqueue, get_first, &tfc);
1189
1190 return tfc;
1191 }
This page took 0.067674 seconds and 4 git commands to generate.