Пример #1
0
static void
create_seconds(void)
{
    const struct sol_flow_node_type **type;
    struct sol_flow_node_named_options named_opts = {};
    const char *strv_opts[] = {
        "send_initial_packet=1",
        NULL
    };
    struct sol_flow_node_options *opts;
    int err;

    err = sol_flow_get_node_type("wallclock",
        SOL_FLOW_NODE_TYPE_WALLCLOCK_SECOND, &type);
    if (err < 0) {
        fputs("could not find type: wallclock/second\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    seconds_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED");
    if (seconds_port_enabled == UINT16_MAX) {
        fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }
    seconds_port_out = sol_flow_node_find_port_out(*type, "OUT");
    if (seconds_port_out == UINT16_MAX) {
        fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts);
    if (err < 0) {
        fputs("could not parse options for wallclock/second\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    err = sol_flow_node_options_new(*type, &named_opts, &opts);
    sol_flow_node_named_options_fini(&named_opts);
    if (err < 0) {
        fputs("could not create options for wallclock/second\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    seconds = sol_flow_single_new("seconds", *type, opts,
        SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_enabled),
        SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_out),
        on_seconds_packet, NULL);
    sol_flow_node_options_del(*type, opts);
}
Пример #2
0
static void
startup(void)
{
    const struct sol_flow_node_type **console_type;

    if (sol_flow_get_node_type("console", SOL_FLOW_NODE_TYPE_CONSOLE, &console_type) < 0)
        return;

    /*
     * Since these symbols will be relocated in runtime, we can't
     * initialize them in the vector initialization, we must assign
     * them in runtime.
     */
    nodes[0 /* reader */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER;
    nodes[1 /* logic */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_LOGIC;
    nodes[2 /* writer */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_WRITER;
    nodes[3 /* console */].type = *console_type;

    flow = sol_flow_static_new(NULL, nodes, conns);
}
Пример #3
0
static void
create_minutes(void)
{
    const struct sol_flow_node_type **type;
    struct sol_flow_node_named_options named_opts = {};
    const char *strv_opts[] = {
        "send_initial_packet=1",
        NULL
    };
    struct sol_flow_node_options *opts;
    int err;

    /* Resolves the type based on its name. This will take care of
     * built-in modules and external modules, loading on demand as
     * required. This macro also handles static-compiles, so the
     * second parameter is the C symbol to be used in such case.
     */
    err = sol_flow_get_node_type("wallclock",
        SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE, &type);
    if (err < 0) {
        fputs("could not find type: wallclock/minute\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    /* For efficiency matters Soletta doesn't work with port names,
     * rather using port indexes. If
     * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, then we can resolve
     * strings to numbers, otherwise it is required to check the port
     * numbers, which are often available in the header file such as
     * sol-flow/wallclock.h such as
     * SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE__OUT__OUT.
     */
    minutes_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED");
    if (minutes_port_enabled == UINT16_MAX) {
        fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }
    minutes_port_out = sol_flow_node_find_port_out(*type, "OUT");
    if (minutes_port_out == UINT16_MAX) {
        fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    /* wallclock/minute takes a boolean option send_initial_packet.
     * We have couple of options to create it:
     *
     * 1 - include sol-flow/wallclock.h, declare a variable of type
     *     struct sol_flow_node_type_wallclock_minute_options and fill
     *     its members. This requires sol-flow/wallclock.h to be
     *     avaiable, but is more efficient since goes straight to the
     *     point, no parsing or memory allocations. It would look
     *     like:
     *
     *        #include <sol-flow/wallclock.h>
     *
     *        struct sol_flow_node_type_wallclock_minute_options opts =
     *           SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE_OPTIONS_DEFAULTS(
     *              .send_initial_packet = true);
     *
     * 2 - access type->options_size,
     *     type->default_options and
     *     type->description->options and manually
     *     create the structure in runtime. This demands
     *     SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, but may be useful
     *     when converting from a different representation, like a
     *     language binding such as JavaScript or Python where one can
     *     get an object, hashmap or dictionary and convert straight
     *     to the C structure needed by the flow node type.
     *
     * 3 - use helper sol_flow_node_named_options_init_from_strv() and
     *     sol_flow_node_options_new(), giving it an array of
     *     "key=value" strings. It will do the work described in #2
     *     for us, thus also depends on
     *     SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED.
     *
     * We'll use approach #3 since it is simpler. Language bindings
     * should go with option #2 and those that want to squeeze the
     * size and get performance should consider #1.
     */
    err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts);
    if (err < 0) {
        fputs("could not parse options for wallclock/minute\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    /* convert the named options in the actual options structure */
    err = sol_flow_node_options_new(*type, &named_opts, &opts);
    sol_flow_node_named_options_fini(&named_opts);
    if (err < 0) {
        fputs("could not create options for wallclock/minute\n", stderr);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    /* Build the single node wrapping the wanted 'wallclock/minute'.
     * For most matters the single node behaves like the inner node,
     * it will copy the descriptions and options.
     *
     * The difference is that if you call sol_flow_send_packet() on
     * its input ports, it will forward the packet to the inner
     * node. Likewise, packets originated at the outgoing ports of the
     * inner node will be delivered through the process callback
     * (on_packet()) provided to the single node.
     *
     * Note that ports you want to send (in) or receive (out) packets
     * must be connected with the connected_ports_in and
     * connected_ports_out parameters, or later with
     * sol_flow_single_port_in_connect() and
     * sol_flow_single_port_out_connect().
     */
    minutes = sol_flow_single_new("minutes", *type, opts,
        SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_enabled),
        SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_out),
        on_minutes_packet, NULL);
    sol_flow_node_options_del(*type, opts);
}