Make modules more flexible (builtin or loaded are identical). Add a test module
authordagenais <dagenais@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 9 Mar 2004 22:04:49 +0000 (22:04 +0000)
committerdagenais <dagenais@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 9 Mar 2004 22:04:49 +0000 (22:04 +0000)
to verify the state updating/saving functionality and performance.

git-svn-id: http://ltt.polymtl.ca/svn@493 04897980-b3bd-0310-b5e0-8ef037075253

20 files changed:
ltt/branches/poly/include/lttv/lttv.h
ltt/branches/poly/include/lttv/mainwindow.h
ltt/branches/poly/include/lttv/module.h
ltt/branches/poly/lttv/main/main.c
ltt/branches/poly/lttv/main/module.c
ltt/branches/poly/lttv/main/option.c
ltt/branches/poly/lttv/main/state.c
ltt/branches/poly/lttv/main/stats.c
ltt/branches/poly/lttv/modules/examples/sampledep.c
ltt/branches/poly/lttv/modules/examples/samplemodule.c
ltt/branches/poly/lttv/modules/examples/samplemodule2.c
ltt/branches/poly/lttv/modules/gui/controlflow/module.c
ltt/branches/poly/lttv/modules/gui/detailedevents/events.c
ltt/branches/poly/lttv/modules/gui/main/src/callbacks.c
ltt/branches/poly/lttv/modules/gui/main/src/callbacks.h
ltt/branches/poly/lttv/modules/gui/main/src/init_module.c
ltt/branches/poly/lttv/modules/gui/statistics/statistics.c
ltt/branches/poly/lttv/modules/text/batchAnalysis.c
ltt/branches/poly/lttv/modules/text/batchtest.c [new file with mode: 0644]
ltt/branches/poly/lttv/modules/text/textDump.c

index 4c9477adee598176b3e50c27c617829a22fb0811..27c610a2a67544deddd445f5271473cd2fd50cfc 100644 (file)
 
 LttvAttribute *lttv_global_attributes();
 
+extern gboolean lttv_profile_memory;
+
+extern int lttv_argc;
+
+extern char **lttv_argv;
 
 /* A number of global attributes are initialized before modules are
    loaded, for example hooks lists. More global attributes are defined
@@ -52,6 +57,4 @@ LttvAttribute *lttv_global_attributes();
 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
 
-extern gboolean lttv_profile_memory;
-
 #endif // LTTV_H
index db39fd6e1b316b3e21aa249bc0018134db208e78..ffdeefe500869ee5f714fa780ce9a2ebd8a86087 100644 (file)
 #include <lttv/hook.h>
 #include <lttv/stats.h>
 
-typedef struct _WindowCreationData {
-       int argc;
-       char ** argv;
-} WindowCreationData;
-
-
 typedef struct _TracesetInfo {
   //FIXME? TracesetContext and stats in same or different variable ?
   LttvTracesetStats * traceset_context;
@@ -69,8 +63,6 @@ struct _MainWindow{
   Tab * tab;
   Tab * current_tab;
 
-  WindowCreationData * win_creation_data; 
-
   GHashTable * hash_menu_item;
   GHashTable * hash_toolbar_item;
 };
index 39319151f8184bc5fbd0ddc745d96ade65a8db46..e88b7b92afaee406a5f3bd2085cb38331156236a 100644 (file)
 #ifndef MODULES_H
 #define MODULES_H
 
-#include <gmodule.h>
+#include <glib.h>
 
-/* lttv modules are shared object files, to be loaded dynamically, which
-   interact with the main module to provide additional capabilities. They
-   typically register hooks to be called at various places, read and add
-   attributes...
+/* A module contains some functionality which becomes available atfer it is
+   initialized and before it is destroyed. A module is characterized by a name,
+   a description (short and long), a list of names of other modules on which 
+   it depends, and an initialization and a destruction function.
 
-   Each lttv module must define a function named "init" with
-   the following signature. The init function may itself require other
-   modules using lttv_module_require. 
+   A library contains one or more modules and may be loaded dynamically.
+   The modules contained in a library are automatically registered through
+   constructors which are called when the library is loaded. For modules
+   directly linked with the main program (builtin), the constructors are
+   called before the main program starts. (However, neither malloc nor glib 
+   functions are used during the registration process).
 
-   It should also define a function named "destroy" to free the
-   resources reserved during execution.
-
-   Most modules will not use the command line arguments passed as init 
-   arguments. It is easier to simply register command line options 
-   to be parsed by the main module. However, some modules
-   may require an "early access" to these arguments, for example an embedded
-   python interpreter module which needs to know the modules written in
-   python to load. */
+   The library loading path is a set of directories, where requested
+   libraries and modules are searched for.
+*/
 
 typedef struct _LttvModule LttvModule;
 
-typedef void (*LttvModuleInit)(LttvModule *self, int argc, char **argv);
+typedef struct _LttvLibrary LttvLibrary;
+
+typedef void (*LttvModuleInit)();
 
 typedef void (*LttvModuleDestroy)();
 
+typedef struct _LttvModuleInfo
+{
+  char *name;
+  char *short_description;
+  char *description;
+  LttvModuleInit init;
+  LttvModuleDestroy destroy;
+  LttvLibrary *library;
+  unsigned require_count;
+  unsigned use_count;
+  unsigned prerequisites_number;
+} LttvModuleInfo;
+
+
+typedef struct _LttvLibraryInfo
+{
+  char *name;
+  char *path;
+  unsigned load_count;
+} LttvLibraryInfo;
+
+
+typedef enum _LttvModuleError 
+{
+  LTTV_MODULE_NOT_FOUND,
+  LTTV_MODULE_NO_INIT
+} LttvModuleError;
+
+
+/* Insure that a module is loaded and initialized. Require count 
+   (number of times the module was required) and use count 
+   (number of times required or used as prerequisite) serve to 
+   insure that a module is destroyed only after it has been released 
+   as many times as it was required (and prerequired).
+
+   The module is searched among the modules currently loaded, then as a 
+   similarly named library to load which should contain the named module.
+   If the module cannot be found or loaded, NULL is returned and an
+   explanation is provided in error. */
+
+LttvModule *lttv_module_require(char *name, GError **error);
+
+void lttv_module_release(LttvModule *m);
+
+
+/* Obtain information about the module, including the containing library */
+
+void lttv_module_info(LttvModule *m, LttvModuleInfo *info);
+
+
+/* List the modules on which this module depends */
+
+unsigned lttv_module_prerequisite_number(LttvModule *m);
+
+LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i);
+
+
+/* Insure that a library is loaded. A load count insures that a library 
+   is unloaded only after it has been asked to unload as
+   many times as it was loaded, and its modules are not in use. The library
+   is searched along the library path if name is a relative pathname. 
+   If the library cannot be found or loaded, NULL is returned and an 
+   explanation is provided in error. */
+
+LttvLibrary *lttv_library_load(char *name, GError **error);
 
-/* Additional module search paths may be defined. */
+void lttv_library_unload(LttvLibrary *l);
 
-void lttv_module_path_add(const char *name);
 
+/* Obtain information about the library */
 
-/* Load (or increment its reference count if already loaded) the named module.
-   The init function of the module is executed upon loading. */
+void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info);
 
-LttvModule *lttv_module_load(const char *name, int argc, char **argv);
 
+/* List the modules contained in a library */
 
-/* Module m depends on the named module. The named module will be loaded,
-   remembered by m as a dependent, and unloaded when m is unloaded. */
+unsigned lttv_library_module_number(LttvLibrary *l);
 
-LttvModule *lttv_module_require(LttvModule *m, const char *name, int argc,
-    char **argv);
+LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i);
 
 
-/* Decrement the reference count of the specified module and unload it if 0.
-   The destroy function of the module is executed before unloading. 
-   Dependent modules are unloaded. */
+/* List the currently loaded libraries */
 
-void lttv_module_unload(LttvModule *m) ;
+unsigned lttv_library_number();
 
+LttvLibrary *lttv_library_get(unsigned i);
 
-/* List the loaded modules. The returned array contains nb elements and
-   must be freed with g_free. */
 
-LttvModule **lttv_module_list(guint *nb);
 
+/* Add or remove directory names to the library search path */
 
-/* Obtain information about a module. The list of dependent module is
-   returned and must be freed with g_free. */
+void lttv_library_path_add(char *name);
 
-LttvModule **lttv_module_info(LttvModule *m, const char **name, 
-    guint *ref_count, guint *load_count, guint *nb_dependents);
+void lttv_library_path_remove(char *name);
+
+
+/* List the directory names in the library search path */
+
+unsigned lttv_library_path_number();
+
+char *lttv_library_path_get(unsigned i);
+
+
+/* To define a module, simply call the LTTV_MODULE macro with the needed
+   arguments: single word name, one line short description, larger
+   description, initialization function, destruction function, and
+   list of names for required modules (e.g., "moduleA", "moduleB").
+   This will insure that the module is registered at library load time.
+
+   Example:
+
+   LTTV_MODULE("option", "Command line options processing", "...", \
+       init, destroy, "moduleA", "moduleB") 
+*/
+
+#define LTTV_MODULE(name, short_desc, desc, init, destroy, ...) \
+  \
+  static void _LTTV_MODULE_REGISTER(__LINE__)() \
+      __attribute__((constructor));             \
+  \
+  static void _LTTV_MODULE_REGISTER(__LINE__)() \
+  { \
+    static char *module_prerequisites[] = { __VA_ARGS__ };     \
+    \
+    static struct _LttvModuleDescription module = { \
+        name, short_desc, desc, init, destroy, \
+        sizeof(module_prerequisites) / sizeof(char *), \
+        module_prerequisites, NULL}; \
+        \
+    lttv_module_register(&module); \
+  }
+
+
+/* Internal structure and function used to register modules, called by 
+   LTTV_MODULE */
+
+#define __LTTV_MODULE_REGISTER(line) _lttv_module_register_ ## line
+#define _LTTV_MODULE_REGISTER(line) __LTTV_MODULE_REGISTER(line)
+
+struct _LttvModuleDescription
+{
+  char *name;
+  char *short_description;
+  char *description;
+  LttvModuleInit init;
+  LttvModuleDestroy destroy;
+  unsigned prerequisites_number;
+  char **prerequisites;
+  struct _LttvModuleDescription *next;
+};
+
+void lttv_module_register(struct _LttvModuleDescription *d);
 
-char * lttv_module_name(LttvModule *m);
 #endif // MODULES_H
+
+
+
+
+
+
index fb9c7164e8578bceab33ab47b3925b49a414d7ab..a27519e8fe2c1791a912bc43742fe7bad34a8630 100644 (file)
 #include <lttv/traceset.h>
 #include <ltt/trace.h>
 #include <stdio.h>
