1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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;
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.
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,
24 #include <lttv/tracecontext.h>
25 #include <ltt/event.h>
26 #include <ltt/facility.h>
27 #include <ltt/trace.h>
33 static gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
37 const LttvTracefileContext
*trace_a
= (const LttvTracefileContext
*)a
;
38 const LttvTracefileContext
*trace_b
= (const LttvTracefileContext
*)b
;
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
)
47 else if(trace_a
->t_context
->index
> trace_b
->t_context
->index
)
54 struct _LttvTraceContextPosition
{
55 LttEventPosition
**tf_pos
; /* Position in each tracefile */
56 guint nb_tracefile
; /* Number of tracefiles (check) */
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 */
65 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
67 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
71 void lttv_context_fini(LttvTracesetContext
*self
)
73 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
78 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
80 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
87 lttv_context_new_trace_context(LttvTracesetContext
*self
)
89 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
93 LttvTracefileContext
*
94 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
96 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
99 /****************************************************************************
100 * lttv_traceset_context_compute_time_span
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
108 * Author : Xang Xiu Yang
109 ***************************************************************************/
110 static void lttv_traceset_context_compute_time_span(
111 LttvTracesetContext
*self
,
112 TimeInterval
*time_span
)
114 LttvTraceset
* traceset
= self
->ts
;
115 int numTraces
= lttv_traceset_number(traceset
);
118 LttvTraceContext
*tc
;
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;
126 for(i
=0; i
<numTraces
;i
++){
127 tc
= self
->traces
[i
];
130 ltt_trace_time_span_get(trace
, &s
, &e
);
133 time_span
->start_time
= s
;
134 time_span
->end_time
= e
;
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
;
148 static void init_tracefile_context(LttTracefile
*tracefile
,
149 LttvTraceContext
*tc
)
151 LttvTracefileContext
*tfc
;
152 LttvTracesetContext
*tsc
= tc
->ts_context
;
154 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(tsc
)->new_tracefile_context(tsc
);
156 tfc
->index
= tc
->tracefiles
->len
;
157 tc
->tracefiles
= g_array_append_val(tc
->tracefiles
, tfc
);
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
);
169 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
171 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
173 LttvTraceContext
*tc
;
175 GData
**tracefiles_groups
;
177 struct compute_tracefile_group_args args
;
179 nb_trace
= lttv_traceset_number(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
;
188 tc
->ts_context
= self
;
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);
197 tracefiles_groups
= ltt_trace_get_tracefiles_groups(tc
->t
);
199 args
.func
= (ForEachTraceFileFunc
)init_tracefile_context
;
202 g_datalist_foreach(tracefiles_groups
,
203 (GDataForeachFunc
)compute_tracefile_group
,
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
);
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
;
219 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
222 tfc
->control
= FALSE
;
223 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
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
);
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
);
242 void fini(LttvTracesetContext
*self
)
244 guint i
, j
, nb_trace
, nb_tracefile
;
246 LttvTraceContext
*tc
;
248 LttvTracefileContext
*tfc
;
250 LttvTraceset
*ts
= self
->ts
;
254 g_tree_destroy(self
->pqueue
);
255 g_object_unref(self
->a
);
257 nb_trace
= lttv_traceset_number(ts
);
259 for(i
= 0 ; i
< nb_trace
; i
++) {
260 tc
= self
->traces
[i
];
262 g_object_unref(tc
->a
);
264 nb_tracefile
= tc
->tracefiles
->len
;
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
);
273 g_array_free(tc
->tracefiles
, TRUE
);
276 g_free(self
->traces
);
280 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
281 LttvHooks
*before_traceset
,
282 LttvHooks
*before_trace
,
283 LttvHooks
*before_tracefile
,
285 LttvHooksById
*event_by_id
)
287 LttvTraceset
*ts
= self
->ts
;
291 LttvTraceContext
*tc
;
293 lttv_hooks_call(before_traceset
, self
);
295 nb_trace
= lttv_traceset_number(ts
);
297 for(i
= 0 ; i
< nb_trace
; i
++) {
298 tc
= self
->traces
[i
];
299 lttv_trace_context_add_hooks(tc
,
308 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
309 LttvHooks
*after_traceset
,
310 LttvHooks
*after_trace
,
311 LttvHooks
*after_tracefile
,
313 LttvHooksById
*event_by_id
)
316 LttvTraceset
*ts
= self
->ts
;
320 LttvTraceContext
*tc
;
322 nb_trace
= lttv_traceset_number(ts
);
324 for(i
= 0 ; i
< nb_trace
; i
++) {
325 tc
= self
->traces
[i
];
326 lttv_trace_context_remove_hooks(tc
,
333 lttv_hooks_call(after_traceset
, self
);
338 void lttv_trace_context_add_hooks(LttvTraceContext
*self
,
339 LttvHooks
*before_trace
,
340 LttvHooks
*before_tracefile
,
342 LttvHooksById
*event_by_id
)
344 guint i
, nb_tracefile
;
346 LttvTracefileContext
*tfc
;
348 lttv_hooks_call(before_trace
, self
);
350 nb_tracefile
= self
->tracefiles
->len
;
352 for(i
= 0 ; i
< nb_tracefile
; i
++) {
353 tfc
= &g_array_index(self
->tracefiles
, LttvTracefileContext
, i
);
354 lttv_tracefile_context_add_hooks(tfc
,
363 void lttv_trace_context_remove_hooks(LttvTraceContext
*self
,
364 LttvHooks
*after_trace
,
365 LttvHooks
*after_tracefile
,
367 LttvHooksById
*event_by_id
)
369 guint i
, nb_tracefile
;
371 LttvTracefileContext
*tfc
;
373 nb_tracefile
= self
->tracefiles
->len
;
375 for(i
= 0 ; i
< nb_tracefile
; i
++) {
376 tfc
= &g_array_index(self
->tracefiles
, LttvTracefileContext
, i
);
377 lttv_tracefile_context_remove_hooks(tfc
,
383 lttv_hooks_call(after_trace
, self
);
386 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*self
,
387 LttvHooks
*before_tracefile
,
389 LttvHooksById
*event_by_id
)
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
));
405 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*self
,
406 LttvHooks
*after_tracefile
,
408 LttvHooksById
*event_by_id
)
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
);
420 lttv_hooks_remove_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
423 lttv_hooks_call(after_tracefile
, self
);
428 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
430 LttvHooks
*event_by_id
)
433 h
= lttv_hooks_by_id_find(tfc
->event_by_id
, i
);
434 lttv_hooks_add_list(h
, event_by_id
);
437 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
440 lttv_hooks_by_id_remove(tfc
->event_by_id
, i
);
443 static LttvTracesetContext
*
444 new_traceset_context(LttvTracesetContext
*self
)
446 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
450 static LttvTraceContext
*
451 new_trace_context(LttvTracesetContext
*self
)
453 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
457 static LttvTracefileContext
*
458 new_tracefile_context(LttvTracesetContext
*self
)
460 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
465 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
467 /* Be careful of anything which would not work well with shallow copies */
472 traceset_context_finalize (LttvTracesetContext
*self
)
474 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
475 ->finalize(G_OBJECT(self
));
480 traceset_context_class_init (LttvTracesetContextClass
*klass
)
482 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
484 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
487 klass
->new_traceset_context
= new_traceset_context
;
488 klass
->new_trace_context
= new_trace_context
;
489 klass
->new_tracefile_context
= new_tracefile_context
;
494 lttv_traceset_context_get_type(void)
496 static GType 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
),
507 (GInstanceInitFunc
) traceset_context_instance_init
, /* instance_init */
508 NULL
/* Value handling */
511 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
519 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
521 /* Be careful of anything which would not work well with shallow copies */
526 trace_context_finalize (LttvTraceContext
*self
)
528 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
529 finalize(G_OBJECT(self
));
534 trace_context_class_init (LttvTraceContextClass
*klass
)
536 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
538 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
543 lttv_trace_context_get_type(void)
545 static GType 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
),
556 (GInstanceInitFunc
) trace_context_instance_init
, /* instance_init */
557 NULL
/* Value handling */
560 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
568 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
570 /* Be careful of anything which would not work well with shallow copies */
575 tracefile_context_finalize (LttvTracefileContext
*self
)
577 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
578 ->finalize(G_OBJECT(self
));
583 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
585 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
587 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
592 lttv_tracefile_context_get_type(void)
594 static GType 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
),
605 (GInstanceInitFunc
) tracefile_context_instance_init
, /* instance_init */
606 NULL
/* Value handling */
609 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
617 static gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
618 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
623 /* Put all the tracefiles at the tracefile context position */
624 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext
*self
)
626 guint iter_trace
, nb_trace
;
628 LttvTraceContext
*tc
;
630 nb_trace
= lttv_traceset_number(self
->ts
);
632 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
633 tc
= self
->traces
[iter_trace
];
636 guint iter_tf
, nb_tracefile
;
638 LttvTracefileContext
*tfc
;
640 nb_tracefile
= tc
->tracefiles
->len
;
642 for(iter_tf
= 0 ; iter_tf
< nb_tracefile
; iter_tf
++) {
643 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, iter_tf
);
646 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
647 LttEventPosition
*ep
= ltt_event_position_new();
649 ltt_event_position(ltt_tracefile_get_event(tfc
->tf
), ep
);
651 ltt_tracefile_seek_position(tfc
->tf
, ep
);
661 void lttv_process_traceset_begin(LttvTracesetContext
*self
,
662 LttvHooks
*before_traceset
,
663 LttvHooks
*before_trace
,
664 LttvHooks
*before_tracefile
,
666 LttvHooksById
*event_by_id
)
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
,
680 /* Note : a _middle must be preceded from a _seek or another middle */
681 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
,
684 const LttvTracesetContextPosition
*end_position
)
686 GTree
*pqueue
= self
->pqueue
;
690 LttvTracefileContext
*tfc
;
696 gboolean last_ret
= FALSE
; /* return value of the last hook list called */
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
705 g_tree_foreach(pqueue
, get_first
, &tfc
);
706 /* End of traceset : tfc is NULL */
707 if(unlikely(tfc
== NULL
))
713 * - the maximum number of events specified?
714 * - the end position ?
716 * then the read is finished. We leave the queue in the same state and
720 if(unlikely(last_ret
== TRUE
||
721 count
>= nb_events
||
722 (end_position
!=NULL
&<tv_traceset_context_ctx_pos_compare(self
,
723 end_position
) == 0)||
724 ltt_time_compare(end
, tfc
->timestamp
) <= 0))
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. */
733 g_tree_remove(pqueue
, tfc
);
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
);
741 if(likely(!ltt_tracefile_read(tfc
->tf
))) {
742 tfc
->timestamp
= ltt_event_time(e
);
743 g_tree_insert(pqueue
, tfc
, tfc
);
749 void lttv_process_traceset_end(LttvTracesetContext
*self
,
750 LttvHooks
*after_traceset
,
751 LttvHooks
*after_trace
,
752 LttvHooks
*after_tracefile
,
754 LttvHooksById
*event_by_id
)
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
,
766 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
768 guint i
, nb_tracefile
;
772 LttvTracefileContext
*tfc
;
774 GTree
*pqueue
= self
->ts_context
->pqueue
;
776 nb_tracefile
= self
->tracefiles
->len
;
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
);
789 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
793 LttvTraceContext
*tc
;
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
);
803 gboolean
lttv_process_tracefile_seek_position(LttvTracefileContext
*self
,
804 const LttEventPosition
*pos
)
806 LttvTracefileContext
*tfc
= self
;
808 GTree
*pqueue
= self
->t_context
->ts_context
->pqueue
;
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
);
818 gboolean
lttv_process_trace_seek_position(LttvTraceContext
*self
,
819 const LttvTraceContextPosition
*pos
)
821 guint i
, nb_tracefile
;
823 LttvTracefileContext
*tfc
;
825 nb_tracefile
= self
->tracefiles
->len
;
827 if(nb_tracefile
!= pos
->nb_tracefile
)
828 return FALSE
; /* Error */
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
]);
840 gboolean
lttv_process_traceset_seek_position(LttvTracesetContext
*self
,
841 const LttvTracesetContextPosition
*pos
)
844 gboolean sum_ret
= TRUE
;
846 LttvTraceContext
*tc
;
848 nb_trace
= lttv_traceset_number(self
->ts
);
850 if(nb_trace
!= pos
->nb_trace
)
851 return FALSE
; /* Error */
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
]);
864 find_field(LttEventType
*et
, const GQuark field
)
875 if(field
== 0) return NULL
;
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;
886 return ltt_field_member(f
, i
);
889 LttvTraceHookByFacility
*lttv_trace_hook_get_fac(LttvTraceHook
*th
,
892 return &g_array_index(th
->fac_index
, LttvTraceHookByFacility
, facility_id
);
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 */
899 LttvTraceHookByFacility
*lttv_trace_hook_get_first(LttvTraceHook
*th
)
901 g_assert(th
->fac_list
->len
> 0);
902 return g_array_index(th
->fac_list
, LttvTraceHookByFacility
*, 0);
906 /* Returns 0 on success, -1 if fails. */
908 lttv_trace_find_hook(LttTrace
*t
, GQuark facility
, GQuark event
,
909 GQuark field1
, GQuark field2
, GQuark field3
, LttvHook h
, LttvTraceHook
*th
)
913 LttEventType
*et
, *first_et
;
919 LttvTraceHookByFacility
*thf
, *first_thf
;
921 facilities
= ltt_trace_facility_get_by_name(t
, facility
);
923 if(unlikely(facilities
== NULL
)) goto facility_error
;
925 th
->fac_index
= g_array_sized_new(FALSE
, TRUE
,
926 sizeof(LttvTraceHookByFacility
),
928 th
->fac_index
= g_array_set_size(th
->fac_index
, NUM_FACILITIES
);
930 th
->fac_list
= g_array_sized_new(FALSE
, TRUE
,
931 sizeof(LttvTraceHookByFacility
*),
933 th
->fac_list
= g_array_set_size(th
->fac_list
, facilities
->len
);
935 fac_id
= g_array_index(facilities
, guint
, 0);
936 f
= ltt_trace_get_facility_by_num(t
, fac_id
);
938 et
= ltt_facility_eventtype_get_by_name(f
, ltt_eventtype_name(et
));
939 if(unlikely(et
== NULL
)) goto event_error
;
941 thf
= &g_array_index(th
->fac_index
, LttvTraceHookByFacility
, fac_id
);
942 g_array_index(th
->fac_list
, LttvTraceHookByFacility
*, 0)
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
);
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
);
957 et
= ltt_facility_eventtype_get_by_name(f
, ltt_eventtype_name(et
));
958 if(unlikely(et
== NULL
)) goto event_error
;
960 thf
= &g_array_index(th
->fac_index
, LttvTraceHookByFacility
, fac_id
);
961 g_array_index(th
->fac_list
, LttvTraceHookByFacility
*, i
)
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
))
970 thf
->f2
= find_field(et
, field2
);
971 if(check_fields_compatibility(first_et
, et
,
972 first_thf
->f2
, thf
->f2
))
975 thf
->f3
= find_field(et
, field3
);
976 if(check_fields_compatibility(first_et
, et
,
977 first_thf
->f3
, thf
->f3
))
986 g_error("Event type %s does not exist",
987 g_quark_to_string(ltt_eventtype_name(et
)));
990 g_error("No %s facility", g_quark_to_string(facility
));
993 g_array_free(th
->fac_index
, TRUE
);
994 g_array_free(th
->fac_list
, TRUE
);
995 th
->fac_index
= NULL
;
1000 void lttv_trace_hook_destroy(LttvTraceHook
*th
)
1002 g_array_free(th
->fac_index
, TRUE
);
1003 g_array_free(th
->fac_list
, TRUE
);
1007 LttvTracesetContextPosition
*lttv_traceset_context_position_new()
1009 return g_new(LttvTracesetContextPosition
,1);
1013 void lttv_traceset_context_position_save(const LttvTracesetContext
*self
,
1014 LttvTracesetContextPosition
*pos
)
1016 guint nb_trace
, nb_tracefile
;
1017 guint iter_trace
, iter_tracefile
;
1019 LttvTraceContext
*tc
;
1021 LttvTracefileContext
*tfc
;
1025 LttTime timestamp
= self
->time_span
.end_time
;
1027 pos
->nb_trace
= nb_trace
= lttv_traceset_number(self
->ts
);
1028 pos
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
1030 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1031 tc
= self
->traces
[iter_trace
];
1033 nb_tracefile
= tc
->tracefiles
->len
;
1034 pos
->t_pos
[iter_trace
].nb_tracefile
= nb_tracefile
;
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
*,
1040 event
= ltt_tracefile_get_event(tfc
->tf
);
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
]);
1047 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
1049 if(ltt_time_compare(tfc
->timestamp
, timestamp
) < 0)
1050 timestamp
= tfc
->timestamp
;
1053 pos
->timestamp
= timestamp
;
1056 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition
*pos
)
1059 guint iter_trace
, iter_tracefile
;
1061 nb_trace
= pos
->nb_trace
;
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
;
1067 if(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
1068 g_free(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1070 g_free(pos
->t_pos
[iter_trace
].tf_pos
);
1076 void lttv_traceset_context_position_copy(LttvTracesetContextPosition
*dest
,
1077 const LttvTracesetContextPosition
*src
)
1079 guint nb_trace
, nb_tracefile
;
1080 guint iter_trace
, iter_tracefile
;
1082 nb_trace
= dest
->nb_trace
= src
->nb_trace
;
1083 dest
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
1085 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1087 nb_tracefile
= src
->t_pos
[iter_trace
].nb_tracefile
;
1089 dest
->t_pos
[iter_trace
].nb_tracefile
= nb_tracefile
;
1091 dest
->t_pos
[iter_trace
].tf_pos
= g_new(LttEventPosition
*, nb_tracefile
);
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
]);
1101 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
1105 dest
->timestamp
= src
->timestamp
;
1108 gint
lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext
*self
,
1109 const LttvTracesetContextPosition
*pos
)
1111 guint nb_trace
, nb_tracefile
;
1112 guint iter_trace
, iter_tracefile
;
1115 LttvTraceContext
*tc
;
1117 LttvTracefileContext
*tfc
;
1121 nb_trace
= lttv_traceset_number(self
->ts
);
1123 if(unlikely(pos
->nb_trace
!= nb_trace
))
1124 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
1126 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1127 tc
= self
->traces
[iter_trace
];
1128 nb_tracefile
= tc
->tracefiles
->len
;
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.");
1133 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1134 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*,
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
]);
1147 gint
lttv_traceset_context_pos_pos_compare(
1148 const LttvTracesetContextPosition
*pos1
,
1149 const LttvTracesetContextPosition
*pos2
)
1151 guint nb_trace
, nb_tracefile
;
1152 guint iter_trace
, iter_tracefile
;
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.");
1160 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
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.");
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
]);
1178 LttTime
lttv_traceset_context_position_get_time(
1179 const LttvTracesetContextPosition
*pos
)
1181 return pos
->timestamp
;
1185 LttvTracefileContext
*lttv_traceset_context_get_current_tfc(LttvTracesetContext
*self
)
1187 GTree
*pqueue
= self
->pqueue
;
1188 LttvTracefileContext
*tfc
= NULL
;
1190 g_tree_foreach(pqueue
, get_first
, &tfc
);