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
;
150 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
152 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
154 LttvTraceContext
*tc
;
156 LttvTracefileContext
*tfc
;
158 LttTime null_time
= {0, 0};
160 nb_trace
= lttv_traceset_number(ts
);
162 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
163 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
164 self
->ts_a
= lttv_traceset_attribute(ts
);
165 for(i
= 0 ; i
< nb_trace
; i
++) {
166 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
167 self
->traces
[i
] = tc
;
169 tc
->ts_context
= self
;
171 tc
->vt
= lttv_traceset_get(ts
, i
);
172 tc
->t
= lttv_trace(tc
->vt
);
173 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
174 tc
->t_a
= lttv_trace_attribute(tc
->vt
);
175 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
176 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
177 nb_tracefile
= nb_control
+ nb_per_cpu
;
178 tc
->tracefiles
= g_new(LttvTracefileContext
*, nb_tracefile
);
180 for(j
= 0 ; j
< nb_tracefile
; j
++) {
181 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
182 tc
->tracefiles
[j
] = tfc
;
187 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
190 tfc
->control
= FALSE
;
191 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
194 tfc
->e
= ltt_event_new();
195 tfc
->event
= lttv_hooks_new();
196 tfc
->event_by_id
= lttv_hooks_by_id_new();
197 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
200 self
->pqueue
= g_tree_new(compare_tracefile
);
201 lttv_process_traceset_seek_time(self
, null_time
);
202 lttv_traceset_context_compute_time_span(self
, &self
->time_span
);
207 void fini(LttvTracesetContext
*self
)
209 guint i
, j
, nb_trace
, nb_tracefile
;
211 LttvTraceContext
*tc
;
213 LttvTracefileContext
*tfc
;
215 LttvTraceset
*ts
= self
->ts
;
219 g_tree_destroy(self
->pqueue
);
220 g_object_unref(self
->a
);
222 nb_trace
= lttv_traceset_number(ts
);
224 for(i
= 0 ; i
< nb_trace
; i
++) {
225 tc
= self
->traces
[i
];
227 g_object_unref(tc
->a
);
229 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
230 ltt_trace_per_cpu_tracefile_number(tc
->t
);
232 for(j
= 0 ; j
< nb_tracefile
; j
++) {
233 tfc
= tc
->tracefiles
[j
];
234 ltt_event_destroy(tfc
->e
);
235 lttv_hooks_destroy(tfc
->event
);
236 lttv_hooks_by_id_destroy(tfc
->event_by_id
);
237 g_object_unref(tfc
->a
);
240 g_free(tc
->tracefiles
);
243 g_free(self
->traces
);
247 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
248 LttvHooks
*before_traceset
,
249 LttvHooks
*before_trace
,
250 LttvHooks
*before_tracefile
,
252 LttvHooksById
*event_by_id
)
254 LttvTraceset
*ts
= self
->ts
;
258 LttvTraceContext
*tc
;
260 lttv_hooks_call(before_traceset
, self
);
262 nb_trace
= lttv_traceset_number(ts
);
264 for(i
= 0 ; i
< nb_trace
; i
++) {
265 tc
= self
->traces
[i
];
266 lttv_trace_context_add_hooks(tc
,
275 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
276 LttvHooks
*after_traceset
,
277 LttvHooks
*after_trace
,
278 LttvHooks
*after_tracefile
,
280 LttvHooksById
*event_by_id
)
283 LttvTraceset
*ts
= self
->ts
;
287 LttvTraceContext
*tc
;
289 nb_trace
= lttv_traceset_number(ts
);
291 for(i
= 0 ; i
< nb_trace
; i
++) {
292 tc
= self
->traces
[i
];
293 lttv_trace_context_remove_hooks(tc
,
300 lttv_hooks_call(after_traceset
, self
);
305 void lttv_trace_context_add_hooks(LttvTraceContext
*self
,
306 LttvHooks
*before_trace
,
307 LttvHooks
*before_tracefile
,
309 LttvHooksById
*event_by_id
)
311 guint i
, nb_tracefile
;
313 LttvTracefileContext
*tfc
;
315 lttv_hooks_call(before_trace
, self
);
316 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
317 ltt_trace_per_cpu_tracefile_number(self
->t
);
319 for(i
= 0 ; i
< nb_tracefile
; i
++) {
320 tfc
= self
->tracefiles
[i
];
321 lttv_tracefile_context_add_hooks(tfc
,
330 void lttv_trace_context_remove_hooks(LttvTraceContext
*self
,
331 LttvHooks
*after_trace
,
332 LttvHooks
*after_tracefile
,
334 LttvHooksById
*event_by_id
)
336 guint i
, nb_tracefile
;
338 LttvTracefileContext
*tfc
;
340 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
341 ltt_trace_per_cpu_tracefile_number(self
->t
);
343 for(i
= 0 ; i
< nb_tracefile
; i
++) {
344 tfc
= self
->tracefiles
[i
];
345 lttv_tracefile_context_remove_hooks(tfc
,
351 lttv_hooks_call(after_trace
, self
);
354 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*self
,
355 LttvHooks
*before_tracefile
,
357 LttvHooksById
*event_by_id
)
363 lttv_hooks_call(before_tracefile
, self
);
364 lttv_hooks_add_list(self
->event
, event
);
365 if(event_by_id
!= NULL
)
366 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
367 hook
= lttv_hooks_by_id_find(self
->event_by_id
, i
);
368 lttv_hooks_add_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
373 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*self
,
374 LttvHooks
*after_tracefile
,
376 LttvHooksById
*event_by_id
)
383 lttv_hooks_remove_list(self
->event
, event
);
384 if(event_by_id
!= NULL
)
385 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
386 hook
= lttv_hooks_by_id_get(self
->event_by_id
, i
);
388 lttv_hooks_remove_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
391 lttv_hooks_call(after_tracefile
, self
);
396 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
398 LttvHooks
*event_by_id
)
401 h
= lttv_hooks_by_id_find(tfc
->event_by_id
, i
);
402 lttv_hooks_add_list(h
, event_by_id
);
405 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
408 lttv_hooks_by_id_remove(tfc
->event_by_id
, i
);
411 static LttvTracesetContext
*
412 new_traceset_context(LttvTracesetContext
*self
)
414 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
418 static LttvTraceContext
*
419 new_trace_context(LttvTracesetContext
*self
)
421 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
425 static LttvTracefileContext
*
426 new_tracefile_context(LttvTracesetContext
*self
)
428 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
433 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
435 /* Be careful of anything which would not work well with shallow copies */
440 traceset_context_finalize (LttvTracesetContext
*self
)
442 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
443 ->finalize(G_OBJECT(self
));
448 traceset_context_class_init (LttvTracesetContextClass
*klass
)
450 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
452 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
455 klass
->new_traceset_context
= new_traceset_context
;
456 klass
->new_trace_context
= new_trace_context
;
457 klass
->new_tracefile_context
= new_tracefile_context
;
462 lttv_traceset_context_get_type(void)
464 static GType type
= 0;
466 static const GTypeInfo info
= {
467 sizeof (LttvTracesetContextClass
),
468 NULL
, /* base_init */
469 NULL
, /* base_finalize */
470 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
471 NULL
, /* class_finalize */
472 NULL
, /* class_data */
473 sizeof (LttvTracesetContext
),
475 (GInstanceInitFunc
) traceset_context_instance_init
, /* instance_init */
476 NULL
/* Value handling */
479 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
487 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
489 /* Be careful of anything which would not work well with shallow copies */
494 trace_context_finalize (LttvTraceContext
*self
)
496 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
497 finalize(G_OBJECT(self
));
502 trace_context_class_init (LttvTraceContextClass
*klass
)
504 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
506 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
511 lttv_trace_context_get_type(void)
513 static GType type
= 0;
515 static const GTypeInfo info
= {
516 sizeof (LttvTraceContextClass
),
517 NULL
, /* base_init */
518 NULL
, /* base_finalize */
519 (GClassInitFunc
) trace_context_class_init
, /* class_init */
520 NULL
, /* class_finalize */
521 NULL
, /* class_data */
522 sizeof (LttvTraceContext
),
524 (GInstanceInitFunc
) trace_context_instance_init
, /* instance_init */
525 NULL
/* Value handling */
528 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
536 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
538 /* Be careful of anything which would not work well with shallow copies */
543 tracefile_context_finalize (LttvTracefileContext
*self
)
545 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
546 ->finalize(G_OBJECT(self
));
551 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
553 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
555 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
560 lttv_tracefile_context_get_type(void)
562 static GType type
= 0;
564 static const GTypeInfo info
= {
565 sizeof (LttvTracefileContextClass
),
566 NULL
, /* base_init */
567 NULL
, /* base_finalize */
568 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
569 NULL
, /* class_finalize */
570 NULL
, /* class_data */
571 sizeof (LttvTracefileContext
),
573 (GInstanceInitFunc
) tracefile_context_instance_init
, /* instance_init */
574 NULL
/* Value handling */
577 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
585 static gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
586 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
591 /* Put all the tracefiles at the tracefile context position */
592 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext
*self
)
594 guint iter_trace
, nb_trace
;
596 LttvTraceContext
*tc
;
598 nb_trace
= lttv_traceset_number(self
->ts
);
600 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
601 tc
= self
->traces
[iter_trace
];
604 guint iter_tf
, nb_tracefile
;
606 LttvTracefileContext
*tfc
;
608 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
609 ltt_trace_per_cpu_tracefile_number(tc
->t
);
611 for(iter_tf
= 0 ; iter_tf
< nb_tracefile
; iter_tf
++) {
612 tfc
= tc
->tracefiles
[iter_tf
];
615 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
616 LttEventPosition
*ep
= ltt_event_position_new();
618 ltt_event_position(tfc
->e
, ep
);
620 ltt_tracefile_seek_position(tfc
->tf
, ep
);
630 void lttv_process_traceset_begin(LttvTracesetContext
*self
,
631 LttvHooks
*before_traceset
,
632 LttvHooks
*before_trace
,
633 LttvHooks
*before_tracefile
,
635 LttvHooksById
*event_by_id
)
638 /* simply add hooks in context. _before hooks are called by add_hooks. */
639 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
640 lttv_traceset_context_add_hooks(self
,
649 /* Note : a _middle must be preceded from a _seek or another middle */
650 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
,
653 const LttvTracesetContextPosition
*end_position
)
655 GTree
*pqueue
= self
->pqueue
;
659 LttvTracefileContext
*tfc
;
663 gboolean last_ret
= FALSE
; /* return value of the last hook list called */
665 /* Get the next event from the pqueue, call its hooks,
666 reinsert in the pqueue the following event from the same tracefile
667 unless the tracefile is finished or the event is later than the
672 g_tree_foreach(pqueue
, get_first
, &tfc
);
673 /* End of traceset : tfc is NULL */
674 if(unlikely(tfc
== NULL
))
680 * - the maximum number of events specified?
681 * - the end position ?
683 * then the read is finished. We leave the queue in the same state and
687 if(unlikely(last_ret
== TRUE
||
688 count
>= nb_events
||
689 (end_position
!=NULL
&<tv_traceset_context_ctx_pos_compare(self
,
690 end_position
) == 0)||
691 ltt_time_compare(end
, tfc
->timestamp
) <= 0))
696 /* Get the tracefile with an event for the smallest time found. If two
697 or more tracefiles have events for the same time, hope that lookup
698 and remove are consistent. */
700 g_tree_remove(pqueue
, tfc
);
703 id
= ltt_event_eventtype_id(tfc
->e
);
704 last_ret
= lttv_hooks_call_merge(tfc
->event
, tfc
,
705 lttv_hooks_by_id_get(tfc
->event_by_id
, id
), tfc
);
707 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
708 tfc
->timestamp
= ltt_event_time(tfc
->e
);
709 g_tree_insert(pqueue
, tfc
, tfc
);
715 void lttv_process_traceset_end(LttvTracesetContext
*self
,
716 LttvHooks
*after_traceset
,
717 LttvHooks
*after_trace
,
718 LttvHooks
*after_tracefile
,
720 LttvHooksById
*event_by_id
)
722 /* Remove hooks from context. _after hooks are called by remove_hooks. */
723 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
724 lttv_traceset_context_remove_hooks(self
,
732 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
734 guint i
, nb_tracefile
;
736 LttvTracefileContext
*tfc
;
738 GTree
*pqueue
= self
->ts_context
->pqueue
;
740 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
741 ltt_trace_per_cpu_tracefile_number(self
->t
);
743 for(i
= 0 ; i
< nb_tracefile
; i
++) {
744 tfc
= self
->tracefiles
[i
];
745 ltt_tracefile_seek_time(tfc
->tf
, start
);
746 g_tree_remove(pqueue
, tfc
);
747 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
748 tfc
->timestamp
= ltt_event_time(tfc
->e
);
749 g_tree_insert(pqueue
, tfc
, tfc
);
755 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
759 LttvTraceContext
*tc
;
761 nb_trace
= lttv_traceset_number(self
->ts
);
762 for(i
= 0 ; i
< nb_trace
; i
++) {
763 tc
= self
->traces
[i
];
764 lttv_process_trace_seek_time(tc
, start
);
769 gboolean
lttv_process_tracefile_seek_position(LttvTracefileContext
*self
,
770 const LttEventPosition
*pos
)
772 LttvTracefileContext
*tfc
= self
;
774 GTree
*pqueue
= self
->t_context
->ts_context
->pqueue
;
776 ltt_tracefile_seek_position(tfc
->tf
, pos
);
777 g_tree_remove(pqueue
, tfc
);
778 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
779 tfc
->timestamp
= ltt_event_time(tfc
->e
);
780 g_tree_insert(pqueue
, tfc
, tfc
);
786 gboolean
lttv_process_trace_seek_position(LttvTraceContext
*self
,
787 const LttvTraceContextPosition
*pos
)
789 guint i
, nb_tracefile
;
791 LttvTracefileContext
*tfc
;
793 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
794 ltt_trace_per_cpu_tracefile_number(self
->t
);
796 if(nb_tracefile
!= pos
->nb_tracefile
)
797 return FALSE
; /* Error */
799 for(i
= 0 ; i
< nb_tracefile
; i
++) {
800 tfc
= self
->tracefiles
[i
];
801 lttv_process_tracefile_seek_position(tfc
, pos
->tf_pos
[i
]);
809 gboolean
lttv_process_traceset_seek_position(LttvTracesetContext
*self
,
810 const LttvTracesetContextPosition
*pos
)
813 gboolean sum_ret
= TRUE
;
815 LttvTraceContext
*tc
;
817 nb_trace
= lttv_traceset_number(self
->ts
);
819 if(nb_trace
!= pos
->nb_trace
)
820 return FALSE
; /* Error */
822 for(i
= 0 ; i
< nb_trace
; i
++) {
823 tc
= self
->traces
[i
];
824 sum_ret
= sum_ret
&& lttv_process_trace_seek_position(tc
, &pos
->t_pos
[i
]);
833 find_field(LttEventType
*et
, const char *field
)
843 if(field
== NULL
) return NULL
;
845 f
= ltt_eventtype_field(et
);
846 t
= ltt_eventtype_type(et
);
847 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
848 nb
= ltt_type_member_number(t
);
849 for(i
= 0 ; i
< nb
; i
++) {
850 ltt_type_member_type(t
, i
, &name
);
851 if(strcmp(name
, field
) == 0) break;
854 return ltt_field_member(f
, i
);
859 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
860 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
868 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
869 if(unlikely(nb
< 1)) g_error("No %s facility", facility
);
870 f
= ltt_trace_facility_get(t
, pos
);
871 et
= ltt_facility_eventtype_get_by_name(f
, event_type
);
872 if(unlikely(et
== NULL
)) g_error("Event %s does not exist", event_type
);
875 th
->id
= ltt_eventtype_id(et
);
876 th
->f1
= find_field(et
, field1
);
877 th
->f2
= find_field(et
, field2
);
878 th
->f3
= find_field(et
, field3
);
882 LttvTracesetContextPosition
*lttv_traceset_context_position_new()
884 return g_new(LttvTracesetContextPosition
,1);
888 void lttv_traceset_context_position_save(const LttvTracesetContext
*self
,
889 LttvTracesetContextPosition
*pos
)
891 guint nb_trace
, nb_tracefile
;
892 guint iter_trace
, iter_tracefile
;
894 LttvTraceContext
*tc
;
896 LttvTracefileContext
*tfc
;
900 LttTime timestamp
= self
->time_span
.end_time
;
902 pos
->nb_trace
= nb_trace
= lttv_traceset_number(self
->ts
);
903 pos
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
905 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
906 tc
= self
->traces
[iter_trace
];
907 pos
->t_pos
[iter_trace
].nb_tracefile
= nb_tracefile
=
908 ltt_trace_control_tracefile_number(tc
->t
) +
909 ltt_trace_per_cpu_tracefile_number(tc
->t
);
911 pos
->t_pos
[iter_trace
].tf_pos
= g_new(LttEventPosition
*, nb_tracefile
);
912 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
913 tfc
= tc
->tracefiles
[iter_tracefile
];
916 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]
917 = ltt_event_position_new();
918 ltt_event_position(event
,
919 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
921 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
923 if(ltt_time_compare(tfc
->timestamp
, timestamp
) < 0)
924 timestamp
= tfc
->timestamp
;
927 pos
->timestamp
= timestamp
;
930 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition
*pos
)
933 guint iter_trace
, iter_tracefile
;
935 nb_trace
= pos
->nb_trace
;
937 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
938 for(iter_tracefile
= 0; iter_tracefile
<
939 pos
->t_pos
[iter_trace
].nb_tracefile
;
941 if(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
942 g_free(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
944 g_free(pos
->t_pos
[iter_trace
].tf_pos
);
950 void lttv_traceset_context_position_copy(LttvTracesetContextPosition
*dest
,
951 const LttvTracesetContextPosition
*src
)
953 guint nb_trace
, nb_tracefile
;
954 guint iter_trace
, iter_tracefile
;
956 nb_trace
= dest
->nb_trace
= src
->nb_trace
;
957 dest
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
959 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
961 nb_tracefile
= dest
->t_pos
[iter_trace
].nb_tracefile
=
962 src
->t_pos
[iter_trace
].nb_tracefile
;
964 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
965 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] =
966 ltt_event_position_new();
967 if(src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
968 ltt_event_position_copy(
969 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
970 src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
972 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
976 dest
->timestamp
= src
->timestamp
;
979 gint
lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext
*self
,
980 const LttvTracesetContextPosition
*pos
)
982 guint nb_trace
, nb_tracefile
;
983 guint iter_trace
, iter_tracefile
;
986 LttvTraceContext
*tc
;
988 LttvTracefileContext
*tfc
;
992 nb_trace
= lttv_traceset_number(self
->ts
);
994 if(unlikely(pos
->nb_trace
!= nb_trace
))
995 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
997 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
998 tc
= self
->traces
[iter_trace
];
999 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
1000 ltt_trace_per_cpu_tracefile_number(tc
->t
);
1002 if(unlikely(pos
->t_pos
[iter_trace
].nb_tracefile
!= nb_tracefile
))
1003 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1005 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1006 tfc
= tc
->tracefiles
[iter_tracefile
];
1008 ret
= ltt_event_event_position_compare(event
,
1009 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1018 gint
lttv_traceset_context_pos_pos_compare(
1019 const LttvTracesetContextPosition
*pos1
,
1020 const LttvTracesetContextPosition
*pos2
)
1022 guint nb_trace
, nb_tracefile
;
1023 guint iter_trace
, iter_tracefile
;
1027 nb_trace
= pos1
->nb_trace
;
1028 if(unlikely(nb_trace
!= pos2
->nb_trace
))
1029 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1031 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1033 nb_tracefile
= pos1
->t_pos
[iter_trace
].nb_tracefile
;
1034 if(unlikely(nb_tracefile
!= pos2
->t_pos
[iter_trace
].nb_tracefile
))
1035 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1037 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1038 ret
= ltt_event_position_compare(
1039 pos1
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
1040 pos2
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1049 LttTime
lttv_traceset_context_position_get_time(
1050 const LttvTracesetContextPosition
*pos
)
1052 return pos
->timestamp
;
1056 LttvTracefileContext
*lttv_traceset_context_get_current_tfc(LttvTracesetContext
*self
)
1058 GTree
*pqueue
= self
->pqueue
;
1059 LttvTracefileContext
*tfc
= NULL
;
1061 g_tree_foreach(pqueue
, get_first
, &tfc
);