-#include <mcheck.h>
 
 
-void lttv_option_init(int argc, char **argv);
-void lttv_option_destroy();
-
-void lttv_module_init(int argc, char **argv);
-void lttv_module_destroy();
-
-void lttv_state_init(int argc, char **argv);
-void lttv_state_destroy();
-
-void lttv_stats_init(int argc, char **argv);
-void lttv_stats_destroy();
-
 /* The main program maintains a few central data structures and relies
    on modules for the rest. These data structures may be accessed by modules
    through an exported API */
@@ -63,9 +50,9 @@ static gboolean
 
 gboolean lttv_profile_memory;
 
-static int a_argc;
+int lttv_argc;
 
-static char **a_argv;
+char **lttv_argv;
 
 static void lttv_module_option(void *hook_data);
 
@@ -100,6 +87,8 @@ int main(int argc, char **argv) {
 
   LttvAttributeValue value;
 
+  lttv_argc = argc;
+  lttv_argv = argv;
 
   /* Before anything else, check if memory profiling is requested */
 
@@ -107,7 +96,6 @@ int main(int argc, char **argv) {
     if(*(argv[i]) != '-') break;
     if(strcmp(argv[i], profile_memory_short_option) == 0 || 
        strcmp(argv[i], profile_memory_long_option) == 0) {
-      mcheck(0);
       g_mem_set_vtable(glib_mem_profiler_table);
       g_message("Memory summary before main");
       g_mem_profile();
@@ -153,17 +141,16 @@ int main(int argc, char **argv) {
 
   /* Initialize the command line options processing */
 
-  a_argc = argc;
-  a_argv = argv;
-  lttv_option_init(argc,argv);
-  lttv_module_init(argc,argv);
-  lttv_state_init(argc,argv);
-  lttv_stats_init(argc,argv);
+  GError *error = NULL;
 
+  LttvModule *module_module = lttv_module_require("module", &error);
+  if(error != NULL) g_error(error->message);
+  LttvModule *module_option = lttv_module_require("option", &error);
+  if(error != NULL) g_error(error->message);
 
   /* Initialize the module loading */
 
-  lttv_module_path_add(PACKAGE_PLUGIN_DIR);
+  lttv_library_path_add(PACKAGE_PLUGIN_DIR);
 
 
   /* Add some built-in options */
@@ -214,10 +201,8 @@ int main(int argc, char **argv) {
 
   /* Clean up everything */
 
-  lttv_stats_destroy();
-  lttv_state_destroy();
-  lttv_module_destroy();
-  lttv_option_destroy();
+  lttv_module_release(module_option);
+  lttv_module_release(module_module);
 
   lttv_hooks_destroy(before_options);
   lttv_hooks_destroy(after_options);
@@ -229,6 +214,7 @@ int main(int argc, char **argv) {
     g_message("Memory summary after main");
     g_mem_profile();
   }
+  return 0;
 }
 
 
@@ -240,13 +226,16 @@ LttvAttribute *lttv_global_attributes()
 
 void lttv_module_option(void *hook_data)
 { 
-  lttv_module_load(a_module,a_argc,a_argv);
+  GError *error = NULL;
+
+  lttv_module_require(a_module, &error);
+  if(error != NULL) g_error(error->message);
 }
 
 
 void lttv_module_path_option(void *hook_data)
 {
-  lttv_module_path_add(a_module_path);
+  lttv_library_path_add(a_module_path);
 }
 
 
@@ -272,13 +261,6 @@ void lttv_help(void *hook_data)
 
 /* 
 
-- Make it easier to change modules from builtin to externally loaded.
-
-    have: MODULE_INFO(name, init, destroy, { require} ) in each module.
-    Maintain the list of builtin modules and search these first (or 
-    optionally last). Add the lib prefix if needed to avoid having to
-    specify libbatchAnalysis instead of batchAnalysis.
-
 - Define formally traceset/trace in the GUI for the user and decide how
    trace/traceset sharing goes in the application.
 
index df98aacf7fe1426370523fa76dc75c61885a60c5..c4d3d6b07405c037a444cd11058e42cea2de876a 100644 (file)
@@ -1,3 +1,4 @@
+
 /* This file is part of the Linux Trace Toolkit viewer
  * Copyright (C) 2003-2004 Michel Dagenais
  *
  */
 
 
-/* module.c : Implementation of the module loading/unloading mechanism.
- * 
- */
+/* module.c : Implementation of the module loading/unloading mechanism. */
 
 #include <lttv/module.h>
+#include <gmodule.h>
+
+
+struct _LttvLibrary
+{
+  LttvLibraryInfo info;
+  GPtrArray *modules;
+  GModule *gm;
+  guint locked_loaded;
+};
+
 
 struct _LttvModule
 {
-  GModule *module;
-  guint ref_count;
-  guint load_count;
-  GPtrArray *dependents;
+  LttvModuleInfo info;
+  char **prerequisites_names;
+  GPtrArray *prerequisites;
 };
 
 
-/* Table of loaded modules and paths where to search for modules */
+/* Modules are searched by name. However, a library may be loaded which
+   provides a module with the same name as an existing one. A stack of
+   modules is thus maintained for each name. 
+
+   Libraries correspond to glib modules. The g_module function is 
+   responsible for loading each library only once. */
+
+static GHashTable *modules_by_name = NULL;
 
-static GHashTable *modules = NULL;
+static GPtrArray *libraries = NULL;
 
-static GPtrArray *modulesPaths = NULL;
+static GHashTable *libraries_by_g_module = NULL;
 
-static void lttv_module_unload_all();
+static GPtrArray *library_paths = NULL;
 
+static gboolean initialized = FALSE;
 
-void lttv_module_init(int argc, char **argv) 
+static gboolean destroyed = TRUE;
+
+static struct _LttvModuleDescription *builtin_chain = NULL;
+
+static struct _LttvModuleDescription *module_chain = NULL;
+
+static struct _LttvModuleDescription **module_next = &module_chain;
+
+static GQuark lttv_module_error;
+
+static void init();
+
+static finish_destroy();
+
+static void module_release(LttvModule *m);
+
+
+static LttvLibrary *library_add(char *name, char *path, GModule *gm)
 {
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init module.c");
-  modules = g_hash_table_new(g_str_hash, g_str_equal);
-  modulesPaths = g_ptr_array_new();
-}
+  LttvLibrary *l;
 
+  LttvModule *m;
 
-void lttv_module_destroy() 
-{  
-  int i;
+  struct _LttvModuleDescription *link;
 
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy module.c");
+  GPtrArray *modules;
+
+  l = g_new(LttvLibrary, 1);
+  l->modules = g_ptr_array_new();
+  l->gm = gm;
+  l->locked_loaded = 0;
+  l->info.name = g_strdup(name);
+  l->info.path = g_strdup(path);
+  l->info.load_count = 0;
 
-  /* Unload all modules */
-  lttv_module_unload_all();
+  g_ptr_array_add(libraries, l);
+  g_hash_table_insert(libraries_by_g_module, gm, l);
 
-  /* Free the modules paths pointer array as well as the elements */
-  for(i = 0; i < modulesPaths->len ; i++) {
-    g_free(modulesPaths->pdata[i]);
+  *module_next = NULL;
+  for(link = module_chain; link != NULL; link = link->next) {
+    m = g_new(LttvModule, 1);
+    g_ptr_array_add(l->modules, m);
+
+    modules = g_hash_table_lookup(modules_by_name, link->name);
+    if(modules == NULL) {
+      modules = g_ptr_array_new();
+      g_hash_table_insert(modules_by_name, g_strdup(link->name), modules);
+    }
+    g_ptr_array_add(modules, m);
+
+    m->prerequisites_names = link->prerequisites;
+    m->prerequisites = g_ptr_array_new();
+    m->info.name = link->name;
+    m->info.short_description = link->short_description;
+    m->info.description = link->description;
+    m->info.init = link->init;
+    m->info.destroy = link->destroy;
+    m->info.library = l;
+    m->info.require_count = 0;
+    m->info.use_count = 0;
+    m->info.prerequisites_number = link->prerequisites_number;
   }
-  g_ptr_array_free(modulesPaths,TRUE) ;
-  modulesPaths = NULL;
-  
-  /* destroy the hash table */
-  g_hash_table_destroy(modules) ;
-  modules = NULL;
+  return l;
 }
 
 
-/* Add a new pathname to the modules loading search path */
-
-void lttv_module_path_add(const char *name) 
+static void library_remove(LttvLibrary *l)
 {
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add module path %s", name);
-  g_ptr_array_add(modulesPaths,(char*)g_strdup(name));
+  LttvModule *m;
+
+  GPtrArray *modules;
+
+  guint i;
+
+  char *key;
+
+  for(i = 0 ; i < l->modules->len ; i++) {
+    m = (LttvModule *)(l->modules->pdata[i]);
+
+    g_hash_table_lookup_extended(modules_by_name, m->info.name, 
+                                (gpointer *)&key, (gpointer *)&modules);
+    g_assert(modules != NULL);
+    g_ptr_array_remove(modules, m);
+    if(modules->len == 0) {
+      g_hash_table_remove(modules_by_name, m->info.name);
+      g_ptr_array_free(modules, TRUE);
+      g_free(key);
+    }
+
+    g_ptr_array_free(m->prerequisites, TRUE);
+    g_free(m);
+  }
+
+  g_ptr_array_remove(libraries, l);
+  g_hash_table_remove(libraries_by_g_module, l->gm);
+  g_ptr_array_free(l->modules, TRUE);
+  g_free(l->info.name);
+  g_free(l->info.path);
+  g_free(l);
 }
 
 
-static LttvModule *
-module_load(const char *name, int argc, char **argv) 
+static LttvLibrary *library_load(char *name, GError **error)
 {
   GModule *gm;
 
-  LttvModule *m;
+  int i, nb;
+
+  char *path, *pathname;
+
+  LttvLibrary *l;
 
-  int i;
+  GString *messages = g_string_new("");
 
-  char *pathname;
+  /* insure that module.c is initialized */
 
-  const char *module_name;
-  
-  LttvModuleInit init_function;
+  init();
 
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load module %s", name);
+  /* Try to find the library along all the user specified paths */
 
-  /* Try to find the module along all the user specified paths */
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load library %s", name);
+  nb = lttv_library_path_number();
+  for(i = 0 ; i <= nb ; i++) {
+    if(i < nb) path = lttv_library_path_get(i);
+    else path = NULL;
 
-  for(i = 0 ; i < modulesPaths->len ; i++) {
-    pathname = g_module_build_path(modulesPaths->pdata[i],name);
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Try path %s", pathname);
+    pathname = g_module_build_path(path ,name);
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Try path %s", pathname);
+    module_chain = NULL;
+    module_next = &module_chain;
     gm = g_module_open(pathname,0);
     g_free(pathname);    
     
     if(gm != NULL) break;
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Trial failed, %s",g_module_error());
-  }
-
-  /* Try the default system path */
 
-  if(gm == NULL) {
-    pathname = g_module_build_path(NULL,name);
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Try default path");
-    gm = g_module_open(pathname,0);
-    g_free(pathname);
+    g_string_append(messages, g_module_error());
+    g_string_append(messages, "\n");
+    g_log(G_LOG_DOMAIN,G_LOG_LEVEL_INFO,"Trial failed, %s", g_module_error());
   }
 
   /* Module cannot be found */
+
   if(gm == NULL) {
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Trial failed, %s",g_module_error());
-    g_warning("Failed to load module %s", name); 
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Failed to load %s", name); 
+    g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+          "Cannot load library %s: %s", name, messages->str);
+    g_string_free(messages, TRUE);
     return NULL;
   }
+  g_string_free(messages, TRUE);
+
+  /* Check if the library was already loaded */
+
+  l = g_hash_table_lookup(libraries_by_g_module, gm);
 
-  /* Check if the module was already opened using the hopefully canonical name
-     returned by g_module_name. */
+  /* This library was not already loaded */
 
-  module_name = g_module_name(gm);
+  if(l == NULL) {
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Library %s (%s) loaded", name, 
+        g_module_name(gm));
+    l = library_add(name, path, gm);
+  }
+  return l;
+}
 
-  m = g_hash_table_lookup(modules, module_name);
 
-  if(m == NULL) {
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, 
-        "Module %s (%s) loaded, call its init function", name, module_name);
+LttvLibrary *lttv_library_load(char *name, GError **error)
+{
+  LttvLibrary *l = library_load(name, error); 
+  l->info.load_count++;
+  return l;
+}
 
-    /* Module loaded for the first time. Insert it in the table and call the
-       init function if any. */
 
-    m = g_new(LttvModule, 1);
-    m->module = gm;
-    m->ref_count = 0;
-    m->load_count = 0;
-    m->dependents = g_ptr_array_new();
-    g_hash_table_insert(modules, (gpointer)module_name, m);
-
-    if(!g_module_symbol(gm, "init", (gpointer)&init_function)) {
-      g_warning("module %s (%s) has no init function", name, pathname);
-    }
-    else init_function(m, argc, argv);
+static void library_unload(LttvLibrary *l)
+{
+  guint i, len;
+
+  GModule *gm;
+
+  LttvModule *m;
+
+  if(l->locked_loaded > 0) {
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded", 
+        l->info.name);
+    return;
+  }
+
+  if(l->info.load_count > 0) {
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d", 
+       l->info.name, l->info.load_count);
+    return;
   }
-  else {
 
-    /* Module was already opened, check that it really is the same and
-       undo the extra g_module_open */
+  /* Check if all its modules have been released */
 
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, 
-        "Module %s (%s) was already loaded, no need to call init function",
-       name, module_name);
-    if(m->module != gm) g_error("Two gmodules with the same pathname");
-    g_module_close(gm);
+  for(i = 0 ; i < l->modules->len ; i++) {
+    m = (LttvModule *)(l->modules->pdata[i]);
+    if(m->info.use_count > 0) {
+      g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used",
+          l->info.name, m->info.name);
+      return;
+    }
   }
-  m->ref_count++;
-  return m;
+
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: close the GModule",
+       l->info.name);
+  gm = l->gm;
+  library_remove(l);
+  if(gm != NULL) g_module_close(gm);
+
+  /* insure that module.c will be finalized */
+
+  finish_destroy();
 }
 
 
