Perform trace factor reduction as a separate step
[lttv.git] / lttv / lttv / sync / event_processing_text.c
CommitLineData
48b641c1 1/* This file is part of the Linux Trace Toolkit viewer
277e5b53 2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
48b641c1 3 *
277e5b53
BP
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or (at
7 * your option) any later version.
48b641c1 8 *
277e5b53
BP
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
48b641c1 13 *
277e5b53
BP
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
48b641c1
BP
16 */
17
6ce8ceac 18#define _GNU_SOURCE
48b641c1
BP
19#define NANOSECONDS_PER_SECOND 1000000000
20#define CPU_FREQ 1e9
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <errno.h>
27#include <math.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include "sync_chain.h"
33
34#include "event_processing_text.h"
35
36
37// Functions common to all processing modules
38static void initProcessingText(SyncState* const syncState, ...);
39static void destroyProcessingText(SyncState* const syncState);
0a87ec9a 40static AllFactors* finalizeProcessingText(SyncState* const syncState);
48b641c1
BP
41static void writeProcessingTraceTimeOptionsText(SyncState* const syncState,
42 const unsigned int i, const unsigned int j);
43static void writeProcessingTraceTraceOptionsText(SyncState* const syncState,
44 const unsigned int i, const unsigned int j);
45static void writeProcessingGraphVariablesText(SyncState* const syncState,
46 const unsigned int i);
47
48// Functions specific to this module
48b641c1
BP
49static unsigned int readTraceNb(FILE* testCase);
50static void skipCommentLines(FILE* testCase);
51
52
53static ProcessingModule processingModuleText = {
54 .name= "text",
55 .initProcessing= &initProcessingText,
56 .destroyProcessing= &destroyProcessingText,
57 .finalizeProcessing= &finalizeProcessingText,
48b641c1
BP
58 .graphFunctions= {
59 .writeVariables= &writeProcessingGraphVariablesText,
60 .writeTraceTraceOptions= &writeProcessingTraceTraceOptionsText,
61 .writeTraceTimeOptions= &writeProcessingTraceTimeOptionsText,
62 },
63};
64
65
66/*
67 * Processing Module registering function
68 */
2f961b65 69void registerProcessingText()
48b641c1
BP
70{
71 g_queue_push_tail(&processingModules, &processingModuleText);
72}
73
74
75/*
76 * Allocate and initialize data structures for synchronizing a traceset.
77 * Open test case file.
78 *
79 * Args:
80 * syncState: container for synchronization data.
81 * testCaseName: const char*, test case file name
82 */
83static void initProcessingText(SyncState* const syncState, ...)
84{
85 ProcessingDataText* processingData;
86 const char* testCaseName;
87 va_list ap;
88
89 processingData= malloc(sizeof(ProcessingDataText));
90 syncState->processingData= processingData;
91 va_start(ap, syncState);
92 testCaseName= va_arg(ap, const char*);
93 va_end(ap);
94
95 processingData->testCase= fopen(testCaseName, "r");
96 if (processingData->testCase == NULL)
97 {
98 g_error(strerror(errno));
99 }
100 syncState->traceNb= readTraceNb(processingData->testCase);
101
102 if (syncState->stats)
103 {
104 processingData->factors= NULL;
105 }
106}
107
108
109static void destroyProcessingText(SyncState* const syncState)
110{
111 ProcessingDataText* processingData= (ProcessingDataText*)
112 syncState->processingData;
113
114 if (processingData == NULL)
115 {
116 return;
117 }
118
6ce8ceac
BP
119 fclose(processingData->testCase);
120
48b641c1
BP
121 if (syncState->stats && processingData->factors)
122 {
0a87ec9a 123 freeAllFactors(processingData->factors);
48b641c1
BP
124 }
125
126 free(syncState->processingData);
127 syncState->processingData= NULL;
128}
129
130
131/*
132 * Read the test case file and make up events. Dispatch those events to the
133 * matching module.
134 *
135 * Args:
136 * syncState: container for synchronization data.
9c7696b8
BP
137 *
138 * Returns:
0a87ec9a 139 * AllFactors synchronization factors for each trace pair
48b641c1 140 */
0a87ec9a 141static AllFactors* finalizeProcessingText(SyncState* const syncState)
48b641c1 142{
48b641c1
BP
143 int retval;
144 unsigned int* seq;
0a87ec9a 145 AllFactors* factors;
48b641c1
BP
146 ProcessingDataText* processingData= (ProcessingDataText*)
147 syncState->processingData;
148 FILE* testCase= processingData->testCase;
149 char* line= NULL;
6ce8ceac 150 size_t bufLen;
48b641c1
BP
151
152 seq= calloc(syncState->traceNb, sizeof(unsigned int));
153
154 skipCommentLines(testCase);
6ce8ceac 155 retval= getline(&line, &bufLen, testCase);
48b641c1
BP
156 while(!feof(testCase))
157 {
158 unsigned int sender, receiver;
159 double sendTime, recvTime;
160 char tmp;
161 unsigned int i;
162
163 if (retval == -1 && !feof(testCase))
164 {
165 g_error(strerror(errno));
166 }
167
6ce8ceac 168 if (line[retval - 1] == '\n')
48b641c1 169 {
6ce8ceac 170 line[retval - 1]= '\0';
48b641c1
BP
171 }
172
173 retval= sscanf(line, " %u %u %lf %lf %c", &sender, &receiver,
174 &sendTime, &recvTime, &tmp);
175 if (retval == EOF)
176 {
177 g_error(strerror(errno));
178 }
179 else if (retval != 4)
180 {
181 g_error("Error parsing test file while looking for data point, line was '%s'", line);
182 }
183
184 if (sender + 1 > syncState->traceNb)
185 {
186 g_error("Error parsing test file, sender is out of range, line was '%s'", line);
187 }
188
189 if (receiver + 1 > syncState->traceNb)
190 {
191 g_error("Error parsing test file, receiver is out of range, line was '%s'", line);
192 }
193
194 if (sendTime < 0)
195 {
196 g_error("Error parsing test file, send time is negative, line was '%s'", line);
197 }
198
199 if (recvTime < 0)
200 {
201 g_error("Error parsing test file, receive time is negative, line was '%s'", line);
202 }
203
204 // Generate ouput and input events
205 {
206 unsigned int addressOffset;
207 struct {
208 unsigned int traceNum;
209 double time;
210 enum Direction direction;
211 } loopValues[]= {
212 {sender, sendTime, OUT},
213 {receiver, recvTime, IN},
214 };
215
216 /* addressOffset is added to a traceNum to convert it to an address so
217 * that the address is not plainly the same as the traceNb. */
218 if (syncState->traceNb > 1)
219 {
220 addressOffset= pow(10, floor(log(syncState->traceNb - 1) /
221 log(10)) + 1);
222 }
223 else
224 {
225 addressOffset= 0;
226 }
227
228 for (i= 0; i < sizeof(loopValues) / sizeof(*loopValues); i++)
229 {
230 Event* event;
231
232 event= malloc(sizeof(Event));
233 event->traceNum= loopValues[i].traceNum;
234 event->wallTime.seconds= floor(loopValues[i].time);
235 event->wallTime.nanosec= floor((loopValues[i].time -
236 floor(loopValues[i].time)) * NANOSECONDS_PER_SECOND);
237 event->cpuTime= round(loopValues[i].time * CPU_FREQ);
238 event->type= TCP;
239 event->destroy= &destroyTCPEvent;
240 event->event.tcpEvent= malloc(sizeof(TCPEvent));
241 event->event.tcpEvent->direction= loopValues[i].direction;
242 event->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey));
243 event->event.tcpEvent->segmentKey->ihl= 5;
244 event->event.tcpEvent->segmentKey->tot_len= 40;
245 event->event.tcpEvent->segmentKey->connectionKey.saddr= sender +
246 addressOffset;
247 event->event.tcpEvent->segmentKey->connectionKey.daddr= receiver +
248 addressOffset;
249 event->event.tcpEvent->segmentKey->connectionKey.source= 57645;
250 event->event.tcpEvent->segmentKey->connectionKey.dest= 80;
251 event->event.tcpEvent->segmentKey->seq= seq[sender];
252 event->event.tcpEvent->segmentKey->ack_seq= 0;
253 event->event.tcpEvent->segmentKey->doff= 5;
254 event->event.tcpEvent->segmentKey->ack= 0;
255 event->event.tcpEvent->segmentKey->rst= 0;
256 event->event.tcpEvent->segmentKey->syn= 1;
257 event->event.tcpEvent->segmentKey->fin= 0;
258
259 syncState->matchingModule->matchEvent(syncState, event);
260 }
261 }
262
263 seq[sender]++;
264
265 skipCommentLines(testCase);
6ce8ceac 266 retval= getline(&line, &bufLen, testCase);
48b641c1
BP
267 }
268
269 free(seq);
270
271 if (line)
272 {
273 free(line);
274 }
275
276 factors= syncState->matchingModule->finalizeMatching(syncState);
277 if (syncState->stats)
278 {
279 processingData->factors= factors;
280 }
9c7696b8
BP
281
282 return factors;
48b641c1
BP
283}
284
285
48b641c1
BP
286/*
287 * Read trace number from the test case stream. The trace number should be the
288 * first non-comment line and should be an unsigned int by itself on a line.
289 *
290 * Args:
291 * testCase: test case stream
292 *
293 * Returns:
294 * The trace number
295 */
296static unsigned int readTraceNb(FILE* testCase)
297{
298 unsigned int result;
299 int retval;
300 char* line= NULL;
301 size_t len;
302 char tmp;
303
304 skipCommentLines(testCase);
305 retval= getline(&line, &len, testCase);
306 if (retval == -1)
307 {
308 if (feof(testCase))
309 {
310 g_error("Unexpected end of file while looking for number of traces");
311 }
312 else
313 {
314 g_error(strerror(errno));
315 }
316 }
317 if (line[retval - 1] == '\n')
318 {
319 line[retval - 1]= '\0';
320 }
321
322 retval= sscanf(line, " %u %c", &result, &tmp);
323 if (retval == EOF || retval != 1)
324 {
325 g_error("Error parsing test file while looking for number of traces, line was '%s'", line);
326
327 // Not really needed but avoids warning from gcc
328 abort();
329 }
330
6ce8ceac
BP
331 if (line)
332 {
333 free(line);
334 }
335
48b641c1
BP
336 return result;
337}
338
339
340/*
341 * Advance testCase stream over empty space, empty lines and lines that begin
342 * with '#'
343 *
344 * Args:
345 * testCase: test case stream
346 */
347static void skipCommentLines(FILE* testCase)
348{
349 int firstChar;
350 ssize_t retval;
351 char* line= NULL;
352 size_t len;
353
354 do
355 {
356 firstChar= fgetc(testCase);
357 if (firstChar == (int) '#')
358 {
359 retval= getline(&line, &len, testCase);
360 if (retval == -1)
361 {
362 if (feof(testCase))
363 {
364 goto outEof;
365 }
366 else
367 {
368 g_error(strerror(errno));
369 }
370 }
371 }
372 else if (firstChar == (int) '\n' || firstChar == (int) ' ')
373 {}
374 else if (firstChar == EOF)
375 {
376 goto outEof;
377 }
378 else
379 {
380 break;
381 }
382 } while (true);
383 retval= ungetc(firstChar, testCase);
384 if (retval == EOF)
385 {
386 g_error("Error: ungetc()");
387 }
388
389outEof:
390 if (line)
391 {
392 free(line);
393 }
394}
395
396
397/*
398 * Write the processing-specific variables in the gnuplot script.
399 *
400 * Args:
401 * syncState: container for synchronization data
402 * i: trace number
403 */
404static void writeProcessingGraphVariablesText(SyncState* const syncState,
405 const unsigned int i)
406{
407 fprintf(syncState->graphsStream, "clock_freq_%u= %.3f\n", i, CPU_FREQ);
408}
409
410
411/*
412 * Write the processing-specific options in the gnuplot script.
413 *
414 * Args:
415 * syncState: container for synchronization data
416 * i: first trace number
417 * j: second trace number, garanteed to be larger than i
418 */
419static void writeProcessingTraceTraceOptionsText(SyncState* const syncState,
420 const unsigned int i, const unsigned int j)
421{
422 fprintf(syncState->graphsStream,
423 "set key inside right bottom\n"
424 "set xlabel \"Clock %1$u\"\n"
425 "set xtics nomirror\n"
426 "set ylabel \"Clock %2$u\"\n"
427 "set ytics nomirror\n"
428 "set x2label \"Clock %1$d (s)\"\n"
429 "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n"
430 "set x2tics\n"
431 "set y2label \"Clock %2$d (s)\"\n"
432 "set y2range [GPVAL_Y_MIN / clock_freq_%2$u : GPVAL_Y_MAX / clock_freq_%2$u]\n"
433 "set y2tics\n", i, j);
434}
435
436
437/*
438 * Write the processing-specific options in the gnuplot script.
439 *
440 * Args:
441 * syncState: container for synchronization data
442 * i: first trace number
443 * j: second trace number, garanteed to be larger than i
444 */
445static void writeProcessingTraceTimeOptionsText(SyncState* const syncState,
446 const unsigned int i, const unsigned int j)
447{
448 fprintf(syncState->graphsStream,
449 "set key inside right bottom\n"
450 "set xlabel \"Clock %1$u\"\n"
451 "set xtics nomirror\n"
452 "set ylabel \"time (s)\"\n"
453 "set ytics nomirror\n"
454 "set x2label \"Clock %1$d (s)\"\n"
455 "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n"
456 "set x2tics\n", i);
457}
This page took 0.041087 seconds and 4 git commands to generate.