From 361391d9ae07cabe408eacb4e06a5bb8522c43ee Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 8 Oct 2024 14:55:50 +0200 Subject: [PATCH] tree data REFACTOR recursive default node creation Avoid multiple schema/data tree traversals when creating default nodes. --- src/tree_data_internal.h | 20 +++++++++++++++++++- src/tree_data_new.c | 38 ++++++++++++++++++++++++++++---------- src/validation.c | 29 ++++++++++++++++++++--------- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h index b3a027c58..358528c6e 100644 --- a/src/tree_data_internal.h +++ b/src/tree_data_internal.h @@ -345,7 +345,25 @@ LY_ERR lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_l LY_VALUE_FORMAT format, void *val_prefix_data, uint32_t hints, struct lyd_node **node); /** - * @brief Check the existence and create any non-existing implicit siblings, recursively for the created nodes. + * @brief Check the existence and create any non-existing implicit children. + * + * @param[in] parent Parent of the potential default values, NULL for top-level siblings. + * @param[in,out] first First sibling. + * @param[in] sparent Schema parent of the siblings, NULL if schema of @p parent can be used. + * @param[in] mod Module of the default values, NULL for nested siblings. + * @param[in] node_when Optional set to add nodes with "when" conditions into. + * @param[in] node_types Optional set to add nodes with unresolved types into. + * @param[in] ext_node Optional set to add nodes with extension instance node callbacks into. + * @param[in] impl_opts Implicit options (@ref implicitoptions). + * @param[in,out] diff Validation diff. + * @return LY_ERR value. + */ +LY_ERR lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent, + const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node, + uint32_t impl_opts, struct lyd_node **diff); + +/** + * @brief Check the existence and create any non-existing implicit children, recursively for containers. * * @param[in] parent Parent of the potential default values, NULL for top-level siblings. * @param[in,out] first First sibling. diff --git a/src/tree_data_new.c b/src/tree_data_new.c index 1ecc9f3f5..cd5d63b76 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1876,7 +1876,7 @@ lyd_new_ext_path(struct lyd_node *parent, const struct lysc_ext_instance *ext, c } LY_ERR -lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent, +lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node, uint32_t impl_opts, struct lyd_node **diff) { @@ -1910,12 +1910,12 @@ lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struc node = lys_getnext_data(NULL, *first, NULL, iter, NULL); if (!node && ((struct lysc_node_choice *)iter)->dflt) { /* create default case data */ - LY_CHECK_RET(lyd_new_implicit_r(parent, first, &((struct lysc_node_choice *)iter)->dflt->node, + LY_CHECK_RET(lyd_new_implicit(parent, first, &((struct lysc_node_choice *)iter)->dflt->node, NULL, node_when, node_types, ext_node, impl_opts, diff)); } else if (node) { /* create any default data in the existing case */ assert(node->schema->parent->nodetype == LYS_CASE); - LY_CHECK_RET(lyd_new_implicit_r(parent, first, node->schema->parent, NULL, node_when, node_types, + LY_CHECK_RET(lyd_new_implicit(parent, first, node->schema->parent, NULL, node_when, node_types, ext_node, impl_opts, diff)); } break; @@ -1938,10 +1938,6 @@ lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struc /* add into diff */ LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff)); } - - /* create any default children */ - LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, node_when, node_types, - ext_node, impl_opts, diff)); } break; case LYS_LEAF: @@ -2016,6 +2012,28 @@ lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struc return LY_SUCCESS; } +LY_ERR +lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent, + const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node, + uint32_t impl_opts, struct lyd_node **diff) +{ + struct lyd_node *child; + + /* parent children */ + LY_CHECK_RET(lyd_new_implicit(parent, first, sparent, mod, node_when, node_types, ext_node, + impl_opts, diff)); + + LY_LIST_FOR(parent ? lyd_child_no_keys(parent) : *first, child) { + /* recursively for all the containers */ + if ((child->flags & LYD_DEFAULT) && (child->schema->nodetype == LYS_CONTAINER)) { + LY_CHECK_RET(lyd_new_implicit_r(child, lyd_node_child_p(child), NULL, mod, node_when, node_types, ext_node, + impl_opts, diff)); + } + } + + return LY_SUCCESS; +} + LIBYANG_API_DEF LY_ERR lyd_new_implicit_tree(struct lyd_node *tree, uint32_t implicit_options, struct lyd_node **diff) { @@ -2030,7 +2048,7 @@ lyd_new_implicit_tree(struct lyd_node *tree, uint32_t implicit_options, struct l LYD_TREE_DFS_BEGIN(tree, node) { if (node->schema && (node->schema->nodetype & LYD_NODE_INNER)) { - LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &node_when, NULL, + LY_CHECK_GOTO(ret = lyd_new_implicit(node, lyd_node_child_p(node), NULL, NULL, &node_when, NULL, NULL, implicit_options, diff), cleanup); } @@ -2105,14 +2123,14 @@ lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, } /* add all top-level defaults for this module */ - LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, &node_when, NULL, NULL, implicit_options, diff), + LY_CHECK_GOTO(ret = lyd_new_implicit(NULL, tree, NULL, module, &node_when, NULL, NULL, implicit_options, diff), cleanup); /* resolve when and remove any invalid defaults */ LY_CHECK_GOTO(ret = lyd_validate_unres(tree, module, 0, &node_when, LYXP_IGNORE_WHEN, NULL, NULL, NULL, NULL, 0, diff), cleanup); - /* process nested nodes */ + /* process top-level (and nested) nodes */ LY_LIST_FOR(*tree, root) { LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup); diff --git a/src/validation.c b/src/validation.c index a950c542b..4f91ab335 100644 --- a/src/validation.c +++ b/src/validation.c @@ -1782,7 +1782,7 @@ lyd_validate_subtree(struct lyd_node *root, struct ly_set *node_when, struct ly_ if (val_opts & LYD_VALIDATE_NO_DEFAULTS) { impl_opts |= LYD_IMPLICIT_NO_DEFAULTS; } - r = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, NULL, NULL, NULL, impl_opts, diff); + r = lyd_new_implicit(node, lyd_node_child_p(node), NULL, NULL, NULL, NULL, NULL, impl_opts, diff); LY_CHECK_ERR_GOTO(r, rc = r, cleanup); } @@ -1857,9 +1857,15 @@ lyd_validate(struct lyd_node **tree, const struct lys_module *module, const stru if (val_opts & LYD_VALIDATE_NO_DEFAULTS) { impl_opts |= LYD_IMPLICIT_NO_DEFAULTS; } - r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, validate_subtree ? NULL : node_when_p, - validate_subtree ? NULL : node_types_p, validate_subtree ? NULL : ext_node_p, impl_opts, diff); - LY_CHECK_ERR_GOTO(r, rc = r, cleanup); + if (validate_subtree) { + r = lyd_new_implicit(lyd_parent(*first2), first2, NULL, mod, NULL, NULL, NULL, impl_opts, diff); + LY_CHECK_ERR_GOTO(r, rc = r, cleanup); + } else { + /* descendants will not be validated, create them all */ + r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, node_when_p, node_types_p, ext_node_p, + impl_opts, diff); + LY_CHECK_ERR_GOTO(r, rc = r, cleanup); + } /* our first module node pointer may no longer be the first */ first = *first2; @@ -2069,17 +2075,22 @@ _lyd_validate_op(struct lyd_node *op_tree, struct lyd_node *op_node, const struc } if (int_opts & LYD_INTOPT_REPLY) { - /* add output children defaults */ - rc = lyd_new_implicit_r(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p, - ext_node_p, LYD_IMPLICIT_OUTPUT, diff); - LY_CHECK_GOTO(rc, cleanup); - if (validate_subtree) { + /* add output children defaults */ + rc = lyd_new_implicit(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p, + ext_node_p, LYD_IMPLICIT_OUTPUT, diff); + LY_CHECK_GOTO(rc, cleanup); + /* skip validating the operation itself, go to children directly */ LY_LIST_FOR(lyd_child(op_node), child) { rc = lyd_validate_subtree(child, node_when_p, node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff); LY_CHECK_GOTO(rc, cleanup); } + } else { + /* add output children defaults and their descendants */ + rc = lyd_new_implicit_r(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p, + ext_node_p, LYD_IMPLICIT_OUTPUT, diff); + LY_CHECK_GOTO(rc, cleanup); } } else { if (validate_subtree) {