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
);
47 // Functions specific to this module
48 static void registerMatchingBroadcast() __attribute__((constructor (101)));
50 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
);
52 static MatchingModule matchingModuleBroadcast
= {
54 .canMatch
[TCP
]= false,
56 .initMatching
= &initMatchingBroadcast
,
57 .destroyMatching
= &destroyMatchingBroadcast
,
58 .matchEvent
= &matchEventBroadcast
,
59 .finalizeMatching
= &finalizeMatchingBroadcast
,
60 .printMatchingStats
= &printMatchingStatsBroadcast
,
61 .writeMatchingGraphsPlots
= NULL
,
62 .writeMatchingGraphsOptions
= NULL
,
67 * Matching module registering function
69 static void registerMatchingBroadcast()
71 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
76 * Matching init function
78 * This function is called at the beginning of a synchronization run for a set
81 * Allocate the matching specific data structures
84 * syncState container for synchronization data.
85 * This function allocates these matchingData members:
89 static void initMatchingBroadcast(SyncState
* const syncState
)
91 MatchingDataBroadcast
* matchingData
;
93 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
94 syncState
->matchingData
= matchingData
;
96 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
97 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
101 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
105 matchingData
->stats
= NULL
;
111 * Matching destroy function
113 * Free the matching specific data structures
116 * syncState container for synchronization data.
117 * This function deallocates these matchingData members:
120 static void destroyMatchingBroadcast(SyncState
* const syncState
)
122 MatchingDataBroadcast
* matchingData
;
124 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
126 if (matchingData
== NULL
)
131 partialDestroyMatchingBroadcast(syncState
);
133 if (syncState
->stats
)
135 free(matchingData
->stats
);
138 free(syncState
->matchingData
);
139 syncState
->matchingData
= NULL
;
144 * Free some of the matching specific data structures
146 * This function can be called right after the events have been processed to
147 * free some data structures that are not needed for finalization.
150 * syncState container for synchronization data.
151 * This function deallocates these matchingData members:
154 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
156 MatchingDataBroadcast
* matchingData
;
158 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
160 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
165 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
166 matchingData
->pendingBroadcasts
= NULL
;
171 * Try to match one broadcast with previously received broadcasts (based on
172 * the addresses and the fist bytes of data they contain). Deliver them to the
173 * analysis module once a traceNb events have been accumulated for a
177 * syncState container for synchronization data.
178 * event new event to match
180 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
182 MatchingDataBroadcast
* matchingData
;
184 g_assert(event
->type
== UDP
);
186 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
188 if (!event
->event
.udpEvent
->unicast
)
190 if (event
->event
.udpEvent
->direction
== IN
)
192 Broadcast
* broadcast
;
193 DatagramKey
* datagramKey
;
196 if (matchingData
->stats
)
198 matchingData
->stats
->totReceive
++;
201 // s'il est déjà dans pendingBroadcasts
202 // l'ajouter à son broadcast
203 // s'il y a traceNb éléments
204 // le retirer de pending et le livrer à analysis
205 // détruire le broadcast (et ses éléments)
207 // créer un broadcast et l'ajouter à pending
210 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
211 event
->event
.udpEvent
->datagramKey
, (gpointer
)
212 &datagramKey
, (gpointer
) &broadcast
);
215 g_queue_push_tail(broadcast
->events
, event
);
216 if (broadcast
->events
->length
== syncState
->traceNb
)
218 if (matchingData
->stats
)
220 matchingData
->stats
->totComplete
++;
223 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
225 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
226 destroyBroadcast(broadcast
);
231 broadcast
= malloc(sizeof(Broadcast
));
232 broadcast
->events
= g_queue_new();
233 g_queue_push_tail(broadcast
->events
, event
);
235 datagramKey
= malloc(sizeof(DatagramKey
));
236 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
238 g_hash_table_insert(matchingData
->pendingBroadcasts
,
239 datagramKey
, broadcast
);
244 if (matchingData
->stats
)
246 matchingData
->stats
->totTransmit
++;
249 event
->destroy(event
);
254 event
->destroy(event
);
261 * Call the partial matching destroyer and Obtain the factors from downstream
264 * syncState container for synchronization data.
267 * Factors[traceNb] synchronization factors for each trace
269 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
271 MatchingDataBroadcast
* matchingData
;
273 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
275 if (matchingData
->stats
)
277 matchingData
->stats
->totIncomplete
=
278 g_hash_table_size(matchingData
->pendingBroadcasts
);
281 partialDestroyMatchingBroadcast(syncState
);
283 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
288 * Print statistics related to matching and downstream modules. Must be
289 * called after finalizeMatching.
292 * syncState container for synchronization data.
294 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
296 MatchingDataBroadcast
* matchingData
;
298 if (!syncState
->stats
)
302 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
304 printf("Broadcast matching stats:\n");
305 printf("\ttotal broadcasts datagrams emitted: %u\n",
306 matchingData
->stats
->totTransmit
);
307 printf("\ttotal broadcasts datagrams received: %u\n",
308 matchingData
->stats
->totReceive
);
309 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
310 matchingData
->stats
->totComplete
);
311 printf("\ttotal broadcast groups missing some receptions: %u\n",
312 matchingData
->stats
->totIncomplete
);
313 if (matchingData
->stats
->totIncomplete
> 0)
315 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
316 (double) (matchingData
->stats
->totReceive
-
317 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
318 matchingData
->stats
->totIncomplete
);
321 if (syncState
->analysisModule
->printAnalysisStats
!= NULL
)
323 syncState
->analysisModule
->printAnalysisStats(syncState
);