6 * Copyright 2012 EfficiOS Inc. and Linux Foundation
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 #include <babeltrace/babeltrace.h>
21 #include <babeltrace/format.h>
22 #include <babeltrace/context.h>
23 #include <babeltrace/ctf/types.h>
24 #include <babeltrace/ctf-text/types.h>
25 #include <babeltrace/trace-collection.h>
26 #include <babeltrace/ctf-ir/metadata.h> /* for clocks */
32 struct ctf_clock
*clock_match
;
33 struct trace_collection
*tc
;
36 static void check_clock_match(gpointer key
, gpointer value
, gpointer user_data
)
38 struct clock_match
*match
= user_data
;
39 struct ctf_clock
*clock_a
= value
, *clock_b
;
41 if (clock_a
->uuid
!= 0) {
43 * Lookup the the trace clocks into the collection
46 clock_b
= g_hash_table_lookup(match
->clocks
,
47 (gpointer
) (unsigned long) clock_a
->uuid
);
49 match
->clock_match
= clock_b
;
52 } else if (clock_a
->absolute
) {
54 * Absolute time references, such as NTP, are looked up
57 clock_b
= g_hash_table_lookup(match
->clocks
,
58 (gpointer
) (unsigned long) clock_a
->name
);
60 match
->clock_match
= clock_b
;
66 static void clock_add(gpointer key
, gpointer value
, gpointer user_data
)
68 struct clock_match
*clock_match
= user_data
;
69 GHashTable
*tc_clocks
= clock_match
->clocks
;
70 struct ctf_clock
*t_clock
= value
;
73 if (t_clock
->absolute
)
78 struct ctf_clock
*tc_clock
;
80 tc_clock
= g_hash_table_lookup(tc_clocks
,
81 (gpointer
) (unsigned long) v
);
84 * For now, we only support CTF that has one
85 * single clock uuid or name (absolute ref).
87 if (g_hash_table_size(tc_clocks
) > 0) {
88 fprintf(stderr
, "[error] Only CTF traces with a single clock description are supported by this babeltrace version.\n");
90 if (!clock_match
->tc
->offset_nr
) {
91 clock_match
->tc
->offset_first
=
92 (t_clock
->offset_s
* 1000000000ULL) + t_clock
->offset
;
93 clock_match
->tc
->delta_offset_first_sum
= 0;
94 clock_match
->tc
->offset_nr
++;
95 clock_match
->tc
->single_clock_offset_avg
=
96 clock_match
->tc
->offset_first
;
98 g_hash_table_insert(tc_clocks
,
99 (gpointer
) (unsigned long) v
,
105 * Check that the offsets match. If not, warn
106 * the user that we do an arbitrary choice.
108 diff_ns
= tc_clock
->offset_s
;
109 diff_ns
-= t_clock
->offset_s
;
110 diff_ns
*= 1000000000ULL;
111 diff_ns
+= tc_clock
->offset
;
112 diff_ns
-= t_clock
->offset
;
113 printf_debug("Clock \"%s\" offset between traces has a delta of %" PRIu64
" ns.",
114 g_quark_to_string(tc_clock
->name
),
115 diff_ns
< 0 ? -diff_ns
: diff_ns
);
116 if (diff_ns
> 10000) {
117 fprintf(stderr
, "[warning] Clock \"%s\" offset differs between traces (delta %" PRIu64
" ns). Using average.\n",
118 g_quark_to_string(tc_clock
->name
),
119 diff_ns
< 0 ? -diff_ns
: diff_ns
);
121 /* Compute average */
122 clock_match
->tc
->delta_offset_first_sum
+=
123 (t_clock
->offset_s
* 1000000000ULL) + t_clock
->offset
124 - clock_match
->tc
->offset_first
;
125 clock_match
->tc
->offset_nr
++;
126 clock_match
->tc
->single_clock_offset_avg
=
127 clock_match
->tc
->offset_first
128 + (clock_match
->tc
->delta_offset_first_sum
/ clock_match
->tc
->offset_nr
);
134 * Whenever we add a trace to the trace collection, check that we can
135 * correlate this trace with at least one other clock in the trace.
137 int trace_collection_add(struct trace_collection
*tc
,
138 struct trace_descriptor
*td
)
140 struct ctf_trace
*trace
= container_of(td
, struct ctf_trace
, parent
);
142 g_ptr_array_add(tc
->array
, td
);
143 trace
->collection
= tc
;
145 if (tc
->array
->len
> 1) {
146 struct clock_match clock_match
= {
147 .clocks
= tc
->clocks
,
153 * With two or more traces, we need correlation info
156 g_hash_table_foreach(trace
->clocks
,
159 if (!clock_match
.clock_match
) {
160 fprintf(stderr
, "[error] No clocks can be correlated and multiple traces are added to the collection.\n");
166 struct clock_match clock_match
= {
167 .clocks
= tc
->clocks
,
173 * Add each clock from the trace clocks into the trace
176 g_hash_table_foreach(trace
->clocks
,
185 int trace_collection_remove(struct trace_collection
*tc
,
186 struct trace_descriptor
*td
)
188 if (g_ptr_array_remove(tc
->array
, td
)) {
196 void init_trace_collection(struct trace_collection
*tc
)
198 tc
->array
= g_ptr_array_new();
199 tc
->clocks
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
200 tc
->single_clock_offset_avg
= 0;
201 tc
->offset_first
= 0;
202 tc
->delta_offset_first_sum
= 0;
207 * finalize_trace_collection() closes the opened traces for read
208 * and free the memory allocated for trace collection
210 void finalize_trace_collection(struct trace_collection
*tc
)
212 g_ptr_array_free(tc
->array
, TRUE
);
213 g_hash_table_destroy(tc
->clocks
);
This page took 0.033927 seconds and 4 git commands to generate.