Start of bt_component_factory implementation
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 14 Jul 2015 21:00:24 +0000 (17:00 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sat, 27 May 2017 16:57:25 +0000 (12:57 -0400)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
converter/Makefile.am
formats/lttng-live/lttng-live-comm.c
include/babeltrace/babeltrace-internal.h
include/babeltrace/plugin/component-factory-internal.h
include/babeltrace/plugin/component-factory.h
lib/prio_heap/prio_heap.c
plugins/Makefile.am
plugins/component-factory.c [new file with mode: 0644]

index 47693f5af6fd6c016c7379b36a66cd0e164c4816..1a6c0daff58c6f5794ce85973c9a835ffe4433ed 100644 (file)
@@ -17,7 +17,8 @@ babeltrace_LDADD = \
        $(top_builddir)/formats/ctf-text/libbabeltrace-ctf-text.la \
        $(top_builddir)/formats/ctf-metadata/libbabeltrace-ctf-metadata.la \
        $(top_builddir)/formats/bt-dummy/libbabeltrace-dummy.la \
-       $(top_builddir)/formats/lttng-live/libbabeltrace-lttng-live.la
+       $(top_builddir)/formats/lttng-live/libbabeltrace-lttng-live.la \
+       $(top_builddir)/plugins/libbabeltrace-plugin.la
 
 if ENABLE_DEBUG_INFO
 babeltrace_LDADD += $(top_builddir)/lib/libdebug-info.la
index fef374a381c2b4aa685f418b30bcd3ebc82b8a91..6c5d4fd296f55fc9f23f4bba506432c3889f367c 100644 (file)
 #include <babeltrace/compat/send.h>
 #include <babeltrace/compat/string.h>
 #include <babeltrace/compat/mman.h>
+#include <babeltrace/babeltrace-internal.h>
 
 #include "lttng-live.h"
 #include "lttng-viewer-abi.h"
 
 #define ACTIVE_POLL_DELAY      100     /* ms */
 
-/*
- * Memory allocation zeroed
- */
-#define zmalloc(x) calloc(1, x)
-
-#ifndef max_t
-#define max_t(type, a, b)      \
-       ((type) (a) > (type) (b) ? (type) (a) : (type) (b))
-#endif
-
 static void ctf_live_packet_seek(struct bt_stream_pos *stream_pos,
                size_t index, int whence);
 static int add_traces(struct lttng_live_ctx *ctx);
index 6384eee007f4d2bf922ab4a2d77dc253a49f9346..9a91ba46736128bae32bb13daa62963198a52147 100644 (file)
@@ -27,6 +27,8 @@
 #include <stdio.h>
 #include <glib.h>
 #include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
 #include <babeltrace/compat/string.h>
 
 #define PERROR_BUFLEN  200
@@ -159,6 +161,16 @@ extern int babeltrace_verbose, babeltrace_debug;
 #define max(a, b)      (((a) > (b)) ? (a) : (b))
 #endif
 
+#ifndef max_t
+#define max_t(type, a, b)      \
+       ((type) (a) > (type) (b) ? (type) (a) : (type) (b))
+#endif
+
+/*
+ * Memory allocation zeroed
+ */
+#define zmalloc(x) calloc(1, x)
+
 /*
  * BT_HIDDEN: set the hidden attribute for internal functions
  */
index 0508cd860728e51374c47cc4ba1cfe041b068885..3149bad3529b231ed847a58530a8bedf2cf5ddf4 100644 (file)
  */
 
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/plugin/component-internal.h>
+#include <babeltrace/plugin/component-factory.h>
+#include <babeltrace/plugin/component.h>
 #include <babeltrace/plugin/plugin-system.h>
+#include <glib.h>
+#include <gmodule.h>
+
+struct component_entry {
+       enum bt_component_type type;
+       GString *name;
+};
+
+struct source_component_entry {
+       struct component_entry parent;
+       bt_component_source_init_cb init;
+       
+};
+
+struct sink_component_entry {
+       struct component_entry parent;
+       bt_component_sink_init_cb init;
+};
 
 struct bt_component_factory {
-       int a;
+       /** Array of GModule pointers */
+       GPtrArray *modules;
+       /** Array of pointers to struct component_entry */
+       GPtrArray *components;
 };
 
 #endif /* BABELTRACE_PLUGIN_COMPONENT_FACTORY_INTERNAL_H */
index 350bf72ddafa5dc444100d52a083dd8c4521548f..ded452f1430f487194a6c9ee89d5519f16a83cd5 100644 (file)
 extern "C" {
 #endif
 
+/**
+ * Status code. Errors are always negative.
+ */
+enum bt_component_factory_status {
+       /** General error. */
+       BT_COMPONENT_FACTORY_STATUS_ERROR =     -128,
+
+       /** Invalid arguments. */
+       /* -22 for compatibility with -EINVAL */
+       BT_COMPONENT_FACTORY_STATUS_INVAL =     -22,
+
+       /** Memory allocation failure. */
+       /* -12 for compatibility with -ENOMEM */
+       BT_COMPONENT_FACTORY_STATUS_NOMEM =     -12,
+
+       /** I/O error. */
+       /* -5 for compatibility with -EIO */
+       BT_COMPONENT_FACTORY_STATUS_IO =        -5,
+
+       /** No such file or directory. */
+       /* -2 for compatibility with -ENOENT */
+       BT_COMPONENT_FACTORY_STATUS_NOENT =     -2,
+
+       /** Operation not permitted. */
+       /* -1 for compatibility with -EPERM */
+       BT_COMPONENT_FACTORY_STATUS_PERM =      -1,
+
+       /** No error, okay. */
+       BT_COMPONENT_FACTORY_STATUS_OK =        0,
+};
+
 struct bt_component_factory;
 
-enum bt_component_status bt_component_factory_create(const char *path);
+/**
+ * Create a component factory.
+ *
+ * @returns    An instance of component factory
+ */
+extern
+struct bt_component_factory *bt_component_factory_create(void);
+
+/**
+ * Recursively load and register Babeltrace plugins under a given path.
+ *
+ * Path will be traversed recursively if it is a directory, otherwise only the
+ * provided file will be loaded.
+ *
+ * @param factory      A component factory instance
+ * @param path         A path to a file or directory
+ * @returns            One of #bt_component_factory_status values
+ */
+extern
+enum bt_component_factory_status bt_component_factory_load(
+               struct bt_component_factory *factory, const char *path);
 
-enum bt_component_status bt_component_factory_register_source_component_class(
+extern
+enum bt_component_factory_status
+bt_component_factory_register_source_component_class(
        struct bt_component_factory *factory, const char *name,
        bt_component_source_init_cb init);
 
-enum bt_component_status bt_component_factory_register_sink_component_class(
+extern
+enum bt_component_factory_status bt_component_factory_register_sink_component_class(
        struct bt_component_factory *factory, const char *name,
        bt_component_sink_init_cb init);
 
+extern
 void bt_component_factory_destroy(struct bt_component_factory *factory);
 
 #ifdef __cplusplus
index 8942a113aec50038fe20f59c6bbf84756a2d780d..58e3de68b5f0e93d4260e48841b1a698e3c897bc 100644 (file)
 #include <string.h>
 #include <assert.h>
 
-#ifndef max_t
-#define max_t(type, a, b)      \
-       ((type) (a) > (type) (b) ? (type) (a) : (type) (b))
-#endif
-
 #ifdef DEBUG_HEAP
 void check_heap(const struct ptr_heap *heap)
 {
index ec8248ffbdbe29a49f9c680c5d69d69bac421a3b..53b9ec32fa2b77df79a4d6f9fd60624a0aedfea9 100644 (file)
@@ -7,6 +7,7 @@ lib_LTLIBRARIES = libbabeltrace-plugin.la
 # Plug-in system library
 libbabeltrace_plugin_la_SOURCES = \
        component.c \
+       component-factory.c \
        source.c \
        sink.c \
        iterator.c
diff --git a/plugins/component-factory.c b/plugins/component-factory.c
new file mode 100644 (file)
index 0000000..b4ebe3f
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * component-factory.c
+ *
+ * Babeltrace Plugin Component Factory
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/plugin/component-factory.h>
+#include <babeltrace/plugin/component-factory-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/compiler.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define NATIVE_PLUGIN_SUFFIX ".so"
+#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
+#define LIBTOOL_PLUGIN_SUFFIX ".la"
+#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
+#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX),\
+                               sizeof(LIBTOOL_PLUGIN_SUFFIX))
+
+static
+void module_close(gpointer data)
+{
+       if (g_module_close((GModule *) data)) {
+               printf_error("Failed to close plugin");
+       }
+}
+
+static
+void factory_destroy(gpointer data)
+{
+       bt_component_factory_destroy((struct bt_component_factory *)data);
+}
+
+/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
+static
+struct dirent *alloc_dirent(const char *path)
+{
+       size_t len;
+       long name_max;
+       struct dirent *entry;
+
+       name_max = pathconf(path, _PC_NAME_MAX);
+       if (name_max == -1) {
+               name_max = PATH_MAX;
+       }
+       len = offsetof(struct dirent, d_name) + name_max + 1;
+       entry = zmalloc(len);
+       return entry;
+}
+
+static
+enum bt_component_factory_status
+bt_component_factory_load_file(struct bt_component_factory *factory,
+               const char *path)
+{
+       enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+       size_t path_len;
+       GModule *module;
+
+       if (!factory || !path) {
+               ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
+               goto end;
+       }
+
+       path_len = strlen(path);
+       if (path_len <= PLUGIN_SUFFIX_LEN) {
+               goto end;
+       }
+
+       path_len++;
+       /*
+        * Check if the file ends with a known plugin file type suffix (i.e. .so
+        * or .la on Linux).
+        */
+       if (strncmp(NATIVE_PLUGIN_SUFFIX,
+               path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
+               NATIVE_PLUGIN_SUFFIX_LEN) &&
+               strncmp(LIBTOOL_PLUGIN_SUFFIX,
+               path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
+               LIBTOOL_PLUGIN_SUFFIX_LEN)) {
+               /* Not a plugin file. */
+               goto end;
+       }
+
+       module = g_module_open(path, 0);
+       if (!module) {
+               printf_error("Module open error: %s", g_module_error());
+               goto end;
+       }
+
+       /* Check if the module defines the appropriate entry points */
+end:
+       return ret;
+}
+
+static
+enum bt_component_factory_status
+bt_component_factory_load_dir_recursive(struct bt_component_factory *factory,
+               const char *path)
+{
+       DIR *directory = NULL;
+       struct dirent *entry = NULL, *result = NULL;
+       char *file_path = NULL;
+       size_t path_len = strlen(path);
+       enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+
+       if (path_len >= PATH_MAX) {
+               ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
+               goto end;
+       }
+
+       entry = alloc_dirent(path);
+       if (!entry) {
+               ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
+               goto end;
+       }
+
+       file_path = zmalloc(PATH_MAX);
+       if (!file_path) {
+               ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
+               goto end;
+       }
+
+       strncpy(file_path, path, path_len);
+       /* Append a trailing '/' to the path */
+       if (file_path[path_len - 1] != '/') {
+               file_path[path_len++] = '/';
+       }
+
+       /* Recursively walk directory */
+       while (!readdir_r(directory, entry, &result) && result) {
+               struct stat st;
+               int stat_ret;
+               size_t file_name_len = strlen(result->d_name);
+
+               if (path_len + file_name_len >= PATH_MAX) {
+                       continue;
+               }
+
+               strncpy(file_path + path_len, result->d_name, file_name_len);
+               file_path[path_len + file_name_len] = '\0';
+
+               stat_ret = stat(file_path, &st);
+               if (stat_ret < 0) {
+                       /* Continue to next file / directory. */
+                       printf_perror("Failed to stat() plugin file");
+                       continue;
+               }
+
+               if (S_ISDIR(st.st_mode)) {
+                       ret = bt_component_factory_load_dir_recursive(factory,
+                               file_path);
+                       if (ret != BT_COMPONENT_FACTORY_STATUS_OK) {
+                               goto end;
+                       }
+               } else if (S_ISREG(st.st_mode)) {
+                       ret = bt_component_factory_load_file(factory,
+                               file_path);
+                       if (ret != BT_COMPONENT_FACTORY_STATUS_OK) {
+                               goto end;
+                       }
+               }
+       }
+end:
+       free(entry);
+       free(file_path);
+       return ret;
+}
+
+void bt_component_factory_destroy(struct bt_component_factory *factory)
+{
+       if (!factory) {
+               return;
+       }
+
+       g_free(factory);
+}
+
+struct bt_component_factory *
+bt_component_factory_create(void)
+{
+       struct bt_component_factory *factory;
+
+       factory = g_new0(struct bt_component_factory, 1);
+       if (!factory) {
+               goto end;
+       }
+
+       factory->modules = g_ptr_array_new_with_free_func(module_close);
+       if (!factory->modules) {
+               goto error;
+       }
+
+       factory->components = g_ptr_array_new_with_free_func(factory_destroy);
+       if (factory->components) {
+               goto error;
+       }
+end:
+       return factory;
+error:
+       bt_component_factory_destroy(factory);
+       return NULL;
+}
+
+enum bt_component_factory_status bt_component_factory_load(
+               struct bt_component_factory *factory, const char *path)
+{
+       enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+       DIR *directory = NULL;
+
+       if (!factory || !path) {
+               ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
+               goto end;
+       }
+
+       directory = opendir(path) ;
+       if (!directory) {
+               switch (errno) {
+               case ENOTDIR:
+                       /* Try loading as a file. */
+                       break;
+               case ENOENT:
+                       ret = BT_COMPONENT_FACTORY_STATUS_NOENT;
+                       goto end;
+               default:
+                       ret = BT_COMPONENT_FACTORY_STATUS_IO;
+                       goto end;
+               }
+       }
+
+       if (directory) {
+               ret = bt_component_factory_load_dir_recursive(factory, path);
+       } else {
+               ret = bt_component_factory_load_file(factory, path);
+       }
+end:
+       if (directory) {
+               closedir(directory);
+       }
+       return ret;
+}
This page took 0.030769 seconds and 4 git commands to generate.