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 LttvTracefileContext
*trace_a
= (LttvTracefileContext
*)a
;
35 LttvTracefileContext
*trace_b
= (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;
47 struct _LttvTraceContextPosition
{
48 LttEventPosition
**tf_pos
; /* Position in each tracefile */
49 guint nb_tracefile
; /* Number of tracefiles (check) */
52 struct _LttvTracesetContextPosition
{
53 LttvTraceContextPosition
*t_pos
; /* Position in each trace */
54 guint nb_trace
; /* Number of traces (check) */
55 LttTime timestamp
; /* Current time at the saved position */
58 void lttv_context_init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
60 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
, ts
);
64 void lttv_context_fini(LttvTracesetContext
*self
)
66 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
71 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
73 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
80 lttv_context_new_trace_context(LttvTracesetContext
*self
)
82 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
86 LttvTracefileContext
*
87 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
89 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
92 /****************************************************************************
93 * lttv_traceset_context_compute_time_span
95 * Keep the time span is sync with on the fly addition and removal of traces
96 * in a trace set. It must be called each time a trace is added/removed from
97 * the traceset. It could be more efficient to call it only once a bunch
98 * of traces are loaded, but the calculation is not long, so it's not
101 * Author : Xang Xiu Yang
102 ***************************************************************************/
103 static void lttv_traceset_context_compute_time_span(
104 LttvTracesetContext
*self
,
105 TimeInterval
*time_span
)
107 LttvTraceset
* traceset
= self
->ts
;
108 int numTraces
= lttv_traceset_number(traceset
);
111 LttvTraceContext
*tc
;
114 time_span
->start_time
.tv_sec
= 0;
115 time_span
->start_time
.tv_nsec
= 0;
116 time_span
->end_time
.tv_sec
= 0;
117 time_span
->end_time
.tv_nsec
= 0;
119 for(i
=0; i
<numTraces
;i
++){
120 tc
= self
->traces
[i
];
123 ltt_trace_time_span_get(trace
, &s
, &e
);
126 time_span
->start_time
= s
;
127 time_span
->end_time
= e
;
129 if(s
.tv_sec
< time_span
->start_time
.tv_sec
130 || (s
.tv_sec
== time_span
->start_time
.tv_sec
131 && s
.tv_nsec
< time_span
->start_time
.tv_nsec
))
132 time_span
->start_time
= s
;
133 if(e
.tv_sec
> time_span
->end_time
.tv_sec
134 || (e
.tv_sec
== time_span
->end_time
.tv_sec
135 && e
.tv_nsec
> time_span
->end_time
.tv_nsec
))
136 time_span
->end_time
= e
;
143 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
145 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
147 LttvTraceContext
*tc
;
149 LttvTracefileContext
*tfc
;
151 LttTime null_time
= {0, 0};
153 nb_trace
= lttv_traceset_number(ts
);
155 self
->traces
= g_new(LttvTraceContext
*, nb_trace
);
156 self
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
157 self
->ts_a
= lttv_traceset_attribute(ts
);
158 for(i
= 0 ; i
< nb_trace
; i
++) {
159 tc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
160 self
->traces
[i
] = tc
;
162 tc
->ts_context
= self
;
164 tc
->vt
= lttv_traceset_get(ts
, i
);
165 tc
->t
= lttv_trace(tc
->vt
);
166 tc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
167 tc
->t_a
= lttv_trace_attribute(tc
->vt
);
168 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
169 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
170 nb_tracefile
= nb_control
+ nb_per_cpu
;
171 tc
->tracefiles
= g_new(LttvTracefileContext
*, nb_tracefile
);
173 for(j
= 0 ; j
< nb_tracefile
; j
++) {
174 tfc
= LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
175 tc
->tracefiles
[j
] = tfc
;
180 tfc
->tf
= ltt_trace_control_tracefile_get(tc
->t
, j
);
183 tfc
->control
= FALSE
;
184 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(tc
->t
, j
- nb_control
);
187 tfc
->e
= ltt_event_new();
188 tfc
->event
= lttv_hooks_new();
189 tfc
->event_by_id
= lttv_hooks_by_id_new();
190 tfc
->a
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
193 self
->pqueue
= g_tree_new(compare_tracefile
);
194 lttv_process_traceset_seek_time(self
, null_time
);
195 lttv_traceset_context_compute_time_span(self
, &self
->time_span
);
200 void fini(LttvTracesetContext
*self
)
202 guint i
, j
, nb_trace
, nb_tracefile
;
204 LttvTraceContext
*tc
;
206 LttvTracefileContext
*tfc
;
208 LttvTraceset
*ts
= self
->ts
;
212 g_tree_destroy(self
->pqueue
);
213 g_object_unref(self
->a
);
215 nb_trace
= lttv_traceset_number(ts
);
217 for(i
= 0 ; i
< nb_trace
; i
++) {
218 tc
= self
->traces
[i
];
220 g_object_unref(tc
->a
);
222 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
223 ltt_trace_per_cpu_tracefile_number(tc
->t
);
225 for(j
= 0 ; j
< nb_tracefile
; j
++) {
226 tfc
= tc
->tracefiles
[j
];
227 ltt_event_destroy(tfc
->e
);
228 lttv_hooks_destroy(tfc
->event
);
229 lttv_hooks_by_id_destroy(tfc
->event_by_id
);
230 g_object_unref(tfc
->a
);
233 g_free(tc
->tracefiles
);
236 g_free(self
->traces
);
240 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
241 LttvHooks
*before_traceset
,
242 LttvHooks
*before_trace
,
243 LttvHooks
*before_tracefile
,
245 LttvHooksById
*event_by_id
)
247 LttvTraceset
*ts
= self
->ts
;
251 LttvTraceContext
*tc
;
253 lttv_hooks_call(before_traceset
, self
);
255 nb_trace
= lttv_traceset_number(ts
);
257 for(i
= 0 ; i
< nb_trace
; i
++) {
258 tc
= self
->traces
[i
];
259 lttv_trace_context_add_hooks(tc
,
268 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
269 LttvHooks
*after_traceset
,
270 LttvHooks
*after_trace
,
271 LttvHooks
*after_tracefile
,
273 LttvHooksById
*event_by_id
)
276 LttvTraceset
*ts
= self
->ts
;
280 LttvTraceContext
*tc
;
282 nb_trace
= lttv_traceset_number(ts
);
284 for(i
= 0 ; i
< nb_trace
; i
++) {
285 tc
= self
->traces
[i
];
286 lttv_trace_context_remove_hooks(tc
,
293 lttv_hooks_call(after_traceset
, self
);
298 void lttv_trace_context_add_hooks(LttvTraceContext
*self
,
299 LttvHooks
*before_trace
,
300 LttvHooks
*before_tracefile
,
302 LttvHooksById
*event_by_id
)
304 guint i
, nb_tracefile
;
306 LttvTracefileContext
*tfc
;
308 lttv_hooks_call(before_trace
, self
);
309 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
310 ltt_trace_per_cpu_tracefile_number(self
->t
);
312 for(i
= 0 ; i
< nb_tracefile
; i
++) {
313 tfc
= self
->tracefiles
[i
];
314 lttv_tracefile_context_add_hooks(tfc
,
323 void lttv_trace_context_remove_hooks(LttvTraceContext
*self
,
324 LttvHooks
*after_trace
,
325 LttvHooks
*after_tracefile
,
327 LttvHooksById
*event_by_id
)
329 guint i
, nb_tracefile
;
331 LttvTracefileContext
*tfc
;
333 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
334 ltt_trace_per_cpu_tracefile_number(self
->t
);
336 for(i
= 0 ; i
< nb_tracefile
; i
++) {
337 tfc
= self
->tracefiles
[i
];
338 lttv_tracefile_context_remove_hooks(tfc
,
344 lttv_hooks_call(after_trace
, self
);
347 void lttv_tracefile_context_add_hooks(LttvTracefileContext
*self
,
348 LttvHooks
*before_tracefile
,
350 LttvHooksById
*event_by_id
)
356 lttv_hooks_call(before_tracefile
, self
);
357 lttv_hooks_add_list(self
->event
, event
);
358 if(event_by_id
!= NULL
)
359 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
360 hook
= lttv_hooks_by_id_get(self
->event_by_id
, i
);
362 lttv_hooks_remove_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
367 void lttv_tracefile_context_remove_hooks(LttvTracefileContext
*self
,
368 LttvHooks
*after_tracefile
,
370 LttvHooksById
*event_by_id
)
377 lttv_hooks_remove_list(self
->event
, event
);
378 if(event_by_id
!= NULL
)
379 for(i
= 0; i
< lttv_hooks_by_id_max_id(event_by_id
); i
++) {
380 hook
= lttv_hooks_by_id_find(self
->event_by_id
, i
);
381 lttv_hooks_add_list(hook
, lttv_hooks_by_id_get(event_by_id
, i
));
384 lttv_hooks_call(after_tracefile
, self
);
389 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext
*tfc
,
391 LttvHooks
*event_by_id
)
394 h
= lttv_hooks_by_id_find(tfc
->event_by_id
, i
);
395 lttv_hooks_add_list(h
, event_by_id
);
398 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext
*tfc
,
401 lttv_hooks_by_id_remove(tfc
->event_by_id
, i
);
404 static LttvTracesetContext
*
405 new_traceset_context(LttvTracesetContext
*self
)
407 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
, NULL
);
411 static LttvTraceContext
*
412 new_trace_context(LttvTracesetContext
*self
)
414 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
, NULL
);
418 static LttvTracefileContext
*
419 new_tracefile_context(LttvTracesetContext
*self
)
421 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
, NULL
);
426 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
428 /* Be careful of anything which would not work well with shallow copies */
433 traceset_context_finalize (LttvTracesetContext
*self
)
435 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE
)))
436 ->finalize(G_OBJECT(self
));
441 traceset_context_class_init (LttvTracesetContextClass
*klass
)
443 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
445 gobject_class
->finalize
= (void (*)(GObject
*self
))traceset_context_finalize
;
448 klass
->new_traceset_context
= new_traceset_context
;
449 klass
->new_trace_context
= new_trace_context
;
450 klass
->new_tracefile_context
= new_tracefile_context
;
455 lttv_traceset_context_get_type(void)
457 static GType type
= 0;
459 static const GTypeInfo info
= {
460 sizeof (LttvTracesetContextClass
),
461 NULL
, /* base_init */
462 NULL
, /* base_finalize */
463 (GClassInitFunc
) traceset_context_class_init
, /* class_init */
464 NULL
, /* class_finalize */
465 NULL
, /* class_data */
466 sizeof (LttvTracesetContext
),
468 (GInstanceInitFunc
) traceset_context_instance_init
/* instance_init */
471 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
479 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
481 /* Be careful of anything which would not work well with shallow copies */
486 trace_context_finalize (LttvTraceContext
*self
)
488 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE
)))->
489 finalize(G_OBJECT(self
));
494 trace_context_class_init (LttvTraceContextClass
*klass
)
496 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
498 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_context_finalize
;
503 lttv_trace_context_get_type(void)
505 static GType type
= 0;
507 static const GTypeInfo info
= {
508 sizeof (LttvTraceContextClass
),
509 NULL
, /* base_init */
510 NULL
, /* base_finalize */
511 (GClassInitFunc
) trace_context_class_init
, /* class_init */
512 NULL
, /* class_finalize */
513 NULL
, /* class_data */
514 sizeof (LttvTraceContext
),
516 (GInstanceInitFunc
) trace_context_instance_init
/* instance_init */
519 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
527 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
529 /* Be careful of anything which would not work well with shallow copies */
534 tracefile_context_finalize (LttvTracefileContext
*self
)
536 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE
)))
537 ->finalize(G_OBJECT(self
));
542 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
544 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
546 gobject_class
->finalize
= (void (*)(GObject
*self
))tracefile_context_finalize
;
551 lttv_tracefile_context_get_type(void)
553 static GType type
= 0;
555 static const GTypeInfo info
= {
556 sizeof (LttvTracefileContextClass
),
557 NULL
, /* base_init */
558 NULL
, /* base_finalize */
559 (GClassInitFunc
) tracefile_context_class_init
, /* class_init */
560 NULL
, /* class_finalize */
561 NULL
, /* class_data */
562 sizeof (LttvTracefileContext
),
564 (GInstanceInitFunc
) tracefile_context_instance_init
/* instance_init */
567 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
575 gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
576 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
581 /* Put all the tracefiles at the tracefile context position */
582 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext
*self
)
584 guint iter_trace
, nb_trace
;
586 LttvTraceContext
*tc
;
588 nb_trace
= lttv_traceset_number(self
->ts
);
590 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
591 tc
= self
->traces
[iter_trace
];
594 guint iter_tf
, nb_tracefile
;
596 LttvTracefileContext
*tfc
;
598 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
599 ltt_trace_per_cpu_tracefile_number(tc
->t
);
601 for(iter_tf
= 0 ; iter_tf
< nb_tracefile
; iter_tf
++) {
602 tfc
= tc
->tracefiles
[iter_tf
];
605 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
606 LttEventPosition
*ep
= ltt_event_position_new();
608 ltt_event_position(tfc
->e
, ep
);
610 ltt_tracefile_seek_position(tfc
->tf
, ep
);
620 void lttv_process_traceset_begin(LttvTracesetContext
*self
,
621 LttvHooks
*before_traceset
,
622 LttvHooks
*before_trace
,
623 LttvHooks
*before_tracefile
,
625 LttvHooksById
*event_by_id
)
628 /* simply add hooks in context. _before hooks are called by add_hooks. */
629 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
630 lttv_traceset_context_add_hooks(self
,
639 /* Note : a _middle must be preceded from a _seek or another middle */
640 guint
lttv_process_traceset_middle(LttvTracesetContext
*self
,
643 const LttvTracesetContextPosition
*end_position
)
645 GTree
*pqueue
= self
->pqueue
;
649 LttvTracefileContext
*tfc
;
653 gboolean last_ret
= FALSE
; /* return value of the last hook list called */
655 /* Get the next event from the pqueue, call its hooks,
656 reinsert in the pqueue the following event from the same tracefile
657 unless the tracefile is finished or the event is later than the
662 g_tree_foreach(pqueue
, get_first
, &tfc
);
663 /* End of traceset : tfc is NULL */
670 * - the maximum number of events specified?
671 * - the end position ?
673 * then the read is finished. We leave the queue in the same state and
677 if(last_ret
== TRUE
||
678 count
>= nb_events
||
679 (end_position
!=NULL
&<tv_traceset_context_ctx_pos_compare(self
,
680 end_position
) == 0)||
681 ltt_time_compare(tfc
->timestamp
, end
) >= 0)
686 /* Get the tracefile with an event for the smallest time found. If two
687 or more tracefiles have events for the same time, hope that lookup
688 and remove are consistent. */
690 g_tree_remove(pqueue
, tfc
);
693 id
= ltt_event_eventtype_id(tfc
->e
);
694 last_ret
= lttv_hooks_call_merge(tfc
->event
, tfc
,
695 lttv_hooks_by_id_get(tfc
->event_by_id
, id
), tfc
);
697 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
698 tfc
->timestamp
= ltt_event_time(tfc
->e
);
699 g_tree_insert(pqueue
, tfc
, tfc
);
705 void lttv_process_traceset_end(LttvTracesetContext
*self
,
706 LttvHooks
*after_traceset
,
707 LttvHooks
*after_trace
,
708 LttvHooks
*after_tracefile
,
710 LttvHooksById
*event_by_id
)
712 /* Remove hooks from context. _after hooks are called by remove_hooks. */
713 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
714 lttv_traceset_context_remove_hooks(self
,
722 void lttv_process_trace_seek_time(LttvTraceContext
*self
, LttTime start
)
724 guint i
, nb_tracefile
;
726 LttvTracefileContext
*tfc
;
728 GTree
*pqueue
= self
->ts_context
->pqueue
;
730 nb_tracefile
= ltt_trace_control_tracefile_number(self
->t
) +
731 ltt_trace_per_cpu_tracefile_number(self
->t
);
733 for(i
= 0 ; i
< nb_tracefile
; i
++) {
734 tfc
= self
->tracefiles
[i
];
735 ltt_tracefile_seek_time(tfc
->tf
, start
);
736 g_tree_remove(pqueue
, tfc
);
737 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
738 tfc
->timestamp
= ltt_event_time(tfc
->e
);
739 g_tree_insert(pqueue
, tfc
, tfc
);
745 void lttv_process_traceset_seek_time(LttvTracesetContext
*self
, LttTime start
)
749 LttvTraceContext
*tc
;
751 LttvTracefileContext
*tfc
;
753 nb_trace
= lttv_traceset_number(self
->ts
);
754 for(i
= 0 ; i
< nb_trace
; i
++) {
755 tc
= self
->traces
[i
];
756 lttv_process_trace_seek_time(tc
, start
);
761 gboolean
lttv_process_tracefile_seek_position(LttvTracefileContext
*self
,
762 const LttEventPosition
*pos
)
764 LttvTracefileContext
*tfc
= self
;
768 GTree
*pqueue
= self
->t_context
->ts_context
->pqueue
;
770 ltt_tracefile_seek_position(tfc
->tf
, pos
);
771 g_tree_remove(pqueue
, tfc
);
772 if(ltt_tracefile_read(tfc
->tf
, tfc
->e
) != NULL
) {
773 tfc
->timestamp
= ltt_event_time(tfc
->e
);
774 g_tree_insert(pqueue
, tfc
, tfc
);
780 gboolean
lttv_process_trace_seek_position(LttvTraceContext
*self
,
781 const LttvTraceContextPosition
*pos
)
783 guint i
, nb_tracefile
;
785 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 LttvTracefileContext
*tfc
;
815 nb_trace
= lttv_traceset_number(self
->ts
);
817 if(nb_trace
!= pos
->nb_trace
)
818 return FALSE
; /* Error */
820 for(i
= 0 ; i
< nb_trace
; i
++) {
821 tc
= self
->traces
[i
];
822 sum_ret
= sum_ret
&& lttv_process_trace_seek_position(tc
, &pos
->t_pos
[i
]);
831 find_field(LttEventType
*et
, const char *field
)
841 if(field
== NULL
) return NULL
;
843 f
= ltt_eventtype_field(et
);
844 t
= ltt_eventtype_type(et
);
845 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
846 nb
= ltt_type_member_number(t
);
847 for(i
= 0 ; i
< nb
; i
++) {
848 ltt_type_member_type(t
, i
, &name
);
849 if(strcmp(name
, field
) == 0) break;
852 return ltt_field_member(f
, i
);
857 lttv_trace_find_hook(LttTrace
*t
, char *facility
, char *event_type
,
858 char *field1
, char *field2
, char *field3
, LttvHook h
, LttvTraceHook
*th
)
868 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
869 if(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(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
)
932 guint nb_trace
, nb_tracefile
;
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(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(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
];
1010 ltt_event_event_position_compare(event
,
1011 pos
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
])
1020 gint
lttv_traceset_context_pos_pos_compare(
1021 const LttvTracesetContextPosition
*pos1
,
1022 const LttvTracesetContextPosition
*pos2
)
1024 guint nb_trace
, nb_tracefile
;
1025 guint iter_trace
, iter_tracefile
;
1029 nb_trace
= pos1
->nb_trace
;
1030 if(nb_trace
!= pos2
->nb_trace
)
1031 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1033 for(iter_trace
= 0 ; iter_trace
< nb_trace
; iter_trace
++) {
1035 nb_tracefile
= pos1
->t_pos
[iter_trace
].nb_tracefile
;
1036 if(nb_tracefile
!= pos2
->t_pos
[iter_trace
].nb_tracefile
)
1037 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1039 for(iter_tracefile
= 0; iter_tracefile
< nb_tracefile
; iter_tracefile
++) {
1041 ltt_event_position_compare(
1042 pos1
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
],
1043 pos2
->t_pos
[iter_trace
].tf_pos
[iter_tracefile
])
1052 LttTime
lttv_traceset_context_position_get_time(
1053 const LttvTracesetContextPosition
*pos
)
1055 return pos
->timestamp
;
1059 LttvTracefileContext
*lttv_traceset_context_get_current_tfc(LttvTracesetContext
*self
)
1061 GTree
*pqueue
= self
->pqueue
;
1062 LttvTracefileContext
*tfc
= NULL
;
1064 g_tree_foreach(pqueue
, get_first
, &tfc
);