diff options
Diffstat (limited to 'lib/northbound_oper.c')
| -rw-r--r-- | lib/northbound_oper.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c index 27e37abd04..b5201c6306 100644 --- a/lib/northbound_oper.c +++ b/lib/northbound_oper.c @@ -72,6 +72,7 @@ struct nb_op_node_info { * @schema_path: the schema nodes for each node in the query string. # @query_tokstr: the query string tokenized with NUL bytes. * @query_tokens: the string pointers to each query token (node). + * @non_specific_predicate: tracks if a query_token is non-specific predicate. * @walk_root_level: The topmost specific node, +1 is where we start walking. * @walk_start_level: @walk_root_level + 1. * @query_base_level: the level the query string stops at and full walks @@ -85,6 +86,7 @@ struct nb_op_yield_state { const struct lysc_node **schema_path; char *query_tokstr; char **query_tokens; + uint8_t *non_specific_predicate; int walk_root_level; int walk_start_level; int query_base_level; @@ -158,6 +160,7 @@ static inline void nb_op_free_yield_state(struct nb_op_yield_state *ys, if (!nofree_tree && ys_root_node(ys)) lyd_free_all(ys_root_node(ys)); darr_free(ys->query_tokens); + darr_free(ys->non_specific_predicate); darr_free(ys->query_tokstr); darr_free(ys->schema_path); darr_free(ys->node_infos); @@ -809,6 +812,13 @@ static const struct lysc_node *nb_op_sib_first(struct nb_op_yield_state *ys, const struct lysc_node *first_sib; /* + * NOTE: when we want to handle root level walks we will need to use + * lys_getnext() to walk root level of each module and + * ly_ctx_get_module_iter() to walk the modules. + */ + assert(darr_len(ys->node_infos) > 0); + + /* * The top of the node stack points at @parent. * * If the schema path (original query) is longer than our current node @@ -816,7 +826,7 @@ static const struct lysc_node *nb_op_sib_first(struct nb_op_yield_state *ys, * base of the user query, return the next schema node from the query * string (schema_path). */ - assert(darr_last(ys->node_infos)->schema == parent); + assert(darr_last(ys->node_infos) != NULL && darr_last(ys->node_infos)->schema == parent); if (darr_lasti(ys->node_infos) < ys->query_base_level) return ys->schema_path[darr_lasti(ys->node_infos) + 1]; @@ -1012,10 +1022,14 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume) * should be kept. */ ret = nb_op_iter_leaf(ys, nn, xpath_child); + if (ret != NB_OK) + goto done; sib = nb_op_sib_next(ys, sib); continue; case LYS_LEAFLIST: ret = nb_op_iter_leaflist(ys, nn, xpath_child); + if (ret != NB_OK) + goto done; sib = nb_op_sib_next(ys, sib); continue; case LYS_CONTAINER: @@ -1133,18 +1147,23 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume) is_specific_node = false; if (list_start && at_clevel <= darr_lasti(ys->query_tokens) && + !ys->non_specific_predicate[at_clevel] && nb_op_schema_path_has_predicate(ys, at_clevel)) { err = lyd_new_path(&pni->inner->node, NULL, ys->query_tokens[at_clevel], NULL, 0, &node); if (!err) - /* predicate resolved to specific node */ is_specific_node = true; + else if (err == LY_EVALID) + ys->non_specific_predicate[at_clevel] = true; else { - flog_warn(EC_LIB_NB_OPERATIONAL_DATA, - "%s: unable to create node for specific query string: %s", + flog_err(EC_LIB_NB_OPERATIONAL_DATA, + "%s: unable to create node for specific query string: %s: %s", __func__, - ys->query_tokens[at_clevel]); + ys->query_tokens[at_clevel], + yang_ly_strerrcode(err)); + ret = NB_ERR; + goto done; } } @@ -1392,11 +1411,8 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume) */ if (!node) { - /* NOTE: can also use lyd_new_list2 here when available */ err = yang_lyd_new_list(ni[-1].inner, sib, - &ni->keys, - (struct lyd_node_inner * - *)&node); + &ni->keys, &node); if (err) { darr_pop(ys->node_infos); ret = NB_ERR_RESOURCE; @@ -1561,6 +1577,7 @@ static enum nb_error nb_op_yield(struct nb_op_yield_state *ys) static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, struct nb_node **last) { + struct nb_node **nb_nodes = NULL; const struct lysc_node *sn; struct nb_node *nblast; char *s, *s2; @@ -1579,6 +1596,11 @@ static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, */ nblast = nb_node_find(ys->xpath); if (!nblast) { + nb_nodes = nb_nodes_find(ys->xpath); + nblast = darr_len(nb_nodes) ? nb_nodes[0] : NULL; + darr_free(nb_nodes); + } + if (!nblast) { flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, ys->xpath); return NB_ERR; @@ -1605,6 +1627,7 @@ static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, /* create our arrays */ darr_append_n(ys->schema_path, count); darr_append_n(ys->query_tokens, count); + darr_append_nz(ys->non_specific_predicate, count); for (sn = nblast->snode; sn; sn = sn->parent) ys->schema_path[--count] = sn; @@ -1666,6 +1689,7 @@ error: darr_free(ys->query_tokstr); darr_free(ys->schema_path); darr_free(ys->query_tokens); + darr_free(ys->non_specific_predicate); return NB_ERR; } |
