#include <babeltrace/iterator.h>
#include <babeltrace/plugin/component-factory.h>
+#include <babeltrace/plugin/plugin.h>
+#include <babeltrace/plugin/component-class.h>
#include <babeltrace/ref.h>
#include <babeltrace/values.h>
#include <popt.h>
return ret;
}
-void call_plugins_hooks(void)
+static
+const char *component_type_str(enum bt_component_type type)
+{
+ switch (type) {
+ case BT_COMPONENT_TYPE_SOURCE:
+ return "source";
+ case BT_COMPONENT_TYPE_SINK:
+ return "sink";
+ case BT_COMPONENT_TYPE_FILTER:
+ return "filter";
+ case BT_COMPONENT_TYPE_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
+
+static
+void print_detected_component_classes(struct bt_component_factory *factory)
+{
+ int count, i;
+
+ if (!babeltrace_verbose) {
+ return;
+ }
+
+ count = bt_component_factory_get_component_class_count(factory);
+ if (count <= 0) {
+ fprintf(stderr, "No component classes found. Please make sure your plug-in search path is set correctly.");
+ return;
+ }
+
+ printf_verbose("Found %d component classes.\n", count);
+ for (i = 0; i < count; i++) {
+ struct bt_component_class *component_class =
+ bt_component_factory_get_component_class_index(
+ factory, i);
+ struct bt_plugin *plugin = bt_component_class_get_plugin(
+ component_class);
+ const char *plugin_name = bt_plugin_get_name(plugin);
+ const char *component_name = bt_component_class_get_name(
+ component_class);
+ const char *path = bt_plugin_get_path(plugin);
+ const char *author = bt_plugin_get_author(plugin);
+ const char *license = bt_plugin_get_license(plugin);
+ const char *plugin_description = bt_plugin_get_description(
+ plugin);
+ const char *component_description =
+ bt_component_class_get_description(
+ component_class);
+ enum bt_component_type type = bt_component_class_get_type(
+ component_class);
+
+ printf_verbose("[%s - %s (%s)]\n", plugin_name, component_name,
+ component_type_str(type));
+ printf_verbose("\tpath: %s\n", path);
+ printf_verbose("\tauthor: %s\n", author);
+ printf_verbose("\tlicense: %s\n", license);
+ printf_verbose("\tplugin description: %s\n",
+ plugin_description ? plugin_description : "None");
+ printf_verbose("\tcomponent description: %s\n",
+ component_description ? component_description : "None");
+ }
+}
+
+static
+void test_sink_notifications(struct bt_component *sink)
{
- bt_dummy_hook();
- bt_lttng_live_hook();
- bt_ctf_hook();
- bt_ctf_text_hook();
- bt_ctf_metadata_hook();
+ return;
}
int main(int argc, char **argv)
struct bt_format *fmt_write;
struct bt_trace_descriptor *td_write;
struct bt_context *ctx;
- struct bt_component_factory *component_factory;
- struct bt_value *components = NULL;
+ struct bt_component_factory *component_factory = NULL;
+ struct bt_component_class *source_class = NULL;
+ struct bt_component_class *sink_class = NULL;
+ struct bt_component *source = NULL, *sink = NULL;
+ struct bt_value *source_params = NULL, *sink_params = NULL;
int i;
call_plugins_hooks();
ret = -1;
goto end;
}
- printf_verbose("Looking-up plugins at %s",
+ printf_verbose("Looking-up plugins at %s\n",
opt_plugin_path ? opt_plugin_path : "Invalid");
component_factory = bt_component_factory_create();
if (!component_factory) {
goto end;
}
- ret = bt_component_factory_get_component_class_count(component_factory);
- if (ret <= 0) {
+ print_detected_component_classes(component_factory);
+
+ sink_class = bt_component_factory_get_component_class(component_factory,
+ NULL, BT_COMPONENT_TYPE_SINK, "text");
+ if (!sink_class) {
+ fprintf(stderr, "Could not find text output component class. Aborting...\n");
+ ret = -1;
+ goto end;
+ }
+
+ sink = bt_component_create(sink_class, "bt_text_output", sink_params);
+ if (!sink) {
+ fprintf(stderr, "Failed to instanciate text output. Aborting...\n");
+ ret = -1;
goto end;
}
+ test_sink_notifications(sink);
+ goto end;
+
if (opt_input_paths->len == 0) {
ret = -1;
goto end;
free(opt_debug_info_dir);
free(opt_debug_info_target_prefix);
g_ptr_array_free(opt_input_paths, TRUE);
- BT_PUT(components);
BT_PUT(component_factory);
+ BT_PUT(sink_class);
+ BT_PUT(source_class);
+ BT_PUT(source);
+ BT_PUT(sink);
+ BT_PUT(source_params);
+ BT_PUT(sink_params);
+
if (partial_error)
exit(EXIT_FAILURE);
else
struct bt_object base;
enum bt_component_type type;
GString *name;
+ GString *description;
struct bt_plugin *plugin;
bt_component_init_cb init;
};
BT_HIDDEN
struct bt_component_class *bt_component_class_create(
enum bt_component_type type, const char *name,
- struct bt_plugin *plugin);
+ const char *description, struct bt_plugin *plugin);
#endif /* BABELTRACE_PLUGIN_COMPONENT_CLASS_INTERNAL_H */
extern const char *bt_component_class_get_name(
struct bt_component_class *component_class);
+/**
+ * Get a component class' description.
+ *
+ * Component classes may provide an optional description. It may, however,
+ * opt not to.
+ *
+ * @param component_class Component class of which to get the description
+ * @returns Description of the component class, or NULL.
+ */
+extern const char *bt_component_class_get_name(
+ struct bt_component_class *component_class);
+
/**
* Get a component class' type.
*
extern enum bt_component_factory_status
bt_component_factory_register_source_component_class(
struct bt_component_factory *factory, const char *name,
- bt_component_init_cb init);
+ const char *description, bt_component_init_cb init);
extern enum bt_component_factory_status
bt_component_factory_register_sink_component_class(
struct bt_component_factory *factory, const char *name,
- bt_component_init_cb init);
+ const char *description, bt_component_init_cb init);
#ifdef __cplusplus
}
BT_HIDDEN
enum bt_component_status bt_component_init(struct bt_component *component,
- struct bt_component_class *class, const char *name,
bt_component_destroy_cb destroy);
BT_HIDDEN
BT_COMPONENT_STATUS_OK = 0,
};
-struct bt_component;
+struct bt_component;
+struct bt_value;
/**
* Create an instance of a component from a component class.
*
* @param component_class Component class of which to create an instance
* @param name Name of the new component instance, optional
+ * @param params A dictionary of component parameters
* @returns Returns a pointer to a new component instance
*/
extern struct bt_component *bt_component_create(
- struct bt_component_class *component_class, const char *name);
+ struct bt_component_class *component_class, const char *name,
+ struct bt_value *params);
/**
* Get component's name.
const char *name;
const char *author;
const char *license;
+ const char *description;
+ GString *path;
bt_plugin_init_func init;
bt_plugin_exit_func exit;
GModule *module;
};
BT_HIDDEN
-struct bt_plugin *bt_plugin_create(GModule *module);
+struct bt_plugin *bt_plugin_create(GModule *module, const char *path);
BT_HIDDEN
enum bt_component_status bt_plugin_register_component_classes(
#include <babeltrace/plugin/component.h>
/* A plugin must define the __bt_plugin_init symbol */
-#define BT_PLUGIN_NAME(_x) const char __bt_plugin_name[] = (_x)
-#define BT_PLUGIN_AUTHOR(_x) const char __bt_plugin_author[] = (_x)
-#define BT_PLUGIN_LICENSE(_x) const char __bt_plugin_license[] = (_x)
-#define BT_PLUGIN_INIT(_x) bt_plugin_init_func __bt_plugin_init = (_x)
-#define BT_PLUGIN_EXIT(_x) bt_plugin_exit_func __bt_plugin_exit = (_x)
-
-#define BT_PLUGIN_COMPONENT_CLASSES_BEGIN \
+#define BT_PLUGIN_NAME(_x) const char __bt_plugin_name[] = (_x)
+#define BT_PLUGIN_AUTHOR(_x) const char __bt_plugin_author[] = (_x)
+#define BT_PLUGIN_LICENSE(_x) const char __bt_plugin_license[] = (_x)
+#define BT_PLUGIN_DESCRIPTION(_x) const char __bt_plugin_description[] = (_x)
+#define BT_PLUGIN_INIT(_x) bt_plugin_init_func __bt_plugin_init = (_x)
+#define BT_PLUGIN_EXIT(_x) bt_plugin_exit_func __bt_plugin_exit = (_x)
+
+#define BT_PLUGIN_COMPONENT_CLASSES_BEGIN \
enum bt_component_status __bt_plugin_register_component_classes(\
- struct bt_component_factory *factory)\
+ struct bt_component_factory *factory) \
{
-#define BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(_name, _init) \
- bt_component_factory_register_source_component_class(factory, \
- _name, _init);
+#define BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(_name, description, _init) \
+ bt_component_factory_register_source_component_class(factory, \
+ _name, description, _init);
-#define BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(_name, _init) \
- bt_component_factory_register_sink_component_class(factory, \
- _name, _init);
+#define BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(_name, _description, _init) \
+ bt_component_factory_register_sink_component_class(factory, \
+ _name, _description, _init);
#define BT_PLUGIN_COMPONENT_CLASSES_END\
\
struct bt_notification_iterator;
struct bt_component;
struct bt_component_factory;
+struct bt_value;
typedef enum bt_component_status (*bt_plugin_init_func)(
struct bt_component_factory *factory);
* function.
*
* @param component Component instance
+ * @param params A dictionary of component parameters
* @returns One of #bt_component_status values
*/
typedef enum bt_component_status (*bt_component_init_cb)(
- struct bt_component *component);
+ struct bt_component *component, struct bt_value *params);
/**
* Get a component's private data.
*/
extern const char *bt_plugin_get_license(struct bt_plugin *plugin);
+/**
+ * Get the path of a plug-in.
+ *
+ * @param plugin An instance of a plug-in
+ * @returns Plug-in path or NULL on error
+ */
+extern const char *bt_plugin_get_path(struct bt_plugin *plugin);
+
#ifdef __cplusplus
}
#endif
#include <babeltrace/plugin/component-class-internal.h>
#include <babeltrace/plugin/plugin-system.h>
+struct bt_value;
+
struct bt_component_sink_class {
struct bt_component_class parent;
};
* Allocate a sink component.
*
* @param class Component class
- * @param name Component instance name (will be copied)
+ * @param params A dictionary of component parameters
* @returns A sink component instance
*/
BT_HIDDEN
-extern struct bt_component *bt_component_sink_create(
- struct bt_component_class *class, const char *name);
+struct bt_component *bt_component_sink_create(
+ struct bt_component_class *class, struct bt_value *params);
/**
- * Allocate a sink component class.
+ * Validate a sink component.
*
- * @param name Component instance name (will be copied)
- * @returns A sink component class instance
+ * @param component Sink component instance to validate
+ * @returns One of #bt_component_status
*/
-/* FIXME */
BT_HIDDEN
-extern struct bt_component *bt_component_class_sink_create(
- struct bt_component_class *class, const char *name);
+enum bt_component_status bt_component_sink_validate(
+ struct bt_component *component);
#endif /* BABELTRACE_PLUGIN_SINK_INTERNAL_H */
#include <babeltrace/plugin/component-class-internal.h>
#include <babeltrace/plugin/plugin-system.h>
+struct bt_value;
+
struct bt_component_source_class {
struct bt_component_class parent;
};
* Allocate a source component.
*
* @param class Component class
- * @param name Component instance name (will be copied)
+ * @param params A dictionary of component parameters
* @returns A source component instance
*/
BT_HIDDEN
-extern struct bt_component *bt_component_source_create(
- struct bt_component_class *class, const char *name);
+struct bt_component *bt_component_source_create(
+ struct bt_component_class *class, struct bt_value *params);
+
+/**
+ * Validate a source component.
+ *
+ * @param component Source component instance to validate
+ * @returns One of #bt_component_status
+ */
+BT_HIDDEN
+enum bt_component_status bt_component_source_validate(
+ struct bt_component *component);
#endif /* BABELTRACE_PLUGIN_SOURCE_INTERNAL_H */
if (class->name) {
g_string_free(class->name, TRUE);
}
+ if (class->description) {
+ g_string_free(class->description, TRUE);
+ }
bt_put(class->plugin);
g_free(class);
BT_HIDDEN
struct bt_component_class *bt_component_class_create(
enum bt_component_type type, const char *name,
- struct bt_plugin *plugin)
+ const char *description, struct bt_plugin *plugin)
{
struct bt_component_class *class;
bt_object_init(class, bt_component_class_destroy);
class->type = type;
class->name = g_string_new(name);
- if (!class->name) {
+ class->description = g_string_new(description);
+ if (!class->name || !class->description) {
BT_PUT(class);
goto end;
}
return component_class ? bt_get(component_class->plugin) :
NULL;
}
+
+const char *bt_component_class_get_description(
+ struct bt_component_class *component_class)
+{
+ return component_class ? component_class->description->str : NULL;
+}
+
}
/* Load plugin and make sure it defines the required entry points */
- plugin = bt_plugin_create(module);
+ plugin = bt_plugin_create(module, path);
if (!plugin) {
ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
if (!g_module_close(module)) {
static
enum bt_component_factory_status
add_component_class(struct bt_component_factory *factory, const char *name,
- bt_component_init_cb init, enum bt_component_type type)
+ const char *description, bt_component_init_cb init,
+ enum bt_component_type type)
{
struct bt_component_class *class;
enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
goto end;
}
- class = bt_component_class_create(type, name,
+ class = bt_component_class_create(type, name, description,
factory->current_plugin);
g_ptr_array_add(factory->component_classes, class);
end:
enum bt_component_factory_status
bt_component_factory_register_source_component_class(
struct bt_component_factory *factory, const char *name,
- bt_component_init_cb init)
+ const char *description, bt_component_init_cb init)
{
- return add_component_class(factory, name, init,
+ return add_component_class(factory, name, description, init,
BT_COMPONENT_TYPE_SOURCE);
}
enum bt_component_factory_status
bt_component_factory_register_sink_component_class(
struct bt_component_factory *factory, const char *name,
- bt_component_init_cb init)
+ const char *description, bt_component_init_cb init)
{
- return add_component_class(factory, name, init,
+ return add_component_class(factory, name, description, init,
BT_COMPONENT_TYPE_SINK);
}
#include <babeltrace/compiler.h>
#include <babeltrace/ref.h>
+static
+struct bt_component * (* const component_create_funcs[])(
+ struct bt_component_class *, struct bt_value *) = {
+ [BT_COMPONENT_TYPE_SOURCE] = bt_component_source_create,
+ [BT_COMPONENT_TYPE_SINK] = bt_component_sink_create,
+};
+
+static
+enum bt_component_status (* const component_validation_funcs[])(
+ struct bt_component *) = {
+ [BT_COMPONENT_TYPE_SOURCE] = bt_component_source_validate,
+ [BT_COMPONENT_TYPE_SINK] = bt_component_sink_validate,
+};
+
static
void bt_component_destroy(struct bt_object *obj)
{
component = container_of(obj, struct bt_component, base);
- /**
+ assert(component->destroy);
+ component_class = component->class;
+
+ /*
* User data is destroyed first, followed by the concrete component
* instance.
*/
- assert(!component->user_data || component->user_destroy);
- component->user_destroy(component->user_data);
-
- g_string_free(component->name, TRUE);
-
- assert(component->destroy);
- component_class = component->class;
+ if (component->user_destroy) {
+ component->user_destroy(component->user_data);
+ }
- /* Frees the component, which becomes invalid */
component->destroy(component);
- component = NULL;
-
+ g_string_free(component->name, TRUE);
bt_put(component_class);
+ g_free(component);
}
BT_HIDDEN
enum bt_component_status bt_component_init(struct bt_component *component,
- struct bt_component_class *class, const char *name,
bt_component_destroy_cb destroy)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- bt_object_init(component, bt_component_destroy);
- if (!component || !class || !name || name[0] == '\0' || !destroy) {
+ if (!component || !destroy) {
ret = BT_COMPONENT_STATUS_INVAL;
goto end;
}
- component->class = bt_get(class);
- component->name = g_string_new(name);
- if (!component->name) {
- ret = BT_COMPONENT_STATUS_NOMEM;
- goto end;
- }
component->destroy = destroy;
end:
return ret;
}
struct bt_component *bt_component_create(
- struct bt_component_class *component_class, const char *name)
+ struct bt_component_class *component_class, const char *name,
+ struct bt_value *params)
{
+ int ret;
struct bt_component *component = NULL;
+ enum bt_component_type type;
if (!component_class) {
goto end;
}
- switch (bt_component_class_get_type(component_class))
- {
- case BT_COMPONENT_TYPE_SOURCE:
- component = bt_component_source_create(component_class, name);
- break;
- case BT_COMPONENT_TYPE_SINK:
- component = bt_component_sink_create(component_class, name);
- break;
- default:
+ type = bt_component_class_get_type(component_class);
+ if (type <= BT_COMPONENT_TYPE_UNKNOWN ||
+ type >= BT_COMPONENT_TYPE_FILTER) {
+ /* Filter components are not supported yet. */
+ goto end;
+ }
+
+ component = component_create_funcs[type](component_class, params);
+ if (!component) {
+ goto end;
+ }
+
+ bt_object_init(component, bt_component_destroy);
+ component->class = bt_get(component_class);
+ component->name = g_string_new(name);
+ if (component->name) {
+ BT_PUT(component);
+ goto end;
+ }
+
+ component_class->init(component, params);
+ ret = component_validation_funcs[type](component);
+ if (ret) {
+ BT_PUT(component);
goto end;
}
end:
#include <stdbool.h>
static
-enum bt_component_status ctf_text_init(struct bt_component *);
-static
-void ctf_text_plugin_exit(void);
+enum bt_component_status ctf_text_init(struct bt_component *,
+ struct bt_value *params);
/* Initialize plug-in entry points. */
BT_PLUGIN_NAME("ctf-text");
+BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
BT_PLUGIN_AUTHOR("Jérémie Galarneau");
-BT_PLUGIN_LICENSE("MIT License");
-BT_PLUGIN_EXIT(ctf_text_plugin_exit);
+BT_PLUGIN_LICENSE("MIT");
-/* Defines BT_PLUGIN_INIT. */
BT_PLUGIN_COMPONENT_CLASSES_BEGIN
-BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(__bt_plugin_name, ctf_text_init)
+BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY("text", "Formats CTF-IR to text. Formerly known as ctf-text.", ctf_text_init)
BT_PLUGIN_COMPONENT_CLASSES_END
enum loglevel {
static
enum bt_component_status ctf_text_init(
- struct bt_component *component)
+ struct bt_component *component, struct bt_value *params)
{
- printf(__bt_plugin_name);
+ printf("ctf_text_init\n");
return BT_COMPONENT_STATUS_OK;
}
-
-static
-void ctf_text_plugin_exit(void)
-{
- printf("in ctf_text_exit\n");
-}
#include <babeltrace/plugin/plugin-internal.h>
#include <glib.h>
-#define PLUGIN_SYMBOL_NAME "__bt_plugin_name"
-#define PLUGIN_SYMBOL_AUTHOR "__bt_plugin_author"
-#define PLUGIN_SYMBOL_LICENSE "__bt_plugin_license"
-#define PLUGIN_SYMBOL_INIT "__bt_plugin_init"
-#define PLUGIN_SYMBOL_EXIT "__bt_plugin_exit"
+#define PLUGIN_SYMBOL_NAME "__bt_plugin_name"
+#define PLUGIN_SYMBOL_AUTHOR "__bt_plugin_author"
+#define PLUGIN_SYMBOL_LICENSE "__bt_plugin_license"
+#define PLUGIN_SYMBOL_INIT "__bt_plugin_init"
+#define PLUGIN_SYMBOL_EXIT "__bt_plugin_exit"
+#define PLUGIN_SYMBOL_DESCRIPTION "__bt_plugin_description"
static
void bt_plugin_destroy(struct bt_object *obj)
if (!g_module_close(plugin->module)) {
printf_error("Module close error: %s",
g_module_error());
-
}
}
+
+ if (plugin->exit) {
+ plugin->exit();
+ }
+ g_string_free(plugin->path, TRUE);
g_free(plugin);
}
BT_HIDDEN
-struct bt_plugin *bt_plugin_create(GModule *module)
+struct bt_plugin *bt_plugin_create(GModule *module, const char *path)
{
struct bt_plugin *plugin = NULL;
gpointer symbol = NULL;
- if (!module) {
+ if (!module || !path) {
goto error;
}
}
bt_object_init(plugin, bt_plugin_destroy);
+ plugin->path = g_string_new(path);
+ if (!plugin->path) {
+ goto error;
+ }
+
if (!g_module_symbol(module, PLUGIN_SYMBOL_NAME,
(gpointer *) &plugin->name)) {
printf_error("Unable to resolve plugin symbol %s from %s",
}
g_module_symbol(module, PLUGIN_SYMBOL_AUTHOR,
(gpointer *) &plugin->author);
+ g_module_symbol(module, PLUGIN_SYMBOL_DESCRIPTION,
+ (gpointer *) &plugin->description);
return plugin;
error:
{
return plugin ? plugin->license : NULL;
}
+
+const char *bt_plugin_get_path(struct bt_plugin *plugin)
+{
+ return plugin ? plugin->path->str : NULL;
+}
+
+const char *bt_plugin_get_description(struct bt_plugin *plugin)
+{
+ return plugin ? plugin->description : NULL;
+}
static
void bt_component_sink_destroy(struct bt_component *component)
{
- struct bt_component_sink *sink;
-
- if (!component) {
- return;
- }
+ return;
+}
- sink = container_of(component, struct bt_component_sink, parent);
- g_free(sink);
+BT_HIDDEN
+enum bt_component_status bt_component_sink_validate(
+ struct bt_component *component)
+{
+ return BT_COMPONENT_STATUS_OK;
}
BT_HIDDEN
struct bt_component *bt_component_sink_create(
- struct bt_component_class *class, const char *name)
+ struct bt_component_class *class, struct bt_value *params)
{
struct bt_component_sink *sink = NULL;
enum bt_component_status ret;
goto end;
}
- ret = bt_component_init(&sink->parent, class, name,
- bt_component_sink_destroy);
+ ret = bt_component_init(&sink->parent, bt_component_sink_destroy);
if (ret != BT_COMPONENT_STATUS_OK) {
BT_PUT(sink);
goto end;
static
void bt_component_source_destroy(struct bt_component *component)
{
- struct bt_component_source *source;
-
- if (!component) {
- return;
- }
+ return;
+}
- source = container_of(component, struct bt_component_source, parent);
- g_free(source);
+BT_HIDDEN
+enum bt_component_status bt_component_source_validate(
+ struct bt_component *component)
+{
+ return BT_COMPONENT_STATUS_OK;
}
BT_HIDDEN
struct bt_component *bt_component_source_create(
- struct bt_component_class *class, const char *name)
+ struct bt_component_class *class, struct bt_value *params)
{
struct bt_component_source *source = NULL;
enum bt_component_status ret;
goto end;
}
- ret = bt_component_init(&source->parent, class, name,
- bt_component_source_destroy);
+ ret = bt_component_init(&source->parent, bt_component_source_destroy);
if (ret != BT_COMPONENT_STATUS_OK) {
BT_PUT(source);
goto end;