Skip to content

Commit

Permalink
libyang FEATURE sorting of data nodes
Browse files Browse the repository at this point in the history
1. Plugin type 'lyds_tree' is integrated. Used in metadata and it is
internal, which is distinguished by the unset print callback.
Internal metadata must not be printed.
2. Leaf-list and list data instances are now automatically sorted.
3. Both the explicit and implicit YANG statement 'ordered-by system'
will cause the nodes to be ordered.
4. The first instance of the list or leaf-list of node contain
new metadata named 'lyds_tree'.
5. Data nodes are sorted only if their data types have
callback 'sort' set.
6. Sorting can be turned off so far only by adding the 'ordered-by user'
statement to the YANG model.
7. If the sort fails for some reason, the node is still inserted
as the last instance. A warning message informs about this situation.
8. The time required for sorting should be relatively small thanks to
the Red-black tree implementation.
9. Memory requirements will now increase by 40 bytes per list/leaf-list
data node, plus metadata structure overhead.
  • Loading branch information
lePici committed Nov 9, 2023
1 parent 8769b75 commit ededb53
Show file tree
Hide file tree
Showing 18 changed files with 1,441 additions and 131 deletions.
35 changes: 32 additions & 3 deletions src/printer_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,9 @@ json_print_metadata(struct jsonpr_ctx *pctx, const struct lyd_node *node, const
}

