diff options
author | Martin Baulig <martin@home-of-linux.org> | 2000-01-12 20:37:21 +0000 |
---|---|---|
committer | Martin Baulig <martin@src.gnome.org> | 2000-01-12 20:37:21 +0000 |
commit | e2e5c3a1ccb5123aa7b2d9fdb90b556bbd00670b (patch) | |
tree | fd01faf92bbeafce6d1349ad9bba7c84ae7bdb2c | |
parent | 8d532c6298f6755d716557ef820513e1940cbb59 (diff) | |
download | libgtop-e2e5c3a1ccb5123aa7b2d9fdb90b556bbd00670b.tar.gz |
New type. (glibtop_backend_module): New private type.
2000-01-12 Martin Baulig <martin@home-of-linux.org>
* include/glibtop/backend.h (glibtop_backend_entry): New type.
(glibtop_backend_module): New private type.
* lib/backend.c (glibtop_register_backend): This now takes a
`glibtop_backend_entry' argument, not a `glibtop_backend_info' one.
(glibtop_backend_by_id): Return a `glibtop_backend_entry' type,
not a `glibtop_backend_info' one.
(glibtop_backend_by_name): Likewise.
* lib/init-backends.c: If we have libxml, read all `.backend' files
in $(LIBGTOP_BACKEND_DIR), XML parse them and register them via
`glibtop_backend_register'. This builds a list of all currently
supported backends without actually loading them into memory.
* lib/open-backend.c (glibtop_open_backend_l): GModule load the
backend if it's not already in memory.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | include/glibtop/backend.h | 31 | ||||
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/backend.c | 20 | ||||
-rw-r--r-- | lib/init-backends.c | 158 | ||||
-rw-r--r-- | lib/open-backend.c | 37 |
6 files changed, 249 insertions, 17 deletions
@@ -1,5 +1,24 @@ 2000-01-12 Martin Baulig <martin@home-of-linux.org> + * include/glibtop/backend.h (glibtop_backend_entry): New type. + (glibtop_backend_module): New private type. + + * lib/backend.c (glibtop_register_backend): This now takes a + `glibtop_backend_entry' argument, not a `glibtop_backend_info' one. + (glibtop_backend_by_id): Return a `glibtop_backend_entry' type, + not a `glibtop_backend_info' one. + (glibtop_backend_by_name): Likewise. + + * lib/init-backends.c: If we have libxml, read all `.backend' files + in $(LIBGTOP_BACKEND_DIR), XML parse them and register them via + `glibtop_backend_register'. This builds a list of all currently + supported backends without actually loading them into memory. + + * lib/open-backend.c (glibtop_open_backend_l): GModule load the + backend if it's not already in memory. + +2000-01-12 Martin Baulig <martin@home-of-linux.org> + * lib/init.c (glibtop_init_s): Comment out `_glibtop_init_hook_s'. * configure.in: We now require libxml. diff --git a/include/glibtop/backend.h b/include/glibtop/backend.h index add3336f..f4e94326 100644 --- a/include/glibtop/backend.h +++ b/include/glibtop/backend.h @@ -34,6 +34,8 @@ BEGIN_LIBGTOP_DECLS typedef struct _glibtop_backend_info glibtop_backend_info; +typedef struct _glibtop_backend_entry glibtop_backend_entry; +typedef struct _glibtop_backend_module glibtop_backend_module; typedef struct _glibtop_backend_private glibtop_backend_private; typedef struct _glibtop_backend glibtop_backend; @@ -52,6 +54,29 @@ struct _glibtop_backend_info glibtop_call_vector *call_vector; }; +#ifdef _IN_LIBGTOP + +#include <gmodule.h> + +/* private structure */ +struct _glibtop_backend_module +{ + int refcount; + GModule *module; +}; + +#endif /* _IN_LIBGTOP */ + +struct _glibtop_backend_entry +{ + char *name; + char *libtool_name; + char *shlib_name; + + glibtop_backend_info *info; + glibtop_backend_module *_priv; +}; + struct _glibtop_backend { glibtop_backend_info *info; @@ -59,15 +84,15 @@ struct _glibtop_backend }; long -glibtop_register_backend (glibtop_backend_info *info); +glibtop_register_backend (glibtop_backend_entry *entry); void glibtop_unregister_backend (long id); -glibtop_backend_info * +glibtop_backend_entry * glibtop_backend_by_id (long id); -glibtop_backend_info * +glibtop_backend_entry * glibtop_backend_by_name (const char *backend_name); void diff --git a/lib/Makefile.am b/lib/Makefile.am index 2eb777dd..ef2164ed 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -9,6 +9,7 @@ libgtop_la_SOURCES = init.c open.c close.c lib.c parameter.c \ backend.c init-backends.c open-backend.c libgtop_la_LDFLAGS = $(LT_VERSION_INFO) +libgtop_la_LIBADD = $(LIBGTOP_XML_LIB) glibtopdir = $(includedir)/glibtop diff --git a/lib/backend.c b/lib/backend.c index 632db119..8e000346 100644 --- a/lib/backend.c +++ b/lib/backend.c @@ -33,7 +33,7 @@ static GHashTable *_glibtop_backend_list = NULL; static long _glibtop_backend_nr = 0; long -glibtop_register_backend (glibtop_backend_info *info) +glibtop_register_backend (glibtop_backend_entry *entry) { long id; @@ -44,7 +44,7 @@ glibtop_register_backend (glibtop_backend_info *info) g_hash_table_insert (_glibtop_backend_list, GINT_TO_POINTER (id), - info); + entry); return id; } @@ -56,7 +56,7 @@ glibtop_unregister_backend (long id) GINT_TO_POINTER (id)); } -glibtop_backend_info * +glibtop_backend_entry * glibtop_backend_by_id (long id) { return g_hash_table_lookup (_glibtop_backend_list, @@ -65,23 +65,23 @@ glibtop_backend_by_id (long id) typedef struct { const char *backend_name; - glibtop_backend_info *info; + glibtop_backend_entry *entry; } _find_by_name_param_t; static void find_by_name (gpointer key, gpointer value, gpointer user_data) { _find_by_name_param_t *param = (_find_by_name_param_t *) user_data; - glibtop_backend_info *info = (glibtop_backend_info *) value; + glibtop_backend_entry *entry = (glibtop_backend_entry *) value; - if (!info || !info->name || param->info) + if (!entry || !entry->name || param->entry) return; - if (!strcmp (info->name, param->backend_name)) - param->info = info; + if (!strcmp (entry->name, param->backend_name)) + param->entry = entry; } -glibtop_backend_info * +glibtop_backend_entry * glibtop_backend_by_name (const char *backend_name) { _find_by_name_param_t param = { backend_name, NULL }; @@ -89,5 +89,5 @@ glibtop_backend_by_name (const char *backend_name) g_hash_table_foreach (_glibtop_backend_list, find_by_name, ¶m); - return param.info; + return param.entry; } diff --git a/lib/init-backends.c b/lib/init-backends.c index f1003907..efe14d0c 100644 --- a/lib/init-backends.c +++ b/lib/init-backends.c @@ -33,6 +33,18 @@ extern glibtop_backend_info glibtop_backend_server; extern glibtop_backend_info glibtop_backend_sysdeps; extern glibtop_backend_info glibtop_backend_common; +#if HAVE_LIBXML + +#define LIBGTOP_XML_NAMESPACE "http://www.home-of-linux.org/libgtop/1.1" + +#include <gnome-xml/parser.h> + +#include <dirent.h> + +static void _glibtop_init_gmodule_backends (const char *); + +#endif /* HAVE_LIBXML */ + void glibtop_init_backends (void) { @@ -42,7 +54,147 @@ glibtop_init_backends (void) return; backends_initialized = 1; - glibtop_register_backend (&glibtop_backend_server); - glibtop_register_backend (&glibtop_backend_sysdeps); - glibtop_register_backend (&glibtop_backend_common); +#if HAVE_LIBXML + _glibtop_init_gmodule_backends (LIBGTOP_BACKEND_DIR); +#endif +} + +#if HAVE_LIBXML + +static gchar * +_get_library_filename (xmlDocPtr doc, xmlNodePtr cur, const char *directory) +{ + char *filename = xmlNodeListGetString (doc, cur->childs, 1); + gchar *retval; + + if (!filename) + return NULL; + + /* already absolute */ + if (filename [0] == '/') + retval = g_strdup (filename); + else + retval = g_strdup_printf ("%s/%s", directory, filename); + + return retval; } + +static glibtop_backend_entry * +_parseBackend (xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *dir) +{ + glibtop_backend_entry *ret = NULL; + + /* + * allocate the struct + */ + ret = g_new0 (glibtop_backend_entry, 1); + + /* We don't care what the top level element name is */ + cur = cur->childs; + while (cur != NULL) { + if ((!strcmp (cur->name, "Name")) && (cur->ns == ns)) + ret->name = xmlNodeListGetString + (doc, cur->childs, 1); + + if ((!strcmp (cur->name, "Location")) && (cur->ns == ns)) { + xmlNodePtr sub = cur->childs; + + while (sub != NULL) { + if ((!strcmp (sub->name, "LibtoolName")) && (sub->ns == ns)) + ret->libtool_name = _get_library_filename (doc, sub, dir); + if ((!strcmp (sub->name, "ShlibName")) && (sub->ns == ns)) + ret->shlib_name = _get_library_filename (doc, sub, dir); + + sub = sub->next; + } + } + + cur = cur->next; + } + + return ret; +} + +static void +_glibtop_init_gmodule_backends (const char *directory) +{ + DIR *dir; + struct dirent *entry; + + dir = opendir (directory); + if (!dir) return; + + while ((entry = readdir (dir)) != NULL) { + size_t len = strlen (entry->d_name); + gchar *filename; + xmlDocPtr doc; + xmlNsPtr ns; + xmlNodePtr cur; + + if (len < 8) + continue; + + if (strcmp (entry->d_name+len-8, ".backend")) + continue; + + filename = g_strdup_printf ("%s/%s", directory, entry->d_name); + + doc = xmlParseFile (filename); + + if (!doc) { + g_warning ("Cannot parse %s", filename); + g_free (filename); + continue; + } + + /* Make sure the document is of the right kind */ + + cur = xmlDocGetRootElement (doc); + if (!cur) { + xmlFreeDoc (doc); + g_free (filename); + continue; + } + + ns = xmlSearchNsByHref (doc, cur, LIBGTOP_XML_NAMESPACE); + if (!ns) { + g_warning ("File %s of wrong type; LibGTop Namespace not found", + filename); + g_free (filename); + xmlFreeDoc (doc); + continue; + } + + if (strcmp (cur->name, "Backends")) { + g_warning ("File %s of the wrong type, root node != 'Backends'", + filename); + g_free (filename); + xmlFreeDoc (doc); + continue; + } + + cur = cur->childs; + while (cur != NULL) { + glibtop_backend_entry *backend; + + if ((!strcmp(cur->name, "Backend")) && (cur->ns == ns)) { + backend = _parseBackend (doc, ns, cur, directory); + if (!backend) { + g_warning ("File %s of wrong type; cannot parse", + filename); + continue; + } + + glibtop_register_backend (backend); + } + cur = cur->next; + } + + g_free (filename); + xmlFreeDoc (doc); + } + + closedir (dir); +} + +#endif /* HAVE_LIBXML */ diff --git a/lib/open-backend.c b/lib/open-backend.c index d4e924f9..fb54a0a5 100644 --- a/lib/open-backend.c +++ b/lib/open-backend.c @@ -29,14 +29,49 @@ #include <glibtop/backend.h> +#include <gmodule.h> + int glibtop_open_backend_l (glibtop *server, const char *backend_name, u_int64_t features, const char **backend_args) { + glibtop_backend_entry *entry; glibtop_backend_info *info; glibtop_backend *backend; - info = glibtop_backend_by_name (backend_name); + entry = glibtop_backend_by_name (backend_name); + if (!entry) return -GLIBTOP_ERROR_NO_SUCH_BACKEND; + + if (!entry->_priv) { + entry->_priv = g_new0 (glibtop_backend_module, 1); + + entry->_priv->module = g_module_open (entry->shlib_name, + G_MODULE_BIND_LAZY); + if (!entry->_priv->module) { + glibtop_warn_r (server, "Cannot open shared library `%s' " + "for backend `%s'", entry->shlib_name, + entry->name); + return -GLIBTOP_ERROR_NO_SUCH_BACKEND; + } + + if (!g_module_symbol (entry->_priv->module, + "LibGTopBackendInfo", + (gpointer*) &entry->info)) { + glibtop_warn_r (server, "Library `%s' is not a valid " + "LibGTop Backend library (start symbol not found)", + entry->shlib_name); + + g_module_close (entry->_priv->module); + g_free (entry->_priv); + entry->_priv = NULL; + + return -GLIBTOP_ERROR_NO_SUCH_BACKEND; + } + + entry->_priv->refcount++; + } + + info = entry->info; if (!info) return -GLIBTOP_ERROR_NO_SUCH_BACKEND; backend = glibtop_calloc_r (server, 1, sizeof (glibtop_backend)); |