SOL_API struct sol_flow_node * sol_flow_node_new(struct sol_flow_node *parent, const char *id, const struct sol_flow_node_type *type, const struct sol_flow_node_options *options) { struct sol_flow_node *node; int err; bool free_opts = false; SOL_NULL_CHECK(type, NULL); SOL_FLOW_NODE_TYPE_API_CHECK(type, SOL_FLOW_NODE_TYPE_API_VERSION, NULL); node = calloc(1, sizeof(*node) + type->data_size); SOL_NULL_CHECK(node, NULL); if (!options) { options = sol_flow_node_get_options(type, NULL); free_opts = true; } err = sol_flow_node_init(node, parent, id, type, options); if (err < 0) { free(node); node = NULL; errno = -err; } if (free_opts) sol_flow_node_free_options(type, (struct sol_flow_node_options *)options); return node; }
SOL_API struct sol_flow_node * sol_flow_node_new(struct sol_flow_node *parent, const char *id, const struct sol_flow_node_type *type, const struct sol_flow_node_options *options) { struct sol_flow_node *node; int err; SOL_NULL_CHECK(type, NULL); SOL_FLOW_NODE_TYPE_API_CHECK(type, SOL_FLOW_NODE_TYPE_API_VERSION, NULL); node = calloc(1, sizeof(*node) + type->data_size); SOL_NULL_CHECK(node, NULL); if (!options) options = type->default_options; if (!options) options = &sol_flow_node_options_empty; err = sol_flow_node_init(node, parent, id, type, options); if (err < 0) { free(node); node = NULL; errno = -err; } return node; }
static int flow_node_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct flow_static_type *type; struct flow_static_data *fsd; const struct sol_flow_static_node_spec *spec; char *node_storage_it; int r, i; type = (struct flow_static_type *)node->type; fsd = data; fsd->nodes = calloc(type->node_count, sizeof(struct sol_flow_node *)); fsd->node_storage = calloc(1, type->node_storage_size); if (!fsd->nodes || !fsd->node_storage) { r = -ENOMEM; goto error_alloc; } /* Assure flow_send_idle()'s timeout is the first registered, so * that timeouts coming from nodes' init/open functions and that * may produce packets will always have them delivered */ r = flow_delay_send(node, fsd); SOL_INT_CHECK(r, < 0, r); sol_list_init(&fsd->delayed_packets); /* Set all pointers before calling nodes methods */ node_storage_it = fsd->node_storage; for (spec = type->node_specs, i = 0; spec->type != NULL; spec++, i++) { struct sol_flow_node *child_node = (struct sol_flow_node *)node_storage_it; fsd->nodes[i] = child_node; child_node->parent_data = INT_TO_PTR(i); node_storage_it += calc_node_size(spec); } for (spec = type->node_specs, i = 0; spec->type != NULL; spec++, i++) { struct sol_flow_node *child_node = fsd->nodes[i]; struct sol_flow_node_options *child_opts; child_opts = sol_flow_node_get_options(spec->type, spec->opts); if (!child_opts) { SOL_WRN("failed to get options for node #%u, type=%p: %s", (unsigned)(spec - type->node_specs), spec->type, sol_util_strerrora(errno)); } if (type->child_opts_set) type->child_opts_set(i, options, child_opts); r = sol_flow_node_init(child_node, node, spec->name, spec->type, child_opts); sol_flow_node_free_options(spec->type, child_opts); if (r < 0) { SOL_WRN("failed to init node #%u, type=%p, opts=%p: %s", (unsigned)(spec - type->node_specs), spec->type, spec->opts, sol_util_strerrora(-r)); goto error_nodes; } } r = connect_nodes(type, fsd); if (r < 0) goto error_conns; return 0; error_conns: error_nodes: /* Skip the failed index, since it doesn't need fini. */ for (i--; i >= 0; i--) sol_flow_node_fini(fsd->nodes[i]); error_alloc: free(fsd->node_storage); free(fsd->nodes); return r; }