data tree BUGFIX duplication of metadata
... from different contexts.
diff --git a/src/tree_data.c b/src/tree_data.c
index 7d1989b..0e17384 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1804,7 +1804,7 @@
}
} else {
LY_LIST_FOR(node->meta, meta) {
- LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
+ LY_CHECK_GOTO(ret = lyd_dup_meta_single_to_ctx(trg_ctx, meta, dup, NULL), error);
}
}
}
@@ -2078,33 +2078,52 @@
return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 0, dup);
}
-LIBYANG_API_DEF LY_ERR
-lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
+LY_ERR
+lyd_dup_meta_single_to_ctx(const struct ly_ctx *parent_ctx, const struct lyd_meta *meta, struct lyd_node *parent,
+ struct lyd_meta **dup)
{
LY_ERR ret = LY_SUCCESS;
- const struct ly_ctx *ctx;
struct lyd_meta *mt, *last;
+ const struct lysc_type *ant_type;
+ struct lys_module *mod;
+ const char *val_can;
- LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
-
- /* log to node context but value must always use the annotation context */
- ctx = meta->annotation->module->ctx;
+ LY_CHECK_ARG_RET(NULL, meta, parent, LY_EINVAL);
/* create a copy */
mt = calloc(1, sizeof *mt);
- LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_CTX(node)), LY_EMEM);
- mt->annotation = meta->annotation;
- ret = meta->value.realtype->plugin->duplicate(ctx, &meta->value, &mt->value);
- LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(node), LY_EINT, "Value duplication failed."), finish);
- LY_CHECK_GOTO(ret = lydict_insert(ctx, meta->name, 0, &mt->name), finish);
+ LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_CTX(parent)), LY_EMEM);
+
+ if (parent_ctx != meta->annotation->module->ctx) {
+ /* different contexts */
+ mod = ly_ctx_get_module(parent_ctx, meta->annotation->module->name, meta->annotation->module->revision);
+
+ /* annotation */
+ mt->annotation = lyd_get_meta_annotation(mod, meta->name, strlen(meta->name));
+ lyplg_ext_get_storage(mt->annotation, LY_STMT_TYPE, sizeof ant_type, (const void **)&ant_type);
+ LY_CHECK_ERR_GOTO((ret = mt->annotation ? LY_SUCCESS : LY_EINVAL), LOGERR(parent_ctx, LY_EINVAL,
+ "Annotation for metadata %s not found, value duplication failed.", meta->name), finish);
+
+ /* duplicate callback expect only the same contexts, so use the store callback */
+ val_can = lyd_value_get_canonical(meta->annotation->module->ctx, &meta->value);
+ ret = lyd_value_store(parent_ctx, &mt->value, ant_type, val_can, strlen(val_can), 1, NULL,
+ LY_VALUE_CANON, NULL, LYD_HINT_DATA, parent->schema, NULL);
+ } else {
+ /* annotation */
+ mt->annotation = meta->annotation;
+ /* duplication of value */
+ ret = meta->value.realtype->plugin->duplicate(parent_ctx, &meta->value, &mt->value);
+ }
+ LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(parent), LY_EINT, "Value duplication failed."), finish);
+ LY_CHECK_GOTO(ret = lydict_insert(parent_ctx, meta->name, 0, &mt->name), finish);
/* insert as the last attribute */
- mt->parent = node;
- if (node->meta) {
- for (last = node->meta; last->next; last = last->next) {}
+ mt->parent = parent;
+ if (parent->meta) {
+ for (last = parent->meta; last->next; last = last->next) {}
last->next = mt;
} else {
- node->meta = mt;
+ parent->meta = mt;
}
finish:
@@ -2116,6 +2135,15 @@
return LY_SUCCESS;
}
+LIBYANG_API_DEF LY_ERR
+lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
+{
+ LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
+
+ /* log to node context but value must always use the annotation context */
+ return lyd_dup_meta_single_to_ctx(meta->annotation->module->ctx, meta, node, dup);
+}
+
/**
* @brief Merge a source sibling into target siblings.
*