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