Add a module to distribute messages to many analysis modules
[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 /* if event in pendingBroadcasts:
202 * add it to its broadcast
203 * if this broadcast has traceNb events:
204 * remove it from pending and deliver it to analysis
205 * destroy the broadcast (and its elements)
206 * else:
207 * create a broadcast and add it to pending
208 */
209
210 result=
211 g_hash_table_lookup_extended(matchingData->pendingBroadcasts,
212 event->event.udpEvent->datagramKey, (gpointer)
213 &datagramKey, (gpointer) &broadcast);
214 if (result)
215 {
216 g_queue_push_tail(broadcast->events, event);
217 if (broadcast->events->length == syncState->traceNb)
218 {
219 if (matchingData->stats)
220 {
221 matchingData->stats->totComplete++;
222 }
223
224 g_hash_table_steal(matchingData->pendingBroadcasts, datagramKey);
225 free(datagramKey);
226 syncState->analysisModule->analyzeBroadcast(syncState, broadcast);
227 destroyBroadcast(broadcast);
228 }
229 }
230 else
231 {
232 broadcast= malloc(sizeof(Broadcast));
233 broadcast->events= g_queue_new();
234 g_queue_push_tail(broadcast->events, event);
235
236 datagramKey= malloc(sizeof(DatagramKey));
237 *datagramKey= *event->event.udpEvent->datagramKey;
238
239 g_hash_table_insert(matchingData->pendingBroadcasts,
240 datagramKey, broadcast);
241 }
242 }
243 else
244 {
245 if (matchingData->stats)
246 {
247 matchingData->stats->totTransmit++;
248 }
249
250 event->destroy(event);
251 }
252 }
253 else
254 {
255 event->destroy(event);
256 }
257
258 }
259
260
261 /*
262 * Call the partial matching destroyer and Obtain the factors from downstream
263 *
264 * Args:
265 * syncState container for synchronization data.
266 *
267 * Returns:
268 * Factors[traceNb] synchronization factors for each trace
269 */
270 static GArray* finalizeMatchingBroadcast(SyncState* const syncState)
271 {
272 MatchingDataBroadcast* matchingData;
273
274 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
275
276 if (matchingData->stats)
277 {
278 matchingData->stats->totIncomplete=
279 g_hash_table_size(matchingData->pendingBroadcasts);
280 }
281
282 partialDestroyMatchingBroadcast(syncState);
283
284 return syncState->analysisModule->finalizeAnalysis(syncState);
285 }
286
287
288 /*
289 * Print statistics related to matching and downstream modules. Must be
290 * called after finalizeMatching.
291 *
292 * Args:
293 * syncState container for synchronization data.
294 */
295 static void printMatchingStatsBroadcast(SyncState* const syncState)
296 {
297 MatchingDataBroadcast* matchingData;
298
299 if (!syncState->stats)
300 {
301 return;
302 }
303 matchingData= (MatchingDataBroadcast*) syncState->matchingData;
304
305 printf("Broadcast matching stats:\n");
306 printf("\ttotal broadcasts datagrams emitted: %u\n",
307 matchingData->stats->totTransmit);
308 printf("\ttotal broadcasts datagrams received: %u\n",
309 matchingData->stats->totReceive);
310 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
311 matchingData->stats->totComplete);
312 printf("\ttotal broadcast groups missing some receptions: %u\n",
313 matchingData->stats->totIncomplete);
314 if (matchingData->stats->totIncomplete > 0)
315 {
316 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
317 (double) (matchingData->stats->totReceive -
318 matchingData->stats->totComplete * syncState->traceNb) /
319 matchingData->stats->totIncomplete);
320 }
321
322 if (syncState->analysisModule->printAnalysisStats != NULL)
323 {
324 syncState->analysisModule->printAnalysisStats(syncState);
325 }
326 }
This page took 0.035214 seconds and 4 git commands to generate.