tree data UPDATE support for milti-target leafref links (#2161)
* Adding support for multiple leafref target nodes
diff --git a/src/tree_data.c b/src/tree_data.c
index ebe7eaf..8a6de8a 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -3316,9 +3316,9 @@
LY_ERR
lyd_link_leafref_node(const struct lyd_node_term *node, const struct lyd_node_term *leafref_node)
{
- LY_ARRAY_COUNT_TYPE u;
const struct lyd_node_term **item = NULL;
struct lyd_leafref_links_rec *rec;
+ LY_ARRAY_COUNT_TYPE u;
assert(node);
assert(leafref_node);
@@ -3327,6 +3327,7 @@
return LY_EDENIED;
}
+ /* add leafref node into the list of target node */
LY_CHECK_RET(lyd_get_or_create_leafref_links_record(node, &rec, 1));
LY_ARRAY_FOR(rec->leafref_nodes, u) {
if (rec->leafref_nodes[u] == leafref_node) {
@@ -3336,8 +3337,18 @@
LY_ARRAY_NEW_RET(LYD_CTX(node), rec->leafref_nodes, item, LY_EMEM);
*item = leafref_node;
+
+ /* add target node into the list of leafref node*/
LY_CHECK_RET(lyd_get_or_create_leafref_links_record(leafref_node, &rec, 1));
- rec->target_node = node;
+ LY_ARRAY_FOR(rec->target_nodes, u) {
+ if (rec->target_nodes[u] == node) {
+ return LY_SUCCESS;
+ }
+ }
+
+ LY_ARRAY_NEW_RET(LYD_CTX(node), rec->target_nodes, item, LY_EMEM);
+ *item = node;
+
return LY_SUCCESS;
}
@@ -3345,11 +3356,13 @@
lyd_leafref_link_node_tree(const struct lyd_node *tree)
{
const struct lyd_node *sibling, *elem;
- struct lyd_node *target;
+ struct ly_set *targets = NULL;
char *errmsg;
struct lyd_node_term *leafref_node;
struct lysc_node_leaf *leaf_schema;
struct lysc_type_leafref *lref;
+ LY_ERR ret = LY_SUCCESS;
+ uint32_t i;
LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
@@ -3365,12 +3378,18 @@
if (leaf_schema->type->basetype == LY_TYPE_LEAFREF) {
lref = (struct lysc_type_leafref *)leaf_schema->type;
- if (lyplg_type_resolve_leafref(lref, elem, &leafref_node->value, tree, &target, &errmsg)) {
+ ly_set_free(targets, NULL);
+ if (lyplg_type_resolve_leafref(lref, elem, &leafref_node->value, tree, &targets, &errmsg)) {
/* leafref target not found */
free(errmsg);
} else {
/* leafref target found, link it */
- LY_CHECK_RET(lyd_link_leafref_node((struct lyd_node_term *)target, leafref_node));
+ for (i = 0; i < targets->count; ++i) {
+ if (targets->dnodes[i]->schema->nodetype & LYD_NODE_TERM) {
+ ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], leafref_node);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+ }
}
}
}
@@ -3378,7 +3397,9 @@
}
}
- return LY_SUCCESS;
+cleanup:
+ ly_set_free(targets, NULL);
+ return ret;
}
LY_ERR
@@ -3394,20 +3415,22 @@
return LY_EDENIED;
}
+ /* remove link from target node to leafref node */
ret = lyd_get_or_create_leafref_links_record(node, &rec, 0);
if (ret == LY_SUCCESS) {
LY_ARRAY_REMOVE_VALUE(rec->leafref_nodes, leafref_node);
- if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (rec->target_node == NULL)) {
+ if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec->target_nodes) == 0)) {
lyd_free_leafref_nodes(node);
}
} else if (ret != LY_ENOTFOUND) {
return ret;
}
+ /* remove link from leafref node to target node */
ret = lyd_get_or_create_leafref_links_record(leafref_node, &rec, 0);
if (ret == LY_SUCCESS) {
- rec->target_node = NULL;
- if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (rec->target_node == NULL)) {
+ LY_ARRAY_REMOVE_VALUE(rec->target_nodes, node);
+ if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec->target_nodes) == 0)) {
lyd_free_leafref_nodes(leafref_node);
}
} else if (ret != LY_ENOTFOUND) {