tree schema BUGFIX separate single-item dep set creation
diff --git a/src/context.c b/src/context.c
index 922bb96..69c3b77 100644
--- a/src/context.c
+++ b/src/context.c
@@ -208,8 +208,8 @@
/* create dep set for the module and mark all the modules that will be (re)compiled */
LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &unres.dep_sets, mod), cleanup);
- /* (re)compile the whole dep set */
- LY_CHECK_GOTO(ret = lys_compile_dep_set_r(ctx, unres.dep_sets.objs[0], &unres), cleanup);
+ /* (re)compile the whole dep set (other dep sets will have no modules marked for compilation) */
+ LY_CHECK_GOTO(ret = lys_compile_depset_all(ctx, &unres), cleanup);
}
cleanup:
@@ -505,7 +505,6 @@
ly_ctx_compile(struct ly_ctx *ctx)
{
LY_ERR ret = LY_SUCCESS;
- uint32_t i;
struct lys_glob_unres unres = {0};
LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
@@ -514,9 +513,7 @@
LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &unres.dep_sets, NULL), cleanup);
/* (re)compile all the dep sets */
- for (i = 0; i < unres.dep_sets.count; ++i) {
- LY_CHECK_GOTO(ret = lys_compile_dep_set_r(ctx, unres.dep_sets.objs[i], &unres), cleanup);
- }
+ LY_CHECK_GOTO(ret = lys_compile_depset_all(ctx, &unres), cleanup);
cleanup:
if (ret) {
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 7fed48f..2efc2e1 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -1431,8 +1431,16 @@
ly_set_erase(&unres->ds_unres.disabled, NULL);
}
-LY_ERR
-lys_compile_dep_set_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres)
+/**
+ * @brief Compile all flagged modules in a dependency set, recursively if recompilation is needed.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] dep_set Dependency set to compile.
+ * @param[in,out] unres Global unres to use.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres)
{
LY_ERR ret = LY_SUCCESS;
struct lys_module *mod;
@@ -1459,7 +1467,7 @@
if (ret == LY_ERECOMPILE) {
/* new module is implemented, discard current dep set unres and recompile the whole dep set */
lys_compile_unres_depset_erase(ctx, unres);
- return lys_compile_dep_set_r(ctx, dep_set, unres);
+ return lys_compile_depset_r(ctx, dep_set, unres);
} else if (ret) {
/* error */
goto cleanup;
@@ -1476,6 +1484,18 @@
return ret;
}
+LY_ERR
+lys_compile_depset_all(struct ly_ctx *ctx, struct lys_glob_unres *unres)
+{
+ uint32_t i;
+
+ for (i = 0; i < unres->dep_sets.count; ++i) {
+ LY_CHECK_RET(lys_compile_depset_r(ctx, unres->dep_sets.objs[i], unres));
+ }
+
+ return LY_SUCCESS;
+}
+
/**
* @brief Finish compilation of all the module unres sets in a compile context.
*
diff --git a/src/schema_compile.h b/src/schema_compile.h
index d31cbe4..2536fb4 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -75,7 +75,7 @@
* @brief Unres structure global for compilation.
*/
struct lys_glob_unres {
- struct ly_set dep_sets; /**< set of dependency sets of modules, see ::lys_compile_dep_set_r() */
+ struct ly_set dep_sets; /**< set of dependency sets of modules, see ::lys_compile_depset_all() */
struct ly_set implementing; /**< set of YANG schemas being atomically implemented (compiled); the first added
module is always the explicitly implemented module, the other ones are dependencies */
struct ly_set creating; /**< set of YANG schemas being atomically created (parsed); it is a subset of implemented
@@ -280,11 +280,10 @@
* - new implemented module augments, deviations
*
* @param[in] ctx libyang context.
- * @param[in] dep_set Dependency set to compile.
* @param[in,out] unres Global unres to use.
* @return LY_ERR value.
*/
-LY_ERR lys_compile_dep_set_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres);
+LY_ERR lys_compile_depset_all(struct ly_ctx *ctx, struct lys_glob_unres *unres);
/**
* @brief Implement a single module. Does not actually compile, only marks to_compile!
diff --git a/src/tree_schema.c b/src/tree_schema.c
index cbd2e64..5582fce 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -866,26 +866,21 @@
LY_ARRAY_COUNT_TYPE u, v;
ly_bool found;
- if (!ly_set_contains(ctx_set, mod, &i)) {
- /* it was already processed */
- return LY_SUCCESS;
- }
-
- /* remove it from the set, we are processing it now */
- ly_set_rm_index(ctx_set, i, NULL);
-
if (!lys_has_compiled(mod) || (mod->compiled && !lys_has_recompiled(mod))) {
- if (!dep_set->count) {
- /* add a new dependent module into the dep set */
- LY_CHECK_RET(ly_set_add(dep_set, mod, 1, NULL));
- }
-
+ /* is already in a separate dep set */
if (!lys_has_groupings(mod)) {
- /* break the dep set here, nothing to compile or recompile and no groupings, no modules will depend
- * on this one */
+ /* break the dep set here, no modules depend on this one */
return LY_SUCCESS;
}
} else {
+ if (!ly_set_contains(ctx_set, mod, &i)) {
+ /* it was already processed */
+ return LY_SUCCESS;
+ }
+
+ /* remove it from the set, we are processing it now */
+ ly_set_rm_index(ctx_set, i, NULL);
+
/* add a new dependent module into the dep set */
LY_CHECK_RET(ly_set_add(dep_set, mod, 1, NULL));
}
@@ -893,11 +888,27 @@
/* process imports of the module and submodules */
imports = mod->parsed->imports;
LY_ARRAY_FOR(imports, u) {
- LY_CHECK_RET(lys_unres_dep_sets_create_mod_r(imports[u].module, ctx_set, dep_set));
+ mod2 = imports[u].module;
+ if (!lys_has_compiled(mod2) || (mod2->compiled && !lys_has_recompiled(mod2))) {
+ if (!lys_has_groupings(mod2)) {
+ /* break the dep set here, no modules depend on this one */
+ continue;
+ }
+ }
+
+ LY_CHECK_RET(lys_unres_dep_sets_create_mod_r(mod2, ctx_set, dep_set));
}
LY_ARRAY_FOR(mod->parsed->includes, v) {
imports = mod->parsed->includes[v].submodule->imports;
LY_ARRAY_FOR(imports, u) {
+ mod2 = imports[u].module;
+ if (!lys_has_compiled(mod2) || (mod2->compiled && !lys_has_recompiled(mod2))) {
+ if (!lys_has_groupings(mod2)) {
+ /* break the dep set here, no modules depend on this one */
+ continue;
+ }
+ }
+
LY_CHECK_RET(lys_unres_dep_sets_create_mod_r(imports[u].module, ctx_set, dep_set));
}
}
@@ -932,6 +943,11 @@
}
if (found) {
+ if (!lys_has_compiled(mod2) || (mod2->compiled && !lys_has_recompiled(mod2))) {
+ /* break the dep set here, no modules depend on this one (groupings were handled as imports) */
+ continue;
+ }
+
LY_CHECK_RET(lys_unres_dep_sets_create_mod_r(mod2, ctx_set, dep_set));
}
}
@@ -939,6 +955,43 @@
return LY_SUCCESS;
}
+/**
+ * @brief Add all simple modules (that have nothing to (re)compile) into separate dep sets.
+ *
+ * @param[in,out] ctx_set Set with all not-yet-processed modules.
+ * @param[in,out] main_set Set of dependency module sets.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_unres_dep_sets_create_single(struct ly_set *ctx_set, struct ly_set *main_set)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lys_module *m;
+ uint32_t i = 0;
+ struct ly_set *dep_set = NULL;
+
+ while (i < ctx_set->count) {
+ m = ctx_set->objs[i];
+ if (!lys_has_compiled(m) || (m->compiled && !lys_has_recompiled(m))) {
+ /* remove it from the set, we are processing it now */
+ ly_set_rm_index(ctx_set, i, NULL);
+
+ /* this module can be in a separate dep set (but there still may be modules importing this one
+ * that depend on imports of this one in case it defines groupings) */
+ LY_CHECK_GOTO(ret = ly_set_new(&dep_set), cleanup);
+ LY_CHECK_GOTO(ret = ly_set_add(dep_set, m, 1, NULL), cleanup);
+ LY_CHECK_GOTO(ret = ly_set_add(main_set, dep_set, 1, NULL), cleanup);
+ dep_set = NULL;
+ } else {
+ ++i;
+ }
+ }
+
+cleanup:
+ ly_set_free(dep_set, NULL);
+ return ret;
+}
+
LY_ERR
lys_unres_dep_sets_create(struct ly_ctx *ctx, struct ly_set *main_set, struct lys_module *mod)
{
@@ -951,6 +1004,14 @@
/* start with a duplicate set of modules that we will remove from */
LY_CHECK_GOTO(ret = ly_set_dup(&ctx->list, NULL, &ctx_set), cleanup);
+ /* first create all dep sets with single modules */
+ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create_single(ctx_set, main_set), cleanup);
+
+ if (mod && !ly_set_contains(ctx_set, mod, NULL)) {
+ /* dep set for this module has already been created, nothing else to do */
+ goto cleanup;
+ }
+
while (ctx_set->count) {
/* create new dep set */
LY_CHECK_GOTO(ret = ly_set_new(&dep_set), cleanup);
@@ -1089,8 +1150,8 @@
/* create dep set for the module and mark all the modules that will be (re)compiled */
LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(mod->ctx, &unres.dep_sets, mod), cleanup);
- /* (re)compile the whole dep set */
- LY_CHECK_GOTO(ret = lys_compile_dep_set_r(mod->ctx, unres.dep_sets.objs[0], &unres), cleanup);
+ /* (re)compile the whole dep set (other dep sets will have no modules marked for compilation) */
+ LY_CHECK_GOTO(ret = lys_compile_depset_all(mod->ctx, &unres), cleanup);
}
cleanup:
@@ -1675,8 +1736,8 @@
/* create dep set for the module and mark all the modules that will be (re)compiled */
LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &unres.dep_sets, mod), cleanup);
- /* (re)compile the whole dep set */
- LY_CHECK_GOTO(ret = lys_compile_dep_set_r(ctx, unres.dep_sets.objs[0], &unres), cleanup);
+ /* (re)compile the whole dep set (other dep sets will have no modules marked for compilation) */
+ LY_CHECK_GOTO(ret = lys_compile_depset_all(ctx, &unres), cleanup);
}
cleanup: