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