Adds wall time field to events
[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 #ifndef g_info
35 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
36 #endif
37
38
39 // Functions common to all matching modules
40 static void initMatchingBroadcast(SyncState* const syncState);
41 static void destroyMatchingBroadcast(SyncState* const syncState);
42
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
47 // Functions specific to this module
48 static void registerMatchingBroadcast() __attribute__((constructor (101)));
49
50 static void partialDestroyMatchingBroadcast(SyncState* const syncState);
51
52 static MatchingModule matchingModuleBroadcast = {
53 .name= "broadcast",
54 .canMatch[TCP]= false,
55 .canMatch[UDP]= true,
56 .initMatching= &initMatchingBroadcast,
57 .destroyMatching= &destroyMatchingBroadcast,
58 .matchEvent= &matchEventBroadcast,
59 .finalizeMatching= &finalizeMatchingBroadcast,
60 .printMatchingStats= &printMatchingStatsBroadcast,
61 .writeMatchingGraphsPlots= NULL,
62 .writeMatchingGraphsOptions= NULL,
63 };
64
65
66 /*
67 * Matching module registering function
68 */
69 static void registerMatchingBroadcast()
70 {
71 g_queue_push_tail(&matchingModules, &matchingModuleBroadcast);
72 }
73
74
75 /*
76 * Matching init function
77 *
78 * This function is called at the beginning of a synchronization run for a set
79 * of traces.
80 *
81 * Allocate the matching specific data structures
82 *
83 * Args:
84 * syncState container for synchronization data.
85 * This function allocates these matchingData members:
86 * pendingBroadcasts
87 * stats
88 */
89 static void initMatchingBroadcast(SyncState* const syncState)
90 {
91 MatchingDataBroadcast* matchingData;
92
93 matchingData= malloc(sizeof(MatchingDataBroadcast));
94 syncState->matchingData= matchingData;
95
96 matchingData->pendingBroadcasts= g_hash_table_new_full(&ghfDatagramKeyHash,
97 &gefDatagramKeyEqual, &gdnDestroyDatagramKey, &gdnDestroyBroadcast);
98
99 if (syncState->stats)
100 {
101 matchingData->stats= calloc(1, sizeof(MatchingStatsBroadcast));
102 }
103 else
104 {
105 matchingData->stats= NULL;
106 }
107 }
108
109
110 /*
111 * Matching destroy function
112 *
113 * Free the matching specific data structures
114 *
115 * Args:
116 * syncState container for synchronization data.
117 * This function deallocates these matchingData members:
118 * stats
119 */
120 static void destroyMatchingBroadcast(SyncState* const syncState)
121 {
122 MatchingDataBroadcast* matchingData;
123
124 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
125
126 if (matchingData == NULL)
127 {
128 return;
129 }
130
131 partialDestroyMatchingBroadcast(syncState);
132
133 if (syncState->stats)
134 {
135 free(matchingData->stats);
136 }
137
138 free(syncState->matchingData);
139 syncState->matchingData= NULL;
140 }
141
142
143 /*
144 * Free some of the matching specific data structures
145 *
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.
148 *
149 * Args:
150 * syncState container for synchronization data.
151 * This function deallocates these matchingData members:
152 * pendingBroadcasts
153 */
154 static void partialDestroyMatchingBroadcast(SyncState* const syncState)
155 {
156 MatchingDataBroadcast* matchingData;
157
158 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
159
160 if (matchingData == NULL || matchingData->pendingBroadcasts == NULL)
161 {
162 return;
163 }
164
165 g_hash_table_destroy(matchingData->pendingBroadcasts);
166 matchingData->pendingBroadcasts= NULL;
167 }
168
169
170 /*
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
174 * broadcast.
175 *
176 * Args:
177 * syncState container for synchronization data.
178 * event new event to match
179 */
180 static void matchEventBroadcast(SyncState* const syncState, Event* const event)
181 {
182 MatchingDataBroadcast* matchingData;
183
184 g_assert(event->type == UDP);
185
186 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
187
188 if (!event->event.udpEvent->unicast)
189 {
190 if (event->event.udpEvent->direction == IN)
191 {
192 Broadcast* broadcast;
193 DatagramKey* datagramKey;
194 gboolean result;
195
196 if (matchingData->stats)
197 {
198 matchingData->stats->totReceive++;
199 }
200
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)
206 // sinon
207 // créer un broadcast et l'ajouter à pending
208
209 result=
210 g_hash_table_lookup_extended(matchingData->pendingBroadcasts,
211 event->event.udpEvent->datagramKey, (gpointer)
212 &datagramKey, (gpointer) &broadcast);
213 if (result)
214 {
215 g_queue_push_tail(broadcast->events, event);
216 if (broadcast->events->length == syncState->traceNb)
217 {
218 if (matchingData->stats)
219 {
220 matchingData->stats->totComplete++;
221 }
222
223 g_hash_table_steal(matchingData->pendingBroadcasts, datagramKey);
224 free(datagramKey);
225 syncState->analysisModule->analyzeBroadcast(syncState, broadcast);
226 destroyBroadcast(broadcast);
227 }
228 }
229 else
230 {
231 broadcast= malloc(sizeof(Broadcast));
232 broadcast->events= g_queue_new();
233 g_queue_push_tail(broadcast->events, event);
234
235 datagramKey= malloc(sizeof(DatagramKey));
236 *datagramKey= *event->event.udpEvent->datagramKey;
237
238 g_hash_table_insert(matchingData->pendingBroadcasts,
239 datagramKey, broadcast);
240 }
241 }
242 else
243 {
244 if (matchingData->stats)
245 {
246 matchingData->stats->totTransmit++;
247 }
248
249 event->destroy(event);
250 }
251 }
252 else
253 {
254 event->destroy(event);
255 }
256
257 }
258
259
260 /*
261 * Call the partial matching destroyer and Obtain the factors from downstream
262 *
263 * Args:
264 * syncState container for synchronization data.
265 *
266 * Returns:
267 * Factors[traceNb] synchronization factors for each trace
268 */
269 static GArray* finalizeMatchingBroadcast(SyncState* const syncState)
270 {
271 MatchingDataBroadcast* matchingData;
272
273 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
274
275 if (matchingData->stats)
276 {
277 matchingData->stats->totIncomplete=
278 g_hash_table_size(matchingData->pendingBroadcasts);
279 }
280
281 partialDestroyMatchingBroadcast(syncState);
282
283 return syncState->analysisModule->finalizeAnalysis(syncState);
284 }
285
286
287 /*
288 * Print statistics related to matching and downstream modules. Must be
289 * called after finalizeMatching.
290 *
291 * Args:
292 * syncState container for synchronization data.
293 */
294 static void printMatchingStatsBroadcast(SyncState* const syncState)
295 {
296 MatchingDataBroadcast* matchingData;
297
298 if (!syncState->stats)
299 {
300 return;
301 }
302 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
303
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)
314 {
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);
319 }
320
321 if (syncState->analysisModule->printAnalysisStats != NULL)
322 {
323 syncState->analysisModule->printAnalysisStats(syncState);
324 }
325 }
This page took 0.035552 seconds and 4 git commands to generate.