Calculate synchronization accuracy within the chull module
[lttv.git] / lttv / lttv / sync / event_analysis_eval.c
CommitLineData
cdce23b3 1/* This file is part of the Linux Trace Toolkit viewer
277e5b53 2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
cdce23b3 3 *
277e5b53
BP
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.
cdce23b3 8 *
277e5b53
BP
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.
cdce23b3 13 *
277e5b53
BP
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/>.
cdce23b3
BP
16 */
17
2bd4b3e4 18#define _GNU_SOURCE
d4721e1a 19#define _ISOC99_SOURCE
2bd4b3e4 20
cdce23b3
BP
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
2bd4b3e4
BP
25#include <arpa/inet.h>
26#include <errno.h>
76be6fc2 27#include <math.h>
2bd4b3e4
BP
28#include <netinet/in.h>
29#include <stddef.h>
cdce23b3 30#include <stdlib.h>
2bd4b3e4
BP
31#include <stdio.h>
32#include <string.h>
33#include <sys/socket.h>
4ee223e5 34#include <unistd.h>
cdce23b3 35
2bd4b3e4
BP
36#include "lookup3.h"
37#include "sync_chain.h"
cdce23b3
BP
38
39#include "event_analysis_eval.h"
40
41
66eaf2eb 42struct WriteHistogramInfo
e072e1ab
BP
43{
44 GHashTable* rttInfo;
45 FILE* graphsStream;
46};
47
cdce23b3
BP
48// Functions common to all analysis modules
49static void initAnalysisEval(SyncState* const syncState);
50static void destroyAnalysisEval(SyncState* const syncState);
51
52static void analyzeMessageEval(SyncState* const syncState, Message* const
53 message);
54static void analyzeExchangeEval(SyncState* const syncState, Exchange* const
55 exchange);
56static void analyzeBroadcastEval(SyncState* const syncState, Broadcast* const
57 broadcast);
0a87ec9a 58static AllFactors* finalizeAnalysisEval(SyncState* const syncState);
cdce23b3
BP
59static void printAnalysisStatsEval(SyncState* const syncState);
60
61// Functions specific to this module
2bd4b3e4
BP
62static guint ghfRttKeyHash(gconstpointer key);
63static gboolean gefRttKeyEqual(gconstpointer a, gconstpointer b);
64static void gdnDestroyRttKey(gpointer data);
65static void gdnDestroyDouble(gpointer data);
66static void readRttInfo(GHashTable* rttInfo, FILE* rttFile);
67static void positionStream(FILE* stream);
cdce23b3 68
76be6fc2
BP
69static void gfSum(gpointer data, gpointer userData);
70static void gfSumSquares(gpointer data, gpointer userData);
66eaf2eb
BP
71static void ghfPrintExchangeRtt(gpointer key, gpointer value, gpointer
72 user_data);
76be6fc2 73
e072e1ab 74static void hitBin(struct Bins* const bins, const double value);
4ee223e5
BP
75static unsigned int binNum(const double value) __attribute__((pure));
76static double binStart(const unsigned int binNum) __attribute__((pure));
77static double binEnd(const unsigned int binNum) __attribute__((pure));
467066ee 78static uint32_t normalTotal(struct Bins* const bins) __attribute__((const));
4ee223e5 79
66eaf2eb 80static AnalysisHistogramEval* constructAnalysisHistogramEval(const char* const
e072e1ab 81 graphsDir, const struct RttKey* const rttKey);
66eaf2eb
BP
82static void destroyAnalysisHistogramEval(AnalysisHistogramEval* const
83 histogram);
84static void gdnDestroyAnalysisHistogramEval(gpointer data);
85static void ghfWriteHistogram(gpointer key, gpointer value, gpointer
86 user_data);
e072e1ab
BP
87static void dumpBinToFile(const struct Bins* const bins, FILE* const file);
88static void writeHistogram(FILE* graphsStream, const struct RttKey* rttKey,
66eaf2eb
BP
89 double* minRtt, AnalysisHistogramEval* const histogram);
90
c6356aa7
BP
91static void updateBounds(Bounds** const bounds, Event* const e1, Event* const
92 e2);
66eaf2eb 93
4ee223e5 94
66eaf2eb 95// initialized in registerAnalysisEval()
4ee223e5 96double binBase;
cdce23b3
BP
97
98static AnalysisModule analysisModuleEval= {
99 .name= "eval",
100 .initAnalysis= &initAnalysisEval,
101 .destroyAnalysis= &destroyAnalysisEval,
102 .analyzeMessage= &analyzeMessageEval,
103 .analyzeExchange= &analyzeExchangeEval,
104 .analyzeBroadcast= &analyzeBroadcastEval,
105 .finalizeAnalysis= &finalizeAnalysisEval,
106 .printAnalysisStats= &printAnalysisStatsEval,
ab6edc6a 107 .graphFunctions= {}
cdce23b3
BP
108};
109
2bd4b3e4
BP
110static ModuleOption optionEvalRttFile= {
111 .longName= "eval-rtt-file",
112 .hasArg= REQUIRED_ARG,
4ee223e5 113 .optionHelp= "specify the file containing RTT information",
2bd4b3e4
BP
114 .argHelp= "FILE",
115};
116
cdce23b3
BP
117
118/*
119 * Analysis module registering function
120 */
2f961b65 121void registerAnalysisEval()
cdce23b3 122{
66eaf2eb
BP
123 binBase= exp10(6. / (BIN_NB - 3));
124
cdce23b3 125 g_queue_push_tail(&analysisModules, &analysisModuleEval);
2bd4b3e4 126 g_queue_push_tail(&moduleOptions, &optionEvalRttFile);
cdce23b3
BP
127}
128
129
130/*
131 * Analysis init function
132 *
133 * This function is called at the beginning of a synchronization run for a set
134 * of traces.
135 *
136 * Args:
137 * syncState container for synchronization data.
138 */
139static void initAnalysisEval(SyncState* const syncState)
140{
141 AnalysisDataEval* analysisData;
66eaf2eb 142 unsigned int i, j;
cdce23b3
BP
143
144 analysisData= malloc(sizeof(AnalysisDataEval));
145 syncState->analysisData= analysisData;
146
2bd4b3e4
BP
147 analysisData->rttInfo= g_hash_table_new_full(&ghfRttKeyHash,
148 &gefRttKeyEqual, &gdnDestroyRttKey, &gdnDestroyDouble);
149 if (optionEvalRttFile.arg)
150 {
151 FILE* rttStream;
152 int retval;
153
154 rttStream= fopen(optionEvalRttFile.arg, "r");
155 if (rttStream == NULL)
156 {
157 g_error(strerror(errno));
158 }
159
160 readRttInfo(analysisData->rttInfo, rttStream);
161
162 retval= fclose(rttStream);
163 if (retval == EOF)
164 {
165 g_error(strerror(errno));
166 }
167 }
cdce23b3
BP
168
169 if (syncState->stats)
170 {
76be6fc2 171 analysisData->stats= calloc(1, sizeof(AnalysisStatsEval));
2849af52
BP
172 analysisData->stats->broadcastRangeMin= INFINITY;
173 analysisData->stats->broadcastRangeMax= -INFINITY;
cdce23b3 174
76be6fc2
BP
175 analysisData->stats->messageStats= malloc(syncState->traceNb *
176 sizeof(MessageStats*));
cdce23b3
BP
177 for (i= 0; i < syncState->traceNb; i++)
178 {
76be6fc2
BP
179 analysisData->stats->messageStats[i]= calloc(syncState->traceNb,
180 sizeof(MessageStats));
cdce23b3 181 }
d4721e1a
BP
182
183 analysisData->stats->exchangeRtt=
184 g_hash_table_new_full(&ghfRttKeyHash, &gefRttKeyEqual,
185 &gdnDestroyRttKey, &gdnDestroyDouble);
cdce23b3 186 }
4ee223e5 187
8d7d16dd 188 if (syncState->graphsStream)
4ee223e5 189 {
66eaf2eb
BP
190 AnalysisGraphsEval* graphs= malloc(sizeof(AnalysisGraphsEval));
191
192 analysisData->graphs= graphs;
193
194 graphs->histograms= g_hash_table_new_full(&ghfRttKeyHash,
195 &gefRttKeyEqual, &gdnDestroyRttKey,
196 &gdnDestroyAnalysisHistogramEval);
197
198 graphs->bounds= malloc(syncState->traceNb * sizeof(Bounds*));
199 for (i= 0; i < syncState->traceNb; i++)
200 {
201 graphs->bounds[i]= malloc(i * sizeof(Bounds));
202 for (j= 0; j < i; j++)
203 {
204 graphs->bounds[i][j].min= UINT64_MAX;
205 graphs->bounds[i][j].max= 0;
206 }
207 }
4ee223e5
BP
208 }
209}
210
211
212/*
e072e1ab
BP
213 * Create and open files used to store histogram points to generate graphs.
214 * Create data structures to store histogram points during analysis.
4ee223e5
BP
215 *
216 * Args:
e072e1ab
BP
217 * graphsDir: folder where to write files
218 * rttKey: host pair, make sure saddr < daddr
4ee223e5 219 */
66eaf2eb 220static AnalysisHistogramEval* constructAnalysisHistogramEval(const char* const
e072e1ab 221 graphsDir, const struct RttKey* const rttKey)
4ee223e5 222{
4ee223e5 223 int retval;
e072e1ab 224 unsigned int i;
4ee223e5 225 char* cwd;
e072e1ab 226 char name[60], saddr[16], daddr[16];
66eaf2eb 227 AnalysisHistogramEval* histogram= calloc(1, sizeof(*histogram));
e072e1ab
BP
228 const struct {
229 size_t pointsOffset;
230 const char* fileName;
231 const char* host1, *host2;
232 } loopValues[]= {
66eaf2eb
BP
233 {offsetof(AnalysisHistogramEval, ttSendPoints),
234 "analysis_eval_tt-%s_to_%s.data", saddr, daddr},
235 {offsetof(AnalysisHistogramEval, ttRecvPoints),
236 "analysis_eval_tt-%s_to_%s.data", daddr, saddr},
237 {offsetof(AnalysisHistogramEval, hrttPoints),
238 "analysis_eval_hrtt-%s_and_%s.data", saddr, daddr},
e072e1ab
BP
239 };
240
66eaf2eb
BP
241 histogram->ttSendBins.min= BIN_NB - 1;
242 histogram->ttRecvBins.min= BIN_NB - 1;
243 histogram->hrttBins.min= BIN_NB - 1;
e072e1ab
BP
244
245 convertIP(saddr, rttKey->saddr);
246 convertIP(daddr, rttKey->daddr);
247
1d597550 248 cwd= changeToGraphsDir(graphsDir);
e072e1ab
BP
249
250 for (i= 0; i < sizeof(loopValues) / sizeof(*loopValues); i++)
4ee223e5 251 {
e072e1ab
BP
252 retval= snprintf(name, sizeof(name), loopValues[i].fileName,
253 loopValues[i].host1, loopValues[i].host2);
254 if (retval > sizeof(name) - 1)
4ee223e5 255 {
e072e1ab 256 name[sizeof(name) - 1]= '\0';
4ee223e5 257 }
66eaf2eb 258 if ((*(FILE**)((void*) histogram + loopValues[i].pointsOffset)=
e072e1ab 259 fopen(name, "w")) == NULL)
4ee223e5 260 {
e072e1ab 261 g_error(strerror(errno));
4ee223e5
BP
262 }
263 }
264
265 retval= chdir(cwd);
266 if (retval == -1)
267 {
268 g_error(strerror(errno));
269 }
270 free(cwd);
e072e1ab 271
66eaf2eb 272 return histogram;
4ee223e5
BP
273}
274
275
276/*
e072e1ab 277 * Close files used to store histogram points to generate graphs.
4ee223e5
BP
278 *
279 * Args:
e072e1ab
BP
280 * graphsDir: folder where to write files
281 * rttKey: host pair, make sure saddr < daddr
4ee223e5 282 */
66eaf2eb
BP
283static void destroyAnalysisHistogramEval(AnalysisHistogramEval* const
284 histogram)
4ee223e5 285{
e072e1ab
BP
286 unsigned int i;
287 int retval;
288 const struct {
289 size_t pointsOffset;
290 } loopValues[]= {
66eaf2eb
BP
291 {offsetof(AnalysisHistogramEval, ttSendPoints)},
292 {offsetof(AnalysisHistogramEval, ttRecvPoints)},
293 {offsetof(AnalysisHistogramEval, hrttPoints)},
e072e1ab
BP
294 };
295
296 for (i= 0; i < sizeof(loopValues) / sizeof(*loopValues); i++)
4ee223e5 297 {
66eaf2eb 298 retval= fclose(*(FILE**)((void*) histogram + loopValues[i].pointsOffset));
e072e1ab 299 if (retval != 0)
4ee223e5 300 {
e072e1ab 301 g_error(strerror(errno));
4ee223e5
BP
302 }
303 }
66eaf2eb
BP
304
305 free(histogram);
4ee223e5
BP
306}
307
308
e072e1ab
BP
309/*
310 * A GDestroyNotify function for g_hash_table_new_full()
311 *
312 * Args:
66eaf2eb 313 * data: AnalysisHistogramEval*
e072e1ab 314 */
66eaf2eb 315static void gdnDestroyAnalysisHistogramEval(gpointer data)
e072e1ab 316{
66eaf2eb 317 destroyAnalysisHistogramEval(data);
e072e1ab
BP
318}
319
320
321/*
322 * A GHFunc for g_hash_table_foreach()
323 *
324 * Args:
325 * key: RttKey* where saddr < daddr
66eaf2eb
BP
326 * value: AnalysisHistogramEval*
327 * user_data struct WriteHistogramInfo*
e072e1ab 328 */
66eaf2eb 329static void ghfWriteHistogram(gpointer key, gpointer value, gpointer user_data)
e072e1ab
BP
330{
331 double* rtt1, * rtt2;
332 struct RttKey* rttKey= key;
333 struct RttKey oppositeRttKey= {.saddr= rttKey->daddr, .daddr=
334 rttKey->saddr};
66eaf2eb
BP
335 AnalysisHistogramEval* histogram= value;
336 struct WriteHistogramInfo* info= user_data;
e072e1ab
BP
337
338 rtt1= g_hash_table_lookup(info->rttInfo, rttKey);
339 rtt2= g_hash_table_lookup(info->rttInfo, &oppositeRttKey);
340
341 if (rtt1 == NULL)
342 {
343 rtt1= rtt2;
344 }
345 else if (rtt2 != NULL)
346 {
347 rtt1= MIN(rtt1, rtt2);
348 }
349
66eaf2eb
BP
350 dumpBinToFile(&histogram->ttSendBins, histogram->ttSendPoints);
351 dumpBinToFile(&histogram->ttRecvBins, histogram->ttRecvPoints);
352 dumpBinToFile(&histogram->hrttBins, histogram->hrttPoints);
353 writeHistogram(info->graphsStream, rttKey, rtt1, histogram);
e072e1ab
BP
354}
355
356
4ee223e5
BP
357/*
358 * Write the content of one bin in a histogram point file
359 *
360 * Args:
361 * bin: array of values that make up a histogram
e072e1ab 362 * file: FILE*, write to this file
4ee223e5 363 */
e072e1ab 364static void dumpBinToFile(const struct Bins* const bins, FILE* const file)
4ee223e5
BP
365{
366 unsigned int i;
367
e072e1ab
BP
368 // The first and last bins are skipped, see struct Bins
369 for (i= 1; i < BIN_NB - 1; i++)
4ee223e5 370 {
e072e1ab 371 if (bins->bin[i] > 0)
4ee223e5 372 {
e072e1ab
BP
373 fprintf(file, "%20.9f %20.9f %20.9f\n", (binStart(i) + binEnd(i))
374 / 2., (double) bins->bin[i] / ((binEnd(i) - binStart(i)) *
375 bins->total), binEnd(i) - binStart(i));
4ee223e5
BP
376 }
377 }
378}
379
380
381/*
e072e1ab 382 * Write the analysis-specific plot in the gnuplot script.
4ee223e5
BP
383 *
384 * Args:
e072e1ab
BP
385 * graphsStream: write to this file
386 * rttKey: must be sorted such that saddr < daddr
387 * minRtt: if available, else NULL
66eaf2eb 388 * histogram: struct that contains the bins for the pair of traces
467066ee 389 * identified by rttKey
4ee223e5 390 */
e072e1ab 391static void writeHistogram(FILE* graphsStream, const struct RttKey* rttKey,
66eaf2eb 392 double* minRtt, AnalysisHistogramEval* const histogram)
4ee223e5 393{
e072e1ab 394 char saddr[16], daddr[16];
4ee223e5 395
e072e1ab
BP
396 convertIP(saddr, rttKey->saddr);
397 convertIP(daddr, rttKey->daddr);
4ee223e5 398
e072e1ab 399 fprintf(graphsStream,
66eaf2eb 400 "\nreset\n"
e072e1ab
BP
401 "set output \"histogram-%s-%s.eps\"\n"
402 "set title \"\"\n"
403 "set xlabel \"Message Latency (s)\"\n"
404 "set ylabel \"Proportion of messages per second\"\n", saddr, daddr);
4ee223e5 405
e072e1ab 406 if (minRtt != NULL)
4ee223e5 407 {
e072e1ab
BP
408 fprintf(graphsStream,
409 "set arrow from %.9f, 0 rto 0, graph 1 "
467066ee
BP
410 "nohead linetype 3 linewidth 3 linecolor rgb \"black\"\n", *minRtt
411 / 2);
4ee223e5 412 }
4ee223e5 413
66eaf2eb
BP
414 if (normalTotal(&histogram->ttSendBins) ||
415 normalTotal(&histogram->ttRecvBins) ||
416 normalTotal(&histogram->hrttBins))
467066ee
BP
417 {
418 fprintf(graphsStream, "plot \\\n");
419
66eaf2eb 420 if (normalTotal(&histogram->hrttBins))
467066ee
BP
421 {
422 fprintf(graphsStream,
423 "\t\"analysis_eval_hrtt-%s_and_%s.data\" "
424 "title \"RTT/2\" with linespoints linetype 1 linewidth 2 "
425 "linecolor rgb \"black\" pointtype 6 pointsize 1,\\\n",
426 saddr, daddr);
427 }
428
66eaf2eb 429 if (normalTotal(&histogram->ttSendBins))
467066ee
BP
430 {
431 fprintf(graphsStream,
432 "\t\"analysis_eval_tt-%1$s_to_%2$s.data\" "
433 "title \"%1$s to %2$s\" with linespoints linetype 4 linewidth 2 "
434 "linecolor rgb \"gray60\" pointtype 6 pointsize 1,\\\n",
435 saddr, daddr);
436 }
437
66eaf2eb 438 if (normalTotal(&histogram->ttRecvBins))
467066ee
BP
439 {
440 fprintf(graphsStream,
441 "\t\"analysis_eval_tt-%1$s_to_%2$s.data\" "
442 "title \"%1$s to %2$s\" with linespoints linetype 4 linewidth 2 "
443 "linecolor rgb \"gray30\" pointtype 6 pointsize 1,\\\n",
444 daddr, saddr);
445 }
446
447 // Remove the ",\\\n" from the last graph plot line
448 if (ftruncate(fileno(graphsStream), ftell(graphsStream) - 3) == -1)
449 {
450 g_error(strerror(errno));
451 }
452 if (fseek(graphsStream, 0, SEEK_END) == -1)
453 {
454 g_error(strerror(errno));
455 }
456 fprintf(graphsStream, "\n");
457 }
cdce23b3
BP
458}
459
460
461/*
462 * Analysis destroy function
463 *
464 * Free the analysis specific data structures
465 *
466 * Args:
467 * syncState container for synchronization data.
468 */
469static void destroyAnalysisEval(SyncState* const syncState)
470{
05a840df 471 unsigned int i;
cdce23b3
BP
472 AnalysisDataEval* analysisData;
473
474 analysisData= (AnalysisDataEval*) syncState->analysisData;
475
66eaf2eb 476 if (analysisData == NULL)
cdce23b3
BP
477 {
478 return;
479 }
480
2bd4b3e4 481 g_hash_table_destroy(analysisData->rttInfo);
cdce23b3
BP
482
483 if (syncState->stats)
484 {
66eaf2eb
BP
485 AnalysisStatsEval* stats= analysisData->stats;
486
487 for (i= 0; i < syncState->traceNb; i++)
488 {
489 free(stats->messageStats[i]);
490 }
491 free(stats->messageStats);
492
493 g_hash_table_destroy(stats->exchangeRtt);
494
66eaf2eb
BP
495 free(stats);
496 }
497
498 if (syncState->graphsStream)
499 {
500 AnalysisGraphsEval* graphs= analysisData->graphs;
501
502 if (graphs->histograms)
503 {
504 g_hash_table_destroy(graphs->histograms);
505 }
506
cdce23b3
BP
507 for (i= 0; i < syncState->traceNb; i++)
508 {
66eaf2eb
BP
509 free(graphs->bounds[i]);
510 }
511 free(graphs->bounds);
512
66eaf2eb 513 free(graphs);
cdce23b3
BP
514 }
515
516 free(syncState->analysisData);
517 syncState->analysisData= NULL;
518}
519
520
521/*
522 * Perform analysis on an event pair.
523 *
76be6fc2
BP
524 * Check if there is message inversion or messages that are too fast.
525 *
cdce23b3
BP
526 * Args:
527 * syncState container for synchronization data
528 * message structure containing the events
529 */
66eaf2eb
BP
530static void analyzeMessageEval(SyncState* const syncState, Message* const
531 message)
cdce23b3 532{
e072e1ab 533 AnalysisDataEval* analysisData= syncState->analysisData;
7e39acc6 534 MessageStats* messageStats;
d4721e1a 535 double* rtt;
76be6fc2
BP
536 double tt;
537 struct RttKey rttKey;
538
e072e1ab 539 g_assert(message->inE->type == TCP);
76be6fc2 540
66eaf2eb
BP
541 if (syncState->stats)
542 {
7e39acc6
BP
543 messageStats=
544 &analysisData->stats->messageStats[message->outE->traceNum][message->inE->traceNum];
66eaf2eb
BP
545 messageStats->total++;
546 }
76be6fc2
BP
547
548 tt= wallTimeSub(&message->inE->wallTime, &message->outE->wallTime);
549 if (tt <= 0)
550 {
66eaf2eb
BP
551 if (syncState->stats)
552 {
553 messageStats->inversionNb++;
554 }
76be6fc2 555 }
8d7d16dd 556 else if (syncState->graphsStream)
4ee223e5 557 {
e072e1ab
BP
558 struct RttKey rttKey= {
559 .saddr=MIN(message->inE->event.tcpEvent->segmentKey->connectionKey.saddr,
560 message->inE->event.tcpEvent->segmentKey->connectionKey.daddr),
561 .daddr=MAX(message->inE->event.tcpEvent->segmentKey->connectionKey.saddr,
562 message->inE->event.tcpEvent->segmentKey->connectionKey.daddr),
563 };
66eaf2eb
BP
564 AnalysisHistogramEval* histogram=
565 g_hash_table_lookup(analysisData->graphs->histograms, &rttKey);
e072e1ab 566
66eaf2eb 567 if (histogram == NULL)
e072e1ab
BP
568 {
569 struct RttKey* tableKey= malloc(sizeof(*tableKey));
570
66eaf2eb 571 histogram= constructAnalysisHistogramEval(syncState->graphsDir, &rttKey);
e072e1ab 572 memcpy(tableKey, &rttKey, sizeof(*tableKey));
66eaf2eb 573 g_hash_table_insert(analysisData->graphs->histograms, tableKey, histogram);
e072e1ab
BP
574 }
575
576 if (message->inE->event.udpEvent->datagramKey->saddr <
577 message->inE->event.udpEvent->datagramKey->daddr)
578 {
66eaf2eb 579 hitBin(&histogram->ttSendBins, tt);
e072e1ab
BP
580 }
581 else
582 {
66eaf2eb 583 hitBin(&histogram->ttRecvBins, tt);
e072e1ab 584 }
4ee223e5 585 }
76be6fc2 586
66eaf2eb 587 if (syncState->stats)
76be6fc2 588 {
66eaf2eb
BP
589 rttKey.saddr=
590 message->inE->event.tcpEvent->segmentKey->connectionKey.saddr;
591 rttKey.daddr=
592 message->inE->event.tcpEvent->segmentKey->connectionKey.daddr;
593 rtt= g_hash_table_lookup(analysisData->rttInfo, &rttKey);
594 g_debug("rttInfo, looking up (%u, %u)->(%f)", rttKey.saddr,
595 rttKey.daddr, rtt ? *rtt : NAN);
596
597 if (rtt)
76be6fc2 598 {
66eaf2eb
BP
599 g_debug("rttInfo, tt: %f rtt / 2: %f", tt, *rtt / 2.);
600 if (tt < *rtt / 2.)
601 {
602 messageStats->tooFastNb++;
603 }
604 }
605 else
606 {
607 messageStats->noRTTInfoNb++;
76be6fc2
BP
608 }
609 }
66eaf2eb
BP
610
611 if (syncState->graphsStream)
612 {
613 updateBounds(analysisData->graphs->bounds, message->inE,
614 message->outE);
615 }
cdce23b3
BP
616}
617
618
619/*
620 * Perform analysis on multiple messages
621 *
76be6fc2
BP
622 * Measure the RTT
623 *
cdce23b3
BP
624 * Args:
625 * syncState container for synchronization data
626 * exchange structure containing the messages
627 */
66eaf2eb
BP
628static void analyzeExchangeEval(SyncState* const syncState, Exchange* const
629 exchange)
cdce23b3 630{
d4721e1a
BP
631 AnalysisDataEval* analysisData= syncState->analysisData;
632 Message* m1= g_queue_peek_tail(exchange->acks);
633 Message* m2= exchange->message;
634 struct RttKey* rttKey;
635 double* rtt, * exchangeRtt;
cdce23b3 636
e072e1ab
BP
637 g_assert(m1->inE->type == TCP);
638
d4721e1a
BP
639 // (T2 - T1) - (T3 - T4)
640 rtt= malloc(sizeof(double));
641 *rtt= wallTimeSub(&m1->inE->wallTime, &m1->outE->wallTime) -
642 wallTimeSub(&m2->outE->wallTime, &m2->inE->wallTime);
643
d4721e1a
BP
644 rttKey= malloc(sizeof(struct RttKey));
645 rttKey->saddr=
646 MIN(m1->inE->event.tcpEvent->segmentKey->connectionKey.saddr,
647 m1->inE->event.tcpEvent->segmentKey->connectionKey.daddr);
648 rttKey->daddr=
649 MAX(m1->inE->event.tcpEvent->segmentKey->connectionKey.saddr,
650 m1->inE->event.tcpEvent->segmentKey->connectionKey.daddr);
e072e1ab
BP
651
652 if (syncState->graphsStream)
653 {
66eaf2eb
BP
654 AnalysisHistogramEval* histogram=
655 g_hash_table_lookup(analysisData->graphs->histograms, rttKey);
e072e1ab 656
66eaf2eb 657 if (histogram == NULL)
e072e1ab
BP
658 {
659 struct RttKey* tableKey= malloc(sizeof(*tableKey));
660
66eaf2eb
BP
661 histogram= constructAnalysisHistogramEval(syncState->graphsDir,
662 rttKey);
e072e1ab 663 memcpy(tableKey, rttKey, sizeof(*tableKey));
66eaf2eb
BP
664 g_hash_table_insert(analysisData->graphs->histograms, tableKey,
665 histogram);
e072e1ab
BP
666 }
667
66eaf2eb 668 hitBin(&histogram->hrttBins, *rtt / 2);
e072e1ab
BP
669 }
670
66eaf2eb 671 if (syncState->stats)
d4721e1a 672 {
66eaf2eb
BP
673 exchangeRtt= g_hash_table_lookup(analysisData->stats->exchangeRtt,
674 rttKey);
675
676 if (exchangeRtt)
d4721e1a 677 {
66eaf2eb
BP
678 if (*rtt < *exchangeRtt)
679 {
680 g_hash_table_replace(analysisData->stats->exchangeRtt, rttKey, rtt);
681 }
682 else
683 {
684 free(rttKey);
685 free(rtt);
686 }
687 }
688 else
689 {
690 g_hash_table_insert(analysisData->stats->exchangeRtt, rttKey, rtt);
d4721e1a
BP
691 }
692 }
693 else
694 {
66eaf2eb
BP
695 free(rttKey);
696 free(rtt);
d4721e1a 697 }
cdce23b3
BP
698}
699
700
701/*
702 * Perform analysis on muliple events
703 *
76be6fc2
BP
704 * Sum the broadcast differential delays
705 *
cdce23b3
BP
706 * Args:
707 * syncState container for synchronization data
708 * broadcast structure containing the events
709 */
66eaf2eb
BP
710static void analyzeBroadcastEval(SyncState* const syncState, Broadcast* const
711 broadcast)
cdce23b3 712{
66eaf2eb 713 AnalysisDataEval* analysisData= syncState->analysisData;
76be6fc2 714
66eaf2eb 715 if (syncState->stats)
76be6fc2 716 {
66eaf2eb
BP
717 double sum= 0, squaresSum= 0;
718 double y;
cdce23b3 719
66eaf2eb
BP
720 g_queue_foreach(broadcast->events, &gfSum, &sum);
721 g_queue_foreach(broadcast->events, &gfSumSquares, &squaresSum);
76be6fc2 722
66eaf2eb
BP
723 analysisData->stats->broadcastNb++;
724 // Because of numerical errors, this can at times be < 0
725 y= squaresSum / g_queue_get_length(broadcast->events) - pow(sum /
726 g_queue_get_length(broadcast->events), 2.);
727 if (y > 0)
728 {
2849af52
BP
729 analysisData->stats->broadcastStdevSum+= sqrt(y);
730 }
731
732 if (syncState->traceNb == 2 && g_queue_get_length(broadcast->events)
733 == 2)
734 {
735 Event* e0, * e1;
736 double dd;
737
738 e0= g_queue_peek_head(broadcast->events);
739 e1= g_queue_peek_tail(broadcast->events);
740 if (e0->traceNum > e1->traceNum)
741 {
742 Event* tmp;
743
744 tmp= e0;
745 e0= e1;
746 e1= tmp;
747 }
748
749 dd= wallTimeSub(&e1->wallTime, &e0->wallTime);
750
751 analysisData->stats->broadcastPairNb++;
752 if (dd < analysisData->stats->broadcastRangeMin)
753 {
754 analysisData->stats->broadcastRangeMin= dd;
755 }
756 if (dd > analysisData->stats->broadcastRangeMax)
757 {
758 analysisData->stats->broadcastRangeMax= dd;
759 }
760
761 analysisData->stats->broadcastSum+= dd;
762 analysisData->stats->broadcastSumSquares+= pow(dd, 2);
66eaf2eb
BP
763 }
764 }
76be6fc2 765
66eaf2eb 766 if (syncState->graphsStream)
76be6fc2 767 {
66eaf2eb
BP
768 unsigned int i, j;
769 GArray* events;
770 unsigned int eventNb= broadcast->events->length;
771
772 events= g_array_sized_new(FALSE, FALSE, sizeof(Event*), eventNb);
773 g_queue_foreach(broadcast->events, &gfAddEventToArray, events);
774
775 for (i= 0; i < eventNb; i++)
776 {
777 for (j= 0; j < eventNb; j++)
778 {
779 Event* eventI= g_array_index(events, Event*, i), * eventJ=
780 g_array_index(events, Event*, j);
781
782 if (eventI->traceNum < eventJ->traceNum)
783 {
784 updateBounds(analysisData->graphs->bounds, eventI, eventJ);
785 }
786 }
787 }
788
789 g_array_free(events, TRUE);
76be6fc2 790 }
cdce23b3
BP
791}
792
793
794/*
66eaf2eb 795 * Finalize the factor calculations. Since this module does not really
0a87ec9a 796 * calculate factors, absent factors are returned. Instead, histograms are
66eaf2eb 797 * written out and histogram structures are freed.
cdce23b3
BP
798 *
799 * Args:
800 * syncState container for synchronization data.
801 *
802 * Returns:
0a87ec9a 803 * AllFactors* synchronization factors for each trace pair
cdce23b3 804 */
0a87ec9a 805static AllFactors* finalizeAnalysisEval(SyncState* const syncState)
cdce23b3 806{
4ee223e5
BP
807 AnalysisDataEval* analysisData= syncState->analysisData;
808
66eaf2eb 809 if (syncState->graphsStream && analysisData->graphs->histograms)
4ee223e5 810 {
66eaf2eb
BP
811 g_hash_table_foreach(analysisData->graphs->histograms,
812 &ghfWriteHistogram, &(struct WriteHistogramInfo) {.rttInfo=
813 analysisData->rttInfo, .graphsStream= syncState->graphsStream});
814 g_hash_table_destroy(analysisData->graphs->histograms);
815 analysisData->graphs->histograms= NULL;
4ee223e5 816 }
cdce23b3 817
0a87ec9a 818 return createAllFactors(syncState->traceNb);
cdce23b3
BP
819}
820
821
822/*
823 * Print statistics related to analysis. Must be called after
824 * finalizeAnalysis.
825 *
826 * Args:
827 * syncState container for synchronization data.
828 */
829static void printAnalysisStatsEval(SyncState* const syncState)
830{
831 AnalysisDataEval* analysisData;
f109919b
BP
832 unsigned int i, j, k;
833 unsigned int totInversion= 0, totTooFast= 0, totNoInfo= 0, totTotal= 0;
834 int charNb;
cdce23b3
BP
835
836 if (!syncState->stats)
837 {
838 return;
839 }
840
841 analysisData= (AnalysisDataEval*) syncState->analysisData;
842
843 printf("Synchronization evaluation analysis stats:\n");
ffa21cfd
BP
844 if (analysisData->stats->broadcastNb)
845 {
2849af52
BP
846 printf("\tBroadcast differential delay:\n");
847 printf("\t\tsum of standard deviations: %g\n",
848 analysisData->stats->broadcastStdevSum);
849 printf("\t\taverage standard deviation: %g\n",
850 analysisData->stats->broadcastStdevSum /
ffa21cfd 851 analysisData->stats->broadcastNb);
2849af52
BP
852
853 if (syncState->traceNb == 2)
854 {
855 printf("\t\tdifferential delay range: [ %g .. %g ]\n",
856 analysisData->stats->broadcastRangeMin,
857 analysisData->stats->broadcastRangeMax);
858 printf("\t\tdifferential delay average: %g\n",
859 analysisData->stats->broadcastSum /
860 analysisData->stats->broadcastPairNb);
861 printf("\t\tdifferential delay standard deviation: %g\n",
862 sqrt(analysisData->stats->broadcastSumSquares /
863 analysisData->stats->broadcastPairNb -
864 pow(analysisData->stats->broadcastSum /
865 analysisData->stats->broadcastPairNb, 2)));
866 }
ffa21cfd 867 }
cdce23b3
BP
868
869 printf("\tIndividual evaluation:\n"
f109919b 870 "\t\tTrace pair Inversions Too fast No RTT info Total\n");
cdce23b3
BP
871
872 for (i= 0; i < syncState->traceNb; i++)
873 {
874 for (j= i + 1; j < syncState->traceNb; j++)
875 {
76be6fc2 876 MessageStats* messageStats;
f109919b
BP
877 struct {
878 unsigned int t1, t2;
879 } loopValues[]= {
880 {i, j},
881 {j, i}
882 };
883
884 for (k= 0; k < sizeof(loopValues) / sizeof(*loopValues); k++)
885 {
886 messageStats=
887 &analysisData->stats->messageStats[loopValues[k].t1][loopValues[k].t2];
888
889 printf("\t\t%3d - %-3d ", loopValues[k].t1, loopValues[k].t2);
2849af52
BP
890 printf("%u (%.2f%%)%n", messageStats->inversionNb, (double)
891 messageStats->inversionNb / messageStats->total * 100,
892 &charNb);
f109919b 893 printf("%*s", 17 - charNb > 0 ? 17 - charNb + 1: 1, " ");
2849af52
BP
894 printf("%u (%.2f%%)%n", messageStats->tooFastNb, (double)
895 messageStats->tooFastNb / messageStats->total * 100,
896 &charNb);
f109919b
BP
897 printf("%*s%-10u %u\n", 17 - charNb > 0 ? 17 - charNb + 1:
898 1, " ", messageStats->noRTTInfoNb, messageStats->total);
899
900 totInversion+= messageStats->inversionNb;
901 totTooFast+= messageStats->tooFastNb;
902 totNoInfo+= messageStats->noRTTInfoNb;
903 totTotal+= messageStats->total;
904 }
cdce23b3
BP
905 }
906 }
d4721e1a 907
f109919b 908 printf("\t\t total ");
2849af52
BP
909 printf("%u (%.2f%%)%n", totInversion, (double) totInversion / totTotal *
910 100, &charNb);
f109919b 911 printf("%*s", 17 - charNb > 0 ? 17 - charNb + 1: 1, " ");
2849af52
BP
912 printf("%u (%.2f%%)%n", totTooFast, (double) totTooFast / totTotal * 100,
913 &charNb);
f109919b
BP
914 printf("%*s%-10u %u\n", 17 - charNb > 0 ? 17 - charNb + 1: 1, " ",
915 totNoInfo, totTotal);
916
d4721e1a
BP
917 printf("\tRound-trip times:\n"
918 "\t\tHost pair RTT from exchanges RTTs from file (ms)\n");
919 g_hash_table_foreach(analysisData->stats->exchangeRtt,
920 &ghfPrintExchangeRtt, analysisData->rttInfo);
921}
922
923
924/*
925 * A GHFunc for g_hash_table_foreach()
926 *
927 * Args:
928 * key: RttKey* where saddr < daddr
929 * value: double*, RTT estimated from exchanges
930 * user_data GHashTable* rttInfo
931 */
66eaf2eb
BP
932static void ghfPrintExchangeRtt(gpointer key, gpointer value, gpointer
933 user_data)
d4721e1a
BP
934{
935 char addr1[16], addr2[16];
936 struct RttKey* rttKey1= key;
937 struct RttKey rttKey2= {rttKey1->daddr, rttKey1->saddr};
938 double* fileRtt1, *fileRtt2;
939 GHashTable* rttInfo= user_data;
940
941 convertIP(addr1, rttKey1->saddr);
942 convertIP(addr2, rttKey1->daddr);
943
944 fileRtt1= g_hash_table_lookup(rttInfo, rttKey1);
945 fileRtt2= g_hash_table_lookup(rttInfo, &rttKey2);
946
947 printf("\t\t(%15s, %-15s) %-18.3f ", addr1, addr2, *(double*) value * 1e3);
948
949 if (fileRtt1 || fileRtt2)
950 {
951 if (fileRtt1)
952 {
953 printf("%.3f", *fileRtt1 * 1e3);
954 }
955 if (fileRtt1 && fileRtt2)
956 {
957 printf(", ");
958 }
959 if (fileRtt2)
960 {
961 printf("%.3f", *fileRtt2 * 1e3);
962 }
963 }
964 else
965 {
966 printf("-");
967 }
968 printf("\n");
cdce23b3 969}
2bd4b3e4
BP
970
971
972/*
973 * A GHashFunc for g_hash_table_new()
974 *
975 * Args:
976 * key struct RttKey*
977 */
978static guint ghfRttKeyHash(gconstpointer key)
979{
980 struct RttKey* rttKey;
981 uint32_t a, b, c;
982
983 rttKey= (struct RttKey*) key;
984
985 a= rttKey->saddr;
986 b= rttKey->daddr;
987 c= 0;
988 final(a, b, c);
989
990 return c;
991}
992
993
994/*
995 * A GDestroyNotify function for g_hash_table_new_full()
996 *
997 * Args:
998 * data: struct RttKey*
999 */
1000static void gdnDestroyRttKey(gpointer data)
1001{
1002 free(data);
1003}
1004
1005
1006/*
1007 * A GDestroyNotify function for g_hash_table_new_full()
1008 *
1009 * Args:
1010 * data: double*
1011 */
1012static void gdnDestroyDouble(gpointer data)
1013{
1014 free(data);
1015}
1016
1017
1018/*
1019 * A GEqualFunc for g_hash_table_new()
1020 *
1021 * Args:
1022 * a, b RttKey*
1023 *
1024 * Returns:
1025 * TRUE if both values are equal
1026 */
1027static gboolean gefRttKeyEqual(gconstpointer a, gconstpointer b)
1028{
1029 const struct RttKey* rkA, * rkB;
1030
1031 rkA= (struct RttKey*) a;
1032 rkB= (struct RttKey*) b;
1033
1034 if (rkA->saddr == rkB->saddr && rkA->daddr == rkB->daddr)
1035 {
1036 return TRUE;
1037 }
1038 else
1039 {
1040 return FALSE;
1041 }
1042}
1043
1044
1045/*
1046 * Read a file contain minimum round trip time values and fill an array with
1047 * them. The file is formatted as such:
1048 * <host1 IP> <host2 IP> <RTT in milliseconds>
1049 * ip's should be in dotted quad format
1050 *
1051 * Args:
1052 * rttInfo: double* rttInfo[RttKey], empty table, will be filled
1053 * rttStream: stream from which to read
1054 */
1055static void readRttInfo(GHashTable* rttInfo, FILE* rttStream)
1056{
1057 char* line= NULL;
1058 size_t len;
1059 int retval;
1060
1061 positionStream(rttStream);
1062 retval= getline(&line, &len, rttStream);
1063 while(!feof(rttStream))
1064 {
1065 struct RttKey* rttKey;
1066 char saddrDQ[20], daddrDQ[20];
1067 double* rtt;
1068 char tmp;
1069 struct in_addr addr;
1070 unsigned int i;
1071 struct {
1072 char* dq;
1073 size_t offset;
1074 } loopValues[] = {
1075 {saddrDQ, offsetof(struct RttKey, saddr)},
1076 {daddrDQ, offsetof(struct RttKey, daddr)}
1077 };
1078
1079 if (retval == -1 && !feof(rttStream))
1080 {
1081 g_error(strerror(errno));
1082 }
1083
1084 if (line[retval - 1] == '\n')
1085 {
1086 line[retval - 1]= '\0';
1087 }
1088
1089 rtt= malloc(sizeof(double));
1090 retval= sscanf(line, " %19s %19s %lf %c", saddrDQ, daddrDQ, rtt,
1091 &tmp);
1092 if (retval == EOF)
1093 {
1094 g_error(strerror(errno));
1095 }
1096 else if (retval != 3)
1097 {
1098 g_error("Error parsing RTT file, line was '%s'", line);
1099 }
1100
1101 rttKey= malloc(sizeof(struct RttKey));
1102 for (i= 0; i < sizeof(loopValues) / sizeof(*loopValues); i++)
1103 {
1104 retval= inet_aton(loopValues[i].dq, &addr);
1105 if (retval == 0)
1106 {
1107 g_error("Error converting address '%s'", loopValues[i].dq);
1108 }
1109 *(uint32_t*) ((void*) rttKey + loopValues[i].offset)=
1110 addr.s_addr;
1111 }
1112
76be6fc2 1113 *rtt/= 1e3;
d4721e1a
BP
1114 g_debug("rttInfo, Inserting (%u, %u)->(%f)", rttKey->saddr,
1115 rttKey->daddr, *rtt);
2bd4b3e4
BP
1116 g_hash_table_insert(rttInfo, rttKey, rtt);
1117
1118 positionStream(rttStream);
1119 retval= getline(&line, &len, rttStream);
1120 }
1121
1122 if (line)
1123 {
1124 free(line);
1125 }
1126}
1127
1128
1129/*
1130 * Advance stream over empty space, empty lines and lines that begin with '#'
1131 *
1132 * Args:
1133 * stream: stream, at exit, will be over the first non-empty character
1134 * of a line of be at EOF
1135 */
1136static void positionStream(FILE* stream)
1137{
1138 int firstChar;
1139 ssize_t retval;
1140 char* line= NULL;
1141 size_t len;
1142
1143 do
1144 {
1145 firstChar= fgetc(stream);
1146 if (firstChar == (int) '#')
1147 {
1148 retval= getline(&line, &len, stream);
1149 if (retval == -1)
1150 {
1151 if (feof(stream))
1152 {
1153 goto outEof;
1154 }
1155 else
1156 {
1157 g_error(strerror(errno));
1158 }
1159 }
1160 }
1161 else if (firstChar == (int) '\n' || firstChar == (int) ' ' ||
1162 firstChar == (int) '\t')
1163 {}
1164 else if (firstChar == EOF)
1165 {
1166 goto outEof;
1167 }
1168 else
1169 {
1170 break;
1171 }
1172 } while (true);
1173 retval= ungetc(firstChar, stream);
1174 if (retval == EOF)
1175 {
1176 g_error("Error: ungetc()");
1177 }
1178
1179outEof:
1180 if (line)
1181 {
1182 free(line);
1183 }
1184}
76be6fc2
BP
1185
1186
1187/*
1188 * A GFunc for g_queue_foreach()
1189 *
1190 * Args:
1191 * data Event*, a UDP broadcast event
1192 * user_data double*, the running sum
1193 *
1194 * Returns:
1195 * Adds the time of the event to the sum
1196 */
1197static void gfSum(gpointer data, gpointer userData)
1198{
1199 Event* event= (Event*) data;
1200
1201 *(double*) userData+= event->wallTime.seconds + event->wallTime.nanosec /
1202 1e9;
1203}
1204
1205
1206/*
1207 * A GFunc for g_queue_foreach()
1208 *
1209 * Args:
1210 * data Event*, a UDP broadcast event
1211 * user_data double*, the running sum
1212 *
1213 * Returns:
1214 * Adds the square of the time of the event to the sum
1215 */
1216static void gfSumSquares(gpointer data, gpointer userData)
1217{
1218 Event* event= (Event*) data;
1219
1220 *(double*) userData+= pow(event->wallTime.seconds + event->wallTime.nanosec
1221 / 1e9, 2.);
1222}
4ee223e5
BP
1223
1224
e072e1ab
BP
1225/*
1226 * Update a struct Bins according to a new value
1227 *
1228 * Args:
1229 * bins: the structure containing bins to build a histrogram
1230 * value: the new value
1231 */
1232static void hitBin(struct Bins* const bins, const double value)
1233{
1234 unsigned int binN= binNum(value);
1235
1236 if (binN < bins->min)
1237 {
1238 bins->min= binN;
1239 }
1240 else if (binN > bins->max)
1241 {
1242 bins->max= binN;
1243 }
1244
1245 bins->total++;
1246
1247 bins->bin[binN]++;
1248}
1249
1250
4ee223e5
BP
1251/*
1252 * Figure out the bin in a histogram to which a value belongs.
1253 *
1254 * This uses exponentially sized bins that go from 0 to infinity.
1255 *
1256 * Args:
e072e1ab
BP
1257 * value: in the range -INFINITY to INFINITY
1258 *
1259 * Returns:
1260 * The number of the bin in a struct Bins.bin
4ee223e5
BP
1261 */
1262static unsigned int binNum(const double value)
1263{
e072e1ab 1264 if (value <= 0)
4ee223e5
BP
1265 {
1266 return 0;
1267 }
e072e1ab
BP
1268 else if (value < binEnd(1))
1269 {
1270 return 1;
1271 }
1272 else if (value >= binStart(BIN_NB - 1))
1273 {
1274 return BIN_NB - 1;
1275 }
4ee223e5
BP
1276 else
1277 {
e072e1ab 1278 return floor(log(value) / log(binBase)) + BIN_NB + 1;
4ee223e5
BP
1279 }
1280}
1281
1282
1283/*
e072e1ab
BP
1284 * Figure out the start of the interval of a bin in a histogram. See struct
1285 * Bins.
4ee223e5
BP
1286 *
1287 * This uses exponentially sized bins that go from 0 to infinity.
1288 *
1289 * Args:
1290 * binNum: bin number
e072e1ab
BP
1291 *
1292 * Return:
1293 * The start of the interval, this value is included in the interval (except
1294 * for -INFINITY, naturally)
4ee223e5
BP
1295 */
1296static double binStart(const unsigned int binNum)
1297{
e072e1ab 1298 g_assert_cmpuint(binNum, <, BIN_NB);
4ee223e5
BP
1299
1300 if (binNum == 0)
1301 {
e072e1ab
BP
1302 return -INFINITY;
1303 }
1304 else if (binNum == 1)
1305 {
1306 return 0.;
4ee223e5
BP
1307 }
1308 else
1309 {
e072e1ab 1310 return pow(binBase, (double) binNum - BIN_NB + 1);
4ee223e5
BP
1311 }
1312}
1313
1314
1315/*
e072e1ab
BP
1316 * Figure out the end of the interval of a bin in a histogram. See struct
1317 * Bins.
4ee223e5
BP
1318 *
1319 * This uses exponentially sized bins that go from 0 to infinity.
1320 *
1321 * Args:
1322 * binNum: bin number
e072e1ab
BP
1323 *
1324 * Return:
1325 * The end of the interval, this value is not included in the interval
4ee223e5
BP
1326 */
1327static double binEnd(const unsigned int binNum)
1328{
e072e1ab 1329 g_assert_cmpuint(binNum, <, BIN_NB);
4ee223e5 1330
e072e1ab 1331 if (binNum == 0)
4ee223e5 1332 {
e072e1ab
BP
1333 return 0.;
1334 }
1335 else if (binNum < BIN_NB - 1)
1336 {
1337 return pow(binBase, (double) binNum - BIN_NB + 2);
4ee223e5
BP
1338 }
1339 else
1340 {
1341 return INFINITY;
1342 }
1343}
467066ee
BP
1344
1345
1346/*
1347 * Return the total number of elements in the "normal" bins (not underflow or
1348 * overflow)
1349 *
1350 * Args:
1351 * bins: the structure containing bins to build a histrogram
1352 */
1353static uint32_t normalTotal(struct Bins* const bins)
1354{
1355 return bins->total - bins->bin[0] - bins->bin[BIN_NB - 1];
1356}
66eaf2eb
BP
1357
1358
1359/* Update the bounds between two traces
1360 *
1361 * Args:
1362 * bounds: the array containing all the trace-pair bounds
1363 * e1, e2: the two related events
1364 */
c6356aa7
BP
1365static void updateBounds(Bounds** const bounds, Event* const e1, Event* const
1366 e2)
66eaf2eb
BP
1367{
1368 unsigned int traceI, traceJ;
1369 uint64_t messageTime;
1370 Bounds* tpBounds;
1371
1372 if (e1->traceNum < e2->traceNum)
1373 {
1374 traceI= e2->traceNum;
1375 traceJ= e1->traceNum;
1376 messageTime= e1->cpuTime;
1377 }
1378 else
1379 {
1380 traceI= e1->traceNum;
1381 traceJ= e2->traceNum;
1382 messageTime= e2->cpuTime;
1383 }
1384 tpBounds= &bounds[traceI][traceJ];
1385
1386 if (messageTime < tpBounds->min)
1387 {
1388 tpBounds->min= messageTime;
1389 }
1390 if (messageTime > tpBounds->max)
1391 {
1392 tpBounds->max= messageTime;
1393 }
1394}
This page took 0.090016 seconds and 4 git commands to generate.