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