Change synchronization code license to LGPLv2.1
[lttv.git] / lttv / lttv / sync / sync_chain_lttv.c
CommitLineData
70407e86 1/* This file is part of the Linux Trace Toolkit viewer
277e5b53 2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
70407e86 3 *
277e5b53
BP
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or (at
7 * your option) any later version.
70407e86 8 *
277e5b53
BP
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
70407e86 13 *
277e5b53
BP
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
70407e86
BP
16 */
17
18#ifdef HAVE_CONFIG_H
19#include <config.h>
20#endif
21
08365995
BP
22#include <errno.h>
23#include <fcntl.h>
24#include <stdio.h>
70407e86 25#include <stdlib.h>
70407e86 26#include <sys/resource.h>
08365995 27#include <sys/stat.h>
08365995
BP
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
70407e86
BP
31
32#include <lttv/module.h>
33#include <lttv/option.h>
34
2f961b65
BP
35
36#include "event_processing_lttng_standard.h"
37#include "event_processing_lttng_null.h"
38#include "event_matching_tcp.h"
39#include "event_matching_broadcast.h"
40#include "event_matching_distributor.h"
41#include "event_analysis_chull.h"
42#include "event_analysis_linreg.h"
43#include "event_analysis_eval.h"
2bd4b3e4 44#include "sync_chain.h"
2f076594 45#include "sync_chain_lttv.h"
70407e86
BP
46
47
70407e86
BP
48static void init();
49static void destroy();
50
2bd4b3e4
BP
51static void gfAddModuleOption(gpointer data, gpointer user_data);
52static void gfRemoveModuleOption(gpointer data, gpointer user_data);
70407e86 53
2bd4b3e4
BP
54static ModuleOption optionSync= {
55 .longName= "sync",
56 .hasArg= NO_ARG,
2bd4b3e4
BP
57 .optionHelp= "synchronize the time between the traces",
58};
2bd4b3e4
BP
59static ModuleOption optionSyncStats= {
60 .longName= "sync-stats",
61 .hasArg= NO_ARG,
2bd4b3e4
BP
62 .optionHelp= "print statistics about the time synchronization",
63};
64static ModuleOption optionSyncNull= {
65 .longName= "sync-null",
66 .hasArg= NO_ARG,
2bd4b3e4
BP
67 .optionHelp= "read the events but do not perform any processing",
68};
69static GString* analysisModulesNames;
70static ModuleOption optionSyncAnalysis= {
71 .longName= "sync-analysis",
72 .hasArg= REQUIRED_ARG,
73 .optionHelp= "specify the algorithm to use for event analysis",
74};
75static ModuleOption optionSyncGraphs= {
76 .longName= "sync-graphs",
77 .hasArg= NO_ARG,
2bd4b3e4
BP
78 .optionHelp= "output gnuplot graph showing synchronization points",
79};
49c335f1 80static char graphsDir[20];
2bd4b3e4
BP
81static ModuleOption optionSyncGraphsDir= {
82 .longName= "sync-graphs-dir",
83 .hasArg= REQUIRED_ARG,
84 .optionHelp= "specify the directory where to store the graphs",
85};
70407e86 86
49c335f1 87
70407e86
BP
88/*
89 * Module init function
90 *
2f961b65 91 * This function is declared to be the module initialization function.
70407e86
BP
92 */
93static void init()
94{
08365995 95 int retval;
70407e86 96
d5b038ec 97 g_debug("Sync init");
70407e86 98
2f961b65
BP
99 /*
100 * Initialize event modules
101 * Call the "constructor" or initialization function of each event module
102 * so it can register itself. This must be done before elements in
103 * processingModules, matchingModules, analysisModules or moduleOptions
104 * are accessed.
105 */
106 registerProcessingLTTVStandard();
107 registerProcessingLTTVNull();
108
109 registerMatchingTCP();
110 registerMatchingBroadcast();
111 registerMatchingDistributor();
112
113 registerAnalysisCHull();
114 registerAnalysisLinReg();
115 registerAnalysisEval();
116
70407e86 117 g_assert(g_queue_get_length(&analysisModules) > 0);
49c335f1 118 optionSyncAnalysis.arg= ((AnalysisModule*)
70407e86
BP
119 g_queue_peek_head(&analysisModules))->name;
120 analysisModulesNames= g_string_new("");
121 g_queue_foreach(&analysisModules, &gfAppendAnalysisName,
122 analysisModulesNames);
123 // remove the last ", "
124 g_string_truncate(analysisModulesNames, analysisModulesNames->len - 2);
2bd4b3e4 125 optionSyncAnalysis.argHelp= analysisModulesNames->str;
08365995
BP
126
127 retval= snprintf(graphsDir, sizeof(graphsDir), "graphs-%d", getpid());
128 if (retval > sizeof(graphsDir) - 1)
129 {
130 graphsDir[sizeof(graphsDir) - 1]= '\0';
131 }
2bd4b3e4
BP
132 optionSyncGraphsDir.arg= graphsDir;
133 optionSyncGraphsDir.argHelp= graphsDir;
134
135 g_queue_push_head(&moduleOptions, &optionSyncGraphsDir);
136 g_queue_push_head(&moduleOptions, &optionSyncGraphs);
137 g_queue_push_head(&moduleOptions, &optionSyncAnalysis);
138 g_queue_push_head(&moduleOptions, &optionSyncNull);
139 g_queue_push_head(&moduleOptions, &optionSyncStats);
140 g_queue_push_head(&moduleOptions, &optionSync);
141
142 g_queue_foreach(&moduleOptions, &gfAddModuleOption, NULL);
70407e86
BP
143}
144
145
146/*
147 * Module unload function
148 */
149static void destroy()
150{
d5b038ec 151 g_debug("Sync destroy");
70407e86 152
2bd4b3e4
BP
153 g_queue_foreach(&moduleOptions, &gfRemoveModuleOption, NULL);
154 g_string_free(analysisModulesNames, TRUE);
155
156 g_queue_clear(&processingModules);
157 g_queue_clear(&matchingModules);
158 g_queue_clear(&analysisModules);
159 g_queue_clear(&moduleOptions);
70407e86
BP
160}
161
162
163/*
164 * Calculate a traceset's drift and offset values based on network events
165 *
166 * The individual correction factors are written out to each trace.
167 *
168 * Args:
169 * traceSetContext: traceset
482fe481
BP
170 *
171 * Returns:
172 * false if synchronization was not performed, true otherwise
70407e86 173 */
482fe481 174bool syncTraceset(LttvTracesetContext* const traceSetContext)
70407e86
BP
175{
176 SyncState* syncState;
177 struct timeval startTime, endTime;
178 struct rusage startUsage, endUsage;
179 GList* result;
467066ee 180 unsigned int i;
70407e86
BP
181 int retval;
182
2bd4b3e4 183 if (!optionSync.present)
70407e86
BP
184 {
185 g_debug("Not synchronizing traceset because option is disabled");
482fe481 186 return false;
70407e86
BP
187 }
188
2bd4b3e4 189 if (optionSyncStats.present)
70407e86
BP
190 {
191 gettimeofday(&startTime, 0);
192 getrusage(RUSAGE_SELF, &startUsage);
193 }
194
195 // Initialize data structures
196 syncState= malloc(sizeof(SyncState));
70407e86 197
2bd4b3e4 198 if (optionSyncStats.present)
70407e86
BP
199 {
200 syncState->stats= true;
201 }
202 else
203 {
204 syncState->stats= false;
205 }
206
1ed11971 207 if (!optionSyncNull.present && optionSyncGraphs.present)
08365995
BP
208 {
209 // Create the graph directory right away in case the module initialization
210 // functions have something to write in it.
8d7d16dd 211 syncState->graphsDir= optionSyncGraphsDir.arg;
1d597550 212 syncState->graphsStream= createGraphsDir(syncState->graphsDir);
08365995 213 }
8d7d16dd
BP
214 else
215 {
216 syncState->graphsStream= NULL;
217 syncState->graphsDir= NULL;
218 }
08365995 219
d4721e1a
BP
220 // Identify and initialize modules
221 syncState->processingData= NULL;
222 if (optionSyncNull.present)
223 {
224 result= g_queue_find_custom(&processingModules, "LTTV-null",
225 &gcfCompareProcessing);
226 }
227 else
228 {
229 result= g_queue_find_custom(&processingModules, "LTTV-standard",
230 &gcfCompareProcessing);
231 }
232 g_assert(result != NULL);
233 syncState->processingModule= (ProcessingModule*) result->data;
234
235 syncState->matchingData= NULL;
f10c27a8
BP
236 result= g_queue_find_custom(&matchingModules, "TCP", &gcfCompareMatching);
237 g_assert(result != NULL);
238 syncState->matchingModule= (MatchingModule*) result->data;
70407e86 239
d4721e1a 240 syncState->analysisData= NULL;
2bd4b3e4 241 result= g_queue_find_custom(&analysisModules, optionSyncAnalysis.arg,
f6691532
BP
242 &gcfCompareAnalysis);
243 if (result != NULL)
70407e86 244 {
f6691532 245 syncState->analysisModule= (AnalysisModule*) result->data;
70407e86
BP
246 }
247 else
248 {
2bd4b3e4 249 g_error("Analysis module '%s' not found", optionSyncAnalysis.arg);
f6691532 250 }
70407e86 251
09857093 252 syncState->processingModule->initProcessing(syncState, traceSetContext);
2bd4b3e4 253 if (!optionSyncNull.present)
f6691532 254 {
d4721e1a 255 syncState->matchingModule->initMatching(syncState);
09857093 256 syncState->analysisModule->initAnalysis(syncState);
70407e86
BP
257 }
258
259 // Process traceset
260 lttv_process_traceset_seek_time(traceSetContext, ltt_time_zero);
261 lttv_process_traceset_middle(traceSetContext, ltt_time_infinite,
262 G_MAXULONG, NULL);
263 lttv_process_traceset_seek_time(traceSetContext, ltt_time_zero);
264
265 syncState->processingModule->finalizeProcessing(syncState);
266
08365995 267 // Write graphs file
1ed11971 268 if (!optionSyncNull.present && optionSyncGraphs.present)
08365995 269 {
467066ee 270 writeGraphsScript(syncState);
08365995 271
8d7d16dd 272 if (fclose(syncState->graphsStream) != 0)
08365995
BP
273 {
274 g_error(strerror(errno));
275 }
276 }
277
1ed11971 278 if (!optionSyncNull.present && optionSyncStats.present)
70407e86 279 {
1ed11971 280 printStats(syncState);
d6ee5003 281
d6ee5003
BP
282 printf("Resulting synchronization factors:\n");
283 for (i= 0; i < syncState->traceNb; i++)
284 {
285 LttTrace* t;
286
287 t= traceSetContext->traces[i]->t;
288
289 printf("\ttrace %u drift= %g offset= %g (%f) start time= %ld.%09ld\n",
290 i, t->drift, t->offset, (double) tsc_to_uint64(t->freq_scale,
291 t->start_freq, t->offset) / NANOSECONDS_PER_SECOND,
292 t->start_time_from_tsc.tv_sec,
293 t->start_time_from_tsc.tv_nsec);
294 }
295 }
70407e86
BP
296
297 syncState->processingModule->destroyProcessing(syncState);
298 if (syncState->matchingModule != NULL)
299 {
300 syncState->matchingModule->destroyMatching(syncState);
301 }
302 if (syncState->analysisModule != NULL)
303 {
304 syncState->analysisModule->destroyAnalysis(syncState);
305 }
306
307 free(syncState);
308
2bd4b3e4 309 if (optionSyncStats.present)
70407e86
BP
310 {
311 gettimeofday(&endTime, 0);
312 retval= getrusage(RUSAGE_SELF, &endUsage);
313
314 timeDiff(&endTime, &startTime);
315 timeDiff(&endUsage.ru_utime, &startUsage.ru_utime);
316 timeDiff(&endUsage.ru_stime, &startUsage.ru_stime);
317
318 printf("Synchronization time:\n");
319 printf("\treal time: %ld.%06ld\n", endTime.tv_sec, endTime.tv_usec);
320 printf("\tuser time: %ld.%06ld\n", endUsage.ru_utime.tv_sec,
321 endUsage.ru_utime.tv_usec);
322 printf("\tsystem time: %ld.%06ld\n", endUsage.ru_stime.tv_sec,
323 endUsage.ru_stime.tv_usec);
324 }
482fe481
BP
325
326 return true;
70407e86
BP
327}
328
329
2bd4b3e4
BP
330/*
331 * A GFunc for g_queue_foreach()
332 *
333 * Args:
334 * data: ModuleOption*
335 * user_data: NULL
336 */
337static void gfAddModuleOption(gpointer data, gpointer user_data)
338{
49c335f1 339 ModuleOption* option= data;
2bd4b3e4
BP
340 LttvOptionType conversion[]= {
341 [NO_ARG]= LTTV_OPT_NONE,
49c335f1 342 [OPTIONAL_ARG]= LTTV_OPT_NONE,
2bd4b3e4
BP
343 [REQUIRED_ARG]= LTTV_OPT_STRING,
344 };
49c335f1
BP
345 size_t fieldOffset[]= {
346 [NO_ARG]= offsetof(ModuleOption, present),
347 [REQUIRED_ARG]= offsetof(ModuleOption, arg),
348 };
349 static const char* argHelpNone= "none";
2bd4b3e4
BP
350
351 g_assert_cmpuint(sizeof(conversion) / sizeof(*conversion), ==,
352 HAS_ARG_COUNT);
49c335f1
BP
353 if (option->hasArg == OPTIONAL_ARG)
354 {
355 g_warning("Parameters with optional arguments not supported by the "
356 "lttv option scheme, parameter '%s' will not be available",
357 option->longName);
358 }
359 else
360 {
361 lttv_option_add(option->longName, '\0', option->optionHelp,
362 option->argHelp ? option->argHelp : argHelpNone,
363 conversion[option->hasArg], (void*) option + fieldOffset[option->hasArg],
364 NULL, NULL);
365 }
2bd4b3e4
BP
366}
367
368
369/*
370 * A GFunc for g_queue_foreach()
371 *
372 * Args:
373 * data: ModuleOption*
374 * user_data: NULL
375 */
376static void gfRemoveModuleOption(gpointer data, gpointer user_data)
377{
378 lttv_option_remove(((ModuleOption*) data)->longName);
379}
380
381
70407e86
BP
382LTTV_MODULE("sync", "Synchronize traces", \
383 "Synchronizes a traceset based on the correspondance of network events", \
384 init, destroy, "option")
This page took 0.043349 seconds and 4 git commands to generate.