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)
-LDADD = $(M_LIBS)
+LDADD = $(M_LIBS) $(GLPK_LIBS)
 
 check_PROGRAMS = unittest
 
 unittest_SOURCES = \
-       unittest.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\
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
-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.
index d999c9ce4327cafd6eafb9b78e41aaec04ccb45d..5d10a08bf6b696178351b2e7043df4b8ba8b792c 100644 (file)
@@ -43,7 +43,7 @@ typedef struct _SyncState
 
 typedef struct
 {
-       const char shortName;
+       char shortName;
        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.035852 seconds and 4 git commands to generate.