/*
+ * SPDX-License-Identifier: MIT
+ *
* Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
* Copyright 2015 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.
*/
-#define BT_LOG_TAG "COMP"
-#include "lib/lib-logging.h"
+#define BT_LOG_TAG "LIB/COMPONENT"
+#include "lib/logging.h"
+#include "common/common.h"
#include "common/assert.h"
-#include "lib/assert-pre.h"
+#include "lib/assert-cond.h"
#include <babeltrace2/graph/self-component.h>
-#include <babeltrace2/graph/component-const.h>
-#include <babeltrace2/graph/component-source-const.h>
-#include <babeltrace2/graph/component-filter-const.h>
-#include <babeltrace2/graph/component-sink-const.h>
+#include <babeltrace2/graph/component.h>
+#include <babeltrace2/graph/graph.h>
#include "common/macros.h"
#include "compat/compiler.h"
#include <babeltrace2/types.h>
#include "graph.h"
#include "message/iterator.h"
#include "port.h"
+#include "lib/func-status.h"
static
struct bt_component * (* const component_create_funcs[])(
void finalize_component(struct bt_component *comp)
{
typedef void (*method_t)(void *);
+ const char *method_name;
method_t method = NULL;
struct bt_component_class_source *src_cc = (void *) comp->class;
method = (method_t) src_cc->methods.finalize;
+ method_name = "bt_component_class_source_finalize_method";
break;
}
case BT_COMPONENT_CLASS_TYPE_FILTER:
struct bt_component_class_filter *flt_cc = (void *) comp->class;
method = (method_t) flt_cc->methods.finalize;
+ method_name = "bt_component_class_filter_finalize_method";
break;
}
case BT_COMPONENT_CLASS_TYPE_SINK:
struct bt_component_class_sink *sink_cc = (void *) comp->class;
method = (method_t) sink_cc->methods.finalize;
+ method_name = "bt_component_class_sink_finalize_method";
break;
}
default:
- abort();
+ bt_common_abort();
}
if (method) {
- BT_LIB_LOGD("Calling user's finalization method: "
+ const struct bt_error *saved_error;
+
+ saved_error = bt_current_thread_take_error();
+
+ BT_LIB_LOGI("Calling user's component finalization method: "
"%![comp-]+c", comp);
method(comp);
+ BT_ASSERT_POST_NO_ERROR(method_name);
+
+ if (saved_error) {
+ BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(saved_error);
+ }
}
}
*/
obj->ref_count++;
component = container_of(obj, struct bt_component, base);
- BT_LIB_LOGD("Destroying component: %![comp-]+c, %![graph-]+g",
+ BT_LIB_LOGI("Destroying component: %![comp-]+c, %![graph-]+g",
component, bt_component_borrow_graph(component));
/* Call destroy listeners in reverse registration order */
enum bt_component_class_type bt_component_get_class_type(
const struct bt_component *component)
{
- BT_ASSERT_PRE_NON_NULL(component, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
return component->class->type;
}
static
-enum bt_self_component_status add_port(
+enum bt_self_component_add_port_status add_port(
struct bt_component *component, GPtrArray *ports,
enum bt_port_type port_type, const char *name, void *user_data,
- struct bt_port **port)
+ struct bt_port **port, const char *api_func)
{
struct bt_port *new_port = NULL;
struct bt_graph *graph = NULL;
- enum bt_self_component_status status;
+ enum bt_self_component_add_port_status status;
- BT_ASSERT_PRE_NON_NULL(component, "Component");
- BT_ASSERT_PRE_NON_NULL(name, "Name");
- BT_ASSERT_PRE(strlen(name) > 0, "Name is empty");
+ BT_ASSERT(component);
+ BT_ASSERT(name);
+ BT_ASSERT_PRE_FROM_FUNC(api_func, "name-is-not-empty",
+ strlen(name) > 0, "Name is empty");
graph = bt_component_borrow_graph(component);
- BT_ASSERT_PRE(graph && !bt_graph_is_canceled(graph),
- "Component's graph is canceled: %![comp-]+c, %![graph-]+g",
- component, graph);
- BT_ASSERT_PRE(
+ BT_ASSERT_PRE_FROM_FUNC(api_func, "graph-is-not-configured",
graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
"Component's graph is already configured: "
"%![comp-]+c, %![graph-]+g", component, graph);
// TODO: Validate that the name is not already used.
- BT_LIB_LOGD("Adding port to component: %![comp-]+c, "
+ BT_LIB_LOGI("Adding port to component: %![comp-]+c, "
"port-type=%s, port-name=\"%s\"", component,
bt_port_type_string(port_type), name);
new_port = bt_port_create(component, port_type, name, user_data);
if (!new_port) {
- BT_LOGE_STR("Cannot create port object.");
- status = BT_SELF_COMPONENT_STATUS_NOMEM;
+ BT_LIB_LOGE_APPEND_CAUSE("Cannot create port object.");
+ status = BT_FUNC_STATUS_MEMORY_ERROR;
goto error;
}
*/
graph = bt_component_borrow_graph(component);
if (graph) {
- enum bt_graph_listener_status listener_status;
+ enum bt_graph_listener_func_status listener_status;
listener_status = bt_graph_notify_port_added(graph, new_port);
- if (listener_status != BT_GRAPH_LISTENER_STATUS_OK) {
+ if (listener_status != BT_FUNC_STATUS_OK) {
bt_graph_make_faulty(graph);
- status = listener_status;
+ status = (int) listener_status;
goto error;
}
}
- BT_LIB_LOGD("Created and added port to component: "
+ BT_LIB_LOGI("Created and added port to component: "
"%![comp-]+c, %![port-]+p", component, new_port);
*port = new_port;
- status = BT_SELF_COMPONENT_STATUS_OK;
+ status = BT_FUNC_STATUS_OK;
goto end;
error:
}
BT_HIDDEN
-uint64_t bt_component_get_input_port_count(const struct bt_component *comp)
+uint64_t bt_component_get_input_port_count(const struct bt_component *comp,
+ const char *api_func)
{
- BT_ASSERT_PRE_NON_NULL(comp, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
return (uint64_t) comp->input_ports->len;
}
BT_HIDDEN
-uint64_t bt_component_get_output_port_count(const struct bt_component *comp)
+uint64_t bt_component_get_output_port_count(const struct bt_component *comp,
+ const char *api_func)
{
- BT_ASSERT_PRE_NON_NULL(comp, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
return (uint64_t) comp->output_ports->len;
}
BT_HIDDEN
int bt_component_create(struct bt_component_class *component_class,
- const char *name, struct bt_component **user_component)
+ const char *name, bt_logging_level log_level,
+ struct bt_component **user_component)
{
int ret = 0;
struct bt_component *component = NULL;
BT_ASSERT(component_class);
BT_ASSERT(name);
type = bt_component_class_get_type(component_class);
- BT_LIB_LOGD("Creating empty component from component class: %![cc-]+C, "
- "comp-name=\"%s\"", component_class, name);
+ BT_LIB_LOGI("Creating empty component from component class: %![cc-]+C, "
+ "comp-name=\"%s\", log-level=%s", component_class, name,
+ bt_common_logging_level_string(log_level));
component = component_create_funcs[type](component_class);
if (!component) {
- BT_LOGE_STR("Cannot create specific component object.");
+ BT_LIB_LOGE_APPEND_CAUSE(
+ "Cannot create specific component object.");
ret = -1;
goto end;
}
bt_object_init_shared_with_parent(&component->base, destroy_component);
component->class = component_class;
- bt_object_get_no_null_check(component->class);
+ bt_object_get_ref_no_null_check(component->class);
component->destroy = component_destroy_funcs[type];
component->name = g_string_new(name);
if (!component->name) {
- BT_LOGE_STR("Failed to allocate one GString.");
+ BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GString.");
ret = -1;
goto end;
}
+ component->log_level = log_level;
component->input_ports = g_ptr_array_new_with_free_func(
(GDestroyNotify) bt_object_try_spec_release);
if (!component->input_ports) {
- BT_LOGE_STR("Failed to allocate one GPtrArray.");
+ BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GPtrArray.");
ret = -1;
goto end;
}
component->output_ports = g_ptr_array_new_with_free_func(
(GDestroyNotify) bt_object_try_spec_release);
if (!component->output_ports) {
- BT_LOGE_STR("Failed to allocate one GPtrArray.");
+ BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GPtrArray.");
ret = -1;
goto end;
}
component->destroy_listeners = g_array_new(FALSE, TRUE,
sizeof(struct bt_component_destroy_listener));
if (!component->destroy_listeners) {
- BT_LOGE_STR("Failed to allocate one GArray.");
+ BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GArray.");
ret = -1;
goto end;
}
- BT_LIB_LOGD("Created empty component from component class: "
+ BT_LIB_LOGI("Created empty component from component class: "
"%![cc-]+C, %![comp-]+c", component_class, component);
BT_OBJECT_MOVE_REF(*user_component, component);
const char *bt_component_get_name(const struct bt_component *component)
{
- BT_ASSERT_PRE_NON_NULL(component, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
return component->name->str;
}
const struct bt_component_class *bt_component_borrow_class_const(
const struct bt_component *component)
{
- BT_ASSERT_PRE_NON_NULL(component, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
return component->class;
}
{
struct bt_component *component = (void *) self_comp;
- BT_ASSERT_PRE_NON_NULL(component, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
return component->user_data;
}
{
struct bt_component *component = (void *) self_comp;
- BT_ASSERT_PRE_NON_NULL(component, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
component->user_data = data;
- BT_LIB_LOGV("Set component's user data: %!+c", component);
+ BT_LIB_LOGD("Set component's user data: %!+c", component);
}
BT_HIDDEN
graph ? &graph->base : NULL);
}
-bt_bool bt_component_graph_is_canceled(const struct bt_component *component)
-{
- return bt_graph_is_canceled(
- (void *) bt_object_borrow_parent(&component->base));
-}
-
static
struct bt_port *borrow_port_by_name(GPtrArray *ports,
- const char *name)
+ const char *name, const char *api_func)
{
uint64_t i;
struct bt_port *ret_port = NULL;
- BT_ASSERT(name);
+ BT_ASSERT_PRE_DEV_NAME_NON_NULL_FROM_FUNC(api_func, name);
for (i = 0; i < ports->len; i++) {
struct bt_port *port = g_ptr_array_index(ports, i);
- if (!strcmp(name, port->name->str)) {
+ if (strcmp(name, port->name->str) == 0) {
ret_port = port;
break;
}
BT_HIDDEN
struct bt_port_input *bt_component_borrow_input_port_by_name(
- struct bt_component *comp, const char *name)
+ struct bt_component *comp, const char *name,
+ const char *api_func)
{
- BT_ASSERT(comp);
- return (void *) borrow_port_by_name(comp->input_ports, name);
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
+ return (void *) borrow_port_by_name(comp->input_ports, name, api_func);
}
BT_HIDDEN
struct bt_port_output *bt_component_borrow_output_port_by_name(
- struct bt_component *comp, const char *name)
+ struct bt_component *comp, const char *name,
+ const char *api_func)
{
- BT_ASSERT_PRE_NON_NULL(comp, "Component");
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
return (void *)
- borrow_port_by_name(comp->output_ports, name);
+ borrow_port_by_name(comp->output_ports, name, api_func);
}
static
-struct bt_port *borrow_port_by_index(GPtrArray *ports, uint64_t index)
+struct bt_port *borrow_port_by_index(GPtrArray *ports, uint64_t index,
+ const char *api_func)
{
- BT_ASSERT(index < ports->len);
+ BT_ASSERT_PRE_DEV_VALID_INDEX_FROM_FUNC(api_func, index, ports->len);
return g_ptr_array_index(ports, index);
}
BT_HIDDEN
struct bt_port_input *bt_component_borrow_input_port_by_index(
- struct bt_component *comp, uint64_t index)
+ struct bt_component *comp, uint64_t index,
+ const char *api_func)
{
- BT_ASSERT_PRE_NON_NULL(comp, "Component");
- BT_ASSERT_PRE_VALID_INDEX(index, comp->input_ports->len);
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
return (void *)
- borrow_port_by_index(comp->input_ports, index);
+ borrow_port_by_index(comp->input_ports, index, api_func);
}
BT_HIDDEN
struct bt_port_output *bt_component_borrow_output_port_by_index(
- struct bt_component *comp, uint64_t index)
+ struct bt_component *comp, uint64_t index,
+ const char *api_func)
{
- BT_ASSERT_PRE_NON_NULL(comp, "Component");
- BT_ASSERT_PRE_VALID_INDEX(index, comp->output_ports->len);
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL_FROM_FUNC(api_func, comp);
return (void *)
- borrow_port_by_index(comp->output_ports, index);
+ borrow_port_by_index(comp->output_ports, index, api_func);
}
BT_HIDDEN
-enum bt_self_component_status bt_component_add_input_port(
+enum bt_self_component_add_port_status bt_component_add_input_port(
struct bt_component *component, const char *name,
- void *user_data, struct bt_port **port)
+ void *user_data, struct bt_port **port, const char *api_func)
{
- /* add_port() logs details */
+ BT_ASSERT_PRE_COMP_NON_NULL_FROM_FUNC(api_func, component);
+ BT_ASSERT_PRE_NAME_NON_NULL_FROM_FUNC(api_func, name);
+ BT_ASSERT_PRE_FROM_FUNC(api_func, "input-port-name-is-unique",
+ bt_component_port_name_is_unique(component->input_ports, name),
+ "Input port name is not unique: name=\"%s\", %![comp-]c",
+ name, component);
+
+ /* add_port() logs details and checks preconditions */
return add_port(component, component->input_ports,
- BT_PORT_TYPE_INPUT, name, user_data, port);
+ BT_PORT_TYPE_INPUT, name, user_data, port, api_func);
}
BT_HIDDEN
-enum bt_self_component_status bt_component_add_output_port(
+enum bt_self_component_add_port_status bt_component_add_output_port(
struct bt_component *component, const char *name,
- void *user_data, struct bt_port **port)
+ void *user_data, struct bt_port **port,
+ const char *api_func)
{
- /* add_port() logs details */
+ BT_ASSERT_PRE_COMP_NON_NULL_FROM_FUNC(api_func, component);
+ BT_ASSERT_PRE_NAME_NON_NULL_FROM_FUNC(api_func, name);
+ BT_ASSERT_PRE_FROM_FUNC(api_func, "output-port-name-is-unique",
+ bt_component_port_name_is_unique(component->output_ports, name),
+ "Output port name is not unique: name=\"%s\", %![comp-]c",
+ name, component);
+
+ /* add_port() logs details and checks preconditions */
return add_port(component, component->output_ports,
- BT_PORT_TYPE_OUTPUT, name, user_data, port);
+ BT_PORT_TYPE_OUTPUT, name, user_data, port, api_func);
}
BT_HIDDEN
-enum bt_self_component_status bt_component_accept_port_connection(
- struct bt_component *comp, struct bt_port *self_port,
- struct bt_port *other_port)
+bool bt_component_port_name_is_unique(GPtrArray *ports, const char *name)
{
- typedef enum bt_self_component_status (*method_t)(
- void *, void *, const void *);
-
- enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
- method_t method = NULL;
+ guint i;
+ bool unique;
- BT_ASSERT(comp);
- BT_ASSERT(self_port);
- BT_ASSERT(other_port);
-
- switch (comp->class->type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- {
- struct bt_component_class_source *src_cc = (void *) comp->class;
-
- switch (self_port->type) {
- case BT_PORT_TYPE_OUTPUT:
- method = (method_t) src_cc->methods.accept_output_port_connection;
- break;
- default:
- abort();
- }
-
- break;
- }
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- {
- struct bt_component_class_filter *flt_cc = (void *) comp->class;
+ for (i = 0; i < ports->len; i++) {
+ struct bt_port *port = g_ptr_array_index(ports, i);
- switch (self_port->type) {
- case BT_PORT_TYPE_INPUT:
- method = (method_t) flt_cc->methods.accept_input_port_connection;
- break;
- case BT_PORT_TYPE_OUTPUT:
- method = (method_t) flt_cc->methods.accept_output_port_connection;
- break;
- default:
- abort();
+ if (strcmp(port->name->str, name) == 0) {
+ unique = false;
+ goto end;
}
-
- break;
}
- case BT_COMPONENT_CLASS_TYPE_SINK:
- {
- struct bt_component_class_sink *sink_cc = (void *) comp->class;
- switch (self_port->type) {
- case BT_PORT_TYPE_INPUT:
- method = (method_t) sink_cc->methods.accept_input_port_connection;
- break;
- default:
- abort();
- }
+ unique = true;
- break;
- }
- default:
- abort();
- }
-
- if (method) {
- BT_LIB_LOGD("Calling user's \"accept port connection\" method: "
- "%![comp-]+c, %![self-port-]+p, %![other-port-]+p",
- comp, self_port, other_port);
- status = method(comp, self_port, (void *) other_port);
- BT_LOGD("User method returned: status=%s",
- bt_self_component_status_string(status));
- }
-
- return status;
+end:
+ return unique;
}
BT_HIDDEN
-enum bt_self_component_status bt_component_port_connected(
+enum bt_component_class_port_connected_method_status
+bt_component_port_connected(
struct bt_component *comp, struct bt_port *self_port,
struct bt_port *other_port)
{
- typedef enum bt_self_component_status (*method_t)(
+ typedef enum bt_component_class_port_connected_method_status (*method_t)(
void *, void *, const void *);
- enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
+ enum bt_component_class_port_connected_method_status status =
+ BT_FUNC_STATUS_OK;
method_t method = NULL;
+ const char *method_name = NULL;
BT_ASSERT(comp);
BT_ASSERT(self_port);
switch (self_port->type) {
case BT_PORT_TYPE_OUTPUT:
method = (method_t) src_cc->methods.output_port_connected;
+ method_name = "bt_component_class_source_output_port_connected_method";
break;
default:
- abort();
+ bt_common_abort();
}
break;
switch (self_port->type) {
case BT_PORT_TYPE_INPUT:
method = (method_t) flt_cc->methods.input_port_connected;
+ method_name = "bt_component_class_filter_input_port_connected_method";
break;
case BT_PORT_TYPE_OUTPUT:
method = (method_t) flt_cc->methods.output_port_connected;
+ method_name = "bt_component_class_filter_output_port_connected_method";
break;
default:
- abort();
+ bt_common_abort();
}
break;
switch (self_port->type) {
case BT_PORT_TYPE_INPUT:
method = (method_t) sink_cc->methods.input_port_connected;
+ method_name = "bt_component_class_sink_input_port_connected_method";
break;
default:
- abort();
+ bt_common_abort();
}
break;
}
default:
- abort();
+ bt_common_abort();
}
if (method) {
BT_LIB_LOGD("Calling user's \"port connected\" method: "
"%![comp-]+c, %![self-port-]+p, %![other-port-]+p",
comp, self_port, other_port);
- status = method(comp, self_port, (void *) other_port);
+ status = (int) method(comp, self_port, (void *) other_port);
BT_LOGD("User method returned: status=%s",
- bt_self_component_status_string(status));
- BT_ASSERT_PRE(status == BT_SELF_COMPONENT_STATUS_OK ||
- status == BT_SELF_COMPONENT_STATUS_ERROR ||
- status == BT_SELF_COMPONENT_STATUS_NOMEM,
+ bt_common_func_status_string(status));
+ BT_ASSERT_POST(method_name, "valid-status",
+ status == BT_FUNC_STATUS_OK ||
+ status == BT_FUNC_STATUS_ERROR ||
+ status == BT_FUNC_STATUS_MEMORY_ERROR,
"Unexpected returned component status: status=%s",
- bt_self_component_status_string(status));
+ bt_common_func_status_string(status));
+ BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(method_name, status);
}
return status;
listener.func = func;
listener.data = data;
g_array_append_val(component->destroy_listeners, listener);
- BT_LIB_LOGV("Added destroy listener: %![comp-]+c, "
+ BT_LIB_LOGD("Added destroy listener: %![comp-]+c, "
"func-addr=%p, data-addr=%p",
component, func, data);
}
if (listener->func == func && listener->data == data) {
g_array_remove_index(component->destroy_listeners, i);
i--;
- BT_LIB_LOGV("Removed destroy listener: %![comp-]+c, "
+ BT_LIB_LOGD("Removed destroy listener: %![comp-]+c, "
"func-addr=%p, data-addr=%p",
component, func, data);
}
}
}
+bt_logging_level bt_component_get_logging_level(
+ const struct bt_component *component)
+{
+ BT_ASSERT_PRE_DEV_COMP_NON_NULL(component);
+ return component->log_level;
+}
+
+uint64_t bt_self_component_get_graph_mip_version(
+ bt_self_component *self_component)
+{
+ struct bt_component *comp = (void *) self_component;
+
+ BT_ASSERT_PRE_COMP_NON_NULL(self_component);
+ return bt_component_borrow_graph(comp)->mip_version;
+}
+
void bt_component_get_ref(const struct bt_component *component)
{
bt_object_get_ref(component);