1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
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.
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.
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/>.
26 #include <sys/resource.h>
28 #include <sys/types.h>
32 #include <lttv/module.h>
33 #include <lttv/option.h>
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"
44 #include "sync_chain.h"
45 #include "sync_chain_lttv.h"
49 static void destroy();
51 static void gfAddModuleOption(gpointer data
, gpointer user_data
);
52 static void gfRemoveModuleOption(gpointer data
, gpointer user_data
);
54 static ModuleOption optionSync
= {
57 .optionHelp
= "synchronize the time between the traces",
59 static ModuleOption optionSyncStats
= {
60 .longName
= "sync-stats",
62 .optionHelp
= "print statistics about the time synchronization",
64 static ModuleOption optionSyncNull
= {
65 .longName
= "sync-null",
67 .optionHelp
= "read the events but do not perform any processing",
69 static GString
* analysisModulesNames
;
70 static ModuleOption optionSyncAnalysis
= {
71 .longName
= "sync-analysis",
72 .hasArg
= REQUIRED_ARG
,
73 .optionHelp
= "specify the algorithm to use for event analysis",
75 static ModuleOption optionSyncGraphs
= {
76 .longName
= "sync-graphs",
78 .optionHelp
= "output gnuplot graph showing synchronization points",
80 static char graphsDir
[20];
81 static ModuleOption optionSyncGraphsDir
= {
82 .longName
= "sync-graphs-dir",
83 .hasArg
= REQUIRED_ARG
,
84 .optionHelp
= "specify the directory where to store the graphs",
89 * Module init function
91 * This function is declared to be the module initialization function.
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
106 registerProcessingLTTVStandard();
107 registerProcessingLTTVNull();
109 registerMatchingTCP();
110 registerMatchingBroadcast();
111 registerMatchingDistributor();
113 registerAnalysisCHull();
114 registerAnalysisLinReg();
115 registerAnalysisEval();
117 g_assert(g_queue_get_length(&analysisModules
) > 0);
118 optionSyncAnalysis
.arg
= ((AnalysisModule
*)
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);
125 optionSyncAnalysis
.argHelp
= analysisModulesNames
->str
;
127 retval
= snprintf(graphsDir
, sizeof(graphsDir
), "graphs-%d", getpid());
128 if (retval
> sizeof(graphsDir
) - 1)
130 graphsDir
[sizeof(graphsDir
) - 1]= '\0';
132 optionSyncGraphsDir
.arg
= graphsDir
;
133 optionSyncGraphsDir
.argHelp
= graphsDir
;
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
);
142 g_queue_foreach(&moduleOptions
, &gfAddModuleOption
, NULL
);
147 * Module unload function
149 static void destroy()
151 g_debug("Sync destroy");
153 g_queue_foreach(&moduleOptions
, &gfRemoveModuleOption
, NULL
);
154 g_string_free(analysisModulesNames
, TRUE
);
156 g_queue_clear(&processingModules
);
157 g_queue_clear(&matchingModules
);
158 g_queue_clear(&analysisModules
);
159 g_queue_clear(&moduleOptions
);
164 * Calculate a traceset's drift and offset values based on network events
166 * The individual correction factors are written out to each trace.
169 * traceSetContext: traceset
172 * false if synchronization was not performed, true otherwise
174 bool syncTraceset(LttvTracesetContext
* const traceSetContext
)
176 SyncState
* syncState
;
177 struct timeval startTime
, endTime
;
178 struct rusage startUsage
, endUsage
;
183 if (!optionSync
.present
)
185 g_debug("Not synchronizing traceset because option is disabled");
189 if (optionSyncStats
.present
)
191 gettimeofday(&startTime
, 0);
192 getrusage(RUSAGE_SELF
, &startUsage
);
195 // Initialize data structures
196 syncState
= malloc(sizeof(SyncState
));
198 if (optionSyncStats
.present
)
200 syncState
->stats
= true;
204 syncState
->stats
= false;
207 if (!optionSyncNull
.present
&& optionSyncGraphs
.present
)
209 // Create the graph directory right away in case the module initialization
210 // functions have something to write in it.
211 syncState
->graphsDir
= optionSyncGraphsDir
.arg
;
212 syncState
->graphsStream
= createGraphsDir(syncState
->graphsDir
);
216 syncState
->graphsStream
= NULL
;
217 syncState
->graphsDir
= NULL
;
220 // Identify and initialize modules
221 syncState
->processingData
= NULL
;
222 if (optionSyncNull
.present
)
224 result
= g_queue_find_custom(&processingModules
, "LTTV-null",
225 &gcfCompareProcessing
);
229 result
= g_queue_find_custom(&processingModules
, "LTTV-standard",
230 &gcfCompareProcessing
);
232 g_assert(result
!= NULL
);
233 syncState
->processingModule
= (ProcessingModule
*) result
->data
;
235 syncState
->matchingData
= NULL
;
236 result
= g_queue_find_custom(&matchingModules
, "TCP", &gcfCompareMatching
);
237 g_assert(result
!= NULL
);
238 syncState
->matchingModule
= (MatchingModule
*) result
->data
;
240 syncState
->analysisData
= NULL
;
241 result
= g_queue_find_custom(&analysisModules
, optionSyncAnalysis
.arg
,
242 &gcfCompareAnalysis
);
245 syncState
->analysisModule
= (AnalysisModule
*) result
->data
;
249 g_error("Analysis module '%s' not found", optionSyncAnalysis
.arg
);
252 syncState
->processingModule
->initProcessing(syncState
, traceSetContext
);
253 if (!optionSyncNull
.present
)
255 syncState
->matchingModule
->initMatching(syncState
);
256 syncState
->analysisModule
->initAnalysis(syncState
);
260 lttv_process_traceset_seek_time(traceSetContext
, ltt_time_zero
);
261 lttv_process_traceset_middle(traceSetContext
, ltt_time_infinite
,
263 lttv_process_traceset_seek_time(traceSetContext
, ltt_time_zero
);
265 syncState
->processingModule
->finalizeProcessing(syncState
);
268 if (!optionSyncNull
.present
&& optionSyncGraphs
.present
)
270 writeGraphsScript(syncState
);
272 if (fclose(syncState
->graphsStream
) != 0)
274 g_error(strerror(errno
));
278 if (!optionSyncNull
.present
&& optionSyncStats
.present
)
280 printStats(syncState
);
282 printf("Resulting synchronization factors:\n");
283 for (i
= 0; i
< syncState
->traceNb
; i
++)
287 t
= traceSetContext
->traces
[i
]->t
;
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
);
297 syncState
->processingModule
->destroyProcessing(syncState
);
298 if (syncState
->matchingModule
!= NULL
)
300 syncState
->matchingModule
->destroyMatching(syncState
);
302 if (syncState
->analysisModule
!= NULL
)
304 syncState
->analysisModule
->destroyAnalysis(syncState
);
309 if (optionSyncStats
.present
)
311 gettimeofday(&endTime
, 0);
312 retval
= getrusage(RUSAGE_SELF
, &endUsage
);
314 timeDiff(&endTime
, &startTime
);
315 timeDiff(&endUsage
.ru_utime
, &startUsage
.ru_utime
);
316 timeDiff(&endUsage
.ru_stime
, &startUsage
.ru_stime
);
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
);
331 * A GFunc for g_queue_foreach()
334 * data: ModuleOption*
337 static void gfAddModuleOption(gpointer data
, gpointer user_data
)
339 ModuleOption
* option
= data
;
340 LttvOptionType conversion
[]= {
341 [NO_ARG
]= LTTV_OPT_NONE
,
342 [OPTIONAL_ARG
]= LTTV_OPT_NONE
,
343 [REQUIRED_ARG
]= LTTV_OPT_STRING
,
345 size_t fieldOffset
[]= {
346 [NO_ARG
]= offsetof(ModuleOption
, present
),
347 [REQUIRED_ARG
]= offsetof(ModuleOption
, arg
),
349 static const char* argHelpNone
= "none";
351 g_assert_cmpuint(sizeof(conversion
) / sizeof(*conversion
), ==,
353 if (option
->hasArg
== OPTIONAL_ARG
)
355 g_warning("Parameters with optional arguments not supported by the "
356 "lttv option scheme, parameter '%s' will not be available",
361 lttv_option_add(option
->longName
, '\0', option
->optionHelp
,
362 option
->argHelp
? option
->argHelp
: argHelpNone
,
363 conversion
[option
->hasArg
], (void*) option
+ fieldOffset
[option
->hasArg
],
370 * A GFunc for g_queue_foreach()
373 * data: ModuleOption*
376 static void gfRemoveModuleOption(gpointer data
, gpointer user_data
)
378 lttv_option_remove(((ModuleOption
*) data
)->longName
);
382 LTTV_MODULE("sync", "Synchronize traces", \
383 "Synchronizes a traceset based on the correspondance of network events", \
384 init
, destroy
, "option")