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