static void flow_node_close(struct sol_flow_node *node, void *data) { struct flow_static_type *type = (struct flow_static_type *)node->type; struct flow_static_data *fsd = data; int i; if (fsd->delay_send) sol_timeout_del(fsd->delay_send); while (!sol_list_is_empty(&fsd->delayed_packets)) { struct delayed_packet *dp; struct sol_list *itr = fsd->delayed_packets.next; dp = SOL_LIST_GET_CONTAINER(itr, struct delayed_packet, list); sol_list_remove(itr); sol_flow_packet_del(dp->packet); free(dp); } teardown_connections(type, fsd); for (i = type->node_count - 1; i >= 0; i--) sol_flow_node_fini(fsd->nodes[i]); free(fsd->node_storage); free(fsd->nodes); if (type->owned_by_node) sol_flow_static_del_type(&type->base.base); }
SOL_API void sol_flow_node_del(struct sol_flow_node *node) { SOL_FLOW_NODE_CHECK(node); sol_flow_node_fini(node); free(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; }