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"
35 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
39 // Functions common to all matching modules
40 static void initMatchingBroadcast(SyncState
* const syncState
);
41 static void destroyMatchingBroadcast(SyncState
* const syncState
);
43 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
);
44 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
);
45 static void printMatchingStatsBroadcast(SyncState
* const syncState
);
46 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
47 unsigned int i
, const unsigned int j
);
49 // Functions specific to this module
50 static void registerMatchingBroadcast() __attribute__((constructor (101)));
52 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
);
54 static void openGraphDataFiles(SyncState
* const syncState
);
55 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
56 Broadcast
* const broadcast
);
57 static void closeGraphDataFiles(SyncState
* const syncState
);
60 static MatchingModule matchingModuleBroadcast
= {
62 .canMatch
[TCP
]= false,
64 .initMatching
= &initMatchingBroadcast
,
65 .destroyMatching
= &destroyMatchingBroadcast
,
66 .matchEvent
= &matchEventBroadcast
,
67 .finalizeMatching
= &finalizeMatchingBroadcast
,
68 .printMatchingStats
= &printMatchingStatsBroadcast
,
70 .writeTraceTimePlots
= &writeMatchingGraphsPlotsBroadcast
,
76 * Matching module registering function
78 static void registerMatchingBroadcast()
80 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
85 * Matching init function
87 * This function is called at the beginning of a synchronization run for a set
90 * Allocate the matching specific data structures
93 * syncState container for synchronization data.
94 * This function allocates these matchingData members:
98 static void initMatchingBroadcast(SyncState
* const syncState
)
100 MatchingDataBroadcast
* matchingData
;
102 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
103 syncState
->matchingData
= matchingData
;
105 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
106 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
108 if (syncState
->stats
)
110 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
114 matchingData
->stats
= NULL
;
117 if (syncState
->graphsStream
)
119 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
120 openGraphDataFiles(syncState
);
124 matchingData
->graphs
= NULL
;
130 * Matching destroy function
132 * Free the matching specific data structures
135 * syncState container for synchronization data.
136 * This function deallocates these matchingData members:
139 static void destroyMatchingBroadcast(SyncState
* const syncState
)
141 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
144 if (matchingData
== NULL
)
149 partialDestroyMatchingBroadcast(syncState
);
151 if (syncState
->stats
)
153 free(matchingData
->stats
);
156 if (syncState
->graphsStream
)
158 for (i
= 0; i
< syncState
->traceNb
; i
++)
160 free(matchingData
->graphs
->pointsNb
[i
]);
162 free(matchingData
->graphs
->pointsNb
);
163 free(matchingData
->graphs
);
166 free(syncState
->matchingData
);
167 syncState
->matchingData
= NULL
;
172 * Free some of the matching specific data structures
174 * This function can be called right after the events have been processed to
175 * free some data structures that are not needed for finalization.
178 * syncState container for synchronization data.
179 * This function deallocates these matchingData members:
182 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
184 MatchingDataBroadcast
* matchingData
;
186 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
188 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
193 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
194 matchingData
->pendingBroadcasts
= NULL
;
196 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
198 closeGraphDataFiles(syncState
);
204 * Try to match one broadcast with previously received broadcasts (based on
205 * the addresses and the fist bytes of data they contain). Deliver them to the
206 * analysis module once traceNb events have been accumulated for a broadcast.
209 * syncState container for synchronization data.
210 * event new event to match
212 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
214 MatchingDataBroadcast
* matchingData
;
216 g_assert(event
->type
== UDP
);
218 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
220 if (!event
->event
.udpEvent
->unicast
)
222 if (event
->event
.udpEvent
->direction
== IN
)
224 Broadcast
* broadcast
;
225 DatagramKey
* datagramKey
;
228 if (matchingData
->stats
)
230 matchingData
->stats
->totReceive
++;
233 /* if event in pendingBroadcasts:
234 * add it to its broadcast
235 * if this broadcast has traceNb events:
236 * remove it from pending and deliver it to analysis
237 * destroy the broadcast (and its elements)
239 * create a broadcast and add it to pending
243 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
244 event
->event
.udpEvent
->datagramKey
, (gpointer
)
245 &datagramKey
, (gpointer
) &broadcast
);
248 g_queue_push_tail(broadcast
->events
, event
);
249 if (broadcast
->events
->length
== syncState
->traceNb
)
251 if (matchingData
->stats
)
253 matchingData
->stats
->totComplete
++;
256 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
258 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
260 if (syncState
->graphsStream
)
262 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
264 destroyBroadcast(broadcast
);
269 broadcast
= malloc(sizeof(Broadcast
));
270 broadcast
->events
= g_queue_new();
271 g_queue_push_tail(broadcast
->events
, event
);
273 datagramKey
= malloc(sizeof(DatagramKey
));
274 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
276 g_hash_table_insert(matchingData
->pendingBroadcasts
,
277 datagramKey
, broadcast
);
282 if (matchingData
->stats
)
284 matchingData
->stats
->totTransmit
++;
287 event
->destroy(event
);
292 event
->destroy(event
);
299 * Call the partial matching destroyer and Obtain the factors from downstream
302 * syncState container for synchronization data.
305 * Factors[traceNb] synchronization factors for each trace
307 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
309 MatchingDataBroadcast
* matchingData
;
311 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
313 if (matchingData
->stats
)
315 matchingData
->stats
->totIncomplete
=
316 g_hash_table_size(matchingData
->pendingBroadcasts
);
319 partialDestroyMatchingBroadcast(syncState
);
321 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
326 * Print statistics related to matching. Must be called after
330 * syncState container for synchronization data.
332 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
334 MatchingDataBroadcast
* matchingData
;
336 if (!syncState
->stats
)
340 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
342 printf("Broadcast matching stats:\n");
343 printf("\ttotal broadcasts datagrams emitted: %u\n",
344 matchingData
->stats
->totTransmit
);
345 printf("\ttotal broadcasts datagrams received: %u\n",
346 matchingData
->stats
->totReceive
);
347 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
348 matchingData
->stats
->totComplete
);
349 printf("\ttotal broadcast groups missing some receptions: %u\n",
350 matchingData
->stats
->totIncomplete
);
351 if (matchingData
->stats
->totIncomplete
> 0)
353 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
354 (double) (matchingData
->stats
->totReceive
-
355 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
356 matchingData
->stats
->totIncomplete
);
362 * Create and open files used to store accuracy points to genereate graphs.
363 * Allocate and populate array to store file pointers and counters.
366 * syncState: container for synchronization data
368 static void openGraphDataFiles(SyncState
* const syncState
)
374 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
375 syncState
->matchingData
)->graphs
;
377 cwd
= changeToGraphDir(syncState
->graphsDir
);
379 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
380 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
381 for (i
= 0; i
< syncState
->traceNb
; i
++)
383 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
384 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
385 for (j
= 0; j
< i
; j
++)
387 retval
= snprintf(name
, sizeof(name
),
388 "matching_broadcast-%03u_and_%03u.data", j
, i
);
389 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
390 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
392 g_error(strerror(errno
));
400 g_error(strerror(errno
));
407 * Calculate and write points used to generate graphs
410 * graphs: structure containing array of file pointers and counters
411 * broadcast: broadcast for which to write the points
413 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
414 Broadcast
* const broadcast
)
418 unsigned int eventNb
= broadcast
->events
->length
;
420 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
421 g_queue_foreach(broadcast
->events
, &gfAddEventToArray
, events
);
423 for (i
= 0; i
< eventNb
; i
++)
425 for (j
= 0; j
< eventNb
; j
++)
427 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
428 g_array_index(events
, Event
*, j
);
430 if (eventI
->traceNum
< eventJ
->traceNum
)
432 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
433 "%20llu %20.9f\n", eventI
->cpuTime
,
434 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
435 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
440 g_array_free(events
, TRUE
);
445 * Close files used to store accuracy points to genereate graphs. Deallocate
446 * array to store file pointers (but not array for counters).
449 * syncState: container for synchronization data
451 static void closeGraphDataFiles(SyncState
* const syncState
)
454 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
455 syncState
->matchingData
)->graphs
;
458 if (graphs
->accuracyPoints
== NULL
)
463 for (i
= 0; i
< syncState
->traceNb
; i
++)
465 for (j
= 0; j
< i
; j
++)
467 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
470 g_error(strerror(errno
));
473 free(graphs
->accuracyPoints
[i
]);
475 free(graphs
->accuracyPoints
);
477 graphs
->accuracyPoints
= NULL
;
482 * Write the matching-specific graph lines in the gnuplot script.
485 * syncState: container for synchronization data
486 * i: first trace number
487 * j: second trace number, garanteed to be larger than i
489 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
490 unsigned int i
, const unsigned int j
)
492 if (((MatchingDataBroadcast
*)
493 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
495 fprintf(syncState
->graphsStream
,
496 "\t\"matching_broadcast-%03d_and_%03d.data\" "
497 "title \"Broadcast delays\" with points "
498 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,