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 void gfAddToArray(gpointer data
, gpointer user_data
);
58 static void closeGraphDataFiles(SyncState
* const syncState
);
61 static MatchingModule matchingModuleBroadcast
= {
63 .canMatch
[TCP
]= false,
65 .initMatching
= &initMatchingBroadcast
,
66 .destroyMatching
= &destroyMatchingBroadcast
,
67 .matchEvent
= &matchEventBroadcast
,
68 .finalizeMatching
= &finalizeMatchingBroadcast
,
69 .printMatchingStats
= &printMatchingStatsBroadcast
,
71 .writeTraceTimePlots
= &writeMatchingGraphsPlotsBroadcast
,
77 * Matching module registering function
79 static void registerMatchingBroadcast()
81 g_queue_push_tail(&matchingModules
, &matchingModuleBroadcast
);
86 * Matching init function
88 * This function is called at the beginning of a synchronization run for a set
91 * Allocate the matching specific data structures
94 * syncState container for synchronization data.
95 * This function allocates these matchingData members:
99 static void initMatchingBroadcast(SyncState
* const syncState
)
101 MatchingDataBroadcast
* matchingData
;
103 matchingData
= malloc(sizeof(MatchingDataBroadcast
));
104 syncState
->matchingData
= matchingData
;
106 matchingData
->pendingBroadcasts
= g_hash_table_new_full(&ghfDatagramKeyHash
,
107 &gefDatagramKeyEqual
, &gdnDestroyDatagramKey
, &gdnDestroyBroadcast
);
109 if (syncState
->stats
)
111 matchingData
->stats
= calloc(1, sizeof(MatchingStatsBroadcast
));
115 matchingData
->stats
= NULL
;
118 if (syncState
->graphsStream
)
120 matchingData
->graphs
= malloc(sizeof(MatchingGraphsBroadcast
));
121 openGraphDataFiles(syncState
);
125 matchingData
->graphs
= NULL
;
131 * Matching destroy function
133 * Free the matching specific data structures
136 * syncState container for synchronization data.
137 * This function deallocates these matchingData members:
140 static void destroyMatchingBroadcast(SyncState
* const syncState
)
142 MatchingDataBroadcast
* matchingData
= syncState
->matchingData
;
145 if (matchingData
== NULL
)
150 partialDestroyMatchingBroadcast(syncState
);
152 if (syncState
->stats
)
154 free(matchingData
->stats
);
157 if (syncState
->graphsStream
)
159 for (i
= 0; i
< syncState
->traceNb
; i
++)
161 free(matchingData
->graphs
->pointsNb
[i
]);
163 free(matchingData
->graphs
->pointsNb
);
164 free(matchingData
->graphs
);
167 free(syncState
->matchingData
);
168 syncState
->matchingData
= NULL
;
173 * Free some of the matching specific data structures
175 * This function can be called right after the events have been processed to
176 * free some data structures that are not needed for finalization.
179 * syncState container for synchronization data.
180 * This function deallocates these matchingData members:
183 static void partialDestroyMatchingBroadcast(SyncState
* const syncState
)
185 MatchingDataBroadcast
* matchingData
;
187 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
189 if (matchingData
== NULL
|| matchingData
->pendingBroadcasts
== NULL
)
194 g_hash_table_destroy(matchingData
->pendingBroadcasts
);
195 matchingData
->pendingBroadcasts
= NULL
;
197 if (syncState
->graphsStream
&& matchingData
->graphs
->accuracyPoints
)
199 closeGraphDataFiles(syncState
);
205 * Try to match one broadcast with previously received broadcasts (based on
206 * the addresses and the fist bytes of data they contain). Deliver them to the
207 * analysis module once traceNb events have been accumulated for a broadcast.
210 * syncState container for synchronization data.
211 * event new event to match
213 static void matchEventBroadcast(SyncState
* const syncState
, Event
* const event
)
215 MatchingDataBroadcast
* matchingData
;
217 g_assert(event
->type
== UDP
);
219 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
221 if (!event
->event
.udpEvent
->unicast
)
223 if (event
->event
.udpEvent
->direction
== IN
)
225 Broadcast
* broadcast
;
226 DatagramKey
* datagramKey
;
229 if (matchingData
->stats
)
231 matchingData
->stats
->totReceive
++;
234 /* if event in pendingBroadcasts:
235 * add it to its broadcast
236 * if this broadcast has traceNb events:
237 * remove it from pending and deliver it to analysis
238 * destroy the broadcast (and its elements)
240 * create a broadcast and add it to pending
244 g_hash_table_lookup_extended(matchingData
->pendingBroadcasts
,
245 event
->event
.udpEvent
->datagramKey
, (gpointer
)
246 &datagramKey
, (gpointer
) &broadcast
);
249 g_queue_push_tail(broadcast
->events
, event
);
250 if (broadcast
->events
->length
== syncState
->traceNb
)
252 if (matchingData
->stats
)
254 matchingData
->stats
->totComplete
++;
257 g_hash_table_steal(matchingData
->pendingBroadcasts
, datagramKey
);
259 syncState
->analysisModule
->analyzeBroadcast(syncState
, broadcast
);
261 if (syncState
->graphsStream
)
263 writeAccuracyPoints(matchingData
->graphs
, broadcast
);
265 destroyBroadcast(broadcast
);
270 broadcast
= malloc(sizeof(Broadcast
));
271 broadcast
->events
= g_queue_new();
272 g_queue_push_tail(broadcast
->events
, event
);
274 datagramKey
= malloc(sizeof(DatagramKey
));
275 *datagramKey
= *event
->event
.udpEvent
->datagramKey
;
277 g_hash_table_insert(matchingData
->pendingBroadcasts
,
278 datagramKey
, broadcast
);
283 if (matchingData
->stats
)
285 matchingData
->stats
->totTransmit
++;
288 event
->destroy(event
);
293 event
->destroy(event
);
300 * Call the partial matching destroyer and Obtain the factors from downstream
303 * syncState container for synchronization data.
306 * Factors[traceNb] synchronization factors for each trace
308 static GArray
* finalizeMatchingBroadcast(SyncState
* const syncState
)
310 MatchingDataBroadcast
* matchingData
;
312 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
314 if (matchingData
->stats
)
316 matchingData
->stats
->totIncomplete
=
317 g_hash_table_size(matchingData
->pendingBroadcasts
);
320 partialDestroyMatchingBroadcast(syncState
);
322 return syncState
->analysisModule
->finalizeAnalysis(syncState
);
327 * Print statistics related to matching. Must be called after
331 * syncState container for synchronization data.
333 static void printMatchingStatsBroadcast(SyncState
* const syncState
)
335 MatchingDataBroadcast
* matchingData
;
337 if (!syncState
->stats
)
341 matchingData
= (MatchingDataBroadcast
*) syncState
->matchingData
;
343 printf("Broadcast matching stats:\n");
344 printf("\ttotal broadcasts datagrams emitted: %u\n",
345 matchingData
->stats
->totTransmit
);
346 printf("\ttotal broadcasts datagrams received: %u\n",
347 matchingData
->stats
->totReceive
);
348 printf("\ttotal broadcast groups for which all receptions were identified: %u\n",
349 matchingData
->stats
->totComplete
);
350 printf("\ttotal broadcast groups missing some receptions: %u\n",
351 matchingData
->stats
->totIncomplete
);
352 if (matchingData
->stats
->totIncomplete
> 0)
354 printf("\taverage number of broadcast datagrams received in incomplete groups: %f\n",
355 (double) (matchingData
->stats
->totReceive
-
356 matchingData
->stats
->totComplete
* syncState
->traceNb
) /
357 matchingData
->stats
->totIncomplete
);
363 * Create and open files used to store accuracy points to genereate graphs.
364 * Allocate and populate array to store file pointers and counters.
367 * syncState: container for synchronization data
369 static void openGraphDataFiles(SyncState
* const syncState
)
375 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
376 syncState
->matchingData
)->graphs
;
378 cwd
= changeToGraphDir(syncState
->graphsDir
);
380 graphs
->accuracyPoints
= malloc(syncState
->traceNb
* sizeof(FILE**));
381 graphs
->pointsNb
= malloc(syncState
->traceNb
* sizeof(unsigned int*));
382 for (i
= 0; i
< syncState
->traceNb
; i
++)
384 graphs
->accuracyPoints
[i
]= malloc(i
* sizeof(FILE*));
385 graphs
->pointsNb
[i
]= calloc(i
, sizeof(unsigned int));
386 for (j
= 0; j
< i
; j
++)
388 retval
= snprintf(name
, sizeof(name
),
389 "matching_broadcast-%03u_and_%03u.data", j
, i
);
390 g_assert_cmpint(retval
, <=, sizeof(name
) - 1);
391 if ((graphs
->accuracyPoints
[i
][j
]= fopen(name
, "w")) == NULL
)
393 g_error(strerror(errno
));
401 g_error(strerror(errno
));
408 * Calculate and write points used to generate graphs
411 * graphs: structure containing array of file pointers and counters
412 * broadcast: broadcast for which to write the points
414 static void writeAccuracyPoints(MatchingGraphsBroadcast
* graphs
, const
415 Broadcast
* const broadcast
)
419 unsigned int eventNb
= broadcast
->events
->length
;
421 events
= g_array_sized_new(FALSE
, FALSE
, sizeof(Event
*), eventNb
);
422 g_queue_foreach(broadcast
->events
, &gfAddToArray
, events
);
424 for (i
= 0; i
< eventNb
; i
++)
426 for (j
= 0; j
< eventNb
; j
++)
428 Event
* eventI
= g_array_index(events
, Event
*, i
), * eventJ
=
429 g_array_index(events
, Event
*, j
);
431 if (eventI
->traceNum
< eventJ
->traceNum
)
433 fprintf(graphs
->accuracyPoints
[eventJ
->traceNum
][eventI
->traceNum
],
434 "%20llu %20.9f\n", eventI
->cpuTime
,
435 wallTimeSub(&eventJ
->wallTime
, &eventI
->wallTime
));
436 graphs
->pointsNb
[eventJ
->traceNum
][eventI
->traceNum
]++;
444 * A GFunc for g_queue_foreach()
447 * data Event*, event to add
448 * user_data GArray*, array to add to
450 void gfAddToArray(gpointer data
, gpointer user_data
)
452 g_array_append_val((GArray
*) user_data
, data
);
457 * Close files used to store accuracy points to genereate graphs. Deallocate
458 * array to store file pointers (but not array for counters).
461 * syncState: container for synchronization data
463 static void closeGraphDataFiles(SyncState
* const syncState
)
466 MatchingGraphsBroadcast
* graphs
= ((MatchingDataBroadcast
*)
467 syncState
->matchingData
)->graphs
;
470 if (graphs
->accuracyPoints
== NULL
)
475 for (i
= 0; i
< syncState
->traceNb
; i
++)
477 for (j
= 0; j
< i
; j
++)
479 retval
= fclose(graphs
->accuracyPoints
[i
][j
]);
482 g_error(strerror(errno
));
485 free(graphs
->accuracyPoints
[i
]);
487 free(graphs
->accuracyPoints
);
489 graphs
->accuracyPoints
= NULL
;
494 * Write the matching-specific graph lines in the gnuplot script.
497 * syncState: container for synchronization data
498 * i: first trace number
499 * j: second trace number, garanteed to be larger than i
501 static void writeMatchingGraphsPlotsBroadcast(SyncState
* const syncState
, const
502 unsigned int i
, const unsigned int j
)
504 if (((MatchingDataBroadcast
*)
505 syncState
->matchingData
)->graphs
->pointsNb
[j
][i
])
507 fprintf(syncState
->graphsStream
,
508 "\t\"matching_broadcast-%03d_and_%03d.data\" "
509 "title \"Broadcast delays\" with points "
510 "linecolor rgb \"black\" pointtype 6 pointsize 2, \\\n", i
,