X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=converter%2Fbabeltrace-cfg-connect.c;fp=converter%2Fbabeltrace-cfg-connect.c;h=0000000000000000000000000000000000000000;hp=e1de064d56fc7dc88071622f9bea8ff60ff8d07b;hb=8d77550c9ec0f0bdb483a672a676e842510bb384;hpb=599faa1c75b3c429745e0d4a983670c3dd205092 diff --git a/converter/babeltrace-cfg-connect.c b/converter/babeltrace-cfg-connect.c deleted file mode 100644 index e1de064d..00000000 --- a/converter/babeltrace-cfg-connect.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright 2017 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "babeltrace-cfg.h" -#include "babeltrace-cfg-connect.h" - -static bool all_named_and_printable_in_array(GPtrArray *comps) -{ - size_t i; - bool all_named_and_printable = true; - - for (i = 0; i < comps->len; i++) { - struct bt_config_component *comp = g_ptr_array_index(comps, i); - - if (comp->instance_name->len == 0) { - all_named_and_printable = false; - goto end; - } - - if (!bt_common_string_is_printable(comp->instance_name->str)) { - all_named_and_printable = false; - goto end; - } - } - -end: - return all_named_and_printable; -} - -static bool all_named_and_printable(struct bt_config *cfg) -{ - return all_named_and_printable_in_array(cfg->cmd_data.run.sources) && - all_named_and_printable_in_array(cfg->cmd_data.run.filters) && - all_named_and_printable_in_array(cfg->cmd_data.run.sinks); -} - -void bt_config_connection_destroy(struct bt_config_connection *connection) -{ - if (!connection) { - return; - } - - if (connection->src_instance_name) { - g_string_free(connection->src_instance_name, TRUE); - } - - if (connection->dst_instance_name) { - g_string_free(connection->dst_instance_name, TRUE); - } - - if (connection->src_port_name) { - g_string_free(connection->src_port_name, TRUE); - } - - if (connection->dst_port_name) { - g_string_free(connection->dst_port_name, TRUE); - } - - if (connection->arg) { - g_string_free(connection->arg, TRUE); - } - - g_free(connection); -} - -static struct bt_config_connection *bt_config_connection_create(const char *arg) -{ - struct bt_config_connection *cfg_connection; - - cfg_connection = g_new0(struct bt_config_connection, 1); - if (!cfg_connection) { - goto error; - } - - cfg_connection->src_instance_name = g_string_new(NULL); - if (!cfg_connection->src_instance_name) { - goto error; - } - - cfg_connection->dst_instance_name = g_string_new(NULL); - if (!cfg_connection->dst_instance_name) { - goto error; - } - - cfg_connection->src_port_name = g_string_new(NULL); - if (!cfg_connection->src_port_name) { - goto error; - } - - cfg_connection->dst_port_name = g_string_new(NULL); - if (!cfg_connection->dst_port_name) { - goto error; - } - - cfg_connection->arg = g_string_new(arg); - if (!cfg_connection->arg) { - goto error; - } - - goto end; - -error: - g_free(cfg_connection); - cfg_connection = NULL; - -end: - return cfg_connection; -} - -static struct bt_config_connection *cfg_connection_from_arg(const char *arg) -{ - const char *at = arg; - size_t end_pos; - struct bt_config_connection *cfg_conn = NULL; - GString *gs = NULL; - enum { - SRC_NAME, - DST_NAME, - SRC_PORT_NAME, - DST_PORT_NAME, - } state = SRC_NAME; - - if (!bt_common_string_is_printable(arg)) { - goto error; - } - - cfg_conn = bt_config_connection_create(arg); - if (!cfg_conn) { - goto error; - } - - while (true) { - switch (state) { - case SRC_NAME: - gs = bt_common_string_until(at, ".:\\", ".:", &end_pos); - if (!gs || gs->len == 0) { - goto error; - } - - g_string_free(cfg_conn->src_instance_name, TRUE); - cfg_conn->src_instance_name = gs; - gs = NULL; - - if (at[end_pos] == ':') { - state = DST_NAME; - } else if (at[end_pos] == '.') { - state = SRC_PORT_NAME; - } else { - goto error; - } - - at += end_pos + 1; - break; - case DST_NAME: - gs = bt_common_string_until(at, ".:\\", ".:", &end_pos); - if (!gs || gs->len == 0) { - goto error; - } - - g_string_free(cfg_conn->dst_instance_name, TRUE); - cfg_conn->dst_instance_name = gs; - gs = NULL; - - if (at[end_pos] == '.') { - state = DST_PORT_NAME; - } else if (at[end_pos] == '\0') { - goto end; - } else { - goto error; - } - - at += end_pos + 1; - break; - case SRC_PORT_NAME: - gs = bt_common_string_until(at, ".:\\", ".:", &end_pos); - if (!gs || gs->len == 0) { - goto error; - } - - g_string_free(cfg_conn->src_port_name, TRUE); - cfg_conn->src_port_name = gs; - gs = NULL; - - if (at[end_pos] == ':') { - state = DST_NAME; - } else { - goto error; - } - - at += end_pos + 1; - break; - case DST_PORT_NAME: - gs = bt_common_string_until(at, ".:\\", ".:", &end_pos); - if (!gs || gs->len == 0) { - goto error; - } - - g_string_free(cfg_conn->dst_port_name, TRUE); - cfg_conn->dst_port_name = gs; - gs = NULL; - - if (at[end_pos] == '\0') { - goto end; - } else { - goto error; - } - break; - default: - assert(false); - } - } - -error: - bt_config_connection_destroy(cfg_conn); - cfg_conn = NULL; - -end: - if (gs) { - g_string_free(gs, TRUE); - } - - return cfg_conn; -} - -static struct bt_config_component *find_component_in_array(GPtrArray *comps, - const char *name) -{ - size_t i; - struct bt_config_component *found_comp = NULL; - - for (i = 0; i < comps->len; i++) { - struct bt_config_component *comp = g_ptr_array_index(comps, i); - - if (strcmp(name, comp->instance_name->str) == 0) { - found_comp = bt_get(comp); - goto end; - } - } - -end: - return found_comp; -} - -static struct bt_config_component *find_component(struct bt_config *cfg, - const char *name) -{ - struct bt_config_component *comp; - - comp = find_component_in_array(cfg->cmd_data.run.sources, name); - if (comp) { - goto end; - } - - comp = find_component_in_array(cfg->cmd_data.run.filters, name); - if (comp) { - goto end; - } - - comp = find_component_in_array(cfg->cmd_data.run.sinks, name); - if (comp) { - goto end; - } - -end: - return comp; -} - -static int validate_all_endpoints_exist(struct bt_config *cfg, char *error_buf, - size_t error_buf_size) -{ - size_t i; - int ret = 0; - - for (i = 0; i < cfg->cmd_data.run.connections->len; i++) { - struct bt_config_connection *connection = - g_ptr_array_index(cfg->cmd_data.run.connections, i); - struct bt_config_component *comp; - - comp = find_component(cfg, connection->src_instance_name->str); - bt_put(comp); - if (!comp) { - snprintf(error_buf, error_buf_size, - "Invalid connection: cannot find upstream component `%s`:\n %s\n", - connection->src_instance_name->str, - connection->arg->str); - ret = -1; - goto end; - } - - comp = find_component(cfg, connection->dst_instance_name->str); - bt_put(comp); - if (!comp) { - snprintf(error_buf, error_buf_size, - "Invalid connection: cannot find downstream component `%s`:\n %s\n", - connection->dst_instance_name->str, - connection->arg->str); - ret = -1; - goto end; - } - } - -end: - return ret; -} - -static int validate_connection_directions(struct bt_config *cfg, - char *error_buf, size_t error_buf_size) -{ - size_t i; - int ret = 0; - struct bt_config_component *src_comp = NULL; - struct bt_config_component *dst_comp = NULL; - - for (i = 0; i < cfg->cmd_data.run.connections->len; i++) { - struct bt_config_connection *connection = - g_ptr_array_index(cfg->cmd_data.run.connections, i); - - src_comp = find_component(cfg, - connection->src_instance_name->str); - assert(src_comp); - dst_comp = find_component(cfg, - connection->dst_instance_name->str); - assert(dst_comp); - - if (src_comp->type == BT_COMPONENT_CLASS_TYPE_SOURCE) { - if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER && - dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) { - snprintf(error_buf, error_buf_size, - "Invalid connection: source component `%s` not connected to filter or sink component:\n %s\n", - connection->src_instance_name->str, - connection->arg->str); - ret = -1; - goto end; - } - } else if (src_comp->type == BT_COMPONENT_CLASS_TYPE_FILTER) { - if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER && - dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) { - snprintf(error_buf, error_buf_size, - "Invalid connection: filter component `%s` not connected to filter or sink component:\n %s\n", - connection->src_instance_name->str, - connection->arg->str); - ret = -1; - goto end; - } - } else { - snprintf(error_buf, error_buf_size, - "Invalid connection: cannot connect sink component `%s` to component `%s`:\n %s\n", - connection->src_instance_name->str, - connection->dst_instance_name->str, - connection->arg->str); - ret = -1; - goto end; - } - - BT_PUT(src_comp); - BT_PUT(dst_comp); - } - -end: - bt_put(src_comp); - bt_put(dst_comp); - return ret; -} - -static int validate_no_cycles_rec(struct bt_config *cfg, GPtrArray *path, - char *error_buf, size_t error_buf_size) -{ - int ret = 0; - size_t conn_i; - const char *src_comp_name; - - assert(path && path->len > 0); - src_comp_name = g_ptr_array_index(path, path->len - 1); - - for (conn_i = 0; conn_i < cfg->cmd_data.run.connections->len; conn_i++) { - struct bt_config_connection *conn = - g_ptr_array_index(cfg->cmd_data.run.connections, conn_i); - - if (strcmp(conn->src_instance_name->str, src_comp_name) == 0) { - size_t path_i; - - for (path_i = 0; path_i < path->len; path_i++) { - const char *comp_name = - g_ptr_array_index(path, path_i); - - if (strcmp(comp_name, conn->dst_instance_name->str) == 0) { - snprintf(error_buf, error_buf_size, - "Invalid connection: connection forms a cycle:\n %s\n", - conn->arg->str); - ret = -1; - goto end; - } - } - - g_ptr_array_add(path, conn->dst_instance_name->str); - ret = validate_no_cycles_rec(cfg, path, error_buf, - error_buf_size); - if (ret) { - goto end; - } - - g_ptr_array_remove_index(path, path->len - 1); - } - } - -end: - return ret; -} - -static int validate_no_cycles(struct bt_config *cfg, char *error_buf, - size_t error_buf_size) -{ - size_t i; - int ret = 0; - GPtrArray *path; - - path = g_ptr_array_new(); - if (!path) { - ret = -1; - goto end; - } - - g_ptr_array_add(path, NULL); - - for (i = 0; i < cfg->cmd_data.run.connections->len; i++) { - struct bt_config_connection *conn = - g_ptr_array_index(cfg->cmd_data.run.connections, i); - - g_ptr_array_index(path, 0) = conn->src_instance_name->str; - ret = validate_no_cycles_rec(cfg, path, - error_buf, error_buf_size); - if (ret) { - goto end; - } - } - -end: - if (path) { - g_ptr_array_free(path, TRUE); - } - - return ret; -} - -static int validate_all_components_connected_in_array(GPtrArray *comps, - struct bt_value *connected_components, - char *error_buf, size_t error_buf_size) -{ - int ret = 0; - size_t i; - - for (i = 0; i < comps->len; i++) { - struct bt_config_component *comp = g_ptr_array_index(comps, i); - - if (!bt_value_map_has_key(connected_components, - comp->instance_name->str)) { - snprintf(error_buf, error_buf_size, - "Component `%s` is not connected\n", - comp->instance_name->str); - ret = -1; - goto end; - } - } - -end: - return ret; -} - -static int validate_all_components_connected(struct bt_config *cfg, - char *error_buf, size_t error_buf_size) -{ - size_t i; - int ret = 0; - struct bt_value *connected_components = bt_value_map_create(); - - if (!connected_components) { - ret = -1; - goto end; - } - - for (i = 0; i < cfg->cmd_data.run.connections->len; i++) { - struct bt_config_connection *connection = - g_ptr_array_index(cfg->cmd_data.run.connections, i); - - ret = bt_value_map_insert(connected_components, - connection->src_instance_name->str, bt_value_null); - if (ret) { - goto end; - } - - ret = bt_value_map_insert(connected_components, - connection->dst_instance_name->str, bt_value_null); - if (ret) { - goto end; - } - } - - ret = validate_all_components_connected_in_array( - cfg->cmd_data.run.sources, connected_components, - error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_all_components_connected_in_array( - cfg->cmd_data.run.filters, connected_components, - error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_all_components_connected_in_array( - cfg->cmd_data.run.sinks, connected_components, - error_buf, error_buf_size); - if (ret) { - goto end; - } - -end: - bt_put(connected_components); - return ret; -} - -static int validate_no_duplicate_connection(struct bt_config *cfg, - char *error_buf, size_t error_buf_size) -{ - size_t i; - int ret = 0; - struct bt_value *flat_connection_names = bt_value_map_create(); - GString *flat_connection_name = NULL; - - if (!flat_connection_names) { - ret = -1; - goto end; - } - - flat_connection_name = g_string_new(NULL); - if (!flat_connection_name) { - ret = -1; - goto end; - } - - for (i = 0; i < cfg->cmd_data.run.connections->len; i++) { - struct bt_config_connection *connection = - g_ptr_array_index(cfg->cmd_data.run.connections, i); - - g_string_printf(flat_connection_name, "%s\x01%s\x01%s\x01%s", - connection->src_instance_name->str, - connection->src_port_name->str, - connection->dst_instance_name->str, - connection->dst_port_name->str); - - if (bt_value_map_has_key(flat_connection_names, - flat_connection_name->str)) { - snprintf(error_buf, error_buf_size, - "Duplicate connection:\n %s\n", - connection->arg->str); - ret = -1; - goto end; - } - - ret = bt_value_map_insert(flat_connection_names, - flat_connection_name->str, bt_value_null); - if (ret) { - goto end; - } - } - -end: - bt_put(flat_connection_names); - - if (flat_connection_name) { - g_string_free(flat_connection_name, TRUE); - } - - return ret; -} - -static int validate_connections(struct bt_config *cfg, char *error_buf, - size_t error_buf_size) -{ - int ret; - - ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_connection_directions(cfg, error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_all_components_connected(cfg, error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size); - if (ret) { - goto end; - } - - ret = validate_no_cycles(cfg, error_buf, error_buf_size); - if (ret) { - goto end; - } - -end: - return ret; -} - -int bt_config_create_connections(struct bt_config *cfg, - struct bt_value *connection_args, - char *error_buf, size_t error_buf_size) -{ - int ret; - size_t i; - - if (!all_named_and_printable(cfg)) { - snprintf(error_buf, error_buf_size, - "One or more components are unnamed (use --name) or contain a non-printable character\n"); - goto error; - } - - for (i = 0; i < bt_value_array_size(connection_args); i++) { - struct bt_value *arg_value = - bt_value_array_get(connection_args, i); - const char *arg; - struct bt_config_connection *cfg_connection; - - ret = bt_value_string_get(arg_value, &arg); - BT_PUT(arg_value); - assert(ret == 0); - cfg_connection = cfg_connection_from_arg(arg); - if (!cfg_connection) { - snprintf(error_buf, error_buf_size, "Cannot parse --connect option's argument:\n %s\n", - arg); - goto error; - } - - g_ptr_array_add(cfg->cmd_data.run.connections, - cfg_connection); - } - - - ret = validate_connections(cfg, error_buf, error_buf_size); - if (ret) { - goto error; - } - - goto end; - -error: - ret = -1; - -end: - return ret; -}