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 gint
compare_tracefile(gconstpointer a
, gconstpointer b
)
33 const LttvTracefileContext
*trace_a
= (const LttvTracefileContext
*)a
;
35 const LttvTracefileContext
*trace_b
= (const LttvTracefileContext
*)b
;
37 if(trace_a
== trace_b
) return 0;
38 comparison
= ltt_time_compare(trace_a
->timestamp
, trace_b
->timestamp
);
39 if(comparison
!= 0) return comparison
;
40 if(trace_a
->index
< trace_b
->index
) return -1;
41 else if(trace_a
->index
> trace_b
->index
) return 1;
42 if(trace_a
->t_context
->index
< trace_b
->t_context
->index
) return -1;
43 else if(trace_a
->t_context
->index
> trace_b
->t_context
->index
) return 1;
46 return 0; /* This should never happen */
49 struct _LttvTraceContextPosition
{
50 LttEventPosition
**tf_pos
; /* Position in each tracefile */
51 guint nb_tracefile
; /* Number of tracefiles (check) */
54 struct _LttvTracesetContextPosition
{
55 LttvTraceContextPosition
*t_pos
; /* Position in each trace */
56 guint nb_trace
; /* Number of traces (check) */
57 LttTime timestamp
; /* Current time at the saved position */
60 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
62 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
66 void lttv_context_fini(LttvTracesetContext
*self
)
68 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
73 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
75 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
82 lttv_context_new_trace_context(LttvTracesetContext
*self
)
84 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
88 LttvTracefileContext
*
89 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
91 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
94 /****************************************************************************
95 * lttv_traceset_context_compute_time_span
97 * Keep the time span is sync with on the fly addition and removal of traces
98 * in a trace set. It must be called each time a trace is added/removed from
99 * the traceset. It could be more efficient to call it only once a bunch
100 * of traces are loaded, but the calculation is not long, so it's not
103 * Author : Xang Xiu Yang
104 ***************************************************************************/
105 static void lttv_traceset_context_compute_time_span(
106 LttvTracesetContext
*self
,
107 TimeInterval
*time_span
)
109 LttvTraceset
* traceset
= self
->ts
;
110 int numTraces
= lttv_traceset_number(traceset
);
113 LttvTraceContext
*tc
;
116 time_span
->start_time
.tv_sec
= 0;
117 time_span
->start_time
.tv_nsec
= 0;
118 time_span
->end_time
.tv_sec
= 0;
119 time_span
->end_time
.tv_nsec
= 0;
121 for(i
=0; i
<numTraces
;i
++){
122 tc
= self
->traces
[i
];
125 ltt_trace_time_span_get(trace
, &s
, &e
);
128 time_span
->start_time
= s
;
129 time_span
->end_time
= e
;
131 if(s
.tv_sec
< time_span
->start_time
.tv_sec
132 || (s
.tv_sec
== time_span
->start_time
.tv_sec
133 && s
.tv_nsec
< time_span
->start_time
.tv_nsec
))
134 time_span
->start_time
= s
;
135 if(e
.tv_sec
> time_span
->end_time
.tv_sec
136 || (e
.tv_sec
== time_span
->end_time
.tv_sec
137 && e
.tv_nsec
> time_span
->end_time
.tv_nsec
))
138 time_span
->end_time
= e
;
145 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
147 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
149 LttvTraceContext
*tc
;
151 LttvTracefileContext
*tfc
;
153 LttTime null_time
= {0, 0};
155 nb_trace
= lttv_traceset_number(ts
);
157 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
158 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
159 self
->ts_a
= lttv_traceset_attribute(ts
);
160 for(i
= 0 ; i
< nb_trace
; i
++) {
161 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
162 self
->traces
[i
] = tc
;
164 tc
->ts_context
= self
;
166 tc
->vt
= lttv_traceset_get(ts
, i
);
167 tc
->t
= lttv_trace(tc
->vt
);
168 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
169 tc
->t_a
= lttv_trace_attribute(tc
->vt
);
170 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
171 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
172 nb_tracefile
= nb_control
+ nb_per_cpu
;
173 tc
->tracefiles
= g_new(LttvTracefileContext
*, nb_tracefile
);
175 for(j
= 0 ; j
< nb_tracefile
; j
++) {
176 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
177 tc
->tracefiles
[j
] = tfc
;
182 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
185 tfc
->control
= FALSE
;
186 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
189 tfc
->e
= ltt_event_new();
190 tfc
->event
= lttv_hooks_new();
191 tfc
->event_by_id
= lttv_hooks_by_id_new();
192 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
195 self
->pqueue
= g_tree_new(compare_tracefile
);
196 lttv_process_traceset_seek_time(self
, null_time
);
197 lttv_traceset_context_compute_time_span(self
, &self
->time_span
);
202 void fini(LttvTracesetContext
*self
)
204 guint i
, j
, nb_trace
, nb_tracefile
;
206 LttvTraceContext
*tc
;
208 LttvTracefileContext
*tfc
;
210 LttvTraceset
*ts
= self
->ts
;
214 g_tree_destroy(self
->pqueue
);
215 g_object_unref(self
->a
);
217 nb_trace
= lttv_traceset_number(ts
);
219 for(i
= 0 ; i
< nb_trace
; i
++) {
220 tc
= self
->traces
[i
];
222 g_object_unref(tc
->a
);
224 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
225 ltt_trace_per_cpu_tracefile_number(tc
->t
);
227 for(j
= 0 ; j
< nb_tracefile
; j
++) {
228 tfc
= tc
->tracefiles
[j
];
229 ltt_event_destroy(tfc
->e
);
230 lttv_hooks_destroy(tfc
->event
);
231 lttv_hooks_by_id_destroy(tfc
->event_by_id
);
232 g_object_unref(tfc
->a
);
235 g_free(tc
->tracefiles
);
238 g_free(self
->traces
);
242 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
243 LttvHooks
*before_traceset
,
244 LttvHooks
*before_trace
,
245 LttvHooks
*before_tracefile
,
247 LttvHooksById
*event_by_id
)
249 LttvTraceset
*ts
= self
->ts
;
253 LttvTraceContext
*tc
;
255 lttv_hooks_call(before_traceset
, self
);
257 nb_trace
= lttv_traceset_number(ts
);
259 for(i
= 0 ; i
< nb_trace
; i
++) {
260 tc
= self
->traces
[i
];
261 lttv_trace_context_add_hooks(tc
,
270 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
271 LttvHooks
*after_traceset
,
272 LttvHooks
*after_trace
,
273 LttvHooks
*after_tracefile
,
275 LttvHooksById
*event_by_id
)
278 LttvTraceset
*ts
= self
->ts
;
282 LttvTraceContext
*tc
;
284 nb_trace
= lttv_traceset_number(ts
);
286 for(i
= 0 ; i
< nb_trace
; i
++) {
287 tc
= self
->traces
[i
];
288 lttv_trace_context_remove_hooks(tc
,
295 lttv_hooks_call(after_traceset
, self
);
300 void lttv_trace_context_add_hooks(LttvTraceContext
*self
,
301 LttvHooks
*before_trace
,
302 LttvHooks
*before_tracefile
,
304 LttvHooksById
*event_by_id
)
306 guint i
, nb_tracefile
;
308 LttvTracefileContext
*tfc
;
310 lttv_hooks_call(before_trace
, self
);
311 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
312 ltt_trace_per_cpu_tracefile_number(self
->t
);
314 for(i
= 0 ; i
< nb_tracefile
; i
++) {
315 tfc
= self
->tracefiles
[i
];
316 lttv_tracefile_context_add_hooks(tfc
,
325 void lttv_trace_context_remove_hooks(LttvTraceContext
*self
,
326 LttvHooks
*after_trace
,
327 LttvHooks
*after_tracefile
,
329 LttvHooksById
*event_by_id
)
331 guint i
, nb_tracefile
;
333 LttvTracefileContext
*tfc
;
335 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
336 ltt_trace_per_cpu_tracefile_number(self
->t
);
338 for(i
= 0 ; i
< nb_tracefile
; i
++) {
339 tfc
= self
->tracefiles
[i
];
340 lttv_tracefile_context_remove_hooks(tfc
,
346 lttv_hooks_call(after_trace
, self
);
349 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*self
,
350 LttvHooks
*before_tracefile
,
352 LttvHooksById
*event_by_id
)
358 lttv_hooks_call(before_tracefile
, self
);
359 lttv_hooks_add_list(self
->event
, event
);
360 if(event_by_id
!= NULL
)
361 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
362 hook
= lttv_hooks_by_id_find(self
->event_by_id
, i
);
363 lttv_hooks_add_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
368 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*self
,
369 LttvHooks
*after_tracefile
,
371 LttvHooksById
*event_by_id
)
378 lttv_hooks_remove_list(self
->event
, event
);
379 if(event_by_id
!= NULL
)
380 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
381 hook
= lttv_hooks_by_id_get(self
->event_by_id
, i
);
383 lttv_hooks_remove_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
386 lttv_hooks_call(after_tracefile
, self
);
391 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
393 LttvHooks
*event_by_id
)
396 h
= lttv_hooks_by_id_find(tfc
->event_by_id
, i
);
397 lttv_hooks_add_list(h
, event_by_id
);
400 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
403 lttv_hooks_by_id_remove(tfc
->event_by_id
, i
);
406 static LttvTracesetContext
*
407 new_traceset_context(LttvTracesetContext
*self
)
409 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
413 static LttvTraceContext
*
414 new_trace_context(LttvTracesetContext
*self
)
416 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
420 static LttvTracefileContext
*
421 new_tracefile_context(LttvTracesetContext
*self
)
423 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
428 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
430 /* Be careful of anything which would not work well with shallow copies */
435 traceset_context_finalize (LttvTracesetContext
*self
)
437 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
438 ->finalize(G_OBJECT(self
));
443 traceset_context_class_init (LttvTracesetContextClass
*klass
)
445 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
447 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
450 klass
->new_traceset_context
= new_traceset_context
;
451 klass
->new_trace_context
= new_trace_context
;
452 klass
->new_tracefile_context
= new_tracefile_context
;
457 lttv_traceset_context_get_type(void)
459 static GType type
= 0;
461 static const GTypeInfo info
= {
462 sizeof (LttvTracesetContextClass
),
463 NULL
, /* base_init */
464 NULL
, /* base_finalize */
465 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
466 NULL
, /* class_finalize */
467 NULL
, /* class_data */
468 sizeof (LttvTracesetContext
),
470 (GInstanceInitFunc
) traceset_context_instance_init
, /* instance_init */
471 NULL
/* Value handling */
474 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
482 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
484 /* Be careful of anything which would not work well with shallow copies */
489 trace_context_finalize (LttvTraceContext
*self
)
491 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
492 finalize(G_OBJECT(self
));
497 trace_context_class_init (LttvTraceContextClass
*klass
)
499 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
501 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
506 lttv_trace_context_get_type(void)
508 static GType type
= 0;
510 static const GTypeInfo info
= {
511 sizeof (LttvTraceContextClass
),
512 NULL
, /* base_init */
513 NULL
, /* base_finalize */
514 (GClassInitFunc
) trace_context_class_init
, /* class_init */
515 NULL
, /* class_finalize */
516 NULL
, /* class_data */
517 sizeof (LttvTraceContext
),
519 (GInstanceInitFunc
) trace_context_instance_init
, /* instance_init */
520 NULL
/* Value handling */
523 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
531 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
533 /* Be careful of anything which would not work well with shallow copies */
538 tracefile_context_finalize (LttvTracefileContext
*self
)
540 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
541 ->finalize(G_OBJECT(self
));
546 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
548 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
550 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
555 lttv_tracefile_context_get_type(void)
557 static GType type
= 0;
559 static const GTypeInfo info
= {
560 sizeof (LttvTracefileContextClass
),
561 NULL
, /* base_init */
562 NULL
, /* base_finalize */
563 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
564 NULL
, /* class_finalize */
565 NULL
, /* class_data */
566 sizeof (LttvTracefileContext
),
568 (GInstanceInitFunc
) tracefile_context_instance_init
, /* instance_init */
569 NULL
/* Value handling */
572 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
580 static gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
581 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
586 /* Put all the tracefiles at the tracefile context position */
587 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext
*self
)
589 guint iter_trace
, nb_trace
;
591 LttvTraceContext
*tc
;
593 nb_trace
= lttv_traceset_number(self
->ts
);
595 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
596 tc
= self
->traces
[iter_trace
];
599 guint iter_tf
, nb_tracefile
;
601 LttvTracefileContext
*tfc
;
603 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
604 ltt_trace_per_cpu_tracefile_number(tc
->t
);
606 for(iter_tf
= 0 ; iter_tf
< nb_tracefile
; iter_tf
++) {
607 tfc
= tc
->tracefiles
[iter_tf
];
610 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
611 LttEventPosition
*ep
= ltt_event_position_new();
613 ltt_event_position(tfc
->e
, ep
);
615 ltt_tracefile_seek_position(tfc
->tf
, ep
);
625 void lttv_process_traceset_begin(LttvTracesetContext
*self
,
626 LttvHooks
*before_traceset
,
627 LttvHooks
*before_trace
,
628 LttvHooks
*before_tracefile
,
630 LttvHooksById
*event_by_id
)
633 /* simply add hooks in context. _before hooks are called by add_hooks. */
634 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
635 lttv_traceset_context_add_hooks(self
,
644 /* Note : a _middle must be preceded from a _seek or another middle */
645 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
,
648 const LttvTracesetContextPosition
*end_position
)
650 GTree
*pqueue
= self
->pqueue
;
654 LttvTracefileContext
*tfc
;
658 gboolean last_ret
= FALSE
; /* return value of the last hook list called */
660 /* Get the next event from the pqueue, call its hooks,
661 reinsert in the pqueue the following event from the same tracefile
662 unless the tracefile is finished or the event is later than the
667 g_tree_foreach(pqueue
, get_first
, &tfc
);
668 /* End of traceset : tfc is NULL */
675 * - the maximum number of events specified?
676 * - the end position ?
678 * then the read is finished. We leave the queue in the same state and
682 if(last_ret
== TRUE
||
683 count
>= nb_events
||
684 (end_position
!=NULL
&<tv_traceset_context_ctx_pos_compare(self
,
685 end_position
) == 0)||
686 ltt_time_compare(tfc
->timestamp
, end
) >= 0)
691 /* Get the tracefile with an event for the smallest time found. If two
692 or more tracefiles have events for the same time, hope that lookup
693 and remove are consistent. */
695 g_tree_remove(pqueue
, tfc
);
698 id
= ltt_event_eventtype_id(tfc
->e
);
699 last_ret
= lttv_hooks_call_merge(tfc
->event
, tfc
,
700 lttv_hooks_by_id_get(tfc
->event_by_id
, id
), tfc
);
702 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
703 tfc
->timestamp
= ltt_event_time(tfc
->e
);
704 g_tree_insert(pqueue
, tfc
, tfc
);
710 void lttv_process_traceset_end(LttvTracesetContext
*self
,
711 LttvHooks
*after_traceset
,
712 LttvHooks
*after_trace
,
713 LttvHooks
*after_tracefile
,
715 LttvHooksById
*event_by_id
)
717 /* Remove hooks from context. _after hooks are called by remove_hooks. */
718 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
719 lttv_traceset_context_remove_hooks(self
,
727 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
729 guint i
, nb_tracefile
;
731 LttvTracefileContext
*tfc
;
733 GTree
*pqueue
= self
->ts_context
->pqueue
;
735 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
736 ltt_trace_per_cpu_tracefile_number(self
->t
);
738 for(i
= 0 ; i
< nb_tracefile
; i
++) {
739 tfc
= self
->tracefiles
[i
];
740 ltt_tracefile_seek_time(tfc
->tf
, start
);
741 g_tree_remove(pqueue
, tfc
);
742 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
743 tfc
->timestamp
= ltt_event_time(tfc
->e
);
744 g_tree_insert(pqueue
, tfc
, tfc
);
750 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
754 LttvTraceContext
*tc
;
756 nb_trace
= lttv_traceset_number(self
->ts
);
757 for(i
= 0 ; i
< nb_trace
; i
++) {
758 tc
= self
->traces
[i
];
759 lttv_process_trace_seek_time(tc
, start
);
764 gboolean
lttv_process_tracefile_seek_position(LttvTracefileContext
*self
,
765 const LttEventPosition
*pos
)
767 LttvTracefileContext
*tfc
= self
;
769 GTree
*pqueue
= self
->t_context
->ts_context
->pqueue
;
771 ltt_tracefile_seek_position(tfc
->tf
, pos
);
772 g_tree_remove(pqueue
, tfc
);
773 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
774 tfc
->timestamp
= ltt_event_time(tfc
->e
);
775 g_tree_insert(pqueue
, tfc
, tfc
);
781 gboolean
lttv_process_trace_seek_position(LttvTraceContext
*self
,
782 const LttvTraceContextPosition
*pos
)
784 guint i
, nb_tracefile
;
786 LttvTracefileContext
*tfc
;
788 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
789 ltt_trace_per_cpu_tracefile_number(self
->t
);
791 if(nb_tracefile
!= pos
->nb_tracefile
)
792 return FALSE
; /* Error */
794 for(i
= 0 ; i
< nb_tracefile
; i
++) {
795 tfc
= self
->tracefiles
[i
];
796 lttv_process_tracefile_seek_position(tfc
, pos
->tf_pos
[i
]);
804 gboolean
lttv_process_traceset_seek_position(LttvTracesetContext
*self
,
805 const LttvTracesetContextPosition
*pos
)
808 gboolean sum_ret
= TRUE
;
810 LttvTraceContext
*tc
;
812 nb_trace
= lttv_traceset_number(self
->ts
);
814 if(nb_trace
!= pos
->nb_trace
)
815 return FALSE
; /* Error */
817 for(i
= 0 ; i
< nb_trace
; i
++) {
818 tc
= self
->traces
[i
];
819 sum_ret
= sum_ret
&& lttv_process_trace_seek_position(tc
, &pos
->t_pos
[i
]);
828 find_field(LttEventType
*et
, const char *field
)
838 if(field
== NULL
) return NULL
;
840 f
= ltt_eventtype_field(et
);
841 t
= ltt_eventtype_type(et
);
842 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
843 nb
= ltt_type_member_number(t
);
844 for(i
= 0 ; i
< nb
; i
++) {
845 ltt_type_member_type(t
, i
, &name
);
846 if(strcmp(name
, field
) == 0) break;
849 return ltt_field_member(f
, i
);
854 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
855 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
863 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
864 if(nb
< 1) g_error("No %s facility", facility
);
865 f
= ltt_trace_facility_get(t
, pos
);
866 et
= ltt_facility_eventtype_get_by_name(f
, event_type
);
867 if(et
== NULL
) g_error("Event %s does not exist", event_type
);
870 th
->id
= ltt_eventtype_id(et
);
871 th
->f1
= find_field(et
, field1
);
872 th
->f2
= find_field(et
, field2
);
873 th
->f3
= find_field(et
, field3
);
877 LttvTracesetContextPosition
*lttv_traceset_context_position_new()
879 return g_new(LttvTracesetContextPosition
,1);
883 void lttv_traceset_context_position_save(const LttvTracesetContext
*self
,
884 LttvTracesetContextPosition
*pos
)
886 guint nb_trace
, nb_tracefile
;
887 guint iter_trace
, iter_tracefile
;
889 LttvTraceContext
*tc
;
891 LttvTracefileContext
*tfc
;
895 LttTime timestamp
= self
->time_span
.end_time
;
897 pos
->nb_trace
= nb_trace
= lttv_traceset_number(self
->ts
);
898 pos
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
900 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
901 tc
= self
->traces
[iter_trace
];
902 pos
->t_pos
[iter_trace
].nb_tracefile
= nb_tracefile
=
903 ltt_trace_control_tracefile_number(tc
->t
) +
904 ltt_trace_per_cpu_tracefile_number(tc
->t
);
906 pos
->t_pos
[iter_trace
].tf_pos
= g_new(LttEventPosition
*, nb_tracefile
);
907 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
908 tfc
= tc
->tracefiles
[iter_tracefile
];
911 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]
912 = ltt_event_position_new();
913 ltt_event_position(event
,
914 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
916 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
918 if(ltt_time_compare(tfc
->timestamp
, timestamp
) < 0)
919 timestamp
= tfc
->timestamp
;
922 pos
->timestamp
= timestamp
;
925 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition
*pos
)
928 guint iter_trace
, iter_tracefile
;
930 nb_trace
= pos
->nb_trace
;
932 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
933 for(iter_tracefile
= 0; iter_tracefile
<
934 pos
->t_pos
[iter_trace
].nb_tracefile
;
936 if(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
937 g_free(pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
939 g_free(pos
->t_pos
[iter_trace
].tf_pos
);
945 void lttv_traceset_context_position_copy(LttvTracesetContextPosition
*dest
,
946 const LttvTracesetContextPosition
*src
)
948 guint nb_trace
, nb_tracefile
;
949 guint iter_trace
, iter_tracefile
;
951 nb_trace
= dest
->nb_trace
= src
->nb_trace
;
952 dest
->t_pos
= g_new(LttvTraceContextPosition
, nb_trace
);
954 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
956 nb_tracefile
= dest
->t_pos
[iter_trace
].nb_tracefile
=
957 src
->t_pos
[iter_trace
].nb_tracefile
;
959 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
960 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] =
961 ltt_event_position_new();
962 if(src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] != NULL
)
963 ltt_event_position_copy(
964 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
965 src
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
967 dest
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
] = NULL
;
971 dest
->timestamp
= src
->timestamp
;
974 gint
lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext
*self
,
975 const LttvTracesetContextPosition
*pos
)
977 guint nb_trace
, nb_tracefile
;
978 guint iter_trace
, iter_tracefile
;
981 LttvTraceContext
*tc
;
983 LttvTracefileContext
*tfc
;
987 nb_trace
= lttv_traceset_number(self
->ts
);
989 if(pos
->nb_trace
!= nb_trace
)
990 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
992 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
993 tc
= self
->traces
[iter_trace
];
994 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
995 ltt_trace_per_cpu_tracefile_number(tc
->t
);
997 if(pos
->t_pos
[iter_trace
].nb_tracefile
!= nb_tracefile
)
998 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1000 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1001 tfc
= tc
->tracefiles
[iter_tracefile
];
1003 ret
= ltt_event_event_position_compare(event
,
1004 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1013 gint
lttv_traceset_context_pos_pos_compare(
1014 const LttvTracesetContextPosition
*pos1
,
1015 const LttvTracesetContextPosition
*pos2
)
1017 guint nb_trace
, nb_tracefile
;
1018 guint iter_trace
, iter_tracefile
;
1022 nb_trace
= pos1
->nb_trace
;
1023 if(nb_trace
!= pos2
->nb_trace
)
1024 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1026 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1028 nb_tracefile
= pos1
->t_pos
[iter_trace
].nb_tracefile
;
1029 if(nb_tracefile
!= pos2
->t_pos
[iter_trace
].nb_tracefile
)
1030 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1032 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1033 ret
= ltt_event_position_compare(
1034 pos1
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
1035 pos2
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
]);
1044 LttTime
lttv_traceset_context_position_get_time(
1045 const LttvTracesetContextPosition
*pos
)
1047 return pos
->timestamp
;
1051 LttvTracefileContext
*lttv_traceset_context_get_current_tfc(LttvTracesetContext
*self
)
1053 GTree
*pqueue
= self
->pqueue
;
1054 LttvTracefileContext
*tfc
= NULL
;
1056 g_tree_foreach(pqueue
, get_first
, &tfc
);