1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
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;
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.
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,
27 #include <sys/resource.h>
29 #include <sys/types.h>
33 #include <lttv/module.h>
34 #include <lttv/option.h>
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"
45 #include "sync_chain.h"
46 #include "sync_chain_lttv.h"
50 static void destroy();
52 static void gfAddModuleOption(gpointer data
, gpointer user_data
);
53 static void gfRemoveModuleOption(gpointer data
, gpointer user_data
);
55 static ModuleOption optionSync
= {
58 .optionHelp
= "synchronize the time between the traces",
60 static ModuleOption optionSyncStats
= {
61 .longName
= "sync-stats",
63 .optionHelp
= "print statistics about the time synchronization",
65 static ModuleOption optionSyncNull
= {
66 .longName
= "sync-null",
68 .optionHelp
= "read the events but do not perform any processing",
70 static GString
* analysisModulesNames
;
71 static ModuleOption optionSyncAnalysis
= {
72 .longName
= "sync-analysis",
73 .hasArg
= REQUIRED_ARG
,
74 .optionHelp
= "specify the algorithm to use for event analysis",
76 static ModuleOption optionSyncGraphs
= {
77 .longName
= "sync-graphs",
79 .optionHelp
= "output gnuplot graph showing synchronization points",
81 static char graphsDir
[20];
82 static ModuleOption optionSyncGraphsDir
= {
83 .longName
= "sync-graphs-dir",
84 .hasArg
= REQUIRED_ARG
,
85 .optionHelp
= "specify the directory where to store the graphs",
90 * Module init function
92 * This function is declared to be the module initialization function.
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
107 registerProcessingLTTVStandard();
108 registerProcessingLTTVNull();
110 registerMatchingTCP();
111 registerMatchingBroadcast();
112 registerMatchingDistributor();
114 registerAnalysisCHull();
115 registerAnalysisLinReg();
116 registerAnalysisEval();
118 g_assert(g_queue_get_length(&analysisModules
) > 0);
119 optionSyncAnalysis
.arg
= ((AnalysisModule
*)
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);
126 optionSyncAnalysis
.argHelp
= analysisModulesNames
->str
;
128 retval
= snprintf(graphsDir
, sizeof(graphsDir
), "graphs-%d", getpid());
129 if (retval
> sizeof(graphsDir
) - 1)
131 graphsDir
[sizeof(graphsDir
) - 1]= '\0';
133 optionSyncGraphsDir
.arg
= graphsDir
;
134 optionSyncGraphsDir
.argHelp
= graphsDir
;
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
);
143 g_queue_foreach(&moduleOptions
, &gfAddModuleOption
, NULL
);
148 * Module unload function
150 static void destroy()
152 g_debug("Sync destroy");
154 g_queue_foreach(&moduleOptions
, &gfRemoveModuleOption
, NULL
);
155 g_string_free(analysisModulesNames
, TRUE
);
157 g_queue_clear(&processingModules
);
158 g_queue_clear(&matchingModules
);
159 g_queue_clear(&analysisModules
);
160 g_queue_clear(&moduleOptions
);
165 * Calculate a traceset's drift and offset values based on network events
167 * The individual correction factors are written out to each trace.
170 * traceSetContext: traceset
173 * false if synchronization was not performed, true otherwise
175 bool syncTraceset(LttvTracesetContext
* const traceSetContext
)
177 SyncState
* syncState
;
178 struct timeval startTime
, endTime
;
179 struct rusage startUsage
, endUsage
;
184 if (!optionSync
.present
)
186 g_debug("Not synchronizing traceset because option is disabled");
190 if (optionSyncStats
.present
)
192 gettimeofday(&startTime
, 0);
193 getrusage(RUSAGE_SELF
, &startUsage
);
196 // Initialize data structures
197 syncState
= malloc(sizeof(SyncState
));
199 if (optionSyncStats
.present
)
201 syncState
->stats
= true;
205 syncState
->stats
= false;
208 if (!optionSyncNull
.present
&& optionSyncGraphs
.present
)
210 // Create the graph directory right away in case the module initialization
211 // functions have something to write in it.
212 syncState
->graphsDir
= optionSyncGraphsDir
.arg
;
213 syncState
->graphsStream
= createGraphsDir(syncState
->graphsDir
);
217 syncState
->graphsStream
= NULL
;
218 syncState
->graphsDir
= NULL
;
221 // Identify and initialize modules
222 syncState
->processingData
= NULL
;
223 if (optionSyncNull
.present
)
225 result
= g_queue_find_custom(&processingModules
, "LTTV-null",
226 &gcfCompareProcessing
);
230 result
= g_queue_find_custom(&processingModules
, "LTTV-standard",
231 &gcfCompareProcessing
);
233 g_assert(result
!= NULL
);
234 syncState
->processingModule
= (ProcessingModule
*) result
->data
;
236 syncState
->matchingData
= NULL
;
237 result
= g_queue_find_custom(&matchingModules
, "TCP", &gcfCompareMatching
);
238 g_assert(result
!= NULL
);
239 syncState
->matchingModule
= (MatchingModule
*) result
->data
;
241 syncState
->analysisData
= NULL
;
242 result
= g_queue_find_custom(&analysisModules
, optionSyncAnalysis
.arg
,
243 &gcfCompareAnalysis
);
246 syncState
->analysisModule
= (AnalysisModule
*) result
->data
;
250 g_error("Analysis module '%s' not found", optionSyncAnalysis
.arg
);
253 syncState
->processingModule
->initProcessing(syncState
, traceSetContext
);
254 if (!optionSyncNull
.present
)
256 syncState
->matchingModule
->initMatching(syncState
);
257 syncState
->analysisModule
->initAnalysis(syncState
);
261 lttv_process_traceset_seek_time(traceSetContext
, ltt_time_zero
);
262 lttv_process_traceset_middle(traceSetContext
, ltt_time_infinite
,
264 lttv_process_traceset_seek_time(traceSetContext
, ltt_time_zero
);
266 syncState
->processingModule
->finalizeProcessing(syncState
);
269 if (!optionSyncNull
.present
&& optionSyncGraphs
.present
)
271 writeGraphsScript(syncState
);
273 if (fclose(syncState
->graphsStream
) != 0)
275 g_error(strerror(errno
));
279 if (!optionSyncNull
.present
&& optionSyncStats
.present
)
281 printStats(syncState
);
283 printf("Resulting synchronization factors:\n");
284 for (i
= 0; i
< syncState
->traceNb
; i
++)
288 t
= traceSetContext
->traces
[i
]->t
;
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
);
298 syncState
->processingModule
->destroyProcessing(syncState
);
299 if (syncState
->matchingModule
!= NULL
)
301 syncState
->matchingModule
->destroyMatching(syncState
);
303 if (syncState
->analysisModule
!= NULL
)
305 syncState
->analysisModule
->destroyAnalysis(syncState
);
310 if (optionSyncStats
.present
)
312 gettimeofday(&endTime
, 0);
313 retval
= getrusage(RUSAGE_SELF
, &endUsage
);
315 timeDiff(&endTime
, &startTime
);
316 timeDiff(&endUsage
.ru_utime
, &startUsage
.ru_utime
);
317 timeDiff(&endUsage
.ru_stime
, &startUsage
.ru_stime
);
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
);
332 * A GFunc for g_queue_foreach()
335 * data: ModuleOption*
338 static void gfAddModuleOption(gpointer data
, gpointer user_data
)
340 ModuleOption
* option
= data
;
341 LttvOptionType conversion
[]= {
342 [NO_ARG
]= LTTV_OPT_NONE
,
343 [OPTIONAL_ARG
]= LTTV_OPT_NONE
,
344 [REQUIRED_ARG
]= LTTV_OPT_STRING
,
346 size_t fieldOffset
[]= {
347 [NO_ARG
]= offsetof(ModuleOption
, present
),
348 [REQUIRED_ARG
]= offsetof(ModuleOption
, arg
),
350 static const char* argHelpNone
= "none";
352 g_assert_cmpuint(sizeof(conversion
) / sizeof(*conversion
), ==,
354 if (option
->hasArg
== OPTIONAL_ARG
)
356 g_warning("Parameters with optional arguments not supported by the "
357 "lttv option scheme, parameter '%s' will not be available",
362 lttv_option_add(option
->longName
, '\0', option
->optionHelp
,
363 option
->argHelp
? option
->argHelp
: argHelpNone
,
364 conversion
[option
->hasArg
], (void*) option
+ fieldOffset
[option
->hasArg
],
371 * A GFunc for g_queue_foreach()
374 * data: ModuleOption*
377 static void gfRemoveModuleOption(gpointer data
, gpointer user_data
)
379 lttv_option_remove(((ModuleOption
*) data
)->longName
);
383 LTTV_MODULE("sync", "Synchronize traces", \
384 "Synchronizes a traceset based on the correspondance of network events", \
385 init
, destroy
, "option")