Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

fbp meta types on conf files #927

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/bin/sol-fbp-runner/runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ search_fbp_file(struct runner *r, const char *basename)
char *fullpath;
uint16_t i;

fullpath = stat_fullpath(r->dir, basename);
if (fullpath)
return fullpath;

SOL_PTR_VECTOR_FOREACH_IDX (r->fbp_paths, p, i) {
fullpath = stat_fullpath(p, basename);
if (fullpath)
Expand Down Expand Up @@ -379,6 +375,8 @@ runner_new_from_file(
const char **options_strv,
struct sol_ptr_vector *fbps)
{
const struct sol_flow_resolver *resolver;
struct sol_flow_resolver resolver_with_paths;
struct runner *r;
const char *buf;
size_t size;
Expand All @@ -396,14 +394,26 @@ runner_new_from_file(
r->parser_client.data = r;
r->parser_client.read_file = read_file;

r->parser = sol_flow_parser_new(&r->parser_client, NULL);
resolver = sol_flow_get_default_resolver();
resolver_with_paths = *resolver;
resolver_with_paths.data = fbps;
r->parser = sol_flow_parser_new(&r->parser_client, &resolver_with_paths);
if (!r->parser)
goto error;

r->filename = filename;

r->dir = strdup(dirname(strdupa(filename)));
SOL_NULL_CHECK_GOTO(r->dir, error);
/* Ideally we would prepend it here so dirname of file is search
* before other directories passed as arguments for runner. But
* it should matter much since users shouldn't have name clashes
* and trust on this order to solve it. */
err = sol_ptr_vector_append(fbps, r->dir);
if (err < 0) {
errno = -err;
goto error;
}

r->basename = strdup(basename(strdupa(filename)));

Expand Down
171 changes: 161 additions & 10 deletions src/lib/flow/sol-flow-resolver-conffile.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@
#include <assert.h>
#include <dlfcn.h>
#include <limits.h>
#include <sys/stat.h>

#include "sol-conffile.h"
#include "sol-flow-internal.h"
#include "sol-flow-resolver.h"
#include "sol-flow-parser.h"
#include "sol-file-reader.h"
#include "sol-str-slice.h"
#include "sol-util.h"

Expand Down Expand Up @@ -107,6 +110,7 @@ resolver_conffile_clear_data(void)
}

const char MODULE_NAME_SEPARATOR = '/';
const char *META_TYPE_BEGIN = "fbp:";

static struct sol_str_slice
get_module_for_type(const char *type)
Expand Down Expand Up @@ -249,10 +253,145 @@ resolver_conffile_resolve_by_type_name(const char *id,
return 0;
}

static char *
stat_fullpath(const char *path, const char *basename)
{
int err;
struct stat s;
char *fullpath;

err = asprintf(&fullpath, "%s/%s", path, basename);
if (err < 0) {
errno = ENOMEM;
return NULL;
}

if (stat(fullpath, &s) == 0 && S_ISREG(s.st_mode))
return fullpath;

free(fullpath);
return NULL;
}

struct search_fbp_file_data {
struct sol_ptr_vector *fbp_paths;
struct sol_ptr_vector file_readers;
};

static char *
search_fbp_file(void *data, const char *basename)
{
struct search_fbp_file_data *search_data = data;
char *fullpath, *p;
int i;

SOL_PTR_VECTOR_FOREACH_IDX (search_data->fbp_paths, p, i) {
fullpath = stat_fullpath(p, basename);
if (fullpath)
return fullpath;
}

SOL_ERR("Couldn't find file '%s'", basename);
errno = EINVAL;
return NULL;
}

static int
read_file(void *data, const char *name, const char **buf, size_t *size)
{
struct search_fbp_file_data *search_data = data;
struct sol_file_reader *fr = NULL;
struct sol_str_slice slice;
char *path;
int err;

path = search_fbp_file(search_data, name);
if (!path) {
err = -errno;
goto error;
}

fr = sol_file_reader_open(path);
if (!fr) {
err = -errno;
SOL_DBG("Couldn't open input file '%s': %s", path,
sol_util_strerrora(errno));
goto error;
}

err = sol_ptr_vector_append(&search_data->file_readers, fr);
if (err < 0)
goto error;

free(path);
slice = sol_file_reader_get_all(fr);
*buf = slice.data;
*size = slice.len;
return 0;

error:
free(path);
if (fr)
sol_file_reader_close(fr);
return err;
}

static int
get_type_from_fbp(const char *id,
struct sol_flow_node_type const **node_type,
void *data)
{
const char *id_file = id + strlen(META_TYPE_BEGIN);
struct sol_flow_parser_client parser_client;
struct search_fbp_file_data search_data;
const struct sol_flow_node_type *type;
struct sol_flow_parser *parser;
struct sol_file_reader *fr;
const char *buf = NULL;
size_t size = 0;
int err, i;

SOL_DBG("Resolving type declared on '%s'.", id_file);

parser_client.api_version = SOL_FLOW_PARSER_CLIENT_API_VERSION;
parser_client.read_file = read_file;
parser_client.data = &search_data;

search_data.fbp_paths = data;
sol_ptr_vector_init(&search_data.file_readers);

parser = sol_flow_parser_new(&parser_client, NULL);
if (!parser)
return -EINVAL;

err = read_file(&search_data, id_file, &buf, &size);
if (err < 0)
goto read_fail;

type = sol_flow_parse_buffer(parser, buf, size, id_file);
if (!type) {
err = -ENOENT;
goto type_fail;
}

*node_type = type;

type_fail:
SOL_PTR_VECTOR_FOREACH_IDX (&search_data.file_readers, fr, i)
sol_file_reader_close(fr);
sol_ptr_vector_clear(&search_data.file_readers);

read_fail:
sol_flow_parser_del(parser);

return err;
}

static int
resolver_conffile_resolve_by_id(const char *id,
struct sol_flow_node_type const **node_type,
struct sol_flow_node_named_options *named_opts)
struct sol_flow_node_named_options *named_opts,
void *data)
{
const struct sol_flow_node_type *tmp_type;
const char **opts_strv = NULL;
Expand All @@ -274,20 +413,32 @@ resolver_conffile_resolve_by_id(const char *id,
r = 0;
}

/* TODO: is this needed given we already handle builtins from the outside? */
tmp_type = resolve_module_type_by_component(type_name, sol_flow_foreach_builtin_node_type);
if (!strncmp(META_TYPE_BEGIN, type_name, strlen(META_TYPE_BEGIN))) {
r = get_type_from_fbp(type_name, &tmp_type, data);
if (r < 0) {
SOL_DBG("could not resolve a type name for id='%s'", id);
goto end;
}
} else {
/* TODO: is this needed given we already handle builtins
* from the outside? */
tmp_type = resolve_module_type_by_component(type_name,
sol_flow_foreach_builtin_node_type);

if (!tmp_type) {
tmp_type = _resolver_conffile_get_module(type_name);
if (!tmp_type) {
r = -EINVAL;
SOL_DBG("could not resolve a node module for Type='%s'", type_name);
goto end;
tmp_type = _resolver_conffile_get_module(type_name);
if (!tmp_type) {
r = -EINVAL;
SOL_DBG("could not resolve a node module for Type='%s'",
type_name);
goto end;
}
}
}

if (opts_strv) {
r = sol_flow_node_named_options_init_from_strv(named_opts, tmp_type, opts_strv);
r = sol_flow_node_named_options_init_from_strv(named_opts, tmp_type,
opts_strv);
if (r < 0)
goto end;
} else
Expand All @@ -305,7 +456,7 @@ resolver_conffile_resolve(void *data, const char *id,
{
if (strchr(id, MODULE_NAME_SEPARATOR))
return resolver_conffile_resolve_by_type_name(id, node_type, named_opts);
return resolver_conffile_resolve_by_id(id, node_type, named_opts);
return resolver_conffile_resolve_by_id(id, node_type, named_opts, data);
}

static const struct sol_flow_resolver _resolver_conffile = {
Expand Down