static void flow_send_do(struct sol_flow_node *flow, struct flow_static_data *fsd, uint16_t src_idx, uint16_t source_out_port_idx, struct sol_flow_packet *packet) { struct flow_static_type *type = (struct flow_static_type *)flow->type; const struct sol_flow_static_conn_spec *spec; unsigned int i; bool is_error_packet, dispatched; is_error_packet = sol_flow_packet_get_type(packet) == SOL_FLOW_PACKET_TYPE_ERROR; dispatched = false; for (i = type->node_infos[src_idx].first_conn_idx, spec = type->conn_specs + i; spec->src == src_idx; spec++, i++) { const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *dst; struct conn_info *ci; if (spec->src_port != source_out_port_idx) continue; dst = fsd->nodes[spec->dst]; dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); ci = &type->conn_infos[i]; dispatch_process(dst, spec->dst_port, ci->in_conn_id, dst_port_type, packet); dispatched = true; } if (type->ports_out_count > 0) { const struct sol_flow_static_port_spec *pspec; uint16_t exported_out; for (pspec = type->exported_out_specs, exported_out = 0; pspec->node < UINT16_MAX; pspec++, exported_out++) { if (pspec->node == src_idx && pspec->port == source_out_port_idx) { /* Export the packet. Note that ownership of packet * will pass to the send() function. */ sol_flow_send_packet(flow, exported_out, packet); return; } } } if (is_error_packet && !dispatched) { const char *msg; int code; if (sol_flow_packet_get_error(packet, &code, &msg) == 0) { SOL_WRN("Error packet \'%d (%s)\' sent from \'%s (%p)\' was not handled", code, msg, flow->id, flow); } } sol_flow_packet_del(packet); }
ReturnCode cell::process() { configure(); //trigger all parameter change callbacks... tendrils::iterator begin = parameters.begin(), end = parameters.end(); while (begin != end) { try { begin->second->notify(); } catch (const std::exception& e) { ECTO_TRACE_EXCEPTION("const std::exception& outside of CATCH ALL"); BOOST_THROW_EXCEPTION(except::CellException() << except::type(name_of(typeid(e))) << except::what(e.what()) << except::cell_name(name()) << except::function_name(__FUNCTION__) << except::when("While triggering param change callbacks")) ; } ++begin; } try { try { const ReturnCode rc = dispatch_process(inputs, outputs); return rc; } catch (const boost::thread_interrupted&) { ECTO_TRACE_EXCEPTION("const boost::thread_interrupted&, returning QUIT instead of rethrow"); return ecto::QUIT; } } CATCH_ALL() }
static int connect_nodes(struct flow_static_type *type, struct flow_static_data *fsd) { const struct sol_flow_static_conn_spec *spec; int i, r; for (i = 0, spec = type->conn_specs; i < type->conn_count; i++, spec++) { const struct sol_flow_port_type_out *src_port_type; const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *src, *dst; struct conn_info *ci; struct sol_flow_packet *packet = NULL; src = fsd->nodes[spec->src]; dst = fsd->nodes[spec->dst]; ci = &type->conn_infos[i]; src_port_type = sol_flow_node_type_get_port_out(src->type, spec->src_port); dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); SOL_FLOW_PORT_TYPE_OUT_API_CHECK(src_port_type, SOL_FLOW_PORT_TYPE_OUT_API_VERSION, -EINVAL); SOL_FLOW_PORT_TYPE_IN_API_CHECK(dst_port_type, SOL_FLOW_PORT_TYPE_IN_API_VERSION, -EINVAL); if (!src_port_type->packet_type) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Invalid packet type for source port"); return -EINVAL; } if (!dst_port_type->packet_type) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Invalid packet type for destination port"); return -EINVAL; } if (!match_packets(src_port_type->packet_type, dst_port_type->packet_type)) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error matching source and destination packet types: %s != %s: %s", src_port_type->packet_type->name, dst_port_type->packet_type->name, sol_util_strerrora(EINVAL)); r = -EINVAL; goto dispatch_error; } r = dispatch_connect_out(src, spec->src_port, ci->out_conn_id, src_port_type); if (r < 0) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error connecting source: %s", sol_util_strerrora(-r)); if (packet) sol_flow_packet_del(packet); goto dispatch_error; } r = dispatch_connect_in(dst, spec->dst_port, ci->in_conn_id, dst_port_type); if (r < 0) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error connecting destination: %s", sol_util_strerrora(-r)); dispatch_disconnect_out(src, spec->src_port, ci->out_conn_id, src_port_type); if (packet) sol_flow_packet_del(packet); goto dispatch_error; } inspector_did_connect_port(src, spec->src_port, ci->out_conn_id, dst, spec->dst_port, ci->in_conn_id); if (!packet) continue; dispatch_process(dst, spec->dst_port, ci->in_conn_id, dst_port_type, (const struct sol_flow_packet *)packet); sol_flow_packet_del(packet); } SOL_DBG("Making %u connections.", i); return 0; dispatch_error: /* Dispatch disconnections in reverse order. Skip current failed * iteration since it was handled inside the loop. */ i--; spec--; for (; i >= 0; i--, spec--) { const struct sol_flow_port_type_out *src_port_type; const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *src, *dst; struct conn_info *ci; src = fsd->nodes[spec->src]; dst = fsd->nodes[spec->dst]; ci = &type->conn_infos[i]; dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); dispatch_disconnect_in(dst, spec->dst_port, ci->in_conn_id, dst_port_type); src_port_type = sol_flow_node_type_get_port_out(src->type, spec->src_port); dispatch_disconnect_out(src, spec->src_port, ci->out_conn_id, src_port_type); } return r; }