Add sync_chain_unittest
authorBenjamin Poirier <benjamin.poirier@polymtl.ca>
Thu, 26 Nov 2009 22:03:06 +0000 (17:03 -0500)
committerBenjamin Poirier <benjamin.poirier@polymtl.ca>
Fri, 18 Dec 2009 19:04:17 +0000 (14:04 -0500)
Makes the former unitest program more compliant with the current architecture.

Signed-off-by: Benjamin Poirier <benjamin.poirier@polymtl.ca>
lttv/lttv/sync/Makefile.am
lttv/lttv/sync/README
lttv/lttv/sync/sync_chain.h
lttv/lttv/sync/sync_chain_unittest.c [new file with mode: 0644]
lttv/lttv/sync/unittest.c [deleted file]

index 84562f9825d6886e595e0630b3fd1587b1f092d2..cd08bb8d08bb4897e56b276b76b2b17a3646a291 100644 (file)
@@ -1,11 +1,13 @@
 AM_CFLAGS= $(PACKAGE_CFLAGS)
 AM_CFLAGS= $(PACKAGE_CFLAGS)
-LDADD = $(M_LIBS)
+LDADD = $(M_LIBS) $(GLPK_LIBS)
 
 check_PROGRAMS = unittest
 
 unittest_SOURCES = \
 
 check_PROGRAMS = unittest
 
 unittest_SOURCES = \
-       unittest.c\
        data_structures.c\
        data_structures.c\
+       graph_functions.c\
+       sync_chain.c\
+       sync_chain_unittest.c\
        event_matching_broadcast.c\
        event_matching_distributor.c\
        event_matching_tcp.c\
        event_matching_broadcast.c\
        event_matching_distributor.c\
        event_matching_tcp.c\
index ada0210b99f01ddc71a64450ea0b4fecbca17b00..4e6b19cea82af8e2c9b0091f4fb859201f01f20d 100644 (file)
@@ -192,9 +192,11 @@ This reads parameters, creates SyncState and calls the processing init
 function. The "sync chain" is the set of event-* modules. At the moment there
 is only one module at each stage. However, as more module are added, it will
 become relevant to have many modules at the same stage simultaneously. This
 function. The "sync chain" is the set of event-* modules. At the moment there
 is only one module at each stage. However, as more module are added, it will
 become relevant to have many modules at the same stage simultaneously. This
-will require some modifications. I've kept this possibility at the back of my
-mind while designing. It is already partly supported at the matching stage
-through encapsulation of other matching modules.
+will require some modifications. It is already partly supported at the
+matching stage through encapsulation of other matching modules.
+
+sync_chain_unitest provides a fairly simple example of sync chain
+implementation.
 
 ++ Stage 1: Event processing
 Specific to the tracing data source.
 
 ++ Stage 1: Event processing
 Specific to the tracing data source.
