diff --git a/include/maestro/env.h b/include/maestro/env.h index 0d95b73a21a19b4fbae924559b4183bcd904d61d..a8586cb7adf3cb722dc51ecf4d1ff49dbfecdb56 100644 --- a/include/maestro/env.h +++ b/include/maestro/env.h @@ -96,6 +96,11 @@ */ #define MSTRO_ENV_LOG_COLOR "MSTRO_LOG_COLOR" +/**@brief lists the set of Schemata (in order from left to right) that should be loaded after the maestro-core schema is loaded. + * If set,mstro_init will merge these onto the built-ins. Default: core + ecmwf +*/ +#define MSTRO_ENV_SCHEMA_LIST "MSTRO_SCHEMA_LIST" + /**@brief enable coloring of error log messages * * If set, enable coloring of error and warning messages. May not be a good idea if logging to syslog (see @ref MSTRO_LOG_DST). diff --git a/maestro/core.c b/maestro/core.c index 83c1fdfb718fb12a33c1711e5a80cf50812c52fc..85f7cbae072a6fe234476dffb18a604857eb8610 100644 --- a/maestro/core.c +++ b/maestro/core.c @@ -145,6 +145,72 @@ BAILOUT: /** minimum mlock() limit */ #define MSTRO_MIN_MEMLOCK (4*sizeof(g_component_descriptor)) + +mstro_status mstro_core_init__setup_schemata(void) +{ + + mstro_status status = MSTRO_OK; + + char * env_schema_list = getenv(MSTRO_ENV_SCHEMA_LIST); + + char *token; + + // parse and merge the builtin schemas first + DEBUG("Parsing Maestro core schema\n"); + status=mstro_schema_parse(MSTRO_SCHEMA_BUILTIN_YAML_CORE, + MSTRO_SCHEMA_BUILTIN_YAML_CORE_LEN, + &g_mstro_core_schema_instance); + if(status!=MSTRO_OK) { + ERR("Failed to parse built-in core schema\n"); + return status; + } + + DEBUG("Parsing ECMWF schema\n"); + mstro_schema ecmwf; + status=mstro_schema_parse(MSTRO_SCHEMA_BUILTIN_YAML_ECMWF, + MSTRO_SCHEMA_BUILTIN_YAML_ECMWF_LEN, + &ecmwf); + if(status!=MSTRO_OK) { + ERR("Failed to parse built-in ecmwf schema\n"); + return status; + } + status=mstro_schema_merge(g_mstro_core_schema_instance, ecmwf); + if(status!=MSTRO_OK) { + ERR("Failed to merge core and ECMWF schema\n"); + return status; + } + + // start reading user-defined schemas and merge them. + /* get the first token */ + token = strtok(env_schema_list, ":"); + + /* walk through other tokens */ + while( token != NULL ) + { + // parse a schema from the user + mstro_schema user_schema; + + DEBUG("Parsing user-defined schema\n"); + status=mstro_schema_parse_from_file(token, &user_schema); + + if(status!=MSTRO_OK) { + ERR("Failed to parse user_schema from file: %s \n", token); + return status; + } + // merge the schema + status=mstro_schema_merge(g_mstro_core_schema_instance, user_schema); + + if(status!=MSTRO_OK) { + ERR("Failed to merge core and user schema from file %s\n", token); + return status; + } + // read the next path + token = strtok(NULL, ":"); + } + + return status; +} + mstro_status mstro_core_init(const char *workflow_name, const char *component_name, @@ -197,29 +263,12 @@ mstro_core_init(const char *workflow_name, g_component_descriptor.component_name[MSTRO_WORKFLOW_NAME_MAX-1] = '\0'; strcpy(g_component_descriptor.version, mstro_version()); - status=mstro_schema_parse(MSTRO_SCHEMA_BUILTIN_YAML_CORE, - MSTRO_SCHEMA_BUILTIN_YAML_CORE_LEN, - &g_mstro_core_schema_instance); - if(status!=MSTRO_OK) { - ERR("Failed to parse built-in core schema\n"); - goto BAILOUT; - } - /* FIXME: this should not be here */ - DEBUG("Including ECMWF schema\n"); - mstro_schema ecmwf; - status=mstro_schema_parse(MSTRO_SCHEMA_BUILTIN_YAML_ECMWF, - MSTRO_SCHEMA_BUILTIN_YAML_ECMWF_LEN, - &ecmwf); - if(status!=MSTRO_OK) { - ERR("Failed to parse built-in ecmwf schema\n"); - goto BAILOUT; - } - status=mstro_schema_merge(g_mstro_core_schema_instance, ecmwf); + + status = mstro_core_init__setup_schemata(); if(status!=MSTRO_OK) { - ERR("Failed to merge core and ECMWF schema\n"); goto BAILOUT; } - + DEBUG("init %s/%s/% "PRIi64 " in thread %" PRIxPTR" complete\n", data->workflow_name, data->component_name, data->component_index, (intptr_t)pthread_self()); diff --git a/tests/check_declaration_seal.c b/tests/check_declaration_seal.c index b00a215d86f0b1f8a0b50106e23ac64930ad8796..d2347470f5e29ad7e8b0309b023c06186256c97f 100644 --- a/tests/check_declaration_seal.c +++ b/tests/check_declaration_seal.c @@ -133,3 +133,36 @@ CHEAT_TEST(cdo_declaration_seal_works, ) +/* put a path to user-defined schema*/ + +CHEAT_TEST(user_defined_schemas_works, + + putenv("MSTRO_SCHEMA_LIST=test_attributes.yaml"); + + cheat_assert(MSTRO_OK == mstro_init("Tests","DECLARE",0)); + + mstro_cdo cdo; + cheat_assert(MSTRO_OK ==mstro_cdo_declare("test cdo", MSTRO_ATTR_DEFAULT, &cdo)); + cheat_assert(MSTRO_OK ==mstro_cdo_attribute_set(cdo, ".maestro.test.t_1", "test value")); + cheat_assert(MSTRO_OK ==mstro_cdo_declaration_seal(cdo)); + + cheat_assert(MSTRO_OK ==mstro_cdo_offer(cdo)); + + cheat_assert(MSTRO_OK ==mstro_cdo_withdraw(cdo)); + cheat_assert(MSTRO_OK ==mstro_cdo_dispose(cdo)); + cheat_assert(MSTRO_OK == mstro_finalize()); + + ) + +/* put a path to user-defined schema with wrong path and wrong separators*/ + +CHEAT_TEST(user_defined_schemas_doesnot_exist, + + putenv("MSTRO_SCHEMA_LIST=bechmark_attributes.yaml"); + cheat_assert(MSTRO_OK != mstro_init("Tests","DECLARE",0)); + cheat_assert(MSTRO_FAIL == mstro_finalize()); + + ) + + + diff --git a/tests/test_attributes.yaml b/tests/test_attributes.yaml new file mode 100644 index 0000000000000000000000000000000000000000..68008c9aa1da68dd0df39002d20a627537a127f4 --- /dev/null +++ b/tests/test_attributes.yaml @@ -0,0 +1,16 @@ +# A user-defined schema. The minimum is name and version +schema-name: Test Attributes +schema-version: 0 + +schema-namespace: ".maestro.test." + +# attributes section is optional; if given it needs to have a sequence value +maestro-attributes: + +# Top-level attributes + + - key: "t_1" + type: str() + required: False + default: "" + documentation: Value length is the attribute size