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