-LttvModule *
-lttv_module_load(const char *name, int argc, char **argv) 
+void lttv_library_unload(LttvLibrary *l)
 {
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load module %s explicitly", name);
-  LttvModule *m = module_load(name, argc, argv);
-  if(m != NULL) m->load_count++;
-  return m;
+  l->info.load_count--;
+  library_unload(l);
 }
 
 
-LttvModule *
-lttv_module_require(LttvModule *m, const char *name, int argc, char **argv)
+static void library_lock_loaded(LttvLibrary *l)
 {
-  LttvModule *module;
-
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, 
-      "Load module %s, as %s is a dependent requiring it", name, 
-      g_module_name(m->module));
-  module = module_load(name, argc, argv);
-  if(module != NULL) g_ptr_array_add(m->dependents, module);
-  return module;
+  l->locked_loaded++;
 }
 
 
-static void module_unload(LttvModule *m) 
+static void library_unlock_loaded(LttvLibrary *l)
 {
-  LttvModuleDestroy destroy_function;
+  l->locked_loaded--;
+  library_unload(l);
+}
 
-  char *pathname;
 
-  guint i, len;
+static LttvModule *module_require(char *name, GError **error)
+{
+  GError *tmp_error = NULL;
 
-  /* Decrement the reference count */
+  guint i, j;
 
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload module %s", 
-      g_module_name(m->module));
-  m->ref_count--;
-  if(m->ref_count > 0) {
-    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, 
-        "Module usage count decremented to %d", m->ref_count);
-    return;
-  }
+  LttvModule *m, *required;
+
+  LttvLibrary *l = NULL;
+
+  GPtrArray *modules;
+
+  /* Insure that module.c is initialized */
+
+  init();
 
-  /* We really have to unload the module. First destroy it. */
+  /* Check if the module is already loaded */
 
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, 
-      "Call the destroy function and unload the module");
-  if(!g_module_symbol(m->module, "destroy", (gpointer)&destroy_function)) {
-    g_warning("module (%s) has no destroy function", pathname);
+  modules = g_hash_table_lookup(modules_by_name, name);
+
+  /* Try to load a library having the module name */
+
+  if(modules == NULL) {
+    l = library_load(name, error);
+    if(l == NULL) return NULL;
+    else library_lock_loaded(l);
+
+    /* A library was found, does it contain the named module */
+
+    modules = g_hash_table_lookup(modules_by_name, name);
+    if(modules == NULL) {
+      g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+          "Module %s not found in library %s", name, l->info.name);
+      library_unlock_loaded(l);
+      return NULL;
+    }
   }
-  else destroy_function();
+  m = (LttvModule *)(modules->pdata[modules->len - 1]);
 
-  /* Then release the modules required by this module */
+  /* We have the module */
 
-  len = m->dependents->len;
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload dependent modules");
+  m->info.use_count++;
 
-  for(i = 0 ; i < len ; i++) {
-    module_unload(m->dependents->pdata[i]);
+  /* First use of the module. Initialize after getting the prerequisites */
+
+  if(m->info.use_count == 1) {
+    for(i = 0 ; i < m->info.prerequisites_number ; i++) {
+      required = module_require(m->prerequisites_names[i], &tmp_error);
+
+      /* A prerequisite could not be found, undo everything and fail */
+
+      if(required == NULL) {
+        for(j = 0 ; j < m->prerequisites->len ; j++) {
+          module_release((LttvModule *)(m->prerequisites->pdata[j]));
+        }
+        g_ptr_array_set_size(m->prerequisites, 0);
+        if(l != NULL) library_unlock_loaded(l);
+        g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+            "Cannot find prerequisite for module %s: %s", name, 
+           tmp_error->message);
+        g_clear_error(&tmp_error);
+        return NULL;
+      }
+      g_ptr_array_add(m->prerequisites, required);
+    }
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: init()", m->info.name);
+    m->info.init();
   }
 
-  if(len != m->dependents->len) g_error("dependents list modified");
+  /* Decrement the load count of the library. It will not really be 
+     unloaded since it contains a currently used module. */
+
+  if(l != NULL) library_unlock_loaded(l);
 
-  /* Finally remove any trace of this module */
+  return(m);
+}
+
+
+/* The require_count for a module is the number of explicit calls to 
+   lttv_module_require, while the use_count also counts the number of times
+   a module is needed as a prerequisite. */
 
-  g_hash_table_remove(modules, g_module_name(m->module));
-  g_ptr_array_free(m->dependents, TRUE);
-  g_module_close(m->module);
-  g_free(m);
+LttvModule *lttv_module_require(char *name, GError **error)
+{
+  LttvModule *m = module_require(name, error);
+  if(m != NULL) m->info.require_count++;
+  return(m);
 }
 
 
-void lttv_module_unload(LttvModule *m) 
+static void module_release(LttvModule *m)
 {
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Explicitly unload module %s", 
-      g_module_name(m->module));
-  if(m->load_count <= 0) { 
-    g_error("more unload than load (%s)", g_module_name(m->module));
-    return;
+  guint i;
+
+  library_lock_loaded(m->info.library);
+
+  m->info.use_count--;
+  if(m->info.use_count == 0) {
+    g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: destroy()",m->info.name);
+    m->info.destroy();
+    for(i = 0 ; i < m->prerequisites->len ; i++) {
+      module_release((LttvModule *)(m->prerequisites->pdata[i]));
+    }
+    g_ptr_array_set_size(m->prerequisites, 0);
   }
-  m->load_count--;
-  module_unload(m);
+  library_unlock_loaded(m->info.library);
+}
+
+
+void lttv_module_release(LttvModule *m)
+{
+  m->info.require_count--;
+  module_release(m);
+}
+
+
+void lttv_module_info(LttvModule *m, LttvModuleInfo *info)
+{
+  *info = m->info;
+}
+
+
+unsigned lttv_module_prerequisite_number(LttvModule *m)
+{
+  return m->prerequisites->len;
+}
+
+
+LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i)
+{
+  return (LttvModule *)(m->prerequisites->pdata[i]);
+}
+
+
+void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info)
+{
+  *info = l->info;
+}
+
+
+unsigned lttv_library_module_number(LttvLibrary *l)
+{
+  return l->modules->len;
+}
+
+
+LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i)
+{
+  return (LttvModule *)(l->modules->pdata[i]);
+}
+
+
+unsigned lttv_library_number()
+{
+  return libraries->len;  
 }
 
 
-static void
-list_modules(gpointer key, gpointer value, gpointer user_data)
+LttvLibrary *lttv_library_get(unsigned i)
 {
-  g_ptr_array_add((GPtrArray *)user_data, value);
+  return (LttvLibrary *)(libraries->pdata[i]);
 }
 
 
-LttvModule **
-lttv_module_list(guint *nb)
+void lttv_library_path_add(char *name)
 {
-  GPtrArray *list = g_ptr_array_new();
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add library path %s", name);
+  g_ptr_array_add(library_paths,(char*)g_strdup(name));
+}
+
 
-  LttvModule **array;
+void lttv_library_path_remove(char *name) 
+{
+  guint i;
 
-  g_hash_table_foreach(modules, list_modules, list);
-  *nb = list->len;
-  array = (LttvModule **)list->pdata;
-  g_ptr_array_free(list, FALSE);
-  return array;
+  for(i = 0 ; i < library_paths->len ; i++) {
+    if(g_str_equal(name, library_paths->pdata[i])) {
+      g_free(library_paths->pdata[i]);
+      g_ptr_array_remove_index(library_paths,i);
+      return;
+    }
+  }
 }
 
 
