context FEATURE allow explicit context compilation
diff --git a/src/context.c b/src/context.c
index 6aa42c1..e93db25 100644
--- a/src/context.c
+++ b/src/context.c
@@ -467,6 +467,44 @@
return ly_ctx_new_yl_common(search_dir, data, format, options, lyd_parse_data_mem, ctx);
}
+API LY_ERR
+ly_ctx_compile(struct ly_ctx *ctx)
+{
+ struct lys_module *mod;
+ uint32_t i;
+ ly_bool recompile = 0;
+
+ LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
+
+ for (i = 0; i < ctx->list.count; ++i) {
+ mod = ctx->list.objs[i];
+ if (mod->to_compile) {
+ /* if was not implemented, will be */
+ mod->implemented = 1;
+
+ recompile = 1;
+ }
+ }
+
+ if (!recompile) {
+ /* no recompilation needed */
+ return LY_SUCCESS;
+ }
+
+ /* recompile */
+ LY_CHECK_RET(lys_recompile(ctx, 0));
+
+ /* everything is fine, clear the flags */
+ for (i = 0; i < ctx->list.count; ++i) {
+ mod = ctx->list.objs[i];
+ if (mod->to_compile) {
+ mod->to_compile = 0;
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
API uint16_t
ly_ctx_get_options(const struct ly_ctx *ctx)
{
@@ -477,15 +515,16 @@
API LY_ERR
ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option)
{
- LY_ERR lyrc;
+ LY_ERR lyrc = LY_SUCCESS;
LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL);
LY_CHECK_ERR_RET(option & LY_CTX_NO_YANGLIBRARY, LOGARG(ctx, option), LY_EINVAL);
- lyrc = LY_SUCCESS;
if (!(ctx->flags & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) {
ctx->flags |= LY_CTX_SET_PRIV_PARSED;
- if ((lyrc = lys_recompile(ctx, 0))) {
+ /* recompile to set the priv pointers */
+ lyrc = lys_recompile(ctx, 0);
+ if (lyrc) {
ly_ctx_unset_options(ctx, LY_CTX_SET_PRIV_PARSED);
}
}
diff --git a/src/context.h b/src/context.h
index f540bd4..f208c95 100644
--- a/src/context.h
+++ b/src/context.h
@@ -188,6 +188,12 @@
Setting this option by ::ly_ctx_set_options() may result in context recompilation.
Resetting this option by ::ly_ctx_unset_options() cause that private
objects will be set to NULL. */
+#define LY_CTX_EXPLICIT_COMPILE 0x80 /**< If this flag is set, the compiled modules and their schema nodes are
+ not automatically updated (compiled) on any context changes. In other words, they do
+ not immediately take effect. To do that, call ::ly_ctx_compile(). Changes
+ requiring compilation include adding new modules, changing their features,
+ and implementing parsed-only modules. This option allows efficient compiled
+ context creation without redundant recompilations. */
/** @} contextoptions */
@@ -261,6 +267,15 @@
LY_ERR ly_ctx_new_ylmem(const char *search_dir, const char *data, LYD_FORMAT format, int options, struct ly_ctx **ctx);
/**
+ * @brief Compile (recompile) the context applying all the performed changes after the last context compilation.
+ * Should be used only if ::LY_CTX_EXPLICIT_COMPILE option is set, has no effect otherwise.
+ *
+ * @param[in] ctx Context to compile.
+ * @return LY_ERR return value.
+ */
+LY_ERR ly_ctx_compile(struct ly_ctx *ctx);
+
+/**
* @brief Add the search path into libyang context
*
* To reset search paths set in the context, use ::ly_ctx_unset_searchdir() and then
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 97bbe2a..89c97ad 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -800,6 +800,12 @@
assert(!mod->implemented);
+ if (mod->ctx->flags & LY_CTX_EXPLICIT_COMPILE) {
+ /* do not compile the module yet */
+ mod->to_compile = 1;
+ return LY_SUCCESS;
+ }
+
/* we have module from the current context */
m = ly_ctx_get_module_implemented(mod->ctx, mod->name);
if (m) {
@@ -843,8 +849,14 @@
return r;
}
- /* full recompilation */
- return lys_recompile(mod->ctx, 1);
+ if (mod->ctx->flags & LY_CTX_EXPLICIT_COMPILE) {
+ /* just mark the module as changed */
+ mod->to_compile = 1;
+ return LY_SUCCESS;
+ } else {
+ /* full recompilation */
+ return lys_recompile(mod->ctx, 1);
+ }
}
/* implement this module and any other required modules, recursively */
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 564be73..1c4f79f 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -2316,6 +2316,8 @@
struct lys_module **deviated_by; /**< List of modules that deviate this module ([sized array](@ref sizedarrays)) */
ly_bool implemented; /**< flag if the module is implemented, not just imported */
+ ly_bool to_compile; /**< flag marking a module that was changed but not (re)compiled, see
+ ::LY_CTX_EXPLICIT_COMPILE. */
uint8_t latest_revision; /**< flag to mark the latest available revision:
1 - the latest revision in searchdirs was not searched yet and this is the
latest revision in the current context