#include "common/common.h"
#include <unistd.h>
#include <stdlib.h>
-#include <popt.h>
#include <string.h>
#include <stdio.h>
#include <glib.h>
#include "babeltrace2-cfg-cli-args.h"
#include "babeltrace2-cfg-cli-args-default.h"
#include "babeltrace2-plugins.h"
+#include "babeltrace2-query.h"
#define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH"
#define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL"
NULL,
};
-/* Application's processing graph (weak) */
-static bt_graph *the_graph;
-static bt_query_executor *the_query_executor;
-static bool canceled = false;
+/* Application's interrupter (owned by this) */
+static bt_interrupter *the_interrupter;
#ifdef __MINGW32__
static
BOOL WINAPI signal_handler(DWORD signal) {
- if (the_graph) {
- bt_graph_cancel(the_graph);
+ if (the_interrupter) {
+ bt_interrupter_set(the_interrupter);
}
- canceled = true;
-
return TRUE;
}
return;
}
- if (the_graph) {
- bt_graph_cancel(the_graph);
- }
-
- if (the_query_executor) {
- bt_query_executor_cancel(the_query_executor);
+ if (the_interrupter) {
+ bt_interrupter_set(the_interrupter);
}
-
- canceled = true;
}
static
#endif /* __MINGW32__ */
-static
-int create_the_query_executor(void)
-{
- int ret = 0;
-
- the_query_executor = bt_query_executor_create();
- if (!the_query_executor) {
- BT_CLI_LOGE_APPEND_CAUSE("Cannot create a query executor.");
- ret = -1;
- }
-
- return ret;
-}
-
-static
-void destroy_the_query_executor(void)
-{
- BT_QUERY_EXECUTOR_PUT_REF_AND_RESET(the_query_executor);
-}
-
static
int query(struct bt_config *cfg, const bt_component_class *comp_cls,
const char *obj, const bt_value *params,
const bt_value **user_result, const char **fail_reason)
{
- const bt_value *result = NULL;
- bt_query_executor_query_status query_status;
- *fail_reason = "unknown error";
- int ret = 0;
-
- BT_ASSERT(fail_reason);
- BT_ASSERT(user_result);
- ret = create_the_query_executor();
- if (ret) {
- /* create_the_query_executor() logs errors */
- goto end;
- }
-
- if (canceled) {
- BT_CLI_LOGW_APPEND_CAUSE(
- "Canceled by user before executing the query: "
- "comp-cls-addr=%p, comp-cls-name=\"%s\", "
- "query-obj=\"%s\"", comp_cls,
- bt_component_class_get_name(comp_cls), obj);
- *fail_reason = "canceled by user";
- goto error;
- }
-
- while (true) {
- query_status = bt_query_executor_query(
- the_query_executor, comp_cls, obj, params,
- cfg->log_level, &result);
- switch (query_status) {
- case BT_QUERY_EXECUTOR_QUERY_STATUS_OK:
- goto ok;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN:
- {
- const uint64_t sleep_time_us = 100000;
-
- /* Wait 100 ms and retry */
- BT_LOGD("Got BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: sleeping: "
- "time-us=%" PRIu64, sleep_time_us);
-
- if (usleep(sleep_time_us)) {
- if (bt_query_executor_is_canceled(the_query_executor)) {
- BT_CLI_LOGW_APPEND_CAUSE(
- "Query was canceled by user: "
- "comp-cls-addr=%p, comp-cls-name=\"%s\", "
- "query-obj=\"%s\"", comp_cls,
- bt_component_class_get_name(comp_cls),
- obj);
- *fail_reason = "canceled by user";
- goto error;
- }
- }
-
- continue;
- }
- case BT_QUERY_EXECUTOR_QUERY_STATUS_CANCELED:
- *fail_reason = "canceled by user";
- goto error;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR:
- goto error;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_INVALID_OBJECT:
- *fail_reason = "invalid or unknown query object";
- goto error;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_INVALID_PARAMS:
- *fail_reason = "invalid query parameters";
- goto error;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_UNSUPPORTED:
- *fail_reason = "unsupported action";
- goto error;
- case BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR:
- *fail_reason = "not enough memory";
- goto error;
- default:
- BT_LOGF("Unknown query status: status=%s",
- bt_common_func_status_string(query_status));
- abort();
- }
- }
-
-ok:
- *user_result = result;
- result = NULL;
- goto end;
-
-error:
- ret = -1;
-
-end:
- destroy_the_query_executor();
- bt_value_put_ref(result);
- return ret;
+ return cli_query(comp_cls, obj, params, cfg->log_level,
+ the_interrupter, user_result, fail_reason);
}
-
-
typedef const void *(*plugin_borrow_comp_cls_func_t)(
const bt_plugin *, const char *);
bt_common_color_reset());
break;
case BT_VALUE_TYPE_ARRAY:
- size = bt_value_array_get_size(value);
+ size = bt_value_array_get_length(value);
if (size < 0) {
goto error;
}
}
}
- array_size = bt_value_array_get_size(results);
+ array_size = bt_value_array_get_length(results);
for (i = 0; i < array_size; i++) {
const char *url_text;
int64_t timer_us, streams, clients;
switch (connect_ports_status) {
case BT_GRAPH_CONNECT_PORTS_STATUS_OK:
break;
- case BT_GRAPH_CONNECT_PORTS_STATUS_CANCELED:
- BT_CLI_LOGW_APPEND_CAUSE("Graph was canceled by user.");
- break;
default:
BT_CLI_LOGE_APPEND_CAUSE(
"Cannot create connection: graph refuses to connect ports: "
}
BT_GRAPH_PUT_REF_AND_RESET(ctx->graph);
- the_graph = NULL;
ctx->cfg = NULL;
}
+static
+int add_descriptor_to_component_descriptor_set(
+ bt_component_descriptor_set *comp_descr_set,
+ const char *plugin_name, const char *comp_cls_name,
+ bt_component_class_type comp_cls_type,
+ const bt_value *params)
+{
+ const bt_component_class *comp_cls;
+ int status = 0;
+
+ comp_cls = find_component_class(plugin_name, comp_cls_name,
+ comp_cls_type);
+ if (!comp_cls) {
+ BT_CLI_LOGE_APPEND_CAUSE(
+ "Cannot find component class: plugin-name=\"%s\", "
+ "comp-cls-name=\"%s\", comp-cls-type=%d",
+ plugin_name, comp_cls_name, comp_cls_type);
+ status = -1;
+ goto end;
+ }
+
+ status = bt_component_descriptor_set_add_descriptor(
+ comp_descr_set, comp_cls, params);
+ if (status != BT_COMPONENT_DESCRIPTOR_SET_ADD_DESCRIPTOR_STATUS_OK) {
+ BT_CLI_LOGE_APPEND_CAUSE(
+ "Cannot append descriptor to component descriptor set: "
+ "status=%s", bt_common_func_status_string(status));
+ goto end;
+ }
+
+end:
+ bt_component_class_put_ref(comp_cls);
+ return status;
+}
+
+static
+int append_descriptors_from_bt_config_component_array(
+ bt_component_descriptor_set *comp_descr_set,
+ GPtrArray *component_configs)
+{
+ int ret = 0;
+ uint64_t i;
+
+ for (i = 0; i < component_configs->len; i++) {
+ struct bt_config_component *cfg_comp =
+ component_configs->pdata[i];
+
+ ret = add_descriptor_to_component_descriptor_set(
+ comp_descr_set,
+ cfg_comp->plugin_name->str,
+ cfg_comp->comp_cls_name->str,
+ cfg_comp->type, cfg_comp->params);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+bt_get_greatest_operative_mip_version_status get_greatest_operative_mip_version(
+ struct bt_config *cfg, uint64_t *mip_version)
+{
+ bt_get_greatest_operative_mip_version_status status =
+ BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_OK;
+ bt_component_descriptor_set *comp_descr_set = NULL;
+ int ret;
+
+ BT_ASSERT(cfg);
+ BT_ASSERT(mip_version);
+ comp_descr_set = bt_component_descriptor_set_create();
+ if (!comp_descr_set) {
+ BT_CLI_LOGE_APPEND_CAUSE(
+ "Failed to create a component descriptor set object.");
+ status = BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_MEMORY_ERROR;
+ goto end;
+ }
+
+ ret = append_descriptors_from_bt_config_component_array(
+ comp_descr_set, cfg->cmd_data.run.sources);
+ if (ret) {
+ status = BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_ERROR;
+ goto end;
+ }
+
+ ret = append_descriptors_from_bt_config_component_array(
+ comp_descr_set, cfg->cmd_data.run.filters);
+ if (ret) {
+ status = BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_ERROR;
+ goto end;
+ }
+
+ ret = append_descriptors_from_bt_config_component_array(
+ comp_descr_set, cfg->cmd_data.run.sinks);
+ if (ret) {
+ status = BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_ERROR;
+ goto end;
+ }
+
+ if (cfg->cmd_data.run.stream_intersection_mode) {
+ /*
+ * Stream intersection mode adds `flt.utils.trimmer`
+ * components; we need to include this type of component
+ * in the component descriptor set to get the real
+ * greatest operative MIP version.
+ */
+ ret = add_descriptor_to_component_descriptor_set(
+ comp_descr_set, "utils", "trimmer",
+ BT_COMPONENT_CLASS_TYPE_FILTER, NULL);
+ if (ret) {
+ status = BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_ERROR;
+ goto end;
+ }
+ }
+
+ status = bt_get_greatest_operative_mip_version(comp_descr_set,
+ bt_cli_log_level, mip_version);
+
+end:
+ bt_component_descriptor_set_put_ref(comp_descr_set);
+ return status;
+}
+
static
int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
{
int ret = 0;
bt_graph_add_listener_status add_listener_status;
+ bt_get_greatest_operative_mip_version_status mip_version_status;
+ uint64_t mip_version = UINT64_C(-1);
ctx->cfg = cfg;
ctx->connect_ports = false;
}
}
- ctx->graph = bt_graph_create();
+ /*
+ * Get the greatest operative MIP version to use to configure
+ * the graph to create.
+ */
+ mip_version_status = get_greatest_operative_mip_version(
+ cfg, &mip_version);
+ if (mip_version_status == BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_NO_MATCH) {
+ BT_CLI_LOGE_APPEND_CAUSE(
+ "Failed to find an operative message interchange "
+ "protocol version to use to create the `run` command's "
+ "graph (components are not interoperable).");
+ goto error;
+ } else if (mip_version_status < 0) {
+ BT_CLI_LOGE_APPEND_CAUSE(
+ "Cannot find an operative message interchange "
+ "protocol version to use to create the `run` command's "
+ "graph: status=%s",
+ bt_common_func_status_string(mip_version_status));
+ goto error;
+ }
+
+ BT_ASSERT(mip_version_status == BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_OK);
+ BT_LOGI("Found operative message interchange protocol version to "
+ "configure the `run` command's graph: mip-version=%" PRIu64,
+ mip_version);
+ ctx->graph = bt_graph_create(mip_version);
if (!ctx->graph) {
goto error;
}
- the_graph = ctx->graph;
+ bt_graph_add_interrupter(ctx->graph, the_interrupter);
add_listener_status = bt_graph_add_source_component_output_port_added_listener(
ctx->graph, graph_source_output_port_added_listener, NULL, ctx,
NULL);
const bt_component_class *comp_cls =
bt_component_class_source_as_component_class_const(src_comp_cls);
- ret = query(ctx->cfg, comp_cls, "trace-info",
+ ret = query(ctx->cfg, comp_cls, "babeltrace.trace-info",
cfg_comp->params, &query_result,
&fail_reason);
if (ret) {
- BT_LOGD("Component class does not support the `trace-info` query: %s: "
+ BT_LOGD("Component class does not support the `babeltrace.trace-info` query: %s: "
"comp-class-name=\"%s\"", fail_reason,
bt_component_class_get_name(comp_cls));
ret = -1;
BT_ASSERT(query_result);
if (!bt_value_is_array(query_result)) {
- BT_LOGD("Unexpected format of \'trace-info\' query result: "
+ BT_LOGD("Unexpected format of `babeltrace.trace-info` query result: "
"component-class-name=%s",
bt_component_class_get_name(comp_cls));
ret = -1;
goto error;
}
- trace_count = bt_value_array_get_size(query_result);
+ trace_count = bt_value_array_get_length(query_result);
if (trace_count < 0) {
ret = -1;
goto error;
goto error;
}
- stream_count = bt_value_array_get_size(stream_infos);
+ stream_count = bt_value_array_get_length(stream_infos);
if (stream_count < 0) {
ret = -1;
goto error;
goto error;
}
- if (canceled) {
+ if (bt_interrupter_is_set(the_interrupter)) {
BT_CLI_LOGW_APPEND_CAUSE(
- "Canceled by user before creating components.");
+ "Interrupted by user before creating components.");
goto error;
}
goto error;
}
- if (canceled) {
+ if (bt_interrupter_is_set(the_interrupter)) {
BT_CLI_LOGW_APPEND_CAUSE(
- "Canceled by user before connecting components.");
+ "Interrupted by user before connecting components.");
goto error;
}
goto error;
}
- if (canceled) {
- BT_CLI_LOGW_APPEND_CAUSE(
- "Canceled by user before running the graph.");
- goto error;
- }
-
BT_LOGI_STR("Running the graph.");
/* Run the graph */
switch (run_status) {
case BT_GRAPH_RUN_STATUS_OK:
break;
- case BT_GRAPH_RUN_STATUS_CANCELED:
- BT_CLI_LOGW_APPEND_CAUSE("Graph was canceled by user.");
- goto error;
case BT_GRAPH_RUN_STATUS_AGAIN:
- if (bt_graph_is_canceled(ctx.graph)) {
+ if (bt_interrupter_is_set(the_interrupter)) {
BT_CLI_LOGW_APPEND_CAUSE(
- "Graph was canceled by user.");
+ "Graph was interrupted by user.");
goto error;
}
cfg->cmd_data.run.retry_duration_us);
if (usleep(cfg->cmd_data.run.retry_duration_us)) {
- if (bt_graph_is_canceled(ctx.graph)) {
+ if (bt_interrupter_is_set(the_interrupter)) {
BT_CLI_LOGW_APPEND_CAUSE(
- "Graph was canceled by user.");
+ "Graph was interrupted by user.");
goto error;
}
}
case BT_GRAPH_RUN_STATUS_END:
goto end;
default:
+ if (bt_interrupter_is_set(the_interrupter)) {
+ BT_CLI_LOGW_APPEND_CAUSE(
+ "Graph was interrupted by user and failed: "
+ "status=%s",
+ bt_common_func_status_string(run_status));
+ goto error;
+ }
+
BT_CLI_LOGE_APPEND_CAUSE(
"Graph failed to complete successfully");
goto error;
}
end:
- if (folded) {
- g_string_free(folded, TRUE);
- }
+ BT_ASSERT(!folded);
if (error) {
bt_error_release(error);
if (!cfg) {
BT_CLI_LOGE_APPEND_CAUSE(
- "Failed to create a valid Babeltrace configuration.");
+ "Failed to create a valid Babeltrace CLI configuration.");
retcode = 1;
goto end;
}
}
}
+ BT_ASSERT(!the_interrupter);
+ the_interrupter = bt_interrupter_create();
+ if (!the_interrupter) {
+ BT_CLI_LOGE_APPEND_CAUSE("Failed to create an interrupter object.");
+ retcode = 1;
+ goto end;
+ }
+
BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
cfg->command, cfg->command_name);
end:
BT_OBJECT_PUT_REF_AND_RESET(cfg);
fini_loaded_plugins();
+ bt_interrupter_put_ref(the_interrupter);
if (retcode != 0) {
print_error_causes();