X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fgraph_functions.c;h=6bd28b8091ed26354b1d7a308934543ac0556c3f;hb=1d597550379cb00832f73bd5402918fd6ed2e9df;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..6bd28b80 100644 --- a/lttv/lttv/sync/graph_functions.c +++ b/lttv/lttv/sync/graph_functions.c @@ -21,6 +21,9 @@ #endif #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(strerror(errno)); + } + if ((result= fdopen(graphsFp, "w")) == NULL) + { + g_error(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(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(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(strerror(errno)); + } + } + else + { + g_error(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); + } } } @@ -100,13 +242,13 @@ void writeGraphsScript(SyncState* const syncState) 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) {