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,
29 #include "event_analysis.h"
30 #include "sync_chain.h"
32 #include "event_matching_broadcast.h"
35 // Functions common to all matching modules
36 static void initMatchingBroadcast(SyncState
* const syncState
);
37 static void destroyMatchingBroadcast(SyncState
* const syncState
);
39 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
);
40 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
);
41 static void printMatchingStatsBroadcast(SyncState
* const syncState
);
42 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
43 unsigned int i
, const unsigned int j
);
45 // Functions specific to this module
46 static void registerMatchingBroadcast() __attribute__((constructor (101)));
48 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
);
50 static void openGraphDataFiles(SyncState
* const syncState
);
51 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
52 Broadcast
* const broadcast
);
53 static void closeGraphDataFiles(SyncState
* const syncState
);
56 static MatchingModule matchingModuleBroadcast
= {
58 .canMatch
[TCP
]= false,
60 .initMatching
= &initMatchingBroadcast
,
61 .destroyMatching
= &destroyMatchingBroadcast
,
62 .matchEvent
= &matchEventBroadcast
,
63 .finalizeMatching
= &finalizeMatchingBroadcast
,
64 .printMatchingStats
= &printMatchingStatsBroadcast
,
66 .writeTraceTimeForePlots
= &writeMatchingGraphsPlotsBroadcast
,
72 * Matching module registering function
74 static void registerMatchingBroadcast()
76 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
81 * Matching init function
83 * This function is called at the beginning of a synchronization run for a set
86 * Allocate the matching specific data structures
89 * syncState container for synchronization data.
90 * This function allocates these matchingData members:
94 static void initMatchingBroadcast(SyncState
* const syncState
)
96 MatchingDataBroadcast
* matchingData
;
98 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
99 syncState
->matchingData
= matchingData
;
101 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
102 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
104 if (syncState
->stats
)
106 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
110 matchingData
->stats
= NULL
;
113 if (syncState
->graphsStream
)
115 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
116 openGraphDataFiles(syncState
);
120 matchingData
->graphs
= NULL
;
126 * Matching destroy function
128 * Free the matching specific data structures
131 * syncState container for synchronization data.
132 * This function deallocates these matchingData members:
135 static void destroyMatchingBroadcast(SyncState
* const syncState
)
137 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
140 if (matchingData
== NULL
)
145 partialDestroyMatchingBroadcast(syncState
);
147 if (syncState
->stats
)
149 free(matchingData
->stats
);
152 if (syncState
->graphsStream
)
154 for (i
= 0; i
< syncState
->traceNb
; i
++)
156 free(matchingData
->graphs
->pointsNb
[i
]);
158 free(matchingData
->graphs
->pointsNb
);
159 free(matchingData
->graphs
);
162 free(syncState
->matchingData
);
163 syncState
->matchingData
= NULL
;
168 * Free some of the matching specific data structures
170 * This function can be called right after the events have been processed to
171 * free some data structures that are not needed for finalization.
174 * syncState container for synchronization data.
175 * This function deallocates these matchingData members:
178 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
180 MatchingDataBroadcast
* matchingData
;
182 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
184 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
189 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
190 matchingData
->pendingBroadcasts
= NULL
;
192 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
194 closeGraphDataFiles(syncState
);
200 * Try to match one broadcast with previously received broadcasts (based on
201 * the addresses and the fist bytes of data they contain). Deliver them to the
202 * analysis module once traceNb events have been accumulated for a broadcast.
205 * syncState container for synchronization data.
206 * event new event to match
208 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
210 MatchingDataBroadcast
* matchingData
;
212 g_assert(event
->type
== UDP
);
214 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
216 if (!event
->event
.udpEvent
->unicast
)
218 if (event
->event
.udpEvent
->direction
== IN
)
220 Broadcast
* broadcast
;
221 DatagramKey
* datagramKey
;
224 if (matchingData
->stats
)
226 matchingData
->stats
->totReceive
++;
229 /* if event in pendingBroadcasts:
230 * add it to its broadcast
231 * if this broadcast has traceNb events:
232 * remove it from pending and deliver it to analysis
233 * destroy the broadcast (and its elements)
235 * create a broadcast and add it to pending
239 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
240 event
->event
.udpEvent
->datagramKey
, (gpointer
)
241 &datagramKey
, (gpointer
) &broadcast
);
244 g_queue_push_tail(broadcast
->events
, event
);
245 if (broadcast
->events
->length
== syncState
->traceNb
)
247 if (matchingData
->stats
)
249 matchingData
->stats
->totComplete
++;
252 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
254 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
256 if (syncState
->graphsStream
)
258 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
260 destroyBroadcast(broadcast
);
265 broadcast
= malloc(sizeof(Broadcast
));
266 broadcast
->events
= g_queue_new();
267 g_queue_push_tail(broadcast
->events
, event
);
269 datagramKey
= malloc(sizeof(DatagramKey
));
270 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
272 g_hash_table_insert(matchingData
->pendingBroadcasts
,
273 datagramKey
, broadcast
);
278 if (matchingData
->stats
)
280 matchingData
->stats
->totTransmit
++;
283 event
->destroy(event
);
288 event
->destroy(event
);
295 * Call the partial matching destroyer and Obtain the factors from downstream
298 * syncState container for synchronization data.
301 * Factors[traceNb] synchronization factors for each trace
303 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
305 MatchingDataBroadcast
* matchingData
;
307 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
309 if (matchingData
->stats
)
311 matchingData
->stats
->totIncomplete
=
312 g_hash_table_size(matchingData
->pendingBroadcasts
);
315 partialDestroyMatchingBroadcast(syncState
);
317 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
322 * Print statistics related to matching. Must be called after
326 * syncState container for synchronization data.
328 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
330 MatchingDataBroadcast
* matchingData
;
332 if (!syncState
->stats
)
336 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
338 printf("Broadcast matching stats:\n");
339 printf("\ttotal broadcasts datagrams emitted: %u\n",
340 matchingData
->stats
->totTransmit
);
341 printf("\ttotal broadcasts datagrams received: %u\n",
342 matchingData
->stats
->totReceive
);
343 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
344 matchingData
->stats
->totComplete
);
345 printf("\ttotal broadcast groups missing some receptions: %u\n",
346 matchingData
->stats
->totIncomplete
);
347 if (matchingData
->stats
->totIncomplete
> 0)
349 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
350 (double) (matchingData
->stats
->totReceive
-
351 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
352 matchingData
->stats
->totIncomplete
);
358 * Create and open files used to store accuracy points to genereate graphs.
359 * Allocate and populate array to store file pointers and counters.
362 * syncState: container for synchronization data
364 static void openGraphDataFiles(SyncState
* const syncState
)
370 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
371 syncState
->matchingData
)->graphs
;
373 cwd
= changeToGraphsDir(syncState
->graphsDir
);
375 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
376 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
377 for (i
= 0; i
< syncState
->traceNb
; i
++)
379 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
380 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
381 for (j
= 0; j
< i
; j
++)
383 retval
= snprintf(name
, sizeof(name
),
384 "matching_broadcast-%03u_and_%03u.data", j
, i
);
385 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
386 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
388 g_error(strerror(errno
));
396 g_error(strerror(errno
));
403 * Calculate and write points used to generate graphs
406 * graphs: structure containing array of file pointers and counters
407 * broadcast: broadcast for which to write the points
409 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
410 Broadcast
* const broadcast
)
414 unsigned int eventNb
= broadcast
->events
->length
;
416 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
417 g_queue_foreach(broadcast
->events
, &gfAddEventToArray
, events
);
419 for (i
= 0; i
< eventNb
; i
++)
421 for (j
= 0; j
< eventNb
; j
++)
423 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
424 g_array_index(events
, Event
*, j
);
426 if (eventI
->traceNum
< eventJ
->traceNum
)
428 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
429 "%20" PRIu64
" %20.9f\n", eventI
->cpuTime
,
430 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
431 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
436 g_array_free(events
, TRUE
);
441 * Close files used to store accuracy points to genereate graphs. Deallocate
442 * array to store file pointers (but not array for counters).
445 * syncState: container for synchronization data
447 static void closeGraphDataFiles(SyncState
* const syncState
)
450 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
451 syncState
->matchingData
)->graphs
;
454 if (graphs
->accuracyPoints
== NULL
)
459 for (i
= 0; i
< syncState
->traceNb
; i
++)
461 for (j
= 0; j
< i
; j
++)
463 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
466 g_error(strerror(errno
));
469 free(graphs
->accuracyPoints
[i
]);
471 free(graphs
->accuracyPoints
);
473 graphs
->accuracyPoints
= NULL
;
478 * Write the matching-specific graph lines in the gnuplot script.
481 * syncState: container for synchronization data
482 * i: first trace number
483 * j: second trace number, garanteed to be larger than i
485 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
486 unsigned int i
, const unsigned int j
)
488 if (((MatchingDataBroadcast
*)
489 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
491 fprintf(syncState
->graphsStream
,
492 "\t\"matching_broadcast-%03d_and_%03d.data\" "
493 "title \"Broadcast differential delays\" with points "
494 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,