Skip to content

Commit

Permalink
tree data REFACTOR recursive default node creation
Browse files Browse the repository at this point in the history
Avoid multiple schema/data tree traversals when
creating default nodes.
  • Loading branch information
michalvasko committed Oct 8, 2024
1 parent 0af8370 commit 361391d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 20 deletions.
20 changes: 19 additions & 1 deletion src/tree_data_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
38 changes: 28 additions & 10 deletions src/tree_data_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);

Expand Down
29 changes: 20 additions & 9 deletions src/validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 361391d

Please sign in to comment.