summaryrefslogtreecommitdiff
path: root/lib/northbound_oper.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/northbound_oper.c')
-rw-r--r--lib/northbound_oper.c42
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;
}