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,
25 #include <arpa/inet.h>
27 #include <netinet/in.h>
32 #include <sys/socket.h>
35 #include "sync_chain.h"
37 #include "event_analysis_eval.h"
40 // Functions common to all analysis modules
41 static void initAnalysisEval(SyncState
* const syncState
);
42 static void destroyAnalysisEval(SyncState
* const syncState
);
44 static void analyzeMessageEval(SyncState
* const syncState
, Message
* const
46 static void analyzeExchangeEval(SyncState
* const syncState
, Exchange
* const
48 static void analyzeBroadcastEval(SyncState
* const syncState
, Broadcast
* const
50 static GArray
* finalizeAnalysisEval(SyncState
* const syncState
);
51 static void printAnalysisStatsEval(SyncState
* const syncState
);
53 // Functions specific to this module
54 static void registerAnalysisEval() __attribute__((constructor (102)));
55 static guint
ghfRttKeyHash(gconstpointer key
);
56 static gboolean
gefRttKeyEqual(gconstpointer a
, gconstpointer b
);
57 static void gdnDestroyRttKey(gpointer data
);
58 static void gdnDestroyDouble(gpointer data
);
59 static void readRttInfo(GHashTable
* rttInfo
, FILE* rttFile
);
60 static void positionStream(FILE* stream
);
63 static AnalysisModule analysisModuleEval
= {
65 .initAnalysis
= &initAnalysisEval
,
66 .destroyAnalysis
= &destroyAnalysisEval
,
67 .analyzeMessage
= &analyzeMessageEval
,
68 .analyzeExchange
= &analyzeExchangeEval
,
69 .analyzeBroadcast
= &analyzeBroadcastEval
,
70 .finalizeAnalysis
= &finalizeAnalysisEval
,
71 .printAnalysisStats
= &printAnalysisStatsEval
,
72 .writeAnalysisGraphsPlots
= NULL
,
73 .writeAnalysisGraphsOptions
= NULL
,
76 static ModuleOption optionEvalRttFile
= {
77 .longName
= "eval-rtt-file",
78 .hasArg
= REQUIRED_ARG
,
80 .optionHelp
= "specify the file containing rtt information",
86 * Analysis module registering function
88 static void registerAnalysisEval()
90 g_queue_push_tail(&analysisModules
, &analysisModuleEval
);
91 g_queue_push_tail(&moduleOptions
, &optionEvalRttFile
);
96 * Analysis init function
98 * This function is called at the beginning of a synchronization run for a set
102 * syncState container for synchronization data.
104 static void initAnalysisEval(SyncState
* const syncState
)
106 AnalysisDataEval
* analysisData
;
109 analysisData
= malloc(sizeof(AnalysisDataEval
));
110 syncState
->analysisData
= analysisData
;
112 analysisData
->rttInfo
= g_hash_table_new_full(&ghfRttKeyHash
,
113 &gefRttKeyEqual
, &gdnDestroyRttKey
, &gdnDestroyDouble
);
114 if (optionEvalRttFile
.arg
)
119 rttStream
= fopen(optionEvalRttFile
.arg
, "r");
120 if (rttStream
== NULL
)
122 g_error(strerror(errno
));
125 readRttInfo(analysisData
->rttInfo
, rttStream
);
127 retval
= fclose(rttStream
);
130 g_error(strerror(errno
));
134 if (syncState
->stats
)
136 analysisData
->stats
= malloc(sizeof(AnalysisStatsEval
));
137 analysisData
->stats
->broadcastDiffSum
= 0.;
139 analysisData
->stats
->allStats
= malloc(syncState
->traceNb
*
140 sizeof(TracePairStats
*));
141 for (i
= 0; i
< syncState
->traceNb
; i
++)
143 analysisData
->stats
->allStats
[i
]= calloc(syncState
->traceNb
,
144 sizeof(TracePairStats
));
151 * Analysis destroy function
153 * Free the analysis specific data structures
156 * syncState container for synchronization data.
158 static void destroyAnalysisEval(SyncState
* const syncState
)
161 AnalysisDataEval
* analysisData
;
163 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
165 if (analysisData
== NULL
|| analysisData
->rttInfo
== NULL
)
170 g_hash_table_destroy(analysisData
->rttInfo
);
171 analysisData
->rttInfo
= NULL
;
173 if (syncState
->stats
)
175 for (i
= 0; i
< syncState
->traceNb
; i
++)
177 free(analysisData
->stats
->allStats
[i
]);
179 free(analysisData
->stats
->allStats
);
180 free(analysisData
->stats
);
183 free(syncState
->analysisData
);
184 syncState
->analysisData
= NULL
;
189 * Perform analysis on an event pair.
192 * syncState container for synchronization data
193 * message structure containing the events
195 static void analyzeMessageEval(SyncState
* const syncState
, Message
* const message
)
197 AnalysisDataEval
* analysisData
;
199 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
204 * Perform analysis on multiple messages
207 * syncState container for synchronization data
208 * exchange structure containing the messages
210 static void analyzeExchangeEval(SyncState
* const syncState
, Exchange
* const exchange
)
212 AnalysisDataEval
* analysisData
;
214 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
219 * Perform analysis on muliple events
222 * syncState container for synchronization data
223 * broadcast structure containing the events
225 static void analyzeBroadcastEval(SyncState
* const syncState
, Broadcast
* const broadcast
)
227 AnalysisDataEval
* analysisData
;
229 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
234 * Finalize the factor calculations
236 * Since this module does not really calculate factors, identity factors are
240 * syncState container for synchronization data.
243 * Factors[traceNb] synchronization factors for each trace
245 static GArray
* finalizeAnalysisEval(SyncState
* const syncState
)
250 factors
= g_array_sized_new(FALSE
, FALSE
, sizeof(Factors
),
252 g_array_set_size(factors
, syncState
->traceNb
);
253 for (i
= 0; i
< syncState
->traceNb
; i
++)
257 e
= &g_array_index(factors
, Factors
, i
);
267 * Print statistics related to analysis. Must be called after
271 * syncState container for synchronization data.
273 static void printAnalysisStatsEval(SyncState
* const syncState
)
275 AnalysisDataEval
* analysisData
;
278 if (!syncState
->stats
)
283 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
285 printf("Synchronization evaluation analysis stats:\n");
286 printf("\tsum of broadcast differential delays: %g\n",
287 analysisData
->stats
->broadcastDiffSum
);
289 printf("\tIndividual evaluation:\n"
290 "\t\tTrace pair Inversions Too fast (No RTT info)\n");
292 for (i
= 0; i
< syncState
->traceNb
; i
++)
294 for (j
= i
+ 1; j
< syncState
->traceNb
; j
++)
296 TracePairStats
* tpStats
;
297 const char* format
= "\t\t%3d - %-3d %-10u %-10u %u\n";
299 tpStats
= &analysisData
->stats
->allStats
[i
][j
];
301 printf(format
, i
, j
, tpStats
->inversionNb
, tpStats
->tooFastNb
,
302 tpStats
->noRTTInfoNb
);
304 tpStats
= &analysisData
->stats
->allStats
[j
][i
];
306 printf(format
, j
, i
, tpStats
->inversionNb
, tpStats
->tooFastNb
,
307 tpStats
->noRTTInfoNb
);
314 * A GHashFunc for g_hash_table_new()
319 static guint
ghfRttKeyHash(gconstpointer key
)
321 struct RttKey
* rttKey
;
324 rttKey
= (struct RttKey
*) key
;
336 * A GDestroyNotify function for g_hash_table_new_full()
339 * data: struct RttKey*
341 static void gdnDestroyRttKey(gpointer data
)
348 * A GDestroyNotify function for g_hash_table_new_full()
353 static void gdnDestroyDouble(gpointer data
)
360 * A GEqualFunc for g_hash_table_new()
366 * TRUE if both values are equal
368 static gboolean
gefRttKeyEqual(gconstpointer a
, gconstpointer b
)
370 const struct RttKey
* rkA
, * rkB
;
372 rkA
= (struct RttKey
*) a
;
373 rkB
= (struct RttKey
*) b
;
375 if (rkA
->saddr
== rkB
->saddr
&& rkA
->daddr
== rkB
->daddr
)
387 * Read a file contain minimum round trip time values and fill an array with
388 * them. The file is formatted as such:
389 * <host1 IP> <host2 IP> <RTT in milliseconds>
390 * ip's should be in dotted quad format
393 * rttInfo: double* rttInfo[RttKey], empty table, will be filled
394 * rttStream: stream from which to read
396 static void readRttInfo(GHashTable
* rttInfo
, FILE* rttStream
)
402 positionStream(rttStream
);
403 retval
= getline(&line
, &len
, rttStream
);
404 while(!feof(rttStream
))
406 struct RttKey
* rttKey
;
407 char saddrDQ
[20], daddrDQ
[20];
416 {saddrDQ
, offsetof(struct RttKey
, saddr
)},
417 {daddrDQ
, offsetof(struct RttKey
, daddr
)}
420 if (retval
== -1 && !feof(rttStream
))
422 g_error(strerror(errno
));
425 if (line
[retval
- 1] == '\n')
427 line
[retval
- 1]= '\0';
430 rtt
= malloc(sizeof(double));
431 retval
= sscanf(line
, " %19s %19s %lf %c", saddrDQ
, daddrDQ
, rtt
,
435 g_error(strerror(errno
));
437 else if (retval
!= 3)
439 g_error("Error parsing RTT file, line was '%s'", line
);
442 rttKey
= malloc(sizeof(struct RttKey
));
443 for (i
= 0; i
< sizeof(loopValues
) / sizeof(*loopValues
); i
++)
445 retval
= inet_aton(loopValues
[i
].dq
, &addr
);
448 g_error("Error converting address '%s'", loopValues
[i
].dq
);
450 *(uint32_t*) ((void*) rttKey
+ loopValues
[i
].offset
)=
454 g_hash_table_insert(rttInfo
, rttKey
, rtt
);
456 positionStream(rttStream
);
457 retval
= getline(&line
, &len
, rttStream
);
468 * Advance stream over empty space, empty lines and lines that begin with '#'
471 * stream: stream, at exit, will be over the first non-empty character
472 * of a line of be at EOF
474 static void positionStream(FILE* stream
)
483 firstChar
= fgetc(stream
);
484 if (firstChar
== (int) '#')
486 retval
= getline(&line
, &len
, stream
);
495 g_error(strerror(errno
));
499 else if (firstChar
== (int) '\n' || firstChar
== (int) ' ' ||
500 firstChar
== (int) '\t')
502 else if (firstChar
== EOF
)
511 retval
= ungetc(firstChar
, stream
);
514 g_error("Error: ungetc()");