-LttvModule **
-lttv_module_info(LttvModule *m, const char **name, 
-    guint *ref_count, guint *load_count, guint *nb_dependents)
+unsigned lttv_library_path_number()
 {
-  guint i, len = m->dependents->len;
+  return library_paths->len;
+}
 
-  LttvModule **array = g_new(LttvModule *, len);
 
-  *name = g_module_name(m->module);
-  *ref_count = m->ref_count;
-  *load_count = m->load_count;
-  *nb_dependents = len;
-  for(i = 0 ; i < len ; i++) array[i] = m->dependents->pdata[i];
-  return array;
+char *lttv_library_path_get(unsigned i)
+{
+  return (char *)(library_paths->pdata[library_paths->len - i - 1]);
 }
 
-char * 
-lttv_module_name(LttvModule *m)
+
+void lttv_module_register(struct _LttvModuleDescription *d)
 {
-  return g_module_name(m->module);
+  *module_next = d;
+  module_next = &(d->next);
 }
 
-static void
-list_independent(gpointer key, gpointer value, gpointer user_data)
+
+static void init() 
 {
-  LttvModule *m = (LttvModule *)value;
+  if(initialized) return;
+  g_assert(destroyed);
+
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init module.c");
 
-  if(m->load_count > 0) g_ptr_array_add((GPtrArray *)user_data, m);
+  initialized = TRUE;
+  destroyed = FALSE;
+  lttv_module_error = g_quark_from_string("LTTV_MODULE_ERROR");
+  modules_by_name = g_hash_table_new(g_str_hash, g_str_equal);
+  libraries = g_ptr_array_new();
+  libraries_by_g_module = g_hash_table_new(g_direct_hash, g_direct_equal);
+  library_paths = g_ptr_array_new();
+
+  if(builtin_chain == NULL) builtin_chain = module_chain;
+  module_chain = builtin_chain;
+  library_add("builtin", NULL, NULL);
 }
 
 
-void
-lttv_module_unload_all()
+static finish_destroy()
 {
   guint i;
 
+  if(initialized) return;
+  g_assert(!destroyed);
+
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Finish destroy module.c");
+  g_hash_table_destroy(modules_by_name);
+  g_ptr_array_free(libraries, TRUE);
+  g_hash_table_destroy(libraries_by_g_module);
+  for(i = 0 ; i < library_paths->len ; i++) {
+    g_free(library_paths->pdata[i]);
+  }
+  g_ptr_array_free(library_paths, TRUE);
+  destroyed = TRUE;
+}
+
+
+static void destroy() 
+{  
+  guint i, j, nb;
+
+  LttvLibrary *l, **locked_libraries;
+
   LttvModule *m;
 
-  GPtrArray *independent_modules;
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy module.c");
+
+  /* Unload all libraries */
 
-  while(g_hash_table_size(modules) != 0) {
-    independent_modules = g_ptr_array_new();
-    g_hash_table_foreach(modules, list_independent, independent_modules);
+  nb = libraries->len;
+  locked_libraries = g_new(LttvLibrary *, nb);
 
-    for(i = 0 ; i < independent_modules->len ; i++) {
-      m = (LttvModule *)independent_modules->pdata[i];
-      lttv_module_unload(m);
+  for(i = 0 ; i < nb ; i++) {
+    l = (LttvLibrary *)(libraries->pdata[i]);
+    locked_libraries[i] = l;
+    library_lock_loaded(l);
+    for(j = 0 ; j < l->modules->len ; j++) {
+      m = (LttvModule *)(l->modules->pdata[j]);
+      while(m->info.require_count > 0) lttv_module_release(m);
     }
-    g_ptr_array_free(independent_modules, TRUE);
+    while(l->info.load_count > 0) lttv_library_unload(l);
+  }
+
+  for(i = 0 ; i < nb ; i++) {
+    l = locked_libraries[i];
+    library_unlock_loaded(l);
   }
+  g_free(locked_libraries);
+
+  /* The library containing module.c may be locked by our caller */
+
+  g_assert(libraries->len <= 1); 
+
+  initialized = FALSE;
 }
+
+LTTV_MODULE("module", "Modules in libraries",                        \
+    "Load libraries, list, require and initialize contained modules", \
+    init, destroy)
+
index 7c80b7f65541215da8d9482c58057f6ed4fd425c..7532073ed95c6e9f90f902c4833c66e7694512ed 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <popt.h>
 #include <glib.h>
+#include <lttv/module.h>
 #include <lttv/option.h>
 
 typedef struct _LttvOption {
@@ -52,32 +53,6 @@ free_option(LttvOption *option)
 }
 
 
-void lttv_option_init(int argc, char **argv)
-{
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
-  options = g_hash_table_new(g_str_hash, g_str_equal);
-}
-
-
-void lttv_option_destroy()
-{
-  LttvOption option;
-
-  GPtrArray *list = g_ptr_array_new();
-
-  int i;
-
-  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
-  g_hash_table_foreach(options, list_options, list);
-  g_hash_table_destroy(options);
-
-  for(i = 0 ; i < list->len ; i++) {
-    free_option((LttvOption *)list->pdata[i]);
-  }
-  g_ptr_array_free(list, TRUE);
-}
-
-
 void lttv_option_add(const char *long_name, const char char_name,
     const char *description, const char *arg_description,
     const LttvOptionType t, void *p,
@@ -251,6 +226,7 @@ void lttv_option_parse(int argc, char **argv)
   destroy_popts(&list, &popts, &c);
 }
 
+/* CHECK */
 static void show_help(LttvOption *option)
 {
   printf("--%s  -%c  argument: %s\n" , option->long_name,
@@ -281,3 +257,31 @@ void lttv_option_show_help(void)
 
 }
 
+static void init()
+{
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
+  options = g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+
+static void destroy()
+{
+  LttvOption option;
+
+  GPtrArray *list = g_ptr_array_new();
+
+  int i;
+
+  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
+  g_hash_table_foreach(options, list_options, list);
+  g_hash_table_destroy(options);
+
+  for(i = 0 ; i < list->len ; i++) {
+    free_option((LttvOption *)list->pdata[i]);
+  }
+  g_ptr_array_free(list, TRUE);
+}
+
+LTTV_MODULE("option", "Command line options processing", \
+    "Functions to add, remove and parse command line options", \
+    init, destroy)
index 5f67bf7b4cdb2f84757c96809c4ef98e78ceff44..c69d6a6a8088f5a52286c2e335ce1af7f1844b44 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 
+#include <lttv/lttv.h>
+#include <lttv/module.h>
 #include <lttv/state.h>
 #include <ltt/facility.h>
 #include <ltt/trace.h>
@@ -150,7 +152,10 @@ init(LttvTracesetState *self, LttvTraceset *ts)
     tcs->save_interval = 50000;
     lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, 
         LTTV_POINTER, &v);
-    if(*(v.v_pointer) == NULL) *(v.v_pointer) = g_new(LttTime,1);
+    if(*(v.v_pointer) == NULL) {
+      *(v.v_pointer) = g_new(LttTime,1);
+      *((LttTime *)*(v.v_pointer)) = time_zero;
+    }
     tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
 
     fill_name_tables(tcs);
@@ -263,7 +268,9 @@ void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
 
   for(i = 0 ; i < nb_tracefile ; i++) {
     tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
-    fprintf(fp, "  <TRACEFILE PID=%u", tfcs->process->pid);
+    fprintf(fp, "  <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu", 
+        tfcs->process->pid, tfcs->parent.timestamp.tv_sec, 
+        tfcs->parent.timestamp.tv_nsec);
     if(tfcs->parent.e == NULL) fprintf(fp,"/>\n");
     else {
       ltt_event_position(tfcs->parent.e, ep);
@@ -359,6 +366,12 @@ static void state_save(LttvTraceState *self, LttvAttribute *container)
       ep = ltt_event_position_new();
       ltt_event_position(tfcs->parent.e, ep);
       *(value.v_pointer) = ep;
+
+      guint nb_block, nb_event;
+      LttTracefile *tf;
+      ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+      g_debug("Block %u event %u time %lu.%lu", nb_block, nb_event,
+          tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
     }
   }
 }
@@ -583,12 +596,12 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
   guint depth = process->execution_stack->len - 1;
 
   if(process->state->t != t){
-    g_warning("Different execution mode type (%d.%09d): ignore it\n",
+    g_info("Different execution mode type (%d.%09d): ignore it\n",
         tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
-    g_warning("process state has %s when pop_int is %s\n",
+    g_info("process state has %s when pop_int is %s\n",
                    g_quark_to_string(process->state->t),
                    g_quark_to_string(t));
-    g_warning("{ %u, %u, %s, %s }\n",
+    g_info("{ %u, %u, %s, %s }\n",
                    process->pid,
                    process->ppid,
                    g_quark_to_string(process->name),
@@ -597,7 +610,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
   }
 
   if(depth == 0){
-    g_warning("Trying to pop last state on stack (%d.%09d): ignore it\n",
+    g_info("Trying to pop last state on stack (%d.%09d): ignore it\n",
         tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
     return;
   }
@@ -970,7 +983,7 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self)
 }
 
 
-static gboolean block_end(void *hook_data, void *call_data)
+static gboolean block_start(void *hook_data, void *call_data)
 {
   LttvTracefileState *self = (LttvTracefileState *)call_data;
 
@@ -1015,12 +1028,36 @@ static gboolean block_end(void *hook_data, void *call_data)
     *(value.v_time) = self->parent.timestamp;
     lttv_state_save(tcs, saved_state_tree);
     tcs->nb_event = 0;
+    g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
+           self->parent.timestamp.tv_nsec);
   }
   *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
   return FALSE;
 }
 
 
+static gboolean block_end(void *hook_data, void *call_data)
+{
+  LttvTracefileState *self = (LttvTracefileState *)call_data;
+
+  LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
+
+  LttTracefile *tf;
+
+  LttEventPosition *ep;
+
+  guint nb_block, nb_event;
+
+  ep = ltt_event_position_new();
+  ltt_event_position(self->parent.e, ep);
+  ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+  tcs->nb_event += nb_event - self->saved_position + 1;
+  self->saved_position = 0;
+  *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
+  g_free(ep);
+}
+
+
 void lttv_state_save_add_event_hooks(LttvTracesetState *self)
 {
   LttvTraceset *traceset = self->parent.ts;
@@ -1031,13 +1068,15 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self)
 
   LttvTracefileState *tfs;
 
-  LttvTraceHook hook;
+  LttvTraceHook hook_start, hook_end;
 
   nb_trace = lttv_traceset_number(traceset);
   for(i = 0 ; i < nb_trace ; i++) {
     ts = (LttvTraceState *)self->parent.traces[i];
+    lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL, 
+       NULL, NULL, block_start, &hook_start);
     lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, 
-       NULL, NULL, block_end, &hook);
+       NULL, NULL, block_end, &hook_end);
 
     nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
         ltt_trace_per_cpu_tracefile_number(ts->parent.t);
@@ -1045,7 +1084,9 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self)
     for(j = 0 ; j < nb_tracefile ; j++) {
       tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
       lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, 
-         hook.id), hook.h, NULL);
+         hook_start.id), hook_start.h, NULL);
+      lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, 
+         hook_end.id), hook_end.h, NULL);
     }
   }
 }
