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 partialDestroyMatchingBroadcast(SyncState
* const syncState
);
48 static void openGraphDataFiles(SyncState
* const syncState
);
49 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
50 Broadcast
* const broadcast
);
51 static void closeGraphDataFiles(SyncState
* const syncState
);
54 static MatchingModule matchingModuleBroadcast
= {
56 .canMatch
[TCP
]= false,
58 .initMatching
= &initMatchingBroadcast
,
59 .destroyMatching
= &destroyMatchingBroadcast
,
60 .matchEvent
= &matchEventBroadcast
,
61 .finalizeMatching
= &finalizeMatchingBroadcast
,
62 .printMatchingStats
= &printMatchingStatsBroadcast
,
64 .writeTraceTimeForePlots
= &writeMatchingGraphsPlotsBroadcast
,
70 * Matching module registering function
72 void registerMatchingBroadcast()
74 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
79 * Matching init function
81 * This function is called at the beginning of a synchronization run for a set
84 * Allocate the matching specific data structures
87 * syncState container for synchronization data.
88 * This function allocates these matchingData members:
92 static void initMatchingBroadcast(SyncState
* const syncState
)
94 MatchingDataBroadcast
* matchingData
;
96 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
97 syncState
->matchingData
= matchingData
;
99 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
100 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
102 if (syncState
->stats
)
104 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
108 matchingData
->stats
= NULL
;
111 if (syncState
->graphsStream
)
113 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
114 openGraphDataFiles(syncState
);
118 matchingData
->graphs
= NULL
;
124 * Matching destroy function
126 * Free the matching specific data structures
129 * syncState container for synchronization data.
130 * This function deallocates these matchingData members:
133 static void destroyMatchingBroadcast(SyncState
* const syncState
)
135 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
138 if (matchingData
== NULL
)
143 partialDestroyMatchingBroadcast(syncState
);
145 if (syncState
->stats
)
147 free(matchingData
->stats
);
150 if (syncState
->graphsStream
)
152 for (i
= 0; i
< syncState
->traceNb
; i
++)
154 free(matchingData
->graphs
->pointsNb
[i
]);
156 free(matchingData
->graphs
->pointsNb
);
157 free(matchingData
->graphs
);
160 free(syncState
->matchingData
);
161 syncState
->matchingData
= NULL
;
166 * Free some of the matching specific data structures
168 * This function can be called right after the events have been processed to
169 * free some data structures that are not needed for finalization.
172 * syncState container for synchronization data.
173 * This function deallocates these matchingData members:
176 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
178 MatchingDataBroadcast
* matchingData
;
180 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
182 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
187 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
188 matchingData
->pendingBroadcasts
= NULL
;
190 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
192 closeGraphDataFiles(syncState
);
198 * Try to match one broadcast with previously received broadcasts (based on
199 * the addresses and the fist bytes of data they contain). Deliver them to the
200 * analysis module once traceNb events have been accumulated for a broadcast.
203 * syncState container for synchronization data.
204 * event new event to match
206 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
208 MatchingDataBroadcast
* matchingData
;
210 g_assert(event
->type
== UDP
);
212 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
214 if (!event
->event
.udpEvent
->unicast
)
216 if (event
->event
.udpEvent
->direction
== IN
)
218 Broadcast
* broadcast
;
219 DatagramKey
* datagramKey
;
222 if (matchingData
->stats
)
224 matchingData
->stats
->totReceive
++;
227 /* if event in pendingBroadcasts:
228 * add it to its broadcast
229 * if this broadcast has traceNb events:
230 * remove it from pending and deliver it to analysis
231 * destroy the broadcast (and its elements)
233 * create a broadcast and add it to pending
237 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
238 event
->event
.udpEvent
->datagramKey
, (gpointer
)
239 &datagramKey
, (gpointer
) &broadcast
);
242 g_queue_push_tail(broadcast
->events
, event
);
243 if (broadcast
->events
->length
== syncState
->traceNb
)
245 if (matchingData
->stats
)
247 matchingData
->stats
->totComplete
++;
250 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
252 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
254 if (syncState
->graphsStream
)
256 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
258 destroyBroadcast(broadcast
);
263 broadcast
= malloc(sizeof(Broadcast
));
264 broadcast
->events
= g_queue_new();
265 g_queue_push_tail(broadcast
->events
, event
);
267 datagramKey
= malloc(sizeof(DatagramKey
));
268 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
270 g_hash_table_insert(matchingData
->pendingBroadcasts
,
271 datagramKey
, broadcast
);
276 if (matchingData
->stats
)
278 matchingData
->stats
->totTransmit
++;
281 event
->destroy(event
);
286 event
->destroy(event
);
293 * Call the partial matching destroyer and Obtain the factors from downstream
296 * syncState container for synchronization data.
299 * Factors[traceNb] synchronization factors for each trace
301 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
303 MatchingDataBroadcast
* matchingData
;
305 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
307 if (matchingData
->stats
)
309 matchingData
->stats
->totIncomplete
=
310 g_hash_table_size(matchingData
->pendingBroadcasts
);
313 partialDestroyMatchingBroadcast(syncState
);
315 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
320 * Print statistics related to matching. Must be called after
324 * syncState container for synchronization data.
326 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
328 MatchingDataBroadcast
* matchingData
;
330 if (!syncState
->stats
)
334 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
336 printf("Broadcast matching stats:\n");
337 printf("\ttotal broadcasts datagrams emitted: %u\n",
338 matchingData
->stats
->totTransmit
);
339 printf("\ttotal broadcasts datagrams received: %u\n",
340 matchingData
->stats
->totReceive
);
341 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
342 matchingData
->stats
->totComplete
);
343 printf("\ttotal broadcast groups missing some receptions: %u\n",
344 matchingData
->stats
->totIncomplete
);
345 if (matchingData
->stats
->totIncomplete
> 0)
347 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
348 (double) (matchingData
->stats
->totReceive
-
349 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
350 matchingData
->stats
->totIncomplete
);
356 * Create and open files used to store accuracy points to genereate graphs.
357 * Allocate and populate array to store file pointers and counters.
360 * syncState: container for synchronization data
362 static void openGraphDataFiles(SyncState
* const syncState
)
368 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
369 syncState
->matchingData
)->graphs
;
371 cwd
= changeToGraphsDir(syncState
->graphsDir
);
373 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
374 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
375 for (i
= 0; i
< syncState
->traceNb
; i
++)
377 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
378 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
379 for (j
= 0; j
< i
; j
++)
381 retval
= snprintf(name
, sizeof(name
),
382 "matching_broadcast-%03u_and_%03u.data", j
, i
);
383 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
384 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
386 g_error(strerror(errno
));
394 g_error(strerror(errno
));
401 * Calculate and write points used to generate graphs
404 * graphs: structure containing array of file pointers and counters
405 * broadcast: broadcast for which to write the points
407 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
408 Broadcast
* const broadcast
)
412 unsigned int eventNb
= broadcast
->events
->length
;
414 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
415 g_queue_foreach(broadcast
->events
, &gfAddEventToArray
, events
);
417 for (i
= 0; i
< eventNb
; i
++)
419 for (j
= 0; j
< eventNb
; j
++)
421 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
422 g_array_index(events
, Event
*, j
);
424 if (eventI
->traceNum
< eventJ
->traceNum
)
426 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
427 "%20" PRIu64
" %20.9f\n", eventI
->cpuTime
,
428 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
429 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
434 g_array_free(events
, TRUE
);
439 * Close files used to store accuracy points to genereate graphs. Deallocate
440 * array to store file pointers (but not array for counters).
443 * syncState: container for synchronization data
445 static void closeGraphDataFiles(SyncState
* const syncState
)
448 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
449 syncState
->matchingData
)->graphs
;
452 if (graphs
->accuracyPoints
== NULL
)
457 for (i
= 0; i
< syncState
->traceNb
; i
++)
459 for (j
= 0; j
< i
; j
++)
461 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
464 g_error(strerror(errno
));
467 free(graphs
->accuracyPoints
[i
]);
469 free(graphs
->accuracyPoints
);
471 graphs
->accuracyPoints
= NULL
;
476 * Write the matching-specific graph lines in the gnuplot script.
479 * syncState: container for synchronization data
480 * i: first trace number
481 * j: second trace number, garanteed to be larger than i
483 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
484 unsigned int i
, const unsigned int j
)
486 if (((MatchingDataBroadcast
*)
487 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
489 fprintf(syncState
->graphsStream
,
490 "\t\"matching_broadcast-%03d_and_%03d.data\" "
491 "title \"Broadcast differential delays\" with points "
492 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,