1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
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.
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.
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/>.
28 #include "event_analysis.h"
29 #include "sync_chain.h"
31 #include "event_matching_broadcast.h"
34 // Functions common to all matching modules
35 static void initMatchingBroadcast(SyncState
* const syncState
);
36 static void destroyMatchingBroadcast(SyncState
* const syncState
);
38 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
);
39 static AllFactors
* finalizeMatchingBroadcast(SyncState
* const syncState
);
40 static void printMatchingStatsBroadcast(SyncState
* const syncState
);
41 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
42 unsigned int i
, const unsigned int j
);
44 // Functions specific to this module
45 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
);
47 static void openGraphDataFiles(SyncState
* const syncState
);
48 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
49 Broadcast
* const broadcast
);
50 static void closeGraphDataFiles(SyncState
* const syncState
);
53 static MatchingModule matchingModuleBroadcast
= {
55 .canMatch
[TCP
]= false,
57 .initMatching
= &initMatchingBroadcast
,
58 .destroyMatching
= &destroyMatchingBroadcast
,
59 .matchEvent
= &matchEventBroadcast
,
60 .finalizeMatching
= &finalizeMatchingBroadcast
,
61 .printMatchingStats
= &printMatchingStatsBroadcast
,
63 .writeTraceTimeForePlots
= &writeMatchingGraphsPlotsBroadcast
,
69 * Matching module registering function
71 void registerMatchingBroadcast()
73 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
78 * Matching init function
80 * This function is called at the beginning of a synchronization run for a set
83 * Allocate the matching specific data structures
86 * syncState container for synchronization data.
87 * This function allocates these matchingData members:
91 static void initMatchingBroadcast(SyncState
* const syncState
)
93 MatchingDataBroadcast
* matchingData
;
95 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
96 syncState
->matchingData
= matchingData
;
98 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
99 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
101 if (syncState
->stats
)
103 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
107 matchingData
->stats
= NULL
;
110 if (syncState
->graphsStream
)
112 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
113 openGraphDataFiles(syncState
);
117 matchingData
->graphs
= NULL
;
123 * Matching destroy function
125 * Free the matching specific data structures
128 * syncState container for synchronization data.
129 * This function deallocates these matchingData members:
132 static void destroyMatchingBroadcast(SyncState
* const syncState
)
134 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
137 if (matchingData
== NULL
)
142 partialDestroyMatchingBroadcast(syncState
);
144 if (syncState
->stats
)
146 free(matchingData
->stats
);
149 if (syncState
->graphsStream
)
151 for (i
= 0; i
< syncState
->traceNb
; i
++)
153 free(matchingData
->graphs
->pointsNb
[i
]);
155 free(matchingData
->graphs
->pointsNb
);
156 free(matchingData
->graphs
);
159 free(syncState
->matchingData
);
160 syncState
->matchingData
= NULL
;
165 * Free some of the matching specific data structures
167 * This function can be called right after the events have been processed to
168 * free some data structures that are not needed for finalization.
171 * syncState container for synchronization data.
172 * This function deallocates these matchingData members:
175 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
177 MatchingDataBroadcast
* matchingData
;
179 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
181 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
186 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
187 matchingData
->pendingBroadcasts
= NULL
;
189 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
191 closeGraphDataFiles(syncState
);
197 * Try to match one broadcast with previously received broadcasts (based on
198 * the addresses and the fist bytes of data they contain). Deliver them to the
199 * analysis module once traceNb events have been accumulated for a broadcast.
202 * syncState container for synchronization data.
203 * event new event to match
205 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
207 MatchingDataBroadcast
* matchingData
;
209 g_assert(event
->type
== UDP
);
211 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
213 if (!event
->event
.udpEvent
->unicast
)
215 if (event
->event
.udpEvent
->direction
== IN
)
217 Broadcast
* broadcast
;
218 DatagramKey
* datagramKey
;
221 if (matchingData
->stats
)
223 matchingData
->stats
->totReceive
++;
226 /* if event in pendingBroadcasts:
227 * add it to its broadcast
228 * if this broadcast has traceNb events:
229 * remove it from pending and deliver it to analysis
230 * destroy the broadcast (and its elements)
232 * create a broadcast and add it to pending
236 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
237 event
->event
.udpEvent
->datagramKey
, (gpointer
)
238 &datagramKey
, (gpointer
) &broadcast
);
241 g_queue_push_tail(broadcast
->events
, event
);
242 if (broadcast
->events
->length
== syncState
->traceNb
)
244 if (matchingData
->stats
)
246 matchingData
->stats
->totComplete
++;
249 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
251 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
253 if (syncState
->graphsStream
)
255 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
257 destroyBroadcast(broadcast
);
262 broadcast
= malloc(sizeof(Broadcast
));
263 broadcast
->events
= g_queue_new();
264 g_queue_push_tail(broadcast
->events
, event
);
266 datagramKey
= malloc(sizeof(DatagramKey
));
267 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
269 g_hash_table_insert(matchingData
->pendingBroadcasts
,
270 datagramKey
, broadcast
);
275 if (matchingData
->stats
)
277 matchingData
->stats
->totTransmit
++;
280 event
->destroy(event
);
285 event
->destroy(event
);
292 * Call the partial matching destroyer and Obtain the factors from downstream
295 * syncState container for synchronization data.
298 * AllFactors* synchronization factors for each trace pair
300 static AllFactors
* finalizeMatchingBroadcast(SyncState
* const syncState
)
302 MatchingDataBroadcast
* matchingData
;
304 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
306 if (matchingData
->stats
)
308 matchingData
->stats
->totIncomplete
=
309 g_hash_table_size(matchingData
->pendingBroadcasts
);
312 partialDestroyMatchingBroadcast(syncState
);
314 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
319 * Print statistics related to matching. Must be called after
323 * syncState container for synchronization data.
325 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
327 MatchingDataBroadcast
* matchingData
;
329 if (!syncState
->stats
)
333 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
335 printf("Broadcast matching stats:\n");
336 printf("\ttotal broadcasts datagrams emitted: %u\n",
337 matchingData
->stats
->totTransmit
);
338 printf("\ttotal broadcasts datagrams received: %u\n",
339 matchingData
->stats
->totReceive
);
340 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
341 matchingData
->stats
->totComplete
);
342 printf("\ttotal broadcast groups missing some receptions: %u\n",
343 matchingData
->stats
->totIncomplete
);
344 if (matchingData
->stats
->totIncomplete
> 0)
346 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
347 (double) (matchingData
->stats
->totReceive
-
348 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
349 matchingData
->stats
->totIncomplete
);
355 * Create and open files used to store accuracy points to genereate graphs.
356 * Allocate and populate array to store file pointers and counters.
359 * syncState: container for synchronization data
361 static void openGraphDataFiles(SyncState
* const syncState
)
367 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
368 syncState
->matchingData
)->graphs
;
370 cwd
= changeToGraphsDir(syncState
->graphsDir
);
372 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
373 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
374 for (i
= 0; i
< syncState
->traceNb
; i
++)
376 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
377 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
378 for (j
= 0; j
< i
; j
++)
380 retval
= snprintf(name
, sizeof(name
),
381 "matching_broadcast-%03u_and_%03u.data", j
, i
);
382 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
383 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
385 g_error("%s", strerror(errno
));
393 g_error("%s", strerror(errno
));
400 * Calculate and write points used to generate graphs
403 * graphs: structure containing array of file pointers and counters
404 * broadcast: broadcast for which to write the points
406 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
407 Broadcast
* const broadcast
)
411 unsigned int eventNb
= broadcast
->events
->length
;
413 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
414 g_queue_foreach(broadcast
->events
, &gfAddEventToArray
, events
);
416 for (i
= 0; i
< eventNb
; i
++)
418 for (j
= 0; j
< eventNb
; j
++)
420 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
421 g_array_index(events
, Event
*, j
);
423 if (eventI
->traceNum
< eventJ
->traceNum
)
425 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
426 "%20" PRIu64
" %20.9f\n", eventI
->cpuTime
,
427 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
428 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
433 g_array_free(events
, TRUE
);
438 * Close files used to store accuracy points to genereate graphs. Deallocate
439 * array to store file pointers (but not array for counters).
442 * syncState: container for synchronization data
444 static void closeGraphDataFiles(SyncState
* const syncState
)
447 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
448 syncState
->matchingData
)->graphs
;
451 if (graphs
->accuracyPoints
== NULL
)
456 for (i
= 0; i
< syncState
->traceNb
; i
++)
458 for (j
= 0; j
< i
; j
++)
460 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
463 g_error("%s", strerror(errno
));
466 free(graphs
->accuracyPoints
[i
]);
468 free(graphs
->accuracyPoints
);
470 graphs
->accuracyPoints
= NULL
;
475 * Write the matching-specific graph lines in the gnuplot script.
478 * syncState: container for synchronization data
479 * i: first trace number
480 * j: second trace number, garanteed to be larger than i
482 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
483 unsigned int i
, const unsigned int j
)
485 if (((MatchingDataBroadcast
*)
486 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
488 fprintf(syncState
->graphsStream
,
489 "\t\"matching_broadcast-%03d_and_%03d.data\" "
490 "title \"Broadcast differential delays\" with points "
491 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,