libyang REFACTOR simplify logging and extend location information
Simplify logger interface by using location information maintained in
the background. logger now prints all the available information: schema
path, data path and line numbers. However, the line number are quite
inaccurate (e.g. points to XML closing parent element) and some future
tuning would be great.
diff --git a/src/validation.c b/src/validation.c
index 0bc5ac4..6299dee 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -167,7 +167,7 @@
LY_ERR ret;
uint32_t i;
const struct lysc_when *disabled;
- struct lyd_node *node;
+ struct lyd_node *node = NULL;
if (!node_when->count) {
return LY_SUCCESS;
@@ -177,6 +177,7 @@
do {
--i;
node = node_when->dnodes[i];
+ LOG_LOCSET(LYD_CTX(node), node->schema, node, NULL, NULL);
/* evaluate all when expressions that affect this node's existence */
ret = lyd_validate_node_when(*tree, node, node->schema, &disabled);
@@ -188,13 +189,15 @@
lyd_del_move_root(tree, node, mod);
if (diff) {
/* add into diff */
- LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_DELETE, diff));
+ ret = lyd_val_diff_add(node, LYD_DIFF_OP_DELETE, diff);
+ LY_CHECK_GOTO(ret, error);
}
lyd_free_tree(node);
} else {
/* invalid data */
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOWHEN, disabled->cond->expr);
- return LY_EVALID;
+ LOGVAL(LYD_CTX(node), LY_VCODE_NOWHEN, disabled->cond->expr);
+ ret = LY_EVALID;
+ goto error;
}
} else {
/* when true */
@@ -205,11 +208,17 @@
ly_set_rm_index(node_when, i, NULL);
} else if (ret != LY_EINCOMPLETE) {
/* error */
- return ret;
+ goto error;
}
+
+ LOG_LOCBACK(LYD_CTX(node), 1, 1, 0, 0);
} while (i);
return LY_SUCCESS;
+
+error:
+ LOG_LOCBACK(LYD_CTX(node), 1, 1, 0, 0);
+ return ret;
}
LY_ERR
@@ -242,8 +251,9 @@
struct lysc_type *type = ((struct lysc_node_leaf *)node->schema)->type;
/* resolve the value of the node */
- ret = lyd_value_validate_incomplete(LYD_CTX(node), type, &node->value, (struct lyd_node *)node, *tree,
- LY_VLOG_LYD, node);
+ LOG_LOCSET(LYD_CTX(node), node->schema, (struct lyd_node *)node, NULL, NULL);
+ ret = lyd_value_validate_incomplete(LYD_CTX(node), type, &node->value, (struct lyd_node *)node, *tree);
+ LOG_LOCBACK(LYD_CTX(node), node->schema ? 1 : 0, 1, 0, 0);
LY_CHECK_RET(ret);
/* remove this node from the set */
@@ -261,8 +271,7 @@
struct lysc_type *type = ((struct lyext_metadata *)meta->annotation->data)->type;
/* validate and store the value of the metadata */
- ret = lyd_value_validate_incomplete(LYD_CTX(meta->parent), type, &meta->value, meta->parent, *tree,
- LY_VLOG_NONE, NULL);
+ ret = lyd_value_validate_incomplete(LYD_CTX(meta->parent), type, &meta->value, meta->parent, *tree);
LY_CHECK_RET(ret);
/* remove this attr from the set */
@@ -317,7 +326,7 @@
}
if (fail) {
- LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_DUP, node->schema->name);
+ LOGVAL(node->schema->module->ctx, LY_VCODE_DUP, node->schema->name);
return LY_EVALID;
}
return LY_SUCCESS;
@@ -340,6 +349,8 @@
struct lyd_node *match, *to_del;
ly_bool found;
+ LOG_LOCSET(choic->module->ctx, (const struct lysc_node *)choic, NULL, NULL, NULL);
+
LY_LIST_FOR((struct lysc_node *)choic->cases, scase) {
found = 0;
iter = NULL;
@@ -361,7 +372,8 @@
/* there should not be 2 old cases */
if (old_case) {
/* old data from 2 cases */
- LOGVAL(choic->module->ctx, LY_VLOG_LYSC, choic, LY_VCODE_DUPCASE, old_case->name, scase->name);
+ LOGVAL(choic->module->ctx, LY_VCODE_DUPCASE, old_case->name, scase->name);
+ LOG_LOCBACK(choic->module->ctx, 1, 0, 0, 0);
return LY_EVALID;
}
@@ -370,7 +382,8 @@
} else if (found == 2) {
if (new_case) {
/* new data from 2 cases */
- LOGVAL(choic->module->ctx, LY_VLOG_LYSC, choic, LY_VCODE_DUPCASE, new_case->name, scase->name);
+ LOGVAL(choic->module->ctx, LY_VCODE_DUPCASE, new_case->name, scase->name);
+ LOG_LOCBACK(choic->module->ctx, 1, 0, 0, 0);
return LY_EVALID;
}
@@ -379,6 +392,8 @@
}
}
+ LOG_LOCBACK(choic->module->ctx, 1, 0, 0, 0);
+
if (old_case && new_case) {
/* auto-delete old case */
iter = NULL;
@@ -574,12 +589,17 @@
continue;
}
+ LOG_LOCSET(LYD_CTX(node), node->schema, node, NULL, NULL);
+
if (node->flags & LYD_NEW) {
+ LY_ERR ret;
+
/* remove old default(s) of the new node if it exists */
lyd_validate_autodel_dup(first, node, mod, &next, diff);
/* then check new node instance duplicities */
- LY_CHECK_RET(lyd_validate_duplicates(*first, node));
+ ret = lyd_validate_duplicates(*first, node);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(LYD_CTX(node), node->schema ? 1 : 0, 1, 0, 0), ret);
/* this node is valid */
node->flags &= ~LYD_NEW;
@@ -589,6 +609,8 @@
/* remove leftover default nodes from a no-longer existing case */
lyd_validate_autodel_case_dflt(first, node, mod, &next, diff);
}
+
+ LOG_LOCBACK(LYD_CTX(node), node->schema ? 1 : 0, 1, 0, 0);
}
return LY_SUCCESS;
@@ -688,7 +710,7 @@
if (!disabled) {
/* node instance not found */
- LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAND, snode->name);
+ LOGVAL(snode->module->ctx, LY_VCODE_NOMAND, snode->name);
return LY_EVALID;
}
@@ -712,6 +734,7 @@
uint32_t count = 0;
struct lyd_node *iter;
const struct lysc_when *disabled;
+ ly_bool invalid_instance = 0;
assert(min || max);
@@ -728,6 +751,8 @@
}
if (max && (count > max)) {
/* not satisifed */
+ LOG_LOCSET(snode->module->ctx, NULL, iter, NULL, NULL);
+ invalid_instance = 1;
break;
}
}
@@ -742,15 +767,19 @@
}
if (!disabled) {
- LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMIN, snode->name);
- return LY_EVALID;
+ LOGVAL(snode->module->ctx, LY_VCODE_NOMIN, snode->name);
+ goto failure;
}
} else if (max && (count > max)) {
- LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAX, snode->name);
- return LY_EVALID;
+ LOGVAL(snode->module->ctx, LY_VCODE_NOMAX, snode->name);
+ goto failure;
}
return LY_SUCCESS;
+
+failure:
+ LOG_LOCBACK(snode->module->ctx, 0, invalid_instance, 0, 0);
+ return LY_EVALID;
}
/**
@@ -876,7 +905,9 @@
ptr += strlen(ptr);
}
- LOGVAL(ctx, LY_VLOG_LYD, second, LY_VCODE_NOUNIQ, uniq_str, path1, path2);
+ LOG_LOCSET(ctx, NULL, second, NULL, NULL);
+ LOGVAL(ctx, LY_VCODE_NOUNIQ, uniq_str, path1, path2);
+ LOG_LOCBACK(ctx, 0, 1, 0, 0);
free(path1);
free(path2);
@@ -1032,6 +1063,7 @@
lyd_validate_siblings_schema_r(const struct lyd_node *first, const struct lyd_node *parent,
const struct lysc_node *sparent, const struct lysc_module *mod, uint32_t val_opts, LYD_VALIDATE_OP op)
{
+ LY_ERR ret = LY_SUCCESS;
const struct lysc_node *snode = NULL;
struct lysc_node_list *slist;
struct lysc_node_leaflist *sllist;
@@ -1045,38 +1077,51 @@
continue;
}
+ LOG_LOCSET(mod ? mod->mod->ctx : sparent->module->ctx, snode, NULL, NULL, NULL);
+
/* check min-elements and max-elements */
if (snode->nodetype == LYS_LIST) {
slist = (struct lysc_node_list *)snode;
if (slist->min || slist->max) {
- LY_CHECK_RET(lyd_validate_minmax(first, parent, snode, slist->min, slist->max));
+ ret = lyd_validate_minmax(first, parent, snode, slist->min, slist->max);
+ LY_CHECK_GOTO(ret, error);
}
} else if (snode->nodetype == LYS_LEAFLIST) {
sllist = (struct lysc_node_leaflist *)snode;
if (sllist->min || sllist->max) {
- LY_CHECK_RET(lyd_validate_minmax(first, parent, snode, sllist->min, sllist->max));
+ ret = lyd_validate_minmax(first, parent, snode, sllist->min, sllist->max);
+ LY_CHECK_GOTO(ret, error);
}
} else if (snode->flags & LYS_MAND_TRUE) {
/* check generic mandatory existence */
- LY_CHECK_RET(lyd_validate_mandatory(first, parent, snode));
+ ret = lyd_validate_mandatory(first, parent, snode);
+ LY_CHECK_GOTO(ret, error);
}
/* check unique */
if (snode->nodetype == LYS_LIST) {
slist = (struct lysc_node_list *)snode;
if (slist->uniques) {
- LY_CHECK_RET(lyd_validate_unique(first, snode, (const struct lysc_node_leaf ***)slist->uniques));
+ ret = lyd_validate_unique(first, snode, (const struct lysc_node_leaf ***)slist->uniques);
+ LY_CHECK_GOTO(ret, error);
}
}
if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
/* go recursively for schema-only nodes */
- LY_CHECK_RET(lyd_validate_siblings_schema_r(first, parent, snode, mod, val_opts, op));
+ ret = lyd_validate_siblings_schema_r(first, parent, snode, mod, val_opts, op);
+ LY_CHECK_GOTO(ret, error);
}
+
+ LOG_LOCBACK(mod ? mod->mod->ctx : sparent->module->ctx, 1, 0, 0, 0);
}
return LY_SUCCESS;
+
+error:
+ LOG_LOCBACK(mod ? mod->mod->ctx : sparent->module->ctx, 1, 0, 0, 0);
+ return ret;
}
/**
@@ -1172,7 +1217,7 @@
/* check the result */
lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
if (!xp_set.val.bln) {
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOMUST, musts[u].cond->expr);
+ LOGVAL(LYD_CTX(node), LY_VCODE_NOMUST, musts[u].cond->expr);
return LY_EVALID;
}
}
@@ -1184,6 +1229,7 @@
lyd_validate_final_r(struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *sparent,
const struct lys_module *mod, uint32_t val_opts, LYD_VALIDATE_OP op)
{
+ const char *innode = NULL;
struct lyd_node *next = NULL, *node;
/* validate all restrictions of nodes themselves */
@@ -1193,23 +1239,25 @@
break;
}
+ LOG_LOCSET(LYD_CTX(first), node->schema, node, NULL, NULL);
+
/* opaque data */
if (!node->schema) {
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LYVE_DATA, "Opaque node \"%s\" found.",
- ((struct lyd_node_opaq *)node)->name.name);
+ LOGVAL(LYD_CTX(node), LYVE_DATA, "Opaque node \"%s\" found.", ((struct lyd_node_opaq *)node)->name.name);
+ LOG_LOCBACK(LYD_CTX(first), 0, 1, 0, 0);
return LY_EVALID;
}
/* no state/input/output data */
if ((val_opts & LYD_VALIDATE_NO_STATE) && (node->schema->flags & LYS_CONFIG_R)) {
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "state", node->schema->name);
- return LY_EVALID;
+ innode = "state";
+ goto invalid_node;
} else if ((op == LYD_VALIDATE_OP_RPC) && (node->schema->flags & LYS_CONFIG_R)) {
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "output", node->schema->name);
- return LY_EVALID;
+ innode = "output";
+ goto invalid_node;
} else if ((op == LYD_VALIDATE_OP_REPLY) && (node->schema->flags & LYS_CONFIG_W)) {
- LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "input", node->schema->name);
- return LY_EVALID;
+ innode = "input";
+ goto invalid_node;
}
/* obsolete data */
@@ -1219,6 +1267,8 @@
LY_CHECK_RET(lyd_validate_must(node, op));
/* node value was checked by plugins */
+
+ LOG_LOCBACK(LYD_CTX(first), 1, 1, 0, 0);
}
/* validate schema-based restrictions */
@@ -1242,6 +1292,11 @@
}
return LY_SUCCESS;
+
+invalid_node:
+ LOGVAL(LYD_CTX(node), LY_VCODE_INNODE, innode, node->schema->name);
+ LOG_LOCBACK(LYD_CTX(first), 1, 1, 0, 0);
+ return LY_EVALID;
}
/**
@@ -1499,6 +1554,8 @@
tree = tree_sibling;
}
+ LOG_LOCSET(LYD_CTX(op_node), NULL, op_node, NULL, NULL);
+
/* prevalidate whole operation subtree */
LY_CHECK_GOTO(ret = lyd_validate_subtree(op_node, &type_check, &type_meta_check, &when_check,
op == LYD_VALIDATE_OP_REPLY ? LYD_IMPLICIT_OUTPUT : 0, diff), cleanup);
@@ -1515,6 +1572,7 @@
LY_CHECK_GOTO(ret = lyd_validate_final_r(lyd_child(op_node), op_node, op_node->schema, NULL, 0, op), cleanup);
cleanup:
+ LOG_LOCBACK(LYD_CTX(op_node), 0, 1, 0, 0);
/* restore operation tree */
lyd_unlink_tree(op_subtree);
if (op_parent) {