for (meta = node->meta; meta; meta = meta->next) {
if (!meta->value.realtype->plugin->print) {
continue;
}
PRINT_COMMA;
ly_print_(pctx->out, "%*s\"%s:%s\":%s", INDENT, meta->annotation->module->name, meta->name, DO_FORMAT ? " " : "");
LY_CHECK_RET(json_print_value(pctx, LYD_CTX(node), &meta->value, NULL));
Expand All @@ -464,6 +467,30 @@ json_print_metadata(struct jsonpr_ctx *pctx, const struct lyd_node *node, const
return LY_SUCCESS;
}

/**
* @brief Check if a value can be printed for at least one metadata.
*
* @param[in] node Node to check.
* @return 1 if node has printable meta otherwise 0.
*/
static ly_bool
node_has_printable_meta(const struct lyd_node *node)
{
struct lyd_meta *iter;

if (!node->meta) {
return 0;
}

LY_LIST_FOR(node->meta, iter) {
if (iter->value.realtype->plugin->print) {
return 1;
}
}

return 0;
}

/**
* @brief Print attributes/metadata of the given @p node. Accepts both regular as well as opaq nodes.
*
Expand All @@ -484,7 +511,7 @@ json_print_attributes(struct jsonpr_ctx *pctx, const struct lyd_node *node, ly_b
wdmod = ly_ctx_get_module_implemented(LYD_CTX(node), "ietf-netconf-with-defaults");
}

if (node->schema && (node->meta || wdmod)) {
if (node->schema && (wdmod || node_has_printable_meta(node))) {
if (inner) {
LY_CHECK_RET(json_print_member2(pctx, lyd_parent(node), LY_VALUE_JSON, NULL, 1));
} else {
Expand Down Expand Up @@ -793,11 +820,12 @@ json_print_leaf_list(struct jsonpr_ctx *pctx, const struct lyd_node *node)
LY_CHECK_RET(json_print_value(pctx, LYD_CTX(node), &((const struct lyd_node_term *)node)->value, node->schema->module));

if (!pctx->first_leaflist) {
/* decide if we will be printing metadata for these siblings */
if ((node->flags & LYD_DEFAULT) && (pctx->options & (LYD_PRINT_WD_ALL_TAG | LYD_PRINT_WD_IMPL_TAG))) {
/* we have implicit OR explicit default node, get with-defaults module */
wdmod = ly_ctx_get_module_implemented(LYD_CTX(node), "ietf-netconf-with-defaults");
}
if (node->meta || wdmod) {
if (wdmod || node_has_printable_meta(node)) {
/* we will be printing metadata for these siblings */
pctx->first_leaflist = node;
}
Expand Down Expand Up @@ -848,7 +876,8 @@ json_print_meta_attr_leaflist(struct jsonpr_ctx *pctx)
LEVEL_INC;
LY_LIST_FOR(node, iter) {
PRINT_COMMA;
if ((iter->schema && (iter->meta || (iter->flags & LYD_DEFAULT))) || (opaq && opaq->attr)) {
if ((iter->schema && (node_has_printable_meta(iter) || (iter->flags & LYD_DEFAULT))) ||
(opaq && opaq->attr)) {
ly_print_(pctx->out, "%*s%s", INDENT, DO_FORMAT ? "{\n" : "{");
LEVEL_INC;

Expand Down
7 changes: 7 additions & 0 deletions src/printer_lyb.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ lyb_print_metadata(struct ly_out *out, const struct lyd_node *node, struct lyd_l
++count;
}
for (iter = node->meta; iter; iter = iter->next) {
if (!iter->value.realtype->plugin->print) {
continue;
}
if (count == UINT8_MAX) {
LOGERR(lybctx->lybctx->ctx, LY_EINT, "Maximum supported number of data node metadata is %u.", UINT8_MAX);
return LY_EINT;
Expand All @@ -784,6 +787,10 @@ lyb_print_metadata(struct ly_out *out, const struct lyd_node *node, struct lyd_l

/* write all the node metadata */
LY_LIST_FOR(node->meta, iter) {
if (!iter->value.realtype->plugin->print) {
continue;
}

/* model */
LY_CHECK_RET(lyb_print_model(out, iter->annotation->module, 0, lybctx->lybctx));

Expand Down
4 changes: 4 additions & 0 deletions src/printer_xml.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ xml_print_meta(struct xmlpr_ctx *pctx, const struct lyd_node *node)
}

for (meta = node->meta; meta; meta = meta->next) {
if (!meta->value.realtype->plugin->print) {
continue;
}

/* store the module of the default namespace, NULL because there is none */
ly_set_add(&ns_list, NULL, 0, NULL);

Expand Down
2 changes: 1 addition & 1 deletion src/printer_yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -2148,7 +2148,7 @@ yang_print_parsed_body(struct lys_ypr_ctx *pctx, const struct lysp_module *modp)

YPR_EXTRA_LINE(modp->extensions, pctx);

if (modp->exts) {
if (modp->exts && !(modp->exts->flags & LYS_INTERNAL)) {
YPR_EXTRA_LINE_PRINT(pctx);
yprp_extension_instances(pctx, LY_STMT_MODULE, 0, modp->exts, NULL);
}
Expand Down
4 changes: 3 additions & 1 deletion src/printer_yin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,9 @@ ypr_import_xmlns(struct lys_ypr_ctx *pctx, const struct lysp_module *modp, uint1
LY_ARRAY_COUNT_TYPE u;

LY_ARRAY_FOR(modp->imports, u){
ly_print_(pctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, modp->imports[u].prefix, modp->imports[u].module->ns);
if (!(modp->imports[u].flags & LYS_INTERNAL)) {
ly_print_(pctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, modp->imports[u].prefix, modp->imports[u].module->ns);
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/schema_compile_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -2681,12 +2681,15 @@ lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_nod
/* list ordering */
if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
if ((node->flags & (LYS_CONFIG_R | LYS_IS_OUTPUT | LYS_IS_NOTIF)) && (node->flags & LYS_ORDBY_MASK)) {
node->flags &= ~LYS_ORDBY_MASK;
LOGVRB("The ordered-by statement is ignored in lists representing %s (%s).",
(node->flags & LYS_IS_OUTPUT) ? "RPC/action output parameters" :
(ctx->compile_opts & LYS_IS_NOTIF) ? "notification content" : "state data", ctx->path);
node->flags &= ~LYS_ORDBY_MASK;
node->flags |= LYS_ORDBY_SYSTEM;
} else if (!(node->flags & LYS_ORDBY_MASK)) {
}
if (node->flags & (LYS_IS_OUTPUT | LYS_IS_NOTIF)) {
/* it is probably better not to order them */
node->flags |= LYS_ORDBY_USER;
} else if (!(node->flags & LYS_ORDBY_MASK) || (node->flags & LYS_CONFIG_R)) {
/* default ordering is system */
node->flags |= LYS_ORDBY_SYSTEM;
}
Expand Down
Loading

0 comments on commit ededb53

Please sign in to comment.