extern "C" {
#endif
-extern const bt_plugin *bt_plugin_find(const char *plugin_name);
-
-extern const bt_plugin_set *bt_plugin_find_all_from_file(
- const char *path);
-
-extern const bt_plugin_set *bt_plugin_find_all_from_dir(
- const char *path, bt_bool recurse);
-
-extern const bt_plugin_set *bt_plugin_find_all_from_static(void);
+typedef enum bt_plugin_status {
+ BT_PLUGIN_STATUS_OK = 0,
+ BT_PLUGIN_STATUS_NOT_FOUND = 2,
+ BT_PLUGIN_STATUS_ERROR = -1,
+ BT_PLUGIN_STATUS_LOADING_ERROR = -2,
+ BT_PLUGIN_STATUS_NOMEM = -12,
+} bt_plugin_status;
+
+extern bt_plugin_status bt_plugin_find(const char *plugin_name,
+ bt_bool fail_on_load_error, const bt_plugin **plugin);
+
+extern bt_plugin_status bt_plugin_find_all_from_file(
+ const char *path, bt_bool fail_on_load_error,
+ const bt_plugin_set **plugin_set);
+
+extern bt_plugin_status bt_plugin_find_all_from_dir(
+ const char *path, bt_bool recurse, bt_bool fail_on_load_error,
+ const bt_plugin_set **plugin_set);
+
+extern bt_plugin_status bt_plugin_find_all_from_static(
+ bt_bool fail_on_load_error,
+ const bt_plugin_set **plugin_set);
extern const char *bt_plugin_get_name(const bt_plugin *plugin);
pass
+class PluginLoadingError(Error):
+ pass
+
+
class _ListenerHandle:
def __init__(self, listener_id, obj):
self._listener_id = listener_id
* THE SOFTWARE.
*/
-/* From plugin-const.h */
+/* Output argument typemap for plugin output (always appends) */
+%typemap(in, numinputs=0)
+ (const bt_plugin **OUT)
+ (bt_plugin *temp_plugin = NULL) {
+ $1 = &temp_plugin;
+}
-extern const bt_plugin *bt_plugin_find(const char *plugin_name);
+%typemap(argout)
+ (const bt_plugin **OUT) {
+ if (*$1) {
+ /* SWIG_Python_AppendOutput() steals the created object */
+ $result = SWIG_Python_AppendOutput($result,
+ SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
+ SWIGTYPE_p_bt_plugin, 0));
+ } else {
+ /* SWIG_Python_AppendOutput() steals Py_None */
+ Py_INCREF(Py_None);
+ $result = SWIG_Python_AppendOutput($result, Py_None);
+ }
+}
-extern const bt_plugin_set *bt_plugin_find_all_from_file(
- const char *path);
+/* Output argument typemap for plugin set output (always appends) */
+%typemap(in, numinputs=0)
+ (const bt_plugin_set **OUT)
+ (bt_plugin_set *temp_plugin_set = NULL) {
+ $1 = &temp_plugin_set;
+}
-extern const bt_plugin_set *bt_plugin_find_all_from_dir(
- const char *path, bt_bool recurse);
+%typemap(argout)
+ (const bt_plugin_set **OUT) {
+ if (*$1) {
+ /* SWIG_Python_AppendOutput() steals the created object */
+ $result = SWIG_Python_AppendOutput($result,
+ SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
+ SWIGTYPE_p_bt_plugin_set, 0));
+ } else {
+ /* SWIG_Python_AppendOutput() steals Py_None */
+ Py_INCREF(Py_None);
+ $result = SWIG_Python_AppendOutput($result, Py_None);
+ }
+}
+
+/* From plugin-const.h */
-extern const bt_plugin_set *bt_plugin_find_all_from_static(void);
+typedef enum bt_plugin_status {
+ BT_PLUGIN_STATUS_OK = 0,
+ BT_PLUGIN_STATUS_NOT_FOUND = 2,
+ BT_PLUGIN_STATUS_ERROR = -1,
+ BT_PLUGIN_STATUS_LOADING_ERROR = -2,
+ BT_PLUGIN_STATUS_NOMEM = -12,
+} bt_plugin_status;
extern const char *bt_plugin_get_name(const bt_plugin *plugin);
extern const char *bt_plugin_get_path(const bt_plugin *plugin);
-extern bt_property_availability bt_plugin_get_version(
- const bt_plugin *plugin, unsigned int *OUT,
- unsigned int *OUT, unsigned int *OUT, const char **OUT);
-
extern uint64_t bt_plugin_get_source_component_class_count(
const bt_plugin *plugin);
const bt_plugin *plugin, unsigned int *OUT,
unsigned int *OUT, unsigned int *OUT, const char **OUT);
+bt_plugin_status bt_plugin_find_wrapper(const char *plugin_name,
+ bt_bool fail_on_load_error, const bt_plugin **OUT);
+
+bt_plugin_status bt_plugin_find_all_from_file_wrapper(
+ const char *path, bt_bool fail_on_load_error,
+ const bt_plugin_set **OUT);
+
+bt_plugin_status bt_plugin_find_all_from_dir_wrapper(
+ const char *path, bt_bool recurse, bt_bool fail_on_load_error,
+ const bt_plugin_set **OUT);
+
%{
/*
- * This wrapper ensures that when the API function fails, the `*extra` output
- * parameter is set to NULL. This is necessary because the epilogue of the
- * "char **OUT" typemap will use that value to make a Python str object. We
- * can't rely on the initial value of `*extra`, it could point to unreadable
- * memory.
+ * This *_wrapper() functions below ensure that when the API function
+ * fails, the output parameter is set to `NULL`. This is necessary
+ * because the epilogue of the `something **OUT` typemap will use that
+ * value to make a Python object. We can't rely on the initial value of
+ * `*OUT`; it could point to unreadable memory.
*/
bt_property_availability bt_plugin_get_version_wrapper(
return ret;
}
+bt_plugin_status bt_plugin_find_wrapper(const char *plugin_name,
+ bt_bool fail_on_load_error, const bt_plugin **plugin)
+{
+ bt_plugin_status status;
+
+ status = bt_plugin_find(plugin_name, fail_on_load_error,
+ plugin);
+ if (status != BT_PLUGIN_STATUS_OK) {
+ *plugin = NULL;
+ }
+
+ return status;
+}
+
+bt_plugin_status bt_plugin_find_all_from_file_wrapper(
+ const char *path, bt_bool fail_on_load_error,
+ const bt_plugin_set **plugin_set)
+{
+ bt_plugin_status status;
+
+ status = bt_plugin_find_all_from_file(path, fail_on_load_error,
+ plugin_set);
+ if (status != BT_PLUGIN_STATUS_OK) {
+ *plugin_set = NULL;
+ }
+
+ return status;
+}
+
+bt_plugin_status bt_plugin_find_all_from_dir_wrapper(
+ const char *path, bt_bool recurse, bt_bool fail_on_load_error,
+ const bt_plugin_set **plugin_set)
+{
+ bt_plugin_status status;
+
+ status = bt_plugin_find_all_from_dir(path, recurse, fail_on_load_error,
+ plugin_set);
+ if (status != BT_PLUGIN_STATUS_OK) {
+ *plugin_set = NULL;
+ }
+
+ return status;
+}
+
%}
import bt2
-def find_plugins(path, recurse=True):
+def _handle_status(status, gen_error_msg):
+ if status == native_bt.PLUGIN_STATUS_LOADING_ERROR:
+ raise bt2.PluginLoadingError
+ elif status < 0:
+ raise bt2.Error(gen_error_msg)
+
+
+def find_plugins(path, recurse=True, fail_on_load_error=False):
utils._check_str(path)
utils._check_bool(recurse)
+ utils._check_bool(fail_on_load_error)
plugin_set_ptr = None
if os.path.isfile(path):
- plugin_set_ptr = native_bt.plugin_find_all_from_file(path)
+ status, plugin_set_ptr = native_bt.plugin_find_all_from_file_wrapper(path, fail_on_load_error)
elif os.path.isdir(path):
- plugin_set_ptr = native_bt.plugin_find_all_from_dir(path, int(recurse))
+ status, plugin_set_ptr = native_bt.plugin_find_all_from_dir_wrapper(path, int(recurse), int(fail_on_load_error))
+ else:
+ raise bt2.Error("invalid path: '{}'".format(path))
+
+ _handle_status(status, 'failed to find plugins')
- if plugin_set_ptr is None:
+ if status == native_bt.PLUGIN_STATUS_NOT_FOUND:
return
+ assert plugin_set_ptr is not None
return _PluginSet._create_from_ptr(plugin_set_ptr)
-def find_plugin(name):
+def find_plugin(name, fail_on_load_error=False):
utils._check_str(name)
- ptr = native_bt.plugin_find(name)
+ utils._check_bool(fail_on_load_error)
+ status, ptr = native_bt.plugin_find_wrapper(name, int(fail_on_load_error))
+ _handle_status(status, 'failed to find plugin')
- if ptr is None:
+ if status == native_bt.PLUGIN_STATUS_NOT_FOUND:
return
+ assert ptr is not None
return _Plugin._create_from_ptr(ptr)
for (i = 0; i < nr_paths; i++) {
const bt_value *plugin_path_value = NULL;
const char *plugin_path;
- const bt_plugin_set *plugin_set;
+ const bt_plugin_set *plugin_set = NULL;
+ bt_plugin_status status;
plugin_path_value =
bt_value_array_borrow_element_by_index_const(
continue;
}
- plugin_set = bt_plugin_find_all_from_dir(plugin_path, false);
- if (!plugin_set) {
- BT_LOGI("Unable to load dynamic plugins from directory: "
+ status = bt_plugin_find_all_from_dir(plugin_path, BT_FALSE,
+ BT_FALSE, &plugin_set);
+ if (status < 0) {
+ BT_LOGE("Unable to load dynamic plugins from directory: "
"path=\"%s\"", plugin_path);
continue;
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ BT_LOGI("No plugins found in directory: path=\"%s\"",
+ plugin_path);
+ continue;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+ BT_ASSERT(plugin_set);
add_to_loaded_plugins(plugin_set);
bt_plugin_set_put_ref(plugin_set);
}
{
int ret = 0;
const bt_plugin_set *plugin_set;
+ bt_plugin_status status;
BT_LOGI("Loading static plugins.");
- plugin_set = bt_plugin_find_all_from_static();
- if (!plugin_set) {
+ status = bt_plugin_find_all_from_static(BT_FALSE, &plugin_set);
+ if (status < 0) {
BT_LOGE("Unable to load static plugins.");
ret = -1;
goto end;
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ BT_LOGI("No static plugins found.");
+ goto end;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+ BT_ASSERT(plugin_set);
add_to_loaded_plugins(plugin_set);
bt_plugin_set_put_ref(plugin_set);
end:
}
static
-struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
- const char *path)
+enum bt_plugin_status bt_plugin_so_shared_lib_handle_create(
+ const char *path,
+ struct bt_plugin_so_shared_lib_handle **shared_lib_handle)
{
- struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
+ BT_ASSERT(shared_lib_handle);
BT_LOGI("Creating shared library handle: path=\"%s\"", path);
- shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
- if (!shared_lib_handle) {
+ *shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
+ if (!*shared_lib_handle) {
BT_LOGE_STR("Failed to allocate one shared library handle.");
- goto error;
+ status = BT_PLUGIN_STATUS_NOMEM;
+ goto end;
}
- bt_object_init_shared(&shared_lib_handle->base,
+ bt_object_init_shared(&(*shared_lib_handle)->base,
bt_plugin_so_shared_lib_handle_destroy);
if (!path) {
goto end;
}
- shared_lib_handle->path = g_string_new(path);
- if (!shared_lib_handle->path) {
+ (*shared_lib_handle)->path = g_string_new(path);
+ if (!(*shared_lib_handle)->path) {
BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
+ status = BT_PLUGIN_STATUS_NOMEM;
+ goto end;
}
- shared_lib_handle->module = g_module_open(path, G_MODULE_BIND_LOCAL);
- if (!shared_lib_handle->module) {
+ (*shared_lib_handle)->module = g_module_open(path, G_MODULE_BIND_LOCAL);
+ if (!(*shared_lib_handle)->module) {
/*
* INFO-level logging because we're only _trying_ to
* open this file as a Babeltrace plugin: if it's not,
*/
BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
g_module_error(), path);
- goto error;
+ BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
+ goto end;
}
goto end;
-error:
- BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
-
end:
- if (shared_lib_handle) {
+ BT_ASSERT(*shared_lib_handle || status != BT_PLUGIN_STATUS_OK);
+ if (*shared_lib_handle) {
BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
- path, shared_lib_handle);
+ path, *shared_lib_handle);
}
- return shared_lib_handle;
+ return status;
}
static
* 6. Freeze the plugin object.
*/
static
-enum bt_plugin_status bt_plugin_so_init(
- struct bt_plugin *plugin,
+enum bt_plugin_status bt_plugin_so_init(struct bt_plugin *plugin,
+ bool fail_on_load_error,
const struct __bt_plugin_descriptor *descriptor,
struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
struct __bt_plugin_descriptor_attribute const * const *attrs_end,
sizeof(struct comp_class_full_descriptor));
if (!comp_class_full_descriptors) {
BT_LOGE_STR("Failed to allocate a GArray.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
cur_attr->value.version.extra);
break;
default:
- /*
- * WARN-level logging because this should not
- * happen with the appropriate ABI version. If
- * we're here, we know that for the reported
- * version of the ABI, this attribute is
- * unknown.
- */
- BT_LOGW("Ignoring unknown plugin descriptor attribute: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "%s plugin descriptor attribute: "
"plugin-path=\"%s\", plugin-name=\"%s\", "
"attr-type-name=\"%s\", attr-type-id=%d",
+ fail_on_load_error ? "Unknown" :
+ "Ignoring unknown",
spec->shared_lib_handle->path ?
spec->shared_lib_handle->path->str :
NULL,
descriptor->name, cur_attr->type_name,
cur_attr->type);
+
+ if (fail_on_load_error) {
+ status = BT_PLUGIN_STATUS_LOADING_ERROR;
+ goto end;
+ }
+
break;
}
}
}
break;
default:
- /*
- * WARN-level logging because this
- * should not happen with the
- * appropriate ABI version. If we're
- * here, we know that for the reported
- * version of the ABI, this attribute is
- * unknown.
- */
- BT_LOGW("Ignoring unknown component class descriptor attribute: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "%s component class descriptor attribute: "
"plugin-path=\"%s\", "
"plugin-name=\"%s\", "
"comp-class-name=\"%s\", "
"comp-class-type=%s, "
"attr-type-name=\"%s\", "
"attr-type-id=%d",
+ fail_on_load_error ? "Unknown" :
+ "Ignoring unknown",
spec->shared_lib_handle->path ?
spec->shared_lib_handle->path->str :
NULL,
cur_cc_descr_attr->comp_class_descriptor->type),
cur_cc_descr_attr->type_name,
cur_cc_descr_attr->type);
+
+ if (fail_on_load_error) {
+ status = BT_PLUGIN_STATUS_LOADING_ERROR;
+ goto end;
+ }
+
break;
}
}
BT_LOGD_STR("Calling user's plugin initialization function.");
init_status = spec->init((void *) plugin);
- BT_LOGD("User function returned: %s",
+ BT_LOGD("User function returned: status=%s",
bt_self_plugin_status_string(init_status));
if (init_status < 0) {
- BT_LOGW_STR("User's plugin initialization function failed.");
- status = BT_PLUGIN_STATUS_ERROR;
- goto end;
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "User's plugin initialization function failed: "
+ "status=%s",
+ bt_self_plugin_status_string(init_status));
+
+ if (fail_on_load_error) {
+ status = (int) init_status;
+ goto end;
+ }
}
}
sink_comp_class);
break;
default:
- /*
- * WARN-level logging because this should not
- * happen with the appropriate ABI version. If
- * we're here, we know that for the reported
- * version of the ABI, this component class type
- * is unknown.
- */
- BT_LOGW("Ignoring unknown component class type: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "%s component class type: "
"plugin-path=\"%s\", plugin-name=\"%s\", "
"comp-class-name=\"%s\", comp-class-type=%d",
+ fail_on_load_error ? "Unknown" :
+ "Ignoring unknown",
spec->shared_lib_handle->path->str ?
spec->shared_lib_handle->path->str :
NULL,
descriptor->name,
cc_full_descr->descriptor->name,
cc_full_descr->descriptor->type);
+
+ if (fail_on_load_error) {
+ status = BT_PLUGIN_STATUS_LOADING_ERROR;
+ goto end;
+ }
+
continue;
}
if (!comp_class) {
BT_LOGE_STR("Cannot create component class.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
comp_class, cc_full_descr->description);
if (ret) {
BT_LOGE_STR("Cannot set component class's description.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(comp_class);
goto end;
}
cc_full_descr->help);
if (ret) {
BT_LOGE_STR("Cannot set component class's help string.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(comp_class);
goto end;
}
cc_full_descr->methods.source.init);
if (ret) {
BT_LOGE_STR("Cannot set source component class's initialization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.finalize);
if (ret) {
BT_LOGE_STR("Cannot set source component class's finalization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.query);
if (ret) {
BT_LOGE_STR("Cannot set source component class's query method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.output_port_connected);
if (ret) {
BT_LOGE_STR("Cannot set source component class's \"output port connected\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_init);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator initialization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_finalize);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator finalization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_seek_ns_from_origin);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator \"seek nanoseconds from origin\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_seek_beginning);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator \"seek beginning\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator \"can seek nanoseconds from origin\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.source.msg_iter_can_seek_beginning);
if (ret) {
BT_LOGE_STR("Cannot set source component class's message iterator \"can seek beginning\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
goto end;
}
cc_full_descr->methods.filter.init);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's initialization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.finalize);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's finalization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.query);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's query method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.input_port_connected);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's \"input port connected\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.output_port_connected);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's \"output port connected\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_init);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator initialization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_finalize);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator finalization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator \"seek nanoseconds from origin\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_seek_beginning);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator \"seek beginning\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek nanoseconds from origin\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.filter.msg_iter_can_seek_beginning);
if (ret) {
BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek beginning\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
goto end;
}
cc_full_descr->methods.sink.init);
if (ret) {
BT_LOGE_STR("Cannot set sink component class's initialization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
goto end;
}
cc_full_descr->methods.sink.finalize);
if (ret) {
BT_LOGE_STR("Cannot set sink component class's finalization method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
goto end;
}
cc_full_descr->methods.sink.query);
if (ret) {
BT_LOGE_STR("Cannot set sink component class's query method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
goto end;
}
cc_full_descr->methods.sink.input_port_connected);
if (ret) {
BT_LOGE_STR("Cannot set sink component class's \"input port connected\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
goto end;
}
cc_full_descr->methods.sink.graph_is_configured);
if (ret) {
BT_LOGE_STR("Cannot set sink component class's \"graph is configured\" method.");
- status = BT_PLUGIN_STATUS_ERROR;
+ status = BT_PLUGIN_STATUS_NOMEM;
BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
goto end;
}
}
static
-struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
+enum bt_plugin_status bt_plugin_so_create_all_from_sections(
struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
+ bool fail_on_load_error,
struct __bt_plugin_descriptor const * const *descriptors_begin,
struct __bt_plugin_descriptor const * const *descriptors_end,
struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
- struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
+ struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end,
+ struct bt_plugin_set **plugin_set_out)
{
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
size_t descriptor_count;
size_t attrs_count;
size_t cc_descriptors_count;
size_t cc_descr_attrs_count;
size_t i;
- struct bt_plugin_set *plugin_set = NULL;
+ BT_ASSERT(plugin_set_out);
+ *plugin_set_out = NULL;
descriptor_count = count_non_null_items_in_section(descriptors_begin, descriptors_end);
attrs_count = count_non_null_items_in_section(attrs_begin, attrs_end);
cc_descriptors_count = count_non_null_items_in_section(cc_descriptors_begin, cc_descriptors_end);
cc_descr_attrs_count = count_non_null_items_in_section(cc_descr_attrs_begin, cc_descr_attrs_end);
-
BT_LOGI("Creating all SO plugins from sections: "
"plugin-path=\"%s\", "
"descr-begin-addr=%p, descr-end-addr=%p, "
cc_descr_attrs_begin, cc_descr_attrs_end,
descriptor_count, attrs_count,
cc_descriptors_count, cc_descr_attrs_count);
- plugin_set = bt_plugin_set_create();
- if (!plugin_set) {
+ *plugin_set_out = bt_plugin_set_create();
+ if (!*plugin_set_out) {
BT_LOGE_STR("Cannot create empty plugin set.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto error;
}
descriptor->name, descriptor->major, descriptor->minor);
if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
- /*
- * INFO-level logging because we're only
- * _trying_ to open this file as a compatible
- * Babeltrace plugin: if it's not, it's not an
- * error. And because this can be tried during
- * bt_plugin_find_all_from_dir(), it's not even
- * a warning.
- */
- BT_LOGI("Unknown ABI major version: abi-major=%d",
- descriptor->major);
- goto error;
+ BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN :
+ BT_LOG_INFO, BT_LOG_TAG,
+ "Unknown ABI major version: abi-major=%d",
+ descriptor->major);
+
+ if (fail_on_load_error) {
+ status = BT_PLUGIN_STATUS_LOADING_ERROR;
+ goto error;
+ } else {
+ continue;
+ }
}
plugin = bt_plugin_so_create_empty(shared_lib_handle);
if (!plugin) {
BT_LOGE_STR("Cannot create empty shared library handle.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto error;
}
if (shared_lib_handle && shared_lib_handle->path) {
- bt_plugin_set_path(plugin, shared_lib_handle->path->str);
+ bt_plugin_set_path(plugin,
+ shared_lib_handle->path->str);
}
- status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
- attrs_end, cc_descriptors_begin, cc_descriptors_end,
+ status = bt_plugin_so_init(plugin, fail_on_load_error,
+ descriptor, attrs_begin, attrs_end,
+ cc_descriptors_begin, cc_descriptors_end,
cc_descr_attrs_begin, cc_descr_attrs_end);
- if (status < 0) {
+ if (status == BT_PLUGIN_STATUS_OK) {
+ /* Add to plugin set */
+ bt_plugin_set_add_plugin(*plugin_set_out, plugin);
+ BT_OBJECT_PUT_REF_AND_RESET(plugin);
+ } else if (status < 0) {
/*
- * DEBUG-level logging because we're only
- * _trying_ to open this file as a compatible
- * Babeltrace plugin: if it's not, it's not an
- * error. And because this can be tried during
- * bt_plugin_find_all_from_dir(), it's not
- * even a warning.
+ * bt_plugin_so_init() handles
+ * `fail_on_load_error`, so this is a "real"
+ * error.
*/
- BT_LOGD_STR("Cannot initialize SO plugin object from sections.");
+ BT_LOGW_STR("Cannot initialize SO plugin object from sections.");
BT_OBJECT_PUT_REF_AND_RESET(plugin);
goto error;
}
- /* Add to plugin set */
- bt_plugin_set_add_plugin(plugin_set, plugin);
- bt_object_put_ref(plugin);
+ BT_ASSERT(!plugin);
+ }
+
+ BT_ASSERT(*plugin_set_out);
+
+ if ((*plugin_set_out)->plugins->len == 0) {
+ BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
}
goto end;
error:
- BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
+ BT_ASSERT(status < 0);
+ BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
end:
- return plugin_set;
+ return status;
}
BT_HIDDEN
-struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
+enum bt_plugin_status bt_plugin_so_create_all_from_static(
+ bool fail_on_load_error,
+ struct bt_plugin_set **plugin_set_out)
{
- struct bt_plugin_set *plugin_set = NULL;
- struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
- bt_plugin_so_shared_lib_handle_create(NULL);
+ enum bt_plugin_status status;
+ struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
- if (!shared_lib_handle) {
+ BT_ASSERT(plugin_set_out);
+ *plugin_set_out = NULL;
+ status = bt_plugin_so_shared_lib_handle_create(NULL,
+ &shared_lib_handle);
+ if (status != BT_PLUGIN_STATUS_OK) {
+ BT_ASSERT(!shared_lib_handle);
goto end;
}
+ BT_ASSERT(shared_lib_handle);
BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
- plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
+ status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
+ fail_on_load_error,
__bt_get_begin_section_plugin_descriptors(),
__bt_get_end_section_plugin_descriptors(),
__bt_get_begin_section_plugin_descriptor_attributes(),
__bt_get_begin_section_component_class_descriptors(),
__bt_get_end_section_component_class_descriptors(),
__bt_get_begin_section_component_class_descriptor_attributes(),
- __bt_get_end_section_component_class_descriptor_attributes());
+ __bt_get_end_section_component_class_descriptor_attributes(),
+ plugin_set_out);
+ BT_ASSERT((status == BT_PLUGIN_STATUS_OK && *plugin_set_out &&
+ (*plugin_set_out)->plugins->len > 0) || !*plugin_set_out);
end:
BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
-
- return plugin_set;
+ return status;
}
BT_HIDDEN
-struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
+enum bt_plugin_status bt_plugin_so_create_all_from_file(const char *path,
+ bool fail_on_load_error, struct bt_plugin_set **plugin_set_out)
{
size_t path_len;
- struct bt_plugin_set *plugin_set = NULL;
+ enum bt_plugin_status status;
struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
BT_ASSERT(path);
+ BT_ASSERT(plugin_set_out);
+ *plugin_set_out = NULL;
path_len = strlen(path);
BT_ASSERT_PRE(path_len > PLUGIN_SUFFIX_LEN,
"Path length is too short: path-length=%zu, min-length=%zu",
NATIVE_PLUGIN_SUFFIX_LEN);
if (!is_shared_object && !is_libtool_wrapper) {
/* Name indicates this is not a plugin file; not an error */
- BT_LOGI("File is not a SO plugin file: path=\"%s\"", path);
+ BT_LOGI("File is not an SO plugin file: path=\"%s\"", path);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
- shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
- if (!shared_lib_handle) {
+ status = bt_plugin_so_shared_lib_handle_create(path,
+ &shared_lib_handle);
+ if (status != BT_PLUGIN_STATUS_OK) {
/* bt_plugin_so_shared_lib_handle_create() logs more details */
- BT_LOGD_STR("Cannot create shared library handle.");
+ BT_ASSERT(!shared_lib_handle);
+ BT_LOGE_STR("Cannot create shared library handle.");
goto end;
}
(gpointer *) &get_begin_section_plugin_descriptors)) {
descriptors_begin = get_begin_section_plugin_descriptors();
} else {
+ /*
+ * Use this first symbol to know whether or not this
+ * shared object _looks like_ a Babeltrace plugin. Since
+ * g_module_symbol() failed, assume that this is not a
+ * Babeltrace plugin, so it's not an error.
+ */
BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
"symbol=\"%s\"", path,
"__bt_get_begin_section_plugin_descriptors");
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
+ /*
+ * If g_module_symbol() fails for any of the other symbols, fail
+ * if `fail_on_load_error` is true.
+ */
if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptors",
(gpointer *) &get_end_section_plugin_descriptors)) {
descriptors_end = get_end_section_plugin_descriptors();
} else {
- BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
+ BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO,
+ BT_LOG_TAG,
+ "Cannot resolve plugin symbol: path=\"%s\", "
"symbol=\"%s\"", path,
"__bt_get_end_section_plugin_descriptors");
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
}
if ((!!attrs_begin - !!attrs_end) != 0) {
- BT_LOGI("Found section start or end symbol, but not both: "
+ BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO,
+ BT_LOG_TAG,
+ "Found section start or end symbol, but not both: "
"path=\"%s\", symbol-start=\"%s\", "
"symbol-end=\"%s\", symbol-start-addr=%p, "
"symbol-end-addr=%p",
path, "__bt_get_begin_section_plugin_descriptor_attributes",
"__bt_get_end_section_plugin_descriptor_attributes",
attrs_begin, attrs_end);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
}
if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
- BT_LOGI("Found section start or end symbol, but not both: "
+ BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO,
+ BT_LOG_TAG,
+ "Found section start or end symbol, but not both: "
"path=\"%s\", symbol-start=\"%s\", "
"symbol-end=\"%s\", symbol-start-addr=%p, "
"symbol-end-addr=%p",
path, "__bt_get_begin_section_component_class_descriptors",
"__bt_get_end_section_component_class_descriptors",
cc_descriptors_begin, cc_descriptors_end);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
}
if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
- BT_LOGI("Found section start or end symbol, but not both: "
+ BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO,
+ BT_LOG_TAG,
+ "Found section start or end symbol, but not both: "
"path=\"%s\", symbol-start=\"%s\", "
"symbol-end=\"%s\", symbol-start-addr=%p, "
"symbol-end-addr=%p",
path, "__bt_get_begin_section_component_class_descriptor_attributes",
"__bt_get_end_section_component_class_descriptor_attributes",
cc_descr_attrs_begin, cc_descr_attrs_end);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto end;
}
/* Initialize plugin */
BT_LOGD_STR("Initializing plugin object.");
- plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
+ status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
+ fail_on_load_error,
descriptors_begin, descriptors_end, attrs_begin, attrs_end,
cc_descriptors_begin, cc_descriptors_end,
- cc_descr_attrs_begin, cc_descr_attrs_end);
+ cc_descr_attrs_begin, cc_descr_attrs_end, plugin_set_out);
end:
BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
- return plugin_set;
+ return status;
}
static
};
BT_HIDDEN
-struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path);
+enum bt_plugin_status bt_plugin_so_create_all_from_file(const char *path,
+ bool fail_on_load_error, struct bt_plugin_set **plugin_set_out);
BT_HIDDEN
-struct bt_plugin_set *bt_plugin_so_create_all_from_static(void);
+enum bt_plugin_status bt_plugin_so_create_all_from_static(
+ bool fail_on_load_error,
+ struct bt_plugin_set **plugin_set_out);
void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
struct bt_component_class *comp_class);
#include <plugin/python-plugin-provider.h>
static
-struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path) =
+enum bt_plugin_status (*bt_plugin_python_create_all_from_file_sym)(
+ const char *path, bool fail_on_load_error,
+ struct bt_plugin_set **plugin_set_out) =
bt_plugin_python_create_all_from_file;
static
-void init_python_plugin_provider(void) {}
+void init_python_plugin_provider(void)
+{
+}
#else /* BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT */
static GModule *python_plugin_provider_module;
+
static
-struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path);
+enum bt_plugin_status (*bt_plugin_python_create_all_from_file_sym)(
+ const char *path, bool fail_on_load_error,
+ struct bt_plugin_set **plugin_set_out);
static
void init_python_plugin_provider(void) {
python_plugin_provider_module =
g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME, 0);
if (!python_plugin_provider_module) {
+ /*
+ * This is not an error. The whole point of having an
+ * external Python plugin provider is that it can be
+ * missing and the Babeltrace library still works.
+ */
BT_LOGI("Cannot open `%s`: %s: continuing without Python plugin support.",
PYTHON_PLUGIN_PROVIDER_FILENAME, g_module_error());
return;
if (!g_module_symbol(python_plugin_provider_module,
PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR,
(gpointer) &bt_plugin_python_create_all_from_file_sym)) {
- BT_LOGI("Cannot find the Python plugin provider loading symbol: continuing without Python plugin support: "
+ /*
+ * This is an error because, since we found the Python
+ * plugin provider shared object, we expect this symbol
+ * to exist.
+ */
+ BT_LOGE("Cannot find the Python plugin provider loading symbol: "
+ "%s: continuing without Python plugin support: "
"file=\"%s\", symbol=\"%s\"",
+ g_module_error(),
PYTHON_PLUGIN_PROVIDER_FILENAME,
PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR);
return;
return g_ptr_array_index(plugin_set->plugins, index);
}
-const struct bt_plugin_set *bt_plugin_find_all_from_static(void)
+enum bt_plugin_status bt_plugin_find_all_from_static(
+ bt_bool fail_on_load_error,
+ const struct bt_plugin_set **plugin_set_out)
{
/* bt_plugin_so_create_all_from_static() logs errors */
- return bt_plugin_so_create_all_from_static();
+ return bt_plugin_so_create_all_from_static(fail_on_load_error,
+ (void *) plugin_set_out);
}
-const struct bt_plugin_set *bt_plugin_find_all_from_file(const char *path)
+enum bt_plugin_status bt_plugin_find_all_from_file(const char *path,
+ bt_bool fail_on_load_error,
+ const struct bt_plugin_set **plugin_set_out)
{
- struct bt_plugin_set *plugin_set = NULL;
+ enum bt_plugin_status status;
BT_ASSERT_PRE_NON_NULL(path, "Path");
+ BT_ASSERT_PRE_NON_NULL(path, "Plugin set (output)");
BT_LOGI("Creating plugins from file: path=\"%s\"", path);
/* Try shared object plugins */
- plugin_set = bt_plugin_so_create_all_from_file(path);
- if (plugin_set) {
+ status = bt_plugin_so_create_all_from_file(path, fail_on_load_error,
+ (void *) plugin_set_out);
+ if (status == BT_PLUGIN_STATUS_OK) {
+ BT_ASSERT(*plugin_set_out);
+ BT_ASSERT((*plugin_set_out)->plugins->len > 0);
+ goto end;
+ } else if (status < 0) {
+ BT_ASSERT(!*plugin_set_out);
goto end;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_NOT_FOUND);
+ BT_ASSERT(!*plugin_set_out);
+
/* Try Python plugins if support is available */
init_python_plugin_provider();
if (bt_plugin_python_create_all_from_file_sym) {
- plugin_set = bt_plugin_python_create_all_from_file_sym(path);
- if (plugin_set) {
+ status = bt_plugin_python_create_all_from_file_sym(path,
+ fail_on_load_error, (void *) plugin_set_out);
+ if (status == BT_PLUGIN_STATUS_OK) {
+ BT_ASSERT(*plugin_set_out);
+ BT_ASSERT((*plugin_set_out)->plugins->len > 0);
+ goto end;
+ } else if (status < 0) {
+ BT_ASSERT(!*plugin_set_out);
goto end;
}
+
+ BT_ASSERT(status == BT_PLUGIN_STATUS_NOT_FOUND);
+ BT_ASSERT(!*plugin_set_out);
}
end:
- if (plugin_set) {
+ if (status == BT_PLUGIN_STATUS_OK) {
BT_LOGI("Created %u plugins from file: "
"path=\"%s\", count=%u, plugin-set-addr=%p",
- plugin_set->plugins->len, path,
- plugin_set->plugins->len, plugin_set);
- } else {
+ (*plugin_set_out)->plugins->len, path,
+ (*plugin_set_out)->plugins->len,
+ *plugin_set_out);
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
BT_LOGI("Found no plugins in file: path=\"%s\"", path);
}
- return plugin_set;
+ return status;
}
static void destroy_gstring(void *data)
g_string_free(data, TRUE);
}
-const struct bt_plugin *bt_plugin_find(const char *plugin_name)
+enum bt_plugin_status bt_plugin_find(const char *plugin_name,
+ bt_bool fail_on_load_error, const struct bt_plugin **plugin_out)
{
const char *system_plugin_dir;
char *home_plugin_dir = NULL;
const struct bt_plugin_set *plugin_set = NULL;
GPtrArray *dirs = NULL;
int ret;
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
size_t i, j;
BT_ASSERT_PRE_NON_NULL(plugin_name, "Name");
+ BT_ASSERT_PRE_NON_NULL(plugin_out, "Plugin (output)");
BT_LOGI("Finding named plugin in standard directories and built-in plugins: "
"name=\"%s\"", plugin_name);
dirs = g_ptr_array_new_with_free_func((GDestroyNotify) destroy_gstring);
if (!dirs) {
BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
ret = bt_common_append_plugin_path_dirs(envvar, dirs);
if (ret) {
BT_LOGE_STR("Failed to append plugin path to array of directories.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
}
home_plugin_dir = bt_common_get_home_plugin_path(BT_LOG_OUTPUT_LEVEL);
if (home_plugin_dir) {
- GString *home_plugin_dir_str =
- g_string_new(home_plugin_dir);
+ GString *home_plugin_dir_str = g_string_new(home_plugin_dir);
if (!home_plugin_dir_str) {
BT_LOGE_STR("Failed to allocate a GString.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
if (!system_plugin_dir_str) {
BT_LOGE_STR("Failed to allocate a GString.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto end;
}
}
/* bt_plugin_find_all_from_dir() logs details/errors */
- plugin_set = bt_plugin_find_all_from_dir(dir->str, BT_FALSE);
- if (!plugin_set) {
+ status = bt_plugin_find_all_from_dir(dir->str, BT_FALSE,
+ fail_on_load_error, &plugin_set);
+ if (status < 0) {
+ BT_ASSERT(!plugin_set);
+ goto end;
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ BT_ASSERT(!plugin_set);
BT_LOGI("No plugins found in directory: path=\"%s\"",
dir->str);
continue;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+ BT_ASSERT(plugin_set);
+
for (j = 0; j < plugin_set->plugins->len; j++) {
const struct bt_plugin *candidate_plugin =
g_ptr_array_index(plugin_set->plugins, j);
plugin_name) == 0) {
BT_LOGI("Plugin found in directory: name=\"%s\", path=\"%s\"",
plugin_name, dir->str);
- plugin = candidate_plugin;
- bt_object_get_no_null_check(plugin);
+ *plugin_out = candidate_plugin;
+ bt_object_get_no_null_check(*plugin_out);
goto end;
}
}
plugin_name, dir->str);
}
- bt_object_put_ref(plugin_set);
- plugin_set = bt_plugin_find_all_from_static();
- if (plugin_set) {
- for (j = 0; j < plugin_set->plugins->len; j++) {
- const struct bt_plugin *candidate_plugin =
- g_ptr_array_index(plugin_set->plugins, j);
+ BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
+ status = bt_plugin_find_all_from_static(fail_on_load_error,
+ &plugin_set);
+ if (status < 0) {
+ BT_ASSERT(!plugin_set);
+ goto end;
+ }
- if (strcmp(bt_plugin_get_name(candidate_plugin),
- plugin_name) == 0) {
- BT_LOGI("Plugin found in built-in plugins: "
- "name=\"%s\"", plugin_name);
- plugin = candidate_plugin;
- bt_object_get_no_null_check(plugin);
- goto end;
- }
+ if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ BT_ASSERT(!plugin_set);
+ BT_LOGI_STR("No plugins found in built-in plugins.");
+ goto end;
+ }
+
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+ BT_ASSERT(plugin_set);
+
+ for (j = 0; j < plugin_set->plugins->len; j++) {
+ const struct bt_plugin *candidate_plugin =
+ g_ptr_array_index(plugin_set->plugins, j);
+
+ if (strcmp(bt_plugin_get_name(candidate_plugin),
+ plugin_name) == 0) {
+ BT_LOGI("Plugin found in built-in plugins: "
+ "name=\"%s\"", plugin_name);
+ *plugin_out = candidate_plugin;
+ bt_object_get_no_null_check(*plugin_out);
+ goto end;
}
}
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
+
end:
free(home_plugin_dir);
bt_object_put_ref(plugin_set);
g_ptr_array_free(dirs, TRUE);
}
- if (plugin) {
+ if (status == BT_PLUGIN_STATUS_OK) {
BT_LIB_LOGI("Found plugin in standard directories and built-in plugins: "
"%!+l", plugin);
- } else {
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
BT_LOGI("No plugin found in standard directories and built-in plugins: "
"name=\"%s\"", plugin_name);
}
- return plugin;
+ return status;
}
static struct {
pthread_mutex_t lock;
struct bt_plugin_set *plugin_set;
bool recurse;
+ bool fail_on_load_error;
+ enum bt_plugin_status status;
} append_all_from_dir_info = {
.lock = PTHREAD_MUTEX_INITIALIZER
};
static
-int nftw_append_all_from_dir(const char *file, const struct stat *sb, int flag,
- struct FTW *s)
+int nftw_append_all_from_dir(const char *file,
+ const struct stat *sb, int flag, struct FTW *s)
{
int ret = 0;
const char *name = file + s->base;
switch (flag) {
case FTW_F:
{
- const struct bt_plugin_set *plugins_from_file;
+ const struct bt_plugin_set *plugins_from_file = NULL;
if (name[0] == '.') {
/* Skip hidden files */
goto end;
}
- plugins_from_file = bt_plugin_find_all_from_file(file);
-
- if (plugins_from_file) {
+ append_all_from_dir_info.status =
+ bt_plugin_find_all_from_file(file,
+ append_all_from_dir_info.fail_on_load_error,
+ &plugins_from_file);
+ if (append_all_from_dir_info.status == BT_PLUGIN_STATUS_OK) {
size_t j;
+ BT_ASSERT(plugins_from_file);
+
for (j = 0; j < plugins_from_file->plugins->len; j++) {
struct bt_plugin *plugin =
g_ptr_array_index(plugins_from_file->plugins, j);
}
bt_object_put_ref(plugins_from_file);
+ goto end;
+ } else if (append_all_from_dir_info.status < 0) {
+ /* bt_plugin_find_all_from_file() logs errors */
+ BT_ASSERT(!plugins_from_file);
+ ret = -1;
+ goto end;
}
+
+ /*
+ * Not found in this file: this is no an error; continue
+ * walking the directories.
+ */
+ BT_ASSERT(!plugins_from_file);
+ BT_ASSERT(append_all_from_dir_info.status ==
+ BT_PLUGIN_STATUS_NOT_FOUND);
break;
}
case FTW_DNR:
/* Continue to next file / directory. */
- BT_LOGW("Cannot enter directory: continuing: path=\"%s\"", file);
+ BT_LOGI("Cannot enter directory: continuing: path=\"%s\"", file);
break;
case FTW_NS:
/* Continue to next file / directory. */
static
enum bt_plugin_status bt_plugin_create_append_all_from_dir(
struct bt_plugin_set *plugin_set, const char *path,
- bt_bool recurse)
+ bt_bool recurse, bt_bool fail_on_load_error)
{
int nftw_flags = FTW_PHYS;
- enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK;
+ int ret;
+ enum bt_plugin_status status;
BT_ASSERT(plugin_set);
BT_ASSERT(path);
pthread_mutex_lock(&append_all_from_dir_info.lock);
append_all_from_dir_info.plugin_set = plugin_set;
append_all_from_dir_info.recurse = recurse;
+ append_all_from_dir_info.status = BT_PLUGIN_STATUS_OK;
+ append_all_from_dir_info.fail_on_load_error = fail_on_load_error;
ret = nftw(path, nftw_append_all_from_dir,
APPEND_ALL_FROM_DIR_NFDOPEN_MAX, nftw_flags);
+ append_all_from_dir_info.plugin_set = NULL;
+ status = append_all_from_dir_info.status;
pthread_mutex_unlock(&append_all_from_dir_info.lock);
- if (ret != 0) {
- BT_LOGW_ERRNO("Cannot open directory", ": path=\"%s\"", path);
- ret = BT_PLUGIN_STATUS_ERROR;
+ if (ret) {
+ BT_LOGW_ERRNO("Failed to walk directory",
+ ": path=\"%s\", recurse=%d",
+ path, recurse);
+ status = BT_PLUGIN_STATUS_ERROR;
+ goto end;
+ }
+
+ if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ /*
+ * We're just appending in this function; even if
+ * nothing was found, it's still okay from the caller's
+ * perspective.
+ */
+ status = BT_PLUGIN_STATUS_OK;
}
+end:
return ret;
}
-const struct bt_plugin_set *bt_plugin_find_all_from_dir(const char *path,
- bt_bool recurse)
+enum bt_plugin_status bt_plugin_find_all_from_dir(const char *path,
+ bt_bool recurse, bt_bool fail_on_load_error,
+ const struct bt_plugin_set **plugin_set_out)
{
- struct bt_plugin_set *plugin_set;
- enum bt_plugin_status status;
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
+ BT_ASSERT_PRE_NON_NULL(plugin_set_out, "Plugin set (output)");
BT_LOGI("Creating all plugins in directory: path=\"%s\", recurse=%d",
path, recurse);
- plugin_set = bt_plugin_set_create();
- if (!plugin_set) {
+ *plugin_set_out = bt_plugin_set_create();
+ if (!*plugin_set_out) {
BT_LOGE_STR("Cannot create empty plugin set.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto error;
}
- /* Append found plugins to array */
- status = bt_plugin_create_append_all_from_dir(plugin_set, path,
- recurse);
+ /*
+ * Append found plugins to array (never returns
+ * `BT_PLUGIN_STATUS_NOT_FOUND`)
+ */
+ status = bt_plugin_create_append_all_from_dir((void *) *plugin_set_out,
+ path, recurse, fail_on_load_error);
if (status < 0) {
+ /*
+ * bt_plugin_create_append_all_from_dir() handles
+ * `fail_on_load_error`, so this is a "real" error.
+ */
BT_LOGW("Cannot append plugins found in directory: "
"path=\"%s\", status=%s",
path, bt_plugin_status_string(status));
goto error;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+
+ if ((*plugin_set_out)->plugins->len == 0) {
+ /* Nothing was appended: not found */
+ BT_LOGI("No plugins found in directory: path=\"%s\"", path);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
+ goto error;
+ }
+
BT_LOGI("Created %u plugins from directory: count=%u, path=\"%s\"",
- plugin_set->plugins->len, plugin_set->plugins->len, path);
+ (*plugin_set_out)->plugins->len,
+ (*plugin_set_out)->plugins->len, path);
goto end;
error:
- BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
+ BT_ASSERT(status != BT_PLUGIN_STATUS_OK);
+ BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
end:
- return plugin_set;
+ return status;
}
const char *bt_plugin_get_name(const struct bt_plugin *plugin)
BT_PLUGIN_TYPE_PYTHON = 1,
};
-enum bt_plugin_status {
- BT_PLUGIN_STATUS_OK = 0,
- BT_PLUGIN_STATUS_ERROR = -1,
- BT_PLUGIN_STATUS_NOMEM = -12,
-};
-
struct bt_plugin {
struct bt_object base;
enum bt_plugin_type type;
switch (status) {
case BT_PLUGIN_STATUS_OK:
return "BT_PLUGIN_STATUS_OK";
+ case BT_PLUGIN_STATUS_NOT_FOUND:
+ return "BT_PLUGIN_STATUS_NOT_FOUND";
case BT_PLUGIN_STATUS_ERROR:
return "BT_PLUGIN_STATUS_ERROR";
+ case BT_PLUGIN_STATUS_LOADING_ERROR:
+ return "BT_PLUGIN_STATUS_LOADING_ERROR";
case BT_PLUGIN_STATUS_NOMEM:
return "BT_PLUGIN_STATUS_NOMEM";
default:
/* init_python() called once without success */
PYTHON_STATE_CANNOT_INITIALIZE,
+
+ /*
+ * init_python() called, but environment variable asks the
+ * Python interpreter not to be loaded.
+ */
+ PYTHON_STATE_WONT_INITIALIZE,
} python_state = PYTHON_STATE_NOT_INITED;
static PyObject *py_try_load_plugin_module_func = NULL;
static bool python_was_initialized_by_us;
static
-void print_python_traceback_warn(void)
+void print_python_traceback(int log_level)
{
- if (BT_LOG_ON_WARN && Py_IsInitialized() && PyErr_Occurred()) {
- BT_LOGW_STR("Exception occured: traceback: ");
+ if (BT_LOG_ON(log_level) && Py_IsInitialized() && PyErr_Occurred()) {
+ BT_LOG_WRITE(log_level, BT_LOG_TAG,
+ "Exception occured: Python traceback: ");
PyErr_Print();
}
}
dis_python_env = getenv("BABELTRACE_DISABLE_PYTHON_PLUGINS");
if (dis_python_env && strcmp(dis_python_env, "1") == 0) {
BT_LOGI_STR("Python plugin support is disabled because `BABELTRACE_DISABLE_PYTHON_PLUGINS=1`.");
- python_state = PYTHON_STATE_CANNOT_INITIALIZE;
+ python_state = PYTHON_STATE_WONT_INITIALIZE;
goto end;
}
py_bt2_py_plugin_mod = PyImport_ImportModule("bt2.py_plugin");
if (!py_bt2_py_plugin_mod) {
- BT_LOGI_STR("Cannot import bt2.py_plugin Python module: Python plugin support is disabled.");
+ BT_LOGW_STR("Cannot import bt2.py_plugin Python module: Python plugin support is disabled.");
python_state = PYTHON_STATE_CANNOT_INITIALIZE;
goto end;
}
py_try_load_plugin_module_func =
PyObject_GetAttrString(py_bt2_py_plugin_mod, "_try_load_plugin_module");
if (!py_try_load_plugin_module_func) {
- BT_LOGI_STR("Cannot get _try_load_plugin_module attribute from bt2.py_plugin Python module: Python plugin support is disabled.");
+ BT_LOGW_STR("Cannot get _try_load_plugin_module attribute from bt2.py_plugin Python module: Python plugin support is disabled.");
python_state = PYTHON_STATE_CANNOT_INITIALIZE;
goto end;
}
}
#endif
- print_python_traceback_warn();
+ print_python_traceback(BT_LOG_WARN);
pyerr_clear();
Py_XDECREF(py_bt2_py_plugin_mod);
return;
}
static
-bt_plugin *bt_plugin_from_python_plugin_info(PyObject *plugin_info)
+enum bt_plugin_status bt_plugin_from_python_plugin_info(PyObject *plugin_info,
+ bool fail_on_load_error, bt_plugin **plugin_out)
{
- bt_plugin *plugin = NULL;
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
PyObject *py_name = NULL;
PyObject *py_author = NULL;
PyObject *py_description = NULL;
const char *license = NULL;
unsigned int major = 0, minor = 0, patch = 0;
const char *version_extra = NULL;
- int ret;
+ BT_ASSERT(plugin_out);
+ *plugin_out = NULL;
BT_ASSERT(plugin_info);
BT_ASSERT(python_state == PYTHON_STATE_FULLY_INITIALIZED);
py_name = PyObject_GetAttrString(plugin_info, "name");
if (!py_name) {
- BT_LOGW("Cannot find `name` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `name` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
py_author = PyObject_GetAttrString(plugin_info, "author");
if (!py_author) {
- BT_LOGW("Cannot find `author` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `author` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
py_description = PyObject_GetAttrString(plugin_info, "description");
if (!py_description) {
- BT_LOGW("Cannot find `desciption` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `desciption` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
py_license = PyObject_GetAttrString(plugin_info, "license");
if (!py_license) {
- BT_LOGW("Cannot find `license` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `license` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
py_version = PyObject_GetAttrString(plugin_info, "version");
if (!py_version) {
- BT_LOGW("Cannot find `version` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `version` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
py_comp_class_addrs = PyObject_GetAttrString(plugin_info,
"comp_class_addrs");
if (!py_comp_class_addrs) {
- BT_LOGW("Cannot find `comp_class_addrs` attribute in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot find `comp_class_addrs` attribute in Python plugin info object: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
if (PyUnicode_Check(py_name)) {
name = PyUnicode_AsUTF8(py_name);
if (!name) {
- BT_LOGW("Cannot decode Python plugin name string: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot decode Python plugin name string: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
} else {
/* Plugin name is mandatory */
- BT_LOGW("Plugin name is not a string: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Plugin name is not a string: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
if (PyUnicode_Check(py_author)) {
author = PyUnicode_AsUTF8(py_author);
if (!author) {
- BT_LOGW("Cannot decode Python plugin author string: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot decode Python plugin author string: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
}
if (PyUnicode_Check(py_description)) {
description = PyUnicode_AsUTF8(py_description);
if (!description) {
- BT_LOGW("Cannot decode Python plugin description string: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot decode Python plugin description string: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
}
if (PyUnicode_Check(py_license)) {
license = PyUnicode_AsUTF8(py_license);
if (!license) {
- BT_LOGW("Cannot decode Python plugin license string: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot decode Python plugin license string: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
}
if (PyErr_Occurred()) {
/* Overflow error, most probably */
- BT_LOGW("Invalid Python plugin version format: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Invalid Python plugin version format: "
"py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
}
if (PyUnicode_Check(py_extra)) {
version_extra = PyUnicode_AsUTF8(py_extra);
if (!version_extra) {
- BT_LOGW("Cannot decode Python plugin version's extra string: "
- "py-plugin-info-addr=%p", plugin_info);
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot decode Python plugin version's extra string: "
+ "py-plugin-info-addr=%p", plugin_info);
+ status = fail_on_load_error ?
+ BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
}
}
}
- plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_PYTHON);
- if (!plugin) {
+ *plugin_out = bt_plugin_create_empty(BT_PLUGIN_TYPE_PYTHON);
+ if (!*plugin_out) {
BT_LOGE_STR("Cannot create empty plugin object.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto error;
}
- bt_plugin_set_name(plugin, name);
+ bt_plugin_set_name(*plugin_out, name);
if (description) {
- bt_plugin_set_description(plugin, description);
+ bt_plugin_set_description(*plugin_out, description);
}
if (author) {
- bt_plugin_set_author(plugin, author);
+ bt_plugin_set_author(*plugin_out, author);
}
if (license) {
- bt_plugin_set_license(plugin, license);
+ bt_plugin_set_license(*plugin_out, license);
}
- bt_plugin_set_version(plugin, major, minor, patch, version_extra);
+ bt_plugin_set_version(*plugin_out, major, minor, patch, version_extra);
if (PyList_Check(py_comp_class_addrs)) {
size_t i;
if (PyLong_Check(py_comp_class_addr)) {
comp_class = PyLong_AsVoidPtr(py_comp_class_addr);
} else {
- BT_LOGW("Component class address is not an integer in Python plugin info object: "
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Component class address is not an integer in Python plugin info object: "
"py-plugin-info-addr=%p, index=%zu",
plugin_info, i);
+
+ if (fail_on_load_error) {
+ status = BT_PLUGIN_STATUS_LOADING_ERROR;
+ goto error;
+ }
+
continue;
}
- ret = bt_plugin_add_component_class(plugin, comp_class);
- if (ret < 0) {
+ status = bt_plugin_add_component_class(*plugin_out,
+ comp_class);
+ if (status < 0) {
BT_LOGE("Cannot add component class to plugin: "
"py-plugin-info-addr=%p, "
"plugin-addr=%p, plugin-name=\"%s\", "
"comp-class-addr=%p, "
"comp-class-name=\"%s\", "
"comp-class-type=%s",
- plugin_info,
- plugin, bt_plugin_get_name(plugin),
+ plugin_info, *plugin_out,
+ bt_plugin_get_name(*plugin_out),
comp_class,
bt_component_class_get_name(comp_class),
bt_component_class_type_string(
bt_component_class_get_type(comp_class)));
- continue;
+ goto error;
}
}
}
goto end;
error:
- print_python_traceback_warn();
+ BT_ASSERT(status != BT_PLUGIN_STATUS_OK);
+ print_python_traceback(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO);
pyerr_clear();
- BT_OBJECT_PUT_REF_AND_RESET(plugin);
+ BT_OBJECT_PUT_REF_AND_RESET(*plugin_out);
end:
Py_XDECREF(py_name);
Py_XDECREF(py_license);
Py_XDECREF(py_version);
Py_XDECREF(py_comp_class_addrs);
- return plugin;
+ return status;
}
G_MODULE_EXPORT
-bt_plugin_set *bt_plugin_python_create_all_from_file(const char *path)
+enum bt_plugin_status bt_plugin_python_create_all_from_file(const char *path,
+ bool fail_on_load_error, struct bt_plugin_set **plugin_set_out)
{
- bt_plugin_set *plugin_set = NULL;
bt_plugin *plugin = NULL;
PyObject *py_plugin_info = NULL;
gchar *basename = NULL;
size_t path_len;
+ enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
BT_ASSERT(path);
* here because we already know Python cannot be fully
* initialized.
*/
+ status = BT_PLUGIN_STATUS_ERROR;
+ goto error;
+ } else if (python_state == PYTHON_STATE_WONT_INITIALIZE) {
+ /*
+ * This is not an error: the environment requires that
+ * Python plugins are disabled, so it's simply not
+ * found.
+ */
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
PYTHON_PLUGIN_FILE_EXT,
PYTHON_PLUGIN_FILE_EXT_LEN) != 0) {
BT_LOGI("Skipping non-Python file: path=\"%s\"", path);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
/* File name starts with `bt_plugin_` */
basename = g_path_get_basename(path);
if (!basename) {
- BT_LOGW("Cannot get path's basename: path=\"%s\"", path);
+ BT_LOGE("Cannot get path's basename: path=\"%s\"", path);
+ status = BT_PLUGIN_STATUS_ERROR;
goto error;
}
PYTHON_PLUGIN_FILE_PREFIX_LEN) != 0) {
BT_LOGI("Skipping Python file not starting with `%s`: "
"path=\"%s\"", PYTHON_PLUGIN_FILE_PREFIX, path);
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
* this waiting time everytime you load the library.
*/
init_python();
- if (python_state != PYTHON_STATE_FULLY_INITIALIZED) {
+ if (python_state == PYTHON_STATE_WONT_INITIALIZE) {
+ /*
+ * This is not an error: the environment requires that
+ * Python plugins are disabled, so it's simply not
+ * found.
+ */
+ status = BT_PLUGIN_STATUS_NOT_FOUND;
+ goto error;
+ } else if (python_state != PYTHON_STATE_FULLY_INITIALIZED) {
/*
* For some reason we cannot initialize Python,
* import the required modules, and get the required
* attributes from them.
*/
- BT_LOGI("Failed to initialize Python interpreter.");
+ BT_LOGE("Failed to initialize Python interpreter.");
+ status = BT_PLUGIN_STATUS_ERROR;
goto error;
}
py_plugin_info = PyObject_CallFunction(py_try_load_plugin_module_func,
"(s)", path);
if (!py_plugin_info || py_plugin_info == Py_None) {
- BT_LOGW("Cannot load Python plugin: path=\"%s\"", path);
- print_python_traceback_warn();
+ BT_LOG_WRITE(fail_on_load_error ?
+ BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG,
+ "Cannot load Python plugin: path=\"%s\"", path);
+ print_python_traceback(fail_on_load_error ? BT_LOG_WARN :
+ BT_LOG_INFO);
PyErr_Clear();
+ status = fail_on_load_error ? BT_PLUGIN_STATUS_LOADING_ERROR :
+ BT_PLUGIN_STATUS_NOT_FOUND;
goto error;
}
/*
* Get bt_plugin from plugin info object.
*/
- plugin = bt_plugin_from_python_plugin_info(py_plugin_info);
- if (!plugin) {
+ plugin = NULL;
+ status = bt_plugin_from_python_plugin_info(py_plugin_info,
+ fail_on_load_error, &plugin);
+ if (status < 0) {
+ /*
+ * bt_plugin_from_python_plugin_info() handles
+ * `fail_on_load_error`, so this is a "real" error.
+ */
BT_LOGW("Cannot create plugin object from Python plugin info object: "
"path=\"%s\", py-plugin-info-addr=%p",
path, py_plugin_info);
+ BT_ASSERT(!plugin);
+ goto error;
+ } else if (status == BT_PLUGIN_STATUS_NOT_FOUND) {
+ BT_ASSERT(!plugin);
goto error;
}
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK);
+ BT_ASSERT(plugin);
bt_plugin_set_path(plugin, path);
- plugin_set = bt_plugin_set_create();
- if (!plugin_set) {
+ *plugin_set_out = bt_plugin_set_create();
+ if (!*plugin_set_out) {
BT_LOGE_STR("Cannot create empty plugin set.");
+ status = BT_PLUGIN_STATUS_NOMEM;
goto error;
}
- bt_plugin_set_add_plugin(plugin_set, plugin);
+ bt_plugin_set_add_plugin(*plugin_set_out, plugin);
BT_LOGD("Created all Python plugins from file: path=\"%s\", "
"plugin-addr=%p, plugin-name=\"%s\"",
path, plugin, bt_plugin_get_name(plugin));
goto end;
error:
- BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
+ BT_ASSERT(status != BT_PLUGIN_STATUS_OK);
+ BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
end:
bt_plugin_put_ref(plugin);
Py_XDECREF(py_plugin_info);
g_free(basename);
- return plugin_set;
+ return status;
}
#include <babeltrace2/plugin/plugin-const.h>
extern
-struct bt_plugin_set *bt_plugin_python_create_all_from_file(const char *path);
+enum bt_plugin_status bt_plugin_python_create_all_from_file(const char *path,
+ struct bt_plugin_set **plugin_set_out);
#endif /* BABELTRACE_PLUGIN_PYTHON_PLUGIN_PROVIDER_INTERNAL_H */
class FindPluginsTestCase(unittest.TestCase):
- def test_find_none(self):
- pset = bt2.find_plugins('/this/does/not/exist/246703df-cb85-46d5-8406-5e8dc4a88b41')
- self.assertIsNone(pset)
+ def test_find_nonexistent_dir(self):
+ with self.assertRaises(bt2.Error):
+ bt2.find_plugins('/this/does/not/exist/246703df-cb85-46d5-8406-5e8dc4a88b41')
+
+ def test_find_none_existing_dir(self):
+ plugins = bt2.find_plugins(_TEST_PLUGIN_PLUGINS_PATH, recurse=False)
+ self.assertIsNone(plugins)
def test_find_dir(self):
pset = bt2.find_plugins(_TEST_PLUGIN_PLUGINS_PATH)
#include "tap/tap.h"
#include "common.h"
-#define NR_TESTS 35
+#define NR_TESTS 38
#define NON_EXISTING_PATH "/this/hopefully/does/not/exist/5bc75f8d-0dba-4043-a509-d7984b97e42b.so"
/* Those symbols are written to by some test plugins */
static void test_minimal(const char *plugin_dir)
{
- const bt_plugin_set *plugin_set;
+ const bt_plugin_set *plugin_set = NULL;
const bt_plugin *plugin;
char *minimal_path = get_test_plugin_path(plugin_dir, "minimal");
+ bt_plugin_status status;
BT_ASSERT(minimal_path);
diag("minimal plugin test below");
reset_test_plugin_env_vars();
- plugin_set = bt_plugin_find_all_from_file(minimal_path);
- ok(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1,
+ status = bt_plugin_find_all_from_file(minimal_path, BT_FALSE,
+ &plugin_set);
+ ok(status == BT_PLUGIN_STATUS_OK,
"bt_plugin_find_all_from_file() succeeds with a valid file");
+ ok(plugin_set,
+ "bt_plugin_find_all_from_file() returns a plugin set");
ok(check_env_var("BT_TEST_PLUGIN_INIT_CALLED") == 1,
"plugin's initialization function is called during bt_plugin_find_all_from_file()");
ok(bt_plugin_set_get_plugin_count(plugin_set) == 1,
static void test_sfs(const char *plugin_dir)
{
- const bt_plugin_set *plugin_set;
+ const bt_plugin_set *plugin_set = NULL;
const bt_plugin *plugin;
const bt_component_class_sink *sink_comp_class;
const bt_component_class_source *source_comp_class;
bt_graph_status graph_ret;
bt_query_executor *query_exec = bt_query_executor_create();
int ret;
+ bt_plugin_status status;
BT_ASSERT(query_exec);
BT_ASSERT(sfs_path);
diag("sfs plugin test below");
- plugin_set = bt_plugin_find_all_from_file(sfs_path);
- BT_ASSERT(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1);
+ status = bt_plugin_find_all_from_file(sfs_path, BT_FALSE, &plugin_set);
+ BT_ASSERT(status == BT_PLUGIN_STATUS_OK && plugin_set &&
+ bt_plugin_set_get_plugin_count(plugin_set) == 1);
plugin = bt_plugin_set_borrow_plugin_by_index_const(plugin_set, 0);
ok(bt_plugin_get_version(plugin, &major, &minor, &patch, &extra) ==
BT_PROPERTY_AVAILABILITY_AVAILABLE,
static void test_create_all_from_dir(const char *plugin_dir)
{
const bt_plugin_set *plugin_set;
+ bt_plugin_status status;
diag("create from all test below");
- plugin_set = bt_plugin_find_all_from_dir(NON_EXISTING_PATH, BT_FALSE);
- ok(!plugin_set,
+ status = bt_plugin_find_all_from_dir(NON_EXISTING_PATH, BT_FALSE,
+ BT_FALSE, &plugin_set);
+ ok(status == BT_PLUGIN_STATUS_ERROR,
"bt_plugin_find_all_from_dir() fails with an invalid path");
- plugin_set = bt_plugin_find_all_from_dir(plugin_dir, BT_FALSE);
- ok(plugin_set, "bt_plugin_find_all_from_dir() succeeds with a valid path");
+ plugin_set = NULL;
+ status = bt_plugin_find_all_from_dir(plugin_dir, BT_FALSE, BT_FALSE,
+ &plugin_set);
+ ok(status == BT_PLUGIN_STATUS_OK,
+ "bt_plugin_find_all_from_dir() succeeds with a valid path");
+ ok(plugin_set,
+ "bt_plugin_find_all_from_dir() returns a plugin set with a valid path");
/* 2 or 4, if `.la` files are considered or not */
ok(bt_plugin_set_get_plugin_count(plugin_set) == 2 ||
int ret;
const bt_plugin *plugin;
char *plugin_path;
+ bt_plugin_status status;
- ok(!bt_plugin_find(NON_EXISTING_PATH),
- "bt_plugin_find() returns NULL with an unknown plugin name");
+ ok(bt_plugin_find(NON_EXISTING_PATH, BT_FALSE, &plugin) ==
+ BT_PLUGIN_STATUS_NOT_FOUND,
+ "bt_plugin_find() returns BT_PLUGIN_STATUS_NOT_FOUND with an unknown plugin name");
ret = asprintf(&plugin_path, "%s" G_SEARCHPATH_SEPARATOR_S
G_DIR_SEPARATOR_S "ec1d09e5-696c-442e-b1c3-f9c6cf7f5958"
G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S
NON_EXISTING_PATH, plugin_dir);
BT_ASSERT(ret > 0 && plugin_path);
g_setenv("BABELTRACE_PLUGIN_PATH", plugin_path, 1);
- plugin = bt_plugin_find("test_minimal");
- ok(plugin,
+ plugin = NULL;
+ status = bt_plugin_find("test_minimal", BT_FALSE, &plugin);
+ ok(status == BT_PLUGIN_STATUS_OK,
"bt_plugin_find() succeeds with a plugin name it can find");
+ ok(plugin, "bt_plugin_find() returns a plugin object");
ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
"bt_plugin_find() finds the correct plugin for a given name");
BT_PLUGIN_PUT_REF_AND_RESET(plugin);