210be504d614590f8e33a2ca85841f3268962f65
[lttv.git] / lttv / lttv / sync / sync_chain.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26
27 #include <lttv/module.h>
28 #include <lttv/option.h>
29
30 #include "sync_chain.h"
31
32
33 #ifndef g_info
34 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
35 #endif
36
37
38 static void init();
39 static void destroy();
40
41 static void timeDiff(struct timeval* const end, const struct timeval* const start);
42 static gint gcfCompareAnalysis(gconstpointer a, gconstpointer b);
43 static gint gcfCompareProcessing(gconstpointer a, gconstpointer b);
44 static void gfAppendAnalysisName(gpointer data, gpointer user_data);
45
46 static gboolean optionSync;
47 static gboolean optionSyncStats;
48 static gboolean optionSyncNull;
49 static char* optionSyncAnalysis;
50
51 GQueue processingModules= G_QUEUE_INIT;
52 GQueue matchingModules= G_QUEUE_INIT;
53 GQueue analysisModules= G_QUEUE_INIT;
54
55
56 /*
57 * Module init function
58 *
59 * This function is declared to be the module initialization function. Event
60 * modules are registered with a "constructor (102)" attribute except one in
61 * each class (processing, matching, analysis) which is chosen to be the
62 * default and which is registered with a "constructor (101)" attribute.
63 * Constructors with no priority are called after constructors with
64 * priorities. The result is that the list of event modules is known when this
65 * function is executed.
66 */
67 static void init()
68 {
69 GString* analysisModulesNames;
70
71 g_debug("\t\t\tXXXX sync init\n");
72
73 optionSync= FALSE;
74 lttv_option_add("sync", '\0', "synchronize the time between the traces" ,
75 "none", LTTV_OPT_NONE, &optionSync, NULL, NULL);
76
77 optionSyncStats= FALSE;
78 lttv_option_add("sync-stats", '\0', "print statistics about the time "
79 "synchronization", "none", LTTV_OPT_NONE, &optionSyncStats, NULL,
80 NULL);
81
82 optionSyncNull= FALSE;
83 lttv_option_add("sync-null", '\0', "read the events but do not perform "
84 "any processing", "none", LTTV_OPT_NONE, &optionSyncNull, NULL, NULL);
85
86 g_assert(g_queue_get_length(&analysisModules) > 0);
87 optionSyncAnalysis= ((AnalysisModule*)
88 g_queue_peek_head(&analysisModules))->name;
89 analysisModulesNames= g_string_new("");
90 g_queue_foreach(&analysisModules, &gfAppendAnalysisName,
91 analysisModulesNames);
92 // remove the last ", "
93 g_string_truncate(analysisModulesNames, analysisModulesNames->len - 2);
94 lttv_option_add("sync-analysis", '\0', "specify the algorithm to use for "
95 "event analysis" , analysisModulesNames->str, LTTV_OPT_STRING,
96 &optionSyncAnalysis, NULL, NULL);
97 g_string_free(analysisModulesNames, TRUE);
98 }
99
100
101 /*
102 * Module unload function
103 */
104 static void destroy()
105 {
106 g_debug("\t\t\tXXXX sync destroy\n");
107
108 lttv_option_remove("sync");
109 lttv_option_remove("sync-stats");
110 lttv_option_remove("sync-null");
111 lttv_option_remove("sync-analysis");
112 }
113
114
115 /*
116 * Calculate a traceset's drift and offset values based on network events
117 *
118 * The individual correction factors are written out to each trace.
119 *
120 * Args:
121 * traceSetContext: traceset
122 */
123 void syncTraceset(LttvTracesetContext* const traceSetContext)
124 {
125 SyncState* syncState;
126 struct timeval startTime, endTime;
127 struct rusage startUsage, endUsage;
128 GList* result;
129 int retval;
130
131 if (optionSync == FALSE)
132 {
133 g_debug("Not synchronizing traceset because option is disabled");
134 return;
135 }
136
137 if (optionSyncStats)
138 {
139 gettimeofday(&startTime, 0);
140 getrusage(RUSAGE_SELF, &startUsage);
141 }
142
143 // Initialize data structures
144 syncState= malloc(sizeof(SyncState));
145 syncState->traceNb= lttv_traceset_number(traceSetContext->ts);
146
147 if (optionSyncStats)
148 {
149 syncState->stats= true;
150 }
151 else
152 {
153 syncState->stats= false;
154 }
155
156 syncState->processingData= NULL;
157 if (optionSyncNull)
158 {
159 result= g_queue_find_custom(&processingModules, "LTTV-null",
160 &gcfCompareProcessing);
161 }
162 else
163 {
164 result= g_queue_find_custom(&processingModules, "LTTV-standard",
165 &gcfCompareProcessing);
166 }
167 g_assert(result != NULL);
168 syncState->processingModule= (ProcessingModule*) result->data;
169 syncState->processingModule->initProcessing(syncState, traceSetContext);
170
171 syncState->matchingData= NULL;
172 syncState->analysisData= NULL;
173 if (optionSyncNull)
174 {
175 syncState->matchingModule= NULL;
176 syncState->analysisModule= NULL;
177 }
178 else
179 {
180 g_assert(g_queue_get_length(&matchingModules) == 1);
181 syncState->matchingModule= (MatchingModule*)
182 g_queue_peek_head(&matchingModules);
183 syncState->matchingModule->initMatching(syncState);
184
185 result= g_queue_find_custom(&analysisModules, optionSyncAnalysis,
186 &gcfCompareAnalysis);
187 if (result != NULL)
188 {
189 syncState->analysisModule= (AnalysisModule*) result->data;
190 syncState->analysisModule->initAnalysis(syncState);
191 }
192 else
193 {
194 g_error("Analysis module '%s' not found", optionSyncAnalysis);
195 }
196 }
197
198 // Process traceset
199 lttv_process_traceset_seek_time(traceSetContext, ltt_time_zero);
200 lttv_process_traceset_middle(traceSetContext, ltt_time_infinite,
201 G_MAXULONG, NULL);
202 lttv_process_traceset_seek_time(traceSetContext, ltt_time_zero);
203
204 syncState->processingModule->finalizeProcessing(syncState);
205
206 if (syncState->processingModule->printProcessingStats != NULL)
207 {
208 syncState->processingModule->printProcessingStats(syncState);
209 }
210
211 syncState->processingModule->destroyProcessing(syncState);
212 if (syncState->matchingModule != NULL)
213 {
214 syncState->matchingModule->destroyMatching(syncState);
215 }
216 if (syncState->analysisModule != NULL)
217 {
218 syncState->analysisModule->destroyAnalysis(syncState);
219 }
220
221 free(syncState);
222
223 if (optionSyncStats)
224 {
225 gettimeofday(&endTime, 0);
226 retval= getrusage(RUSAGE_SELF, &endUsage);
227
228 timeDiff(&endTime, &startTime);
229 timeDiff(&endUsage.ru_utime, &startUsage.ru_utime);
230 timeDiff(&endUsage.ru_stime, &startUsage.ru_stime);
231
232 printf("Synchronization time:\n");
233 printf("\treal time: %ld.%06ld\n", endTime.tv_sec, endTime.tv_usec);
234 printf("\tuser time: %ld.%06ld\n", endUsage.ru_utime.tv_sec,
235 endUsage.ru_utime.tv_usec);
236 printf("\tsystem time: %ld.%06ld\n", endUsage.ru_stime.tv_sec,
237 endUsage.ru_stime.tv_usec);
238 }
239 }
240
241
242 /*
243 * Calculate the elapsed time between two timeval values
244 *
245 * Args:
246 * end: end time, result is also stored in this structure
247 * start: start time
248 */
249 static void timeDiff(struct timeval* const end, const struct timeval* const start)
250 {
251 if (end->tv_usec >= start->tv_usec)
252 {
253 end->tv_sec-= start->tv_sec;
254 end->tv_usec-= start->tv_usec;
255 }
256 else
257 {
258 end->tv_sec= end->tv_sec - start->tv_sec - 1;
259 end->tv_usec= end->tv_usec - start->tv_usec + 1e6;
260 }
261 }
262
263
264 /*
265 * A GCompareFunc for g_slist_find_custom()
266 *
267 * Args:
268 * a: AnalysisModule*, element's data
269 * b: char*, user data to compare against
270 *
271 * Returns:
272 * 0 if the analysis module a's name is b
273 */
274 static gint gcfCompareAnalysis(gconstpointer a, gconstpointer b)
275 {
276 const AnalysisModule* analysisModule;
277 const char* name;
278
279 analysisModule= (const AnalysisModule*)a;
280 name= (const char*)b;
281
282 return strncmp(analysisModule->name, name, strlen(analysisModule->name) +
283 1);
284 }
285
286
287 /*
288 * A GCompareFunc for g_slist_find_custom()
289 *
290 * Args:
291 * a: ProcessingModule*, element's data
292 * b: char*, user data to compare against
293 *
294 * Returns:
295 * 0 if the analysis module a's name is b
296 */
297 static gint gcfCompareProcessing(gconstpointer a, gconstpointer b)
298 {
299 const ProcessingModule* processingModule;
300 const char* name;
301
302 processingModule= (const ProcessingModule*)a;
303 name= (const char*)b;
304
305 return strncmp(processingModule->name, name,
306 strlen(processingModule->name) + 1);
307 }
308
309
310 /*
311 * A GFunc for g_queue_foreach()
312 *
313 * Concatenate analysis module names.
314 *
315 * Args:
316 * data: AnalysisModule*
317 * user_data: GString*, concatenated names
318 */
319 static void gfAppendAnalysisName(gpointer data, gpointer user_data)
320 {
321 g_string_append((GString*) user_data, ((AnalysisModule*) data)->name);
322 g_string_append((GString*) user_data, ", ");
323 }
324
325
326 LTTV_MODULE("sync", "Synchronize traces", \
327 "Synchronizes a traceset based on the correspondance of network events", \
328 init, destroy, "option")
329
This page took 0.035857 seconds and 3 git commands to generate.