X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fgraph_functions.c;h=91feef0c45c5a64f2cc28dc3424d3cf748ec4297;hb=df64b31664467d7217fa08fcdee423577856b38a;hp=9b61e1208c2718092587e83f36e413e0340b816c;hpb=467066eeab8b0a4e5ea07d24f1840310730fd470;p=lttv.git diff --git a/lttv/lttv/sync/graph_functions.c b/lttv/lttv/sync/graph_functions.c index 9b61e120..91feef0c 100644 --- a/lttv/lttv/sync/graph_functions.c +++ b/lttv/lttv/sync/graph_functions.c @@ -1,19 +1,18 @@ /* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2009 Benjamin Poirier + * Copyright (C) 2009, 2010 Benjamin Poirier * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation; + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or (at + * your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H @@ -21,6 +20,10 @@ #endif #include +#include +#include +#include +#include #include #include @@ -28,50 +31,189 @@ #include "graph_functions.h" +/* + * Create the directory used to hold graphs and the header of the gnuplot + * script. + * + * Args: + * graphsDir: name of directory + * + * Returns: + * The current working directory before the execution of the function. The + * string must be free'd by the caller. + */ +FILE* createGraphsDir(const char* const graphsDir) +{ + char* cwd; + int graphsFp; + FILE* result; + int retval; + + cwd= changeToGraphsDir(graphsDir); + + if ((graphsFp= open("graphs.gnu", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | + S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH + | S_IWOTH | S_IXOTH)) == -1) + { + g_error("%s", strerror(errno)); + } + if ((result= fdopen(graphsFp, "w")) == NULL) + { + g_error("%s", strerror(errno)); + } + + fprintf(result, + "#!/usr/bin/gnuplot\n\n" + "set terminal postscript eps color size 8in,6in\n"); + + retval= chdir(cwd); + if (retval == -1) + { + g_error("%s", strerror(errno)); + } + free(cwd); + + return result; +} + + +/* + * Change to the directory used to hold graphs. Create it if necessary. + * + * Args: + * graphsDir: name of directory + * + * Returns: + * The current working directory before the execution of the function. The + * string must be free'd by the caller. + */ +char* changeToGraphsDir(const char* const graphsDir) +{ + int retval; + char* cwd; + + cwd= getcwd(NULL, 0); + if (cwd == NULL) + { + g_error("%s", strerror(errno)); + } + while ((retval= chdir(graphsDir)) != 0) + { + if (errno == ENOENT) + { + retval= mkdir(graphsDir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); + if (retval != 0) + { + g_error("%s", strerror(errno)); + } + } + else + { + g_error("%s", strerror(errno)); + } + } + + return cwd; +} + + +/* + * Call each graph variable, option and plot line function of each module to + * produce a gnuplot script. + * + * Args: + * syncState: container for synchronization data + */ void writeGraphsScript(SyncState* const syncState) { - unsigned int i, j, k, l; + unsigned int i, j, k, l, m; + long pos1, pos2; + const GraphFunctions* moduleGraphFunctions[]= { + &syncState->processingModule->graphFunctions, + &syncState->matchingModule->graphFunctions, + &syncState->analysisModule->graphFunctions, + }; const struct { - size_t plotsOffset, - optionsOffset; char* name; - } funcTypes[]= { - {offsetof(GraphFunctions, writeTraceTracePlots), - offsetof(GraphFunctions, writeTraceTraceOptions), "TraceTrace"}, - {offsetof(GraphFunctions, writeTraceTimePlots), - offsetof(GraphFunctions, writeTraceTimeOptions), "TraceTime"}, + size_t plotsOffsets[2]; + size_t optionsOffset; + } graphTypes[]= { + { + "TraceTrace", + { + offsetof(GraphFunctions, writeTraceTraceBackPlots), + offsetof(GraphFunctions, writeTraceTraceForePlots), + }, + offsetof(GraphFunctions, writeTraceTraceOptions), + }, + { + "TraceTime", + { + offsetof(GraphFunctions, writeTraceTimeBackPlots), + offsetof(GraphFunctions, writeTraceTimeForePlots), + }, + offsetof(GraphFunctions, writeTraceTimeOptions), + }, }; - for (l= 0; l < sizeof(funcTypes) / sizeof(*funcTypes); l++) + fprintf(syncState->graphsStream, "\n"); + + // Write variables + pos1= ftell(syncState->graphsStream); + for (i= 0; i < syncState->traceNb; i++) + { + for (k= 0; k < sizeof(moduleGraphFunctions) / + sizeof(*moduleGraphFunctions); k++) + { + GraphVariableFunction** writeVariables= (void*) + moduleGraphFunctions[k] + offsetof(GraphFunctions, + writeVariables); + + if (*writeVariables) + { + (*writeVariables)(syncState, i); + } + } + } + fflush(syncState->graphsStream); + pos2= ftell(syncState->graphsStream); + if (pos1 != pos2) + { + fprintf(syncState->graphsStream, "\n"); + } + + // Write plots and options + for (l= 0; l < sizeof(graphTypes) / sizeof(*graphTypes); l++) { // Cover the upper triangular matrix, i is the reference node. for (i= 0; i < syncState->traceNb; i++) { for (j= i + 1; j < syncState->traceNb; j++) { - long pos1, pos2, trunc; - const GraphFunctions* moduleGraphFunctions[]= { - &syncState->processingModule->graphFunctions, - &syncState->matchingModule->graphFunctions, - &syncState->analysisModule->graphFunctions, - }; + long trunc; fprintf(syncState->graphsStream, "reset\n" "set output \"%03d-%03d-%s.eps\"\n" - "plot \\\n", i, j, funcTypes[l].name); + "plot \\\n", i, j, graphTypes[l].name); pos1= ftell(syncState->graphsStream); - for (k= 0; k < sizeof(moduleGraphFunctions) / - sizeof(*moduleGraphFunctions); k++) + for (m= 0; m < sizeof(graphTypes[l].plotsOffsets) / + sizeof(*graphTypes[l].plotsOffsets); m++) { - GraphFunction** writePlots= (void*) - moduleGraphFunctions[k] + funcTypes[l].plotsOffset; - - if (*writePlots) + for (k= 0; k < sizeof(moduleGraphFunctions) / + sizeof(*moduleGraphFunctions); k++) { - (*writePlots)(syncState, i, j); + GraphFunction** writePlots= (void*) + moduleGraphFunctions[k] + + graphTypes[l].plotsOffsets[m]; + + if (*writePlots) + { + (*writePlots)(syncState, i, j); + } } } @@ -91,22 +233,22 @@ void writeGraphsScript(SyncState* const syncState) if (ftruncate(fileno(syncState->graphsStream), trunc) == -1) { - g_error(strerror(errno)); + g_error("%s", strerror(errno)); } if (fseek(syncState->graphsStream, 0, SEEK_END) == -1) { - g_error(strerror(errno)); + g_error("%s", strerror(errno)); } fprintf(syncState->graphsStream, "\nset output \"%03d-%03d-%s.eps\"\n" - "set title \"\"\n", i, j, funcTypes[l].name); + "set title \"\"\n", i, j, graphTypes[l].name); for (k= 0; k < sizeof(moduleGraphFunctions) / sizeof(*moduleGraphFunctions); k++) { GraphFunction** writeOptions= (void*) - moduleGraphFunctions[k] + funcTypes[l].optionsOffset; + moduleGraphFunctions[k] + graphTypes[l].optionsOffset; if (*writeOptions) {