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,
20 #include <lttv/tracecontext.h>
21 #include <ltt/event.h>
22 #include <ltt/facility.h>
23 #include <ltt/trace.h>
29 static gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
33 const LttvTracefileContext
*trace_a
= (const LttvTracefileContext
*)a
;
34 const LttvTracefileContext
*trace_b
= (const LttvTracefileContext
*)b
;
36 if(likely(trace_a
!= trace_b
)) {
37 comparison
= ltt_time_compare(trace_a
->timestamp
, trace_b
->timestamp
);
38 if(unlikely(comparison
== 0)) {
39 if(trace_a
->index
< trace_b
->index
) comparison
= -1;
40 else if(trace_a
->index
> trace_b
->index
) comparison
= 1;
41 else if(trace_a
->t_context
->index
< trace_b
->t_context
->index
)
43 else if(trace_a
->t_context
->index
> trace_b
->t_context
->index
)
50 struct _LttvTraceContextPosition
{
51 LttEventPosition
**tf_pos
; /* Position in each tracefile */
52 guint nb_tracefile
; /* Number of tracefiles (check) */
55 struct _LttvTracesetContextPosition
{
56 LttvTraceContextPosition
*t_pos
; /* Position in each trace */
57 guint nb_trace
; /* Number of traces (check) */
58 LttTime timestamp
; /* Current time at the saved position */
61 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
63 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
67 void lttv_context_fini(LttvTracesetContext
*self
)
69 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
74 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
76 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
83 lttv_context_new_trace_context(LttvTracesetContext
*self
)
85 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
89 LttvTracefileContext
*
90 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
92 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
95 /****************************************************************************
96 * lttv_traceset_context_compute_time_span
98 * Keep the time span is sync with on the fly addition and removal of traces
99 * in a trace set. It must be called each time a trace is added/removed from
100 * the traceset. It could be more efficient to call it only once a bunch
101 * of traces are loaded, but the calculation is not long, so it's not
104 * Author : Xang Xiu Yang
105 ***************************************************************************/
106 static void lttv_traceset_context_compute_time_span(
107 LttvTracesetContext
*self
,
108 TimeInterval
*time_span
)
110 LttvTraceset
* traceset
= self
->ts
;
111 int numTraces
= lttv_traceset_number(traceset
);
114 LttvTraceContext
*tc
;
117 time_span
->start_time
.tv_sec
= 0;
118 time_span
->start_time
.tv_nsec
= 0;
119 time_span
->end_time
.tv_sec
= 0;
120 time_span
->end_time
.tv_nsec
= 0;
122 for(i
=0; i
<numTraces
;i
++){
123 tc
= self
->traces
[i
];
126 ltt_trace_time_span_get(trace
, &s
, &e
);
129 time_span
->start_time
= s
;
130 time_span
->end_time
= e
;
132 if(s
.tv_sec
< time_span
->start_time
.tv_sec
133 || (s
.tv_sec
== time_span
->start_time
.tv_sec
134 && s
.tv_nsec
< time_span
->start_time
.tv_nsec
))
135 time_span
->start_time
= s
;
136 if(e
.tv_sec
> time_span
->end_time
.tv_sec
137 || (e
.tv_sec
== time_span
->end_time
.tv_sec
138 && e
.tv_nsec
> time_span
->end_time
.tv_nsec
))
139 time_span
->end_time
= e
;
146 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
148 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
150 LttvTraceContext
*tc
;
152 LttvTracefileContext
*tfc
;
154 LttTime null_time
= {0, 0};
156 nb_trace
= lttv_traceset_number(ts
);
158 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
159 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
160 self
->ts_a
= lttv_traceset_attribute(ts
);
161 for(i
= 0 ; i
< nb_trace
; i
++) {
162 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
163 self
->traces
[i
] = tc
;
165 tc
->ts_context
= self
;
167 tc
->vt
= lttv_traceset_get(ts
, i
);
168 tc
->t
= lttv_trace(tc
->vt
);
169 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
170 tc
->t_a
= lttv_trace_attribute(tc
->vt
);
171 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
172 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
173 nb_tracefile
= nb_control
+ nb_per_cpu
;
174 tc
->tracefiles
= g_new(LttvTracefileContext
*, nb_tracefile
);
176 for(j
= 0 ; j
< nb_tracefile
; j
++) {
177 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
178 tc
->tracefiles
[j
] = tfc
;
183 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
186 tfc
->control
= FALSE
;
187 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
190 tfc
->e
= ltt_event_new();
191 tfc
->event
= lttv_hooks_new();
192 tfc
->event_by_id
= lttv_hooks_by_id_new();
193 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
196 self
->pqueue
= g_tree_new(compare_tracefile
);
197 lttv_process_traceset_seek_time(self
, null_time
);
198 lttv_traceset_context_compute_time_span(self
, &self
->time_span
);
203 void fini(LttvTracesetContext
*self
)
205 guint i
, j
, nb_trace
, nb_tracefile
;
207 LttvTraceContext
*tc
;
209 LttvTracefileContext
*tfc
;
211 LttvTraceset
*ts
= self
->ts
;
215 g_tree_destroy(self
->pqueue
);
216 g_object_unref(self
->a
);
218 nb_trace
= lttv_traceset_number(ts
);
220 for(i
= 0 ; i
< nb_trace
; i
++) {
221 tc
= self
->traces
[i
];
223 g_object_unref(tc
->a
);
225 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
226 ltt_trace_per_cpu_tracefile_number(tc
->t
);
228 for(j
= 0 ; j
< nb_tracefile
; j
++) {
229 tfc
= tc
->tracefiles
[j
];
230 ltt_event_destroy(tfc
->e
);
231 lttv_hooks_destroy(tfc
->event
);
232 lttv_hooks_by_id_destroy(tfc
->event_by_id
);
233 g_object_unref(tfc
->a
);
236 g_free(tc
->tracefiles
);
239 g_free(self
->traces
);
243 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
244 LttvHooks
*before_traceset
,
245 LttvHooks
*before_trace
,
246 LttvHooks
*before_tracefile
,
248 LttvHooksById
*event_by_id
)
250 LttvTraceset
*ts
= self
->ts
;
254 LttvTraceContext
*tc
;
256 lttv_hooks_call(before_traceset
, self
);
258 nb_trace
= lttv_traceset_number(ts
);
260 for(i
= 0 ; i
< nb_trace
; i
++) {
261 tc
= self
->traces
[i
];
262 lttv_trace_context_add_hooks(tc
,
271 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
272 LttvHooks
*after_traceset
,
273 LttvHooks
*after_trace
,
274 LttvHooks
*after_tracefile
,
276 LttvHooksById
*event_by_id
)
279 LttvTraceset
*ts
= self
->ts
;
283 LttvTraceContext
*tc
;
285 nb_trace
= lttv_traceset_number(ts
);
287 for(i
= 0 ; i
< nb_trace
; i
++) {
288 tc
= self
->traces
[i
];
289 lttv_trace_context_remove_hooks(tc
,
296 lttv_hooks_call(after_traceset
, self
);
301 void lttv_trace_context_add_hooks(LttvTraceContext
*self
,
302 LttvHooks
*before_trace
,
303 LttvHooks
*before_tracefile
,
305 LttvHooksById
*event_by_id
)
307 guint i
, nb_tracefile
;
309 LttvTracefileContext
*tfc
;
311 lttv_hooks_call(before_trace
, self
);
312 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
313 ltt_trace_per_cpu_tracefile_number(self
->t
);
315 for(i
= 0 ; i
< nb_tracefile
; i
++) {
316 tfc
= self
->tracefiles
[i
];
317 lttv_tracefile_context_add_hooks(tfc
,
326 void lttv_trace_context_remove_hooks(LttvTraceContext
*self
,
327 LttvHooks
*after_trace
,
328 LttvHooks
*after_tracefile
,
330 LttvHooksById
*event_by_id
)
332 guint i
, nb_tracefile
;
334 LttvTracefileContext
*tfc
;
336 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
337 ltt_trace_per_cpu_tracefile_number(self
->t
);
339 for(i
= 0 ; i
< nb_tracefile
; i
++) {
340 tfc
= self
->tracefiles
[i
];
341 lttv_tracefile_context_remove_hooks(tfc
,
347 lttv_hooks_call(after_trace
, self
);
350 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*self
,
351 LttvHooks
*before_tracefile
,
353 LttvHooksById
*event_by_id
)
359 lttv_hooks_call(before_tracefile
, self
);
360 lttv_hooks_add_list(self
->event
, event
);
361 if(event_by_id
!= NULL
)
362 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
363 hook
= lttv_hooks_by_id_find(self
->event_by_id
, i
);
364 lttv_hooks_add_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
369 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*self
,
370 LttvHooks
*after_tracefile
,
372 LttvHooksById
*event_by_id
)
379 lttv_hooks_remove_list(self
->event
, event
);
380 if(event_by_id
!= NULL
)
381 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
382 hook
= lttv_hooks_by_id_get(self
->event_by_id
, i
);
384 lttv_hooks_remove_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
387 lttv_hooks_call(after_tracefile
, self
);
392 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
394 LttvHooks
*event_by_id
)
397 h
= lttv_hooks_by_id_find(tfc
->event_by_id
, i
);
398 lttv_hooks_add_list(h
, event_by_id
);
401 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
404 lttv_hooks_by_id_remove(tfc
->event_by_id
, i
);
407 static LttvTracesetContext
*
408 new_traceset_context(LttvTracesetContext
*self
)
410 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
414 static LttvTraceContext
*
415 new_trace_context(LttvTracesetContext
*self
)
417 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
421 static LttvTracefileContext
*
422 new_tracefile_context(LttvTracesetContext
*self
)
424 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
429 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
431 /* Be careful of anything which would not work well with shallow copies */
436 traceset_context_finalize (LttvTracesetContext
*self
)
438 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
439 ->finalize(G_OBJECT(self
));
444 traceset_context_class_init (LttvTracesetContextClass
*klass
)
446 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
448 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
451 klass
->new_traceset_context
= new_traceset_context
;
452 klass
->new_trace_context
= new_trace_context
;
453 klass
->new_tracefile_context
= new_tracefile_context
;
458 lttv_traceset_context_get_type(void)
460 static GType type
= 0;
462 static const GTypeInfo info
= {
463 sizeof (LttvTracesetContextClass
),
464 NULL
, /* base_init */
465 NULL
, /* base_finalize */
466 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
467 NULL
, /* class_finalize */
468 NULL
, /* class_data */
469 sizeof (LttvTracesetContext
),
471 (GInstanceInitFunc
) traceset_context_instance_init
, /* instance_init */
472 NULL
/* Value handling */
475 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
483 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
485 /* Be careful of anything which would not work well with shallow copies */
490 trace_context_finalize (LttvTraceContext
*self
)
492 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
493 finalize(G_OBJECT(self
));
498 trace_context_class_init (LttvTraceContextClass
*klass
)
500 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
502 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
507 lttv_trace_context_get_type(void)
509 static GType type
= 0;
511 static const GTypeInfo info
= {
512 sizeof (LttvTraceContextClass
),
513 NULL
, /* base_init */
514 NULL
, /* base_finalize */
515 (GClassInitFunc
) trace_context_class_init
, /* class_init */
516 NULL
, /* class_finalize */
517 NULL
, /* class_data */
518 sizeof (LttvTraceContext
),
520 (GInstanceInitFunc
) trace_context_instance_init
, /* instance_init */
521 NULL
/* Value handling */
524 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
532 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
534 /* Be careful of anything which would not work well with shallow copies */
539 tracefile_context_finalize (LttvTracefileContext
*self
)
541 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
542 ->finalize(G_OBJECT(self
));
547 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
549 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
551 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
556 lttv_tracefile_context_get_type(void)
558 static GType type
= 0;
560 static const GTypeInfo info
= {
561 sizeof (LttvTracefileContextClass
),
562 NULL
, /* base_init */
563 NULL
, /* base_finalize */
564 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
565 NULL
, /* class_finalize */
566 NULL
, /* class_data */
567 sizeof (LttvTracefileContext
),
569 (GInstanceInitFunc
) tracefile_context_instance_init
, /* instance_init */
570 NULL
/* Value handling */
573 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
581 static gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
582 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
587 /* Put all the tracefiles at the tracefile context position */
588 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext
*self
)
590 guint iter_trace
, nb_trace
;
592 LttvTraceContext
*tc
;
594 nb_trace
= lttv_traceset_number(self
->ts
);
596 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
597 tc
= self
->traces
[iter_trace
];
600 guint iter_tf
, nb_tracefile
;
602 LttvTracefileContext
*tfc
;
604 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
605 ltt_trace_per_cpu_tracefile_number(tc
->t
);
607 for(iter_tf
= 0 ; iter_tf
< nb_tracefile
; iter_tf
++) {
608 tfc
= tc
->tracefiles
[iter_tf
];
611 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
612 LttEventPosition
*ep
= ltt_event_position_new();
614 ltt_event_position(tfc
->e
, ep
);
616 ltt_tracefile_seek_position(tfc
->tf
, ep
);
626 void lttv_process_traceset_begin(LttvTracesetContext
*self
,
627 LttvHooks
*before_traceset
,
628 LttvHooks
*before_trace
,
629 LttvHooks
*before_tracefile
,
631 LttvHooksById
*event_by_id
)
634 /* simply add hooks in context. _before hooks are called by add_hooks. */
635 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
636 lttv_traceset_context_add_hooks(self
,
645 /* Note : a _middle must be preceded from a _seek or another middle */
646 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
,
649 const LttvTracesetContextPosition
*end_position
)
651 GTree
*pqueue
= self
->pqueue
;
655 LttvTracefileContext
*tfc
;
659 gboolean last_ret
= FALSE
; /* return value of the last hook list called */
661 /* Get the next event from the pqueue, call its hooks,
662 reinsert in the pqueue the following event from the same tracefile
663 unless the tracefile is finished or the event is later than the
668 g_tree_foreach(pqueue
, get_first
, &tfc
);
669 /* End of traceset : tfc is NULL */
670 if(unlikely(tfc
== NULL
))
676 * - the maximum number of events specified?
677 * - the end position ?
679 * then the read is finished. We leave the queue in the same state and
683 if(unlikely(last_ret
== TRUE
||
684 count
>= nb_events
||
685 (end_position
!=NULL
&<tv_traceset_context_ctx_pos_compare(self
,
686 end_position
) == 0)||
687 ltt_time_compare(end
, tfc
->timestamp
) <= 0))
692 /* Get the tracefile with an event for the smallest time found. If two
693 or more tracefiles have events for the same time, hope that lookup
694 and remove are consistent. */
696 g_tree_remove(pqueue
, tfc
);
699 id
= ltt_event_eventtype_id(tfc
->e
);
700 last_ret
= lttv_hooks_call_merge(tfc
->event
, tfc
,
701 lttv_hooks_by_id_get(tfc
->event_by_id
, id
), tfc
);
703 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
704 tfc
->timestamp
= ltt_event_time(tfc
->e
);
705 g_tree_insert(pqueue
, tfc
, tfc
);
711 void lttv_process_traceset_end(LttvTracesetContext
*self
,
712 LttvHooks
*after_traceset
,
713 LttvHooks
*after_trace
,
714 LttvHooks
*after_tracefile
,
716 LttvHooksById
*event_by_id
)
718 /* Remove hooks from context. _after hooks are called by remove_hooks. */
719 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
720 lttv_traceset_context_remove_hooks(self
,
728 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
730 guint i
, nb_tracefile
;
732 LttvTracefileContext
*tfc
;
734 GTree
*pqueue
= self
->ts_context
->pqueue
;
736 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
737 ltt_trace_per_cpu_tracefile_number(self
->t
);
739 for(i
= 0 ; i
< nb_tracefile
; i
++) {
740 tfc
= self
->tracefiles
[i
];
741 ltt_tracefile_seek_time(tfc
->tf
, start
);
742 g_tree_remove(pqueue
, tfc
);
743 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
744 tfc
->timestamp
= ltt_event_time(tfc
->e
);
745 g_tree_insert(pqueue
, tfc
, tfc
);
751 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
755 LttvTraceContext
*tc
;
757 nb_trace
= lttv_traceset_number(self
->ts
);
758 for(i
= 0 ; i
< nb_trace
; i
++) {
759 tc
= self
->traces
[i
];
760 lttv_process_trace_seek_time(tc
, start
);
765 gboolean
lttv_process_tracefile_seek_position(LttvTracefileContext
*self
,
766 const LttEventPosition
*pos
)
768 LttvTracefileContext
*tfc
= self
;
770 GTree
*pqueue
= self
->t_context
->ts_context
->pqueue
;
772 ltt_tracefile_seek_position(tfc
->tf
, pos
);
773 g_tree_remove(pqueue
, tfc
);
774 if(likely(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
)) {
775 tfc
->timestamp
= ltt_event_time(tfc
->e
);
776 g_tree_insert(pqueue
, tfc
, tfc
);
782 gboolean
lttv_process_trace_seek_position(LttvTraceContext
*self
,
783 const LttvTraceContextPosition
*pos
)
785 guint i
, nb_tracefile
;
787 LttvTracefileContext
*tfc
;
789 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
790 ltt_trace_per_cpu_tracefile_number(self
->t
);
792 if(nb_tracefile
!= pos
->nb_tracefile
)
793 return FALSE
; /* Error */
795 for(i
= 0 ; i
< nb_tracefile
; i
++) {
796 tfc
= self
->tracefiles
[i
];
797 lttv_process_tracefile_seek_position(tfc
, pos
->tf_pos
[i
]);
805 gboolean
lttv_process_traceset_seek_position(LttvTracesetContext
*self
,
806 const LttvTracesetContextPosition
*pos
)
809 gboolean sum_ret
= TRUE
;
811 LttvTraceContext
*tc
;
813 nb_trace
= lttv_traceset_number(self
->ts
);
815 if(nb_trace
!= pos
->nb_trace
)
816 return FALSE
; /* Error */
818 for(i
= 0 ; i
< nb_trace
; i
++) {
819 tc
= self
->traces
[i
];
820 sum_ret
= sum_ret
&& lttv_process_trace_seek_position(tc
, &pos
->t_pos
[i
]);
829 find_field(LttEventType
*et
, const char *field
)
839 if(field
== NULL
) return NULL
;
841 f
= ltt_eventtype_field(et
);
842 t
= ltt_eventtype_type(et
);
843 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
844 nb
= ltt_type_member_number(t
);
845 for(i
= 0 ; i
< nb
; i
++) {
846 ltt_type_member_type(t
, i
, &name
);
847 if(strcmp(name
, field
) == 0) break;
850 return ltt_field_member(f
, i
);
855 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
856 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
864 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
865 if(unlikely(nb
< 1)) g_error("No %s facility", facility
);
866 f
= ltt_trace_facility_get(t
, pos
);
867 et
= ltt_facility_eventtype_get_by_name(f
, event_type
);
868 if(unlikely(et
== NULL
)) g_error("Event %s does not exist", event_type
);
871 th
->id
= ltt_eventtype_id(et
);
872 th
->f1
= find_field(et
, field1
);
873 th
->f2
= find_field(et
, field2
);
874 th
->f3
= find_field(et
, field3
);
878 LttvTracesetContextPosition
*lttv_traceset_context_position_new()
880 return g_new(LttvTracesetContextPosition
,1);
884 void lttv_traceset_context_position_save(const LttvTracesetContext
*self
,
885 LttvTracesetContextPosition
*pos
)
887 guint nb_trace
, nb_tracefile
;
888 guint iter_trace
, iter_tracefile
;
890 LttvTraceContext
*tc
;
892 LttvTracefileContext
*tfc
;
896 LttTime timestamp
= self
->time_span
.end_time
;
898 pos
->nb_trace
= nb_trace
= lttv_traceset_number(self
->ts
);
899 pos
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
901 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
902 tc
= self
->traces
[iter_trace
];
903 pos
->t_pos
[iter_trace
].nb_tracefile
= nb_tracefile
=
904 ltt_trace_control_tracefile_number(tc
->t
) +
905 ltt_trace_per_cpu_tracefile_number(tc
->t
);
907 pos
->t_pos
[iter_trace
].tf_pos
= g_new(LttEventPosition
*, nb_tracefile
);
908 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
909 tfc
= tc
->tracefiles
[iter_tracefile
];
912 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]
913 = ltt_event_position_new();
914 ltt_event_position(event
,
915 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
917 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
919 if(ltt_time_compare(tfc
->timestamp
, timestamp
) < 0)
920 timestamp
= tfc
->timestamp
;
923 pos
->timestamp
= timestamp
;
926 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition
*pos
)
929 guint iter_trace
, iter_tracefile
;
931 nb_trace
= pos
->nb_trace
;
933 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
934 for(iter_tracefile
= 0; iter_tracefile
<
935 pos
->t_pos
[iter_trace
].nb_tracefile
;
937 if(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
938 g_free(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
940 g_free(pos
->t_pos
[iter_trace
].tf_pos
);
946 void lttv_traceset_context_position_copy(LttvTracesetContextPosition
*dest
,
947 const LttvTracesetContextPosition
*src
)
949 guint nb_trace
, nb_tracefile
;
950 guint iter_trace
, iter_tracefile
;
952 nb_trace
= dest
->nb_trace
= src
->nb_trace
;
953 dest
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
955 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
957 nb_tracefile
= dest
->t_pos
[iter_trace
].nb_tracefile
=
958 src
->t_pos
[iter_trace
].nb_tracefile
;
960 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
961 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] =
962 ltt_event_position_new();
963 if(src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
964 ltt_event_position_copy(
965 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
966 src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
968 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
972 dest
->timestamp
= src
->timestamp
;
975 gint
lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext
*self
,
976 const LttvTracesetContextPosition
*pos
)
978 guint nb_trace
, nb_tracefile
;
979 guint iter_trace
, iter_tracefile
;
982 LttvTraceContext
*tc
;
984 LttvTracefileContext
*tfc
;
988 nb_trace
= lttv_traceset_number(self
->ts
);
990 if(unlikely(pos
->nb_trace
!= nb_trace
))
991 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
993 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
994 tc
= self
->traces
[iter_trace
];
995 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
996 ltt_trace_per_cpu_tracefile_number(tc
->t
);
998 if(unlikely(pos
->t_pos
[iter_trace
].nb_tracefile
!= nb_tracefile
))
999 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1001 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1002 tfc
= tc
->tracefiles
[iter_tracefile
];
1004 ret
= ltt_event_event_position_compare(event
,
1005 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1014 gint
lttv_traceset_context_pos_pos_compare(
1015 const LttvTracesetContextPosition
*pos1
,
1016 const LttvTracesetContextPosition
*pos2
)
1018 guint nb_trace
, nb_tracefile
;
1019 guint iter_trace
, iter_tracefile
;
1023 nb_trace
= pos1
->nb_trace
;
1024 if(unlikely(nb_trace
!= pos2
->nb_trace
))
1025 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1027 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1029 nb_tracefile
= pos1
->t_pos
[iter_trace
].nb_tracefile
;
1030 if(unlikely(nb_tracefile
!= pos2
->t_pos
[iter_trace
].nb_tracefile
))
1031 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1033 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1034 ret
= ltt_event_position_compare(
1035 pos1
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
1036 pos2
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1045 LttTime
lttv_traceset_context_position_get_time(
1046 const LttvTracesetContextPosition
*pos
)
1048 return pos
->timestamp
;
1052 LttvTracefileContext
*lttv_traceset_context_get_current_tfc(LttvTracesetContext
*self
)
1054 GTree
*pqueue
= self
->pqueue
;
1055 LttvTracefileContext
*tfc
= NULL
;
1057 g_tree_foreach(pqueue
, get_first
, &tfc
);