@@ -1061,13 +1102,16 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
 
   LttvTracefileState *tfs;
 
-  LttvTraceHook hook;
+  LttvTraceHook hook_start, hook_end;
 
   nb_trace = lttv_traceset_number(traceset);
   for(i = 0 ; i < nb_trace ; i++) {
     ts = LTTV_TRACE_STATE(self->parent.traces[i]);
+    lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL, 
+       NULL, NULL, block_start, &hook_start);
+
     lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, 
-       NULL, NULL, block_end, &hook);
+       NULL, NULL, block_end, &hook_end);
 
     nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
         ltt_trace_per_cpu_tracefile_number(ts->parent.t);
@@ -1075,7 +1119,9 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
     for(j = 0 ; j < nb_tracefile ; j++) {
       tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
       lttv_hooks_remove_data(lttv_hooks_by_id_find(
-          tfs->parent.after_event_by_id, hook.id), hook.h, NULL);
+          tfs->parent.after_event_by_id, hook_start.id), hook_start.h, NULL);
+      lttv_hooks_remove_data(lttv_hooks_by_id_find(
+          tfs->parent.after_event_by_id, hook_end.id), hook_end.h, NULL);
     }
   }
 }
@@ -1295,7 +1341,7 @@ lttv_tracefile_state_get_type(void)
 }
 
 
-void lttv_state_init(int argc, char **argv)
+static void module_init()
 {
   LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
   LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
@@ -1320,10 +1366,14 @@ void lttv_state_init(int argc, char **argv)
   LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
 }
 
-void lttv_state_destroy() 
+static void module_destroy() 
 {
 }
 
 
+LTTV_MODULE("state", "State computation", \
+    "Update the system state, possibly saving it at intervals", \
+    module_init, module_destroy)
+
 
 
index c5686976b3e1967968605f67585fd314fc5c7bf3..c577ab77bb2112df29c52c41ae5502edeff20a30 100644 (file)
@@ -18,6 +18,7 @@
 
 
 #include <stdio.h>
+#include <lttv/module.h>
 #include <lttv/stats.h>
 #include <lttv/lttv.h>
 #include <ltt/facility.h>
@@ -798,27 +799,6 @@ lttv_stats_remove_event_hooks(LttvTracesetStats *self)
 }
 
 
