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 /* 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)
207 * create a broadcast and add it to pending
211 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
212 event
->event
.udpEvent
->datagramKey
, (gpointer
)
213 &datagramKey
, (gpointer
) &broadcast
);
216 g_queue_push_tail(broadcast
->events
, event
);
217 if (broadcast
->events
->length
== syncState
->traceNb
)
219 if (matchingData
->stats
)
221 matchingData
->stats
->totComplete
++;
224 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
226 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
227 destroyBroadcast(broadcast
);
232 broadcast
= malloc(sizeof(Broadcast
));
233 broadcast
->events
= g_queue_new();
234 g_queue_push_tail(broadcast
->events
, event
);
236 datagramKey
= malloc(sizeof(DatagramKey
));
237 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
239 g_hash_table_insert(matchingData
->pendingBroadcasts
,
240 datagramKey
, broadcast
);
245 if (matchingData
->stats
)
247 matchingData
->stats
->totTransmit
++;
250 event
->destroy(event
);
255 event
->destroy(event
);
262 * Call the partial matching destroyer and Obtain the factors from downstream
265 * syncState container for synchronization data.
268 * Factors[traceNb] synchronization factors for each trace
270 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
272 MatchingDataBroadcast
* matchingData
;
274 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
276 if (matchingData
->stats
)
278 matchingData
->stats
->totIncomplete
=
279 g_hash_table_size(matchingData
->pendingBroadcasts
);
282 partialDestroyMatchingBroadcast(syncState
);
284 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
289 * Print statistics related to matching. Must be called after
293 * syncState container for synchronization data.
295 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
297 MatchingDataBroadcast
* matchingData
;
299 if (!syncState
->stats
)
303 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
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)
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
);