ff45a8a71b7729848a6ef61d2918629211063482
[lttv.git] / lttv / lttv / sync / event_matching_broadcast.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "event_analysis.h"
29 #include "sync_chain.h"
30
31 #include "event_matching_broadcast.h"
32
33
34 // Functions common to all matching modules
35 static void initMatchingBroadcast(SyncState* const syncState);
36 static void destroyMatchingBroadcast(SyncState* const syncState);
37
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);
43
44 // Functions specific to this module
45 static void registerMatchingBroadcast() __attribute__((constructor (101)));
46
47 static void partialDestroyMatchingBroadcast(SyncState* const syncState);
48
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);
53
54
55 static MatchingModule matchingModuleBroadcast = {
56 .name= "broadcast",
57 .canMatch[TCP]= false,
58 .canMatch[UDP]= true,
59 .initMatching= &initMatchingBroadcast,
60 .destroyMatching= &destroyMatchingBroadcast,
61 .matchEvent= &matchEventBroadcast,
62 .finalizeMatching= &finalizeMatchingBroadcast,
63 .printMatchingStats= &printMatchingStatsBroadcast,
64 .graphFunctions= {
65 .writeTraceTimeForePlots= &writeMatchingGraphsPlotsBroadcast,
66 }
67 };
68
69
70 /*
71 * Matching module registering function
72 */
73 static void registerMatchingBroadcast()
74 {
75 g_queue_push_tail(&matchingModules, &matchingModuleBroadcast);
76 }
77
78
79 /*
80 * Matching init function
81 *
82 * This function is called at the beginning of a synchronization run for a set
83 * of traces.
84 *
85 * Allocate the matching specific data structures
86 *
87 * Args:
88 * syncState container for synchronization data.
89 * This function allocates these matchingData members:
90 * pendingBroadcasts
91 * stats
92 */
93 static void initMatchingBroadcast(SyncState* const syncState)
94 {
95 MatchingDataBroadcast* matchingData;
96
97 matchingData= malloc(sizeof(MatchingDataBroadcast));
98 syncState->matchingData= matchingData;
99
100 matchingData->pendingBroadcasts= g_hash_table_new_full(&ghfDatagramKeyHash,
101 &gefDatagramKeyEqual, &gdnDestroyDatagramKey, &gdnDestroyBroadcast);
102
103 if (syncState->stats)
104 {
105 matchingData->stats= calloc(1, sizeof(MatchingStatsBroadcast));
106 }
107 else
108 {
109 matchingData->stats= NULL;
110 }
111
112 if (syncState->graphsStream)
113 {
114 matchingData->graphs= malloc(sizeof(MatchingGraphsBroadcast));
115 openGraphDataFiles(syncState);
116 }
117 else
118 {
119 matchingData->graphs= NULL;
120 }
121 }
122
123
124 /*
125 * Matching destroy function
126 *
127 * Free the matching specific data structures
128 *
129 * Args:
130 * syncState container for synchronization data.
131 * This function deallocates these matchingData members:
132 * stats
133 */
134 static void destroyMatchingBroadcast(SyncState* const syncState)
135 {
136 MatchingDataBroadcast* matchingData= syncState->matchingData;
137 unsigned int i;
138
139 if (matchingData == NULL)
140 {
141 return;
142 }
143
144 partialDestroyMatchingBroadcast(syncState);
145
146 if (syncState->stats)
147 {
148 free(matchingData->stats);
149 }
150
151 if (syncState->graphsStream)
152 {
153 for (i= 0; i < syncState->traceNb; i++)
154 {
155 free(matchingData->graphs->pointsNb[i]);
156 }
157 free(matchingData->graphs->pointsNb);
158 free(matchingData->graphs);
159 }
160
161 free(syncState->matchingData);
162 syncState->matchingData= NULL;
163 }
164
165
166 /*
167 * Free some of the matching specific data structures
168 *
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.
171 *
172 * Args:
173 * syncState container for synchronization data.
174 * This function deallocates these matchingData members:
175 * pendingBroadcasts
176 */
177 static void partialDestroyMatchingBroadcast(SyncState* const syncState)
178 {
179 MatchingDataBroadcast* matchingData;
180
181 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
182
183 if (matchingData == NULL || matchingData->pendingBroadcasts == NULL)
184 {
185 return;
186 }
187
188 g_hash_table_destroy(matchingData->pendingBroadcasts);
189 matchingData->pendingBroadcasts= NULL;
190
191 if (syncState->graphsStream && matchingData->graphs->accuracyPoints)
192 {
193 closeGraphDataFiles(syncState);
194 }
195 }
196
197
198 /*
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.
202 *
203 * Args:
204 * syncState container for synchronization data.
205 * event new event to match
206 */
207 static void matchEventBroadcast(SyncState* const syncState, Event* const event)
208 {
209 MatchingDataBroadcast* matchingData;
210
211 g_assert(event->type == UDP);
212
213 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
214
215 if (!event->event.udpEvent->unicast)
216 {
217 if (event->event.udpEvent->direction == IN)
218 {
219 Broadcast* broadcast;
220 DatagramKey* datagramKey;
221 gboolean result;
222
223 if (matchingData->stats)
224 {
225 matchingData->stats->totReceive++;
226 }
227
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)
233 * else:
234 * create a broadcast and add it to pending
235 */
236
237 result=
238 g_hash_table_lookup_extended(matchingData->pendingBroadcasts,
239 event->event.udpEvent->datagramKey, (gpointer)
240 &datagramKey, (gpointer) &broadcast);
241 if (result)
242 {
243 g_queue_push_tail(broadcast->events, event);
244 if (broadcast->events->length == syncState->traceNb)
245 {
246 if (matchingData->stats)
247 {
248 matchingData->stats->totComplete++;
249 }
250
251 g_hash_table_steal(matchingData->pendingBroadcasts, datagramKey);
252 free(datagramKey);
253 syncState->analysisModule->analyzeBroadcast(syncState, broadcast);
254
255 if (syncState->graphsStream)
256 {
257 writeAccuracyPoints(matchingData->graphs, broadcast);
258 }
259 destroyBroadcast(broadcast);
260 }
261 }
262 else
263 {
264 broadcast= malloc(sizeof(Broadcast));
265 broadcast->events= g_queue_new();
266 g_queue_push_tail(broadcast->events, event);
267
268 datagramKey= malloc(sizeof(DatagramKey));
269 *datagramKey= *event->event.udpEvent->datagramKey;
270
271 g_hash_table_insert(matchingData->pendingBroadcasts,
272 datagramKey, broadcast);
273 }
274 }
275 else
276 {
277 if (matchingData->stats)
278 {
279 matchingData->stats->totTransmit++;
280 }
281
282 event->destroy(event);
283 }
284 }
285 else
286 {
287 event->destroy(event);
288 }
289
290 }
291
292
293 /*
294 * Call the partial matching destroyer and Obtain the factors from downstream
295 *
296 * Args:
297 * syncState container for synchronization data.
298 *
299 * Returns:
300 * Factors[traceNb] synchronization factors for each trace
301 */
302 static GArray* finalizeMatchingBroadcast(SyncState* const syncState)
303 {
304 MatchingDataBroadcast* matchingData;
305
306 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
307
308 if (matchingData->stats)
309 {
310 matchingData->stats->totIncomplete=
311 g_hash_table_size(matchingData->pendingBroadcasts);
312 }
313
314 partialDestroyMatchingBroadcast(syncState);
315
316 return syncState->analysisModule->finalizeAnalysis(syncState);
317 }
318
319
320 /*
321 * Print statistics related to matching. Must be called after
322 * finalizeMatching.
323 *
324 * Args:
325 * syncState container for synchronization data.
326 */
327 static void printMatchingStatsBroadcast(SyncState* const syncState)
328 {
329 MatchingDataBroadcast* matchingData;
330
331 if (!syncState->stats)
332 {
333 return;
334 }
335 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
336
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)
347 {
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);
352 }
353 }
354
355
356 /*
357 * Create and open files used to store accuracy points to genereate graphs.
358 * Allocate and populate array to store file pointers and counters.
359 *
360 * Args:
361 * syncState: container for synchronization data
362 */
363 static void openGraphDataFiles(SyncState* const syncState)
364 {
365 unsigned int i, j;
366 int retval;
367 char* cwd;
368 char name[36];
369 MatchingGraphsBroadcast* graphs= ((MatchingDataBroadcast*)
370 syncState->matchingData)->graphs;
371
372 cwd= changeToGraphDir(syncState->graphsDir);
373
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++)
377 {
378 graphs->accuracyPoints[i]= malloc(i * sizeof(FILE*));
379 graphs->pointsNb[i]= calloc(i, sizeof(unsigned int));
380 for (j= 0; j < i; j++)
381 {
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)
386 {
387 g_error(strerror(errno));
388 }
389 }
390 }
391
392 retval= chdir(cwd);
393 if (retval == -1)
394 {
395 g_error(strerror(errno));
396 }
397 free(cwd);
398 }
399
400
401 /*
402 * Calculate and write points used to generate graphs
403 *
404 * Args:
405 * graphs: structure containing array of file pointers and counters
406 * broadcast: broadcast for which to write the points
407 */
408 static void writeAccuracyPoints(MatchingGraphsBroadcast* graphs, const
409 Broadcast* const broadcast)
410 {
411 unsigned int i, j;
412 GArray* events;
413 unsigned int eventNb= broadcast->events->length;
414
415 events= g_array_sized_new(FALSE, FALSE, sizeof(Event*), eventNb);
416 g_queue_foreach(broadcast->events, &gfAddEventToArray, events);
417
418 for (i= 0; i < eventNb; i++)
419 {
420 for (j= 0; j < eventNb; j++)
421 {
422 Event* eventI= g_array_index(events, Event*, i), * eventJ=
423 g_array_index(events, Event*, j);
424
425 if (eventI->traceNum < eventJ->traceNum)
426 {
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]++;
431 }
432 }
433 }
434
435 g_array_free(events, TRUE);
436 }
437
438
439 /*
440 * Close files used to store accuracy points to genereate graphs. Deallocate
441 * array to store file pointers (but not array for counters).
442 *
443 * Args:
444 * syncState: container for synchronization data
445 */
446 static void closeGraphDataFiles(SyncState* const syncState)
447 {
448 unsigned int i, j;
449 MatchingGraphsBroadcast* graphs= ((MatchingDataBroadcast*)
450 syncState->matchingData)->graphs;
451 int retval;
452
453 if (graphs->accuracyPoints == NULL)
454 {
455 return;
456 }
457
458 for (i= 0; i < syncState->traceNb; i++)
459 {
460 for (j= 0; j < i; j++)
461 {
462 retval= fclose(graphs->accuracyPoints[i][j]);
463 if (retval != 0)
464 {
465 g_error(strerror(errno));
466 }
467 }
468 free(graphs->accuracyPoints[i]);
469 }
470 free(graphs->accuracyPoints);
471
472 graphs->accuracyPoints= NULL;
473 }
474
475
476 /*
477 * Write the matching-specific graph lines in the gnuplot script.
478 *
479 * Args:
480 * syncState: container for synchronization data
481 * i: first trace number
482 * j: second trace number, garanteed to be larger than i
483 */
484 static void writeMatchingGraphsPlotsBroadcast(SyncState* const syncState, const
485 unsigned int i, const unsigned int j)
486 {
487 if (((MatchingDataBroadcast*)
488 syncState->matchingData)->graphs->pointsNb[j][i])
489 {
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,
494 j);
495 }
496 }
This page took 0.038156 seconds and 3 git commands to generate.