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/parser_json.c b/src/parser_json.c
index da65f2f..6348459 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -191,12 +191,15 @@
lydjson_get_snode(const struct lyd_json_ctx *lydctx, ly_bool is_attr, const char *prefix, size_t prefix_len, const char *name,
size_t name_len, const struct lyd_node_inner *parent, const struct lysc_node **snode_p)
{
+ LY_ERR ret = LY_SUCCESS;
struct lys_module *mod = NULL;
uint32_t getnext_opts = lydctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
/* init return value */
*snode_p = NULL;
+ LOG_LOCSET(lydctx->jsonctx->ctx, NULL, (const struct lyd_node *)parent, NULL, NULL);
+
/* get the element module */
if (prefix_len) {
mod = ly_ctx_get_module_implemented2(lydctx->jsonctx->ctx, prefix, prefix_len);
@@ -205,17 +208,20 @@
mod = parent->schema->module;
}
} else {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, parent, LYVE_SYNTAX_JSON, "Top-level JSON object member \"%.*s\" must be namespace-qualified.",
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Top-level JSON object member \"%.*s\" must be namespace-qualified.",
is_attr ? name_len + 1 : name_len, is_attr ? name - 1 : name);
- return LY_EVALID;
+ ret = LY_EVALID;
+ goto cleanup;
}
if (!mod) {
if (lydctx->parse_options & LYD_PARSE_STRICT) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, parent, LYVE_REFERENCE, "No module named \"%.*s\" in the context.", prefix_len, prefix);
- return LY_EVALID;
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "No module named \"%.*s\" in the context.", prefix_len, prefix);
+ ret = LY_EVALID;
+ goto cleanup;
}
if (!(lydctx->parse_options & LYD_PARSE_OPAQ)) {
- return LY_ENOT;
+ ret = LY_ENOT;
+ goto cleanup;
}
}
@@ -224,20 +230,24 @@
*snode_p = lys_find_child(parent ? parent->schema : NULL, mod, name, name_len, 0, getnext_opts);
if (!*snode_p) {
if (lydctx->parse_options & LYD_PARSE_STRICT) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, parent, LYVE_REFERENCE, "Node \"%.*s\" not found in the \"%s\" module.",
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "Node \"%.*s\" not found in the \"%s\" module.",
name_len, name, mod->name);
- return LY_EVALID;
+ ret = LY_EVALID;
+ goto cleanup;
} else if (!(lydctx->parse_options & LYD_PARSE_OPAQ)) {
/* skip element with children */
- return LY_ENOT;
+ ret = LY_ENOT;
+ goto cleanup;
}
} else {
/* check that schema node is valid and can be used */
- LY_CHECK_RET(lyd_parser_check_schema((struct lyd_ctx *)lydctx, *snode_p));
+ ret = lyd_parser_check_schema((struct lyd_ctx *)lydctx, *snode_p);
}
}
- return LY_SUCCESS;
+cleanup:
+ LOG_LOCBACK(lydctx->jsonctx->ctx, 0, parent ? 1 : 0, 0, 0);
+ return ret;
}
/**
@@ -482,6 +492,7 @@
struct lyd_node *node, *attr, *next, *start = *first_p, *meta_iter;
uint64_t instance = 0;
const char *prev = NULL;
+ uint32_t log_location_items = 0;
/* finish linking metadata */
LY_LIST_FOR_SAFE(*first_p, next, attr) {
@@ -497,6 +508,9 @@
continue;
}
+ LOG_LOCSET(lydctx->jsonctx->ctx, NULL, attr, NULL, NULL);
+ log_location_items++;
+
if (prev != meta_container->name.name) {
/* metas' names are stored in dictionary, so checking pointers must works */
lydict_remove(lydctx->jsonctx->ctx, prev);
@@ -515,8 +529,8 @@
}
if (((struct lyd_node_opaq *)node)->hints & LYD_NODEHINT_LIST) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, node, LYVE_SYNTAX,
- "Metadata container references a sibling list node %s.", ((struct lyd_node_opaq *)node)->name.name);
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX, "Metadata container references a sibling list node %s.",
+ ((struct lyd_node_opaq *)node)->name.name);
ret = LY_EVALID;
goto cleanup;
}
@@ -572,7 +586,7 @@
&dynamic, LY_PREF_JSON, NULL, meta->hints);
LY_CHECK_GOTO(ret, cleanup);
} else if (lydctx->parse_options & LYD_PARSE_STRICT) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, node, LYVE_REFERENCE,
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE,
"Unknown (or not implemented) YANG module \"%s\" for metadata \"%s%s%s\".",
meta->name.prefix, meta->name.prefix, ly_strlen(meta->name.prefix) ? ":" : "", meta->name.name);
ret = LY_EVALID;
@@ -590,12 +604,11 @@
if (match != instance) {
/* there is no corresponding data node for the metadata */
if (instance > 1) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, *first_p ? (*first_p)->parent : NULL, LYVE_REFERENCE,
- "Missing %d%s JSON data instance to be coupled with %s metadata.", instance,
- instance == 2 ? "nd" : (instance == 3 ? "rd" : "th"), meta_container->name.name);
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "Missing %d%s JSON data instance to be coupled with %s metadata.",
+ instance, instance == 2 ? "nd" : (instance == 3 ? "rd" : "th"), meta_container->name.name);
} else {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, *first_p ? (*first_p)->parent : NULL, LYVE_REFERENCE,
- "Missing JSON data instance to be coupled with %s metadata.", meta_container->name.name);
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "Missing JSON data instance to be coupled with %s metadata.",
+ meta_container->name.name);
}
ret = LY_EVALID;
} else {
@@ -605,11 +618,15 @@
}
lyd_free_tree(attr);
}
+
+ LOG_LOCBACK(lydctx->jsonctx->ctx, 0, log_location_items, 0, 0);
+ log_location_items = 0;
}
cleanup:
lydict_remove(lydctx->jsonctx->ctx, prev);
+ LOG_LOCBACK(lydctx->jsonctx->ctx, 0, log_location_items, 0, 0);
return ret;
}
@@ -671,8 +688,7 @@
LY_CHECK_GOTO(status != LYJSON_OBJECT && status != LYJSON_NULL, representation_error);
if (!node || (node->schema != prev->schema)) {
- LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, prev->parent, LYVE_REFERENCE,
- "Missing JSON data instance no. %u of %s:%s to be coupled with metadata.",
+ LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "Missing JSON data instance no. %u of %s:%s to be coupled with metadata.",
instance, prev->schema->module->name, prev->schema->name);
ret = LY_EVALID;
goto cleanup;
@@ -708,17 +724,17 @@
/* process all the members inside a single metadata object */
assert(status == LYJSON_OBJECT);
+ LOG_LOCSET(ctx, snode, NULL, NULL, NULL);
+
while (status != LYJSON_OBJECT_CLOSED) {
lydjson_parse_name(lydctx->jsonctx->value, lydctx->jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_attr);
if (!prefix) {
- LOGVAL(ctx, LY_VLOG_LYD, (void *)node, LYVE_SYNTAX_JSON,
- "Metadata in JSON must be namespace-qualified, missing prefix for \"%.*s\".",
+ LOGVAL(ctx, LYVE_SYNTAX_JSON, "Metadata in JSON must be namespace-qualified, missing prefix for \"%.*s\".",
lydctx->jsonctx->value_len, lydctx->jsonctx->value);
ret = LY_EVALID;
goto cleanup;
} else if (is_attr) {
- LOGVAL(ctx, LY_VLOG_LYD, (void *)node, LYVE_SYNTAX_JSON,
- "Invalid format of the Metadata identifier in JSON, unexpected '@' in \"%.*s\"",
+ LOGVAL(ctx, LYVE_SYNTAX_JSON, "Invalid format of the Metadata identifier in JSON, unexpected '@' in \"%.*s\"",
lydctx->jsonctx->value_len, lydctx->jsonctx->value);
ret = LY_EVALID;
goto cleanup;
@@ -728,8 +744,7 @@
mod = ly_ctx_get_module_implemented2(ctx, prefix, prefix_len);
if (!mod) {
if (lydctx->parse_options & LYD_PARSE_STRICT) {
- LOGVAL(ctx, LY_VLOG_LYD, (void *)node, LYVE_REFERENCE,
- "Prefix \"%.*s\" of the metadata \"%.*s\" does not match any module in the context.",
+ LOGVAL(ctx, LYVE_REFERENCE, "Prefix \"%.*s\" of the metadata \"%.*s\" does not match any module in the context.",
prefix_len, prefix, name_len, name);
ret = LY_EVALID;
goto cleanup;
@@ -789,15 +804,17 @@
LY_CHECK_GOTO(ret, cleanup);
cleanup:
+ LOG_LOCBACK(ctx, 1, 0, 0, 0);
return ret;
representation_error:
- LOGVAL(ctx, LY_VLOG_LYD, (void *)node, LYVE_SYNTAX_JSON,
+ LOGVAL(ctx, LYVE_SYNTAX_JSON,
"The attribute(s) of %s \"%s\" is expected to be represented as JSON %s, but input data contains @%s/%s.",
lys_nodetype2str(nodetype), node->schema ? node->schema->name : ((struct lyd_node_opaq *)node)->name.name,
expected, lyjson_token2str(status), in_parent ? "" : "name");
- return LY_EVALID;
+ ret = LY_EVALID;
+ goto cleanup;
}
/**
@@ -1033,35 +1050,39 @@
ret = lyd_create_inner(snode, node);
LY_CHECK_RET(ret);
+ LOG_LOCSET(lydctx->jsonctx->ctx, snode, *node, NULL, NULL);
+
/* process children */
while (*status != LYJSON_OBJECT_CLOSED && *status != LYJSON_OBJECT_EMPTY) {
ret = lydjson_subtree_r(lydctx, (struct lyd_node_inner *)*node, lyd_node_children_p(*node));
- LY_CHECK_RET(ret);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0), ret);
*status = lyjson_ctx_status(lydctx->jsonctx, 0);
}
/* finish linking metadata */
ret = lydjson_metadata_finish(lydctx, lyd_node_children_p(*node));
- LY_CHECK_RET(ret);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0), ret);
if (snode->nodetype == LYS_LIST) {
/* check all keys exist */
ret = lyd_parse_check_keys(*node);
- LY_CHECK_RET(ret);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0), ret);
}
if (!(lydctx->parse_options & LYD_PARSE_ONLY)) {
/* new node validation, autodelete CANNOT occur, all nodes are new */
ret = lyd_validate_new(lyd_node_children_p(*node), snode, NULL, NULL);
- LY_CHECK_RET(ret);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0), ret);
/* add any missing default children */
ret = lyd_new_implicit_r(*node, lyd_node_children_p(*node), NULL, NULL, &lydctx->node_types,
&lydctx->node_when, (lydctx->validate_options & LYD_VALIDATE_NO_STATE) ?
LYD_IMPLICIT_NO_STATE : 0, NULL);
- LY_CHECK_RET(ret);
+ LY_CHECK_ERR_RET(ret, LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0), ret);
}
+ LOG_LOCBACK(lydctx->jsonctx->ctx, 1, 1, 0, 0);
+
/* move JSON parser */
ret = lyjson_ctx_next(lydctx->jsonctx, status);
LY_CHECK_RET(ret);
@@ -1160,7 +1181,7 @@
if (!name_len && !prefix_len) {
/* parent's metadata without a name - use the schema from the parent */
if (!parent) {
- LOGVAL(ctx, LY_VLOG_LYD, NULL, LYVE_SYNTAX_JSON,
+ LOGVAL(ctx, LYVE_SYNTAX_JSON,
"Invalid metadata format - \"@\" can be used only inside anydata, container or list entries.");
ret = LY_EVALID;
goto cleanup;
@@ -1274,10 +1295,10 @@
return ret;
representation_error:
- LOGVAL(ctx, LY_VLOG_LYD, parent, LYVE_SYNTAX_JSON,
- "The %s \"%s\" is expected to be represented as JSON %s, but input data contains name/%s.",
+ LOG_LOCSET(ctx, NULL, (const struct lyd_node *)parent, NULL, NULL);
+ LOGVAL(ctx, LYVE_SYNTAX_JSON, "The %s \"%s\" is expected to be represented as JSON %s, but input data contains name/%s.",
lys_nodetype2str(snode->nodetype), snode->name, expected, lyjson_token2str(status));
-
+ LOG_LOCBACK(ctx, 0, parent ? 1 : 0, 0, 0);
ret = LY_EVALID;
goto cleanup;
}
@@ -1326,7 +1347,7 @@
return LY_SUCCESS;
} else {
/* expecting top-level object */
- LOGVAL(ctx, LY_VLOG_LINE, &in->line, LYVE_SYNTAX_JSON, "Expected top-level JSON object, but %s found.",
+ LOGVAL(ctx, LYVE_SYNTAX_JSON, "Expected top-level JSON object, but %s found.",
lyjson_token2str(*status));
*lydctx_p = NULL;
lyd_json_ctx_free((struct lyd_ctx *)lydctx);
@@ -1498,11 +1519,11 @@
/* make sure we have parsed some notification */
if (!lydctx->op_node) {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
+ LOGVAL(ctx, LYVE_DATA, "Missing the \"notification\" node.");
ret = LY_EVALID;
goto cleanup;
} else if (lydctx->jsonctx->in->current[0] && (lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_OBJECT_CLOSED)) {
- LOGVAL(ctx, LY_VLOG_LINE, &lydctx->jsonctx->in->line, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
+ LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
tree->schema->name);
ret = LY_EVALID;
goto cleanup;
@@ -1582,10 +1603,10 @@
{
LY_CHECK_RET(lyjson_ctx_next(jsonctx, status));
if (*status == LYJSON_END) {
- LOGVAL(jsonctx->ctx, LY_VLOG_LINE, &jsonctx->line, LY_VCODE_EOF);
+ LOGVAL(jsonctx->ctx, LY_VCODE_EOF);
return LY_EVALID;
} else if (*status != LYJSON_OBJECT_CLOSED) {
- LOGVAL(jsonctx->ctx, LY_VLOG_LINE, &jsonctx->line, LYVE_SYNTAX, "Unexpected sibling member \"%.*s\" of \"%s\".",
+ LOGVAL(jsonctx->ctx, LYVE_SYNTAX, "Unexpected sibling member \"%.*s\" of \"%s\".",
jsonctx->value_len, jsonctx->value, object_id);
return LY_EVALID;
}
@@ -1642,11 +1663,11 @@
/* make sure we have parsed some operation */
if (!lydctx->op_node) {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the rpc/action node.");
+ LOGVAL(ctx, LYVE_DATA, "Missing the rpc/action node.");
ret = LY_EVALID;
goto cleanup;
} else if (lydctx->jsonctx->in->current[0] && (lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_OBJECT_CLOSED)) {
- LOGVAL(ctx, LY_VLOG_LINE, &lydctx->jsonctx->in->line, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
+ LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
tree->schema->name);
ret = LY_EVALID;
goto cleanup;