-void lttv_stats_init(int argc, char **argv)
-{
-  LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
-  LTTV_STATS_PROCESSES = g_quark_from_string("processes");
-  LTTV_STATS_CPU = g_quark_from_string("cpu");
-  LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
-  LTTV_STATS_MODES = g_quark_from_string("modes");
-  LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
-  LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
-  LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
-  LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
-  LTTV_STATS_EVENTS = g_quark_from_string("events");
-  LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
-  LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
-  LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
-}
-
-void lttv_stats_destroy() 
-{
-}
-
 void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp)
 {
   LttvAttributeType type;
@@ -1124,7 +1104,7 @@ gboolean lttv_stats_load_statistics(LttvTracesetStats *self)
   char filename[BUF_SIZE];
 
   GMarkupParseContext * context;
-  GError * error;
+  GError * error = NULL;
   GMarkupParser markup_parser =
     {
       stats_parser_start_element,
@@ -1171,3 +1151,30 @@ gboolean lttv_stats_load_statistics(LttvTracesetStats *self)
 
   return TRUE;
 }
+
+
+static void module_init()
+{
+  LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
+  LTTV_STATS_PROCESSES = g_quark_from_string("processes");
+  LTTV_STATS_CPU = g_quark_from_string("cpu");
+  LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
+  LTTV_STATS_MODES = g_quark_from_string("modes");
+  LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
+  LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
+  LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
+  LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
+  LTTV_STATS_EVENTS = g_quark_from_string("events");
+  LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
+  LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
+  LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
+}
+
+static void module_destroy() 
+{
+}
+
+
+LTTV_MODULE("stats", "Compute processes statistics", \
+    "Accumulate statistics for event types, processes and CPUs", \
+    module_init, module_destroy, "state");
index dd64c9f4106e4d12d0e2e4a061df08b326182254..305e0460503f68597e368c9fc823ade9ee3f7d9f 100644 (file)
@@ -3,18 +3,19 @@
 /* Created by Mathieu Desnoyers, may 2003 */
 
 #include <glib.h>
-#include <gmodule.h>
 
 /* Include module.h from lttv headers for module loading */
 #include <lttv/module.h>
 
-G_MODULE_EXPORT void init(int argc, char * argv[], LttvModule *self) {
+static void init() {
        g_critical("Sample module dependant init()");
-
-       lttv_module_require(self, "samplemodule",argc,argv);
 }
 
-G_MODULE_EXPORT void destroy() {
+static void destroy() {
        g_critical("Sample module dependant destroy()");
 }
-       
+
+
+LTTV_MODULE("sampledep", "Medium desc...", "Long desc...", init, destroy, \
+           { "samplemodule" })
+
index e64ab2f45bee49f8b7bcda273611df43a68c92d2..3156c9f27397fb5a5b72c8f3092a4ff51fff952f 100644 (file)
@@ -3,13 +3,16 @@
 /* Created by Mathieu Desnoyers, may 2003 */
 
 #include <glib.h>
-#include <gmodule.h>
+#include <lttv/module.h>
 
-G_MODULE_EXPORT void init() {
+static void init() {
        g_critical("Sample module init()");
 }
 
-G_MODULE_EXPORT void destroy() {
+static void destroy() {
        g_critical("Sample module destroy()");
 }
-       
+
+
+LTTV_MODULE("sampledep", "Medium...", "Long...", init, destroy, {})
+
index 3d7bb1c00ccc546040181cefbdb297f8b100f310..6ce8edd6ecb7e9b596a3b780d9251effd93e9958 100644 (file)
@@ -3,13 +3,16 @@
 /* Created by Mathieu Desnoyers, may 2003 */
 
 #include <glib.h>
-#include <gmodule.h>
+#include <lttv/module.h>
 
-G_MODULE_EXPORT void init() {
+static void init() {
        g_critical("Sample module 2 init()");
 }
 
-G_MODULE_EXPORT void destroy() {
+static void destroy() {
        g_critical("Sample module 2 destroy()");
 }
-       
+
+
+LTTV_MODULE("samplemodule2", "Medium...", "Long...", init, destroy, {})
+
index 16068794d3c3f797c2a9fe69550caf28c75a7251..69694d6f7b28e73863fe77bd8063abc607375b42 100644 (file)
@@ -38,7 +38,6 @@
  */
 
 #include <glib.h>
-#include <gmodule.h>
 #include <lttv/lttv.h>
 #include <lttv/module.h>
 #include <lttv/gtktraceset.h>
@@ -66,16 +65,8 @@ GSList *g_control_flow_data_list = NULL ;
  * This function initializes the Control Flow Viewer functionnality through the
  * gtkTraceSet API.
  */
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char *argv[]) {
+static void init() {
 
-  Main_Win_Module = lttv_module_require(self, "mainwin", argc, argv);
-  
-  if(Main_Win_Module == NULL)
-  {
-    g_critical("Can't load Control Flow Viewer : missing mainwin\n");
-    return;
-  }
-  
   g_info("GUI ControlFlow Viewer init()");
 
   /* Register the toolbar insert button */
@@ -101,7 +92,7 @@ void destroy_walk(gpointer data, gpointer user_data)
  * This function releases the memory reserved by the module and unregisters
  * everything that has been registered in the gtkTraceSet API.
  */
-G_MODULE_EXPORT void destroy() {
+static void destroy() {
   g_info("GUI Control Flow Viewer destroy()");
   int i;
 
@@ -116,3 +107,8 @@ G_MODULE_EXPORT void destroy() {
   menu_item_unreg(h_guicontrolflow);
   
 }
+
+
+LTTV_MODULE("guicontrolflow", "Control flow viewer", \
+    "Graphical module to view processes state and control flow", \
+    init, destroy, "mainwin")
index 17cc9321c5255f45f969668d3e270801245fc1cc..43b81d0338d9f1fbda289f15bff163fc727910fb 100644 (file)
@@ -40,7 +40,6 @@
 #include <math.h>
 
 #include <glib.h>
-#include <gmodule.h>
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
@@ -187,57 +186,6 @@ static gboolean parse_event(void *hook_data, void *call_data);
 
 static LttvModule *main_win_module;
 
-/**
- * plugin's init function
- *
- * This function initializes the Event Viewer functionnality through the
- * gtkTraceSet API.
- */
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char *argv[]) {
-
-  main_win_module = lttv_module_require(self, "mainwin", argc, argv);
-  
-  if(main_win_module == NULL){
-    g_critical("Can't load Control Flow Viewer : missing mainwin\n");
-    return;
-  }
-  
-  /* Register the toolbar insert button */
-  toolbar_item_reg(hGuiEventsInsert_xpm, "Insert Event Viewer", h_gui_events);
-  
-  /* Register the menu item insert entry */
-  menu_item_reg("/", "Insert Event Viewer", h_gui_events);
-  
-}
-
-void event_destroy_walk(gpointer data, gpointer user_data)
-{
-  gui_events_destructor((EventViewerData*)data);
-}
-
-/**
- * plugin's destroy function
- *
- * This function releases the memory reserved by the module and unregisters
- * everything that has been registered in the gtkTraceSet API.
- */
-G_MODULE_EXPORT void destroy() {
-  int i;
-  
-  EventViewerData *event_viewer_data;
-  
-  if(g_event_viewer_data_list){
-    g_slist_foreach(g_event_viewer_data_list, event_destroy_walk, NULL );
-    g_slist_free(g_event_viewer_data_list);
-  }
-
-  /* Unregister the toolbar insert button */
-  toolbar_item_unreg(h_gui_events);
-  
-  /* Unregister the menu item insert entry */
-  menu_item_unreg(h_gui_events);
-}
-
 /* Enumeration of the columns */
 enum
 {
@@ -1888,3 +1836,51 @@ void remove_all_items_from_queue(GQueue *q)
 }
 
 
+/**
+ * plugin's init function
+ *
+ * This function initializes the Event Viewer functionnality through the
+ * gtkTraceSet API.
+ */
+static void init() {
+
+  /* Register the toolbar insert button */
+  toolbar_item_reg(hGuiEventsInsert_xpm, "Insert Event Viewer", h_gui_events);
+  
+  /* Register the menu item insert entry */
+  menu_item_reg("/", "Insert Event Viewer", h_gui_events);
+  
+}
+
+void event_destroy_walk(gpointer data, gpointer user_data)
+{
+  gui_events_destructor((EventViewerData*)data);
+}
+
+/**
+ * plugin's destroy function
+ *
+ * This function releases the memory reserved by the module and unregisters
+ * everything that has been registered in the gtkTraceSet API.
+ */
+static void destroy() {
+  int i;
+  
+  EventViewerData *event_viewer_data;
+  
+  if(g_event_viewer_data_list){
+    g_slist_foreach(g_event_viewer_data_list, event_destroy_walk, NULL );
+    g_slist_free(g_event_viewer_data_list);
+  }
+
+  /* Unregister the toolbar insert button */
+  toolbar_item_unreg(h_gui_events);
+  
+  /* Unregister the menu item insert entry */
+  menu_item_unreg(h_gui_events);
+}
+
+
+LTTV_MODULE("guievents", "Detailed events view", \
+    "Graphical module to display a detailed event list", \
+           init, destroy, "mainwin")
index f09f7dbabff146a93547fc9120cb90cf55dbdb4b..08a58516c2eb22bd47019b7e2596e22e3dbf52c4 100644 (file)
@@ -21,7 +21,6 @@
 #endif
 
 #include <gtk/gtk.h>
-#include <gmodule.h>
 
 #include "callbacks.h"
 #include "interface.h"
@@ -275,10 +274,10 @@ void create_new_window(GtkWidget* widget, gpointer user_data, gboolean clone)
 
   if(clone){
     g_printf("Clone : use the same traceset\n");
-    construct_main_window(parent, NULL);
+    construct_main_window(parent);
   }else{
     g_printf("Empty : traceset is set to NULL\n");
-    construct_main_window(NULL, parent->win_creation_data);
+    construct_main_window(NULL);
   }
 }
 
@@ -1042,10 +1041,7 @@ on_load_module_activate                (GtkMenuItem     *menuitem,
        str1 = strrchr(str,'\\');
        str1++;
       }
-      if(mw_data->win_creation_data)
-       lttv_module_load(str1, mw_data->win_creation_data->argc,mw_data->win_creation_data->argv);
-      else
-       lttv_module_load(str1, 0,NULL);
+      lttv_module_require(str1, NULL);
       g_slist_foreach(g_main_window_list, (gpointer)insert_menu_toolbar_item,
           NULL);
       g_strfreev(dir);
@@ -1068,30 +1064,36 @@ on_unload_module_activate              (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
   int i;
-  char **name, *unload_module_name;
+  GPtrArray *name;
+  char *unload_module_name;
   guint nb;
-  LttvModule ** modules, *module;
+  LttvLibrary *library;
+  LttvLibraryInfo library_info;
   MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
   
-  modules = lttv_module_list(&nb);
-  name  = g_new(char*, nb);
+  name  = g_ptr_array_new();
+  nb = lttv_library_number();
+
   for(i=0;i<nb;i++){
-    module = modules[i];
-    name[i] = lttv_module_name(module);
+    library = lttv_library_get(i);
+    lttv_library_info(library, &library_info);
+    if(library_info.load_count > 0) g_ptr_array_add(name, library_info.name);
   }
 
-  unload_module_name =get_unload_module(name,nb);
+  unload_module_name =get_unload_module((char **)(name->pdata), name->len);
   
   if(unload_module_name){
     for(i=0;i<nb;i++){
-      if(strcmp(unload_module_name, name[i]) == 0){
-       lttv_module_unload(modules[i]);
+      library = lttv_library_get(i);
+      lttv_library_info(library, &library_info);
+      if(strcmp(unload_module_name, library_info.name) == 0){
+       lttv_library_unload(library);
        break;
       }
     }    
   }
 
-  g_free(name);
+  g_ptr_array_free(name, TRUE);
 }
 
 
@@ -1113,7 +1115,7 @@ on_add_module_search_path_activate     (GtkMenuItem     *menuitem,
     case GTK_RESPONSE_ACCEPT:
     case GTK_RESPONSE_OK:
       dir = gtk_dir_selection_get_dir (file_selector);
-      lttv_module_path_add(dir);
+      lttv_library_path_add(dir);
     case GTK_RESPONSE_REJECT:
     case GTK_RESPONSE_CANCEL:
     default:
@@ -1764,7 +1766,7 @@ void insert_menu_toolbar_item(MainWindow * mw, gpointer user_data)
 /* Create a main window
  */
 
-void construct_main_window(MainWindow * parent, WindowCreationData * win_creation_data)
+void construct_main_window(MainWindow * parent)
 {
   g_debug("construct_main_window()");
   GtkWidget  * new_window; /* New generated main window */
@@ -1789,11 +1791,6 @@ void construct_main_window(MainWindow * parent, WindowCreationData * win_creatio
   new_m_window->tab = NULL;
   new_m_window->current_tab = NULL;
   new_m_window->attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
-  if(parent){
-    new_m_window->win_creation_data = parent->win_creation_data;
-  }else{
-    new_m_window->win_creation_data = win_creation_data;
-  }
 
   new_m_window->hash_menu_item = g_hash_table_new_full (g_str_hash, g_str_equal,
                                              main_window_destroy_hash_key, 
index 95c57c3b45dcea860c8c46bc9ae08d601f4c400e..c9166bdad73af8670156978920c75dc766451781 100644 (file)
@@ -24,7 +24,7 @@
 
 void create_new_window(GtkWidget* widget, gpointer user_data, gboolean clone);
 void insert_menu_toolbar_item(MainWindow * mw, gpointer user_data);
-void construct_main_window(MainWindow * parent, WindowCreationData *win_creation_data);
+void construct_main_window(MainWindow * parent);
 void main_window_free(MainWindow * mw);
 void main_window_destructor(MainWindow * mw);
 
index 2539ceaa4c4b1f8891309e8c0676bd4edc1dd33f..781844ad04d2f7804b7173042098211dfa3fede7 100644 (file)
@@ -45,9 +45,6 @@
 #include <ltt/trace.h>
 
 
-/* global variable */
-static WindowCreationData  win_creation_data;
-
 /** Array containing instanced objects. */
 GSList * g_main_window_list = NULL ;
 
@@ -79,8 +76,6 @@ void lttv_trace_option(void *hook_data)
 
 static gboolean window_creation_hook(void *hook_data, void *call_data)
 {
-  WindowCreationData* window_creation_data = (WindowCreationData*)hook_data;
-
   g_debug("GUI window_creation_hook()");
 #ifdef ENABLE_NLS
   bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
@@ -89,20 +84,20 @@ static gboolean window_creation_hook(void *hook_data, void *call_data)
 #endif
 
   gtk_set_locale ();
-  gtk_init (&(window_creation_data->argc), &(window_creation_data->argv));
+  gtk_init (&lttv_argc, &lttv_argv);
 
   add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
   add_pixmap_directory ("pixmaps");
   add_pixmap_directory ("../modules/gui/main/pixmaps");
 
-  construct_main_window(NULL, window_creation_data);
+  construct_main_window(NULL);
 
   gtk_main ();
 
   return FALSE;
 }
 
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char *argv[]) {
+static void init() {
 
   LttvAttributeValue value;
  
@@ -120,10 +115,7 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char *argv[]) {
       LTTV_POINTER, &value));
   g_assert((main_hooks = *(value.v_pointer)) != NULL);
 
-  win_creation_data.argc = argc;
-  win_creation_data.argv = argv;
-  
-  lttv_hooks_add(main_hooks, window_creation_hook, &win_creation_data);
+  lttv_hooks_add(main_hooks, window_creation_hook, NULL);
 
 }
 
@@ -174,14 +166,14 @@ void main_window_destroy_walk(gpointer data, gpointer user_data)
  * This function releases the memory reserved by the module and unregisters
  * everything that has been registered in the gtkTraceSet API.
  */
-G_MODULE_EXPORT void destroy() {
+static void destroy() {
 
   LttvAttributeValue value;  
   LttvTrace *trace;
 
   lttv_option_remove("trace");
 
-  lttv_hooks_remove_data(main_hooks, window_creation_hook, &win_creation_data);
+  lttv_hooks_remove_data(main_hooks, window_creation_hook, NULL);
 
   g_debug("GUI destroy()");
 
@@ -193,5 +185,6 @@ G_MODULE_EXPORT void destroy() {
 }
 
 
-
-
+LTTV_MODULE("mainwin", "Viewer main window", \
+    "Viewer with multiple windows, tabs and panes for graphical modules", \
+           init, destroy, "stats")
index 9bd4b8d6f1ded28fbd42554e3f7d51010aca6e70..101f83e942a51148640f3bae8d89da599d3e3a66 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <glib.h>
-#include <gmodule.h>
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
@@ -116,59 +115,6 @@ struct _StatisticViewerData{
 };
 
 
-/**
- * plugin's init function
- *
- * This function initializes the Statistic Viewer functionnality through the
- * gtkTraceSet API.
- */
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char *argv[]) {
-
-  statistic_main_win_module = lttv_module_require(self, "mainwin", argc, argv);
-  
-  if(statistic_main_win_module == NULL){
-      g_critical("Can't load Statistic Viewer : missing mainwin\n");
-      return;
-  }
-
-  statistic_traceset = g_ptr_array_new ();
-
-  /* Register the toolbar insert button */
-  toolbar_item_reg(hGuiStatisticInsert_xpm, "Insert Statistic Viewer", h_gui_statistic);
-  
-  /* Register the menu item insert entry */
-  menu_item_reg("/", "Insert Statistic Viewer", h_gui_statistic);
-  
-}
-
-void statistic_destroy_walk(gpointer data, gpointer user_data)
-{
-  gui_statistic_destructor((StatisticViewerData*)data);
-}
-
-/**
- * plugin's destroy function
- *
- * This function releases the memory reserved by the module and unregisters
- * everything that has been registered in the gtkTraceSet API.
- */
-G_MODULE_EXPORT void destroy() {
-  int i;
-  
-  if(g_statistic_viewer_data_list){
-    g_slist_foreach(g_statistic_viewer_data_list, statistic_destroy_walk, NULL );    
-    g_slist_free(g_statistic_viewer_data_list);
-  }
-  g_ptr_array_free (statistic_traceset, TRUE);
-
-  /* Unregister the toolbar insert button */
-  toolbar_item_unreg(h_gui_statistic);
-  
-  /* Unregister the menu item insert entry */
-  menu_item_unreg(h_gui_statistic);
-}
-
-
 void
 gui_statistic_free(StatisticViewerData *statistic_viewer_data)
 { 
@@ -693,3 +639,53 @@ void statistic_remove_context_hooks(StatisticViewerData * statistic_viewer_data,
 }
 
 
+/**
+ * plugin's init function
+ *
+ * This function initializes the Statistic Viewer functionnality through the
+ * gtkTraceSet API.
+ */
+static void init() {
+
+  statistic_traceset = g_ptr_array_new ();
+
+  /* Register the toolbar insert button */
+  toolbar_item_reg(hGuiStatisticInsert_xpm, "Insert Statistic Viewer", h_gui_statistic);
+  
+  /* Register the menu item insert entry */
+  menu_item_reg("/", "Insert Statistic Viewer", h_gui_statistic);
+  
+}
+
+void statistic_destroy_walk(gpointer data, gpointer user_data)
+{
+  gui_statistic_destructor((StatisticViewerData*)data);
+}
+
+/**
+ * plugin's destroy function
+ *
+ * This function releases the memory reserved by the module and unregisters
+ * everything that has been registered in the gtkTraceSet API.
+ */
+static void destroy() {
+  int i;
+  
+  if(g_statistic_viewer_data_list){
+    g_slist_foreach(g_statistic_viewer_data_list, statistic_destroy_walk, NULL );    
+    g_slist_free(g_statistic_viewer_data_list);
+  }
+  g_ptr_array_free (statistic_traceset, TRUE);
+
+  /* Unregister the toolbar insert button */
+  toolbar_item_unreg(h_gui_statistic);
+  
+  /* Unregister the menu item insert entry */
+  menu_item_unreg(h_gui_statistic);
+}
+
+
+LTTV_MODULE("guistatistics", "Statistics viewer", \
+    "Graphical module to view statistics about processes, CPUs and systems", \
+    init, destroy, "mainwin")
+
index f26ed39a075db44fdf1e5cd61312afbf756e4882..0d8f15224ea20444544bac9e1c593811c484a018 100644 (file)
@@ -104,7 +104,7 @@ static gboolean process_traceset(void *hook_data, void *call_data)
 }
 
 
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
+static void init()
 {
   LttvAttributeValue value;
 
@@ -167,7 +167,7 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
 }
 
 
-G_MODULE_EXPORT void destroy()
+static void destroy()
 {
   guint i, nb;
 
@@ -198,3 +198,7 @@ G_MODULE_EXPORT void destroy()
   lttv_traceset_destroy(traceset); 
 }
 
+
+LTTV_MODULE("batchAnalysis", "Batch processing of a trace", \
+    "Run through a trace calling all the registered hooks", \
+    init, destroy, "state", "stats", "option")
diff --git a/ltt/branches/poly/lttv/modules/text/batchtest.c b/ltt/branches/poly/lttv/modules/text/batchtest.c
new file mode 100644 (file)
index 0000000..41b5fff
--- /dev/null
@@ -0,0 +1,569 @@
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * 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.
+ */
+
+/* This module inserts a hook in the program main loop. This hook processes 
+   all the events in the main tracefile while testing the speed and
+   functionality of the state and stats computations. */
+
+
+#include <lttv/lttv.h>
+#include <lttv/attribute.h>
+#include <lttv/hook.h>
+#include <lttv/option.h>
+#include <lttv/module.h>
+#include <lttv/processTrace.h>
+#include <lttv/state.h>
+#include <lttv/stats.h>
+#include <ltt/trace.h>
+#include <ltt/event.h>
+
+static LttvTraceset *traceset;
+
+static LttvHooks
+  *before_traceset,
+  *after_traceset,
+  *before_trace,
+  *after_trace,
+  *before_tracefile,
+  *after_tracefile,
+  *before_event,
+  *after_event,
+  *main_hooks;
+
+static char *a_trace;
+
+static char *a_dump_tracefiles;
+
+static char *a_save_sample;
+
+static int
+  a_sample_interval,
+  a_sample_number,
+  a_save_interval;
+
+static gboolean
+  a_test1,
+  a_test2,
+  a_test3,
+  a_test4,
+  a_test5,
+  a_test6,
+  a_test7,
+  a_test_all;
+
+typedef struct _save_state {
+  guint count;
+  FILE *fp;
+  guint interval;
+  guint position;
+  guint size;
+  LttTime *write_time;
+  guint version;
+} SaveState;
+
+
+static void lttv_trace_option(void *hook_data)
+{ 
+  LttTrace *trace;
+
+  trace = ltt_trace_open(a_trace);
+  if(trace == NULL) g_critical("cannot open trace %s", a_trace);
+  lttv_traceset_add(traceset, lttv_trace_new(trace));
+}
+
+static double get_time() 
+{
+  GTimeVal gt;
+
+  g_get_current_time(&gt);
+  return gt.tv_sec + (double)gt.tv_usec / (double)1000000.0;
+}
+
+static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end)
+{
+  double t0, t1;
+
+  lttv_traceset_context_add_hooks(&ts->parent,
+  before_traceset, after_traceset, NULL, before_trace, after_trace,
+  NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
+
+  t0 = get_time();
+  lttv_state_traceset_seek_time_closest(ts, start);
+  lttv_process_traceset(&ts->parent, end, G_MAXULONG);
+  t1 = get_time();
+
+  lttv_traceset_context_remove_hooks(&ts->parent,
+  before_traceset, after_traceset, NULL, before_trace, after_trace,
+  NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
+
+  return t1 - t0;
+}
+
+
+gboolean count_event(void *hook_data, void *call_data)
+{
+  guint *pcount = (guint *)hook_data;
+
+  (*pcount)++;
+  return FALSE;
+}
+
+
+gboolean save_state_event(void *hook_data, void *call_data)
+{
+  SaveState *save_state = (SaveState *)hook_data;
+
+  LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+  LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
+
+  GString *filename;
+
+  FILE *fp;
+
+  (save_state->count)++;
+  if(save_state->count % save_state->interval == 0 && 
+     save_state->position < save_state->size) {
+    if(a_save_sample != NULL) {
+      filename = g_string_new("");
+      g_string_printf(filename, "%s.%u.xml.%u", a_save_sample, 
+          save_state->position, save_state->version);
+      fp = fopen(filename->str, "w");
+      if(fp == NULL) g_error("Cannot open %s", filename->str);
+      g_string_free(filename, TRUE);
+      lttv_state_write(ts, tfs->parent.timestamp, fp);
+      fclose(fp);
+    } else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp);
+
+    save_state->write_time[save_state->position] = tfs->parent.timestamp;
+    save_state->position++;
+  }
+  return FALSE;
+}
+
+
+static gboolean process_traceset(void *hook_data, void *call_data)
+{
+  LttvTracesetStats *tscs;
+
+  LttvTracesetState *ts;
+
+  LttvTracesetContext *tc;
+
+  GString *filename;
+
+  FILE *fp;
+
+  double t;
+
+  guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal;
+
+  LttTrace *trace;
+
+  LttTracefile *tracefile, *tf;
+
+  LttEvent *event;
+
+  LttFacility *facility;
+
+  LttType *type;
+
+  LttEventType *event_type;
+
+  LttTime time, previous_time;
+
+  LttEventPosition *event_position;
+
+  LttTime zero_time = ltt_time_zero;
+
+  LttTime max_time = { G_MAXULONG, G_MAXULONG };
+
+  if(a_dump_tracefiles != NULL) {
+    event_position = ltt_event_position_new();
+    for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
+      trace = lttv_trace(lttv_traceset_get(traceset, i));
+      nb_control = ltt_trace_control_tracefile_number(trace);
+      nb_tracefile = nb_control + ltt_trace_per_cpu_tracefile_number(trace);
+      for(j = 0 ; j < nb_tracefile ; j++) {
+        if(j < nb_control) {
+          tracefile = ltt_trace_control_tracefile_get(trace,j);
+        }
+        else {
+          tracefile = ltt_trace_per_cpu_tracefile_get(trace,j - nb_control);
+        }
+
+        filename = g_string_new("");
+        g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j);
+        fp = fopen(filename->str, "w");
+        if(fp == NULL) g_error("Cannot open %s", filename->str);
+        g_string_free(filename, TRUE);
+        ltt_tracefile_seek_time(tracefile, zero_time);
+        previous_time = zero_time;
+        nb_equal = 0;
+        while((event = ltt_tracefile_read(tracefile)) != NULL) {
+          facility = ltt_event_facility(event);
+          event_type = ltt_event_eventtype(event);
+          time = ltt_event_time(event);
+          ltt_event_position(event, event_position);
+          ltt_event_position_get(event_position, &nb_block, &nb_event, &tf);
+          fprintf(fp,"%s.%s: %lu.%09lu position %u/%u\n", 
+              ltt_facility_name(facility), ltt_eventtype_name(event_type), 
+                 (long)time.tv_sec, time.tv_nsec, nb_block, nb_event);
+
+          if(ltt_time_compare(time, previous_time) == 0) nb_equal++;
+         else if(nb_equal > 0) {
+            g_warning("Consecutive %d events with time %lu.%lu",
+               nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec);
+            nb_equal = 0;
+         }
+
+          if(ltt_time_compare(time, previous_time) < 0) {
+            g_warning("Time decreasing trace %d tracefile %d position %u/%u",
+                     i, j, nb_block, nb_event);
+          }
+          previous_time = time;
+        }
+        fclose(fp);
+      }
+    }
+    g_free(event_position);
+  }
+
+  tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
+  ts = &tscs->parent;
+  tc = &tscs->parent.parent;
+
+  lttv_context_init(tc, traceset);
+  for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
+    ((LttvTraceState *)(tc->traces[i]))->save_interval = a_save_interval;
+  }
+
+  /* For each case compute and print the elapsed time.
+     The first case is simply to run through all events with a
+     simple counter. */
+
+  if(a_test1 || a_test_all) {
+    count = 0;
+    lttv_hooks_add(after_event, count_event, &count);
+    t = run_one_test(ts, zero_time, max_time);
+    lttv_hooks_remove_data(after_event, count_event, &count);
+    g_warning(
+        "Processing trace while counting events (%u events in %g seconds)",
+       count, t);
+  }
+
+  /* Run through all events computing the state. */
+
+  if(a_test2 || a_test_all) {
+    lttv_state_add_event_hooks(ts);
+    t = run_one_test(ts, zero_time, max_time);
+    lttv_state_remove_event_hooks(ts);
+    g_warning("Processing trace while updating state (%g seconds)", t);
+  }
+
+  /* Run through all events computing the state and writing it out 
+     periodically. */
+
+  SaveState save_state;
+
+  save_state.interval = a_sample_interval;
+  save_state.size = a_sample_number;
+  save_state.fp = stderr;
+  save_state.write_time = g_new(LttTime, a_sample_number);
+
+
+  if(a_test3 || a_test_all) {
+    for(i = 0 ; i < 2 ; i++) {
+      save_state.count = 0;
+      save_state.position = 0;
+      save_state.version = i;
+      lttv_state_add_event_hooks(ts);
+      lttv_hooks_add(after_event, save_state_event, &save_state);
+      t = run_one_test(ts, zero_time, max_time);
+      lttv_state_remove_event_hooks(ts);
+      lttv_hooks_remove_data(after_event, save_state_event, &save_state);
+      g_warning("Processing while updating/writing state (%g seconds)", t);
+    }
+  }
+
+  /* Run through all events computing the stats. */
+
+  if(a_test4 || a_test_all) {
+    if(lttv_profile_memory) {
+      g_message("Memory summary before computing stats");
+      g_mem_profile();
+    }
+
+    lttv_stats_add_event_hooks(tscs);
+    t = run_one_test(ts, zero_time, max_time);
+    lttv_stats_remove_event_hooks(tscs);
+    g_warning("Processing trace while counting stats (%g seconds)", t);
+
+    if(lttv_profile_memory) {
+      g_message("Memory summary after computing stats");
+      g_mem_profile();
+    }
+  }
+
+  /* Run through all events computing the state and stats. */
+
+  if(a_test5 || a_test_all) {
+    if(lttv_profile_memory) {
+      g_message("Memory summary before computing state and stats");
+      g_mem_profile();
+    }
+
+    lttv_state_add_event_hooks(ts);
+    lttv_stats_add_event_hooks(tscs);
+    t = run_one_test(ts, zero_time, max_time);
+    lttv_state_remove_event_hooks(ts);
+    lttv_stats_remove_event_hooks(tscs);
+    g_warning(
+        "Processing trace while counting state and stats (%g seconds)", t);
+
+    if(lttv_profile_memory) {
+      g_message("Memory summary after computing and state and stats");
+      g_mem_profile();
+    }
+  }
+
+  /* Run through all events computing and saving the state. */
+
+  if(a_test6 || a_test_all) {
+    if(lttv_profile_memory) {
+      g_message("Memory summary before computing and saving state");
+      g_mem_profile();
+    }
+
+    lttv_state_add_event_hooks(ts);
+    lttv_state_save_add_event_hooks(ts);
+    t = run_one_test(ts, zero_time, max_time);
+    lttv_state_remove_event_hooks(ts);
+    lttv_state_save_remove_event_hooks(ts);
+    g_warning("Processing trace while updating/saving state (%g seconds)", t);
+
+    if(lttv_profile_memory) {
+      g_message("Memory summary after computing/saving state");
+      g_mem_profile();
+    }
+  }
+
+  /* Seek a few times to each saved position */
+
+  if((a_test7 && a_test3) || a_test_all) {
+    int i, j;
+
+    for(i = 0 ; i < 2 ; i++) {
+      for(j = save_state.position - 1 ; j >= 0 ; j--) {
+        lttv_state_add_event_hooks(ts);
+        t = run_one_test(ts, save_state.write_time[j], 
+            save_state.write_time[j]);
+        lttv_state_remove_event_hooks(ts);
+        g_warning("Seeking to %lu.%lu (%g seconds)", 
+            save_state.write_time[j].tv_sec, save_state.write_time[j].tv_nsec,
+            t);
+
+        if(a_save_sample != NULL) {
+          filename = g_string_new("");
+          g_string_printf(filename, "%s.%d.xml.bak%d", a_save_sample, j, i);
+          fp = fopen(filename->str, "w");
+          if(fp == NULL) g_error("Cannot open %s", filename->str);
+          g_string_free(filename, TRUE);
+          lttv_state_write((LttvTraceState *)tc->traces[0], 
+              save_state.write_time[j], fp);
+          fclose(fp);
+        }
+        else lttv_state_write((LttvTraceState *)tc->traces[0], 
+            save_state.write_time[j], save_state.fp);
+      }
+    }
+  }
+
+  g_free(save_state.write_time);
+  lttv_context_fini(tc);
+  g_object_unref(tscs);
+
+  g_info("BatchTest end process traceset");
+}
+
+
+static void init()
+{
+  LttvAttributeValue value;
+
+  LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+
+  g_info("Init batchtest.c");
+
+  lttv_option_add("trace", 't', 
+      "add a trace to the trace set to analyse", 
+      "pathname of the directory containing the trace", 
+      LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL);
+
+  a_dump_tracefiles = NULL;
+  lttv_option_add("dump-tracefiles", 'D', 
+      "Write event by event the content of tracefiles", 
+      "basename for the files where to dump events", 
+      LTTV_OPT_STRING, &a_dump_tracefiles, NULL, NULL);
+
+  a_save_sample = NULL;
+  lttv_option_add("save-sample", 's', 
+      "Save state samples to multiple files", 
+      "basename for the files containing the state samples", 
+      LTTV_OPT_STRING, &a_save_sample, NULL, NULL);
+
+  a_save_interval = 100000;
+  lttv_option_add("save-interval", 'i', 
+      "Interval between saving state", 
+      "number of events before a block start triggers saving state", 
+      LTTV_OPT_INT, &a_save_interval, NULL, NULL);
+
+  a_sample_interval = 100000;
+  lttv_option_add("sample-interval", 'S', 
+      "Interval between sampling state", 
+      "number of events before sampling and writing state", 
+      LTTV_OPT_INT, &a_sample_interval, NULL, NULL);
+
+  a_sample_number = 20;
+  lttv_option_add("sample-number", 'N', 
+      "Number of state samples", 
+      "maximum number", 
+      LTTV_OPT_INT, &a_sample_number, NULL, NULL);
+
+  a_test1 = FALSE;
+  lttv_option_add("test1", '1', "Test just counting events", "", 
+      LTTV_OPT_NONE, &a_test1, NULL, NULL);
+
+  a_test2 = FALSE;
+  lttv_option_add("test2", '2', "Test computing the state", "", 
+      LTTV_OPT_NONE, &a_test2, NULL, NULL);
+
+  a_test3 = FALSE;
+  lttv_option_add("test3", '3', "Test computing the state, writing out a few",
+      "", LTTV_OPT_NONE, &a_test3, NULL, NULL);
+
+  a_test4 = FALSE;
+  lttv_option_add("test4", '4', "Test computing the stats", "", 
+      LTTV_OPT_NONE, &a_test4, NULL, NULL);
+
+  a_test5 = FALSE;
+  lttv_option_add("test5", '5', "Test computing the state and stats", "", 
+      LTTV_OPT_NONE, &a_test5, NULL, NULL);
+
+  a_test6 = FALSE;
+  lttv_option_add("test6", '6', "Test computing and saving the state", "", 
+      LTTV_OPT_NONE, &a_test6, NULL, NULL);
+
+  a_test7 = FALSE;
+  lttv_option_add("test7", '7', "Test seeking to positions written out in 3", 
+      "", LTTV_OPT_NONE, &a_test7, NULL, NULL);
+
+  a_test_all = FALSE;
+  lttv_option_add("testall", 'a', "Run all tests ", "", 
+      LTTV_OPT_NONE, &a_test_all, NULL, NULL);
+
+  traceset = lttv_traceset_new();
+
+  before_traceset = lttv_hooks_new();
+  after_traceset = lttv_hooks_new();
+  before_trace = lttv_hooks_new();
+  after_trace = lttv_hooks_new();
+  before_tracefile = lttv_hooks_new();
+  after_tracefile = lttv_hooks_new();
+  before_event = lttv_hooks_new();
+  after_event = lttv_hooks_new();
+
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = before_traceset;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = after_traceset;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = before_trace;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = after_trace;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = before_tracefile;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = after_tracefile;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = before_event;
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after",
+      LTTV_POINTER, &value));
+  *(value.v_pointer) = after_event;
+
+  g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
+      LTTV_POINTER, &value));
+  g_assert((main_hooks = *(value.v_pointer)) != NULL);
+  lttv_hooks_add(main_hooks, process_traceset, NULL);
+}
+
+
+static void destroy()
+{
+  guint i, nb;
+
+  LttvTrace *trace;
+
+  g_info("Destroy batchAnalysis.c");
+
+  lttv_option_remove("trace");
+  lttv_option_remove("dump-tracefiles");
+  lttv_option_remove("save-sample");
+  lttv_option_remove("sample-interval");
+  lttv_option_remove("sample-number");
+  lttv_option_remove("save-interval");
+  lttv_option_remove("test1");
+  lttv_option_remove("test2");
+  lttv_option_remove("test3");
+  lttv_option_remove("test4");
+  lttv_option_remove("test5");
+  lttv_option_remove("test6");
+  lttv_option_remove("test7");
+  lttv_option_remove("testall");
+
+  lttv_hooks_destroy(before_traceset);
+  lttv_hooks_destroy(after_traceset);
+  lttv_hooks_destroy(before_trace);
+  lttv_hooks_destroy(after_trace);
+  lttv_hooks_destroy(before_tracefile);
+  lttv_hooks_destroy(after_tracefile);
+  lttv_hooks_destroy(before_event);
+  lttv_hooks_destroy(after_event);
+  lttv_hooks_remove_data(main_hooks, process_traceset, NULL);
+
+  nb = lttv_traceset_number(traceset);
+  for(i = 0 ; i < nb ; i++) {
+    trace = lttv_traceset_get(traceset, i);
+    ltt_trace_close(lttv_trace(trace));
+    lttv_trace_destroy(trace);
+  }
+
+  lttv_traceset_destroy(traceset); 
+}
+
+
+LTTV_MODULE("batchtest", "Batch processing of a trace for tests", \
+    "Run through a trace calling all the registered hooks for tests", \
+    init, destroy, "state", "stats", "option" )
index bafef11f49cd6d1b05e65c7d636e3b3500951ca8..c105a07c9bb80a06188a6bfbd9ff81472cadf217 100644 (file)
@@ -329,7 +329,7 @@ static int write_event_content(void *hook_data, void *call_data)
 }
 
 
-G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
+static void init()
 {
   LttvAttributeValue value;
 
@@ -337,8 +337,6 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
 
   g_info("Init textDump.c");
 
-  lttv_module_require(self, "libbatchAnalysis", argc, argv);
-
   a_string = g_string_new("");
 
   a_file_name = NULL;
@@ -393,7 +391,7 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
 }
 
 
-G_MODULE_EXPORT void destroy()
+static void destroy()
 {
   g_info("Destroy textDump");
 
@@ -419,5 +417,10 @@ G_MODULE_EXPORT void destroy()
 }
 
 
+LTTV_MODULE("textDump", "Print events in a file", \
+           "Produce a detailed text printout of a trace", \
+           init, destroy, "stats", "batchAnalysis")
+
+
 
 
This page took 0.054118 seconds and 4 git commands to generate.