85adcf37c46de6a34843832d753d1fc6ca554673
[lttv.git] / lttv / lttv / sync / graph_functions.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 <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 #include "sync_chain.h"
32 #include "graph_functions.h"
33
34
35 /*
36 * Create the directory used to hold graphs and the header of the gnuplot
37 * script.
38 *
39 * Args:
40 * graphsDir: name of directory
41 *
42 * Returns:
43 * The current working directory before the execution of the function. The
44 * string must be free'd by the caller.
45 */
46 FILE* createGraphsDir(const char* const graphsDir)
47 {
48 char* cwd;
49 int graphsFp;
50 FILE* result;
51 int retval;
52
53 cwd= changeToGraphsDir(graphsDir);
54
55 if ((graphsFp= open("graphs.gnu", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
56 S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
57 | S_IWOTH | S_IXOTH)) == -1)
58 {
59 g_error(strerror(errno));
60 }
61 if ((result= fdopen(graphsFp, "w")) == NULL)
62 {
63 g_error(strerror(errno));
64 }
65
66 fprintf(result,
67 "#!/usr/bin/gnuplot\n\n"
68 "set terminal postscript eps color size 8in,6in\n");
69
70 retval= chdir(cwd);
71 if (retval == -1)
72 {
73 g_error(strerror(errno));
74 }
75 free(cwd);
76
77 return result;
78 }
79
80
81 /*
82 * Change to the directory used to hold graphs. Create it if necessary.
83 *
84 * Args:
85 * graphsDir: name of directory
86 *
87 * Returns:
88 * The current working directory before the execution of the function. The
89 * string must be free'd by the caller.
90 */
91 char* changeToGraphsDir(const char* const graphsDir)
92 {
93 int retval;
94 char* cwd;
95
96 cwd= getcwd(NULL, 0);
97 if (cwd == NULL)
98 {
99 g_error(strerror(errno));
100 }
101 while ((retval= chdir(graphsDir)) != 0)
102 {
103 if (errno == ENOENT)
104 {
105 retval= mkdir(graphsDir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
106 S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
107 if (retval != 0)
108 {
109 g_error(strerror(errno));
110 }
111 }
112 else
113 {
114 g_error(strerror(errno));
115 }
116 }
117
118 return cwd;
119 }
120
121
122 /*
123 * Call each graph variable, option and plot line function of each module to
124 * produce a gnuplot script.
125 *
126 * Args:
127 * syncState: container for synchronization data
128 */
129 void writeGraphsScript(SyncState* const syncState)
130 {
131 unsigned int i, j, k, l, m;
132 long pos1, pos2;
133 const GraphFunctions* moduleGraphFunctions[]= {
134 &syncState->processingModule->graphFunctions,
135 &syncState->matchingModule->graphFunctions,
136 &syncState->analysisModule->graphFunctions,
137 };
138 const struct {
139 char* name;
140 size_t plotsOffsets[2];
141 size_t optionsOffset;
142 } graphTypes[]= {
143 {
144 "TraceTrace",
145 {
146 offsetof(GraphFunctions, writeTraceTraceBackPlots),
147 offsetof(GraphFunctions, writeTraceTraceForePlots),
148 },
149 offsetof(GraphFunctions, writeTraceTraceOptions),
150 },
151 {
152 "TraceTime",
153 {
154 offsetof(GraphFunctions, writeTraceTimeBackPlots),
155 offsetof(GraphFunctions, writeTraceTimeForePlots),
156 },
157 offsetof(GraphFunctions, writeTraceTimeOptions),
158 },
159 };
160
161 fprintf(syncState->graphsStream, "\n");
162
163 // Write variables
164 pos1= ftell(syncState->graphsStream);
165 for (i= 0; i < syncState->traceNb; i++)
166 {
167 for (k= 0; k < sizeof(moduleGraphFunctions) /
168 sizeof(*moduleGraphFunctions); k++)
169 {
170 GraphVariableFunction** writeVariables= (void*)
171 moduleGraphFunctions[k] + offsetof(GraphFunctions,
172 writeVariables);
173
174 if (*writeVariables)
175 {
176 (*writeVariables)(syncState, i);
177 }
178 }
179 }
180 fflush(syncState->graphsStream);
181 pos2= ftell(syncState->graphsStream);
182 if (pos1 != pos2)
183 {
184 fprintf(syncState->graphsStream, "\n");
185 }
186
187 // Write plots and options
188 for (l= 0; l < sizeof(graphTypes) / sizeof(*graphTypes); l++)
189 {
190 // Cover the upper triangular matrix, i is the reference node.
191 for (i= 0; i < syncState->traceNb; i++)
192 {
193 for (j= i + 1; j < syncState->traceNb; j++)
194 {
195 long trunc;
196
197 fprintf(syncState->graphsStream,
198 "reset\n"
199 "set output \"%03d-%03d-%s.eps\"\n"
200 "plot \\\n", i, j, graphTypes[l].name);
201
202 pos1= ftell(syncState->graphsStream);
203
204 for (m= 0; m < sizeof(graphTypes[l].plotsOffsets) /
205 sizeof(*graphTypes[l].plotsOffsets); m++)
206 {
207 for (k= 0; k < sizeof(moduleGraphFunctions) /
208 sizeof(*moduleGraphFunctions); k++)
209 {
210 GraphFunction** writePlots= (void*)
211 moduleGraphFunctions[k] +
212 graphTypes[l].plotsOffsets[m];
213
214 if (*writePlots)
215 {
216 (*writePlots)(syncState, i, j);
217 }
218 }
219 }
220
221 fflush(syncState->graphsStream);
222 pos2= ftell(syncState->graphsStream);
223 if (pos1 != pos2)
224 {
225 // Remove the ", \\\n" from the last graph plot line
226 trunc= pos2 - 4;
227 }
228 else
229 {
230 // Remove the "plot \\\n" line to avoid creating an invalid
231 // gnuplot script
232 trunc= pos2 - 7;
233 }
234
235 if (ftruncate(fileno(syncState->graphsStream), trunc) == -1)
236 {
237 g_error(strerror(errno));
238 }
239 if (fseek(syncState->graphsStream, 0, SEEK_END) == -1)
240 {
241 g_error(strerror(errno));
242 }
243
244 fprintf(syncState->graphsStream,
245 "\nset output \"%03d-%03d-%s.eps\"\n"
246 "set title \"\"\n", i, j, graphTypes[l].name);
247
248 for (k= 0; k < sizeof(moduleGraphFunctions) /
249 sizeof(*moduleGraphFunctions); k++)
250 {
251 GraphFunction** writeOptions= (void*)
252 moduleGraphFunctions[k] + graphTypes[l].optionsOffset;
253
254 if (*writeOptions)
255 {
256 (*writeOptions)(syncState, i, j);
257 }
258 }
259
260 if (pos1 != pos2)
261 {
262 fprintf(syncState->graphsStream, "replot\n\n");
263 }
264 else
265 {
266 fprintf(syncState->graphsStream, "\n");
267 }
268 }
269 }
270 }
271 }
This page took 0.034078 seconds and 3 git commands to generate.