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