summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Baulig <martin@home-of-linux.org>2000-01-12 20:37:21 +0000
committerMartin Baulig <martin@src.gnome.org>2000-01-12 20:37:21 +0000
commite2e5c3a1ccb5123aa7b2d9fdb90b556bbd00670b (patch)
treefd01faf92bbeafce6d1349ad9bba7c84ae7bdb2c
parent8d532c6298f6755d716557ef820513e1940cbb59 (diff)
downloadlibgtop-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--ChangeLog19
-rw-r--r--include/glibtop/backend.h31
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/backend.c20
-rw-r--r--lib/init-backends.c158
-rw-r--r--lib/open-backend.c37
6 files changed, 249 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 242ebf21..bc0c5efc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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, &param);
- 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));