index d999c9ce4327cafd6eafb9b78e41aaec04ccb45d..5d10a08bf6b696178351b2e7043df4b8ba8b792c 100644 (file)
@@ -43,7 +43,7 @@ typedef struct _SyncState
 
 typedef struct
 {
 
 typedef struct
 {
-       const char shortName;
+       char shortName;
        const char* longName;
        enum {
                NO_ARG,
        const char* longName;
        enum {
                NO_ARG,
diff --git a/lttv/lttv/sync/sync_chain_unittest.c b/lttv/lttv/sync/sync_chain_unittest.c
new file mode 100644 (file)
index 0000000..3a6de57
--- /dev/null
@@ -0,0 +1,411 @@
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
+ *
+ * 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 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.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "sync_chain.h"
+
+
+struct OptionsInfo
+{
+       GArray* longOptions;
+       GString* optionString;
+       GQueue* index;
+};
+
+
+const char* processOptions(const int argc, char* const argv[]);
+static void usage(const char* const programName);
+static void gfPrintModuleOption(gpointer data, gpointer user_data);
+static void nullLog(const gchar *log_domain, GLogLevelFlags log_level, const
+       gchar *message, gpointer user_data);
+static void gfAddModuleOption(gpointer data, gpointer user_data);
+
+
+static ModuleOption optionSyncStats= {
+       .shortName= 's',
+       .longName= "sync-stats",
+       .hasArg= NO_ARG,
+       .optionHelp= "Print statistics and debug messages",
+};
+static char graphsDir[20];
+static ModuleOption optionSyncGraphs= {
+       .shortName= 'g',
+       .longName= "sync-graphs",
+       .hasArg= OPTIONAL_ARG,
+       .optionHelp= "Output gnuplot graph showing synchronization points",
+};
+static ModuleOption optionSyncAnalysis= {
+       .shortName= 'a',
+       .longName= "sync-analysis",
+       .hasArg= REQUIRED_ARG,
+       .optionHelp= "Specify which algorithm to use for event analysis",
+};
+
+
+/*
+ * Implement a sync chain, it is mostly for unittest and it does not depend on
+ * lttv
+ *
+ * Args:
+ *   argc, argv:   standard argument arrays
+ *
+ * Returns:
+ *   exit status from main() is always EXIT_SUCCESS
+ */
+int main(const int argc, char* const argv[])
+{
+       SyncState* syncState;
+       struct timeval startTime, endTime;
+       struct rusage startUsage, endUsage;
+       GList* result;
+       int retval;
+       bool stats;
+       const char* testCaseName;
+       GString* analysisModulesNames;
+
+       // Initialize data structures
+       syncState= malloc(sizeof(SyncState));
+
+       // Process command line arguments
+       g_assert(g_queue_get_length(&analysisModules) > 0);
+       optionSyncAnalysis.arg= ((AnalysisModule*)
+               g_queue_peek_head(&analysisModules))->name;
+       analysisModulesNames= g_string_new("Available modules: ");
+       g_queue_foreach(&analysisModules, &gfAppendAnalysisName,
+               analysisModulesNames);
+       // remove the last ", "
+       g_string_truncate(analysisModulesNames, analysisModulesNames->len - 2);
+       optionSyncAnalysis.argHelp= analysisModulesNames->str;
+
+       retval= snprintf(graphsDir, sizeof(graphsDir), "graphs-%d", getpid());
+       if (retval > sizeof(graphsDir) - 1)
+       {
+               graphsDir[sizeof(graphsDir) - 1]= '\0';
+       }
+       optionSyncGraphs.arg= graphsDir;
+
+       g_queue_push_head(&moduleOptions, &optionSyncAnalysis);
+       g_queue_push_head(&moduleOptions, &optionSyncGraphs);
+       g_queue_push_head(&moduleOptions, &optionSyncStats);
+
+       testCaseName= processOptions(argc, argv);
+
+       g_string_free(analysisModulesNames, TRUE);
+
+       if (optionSyncStats.present)
+       {
+               syncState->stats= true;
+               gettimeofday(&startTime, 0);
+               getrusage(RUSAGE_SELF, &startUsage);
+       }
+       else
+       {
+               syncState->stats= false;
+               g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, nullLog, NULL);
+       }
+
+       if (optionSyncGraphs.present)
+       {
+        // Create the graph directory right away in case the module initialization
+        // functions have something to write in it.
+        syncState->graphsDir= optionSyncGraphs.arg;
+        syncState->graphsStream= createGraphsDir(syncState->graphsDir);
+    }
+    else
+    {
+        syncState->graphsStream= NULL;
+        syncState->graphsDir= NULL;
+    }
+
+       // Identify modules
+       syncState->processingData= NULL;
+       result= g_queue_find_custom(&processingModules, "text",
+               &gcfCompareProcessing);
+       g_assert(result != NULL);
+       syncState->processingModule= (ProcessingModule*) result->data;
+
+       syncState->matchingData= NULL;
+       result= g_queue_find_custom(&matchingModules, "TCP", &gcfCompareMatching);
+       g_assert(result != NULL);
+       syncState->matchingModule= (MatchingModule*) result->data;
+
+       syncState->analysisData= NULL;
+       result= g_queue_find_custom(&analysisModules, optionSyncAnalysis.arg,
+               &gcfCompareAnalysis);
+       if (result != NULL)
+       {
+               syncState->analysisModule= (AnalysisModule*) result->data;
+       }
+       else
+       {
+               g_error("Analysis module '%s' not found", optionSyncAnalysis.arg);
+       }
+
+       // Initialize modules
+       syncState->processingModule->initProcessing(syncState, testCaseName);
+       syncState->matchingModule->initMatching(syncState);
+       syncState->analysisModule->initAnalysis(syncState);
+
+       // Process traceset
+       syncState->processingModule->finalizeProcessing(syncState);
+
+       // Write graphs file
+       if (syncState->graphsStream)
+       {
+               writeGraphsScript(syncState);
+
+               if (fclose(syncState->graphsStream) != 0)
+               {
+                       g_error(strerror(errno));
+               }
+       }
+
+       // Print statistics
+       if (syncState->stats)
+       {
+               printStats(syncState);
+       }
+
+       // Destroy modules and clean up
+       syncState->processingModule->destroyProcessing(syncState);
+       syncState->matchingModule->destroyMatching(syncState);
+       syncState->analysisModule->destroyAnalysis(syncState);
+
+       stats= syncState->stats;
+       free(syncState);
+
+       if (stats)
+       {
+               gettimeofday(&endTime, 0);
+               retval= getrusage(RUSAGE_SELF, &endUsage);
+
+               timeDiff(&endTime, &startTime);
+               timeDiff(&endUsage.ru_utime, &startUsage.ru_utime);
+               timeDiff(&endUsage.ru_stime, &startUsage.ru_stime);
+
+               printf("Synchronization time:\n");
+               printf("\treal time: %ld.%06ld\n", endTime.tv_sec, endTime.tv_usec);
+               printf("\tuser time: %ld.%06ld\n", endUsage.ru_utime.tv_sec,
+                       endUsage.ru_utime.tv_usec);
+               printf("\tsystem time: %ld.%06ld\n", endUsage.ru_stime.tv_sec,
+                       endUsage.ru_stime.tv_usec);
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+/*
+ * Read program arguments dans update ModuleOptions structures
+ *
+ * Args:
+ *   argc, argv:   standard argument arrays
+ *
+ * Returns:
+ *   Name of the test case file (first parameter)
+ */
+const char* processOptions(const int argc, char* const argv[])
+{
+       int c;
+       extern char* optarg;
+       extern int optind, opterr, optopt;
+       GArray* longOptions;
+       GString* optionString;
+       GQueue* index;
+
+       longOptions= g_array_sized_new(TRUE, FALSE, sizeof(struct option),
+               g_queue_get_length(&moduleOptions));
+       optionString= g_string_new("");
+       index= g_queue_new();
+
+       g_queue_foreach(&moduleOptions, &gfAddModuleOption, &(struct OptionsInfo)
+               {longOptions, optionString, index});
+
+       do
+       {
+               int optionIndex= 0;
+
+               c= getopt_long(argc, argv, optionString->str, (struct option*)
+                       longOptions->data, &optionIndex);
+
+               if (c >= 0 && c < g_queue_get_length(index))
+               {
+                       ModuleOption* moduleOption= g_queue_peek_nth(index, c);
+
+                       moduleOption->present= true;
+
+                       if (moduleOption->hasArg == REQUIRED_ARG || moduleOption->hasArg
+                               == OPTIONAL_ARG)
+                       {
+                               moduleOption->arg= optarg;
+                       }
+               }
+               else if (c == -1)
+               {
+                       break;
+               }
+               else if (c == '?')
+               {
+                       usage(argv[0]);
+                       abort();
+               }
+               else
+               {
+                       g_error("Option parse error");
+               }
+       } while (c != -1);
+
+       g_array_free(longOptions, TRUE);
+       g_string_free(optionString, TRUE);
+
+       if (argc <= optind)
+       {
+               fprintf(stderr, "Test file unspecified\n");
+               usage(argv[0]);
+               abort();
+       }
+
+       return argv[optind];
+}
+
+
+/*
+ * Print information about program options and arguments.
+ *
+ * Args:
+ *   programName:  name of the program, as contained in argv[0] for example
+ */
+static void usage(const char* const programName)
+{
+       printf(
+               "%s [options] <test file>\n"
+               "Options:\n", programName);
+
+       g_queue_foreach(&moduleOptions, &gfPrintModuleOption, NULL);
+}
+
+
+/*
+ * A GFunc for g_queue_foreach()
+ *
+ * Print analysis module names.
+ *
+ * Args:
+ *   data:         ModuleOption*, option
+ *   user_data:    NULL
+ */
+static void gfPrintModuleOption(gpointer data, gpointer user_data)
+{
+       ModuleOption* option= data;
+       int width= 0, sum= 0;
+       const int colWidth= 27;
+
+       printf("\t");
+
+       if (option->shortName)
+       {
+               printf("-%c, %n", option->shortName, &width);
+               sum+= width;
+       }
+
+       printf("--%-s%n", option->longName, &width);
+       sum+= width;
+
+       if (option->hasArg == REQUIRED_ARG || option->hasArg == OPTIONAL_ARG)
+       {
+               printf("=[..]%n", &width);
+               sum+= width;
+       }
+
+       if (option->optionHelp)
+       {
+               printf("%*s%s\n", colWidth - sum > 0 ? colWidth - sum : 0, "", option->optionHelp);
+       }
+
+       if (option->argHelp)
+       {
+               printf("\t%*s%s\n", colWidth, "", option->argHelp);
+       }
+
+       if ((option->hasArg == REQUIRED_ARG || option->hasArg == OPTIONAL_ARG) && option->arg)
+       {
+               printf("\t%*sDefault value: %s\n", colWidth, "", option->arg);
+       }
+}
+
+
+/*
+ * A Glib log function which does nothing.
+ */
+static void nullLog(const gchar *log_domain, GLogLevelFlags log_level, const
+       gchar *message, gpointer user_data)
+{}
+
+
+/*
+ * A GFunc for g_queue_foreach()
+ *
+ * Args:
+ *   data:         ModuleOption*, option
+ *   user_data:    struct OptionsInfo*, add option to this array of struct option
+ */
+static void gfAddModuleOption(gpointer data, gpointer user_data)
+{
+       ModuleOption* option= data;
+       struct OptionsInfo* optionsInfo= user_data;
+       struct option newOption;
+       // "[mixing enumerations] can still be considered bad style even though it
+       // is not strictly illegal" c.faq 2.22
+       const int conversion[]= {
+        [NO_ARG]= no_argument,
+        [OPTIONAL_ARG]= optional_argument,
+        [REQUIRED_ARG]= required_argument,
+    };
+       const char* colons[]= {
+        [NO_ARG]= "",
+        [OPTIONAL_ARG]= "::",
+        [REQUIRED_ARG]= ":",
+    };
+
+       newOption.name= option->longName;
+       newOption.has_arg= conversion[option->hasArg];
+       newOption.flag= NULL;
+       newOption.val= g_queue_get_length(optionsInfo->index);
+
+       g_array_append_val(optionsInfo->longOptions, newOption);
+       g_string_append(optionsInfo->optionString, colons[option->hasArg]);
+       g_queue_push_tail(optionsInfo->index, option);
+}
diff --git a/lttv/lttv/sync/unittest.c b/lttv/lttv/sync/unittest.c
deleted file mode 100644 (file)
index 9b99d32..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
- *
- * 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 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.
- *
- * 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.
- */
-
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "sync_chain.h"
-
-
-static void timeDiff(struct timeval* const end, const struct timeval* const start);
-static void usage(const char* const programName);
-static gint gcfCompareAnalysis(gconstpointer a, gconstpointer b);
-static void gfAppendAnalysisName(gpointer data, gpointer user_data);
-static unsigned int readTraceNb(FILE* testCase);
-static void skipCommentLines(FILE* testCase);
-static void processEvents(SyncState* const syncState, FILE* testCase);
-static void nullLog(const gchar *log_domain, GLogLevelFlags log_level, const
-       gchar *message, gpointer user_data);
-
-GQueue processingModules= G_QUEUE_INIT;
-GQueue matchingModules= G_QUEUE_INIT;
-GQueue analysisModules= G_QUEUE_INIT;
-
-// time values in test case files will be scaled by this factor
-const double freq= 1e9;
-
-
-/*
- * Create matching and analysis modules and feed them events read from a text
- * file.
- *
- * Idealy, this would've been a processing module but sync_chain.c and
- * ProcessingModule use some LTTV-specific types and functions. Unfortunately,
- * there is some code duplication from sync_chain.c
- *
- */
-int main(int argc, char* argv[])
-{
-       int c;
-       extern char* optarg;
-       extern int optind, opterr, optopt;
-       bool optionSyncStats= false;
-       char* optionGraphsDir= NULL;
-       FILE* testCase= NULL;
-
-       SyncState* syncState;
-       struct timeval startTime, endTime;
-       struct rusage startUsage, endUsage;
-       GList* result;
-       char* cwd;
-       FILE* graphsStream;
-       int graphsFp;
-       GArray* factors;
-
-       int retval;
-
-       syncState= malloc(sizeof(SyncState));
-
-       g_assert(g_queue_get_length(&analysisModules) > 0);
-       syncState->analysisModule= g_queue_peek_head(&analysisModules);
-
-       do
-       {
-               int optionIndex= 0;
-
-               static struct option longOptions[]=
-               {
-                       {"sync-stats", no_argument, 0, 's'},
-                       {"sync-graphs", optional_argument, 0, 'g'},
-                       {"sync-analysis", required_argument, 0, 'a'},
-                       {0, 0, 0, 0}
-               };
-
-               c= getopt_long(argc, argv, "sg::a:", longOptions, &optionIndex);
-
-               switch (c)
-               {
-                       case -1:
-                       case 0:
-                               break;
-
-                       case 's':
-                               if (!optionSyncStats)
-                               {
-                                       gettimeofday(&startTime, 0);
-                                       getrusage(RUSAGE_SELF, &startUsage);
-                               }
-                               optionSyncStats= true;
-                               break;
-
-                       case 'g':
-                               if (optarg)
-                               {
-                                       printf("xxx:%s\n", optarg);
-                                       optionGraphsDir= malloc(strlen(optarg));
-                                       strcpy(optionGraphsDir, optarg);
-                               }
-                               else
-                               {
-                                       optionGraphsDir= malloc(20);
-                                       retval= snprintf(optionGraphsDir, 20, "graphs-%d",
-                                               getpid());
-                                       if (retval > 20 - 1)
-                                       {
-                                               optionGraphsDir[20 - 1]= '\0';
-                                       }
-                               }
-                               break;
-
-                       case 'a':
-                               printf("xxx:%s\n", optarg);
-                               result= g_queue_find_custom(&analysisModules, optarg,
-                                       &gcfCompareAnalysis);
-                               if (result != NULL)
-                               {
-                                       syncState->analysisModule= (AnalysisModule*) result->data;
-                               }
-                               else
-                               {
-                                       g_error("Analysis module '%s' not found", optarg);
-                               }
-                               break;
-
-                       case '?':
-                               usage(argv[0]);
-                               abort();
-
-                       default:
-                               g_error("Option parse error");
-               }
-       } while (c != -1);
-
-       if (argc <= optind)
-       {
-               fprintf(stderr, "Test file unspecified\n");
-               usage(argv[0]);
-               abort();
-       }
-
-       testCase= fopen(argv[optind], "r");
-       if (testCase == NULL)
-       {
-               g_error(strerror(errno));
-       }
-
-       // Initialize data structures
-       syncState->traceNb= readTraceNb(testCase);
-
-       if (optionSyncStats)
-       {
-               syncState->stats= true;
-       }
-       else
-       {
-               syncState->stats= false;
-       }
-
-       syncState->graphs= optionGraphsDir;
-
-       if (!optionSyncStats)
-       {
-               g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, nullLog, NULL);
-       }
-
-       // Identify and initialize matching and analysis modules
-       syncState->matchingData= NULL;
-       syncState->analysisData= NULL;
-
-       g_assert(g_queue_get_length(&matchingModules) == 1);
-       syncState->matchingModule= (MatchingModule*)
-               g_queue_peek_head(&matchingModules);
-
-       graphsStream= NULL;
-       if (syncState->graphs)
-       {
-               // Create the graph directory right away in case the module initialization
-               // functions have something to write in it.
-               cwd= changeToGraphDir(syncState->graphs);
-
-               if (syncState->matchingModule->writeMatchingGraphsPlots != NULL)
-               {
-                       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 ((graphsStream= fdopen(graphsFp, "w")) == NULL)
-                       {
-                               g_error(strerror(errno));
-                       }
-               }
-
-               retval= chdir(cwd);
-               if (retval == -1)
-               {
-                       g_error(strerror(errno));
-               }
-               free(cwd);
-       }
-
-       syncState->matchingModule->initMatching(syncState);
-       syncState->analysisModule->initAnalysis(syncState);
-
-       // Process traceset
-       processEvents(syncState, testCase);
-
-       factors= syncState->matchingModule->finalizeMatching(syncState);
-
-       // Write graphs file
-       if (graphsStream != NULL)
-       {
-               unsigned int i, j;
-
-               fprintf(graphsStream,
-                       "#!/usr/bin/gnuplot\n\n"
-                       "#set terminal postscript eps color size 8in,6in\n");
-
-               // 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 pos;
-
-                               fprintf(graphsStream,
-                                       "\n#set output \"%03d-%03d.eps\"\n"
-                                       "plot \\\n", i, j);
-
-                               syncState->matchingModule->writeMatchingGraphsPlots(graphsStream,
-                                       syncState, i, j);
-
-                               // Remove the ", \\\n" from the last graph plot line
-                               fflush(graphsStream);
-                               pos= ftell(graphsStream);
-                               if (ftruncate(fileno(graphsStream), pos - 4) == -1)
-                               {
-                                       g_error(strerror(errno));
-                               }
-                               if (fseek(graphsStream, 0, SEEK_END) == -1)
-                               {
-                                       g_error(strerror(errno));
-                               }
-
-                               fprintf(graphsStream,
-                                       "\nset output \"%1$03d-%2$03d.eps\"\n"
-                                       "set title \"\"\n"
-                                       "set xlabel \"Clock %1$u\"\n"
-                                       "set xtics nomirror\n"
-                                       "set ylabel \"Clock %2$u\"\n"
-                                       "set ytics nomirror\n"
-                                       "set x2label \"Clock %1$u (s)\"\n"
-                                       "set x2range [GPVAL_X_MIN / %3$.1f : GPVAL_X_MAX / %3$.1f]\n"
-                                       "set x2tics\n"
-                                       "set y2label \"Clock %2$u (s)\"\n"
-                                       "set y2range [GPVAL_Y_MIN / %3$.1f: GPVAL_Y_MAX / %3$.1f]\n"
-                                       "set y2tics\n"
-                                       "set key inside right bottom\n", i, j, freq);
-
-                               syncState->matchingModule->writeMatchingGraphsOptions(graphsStream,
-                                       syncState, i, j);
-
-                               fprintf(graphsStream, "replot\n\n"
-                                       "pause -1\n");
-                       }
-               }
-
-               if (fclose(graphsStream) != 0)
-               {
-                       g_error(strerror(errno));
-               }
-       }
-       if (optionGraphsDir)
-       {
-               free(optionGraphsDir);
-       }
-
-       if (optionSyncStats && syncState->matchingModule->printMatchingStats !=
-               NULL)
-       {
-               unsigned int i;
-
-               syncState->matchingModule->printMatchingStats(syncState);
-
-               printf("Resulting synchronization factors:\n");
-               for (i= 0; i < syncState->traceNb; i++)
-               {
-                       Factors* traceFactors;
-
-                       traceFactors= &g_array_index(factors, Factors, i);
-                       printf("\ttrace %u drift= %g offset= %g\n", i,
-                               traceFactors->drift, traceFactors->offset);
-               }
-       }
-
-       syncState->matchingModule->destroyMatching(syncState);
-       syncState->analysisModule->destroyAnalysis(syncState);
-
-       free(syncState);
-
-       if (optionSyncStats)
-       {
-               gettimeofday(&endTime, 0);
-               retval= getrusage(RUSAGE_SELF, &endUsage);
-
-               timeDiff(&endTime, &startTime);
-               timeDiff(&endUsage.ru_utime, &startUsage.ru_utime);
-               timeDiff(&endUsage.ru_stime, &startUsage.ru_stime);
-
-               printf("Synchronization time:\n");
-               printf("\treal time: %ld.%06ld\n", endTime.tv_sec, endTime.tv_usec);
-               printf("\tuser time: %ld.%06ld\n", endUsage.ru_utime.tv_sec,
-                       endUsage.ru_utime.tv_usec);
-               printf("\tsystem time: %ld.%06ld\n", endUsage.ru_stime.tv_sec,
-                       endUsage.ru_stime.tv_usec);
-       }
-
-       return EXIT_SUCCESS;
-}
-
-
-/*
- * Print information about program options and arguments.
- *
- * Args:
- *   programName:  name of the program, as contained in argv[0] for example
- */
-static void usage(const char* const programName)
-{
-       GString* analysisModulesNames;
-
-       analysisModulesNames= g_string_new("");
-       g_queue_foreach(&analysisModules, &gfAppendAnalysisName,
-               analysisModulesNames);
-       // remove the last ", "
-       g_string_truncate(analysisModulesNames, analysisModulesNames->len - 2);
-
-       printf(
-               "%s [options] <test file>\n"
-               "Options:\n"
-               "\t-s, --sync-stats                 Print statistics and debug messages\n"
-               "\t-g, --sync-graphs[=OUPUT_DIR]    Generate graphs\n"
-               "\t-a, --sync-analysis=MODULE_NAME  Specify which module to use for analysis\n"
-               "\t                                 Available modules: %s\n",
-               programName, analysisModulesNames->str);
-
-       g_string_free(analysisModulesNames, TRUE);
-}
-
-
-/*
- * Calculate the elapsed time between two timeval values
- *
- * Args:
- *   end:          end time, result is also stored in this structure
- *   start:        start time
- */
-static void timeDiff(struct timeval* const end, const struct timeval* const start)
-{
-               if (end->tv_usec >= start->tv_usec)
-               {
-                       end->tv_sec-= start->tv_sec;
-                       end->tv_usec-= start->tv_usec;
-               }
-               else
-               {
-                       end->tv_sec= end->tv_sec - start->tv_sec - 1;
-                       end->tv_usec= end->tv_usec - start->tv_usec + 1e6;
-               }
-}
-
-
-/*
- * A GCompareFunc for g_slist_find_custom()
- *
- * Args:
- *   a:            AnalysisModule*, element's data
- *   b:            char*, user data to compare against
- *
- * Returns:
- *   0 if the analysis module a's name is b
- */
-static gint gcfCompareAnalysis(gconstpointer a, gconstpointer b)
-{
-       const AnalysisModule* analysisModule;
-       const char* name;
-
-       analysisModule= (const AnalysisModule*)a;
-       name= (const char*)b;
-
-       return strncmp(analysisModule->name, name, strlen(analysisModule->name) +
-               1);
-}
-
-
-/*
- * Change to the directory used to hold graphs. Create it if necessary.
- *
- * Args:
- *   graph:        name of directory
- *
- * Returns:
- *   The current working directory before the execution of the function. The
- *   string must be free'd by the caller.
- */
-char* changeToGraphDir(char* const graphs)
-{
-       int retval;
-       char* cwd;
-
-       cwd= getcwd(NULL, 0);
-       if (cwd == NULL)
-       {
-               g_error(strerror(errno));
-       }
-       while ((retval= chdir(graphs)) != 0)
-       {
-               if (errno == ENOENT)
-               {
-                       retval= mkdir(graphs, 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;
-}
-
-
-/*
- * A GFunc for g_queue_foreach()
- *
- * Concatenate analysis module names.
- *
- * Args:
- *   data:         AnalysisModule*
- *   user_data:    GString*, concatenated names
- */
-static void gfAppendAnalysisName(gpointer data, gpointer user_data)
-{
-       g_string_append((GString*) user_data, ((AnalysisModule*) data)->name);
-       g_string_append((GString*) user_data, ", ");
-}
-
-
-/*
- * Read trace number from the test case stream. The trace number should be the
- * first non-comment line and should be an unsigned int by itself on a line.
- *
- * Args:
- *   testCase:     test case stream
- *
- * Returns:
- *   The trace number
- */
-static unsigned int readTraceNb(FILE* testCase)
-{
-       unsigned int result;
-       int retval;
-       char* line= NULL;
-       size_t len;
-       char tmp;
-
-       skipCommentLines(testCase);
-       retval= getline(&line, &len, testCase);
-       if (retval == -1)
-       {
-               if (feof(testCase))
-               {
-                       g_error("Unexpected end of file while looking for number of traces");
-               }
-               else
-               {
-                       g_error(strerror(errno));
-               }
-       }
-       if (line[retval - 1] == '\n')
-       {
-               line[retval - 1]= '\0';
-       }
-
-       retval= sscanf(line, " %u %c", &result, &tmp);
-       if (retval == EOF || retval != 1)
-       {
-               g_error("Error parsing test file while looking for number of traces, line was '%s'", line);
-
-               // Not really needed but avoids warning from gcc
-               abort();
-       }
-
-       return result;
-}
-
-
-/*
- * Advance testCase stream over empty space, empty lines and lines that begin
- * with '#'
- *
- * Args:
- *   testCase:     test case stream
- */
-static void skipCommentLines(FILE* testCase)
-{
-       int firstChar;
-       ssize_t retval;
-       char* line= NULL;
-       size_t len;
-
-       do
-       {
-               firstChar= fgetc(testCase);
-               if (firstChar == (int) '#')
-               {
-                       retval= getline(&line, &len, testCase);
-                       if (retval == -1)
-                       {
-                               if (feof(testCase))
-                               {
-                                       goto outEof;
-                               }
-                               else
-                               {
-                                       g_error(strerror(errno));
-                               }
-                       }
-               }
-               else if (firstChar == (int) '\n' || firstChar == (int) ' ')
-               {}
-               else if (firstChar == EOF)
-               {
-                       goto outEof;
-               }
-               else
-               {
-                       break;
-               }
-       } while (true);
-       retval= ungetc(firstChar, testCase);
-       if (retval == EOF)
-       {
-               g_error("Error: ungetc()");
-       }
-
-outEof:
-       if (line)
-       {
-               free(line);
-       }
-}
-
-
-/*
- * Make up events from the messages in the test case. Dispatch those events to
- * the matching module.
- */
-static void processEvents(SyncState* const syncState, FILE* testCase)
-{
-       char* line= NULL;
-       size_t len;
-       int retval;
-       unsigned int addressOffset;
-       unsigned int* seq;
-
-       // Trace numbers run from 0 to traceNb - 1. addressOffset is added to a
-       // traceNum to convert it to an address.
-       addressOffset= pow(10, floor(log(syncState->traceNb - 1) / log(10)) + 1);
-
-       seq= calloc(syncState->traceNb, sizeof(unsigned int));
-
-       skipCommentLines(testCase);
-       retval= getline(&line, &len, testCase);
-       while(!feof(testCase))
-       {
-               unsigned int sender, receiver;
-               double sendTime, recvTime;
-               char tmp;
-               Event* event;
-
-               if (retval == -1 && !feof(testCase))
-               {
-                       g_error(strerror(errno));
-               }
-
-               if (line[len - 1] == '\n')
-               {
-                       line[len - 1]= '\0';
-               }
-
-               retval= sscanf(line, " %u %u %lf %lf %c", &sender, &receiver,
-                       &sendTime, &recvTime, &tmp);
-               if (retval == EOF)
-               {
-                       g_error(strerror(errno));
-               }
-               else if (retval != 4)
-               {
-                       g_error("Error parsing test file while looking for data point, line was '%s'", line);
-               }
-
-               if (sender + 1 > syncState->traceNb)
-               {
-                       g_error("Error parsing test file, sender is out of range, line was '%s'", line);
-               }
-
-               if (receiver + 1 > syncState->traceNb)
-               {
-                       g_error("Error parsing test file, receiver is out of range, line was '%s'", line);
-               }
-
-               // Output event
-               event= malloc(sizeof(Event));
-               event->traceNum= sender;
-               event->time= round(sendTime * freq);
-               event->type= TCP;
-               event->destroy= &destroyTCPEvent;
-               event->event.tcpEvent= malloc(sizeof(TCPEvent));
-               event->event.tcpEvent->direction= OUT;
-               event->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey));
-               event->event.tcpEvent->segmentKey->ihl= 5;
-               event->event.tcpEvent->segmentKey->tot_len= 40;
-               event->event.tcpEvent->segmentKey->connectionKey.saddr= sender + addressOffset;
-               event->event.tcpEvent->segmentKey->connectionKey.daddr= receiver + addressOffset;
-               event->event.tcpEvent->segmentKey->connectionKey.source= 57645;
-               event->event.tcpEvent->segmentKey->connectionKey.dest= 80;
-               event->event.tcpEvent->segmentKey->seq= seq[sender];
-               event->event.tcpEvent->segmentKey->ack_seq= 0;
-               event->event.tcpEvent->segmentKey->doff= 5;
-               event->event.tcpEvent->segmentKey->ack= 0;
-               event->event.tcpEvent->segmentKey->rst= 0;
-               event->event.tcpEvent->segmentKey->syn= 1;
-               event->event.tcpEvent->segmentKey->fin= 0;
-
-               syncState->matchingModule->matchEvent(syncState, event);
-
-               // Input event
-               event= malloc(sizeof(Event));
-               event->traceNum= receiver;
-               event->time= round(recvTime * freq);
-               event->type= TCP;
-               event->destroy= &destroyTCPEvent;
-               event->event.tcpEvent= malloc(sizeof(TCPEvent));
-               event->event.tcpEvent->direction= IN;
-               event->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey));
-               event->event.tcpEvent->segmentKey->ihl= 5;
-               event->event.tcpEvent->segmentKey->tot_len= 40;
-               event->event.tcpEvent->segmentKey->connectionKey.saddr= sender + addressOffset;
-               event->event.tcpEvent->segmentKey->connectionKey.daddr= receiver + addressOffset;
-               event->event.tcpEvent->segmentKey->connectionKey.source= 57645;
-               event->event.tcpEvent->segmentKey->connectionKey.dest= 80;
-               event->event.tcpEvent->segmentKey->seq= seq[sender];
-               event->event.tcpEvent->segmentKey->ack_seq= 0;
-               event->event.tcpEvent->segmentKey->doff= 5;
-               event->event.tcpEvent->segmentKey->ack= 0;
-               event->event.tcpEvent->segmentKey->rst= 0;
-               event->event.tcpEvent->segmentKey->syn= 1;
-               event->event.tcpEvent->segmentKey->fin= 0;
-
-               syncState->matchingModule->matchEvent(syncState, event);
-
-               seq[sender]++;
-
-               skipCommentLines(testCase);
-               retval= getline(&line, &len, testCase);
-       }
-
-       free(seq);
-
-       if (line)
-       {
-               free(line);
-       }
-}
-
-
-/*
- * A Glib log function which does nothing.
- */
-static void nullLog(const gchar *log_domain, GLogLevelFlags log_level, const
-       gchar *message, gpointer user_data)
-{}
This page took 0.039166 seconds and 4 git commands to generate.