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,
20 #define _ISOC99_SOURCE
26 #include <arpa/inet.h>
29 #include <netinet/in.h>
34 #include <sys/socket.h>
38 #include "sync_chain.h"
40 #include "event_analysis_eval.h"
43 // Functions common to all analysis modules
44 static void initAnalysisEval(SyncState
* const syncState
);
45 static void destroyAnalysisEval(SyncState
* const syncState
);
47 static void analyzeMessageEval(SyncState
* const syncState
, Message
* const
49 static void analyzeExchangeEval(SyncState
* const syncState
, Exchange
* const
51 static void analyzeBroadcastEval(SyncState
* const syncState
, Broadcast
* const
53 static GArray
* finalizeAnalysisEval(SyncState
* const syncState
);
54 static void printAnalysisStatsEval(SyncState
* const syncState
);
55 static void writeAnalysisGraphsPlotsEval(FILE* stream
, SyncState
* const
56 syncState
, const unsigned int i
, const unsigned int j
);
57 static void writeAnalysisGraphsOptionsEval(FILE* stream
, SyncState
*
58 const syncState
, const unsigned int i
, const unsigned int j
);
60 // Functions specific to this module
61 static void registerAnalysisEval() __attribute__((constructor (102)));
62 static guint
ghfRttKeyHash(gconstpointer key
);
63 static gboolean
gefRttKeyEqual(gconstpointer a
, gconstpointer b
);
64 static void gdnDestroyRttKey(gpointer data
);
65 static void gdnDestroyDouble(gpointer data
);
66 static void readRttInfo(GHashTable
* rttInfo
, FILE* rttFile
);
67 static void positionStream(FILE* stream
);
69 static void gfSum(gpointer data
, gpointer userData
);
70 static void gfSumSquares(gpointer data
, gpointer userData
);
71 static void ghfPrintExchangeRtt(gpointer key
, gpointer value
, gpointer user_data
);
73 static void initGraphs(SyncState
* const syncState
);
74 static void writeGraphFiles(SyncState
* const syncState
);
75 static void dumpBinToFile(const uint32_t* const bin
, const uint32_t total
,
77 static void destroyGraphs(SyncState
* const syncState
);
78 static unsigned int binNum(const double value
) __attribute__((pure
));
79 static double binStart(const unsigned int binNum
) __attribute__((pure
));
80 static double binEnd(const unsigned int binNum
) __attribute__((pure
));
83 const unsigned int binNb
= 10000;
86 static AnalysisModule analysisModuleEval
= {
88 .initAnalysis
= &initAnalysisEval
,
89 .destroyAnalysis
= &destroyAnalysisEval
,
90 .analyzeMessage
= &analyzeMessageEval
,
91 .analyzeExchange
= &analyzeExchangeEval
,
92 .analyzeBroadcast
= &analyzeBroadcastEval
,
93 .finalizeAnalysis
= &finalizeAnalysisEval
,
94 .printAnalysisStats
= &printAnalysisStatsEval
,
95 .writeAnalysisGraphsPlots
= &writeAnalysisGraphsPlotsEval
,
96 .writeAnalysisGraphsOptions
= &writeAnalysisGraphsOptionsEval
,
99 static ModuleOption optionEvalRttFile
= {
100 .longName
= "eval-rtt-file",
101 .hasArg
= REQUIRED_ARG
,
103 .optionHelp
= "specify the file containing RTT information",
109 * Analysis module registering function
111 static void registerAnalysisEval()
113 g_queue_push_tail(&analysisModules
, &analysisModuleEval
);
114 g_queue_push_tail(&moduleOptions
, &optionEvalRttFile
);
119 * Analysis init function
121 * This function is called at the beginning of a synchronization run for a set
125 * syncState container for synchronization data.
127 static void initAnalysisEval(SyncState
* const syncState
)
129 AnalysisDataEval
* analysisData
;
132 analysisData
= malloc(sizeof(AnalysisDataEval
));
133 syncState
->analysisData
= analysisData
;
135 analysisData
->rttInfo
= g_hash_table_new_full(&ghfRttKeyHash
,
136 &gefRttKeyEqual
, &gdnDestroyRttKey
, &gdnDestroyDouble
);
137 if (optionEvalRttFile
.arg
)
142 rttStream
= fopen(optionEvalRttFile
.arg
, "r");
143 if (rttStream
== NULL
)
145 g_error(strerror(errno
));
148 readRttInfo(analysisData
->rttInfo
, rttStream
);
150 retval
= fclose(rttStream
);
153 g_error(strerror(errno
));
157 if (syncState
->stats
)
159 analysisData
->stats
= calloc(1, sizeof(AnalysisStatsEval
));
160 analysisData
->stats
->broadcastDiffSum
= 0.;
162 analysisData
->stats
->messageStats
= malloc(syncState
->traceNb
*
163 sizeof(MessageStats
*));
164 for (i
= 0; i
< syncState
->traceNb
; i
++)
166 analysisData
->stats
->messageStats
[i
]= calloc(syncState
->traceNb
,
167 sizeof(MessageStats
));
170 analysisData
->stats
->exchangeRtt
=
171 g_hash_table_new_full(&ghfRttKeyHash
, &gefRttKeyEqual
,
172 &gdnDestroyRttKey
, &gdnDestroyDouble
);
175 if (syncState
->graphs
)
177 binBase
= exp10(6. / (binNb
- 2));
178 analysisData
->graphs
= malloc(sizeof(AnalysisGraphsEval
));
179 initGraphs(syncState
);
185 * Create and open files used to store histogram points to genereate
186 * graphs. Allocate and populate array to store file pointers.
188 * Also create data structures to store histogram points during analysis.
191 * syncState: container for synchronization data
193 static void initGraphs(SyncState
* const syncState
)
199 AnalysisDataEval
* analysisData
= syncState
->analysisData
;
201 cwd
= changeToGraphDir(syncState
->graphs
);
203 analysisData
->graphs
->ttPoints
= malloc(syncState
->traceNb
*
205 analysisData
->graphs
->ttBinsArray
= malloc(syncState
->traceNb
*
207 analysisData
->graphs
->ttBinsTotal
= malloc(syncState
->traceNb
*
209 for (i
= 0; i
< syncState
->traceNb
; i
++)
211 analysisData
->graphs
->ttPoints
[i
]= malloc(syncState
->traceNb
*
213 analysisData
->graphs
->ttBinsArray
[i
]= malloc(syncState
->traceNb
*
215 analysisData
->graphs
->ttBinsTotal
[i
]= calloc(syncState
->traceNb
,
217 for (j
= 0; j
< syncState
->traceNb
; j
++)
221 retval
= snprintf(name
, sizeof(name
),
222 "analysis_eval_tt-%03u_to_%03u.data", i
, j
);
223 if (retval
> sizeof(name
) - 1)
225 name
[sizeof(name
) - 1]= '\0';
227 if ((analysisData
->graphs
->ttPoints
[i
][j
]= fopen(name
, "w")) ==
230 g_error(strerror(errno
));
233 analysisData
->graphs
->ttBinsArray
[i
][j
]= calloc(binNb
,
239 analysisData
->graphs
->hrttPoints
= malloc(syncState
->traceNb
*
241 analysisData
->graphs
->hrttBinsArray
= malloc(syncState
->traceNb
*
243 analysisData
->graphs
->hrttBinsTotal
= malloc(syncState
->traceNb
*
245 for (i
= 0; i
< syncState
->traceNb
; i
++)
247 analysisData
->graphs
->hrttPoints
[i
]= malloc(i
* sizeof(FILE*));
248 analysisData
->graphs
->hrttBinsArray
[i
]= malloc(i
* sizeof(uint32_t*));
249 analysisData
->graphs
->hrttBinsTotal
[i
]= calloc(i
, sizeof(uint32_t));
250 for (j
= 0; j
< i
; j
++)
252 retval
= snprintf(name
, sizeof(name
),
253 "analysis_eval_hrtt-%03u_and_%03u.data", i
, j
);
254 if (retval
> sizeof(name
) - 1)
256 name
[sizeof(name
) - 1]= '\0';
258 if ((analysisData
->graphs
->hrttPoints
[i
][j
]= fopen(name
, "w")) ==
261 g_error(strerror(errno
));
264 analysisData
->graphs
->hrttBinsArray
[i
][j
]= calloc(binNb
,
272 g_error(strerror(errno
));
279 * Write histogram points to all files to generate graphs.
282 * syncState: container for synchronization data
284 static void writeGraphFiles(SyncState
* const syncState
)
287 AnalysisDataEval
* analysisData
= syncState
->analysisData
;
289 for (i
= 0; i
< syncState
->traceNb
; i
++)
291 for (j
= 0; j
< syncState
->traceNb
; j
++)
295 dumpBinToFile(analysisData
->graphs
->ttBinsArray
[i
][j
],
296 analysisData
->graphs
->ttBinsTotal
[i
][j
] -
297 analysisData
->graphs
->ttBinsArray
[i
][j
][binNb
- 1],
298 analysisData
->graphs
->ttPoints
[i
][j
]);
303 dumpBinToFile(analysisData
->graphs
->hrttBinsArray
[i
][j
],
304 analysisData
->graphs
->hrttBinsTotal
[i
][j
] -
305 analysisData
->graphs
->hrttBinsArray
[i
][j
][binNb
- 1],
306 analysisData
->graphs
->hrttPoints
[i
][j
]);
314 * Write the content of one bin in a histogram point file
317 * bin: array of values that make up a histogram
318 * total: total number of messages in bins 0 to binNb - 2
321 static void dumpBinToFile(const uint32_t* const bin
, const uint32_t total
,
326 // Last bin is skipped because is continues till infinity
327 for (i
= 0; i
< binNb
- 1; i
++)
331 fprintf(file
, "%20.9f %20.9f %20.9f\n", (binStart(i
) + binEnd(i
)) / 2, (double) bin
[i
]
332 / ((binEnd(i
) - binStart(i
)) * total
), binEnd(i
) - binStart(i
));
339 * Close files used to store histogram points to generate graphs. Deallocate
340 * arrays of file pointers and arrays used to store histogram points during
344 * syncState: container for synchronization data
346 static void destroyGraphs(SyncState
* const syncState
)
349 AnalysisDataEval
* analysisData
= syncState
->analysisData
;
352 if (analysisData
->graphs
== NULL
|| analysisData
->graphs
->ttPoints
==
358 for (i
= 0; i
< syncState
->traceNb
; i
++)
360 for (j
= 0; j
< syncState
->traceNb
; j
++)
364 retval
= fclose(analysisData
->graphs
->ttPoints
[i
][j
]);
367 g_error(strerror(errno
));
370 free(analysisData
->graphs
->ttBinsArray
[i
][j
]);
373 free(analysisData
->graphs
->ttPoints
[i
]);
374 free(analysisData
->graphs
->ttBinsArray
[i
]);
375 free(analysisData
->graphs
->ttBinsTotal
[i
]);
377 free(analysisData
->graphs
->ttPoints
);
378 free(analysisData
->graphs
->ttBinsArray
);
379 free(analysisData
->graphs
->ttBinsTotal
);
381 for (i
= 0; i
< syncState
->traceNb
; i
++)
383 for (j
= 0; j
< i
; j
++)
385 retval
= fclose(analysisData
->graphs
->hrttPoints
[i
][j
]);
388 g_error(strerror(errno
));
391 free(analysisData
->graphs
->hrttBinsArray
[i
][j
]);
393 free(analysisData
->graphs
->hrttPoints
[i
]);
394 free(analysisData
->graphs
->hrttBinsArray
[i
]);
395 free(analysisData
->graphs
->hrttBinsTotal
[i
]);
397 free(analysisData
->graphs
->hrttPoints
);
398 free(analysisData
->graphs
->hrttBinsArray
);
399 free(analysisData
->graphs
->hrttBinsTotal
);
401 analysisData
->graphs
->ttPoints
= NULL
;
406 * Analysis destroy function
408 * Free the analysis specific data structures
411 * syncState container for synchronization data.
413 static void destroyAnalysisEval(SyncState
* const syncState
)
416 AnalysisDataEval
* analysisData
;
418 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
420 if (analysisData
== NULL
|| analysisData
->rttInfo
== NULL
)
425 g_hash_table_destroy(analysisData
->rttInfo
);
426 analysisData
->rttInfo
= NULL
;
428 if (syncState
->stats
)
430 for (i
= 0; i
< syncState
->traceNb
; i
++)
432 free(analysisData
->stats
->messageStats
[i
]);
434 free(analysisData
->stats
->messageStats
);
436 g_hash_table_destroy(analysisData
->stats
->exchangeRtt
);
438 free(analysisData
->stats
);
441 if (syncState
->graphs
&& analysisData
->graphs
)
443 destroyGraphs(syncState
);
444 free(analysisData
->graphs
);
447 free(syncState
->analysisData
);
448 syncState
->analysisData
= NULL
;
453 * Perform analysis on an event pair.
455 * Check if there is message inversion or messages that are too fast.
458 * syncState container for synchronization data
459 * message structure containing the events
461 static void analyzeMessageEval(SyncState
* const syncState
, Message
* const message
)
463 AnalysisDataEval
* analysisData
;
464 MessageStats
* messageStats
;
467 struct RttKey rttKey
;
469 if (!syncState
->stats
)
474 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
476 &analysisData
->stats
->messageStats
[message
->outE
->traceNum
][message
->inE
->traceNum
];
478 messageStats
->total
++;
480 tt
= wallTimeSub(&message
->inE
->wallTime
, &message
->outE
->wallTime
);
483 messageStats
->inversionNb
++;
485 else if (syncState
->graphs
)
487 analysisData
->graphs
->ttBinsArray
[message
->outE
->traceNum
][message
->inE
->traceNum
][binNum(tt
)]++;
488 analysisData
->graphs
->ttBinsTotal
[message
->outE
->traceNum
][message
->inE
->traceNum
]++;
491 g_assert(message
->inE
->type
== TCP
);
493 message
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.saddr
;
495 message
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.daddr
;
496 rtt
= g_hash_table_lookup(analysisData
->rttInfo
, &rttKey
);
497 g_debug("rttInfo, looking up (%u, %u)->(%f)", rttKey
.saddr
,
498 rttKey
.daddr
, rtt
? *rtt
: NAN
);
502 g_debug("rttInfo, tt: %f rtt / 2: %f", tt
, *rtt
/ 2.);
505 messageStats
->tooFastNb
++;
510 messageStats
->noRTTInfoNb
++;
516 * Perform analysis on multiple messages
521 * syncState container for synchronization data
522 * exchange structure containing the messages
524 static void analyzeExchangeEval(SyncState
* const syncState
, Exchange
* const exchange
)
526 AnalysisDataEval
* analysisData
= syncState
->analysisData
;
527 Message
* m1
= g_queue_peek_tail(exchange
->acks
);
528 Message
* m2
= exchange
->message
;
529 struct RttKey
* rttKey
;
530 double* rtt
, * exchangeRtt
;
532 if (!syncState
->stats
)
537 // (T2 - T1) - (T3 - T4)
538 rtt
= malloc(sizeof(double));
539 *rtt
= wallTimeSub(&m1
->inE
->wallTime
, &m1
->outE
->wallTime
) -
540 wallTimeSub(&m2
->outE
->wallTime
, &m2
->inE
->wallTime
);
542 if (syncState
->graphs
)
544 unsigned int row
= MAX(m1
->inE
->traceNum
, m1
->outE
->traceNum
);
545 unsigned int col
= MIN(m1
->inE
->traceNum
, m1
->outE
->traceNum
);
547 analysisData
->graphs
->hrttBinsArray
[row
][col
][binNum(*rtt
/ 2.)]++;
548 analysisData
->graphs
->hrttBinsTotal
[row
][col
]++;
551 g_assert(m1
->inE
->type
== TCP
);
552 rttKey
= malloc(sizeof(struct RttKey
));
554 MIN(m1
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.saddr
,
555 m1
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.daddr
);
557 MAX(m1
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.saddr
,
558 m1
->inE
->event
.tcpEvent
->segmentKey
->connectionKey
.daddr
);
559 exchangeRtt
= g_hash_table_lookup(analysisData
->stats
->exchangeRtt
,
564 if (*rtt
< *exchangeRtt
)
566 g_hash_table_replace(analysisData
->stats
->exchangeRtt
, rttKey
, rtt
);
571 g_hash_table_insert(analysisData
->stats
->exchangeRtt
, rttKey
, rtt
);
577 * Perform analysis on muliple events
579 * Sum the broadcast differential delays
582 * syncState container for synchronization data
583 * broadcast structure containing the events
585 static void analyzeBroadcastEval(SyncState
* const syncState
, Broadcast
* const broadcast
)
587 AnalysisDataEval
* analysisData
;
588 double sum
= 0, squaresSum
= 0;
591 if (!syncState
->stats
)
596 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
598 g_queue_foreach(broadcast
->events
, &gfSum
, &sum
);
599 g_queue_foreach(broadcast
->events
, &gfSumSquares
, &squaresSum
);
601 analysisData
->stats
->broadcastNb
++;
602 // Because of numerical errors, this can at times be < 0
603 y
= squaresSum
/ g_queue_get_length(broadcast
->events
) - pow(sum
/
604 g_queue_get_length(broadcast
->events
), 2.);
607 analysisData
->stats
->broadcastDiffSum
+= sqrt(y
);
613 * Finalize the factor calculations
615 * Since this module does not really calculate factors, identity factors are
619 * syncState container for synchronization data.
622 * Factors[traceNb] identity factors for each trace
624 static GArray
* finalizeAnalysisEval(SyncState
* const syncState
)
628 AnalysisDataEval
* analysisData
= syncState
->analysisData
;
630 if (syncState
->graphs
&& analysisData
->graphs
)
632 writeGraphFiles(syncState
);
633 destroyGraphs(syncState
);
634 analysisData
->graphs
= NULL
;
637 factors
= g_array_sized_new(FALSE
, FALSE
, sizeof(Factors
),
639 g_array_set_size(factors
, syncState
->traceNb
);
640 for (i
= 0; i
< syncState
->traceNb
; i
++)
644 e
= &g_array_index(factors
, Factors
, i
);
654 * Print statistics related to analysis. Must be called after
658 * syncState container for synchronization data.
660 static void printAnalysisStatsEval(SyncState
* const syncState
)
662 AnalysisDataEval
* analysisData
;
665 if (!syncState
->stats
)
670 analysisData
= (AnalysisDataEval
*) syncState
->analysisData
;
672 printf("Synchronization evaluation analysis stats:\n");
673 printf("\tsum of broadcast differential delays: %g\n",
674 analysisData
->stats
->broadcastDiffSum
);
675 printf("\taverage broadcast differential delays: %g\n",
676 analysisData
->stats
->broadcastDiffSum
/
677 analysisData
->stats
->broadcastNb
);
679 printf("\tIndividual evaluation:\n"
680 "\t\tTrace pair Inversions Too fast (No RTT info) Total\n");
682 for (i
= 0; i
< syncState
->traceNb
; i
++)
684 for (j
= i
+ 1; j
< syncState
->traceNb
; j
++)
686 MessageStats
* messageStats
;
687 const char* format
= "\t\t%3d - %-3d %-10u %-10u %-10u %u\n";
689 messageStats
= &analysisData
->stats
->messageStats
[i
][j
];
691 printf(format
, i
, j
, messageStats
->inversionNb
, messageStats
->tooFastNb
,
692 messageStats
->noRTTInfoNb
, messageStats
->total
);
694 messageStats
= &analysisData
->stats
->messageStats
[j
][i
];
696 printf(format
, j
, i
, messageStats
->inversionNb
, messageStats
->tooFastNb
,
697 messageStats
->noRTTInfoNb
, messageStats
->total
);
701 printf("\tRound-trip times:\n"
702 "\t\tHost pair RTT from exchanges RTTs from file (ms)\n");
703 g_hash_table_foreach(analysisData
->stats
->exchangeRtt
,
704 &ghfPrintExchangeRtt
, analysisData
->rttInfo
);
709 * A GHFunc for g_hash_table_foreach()
712 * key: RttKey* where saddr < daddr
713 * value: double*, RTT estimated from exchanges
714 * user_data GHashTable* rttInfo
716 static void ghfPrintExchangeRtt(gpointer key
, gpointer value
, gpointer user_data
)
718 char addr1
[16], addr2
[16];
719 struct RttKey
* rttKey1
= key
;
720 struct RttKey rttKey2
= {rttKey1
->daddr
, rttKey1
->saddr
};
721 double* fileRtt1
, *fileRtt2
;
722 GHashTable
* rttInfo
= user_data
;
724 convertIP(addr1
, rttKey1
->saddr
);
725 convertIP(addr2
, rttKey1
->daddr
);
727 fileRtt1
= g_hash_table_lookup(rttInfo
, rttKey1
);
728 fileRtt2
= g_hash_table_lookup(rttInfo
, &rttKey2
);
730 printf("\t\t(%15s, %-15s) %-18.3f ", addr1
, addr2
, *(double*) value
* 1e3
);
732 if (fileRtt1
|| fileRtt2
)
736 printf("%.3f", *fileRtt1
* 1e3
);
738 if (fileRtt1
&& fileRtt2
)
744 printf("%.3f", *fileRtt2
* 1e3
);
756 * A GHashFunc for g_hash_table_new()
761 static guint
ghfRttKeyHash(gconstpointer key
)
763 struct RttKey
* rttKey
;
766 rttKey
= (struct RttKey
*) key
;
778 * A GDestroyNotify function for g_hash_table_new_full()
781 * data: struct RttKey*
783 static void gdnDestroyRttKey(gpointer data
)
790 * A GDestroyNotify function for g_hash_table_new_full()
795 static void gdnDestroyDouble(gpointer data
)
802 * A GEqualFunc for g_hash_table_new()
808 * TRUE if both values are equal
810 static gboolean
gefRttKeyEqual(gconstpointer a
, gconstpointer b
)
812 const struct RttKey
* rkA
, * rkB
;
814 rkA
= (struct RttKey
*) a
;
815 rkB
= (struct RttKey
*) b
;
817 if (rkA
->saddr
== rkB
->saddr
&& rkA
->daddr
== rkB
->daddr
)
829 * Read a file contain minimum round trip time values and fill an array with
830 * them. The file is formatted as such:
831 * <host1 IP> <host2 IP> <RTT in milliseconds>
832 * ip's should be in dotted quad format
835 * rttInfo: double* rttInfo[RttKey], empty table, will be filled
836 * rttStream: stream from which to read
838 static void readRttInfo(GHashTable
* rttInfo
, FILE* rttStream
)
844 positionStream(rttStream
);
845 retval
= getline(&line
, &len
, rttStream
);
846 while(!feof(rttStream
))
848 struct RttKey
* rttKey
;
849 char saddrDQ
[20], daddrDQ
[20];
858 {saddrDQ
, offsetof(struct RttKey
, saddr
)},
859 {daddrDQ
, offsetof(struct RttKey
, daddr
)}
862 if (retval
== -1 && !feof(rttStream
))
864 g_error(strerror(errno
));
867 if (line
[retval
- 1] == '\n')
869 line
[retval
- 1]= '\0';
872 rtt
= malloc(sizeof(double));
873 retval
= sscanf(line
, " %19s %19s %lf %c", saddrDQ
, daddrDQ
, rtt
,
877 g_error(strerror(errno
));
879 else if (retval
!= 3)
881 g_error("Error parsing RTT file, line was '%s'", line
);
884 rttKey
= malloc(sizeof(struct RttKey
));
885 for (i
= 0; i
< sizeof(loopValues
) / sizeof(*loopValues
); i
++)
887 retval
= inet_aton(loopValues
[i
].dq
, &addr
);
890 g_error("Error converting address '%s'", loopValues
[i
].dq
);
892 *(uint32_t*) ((void*) rttKey
+ loopValues
[i
].offset
)=
897 g_debug("rttInfo, Inserting (%u, %u)->(%f)", rttKey
->saddr
,
898 rttKey
->daddr
, *rtt
);
899 g_hash_table_insert(rttInfo
, rttKey
, rtt
);
901 positionStream(rttStream
);
902 retval
= getline(&line
, &len
, rttStream
);
913 * Advance stream over empty space, empty lines and lines that begin with '#'
916 * stream: stream, at exit, will be over the first non-empty character
917 * of a line of be at EOF
919 static void positionStream(FILE* stream
)
928 firstChar
= fgetc(stream
);
929 if (firstChar
== (int) '#')
931 retval
= getline(&line
, &len
, stream
);
940 g_error(strerror(errno
));
944 else if (firstChar
== (int) '\n' || firstChar
== (int) ' ' ||
945 firstChar
== (int) '\t')
947 else if (firstChar
== EOF
)
956 retval
= ungetc(firstChar
, stream
);
959 g_error("Error: ungetc()");
971 * A GFunc for g_queue_foreach()
974 * data Event*, a UDP broadcast event
975 * user_data double*, the running sum
978 * Adds the time of the event to the sum
980 static void gfSum(gpointer data
, gpointer userData
)
982 Event
* event
= (Event
*) data
;
984 *(double*) userData
+= event
->wallTime
.seconds
+ event
->wallTime
.nanosec
/
990 * A GFunc for g_queue_foreach()
993 * data Event*, a UDP broadcast event
994 * user_data double*, the running sum
997 * Adds the square of the time of the event to the sum
999 static void gfSumSquares(gpointer data
, gpointer userData
)
1001 Event
* event
= (Event
*) data
;
1003 *(double*) userData
+= pow(event
->wallTime
.seconds
+ event
->wallTime
.nanosec
1009 * Figure out the bin in a histogram to which a value belongs.
1011 * This uses exponentially sized bins that go from 0 to infinity.
1014 * value: the value, must be >=0, or else expect the unexpected
1015 * (floating point exception)
1017 static unsigned int binNum(const double value
)
1025 double result
= floor(log(value
) / log(binBase
)) + (binNb
- 1);
1040 * Figure out the start of the interval of a bin in a histogram. The starting
1041 * value is included in the interval.
1043 * This uses exponentially sized bins that go from 0 to infinity.
1046 * binNum: bin number
1048 static double binStart(const unsigned int binNum
)
1050 g_assert(binNum
< binNb
);
1058 return pow(binBase
, (double) binNum
- (binNb
- 1));
1064 * Figure out the end of the interval of a bin in a histogram. The end value
1065 * is not included in the interval.
1067 * This uses exponentially sized bins that go from 0 to infinity.
1070 * binNum: bin number
1072 static double binEnd(const unsigned int binNum
)
1074 g_assert(binNum
< binNb
);
1078 return pow(binBase
, (double) binNum
- (binNb
- 2));
1088 * Write the analysis-specific graph lines in the gnuplot script.
1091 * stream: stream where to write the data
1092 * syncState: container for synchronization data
1093 * i: first trace number
1094 * j: second trace number, garanteed to be larger than i
1096 static void writeAnalysisGraphsPlotsEval(FILE* stream
, SyncState
* const
1097 syncState
, const unsigned int i
, const unsigned int j
)
1100 "\t\"analysis_eval_hrtt-%2$03d_and_%1$03d.data\" "
1101 "title \"RTT/2\" with boxes linetype 1 linewidth 3 "
1102 "linecolor rgb \"black\" fill transparent solid 0.75, \\\n"
1103 /*"\t\"analysis_eval_tt-%1$03d_to_%2$03d.data\" "
1104 "title \"%1$u to %2$u\" with boxes linetype 1 linewidth 3 "
1105 "linecolor rgb \"black\" fill transparent solid 0.5, \\\n"
1106 "\t\"analysis_eval_tt-%2$03d_to_%1$03d.data\" "
1107 "title \"%2$u to %1$u\" with boxes linetype 1 linewidth 3 "
1108 "linecolor rgb \"black\" fill transparent solid 0.25, \\\n"*/
1112 "\t\"analysis_eval_hrtt-%2$03d_and_%1$03d.data\" "
1113 "title \"RTT/2\" with linespoints linetype 1 linewidth 3 "
1114 "linecolor rgb \"black\", \\\n"
1115 "\t\"analysis_eval_tt-%1$03d_to_%2$03d.data\" "
1116 "title \"%1$u to %2$u\" with linespoints linetype 1 linewidth 3 "
1117 "linecolor rgb \"gray70\", \\\n"
1118 "\t\"analysis_eval_tt-%2$03d_to_%1$03d.data\" "
1119 "title \"%2$u to %1$u\" with linespoints linetype 1 linewidth 3 "
1120 "linecolor rgb \"gray40\", \\\n", i, j);
1126 * Write the analysis-specific options in the gnuplot script.
1129 * stream: stream where to write the data
1130 * syncState: container for synchronization data
1131 * i: first trace number
1132 * j: second trace number, garanteed to be larger than i
1134 static void writeAnalysisGraphsOptionsEval(FILE* stream
, SyncState
*
1135 const syncState
, const unsigned int i
, const unsigned int j
)
1138 "set xlabel \"Message Latency (s)\"\n"
1139 "set ylabel \"Proportion of messages per second\"\n");