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,
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 GArray
* 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 registerMatchingBroadcast() __attribute__((constructor (101)));
47 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
);
49 static void openGraphDataFiles(SyncState
* const syncState
);
50 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
51 Broadcast
* const broadcast
);
52 static void closeGraphDataFiles(SyncState
* const syncState
);
55 static MatchingModule matchingModuleBroadcast
= {
57 .canMatch
[TCP
]= false,
59 .initMatching
= &initMatchingBroadcast
,
60 .destroyMatching
= &destroyMatchingBroadcast
,
61 .matchEvent
= &matchEventBroadcast
,
62 .finalizeMatching
= &finalizeMatchingBroadcast
,
63 .printMatchingStats
= &printMatchingStatsBroadcast
,
65 .writeTraceTimeForePlots
= &writeMatchingGraphsPlotsBroadcast
,
71 * Matching module registering function
73 static void registerMatchingBroadcast()
75 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
80 * Matching init function
82 * This function is called at the beginning of a synchronization run for a set
85 * Allocate the matching specific data structures
88 * syncState container for synchronization data.
89 * This function allocates these matchingData members:
93 static void initMatchingBroadcast(SyncState
* const syncState
)
95 MatchingDataBroadcast
* matchingData
;
97 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
98 syncState
->matchingData
= matchingData
;
100 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
101 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
103 if (syncState
->stats
)
105 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
109 matchingData
->stats
= NULL
;
112 if (syncState
->graphsStream
)
114 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
115 openGraphDataFiles(syncState
);
119 matchingData
->graphs
= NULL
;
125 * Matching destroy function
127 * Free the matching specific data structures
130 * syncState container for synchronization data.
131 * This function deallocates these matchingData members:
134 static void destroyMatchingBroadcast(SyncState
* const syncState
)
136 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
139 if (matchingData
== NULL
)
144 partialDestroyMatchingBroadcast(syncState
);
146 if (syncState
->stats
)
148 free(matchingData
->stats
);
151 if (syncState
->graphsStream
)
153 for (i
= 0; i
< syncState
->traceNb
; i
++)
155 free(matchingData
->graphs
->pointsNb
[i
]);
157 free(matchingData
->graphs
->pointsNb
);
158 free(matchingData
->graphs
);
161 free(syncState
->matchingData
);
162 syncState
->matchingData
= NULL
;
167 * Free some of the matching specific data structures
169 * This function can be called right after the events have been processed to
170 * free some data structures that are not needed for finalization.
173 * syncState container for synchronization data.
174 * This function deallocates these matchingData members:
177 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
179 MatchingDataBroadcast
* matchingData
;
181 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
183 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
188 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
189 matchingData
->pendingBroadcasts
= NULL
;
191 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
193 closeGraphDataFiles(syncState
);
199 * Try to match one broadcast with previously received broadcasts (based on
200 * the addresses and the fist bytes of data they contain). Deliver them to the
201 * analysis module once traceNb events have been accumulated for a broadcast.
204 * syncState container for synchronization data.
205 * event new event to match
207 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
209 MatchingDataBroadcast
* matchingData
;
211 g_assert(event
->type
== UDP
);
213 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
215 if (!event
->event
.udpEvent
->unicast
)
217 if (event
->event
.udpEvent
->direction
== IN
)
219 Broadcast
* broadcast
;
220 DatagramKey
* datagramKey
;
223 if (matchingData
->stats
)
225 matchingData
->stats
->totReceive
++;
228 /* if event in pendingBroadcasts:
229 * add it to its broadcast
230 * if this broadcast has traceNb events:
231 * remove it from pending and deliver it to analysis
232 * destroy the broadcast (and its elements)
234 * create a broadcast and add it to pending
238 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
239 event
->event
.udpEvent
->datagramKey
, (gpointer
)
240 &datagramKey
, (gpointer
) &broadcast
);
243 g_queue_push_tail(broadcast
->events
, event
);
244 if (broadcast
->events
->length
== syncState
->traceNb
)
246 if (matchingData
->stats
)
248 matchingData
->stats
->totComplete
++;
251 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
253 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
255 if (syncState
->graphsStream
)
257 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
259 destroyBroadcast(broadcast
);
264 broadcast
= malloc(sizeof(Broadcast
));
265 broadcast
->events
= g_queue_new();
266 g_queue_push_tail(broadcast
->events
, event
);
268 datagramKey
= malloc(sizeof(DatagramKey
));
269 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
271 g_hash_table_insert(matchingData
->pendingBroadcasts
,
272 datagramKey
, broadcast
);
277 if (matchingData
->stats
)
279 matchingData
->stats
->totTransmit
++;
282 event
->destroy(event
);
287 event
->destroy(event
);
294 * Call the partial matching destroyer and Obtain the factors from downstream
297 * syncState container for synchronization data.
300 * Factors[traceNb] synchronization factors for each trace
302 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
304 MatchingDataBroadcast
* matchingData
;
306 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
308 if (matchingData
->stats
)
310 matchingData
->stats
->totIncomplete
=
311 g_hash_table_size(matchingData
->pendingBroadcasts
);
314 partialDestroyMatchingBroadcast(syncState
);
316 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
321 * Print statistics related to matching. Must be called after
325 * syncState container for synchronization data.
327 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
329 MatchingDataBroadcast
* matchingData
;
331 if (!syncState
->stats
)
335 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
337 printf("Broadcast matching stats:\n");
338 printf("\ttotal broadcasts datagrams emitted: %u\n",
339 matchingData
->stats
->totTransmit
);
340 printf("\ttotal broadcasts datagrams received: %u\n",
341 matchingData
->stats
->totReceive
);
342 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
343 matchingData
->stats
->totComplete
);
344 printf("\ttotal broadcast groups missing some receptions: %u\n",
345 matchingData
->stats
->totIncomplete
);
346 if (matchingData
->stats
->totIncomplete
> 0)
348 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
349 (double) (matchingData
->stats
->totReceive
-
350 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
351 matchingData
->stats
->totIncomplete
);
357 * Create and open files used to store accuracy points to genereate graphs.
358 * Allocate and populate array to store file pointers and counters.
361 * syncState: container for synchronization data
363 static void openGraphDataFiles(SyncState
* const syncState
)
369 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
370 syncState
->matchingData
)->graphs
;
372 cwd
= changeToGraphsDir(syncState
->graphsDir
);
374 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
375 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
376 for (i
= 0; i
< syncState
->traceNb
; i
++)
378 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
379 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
380 for (j
= 0; j
< i
; j
++)
382 retval
= snprintf(name
, sizeof(name
),
383 "matching_broadcast-%03u_and_%03u.data", j
, i
);
384 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
385 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
387 g_error(strerror(errno
));
395 g_error(strerror(errno
));
402 * Calculate and write points used to generate graphs
405 * graphs: structure containing array of file pointers and counters
406 * broadcast: broadcast for which to write the points
408 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
409 Broadcast
* const broadcast
)
413 unsigned int eventNb
= broadcast
->events
->length
;
415 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
416 g_queue_foreach(broadcast
->events
, &gfAddEventToArray
, events
);
418 for (i
= 0; i
< eventNb
; i
++)
420 for (j
= 0; j
< eventNb
; j
++)
422 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
423 g_array_index(events
, Event
*, j
);
425 if (eventI
->traceNum
< eventJ
->traceNum
)
427 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
428 "%20llu %20.9f\n", eventI
->cpuTime
,
429 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
430 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
435 g_array_free(events
, TRUE
);
440 * Close files used to store accuracy points to genereate graphs. Deallocate
441 * array to store file pointers (but not array for counters).
444 * syncState: container for synchronization data
446 static void closeGraphDataFiles(SyncState
* const syncState
)
449 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
450 syncState
->matchingData
)->graphs
;
453 if (graphs
->accuracyPoints
== NULL
)
458 for (i
= 0; i
< syncState
->traceNb
; i
++)
460 for (j
= 0; j
< i
; j
++)
462 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
465 g_error(strerror(errno
));
468 free(graphs
->accuracyPoints
[i
]);
470 free(graphs
->accuracyPoints
);
472 graphs
->accuracyPoints
= NULL
;
477 * Write the matching-specific graph lines in the gnuplot script.
480 * syncState: container for synchronization data
481 * i: first trace number
482 * j: second trace number, garanteed to be larger than i
484 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
485 unsigned int i
, const unsigned int j
)
487 if (((MatchingDataBroadcast
*)
488 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
490 fprintf(syncState
->graphsStream
,
491 "\t\"matching_broadcast-%03d_and_%03d.data\" "
492 "title \"Broadcast differential delays\" with points "
493 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,