schema BUGFIX switching deviations
- issue with deviating (not-supported deviation) augmentation node,
which is actually removed from 2 locations and it must be reconnected
back to both locations (unless the augment is deactivated in that time)
- misleading 'module' parameter of the deviation switch function caused
that the deviated (not-support) top-level node was actually reconnected
to the module where the deviation is defined instead of the original module
diff --git a/src/tree_schema.c b/src/tree_schema.c
index b594529..8400e94 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -667,7 +667,7 @@
int
lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
{
- struct lys_node *iter;
+ struct lys_node *iter, *next;
struct lys_node_inout *in, *out, *inout;
int type;
@@ -797,11 +797,18 @@
module->data = child;
}
} else {
+ next = NULL;
if (!parent->child) {
/* the only/first child of the parent */
parent->child = child;
child->parent = parent;
iter = child;
+ } else if (type == LYS_AUGMENT) {
+ /* add a new child as a last child of the augment (no matter if applied or not) */
+ for (iter = parent->child->prev; iter->parent != parent; iter = iter->prev);
+ next = iter->next;
+ iter->next = child;
+ child->prev = iter;
} else {
/* add a new child at the end of parent's child list */
iter = parent->child->prev;
@@ -812,7 +819,13 @@
iter = iter->next;
iter->parent = parent;
}
- parent->child->prev = iter;
+ if (next) {
+ /* we are in applied augment, its target has some additional nodes after the nodes from this augment */
+ iter->next = next;
+ next->prev = iter;
+ } else {
+ parent->child->prev = iter;
+ }
}
}
@@ -3284,13 +3297,17 @@
dst->prev = dst;
/* parent child */
- if (dst->parent && (dst->parent->child == dst)) {
- dst->parent->child = src;
+ if (dst->parent) {
+ if (dst->parent->child == dst) {
+ dst->parent->child = src;
+ }
+ } else if (dst->module->data == dst) {
+ dst->module->data = src;
}
/* parent */
- src->parent = dst->parent;
- dst->parent = NULL;
+ src->parent = dst->parent; dst->parent = NULL;
+
/* child parent */
LY_TREE_FOR(dst->child, child) {
@@ -3947,106 +3964,6 @@
}
static void
-lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
-{
- int ret;
- char *parent_path;
- struct lys_node *target;
-
- if (!dev->deviate) {
- return ;
- }
-
- if (dev->deviate[0].mod == LY_DEVIATE_NO) {
- if (dev->orig_node) {
- /* removing not-supported deviation ... */
- if (strrchr(dev->target_name, '/') != dev->target_name) {
- /* ... from a parent */
- parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
-
- target = NULL;
- ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, 1,
- (const struct lys_node **)&target);
- free(parent_path);
- if (ret || !target) {
- LOGINT;
- return;
- }
-
- lys_node_addchild(target, NULL, dev->orig_node);
- } else {
- /* ... from top-level data */
- lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
- }
-
- dev->orig_node = NULL;
- } else {
- /* adding not-supported deviation */
- target = NULL;
- ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
- (const struct lys_node **)&target);
- if (ret || !target) {
- LOGINT;
- return;
- }
-
- lys_node_unlink(target);
- dev->orig_node = target;
- }
- } else {
- target = NULL;
- ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
- (const struct lys_node **)&target);
- if (ret || !target) {
- LOGINT;
- return;
- }
-
- lys_node_switch(target, dev->orig_node);
- dev->orig_node = target;
- }
-}
-
-/* temporarily removes or applies deviations, updates module deviation flag accordingly */
-void
-lys_switch_deviations(struct lys_module *module)
-{
- uint32_t i = 0, j;
- const struct lys_module *mod;
- const char *ptr;
-
- if (module->deviated) {
- while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
- if (mod == module) {
- continue;
- }
-
- for (j = 0; j < mod->deviation_size; ++j) {
- ptr = strstr(mod->deviation[j].target_name, module->name);
- if (ptr && ptr[strlen(module->name)] == ':') {
- lys_switch_deviation(&mod->deviation[j], module);
- }
- }
- }
-
- if (module->deviated == 2) {
- module->deviated = 1;
- } else {
- module->deviated = 2;
- }
- }
-}
-
-static void
-apply_dev(struct lys_deviation *dev, const struct lys_module *module)
-{
- lys_switch_deviation(dev, module);
-
- assert(dev->orig_node);
- lys_node_module(dev->orig_node)->deviated = 1;
-}
-
-static void
apply_aug(struct lys_node_augment *augment)
{
struct lys_node *last;
@@ -4067,72 +3984,6 @@
augment->flags &= ~LYS_NOTAPPLIED;
}
-void
-lys_sub_module_apply_devs_augs(struct lys_module *module)
-{
- uint8_t u, v;
-
- /* remove applied deviations */
- for (u = 0; u < module->deviation_size; ++u) {
- apply_dev(&module->deviation[u], module);
- }
- /* remove applied augments */
- for (u = 0; u < module->augment_size; ++u) {
- apply_aug(&module->augment[u]);
- }
-
- /* remove deviation and augments defined in submodules */
- for (v = 0; v < module->inc_size; ++v) {
- for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
- apply_dev(&module->inc[v].submodule->deviation[u], module);
- }
-
- for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
- apply_aug(&module->inc[v].submodule->augment[u]);
- }
- }
-}
-
-static void
-remove_dev(struct lys_deviation *dev, const struct lys_module *module)
-{
- uint32_t idx = 0, j;
- const struct lys_module *mod;
- struct lys_module *target_mod;
- const char *ptr;
-
- if (dev->orig_node) {
- target_mod = lys_node_module(dev->orig_node);
- } else {
- LOGINT;
- return;
- }
- lys_switch_deviation(dev, module);
-
- /* clear the deviation flag if possible */
- while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
- if ((mod == module) || (mod == target_mod)) {
- continue;
- }
-
- for (j = 0; j < mod->deviation_size; ++j) {
- ptr = strstr(mod->deviation[j].target_name, target_mod->name);
- if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
- /* some other module deviation targets the inspected module, flag remains */
- break;
- }
- }
-
- if (j < mod->deviation_size) {
- break;
- }
- }
-
- if (!mod) {
- target_mod->deviated = 0;
- }
-}
-
static void
remove_aug(struct lys_node_augment *augment)
{
@@ -4179,6 +4030,206 @@
augment->flags |= LYS_NOTAPPLIED;
}
+/*
+ * @param[in] module - the module where the deviation is defined
+ */
+static void
+lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module)
+{
+ int ret;
+ char *parent_path;
+ struct lys_node *target = NULL, *parent;
+
+ if (!dev->deviate) {
+ return ;
+ }
+
+ if (dev->deviate[0].mod == LY_DEVIATE_NO) {
+ if (dev->orig_node) {
+ /* removing not-supported deviation ... */
+ if (strrchr(dev->target_name, '/') != dev->target_name) {
+ /* ... from a parent */
+
+ /* reconnect to its previous position */
+ parent = dev->orig_node->parent;
+ if (parent) {
+ /* the original node was actually from augment, we have to get know if the augment is
+ * applied (its module is enabled and implemented). If yes, the node will be connected
+ * to the augment and the linkage with the target will be fixed if needed, otherwise
+ * it will be connected only to the augment */
+ /* first, connect it into the augment */
+ lys_node_addchild(parent, NULL, dev->orig_node);
+ if (!parent->module->disabled && parent->module->implemented) {
+ /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
+ if (parent->child == dev->orig_node) {
+ /* the only node in augment */
+ dev->orig_node->flags |= LYS_NOTAPPLIED;
+ apply_aug((struct lys_node_augment *)parent);
+ } else {
+ /* other nodes from augment applied, nothing more needed in target, everything was done
+ * by lys_node_addchild() */
+ dev->orig_node->flags |= parent->child->flags & LYS_NOTAPPLIED;
+ }
+ } else {
+ /* augment is not supposed to be applied */
+ dev->orig_node->flags |= LYS_NOTAPPLIED;
+ }
+ } else {
+ /* non-augment, non-toplevel */
+ parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
+ ret = resolve_augment_schema_nodeid(parent_path, NULL, module, 1,
+ (const struct lys_node **)&target);
+ free(parent_path);
+ if (ret || !target) {
+ LOGINT;
+ return;
+ }
+ lys_node_addchild(target, NULL, dev->orig_node);
+ }
+ } else {
+ /* ... from top-level data */
+ lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
+ }
+
+ dev->orig_node = NULL;
+ } else {
+ /* adding not-supported deviation */
+ ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
+ (const struct lys_node **)&target);
+ if (ret || !target) {
+ LOGINT;
+ return;
+ }
+
+ /* unlink and store the original node */
+ parent = target->parent;
+ lys_node_unlink(target);
+ if (parent && parent->nodetype == LYS_AUGMENT) {
+ /* hack for augment, because when the original will be sometime reconnected back, we actually need
+ * to reconnect it to both - the augment and its target (which is deduced from the deviations target
+ * path), so we need to remember the augment as an addition */
+ target->parent = parent;
+ }
+ dev->orig_node = target;
+ }
+ } else {
+ ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
+ (const struct lys_node **)&target);
+ if (ret || !target) {
+ LOGINT;
+ return;
+ }
+
+ lys_node_switch(target, dev->orig_node);
+ dev->orig_node = target;
+ }
+}
+
+/* temporarily removes or applies deviations, updates module deviation flag accordingly */
+void
+lys_switch_deviations(struct lys_module *module)
+{
+ uint32_t i = 0, j;
+ const struct lys_module *mod;
+ const char *ptr;
+
+ if (module->deviated) {
+ while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
+ if (mod == module) {
+ continue;
+ }
+
+ for (j = 0; j < mod->deviation_size; ++j) {
+ ptr = strstr(mod->deviation[j].target_name, module->name);
+ if (ptr && ptr[strlen(module->name)] == ':') {
+ lys_switch_deviation(&mod->deviation[j], mod);
+ }
+ }
+ }
+
+ if (module->deviated == 2) {
+ module->deviated = 1;
+ } else {
+ module->deviated = 2;
+ }
+ }
+}
+
+static void
+apply_dev(struct lys_deviation *dev, const struct lys_module *module)
+{
+ lys_switch_deviation(dev, module);
+
+ assert(dev->orig_node);
+ lys_node_module(dev->orig_node)->deviated = 1;
+}
+
+static void
+remove_dev(struct lys_deviation *dev, const struct lys_module *module)
+{
+ uint32_t idx = 0, j;
+ const struct lys_module *mod;
+ struct lys_module *target_mod;
+ const char *ptr;
+
+ if (dev->orig_node) {
+ target_mod = lys_node_module(dev->orig_node);
+ } else {
+ LOGINT;
+ return;
+ }
+ lys_switch_deviation(dev, module);
+
+ /* clear the deviation flag if possible */
+ while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
+ if ((mod == module) || (mod == target_mod)) {
+ continue;
+ }
+
+ for (j = 0; j < mod->deviation_size; ++j) {
+ ptr = strstr(mod->deviation[j].target_name, target_mod->name);
+ if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
+ /* some other module deviation targets the inspected module, flag remains */
+ break;
+ }
+ }
+
+ if (j < mod->deviation_size) {
+ break;
+ }
+ }
+
+ if (!mod) {
+ target_mod->deviated = 0;
+ }
+}
+
+void
+lys_sub_module_apply_devs_augs(struct lys_module *module)
+{
+ uint8_t u, v;
+
+ /* remove applied deviations */
+ for (u = 0; u < module->deviation_size; ++u) {
+ apply_dev(&module->deviation[u], module);
+ }
+ /* remove applied augments */
+ for (u = 0; u < module->augment_size; ++u) {
+ apply_aug(&module->augment[u]);
+ }
+
+ /* remove deviation and augments defined in submodules */
+ for (v = 0; v < module->inc_size; ++v) {
+ for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
+ apply_dev(&module->inc[v].submodule->deviation[u], module);
+ }
+
+ for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
+ apply_aug(&module->inc[v].submodule->augment[u]);
+ }
+ }
+}
+
void
lys_sub_module_remove_devs_augs(struct lys_module *module)
{