File: | home/sharpd/frr3/lib/northbound_oper.c |
Warning: | line 1012, column 4 Value stored to 'ret' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * October 14 2023, Christian Hopps <chopps@labn.net> |
4 | * |
5 | * Copyright (C) 2018 NetDEF, Inc. |
6 | * Renato Westphal |
7 | * Copyright (c) 2023, LabN Consulting, L.L.C. |
8 | * |
9 | */ |
10 | |
11 | #include <zebra.h> |
12 | #include "darr.h" |
13 | #include "debug.h" |
14 | #include "frrevent.h" |
15 | #include "frrstr.h" |
16 | #include "lib_errors.h" |
17 | #include "monotime.h" |
18 | #include "northbound.h" |
19 | |
20 | /* |
21 | * YANG model yielding design restrictions: |
22 | * |
23 | * In order to be able to yield and guarantee we have a valid data tree at the |
24 | * point of yielding we must know that each parent has all it's siblings |
25 | * collected to represent a complete element. |
26 | * |
27 | * Basically, there should be a only single branch in the schema tree that |
28 | * supports yielding. In practice this means: |
29 | * |
30 | * list node schema with lookup next: |
31 | * - must not have any lookup-next list node sibling schema |
32 | * - must not have any list or container node siblings with lookup-next descendants. |
33 | * - any parent list nodes must also be lookup-next list nodes |
34 | * |
35 | * We must also process containers with lookup-next descendants last. |
36 | */ |
37 | |
38 | DEFINE_MTYPE_STATIC(LIB, NB_YIELD_STATE, "NB Yield State")static struct memtype MTYPE_NB_YIELD_STATE[1] __attribute__(( section(".data.mtypes"))) = { { .name = "NB Yield State", .next = ((void*)0), .n_alloc = 0, .size = 0, .ref = ((void*)0), } } ; static void _mtinit_NB_YIELD_STATE(void) __attribute__((constructor (1001))); static void _mtinit_NB_YIELD_STATE(void) { if (_mg_LIB .insert == ((void*)0)) _mg_LIB.insert = &_mg_LIB.types; MTYPE_NB_YIELD_STATE ->ref = _mg_LIB.insert; *_mg_LIB.insert = MTYPE_NB_YIELD_STATE ; _mg_LIB.insert = &MTYPE_NB_YIELD_STATE->next; } static void _mtfini_NB_YIELD_STATE(void) __attribute__((destructor) ); static void _mtfini_NB_YIELD_STATE(void) { if (MTYPE_NB_YIELD_STATE ->next) MTYPE_NB_YIELD_STATE->next->ref = MTYPE_NB_YIELD_STATE ->ref; *MTYPE_NB_YIELD_STATE->ref = MTYPE_NB_YIELD_STATE ->next; } _Static_assert(1, "please add a semicolon after this macro" ); |
39 | DEFINE_MTYPE_STATIC(LIB, NB_NODE_INFOS, "NB Node Infos")static struct memtype MTYPE_NB_NODE_INFOS[1] __attribute__((section (".data.mtypes"))) = { { .name = "NB Node Infos", .next = ((void *)0), .n_alloc = 0, .size = 0, .ref = ((void*)0), } }; static void _mtinit_NB_NODE_INFOS(void) __attribute__((constructor( 1001))); static void _mtinit_NB_NODE_INFOS(void) { if (_mg_LIB .insert == ((void*)0)) _mg_LIB.insert = &_mg_LIB.types; MTYPE_NB_NODE_INFOS ->ref = _mg_LIB.insert; *_mg_LIB.insert = MTYPE_NB_NODE_INFOS ; _mg_LIB.insert = &MTYPE_NB_NODE_INFOS->next; } static void _mtfini_NB_NODE_INFOS(void) __attribute__((destructor)) ; static void _mtfini_NB_NODE_INFOS(void) { if (MTYPE_NB_NODE_INFOS ->next) MTYPE_NB_NODE_INFOS->next->ref = MTYPE_NB_NODE_INFOS ->ref; *MTYPE_NB_NODE_INFOS->ref = MTYPE_NB_NODE_INFOS-> next; } _Static_assert(1, "please add a semicolon after this macro" ); |
40 | |
41 | /* Amount of time allowed to spend constructing oper-state prior to yielding */ |
42 | #define NB_OP_WALK_INTERVAL_MS50 50 |
43 | #define NB_OP_WALK_INTERVAL_US(50 * 1000) (NB_OP_WALK_INTERVAL_MS50 * 1000) |
44 | |
45 | /* ---------- */ |
46 | /* Data Types */ |
47 | /* ---------- */ |
48 | PREDECL_LIST(nb_op_walks)struct nb_op_walks_head { struct slist_head sh; }; struct nb_op_walks_item { struct slist_item si; }; _Static_assert(1, "please add a semicolon after this macro" ); |
49 | |
50 | /* |
51 | * This is our information about a node on the branch we are looking at |
52 | */ |
53 | struct nb_op_node_info { |
54 | struct lyd_node_inner *inner; |
55 | const struct lysc_node *schema; /* inner schema in case we rm inner */ |
56 | struct yang_list_keys keys; /* if list, keys to locate element */ |
57 | const void *list_entry; /* opaque entry from user or NULL */ |
58 | uint xpath_len; /* length of the xpath string for this node */ |
59 | uint niters; /* # list elems create this iteration */ |
60 | uint nents; /* # list elems create so far */ |
61 | bool_Bool query_specific_entry : 1; /* this info is specific specified */ |
62 | bool_Bool has_lookup_next : 1; /* if this node support lookup next */ |
63 | bool_Bool lookup_next_ok : 1; /* if this and all previous support */ |
64 | }; |
65 | |
66 | /** |
67 | * struct nb_op_yield_state - tracking required state for yielding. |
68 | * |
69 | * @xpath: current xpath representing the node_info stack. |
70 | * @xpath_orig: the original query string from the user |
71 | * @node_infos: the container stack for the walk from root to current |
72 | * @schema_path: the schema nodes for each node in the query string. |
73 | # @query_tokstr: the query string tokenized with NUL bytes. |
74 | * @query_tokens: the string pointers to each query token (node). |
75 | * @walk_root_level: The topmost specific node, +1 is where we start walking. |
76 | * @walk_start_level: @walk_root_level + 1. |
77 | * @query_base_level: the level the query string stops at and full walks |
78 | * commence below that. |
79 | */ |
80 | struct nb_op_yield_state { |
81 | /* Walking state */ |
82 | char *xpath; |
83 | char *xpath_orig; |
84 | struct nb_op_node_info *node_infos; |
85 | const struct lysc_node **schema_path; |
86 | char *query_tokstr; |
87 | char **query_tokens; |
88 | int walk_root_level; |
89 | int walk_start_level; |
90 | int query_base_level; |
91 | bool_Bool query_list_entry; /* XXX query was for a specific list entry */ |
92 | |
93 | /* Yielding state */ |
94 | bool_Bool query_did_entry; /* currently processing the entry */ |
95 | bool_Bool should_batch; |
96 | struct timeval start_time; |
97 | struct yang_translator *translator; |
98 | uint32_t flags; |
99 | nb_oper_data_cb cb; |
100 | void *cb_arg; |
101 | nb_oper_data_finish_cb finish; |
102 | void *finish_arg; |
103 | struct event *walk_ev; |
104 | struct nb_op_walks_item link; |
105 | }; |
106 | |
107 | DECLARE_LIST(nb_op_walks, struct nb_op_yield_state, link)static inline __attribute__((unused)) void nb_op_walks_init(struct nb_op_walks_head *h) { memset(h, 0, sizeof(*h)); h->sh.first = &typesafe_slist_sentinel; h->sh.last_next = &h-> sh.first; } static inline __attribute__((unused)) void nb_op_walks_fini (struct nb_op_walks_head *h) { memset(h, 0, sizeof(*h)); } static inline __attribute__((unused)) void nb_op_walks_add_head(struct nb_op_walks_head *h, struct nb_op_yield_state *item) { typesafe_list_add (&h->sh, &h->sh.first, &item->link.si); } static inline __attribute__((unused)) void nb_op_walks_add_tail (struct nb_op_walks_head *h, struct nb_op_yield_state *item) { typesafe_list_add(&h->sh, h->sh.last_next, &item ->link.si); } static inline __attribute__((unused)) void nb_op_walks_add_after (struct nb_op_walks_head *h, struct nb_op_yield_state *after, struct nb_op_yield_state *item) { struct slist_item **nextp; nextp = after ? &after->link.si.next : &h->sh. first; typesafe_list_add(&h->sh, nextp, &item-> link.si); } static inline __attribute__((unused)) struct nb_op_yield_state *nb_op_walks_del(struct nb_op_walks_head *h, struct nb_op_yield_state *item) { struct slist_item **iter = &h->sh.first; while (*iter != &typesafe_slist_sentinel && *iter != & item->link.si) iter = &(*iter)->next; if (*iter == & typesafe_slist_sentinel) return ((void*)0); h->sh.count--; *iter = item->link.si.next; if (item->link.si.next == & typesafe_slist_sentinel) h->sh.last_next = iter; item-> link.si.next = ((void*)0); return item; } static inline __attribute__ ((unused)) struct nb_op_yield_state *nb_op_walks_pop(struct nb_op_walks_head *h) { struct slist_item *sitem = h->sh.first; if (sitem == &typesafe_slist_sentinel) return ((void*)0); h->sh.count --; h->sh.first = sitem->next; if (h->sh.first == & typesafe_slist_sentinel) h->sh.last_next = &h->sh.first ; sitem->next = ((void*)0); return (__builtin_choose_expr( __builtin_types_compatible_p(typeof(&((struct nb_op_yield_state *)0)->link.si), typeof(sitem)) || __builtin_types_compatible_p (void *, typeof(sitem)), ({ typeof(((struct nb_op_yield_state *)0)->link.si) *__mptr = (void *)(sitem); (struct nb_op_yield_state *)((char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }), ({ typeof(((const struct nb_op_yield_state * )0)->link.si) *__mptr = (sitem); (const struct nb_op_yield_state *)((const char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }) )); } static inline __attribute__((unused)) void nb_op_walks_swap_all(struct nb_op_walks_head *a, struct nb_op_walks_head *b) { struct nb_op_walks_head tmp = *a; *a = *b; *b = tmp; if (a->sh.last_next == &b->sh.first) a->sh.last_next = &a->sh.first; if (b->sh.last_next == &a-> sh.first) b->sh.last_next = &b->sh.first; } static inline __attribute__((unused, pure)) const struct nb_op_yield_state *nb_op_walks_const_first(const struct nb_op_walks_head *h) { if (h->sh.first != &typesafe_slist_sentinel) return ( __builtin_choose_expr( __builtin_types_compatible_p(typeof(& ((struct nb_op_yield_state *)0)->link.si), typeof(h->sh .first)) || __builtin_types_compatible_p(void *, typeof(h-> sh.first)), ({ typeof(((struct nb_op_yield_state *)0)->link .si) *__mptr = (void *)(h->sh.first); (struct nb_op_yield_state *)((char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }), ({ typeof(((const struct nb_op_yield_state * )0)->link.si) *__mptr = (h->sh.first); (const struct nb_op_yield_state *)((const char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }) )); return ((void*)0); } static inline __attribute__ ((unused, pure)) const struct nb_op_yield_state *nb_op_walks_const_next (const struct nb_op_walks_head *h, const struct nb_op_yield_state *item) { const struct slist_item *sitem = &item->link .si; if (sitem->next != &typesafe_slist_sentinel) return (__builtin_choose_expr( __builtin_types_compatible_p(typeof( &((struct nb_op_yield_state *)0)->link.si), typeof(sitem ->next)) || __builtin_types_compatible_p(void *, typeof(sitem ->next)), ({ typeof(((struct nb_op_yield_state *)0)->link .si) *__mptr = (void *)(sitem->next); (struct nb_op_yield_state *)((char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }), ({ typeof(((const struct nb_op_yield_state * )0)->link.si) *__mptr = (sitem->next); (const struct nb_op_yield_state *)((const char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }) )); return ((void*)0); } static inline __attribute__ ((unused, pure)) struct nb_op_yield_state *nb_op_walks_first( struct nb_op_walks_head *h) { return (struct nb_op_yield_state *)nb_op_walks_const_first(h); } static inline __attribute__( (unused, pure)) struct nb_op_yield_state *nb_op_walks_next(struct nb_op_walks_head *h, struct nb_op_yield_state *item) { return (struct nb_op_yield_state *)nb_op_walks_const_next(h, item); } static inline __attribute__((unused, pure)) struct nb_op_yield_state *nb_op_walks_next_safe(struct nb_op_walks_head *h, struct nb_op_yield_state *item) { struct slist_item *sitem; if (!item) return ((void* )0); sitem = &item->link.si; if (sitem->next != & typesafe_slist_sentinel) return (__builtin_choose_expr( __builtin_types_compatible_p (typeof(&((struct nb_op_yield_state *)0)->link.si), typeof (sitem->next)) || __builtin_types_compatible_p(void *, typeof (sitem->next)), ({ typeof(((struct nb_op_yield_state *)0)-> link.si) *__mptr = (void *)(sitem->next); (struct nb_op_yield_state *)((char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }), ({ typeof(((const struct nb_op_yield_state * )0)->link.si) *__mptr = (sitem->next); (const struct nb_op_yield_state *)((const char *)__mptr - __builtin_offsetof(struct nb_op_yield_state , link.si)); }) )); return ((void*)0); } static inline __attribute__ ((unused, pure)) size_t nb_op_walks_count(const struct nb_op_walks_head *h) { return h->sh.count; } static inline __attribute__(( unused, pure)) _Bool nb_op_walks_anywhere(const struct nb_op_yield_state *item) { return item->link.si.next != ((void*)0); } static inline __attribute__((unused, pure)) _Bool nb_op_walks_member (const struct nb_op_walks_head *h, const struct nb_op_yield_state *item) { return typesafe_list_member(&h->sh, &item ->link.si); } _Static_assert(1, "please add a semicolon after this macro" ); |
108 | |
109 | /* ---------------- */ |
110 | /* Global Variables */ |
111 | /* ---------------- */ |
112 | |
113 | static struct event_loop *event_loop; |
114 | static struct nb_op_walks_head nb_op_walks; |
115 | |
116 | /* --------------------- */ |
117 | /* Function Declarations */ |
118 | /* --------------------- */ |
119 | |
120 | static enum nb_error nb_op_yield(struct nb_op_yield_state *ys); |
121 | static struct lyd_node *ys_root_node(struct nb_op_yield_state *ys); |
122 | |
123 | /* -------------------- */ |
124 | /* Function Definitions */ |
125 | /* -------------------- */ |
126 | |
127 | static inline struct nb_op_yield_state * |
128 | nb_op_create_yield_state(const char *xpath, struct yang_translator *translator, |
129 | uint32_t flags, bool_Bool should_batch, nb_oper_data_cb cb, |
130 | void *cb_arg, nb_oper_data_finish_cb finish, |
131 | void *finish_arg) |
132 | { |
133 | struct nb_op_yield_state *ys; |
134 | |
135 | ys = XCALLOC(MTYPE_NB_YIELD_STATE, sizeof(*ys))qcalloc(MTYPE_NB_YIELD_STATE, sizeof(*ys)); |
136 | ys->xpath = darr_strdup_cap(xpath, (size_t)XPATH_MAXLEN)({ size_t __size = strlen(xpath) + 1; char *__s = ((void*)0); ({ if ((ssize_t)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) < (ssize_t)(((ssize_t)((size_t)1024 ) > (ssize_t)__size) ? (size_t)((size_t)1024) : __size)) ( { ((__s)) = __darr_resize((__s), (((ssize_t)((size_t)1024) > (ssize_t)__size) ? (size_t)((size_t)1024) : __size), sizeof( ((__s))[0]), MTYPE_DARR_STR); }); (__s); }); strlcpy(__s, (xpath ), (((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s )) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 136, "lib/northbound_oper.c", __func__, }, .expr = "(__s) || !((size_t)__size)" , }; static const struct xref * const xref_p_256 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((__s) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((__s) || !((size_t)__size) ); }); if ((__s)) { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 136, "lib/northbound_oper.c" , __func__, }, .expr = "(long long)darr_cap(__s) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_257 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)); } ); (((struct darr_metadata *)(__s)) - 1)->len = ((size_t)__size ); } } while (0); __s; }); |
137 | ys->xpath_orig = darr_strdup(xpath)({ size_t __size = strlen(xpath) + 1; char *__s = ((void*)0); ({ if ((ssize_t)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) < (ssize_t)(((ssize_t)(0) > (ssize_t )__size) ? (size_t)(0) : __size)) ({ ((__s)) = __darr_resize( (__s), (((ssize_t)(0) > (ssize_t)__size) ? (size_t)(0) : __size ), sizeof(((__s))[0]), MTYPE_DARR_STR); }); (__s); }); strlcpy (__s, (xpath), (((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 137, "lib/northbound_oper.c", __func__, }, .expr = "(__s) || !((size_t)__size)" , }; static const struct xref * const xref_p_258 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((__s) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((__s) || !((size_t)__size) ); }); if ((__s)) { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 137, "lib/northbound_oper.c" , __func__, }, .expr = "(long long)darr_cap(__s) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_259 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)); } ); (((struct darr_metadata *)(__s)) - 1)->len = ((size_t)__size ); } } while (0); __s; }); |
138 | ys->translator = translator; |
139 | ys->flags = flags; |
140 | ys->should_batch = should_batch; |
141 | ys->cb = cb; |
142 | ys->cb_arg = cb_arg; |
143 | ys->finish = finish; |
144 | ys->finish_arg = finish_arg; |
145 | |
146 | nb_op_walks_add_tail(&nb_op_walks, ys); |
147 | |
148 | return ys; |
149 | } |
150 | |
151 | static inline void nb_op_free_yield_state(struct nb_op_yield_state *ys, |
152 | bool_Bool nofree_tree) |
153 | { |
154 | if (ys) { |
155 | EVENT_OFF(ys->walk_ev)do { if ((ys->walk_ev)) event_cancel(&(ys->walk_ev) ); } while (0); |
156 | nb_op_walks_del(&nb_op_walks, ys); |
157 | /* if we have a branch then free up it's libyang tree */ |
158 | if (!nofree_tree && ys_root_node(ys)) |
159 | lyd_free_all(ys_root_node(ys)); |
160 | darr_free(ys->query_tokens)do { if ((ys->query_tokens)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->query_tokens)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->query_tokens) = ((void*)0); } } while (0); |
161 | darr_free(ys->query_tokstr)do { if ((ys->query_tokstr)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->query_tokstr)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->query_tokstr) = ((void*)0); } } while (0); |
162 | darr_free(ys->schema_path)do { if ((ys->schema_path)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->schema_path)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->schema_path) = ((void*)0); } } while (0); |
163 | darr_free(ys->node_infos)do { if ((ys->node_infos)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->node_infos)) - 1); do { qfree (__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->node_infos) = ((void*)0); } } while (0); |
164 | darr_free(ys->xpath_orig)do { if ((ys->xpath_orig)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->xpath_orig)) - 1); do { qfree (__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->xpath_orig) = ((void*)0); } } while (0); |
165 | darr_free(ys->xpath)do { if ((ys->xpath)) { struct darr_metadata *__meta = ((( struct darr_metadata *)(ys->xpath)) - 1); do { qfree(__meta ->mtype, __meta); __meta = ((void*)0); } while (0); (ys-> xpath) = ((void*)0); } } while (0); |
166 | XFREE(MTYPE_NB_YIELD_STATE, ys)do { qfree(MTYPE_NB_YIELD_STATE, ys); ys = ((void*)0); } while (0); |
167 | } |
168 | } |
169 | |
170 | static const struct lysc_node *ys_get_walk_stem_tip(struct nb_op_yield_state *ys) |
171 | { |
172 | if (ys->walk_start_level <= 0) |
173 | return NULL((void*)0); |
174 | return ys->node_infos[ys->walk_start_level - 1].schema; |
175 | } |
176 | |
177 | static struct lyd_node *ys_root_node(struct nb_op_yield_state *ys) |
178 | { |
179 | if (!darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len)) |
180 | return NULL((void*)0); |
181 | return &ys->node_infos[0].inner->node; |
182 | } |
183 | |
184 | static void ys_trim_xpath(struct nb_op_yield_state *ys) |
185 | { |
186 | uint len = darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); |
187 | |
188 | if (len == 0) |
189 | darr_setlen(ys->xpath, 1)do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 189, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->xpath) || !(1)", }; static const struct xref * const xref_p_260 __attribute__((used, section( "xref_array"))) = &(_xref.xref); if (__builtin_expect(((ys ->xpath) || !(1)) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while ((ys->xpath) || !(1)); }); if ( (ys->xpath)) { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 189, "lib/northbound_oper.c" , __func__, }, .expr = "(long long)darr_cap(ys->xpath) >= (long long)(1)" , }; static const struct xref * const xref_p_261 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(1)) ? 0 : 1 , 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(1)); }); ( ((struct darr_metadata *)(ys->xpath)) - 1)->len = (1); } } while (0); |
190 | else |
191 | darr_setlen(ys->xpath, darr_last(ys->node_infos)->xpath_len + 1)do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 191, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->xpath) || !(({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? &(ys->node_infos)[__len - 1] : ((void*)0)); })->xpath_len + 1)" , }; static const struct xref * const xref_p_262 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((ys->xpath) || !(({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos )) - 1)->len); ((__len > 0) ? &(ys->node_infos)[ __len - 1] : ((void*)0)); })->xpath_len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (( ys->xpath) || !(({ uint __len = (((ys->node_infos) == ( (void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos )) - 1)->len); ((__len > 0) ? &(ys->node_infos)[ __len - 1] : ((void*)0)); })->xpath_len + 1)); }); if ((ys ->xpath)) { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 191, "lib/northbound_oper.c" , __func__, }, .expr = "(long long)darr_cap(ys->xpath) >= (long long)(({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? &(ys->node_infos)[__len - 1] : ((void*)0)); })->xpath_len + 1)" , }; static const struct xref * const xref_p_263 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? & (ys->node_infos)[__len - 1] : ((void*)0)); })->xpath_len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void *)0)); } while ((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(({ uint __len = (((ys->node_infos) == ((void* )0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1 )->len); ((__len > 0) ? &(ys->node_infos)[__len - 1] : ((void*)0)); })->xpath_len + 1)); }); (((struct darr_metadata *)(ys->xpath)) - 1)->len = (({ uint __len = (((ys-> node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys ->node_infos)) - 1)->len); ((__len > 0) ? &(ys-> node_infos)[__len - 1] : ((void*)0)); })->xpath_len + 1); } } while (0); |
192 | ys->xpath[darr_len(ys->xpath)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->len) - 1] = 0; |
193 | } |
194 | |
195 | static void ys_pop_inner(struct nb_op_yield_state *ys) |
196 | { |
197 | uint len = darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); |
198 | |
199 | assert(len)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 199, "lib/northbound_oper.c" , __func__, }, .expr = "len", }; static const struct xref * const xref_p_264 __attribute__((used, section("xref_array"))) = & (_xref.xref); if (__builtin_expect((len) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (len); }); |
200 | darr_setlen(ys->node_infos, len - 1)do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 200, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->node_infos) || !(len - 1)", } ; static const struct xref * const xref_p_265 __attribute__(( used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((ys->node_infos) || !(len - 1)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((ys->node_infos) || !(len - 1)); }); if ((ys->node_infos)) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void *)0)), (XREFT_ASSERT), 200, "lib/northbound_oper.c", __func__ , }, .expr = "(long long)darr_cap(ys->node_infos) >= (long long)(len - 1)" , }; static const struct xref * const xref_p_266 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->cap) >= (long long)(len - 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref , ((void*)0)); } while ((long long)(((ys->node_infos) == ( (void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos )) - 1)->cap) >= (long long)(len - 1)); }); (((struct darr_metadata *)(ys->node_infos)) - 1)->len = (len - 1); } } while ( 0); |
201 | ys_trim_xpath(ys); |
202 | } |
203 | |
204 | static void nb_op_get_keys(struct lyd_node_inner *list_node, |
205 | struct yang_list_keys *keys) |
206 | { |
207 | struct lyd_node *child; |
208 | uint n = 0; |
209 | |
210 | keys->num = 0; |
211 | LY_LIST_FOR (list_node->child, child)for ((child) = (list_node->child); (child); (child) = (child )->next) { |
212 | if (!lysc_is_key(child->schema)((!child->schema || (child->schema->nodetype != 0x0004 ) || !(child->schema->flags & 0x0100)) ? 0 : 1)) |
213 | break; |
214 | strlcpy(keys->key[n], yang_dnode_get_string(child, NULL((void*)0)), |
215 | sizeof(keys->key[n])); |
216 | n++; |
217 | } |
218 | |
219 | keys->num = n; |
220 | } |
221 | |
222 | /** |
223 | * __move_back_to_next() - move back to the next lookup-next schema |
224 | */ |
225 | static bool_Bool __move_back_to_next(struct nb_op_yield_state *ys, int i) |
226 | { |
227 | struct nb_op_node_info *ni; |
228 | int j; |
229 | |
230 | /* |
231 | * We will free the subtree we are trimming back to, or we will be done |
232 | * with the walk and will free the root on cleanup. |
233 | */ |
234 | |
235 | /* pop any node_info we dropped below on entry */ |
236 | for (j = darr_ilen(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1; j > i; j--) |
237 | ys_pop_inner(ys); |
238 | |
239 | for (; i >= ys->walk_root_level; i--) { |
240 | if (ys->node_infos[i].has_lookup_next) |
241 | break; |
242 | ys_pop_inner(ys); |
243 | } |
244 | |
245 | if (i < ys->walk_root_level) |
246 | return false0; |
247 | |
248 | ni = &ys->node_infos[i]; |
249 | |
250 | /* |
251 | * The i'th node has been lost after a yield so trim it from the tree |
252 | * now. |
253 | */ |
254 | lyd_free_tree(&ni->inner->node); |
255 | ni->inner = NULL((void*)0); |
256 | ni->list_entry = NULL((void*)0); |
257 | |
258 | /* |
259 | * Leave the empty-of-data node_info on top, __walk will deal with |
260 | * this, by doing a lookup-next with the keys which we still have. |
261 | */ |
262 | |
263 | return true1; |
264 | } |
265 | |
266 | static void nb_op_resume_data_tree(struct nb_op_yield_state *ys) |
267 | { |
268 | struct nb_op_node_info *ni; |
269 | struct nb_node *nn; |
270 | const void *parent_entry; |
271 | const void *list_entry; |
272 | uint i; |
273 | |
274 | /* |
275 | * IMPORTANT: On yielding: we always yield during list iteration and |
276 | * after the initial list element has been created and handled, so the |
277 | * top of the yield stack will always point at a list node. |
278 | * |
279 | * Additionally, that list node has been processed and was in the |
280 | * process of being "get_next"d when we yielded. We process the |
281 | * lookup-next list node last so all the rest of the data (to the left) |
282 | * has been gotten. NOTE: To keep this simple we will require only a |
283 | * single lookup-next sibling in any parents list of children. |
284 | * |
285 | * Walk the rightmost branch (the node info stack) from base to tip |
286 | * verifying all list nodes are still present. If not we backup to the |
287 | * node which has a lookup next, and we prune the branch to this node. |
288 | * If the list node that went away is the topmost we will be using |
289 | * lookup_next, but if it's a parent then the list_entry will have been |
290 | * restored. |
291 | */ |
292 | darr_foreach_i (ys->node_infos, i)for ((i) = 0; (i) < (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)-> len); (i)++) { |
293 | ni = &ys->node_infos[i]; |
294 | nn = ni->schema->priv; |
295 | |
296 | if (CHECK_FLAG(ni->schema->nodetype, LYS_CONTAINER)((ni->schema->nodetype) & (0x0001))) |
297 | continue; |
298 | |
299 | assert(ni->list_entry != NULL ||({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 300, "lib/northbound_oper.c" , __func__, }, .expr = "ni->list_entry != NULL || ni == darr_last(ys->node_infos)" , }; static const struct xref * const xref_p_267 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((ni->list_entry != ((void*)0) || ni == ({ uint __len = (( (ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? & (ys->node_infos)[__len - 1] : ((void*)0)); })) ? 0 : 1, 0) ) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( ni->list_entry != ((void*)0) || ni == ({ uint __len = (((ys ->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? & (ys->node_infos)[__len - 1] : ((void*)0)); })); }) |
300 | ni == darr_last(ys->node_infos))({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 300, "lib/northbound_oper.c" , __func__, }, .expr = "ni->list_entry != NULL || ni == darr_last(ys->node_infos)" , }; static const struct xref * const xref_p_267 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((ni->list_entry != ((void*)0) || ni == ({ uint __len = (( (ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? & (ys->node_infos)[__len - 1] : ((void*)0)); })) ? 0 : 1, 0) ) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( ni->list_entry != ((void*)0) || ni == ({ uint __len = (((ys ->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); ((__len > 0) ? & (ys->node_infos)[__len - 1] : ((void*)0)); })); }); |
301 | |
302 | /* Verify the entry is still present */ |
303 | parent_entry = (i == 0 ? NULL((void*)0) : ni[-1].list_entry); |
304 | list_entry = nb_callback_lookup_entry(nn, parent_entry, |
305 | &ni->keys); |
306 | if (!list_entry || list_entry != ni->list_entry) { |
307 | /* May be NULL or a different pointer |
308 | * move back to first of |
309 | * container with last lookup_next list node |
310 | * (which may be this one) and get next. |
311 | */ |
312 | if (!__move_back_to_next(ys, i)) |
313 | DEBUGD(&nb_dbg_events,do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: Nothing to resume after delete during walk (yield)" ), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 315, "lib/northbound_oper.c", __func__, }, .fmtstring = ("%s: Nothing to resume after delete during walk (yield)" ), .priority = (7), .ec = (0), .args = ("__func__"), }; static const struct xref * const xref_p_268 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Nothing to resume after delete during walk (yield)" ), __func__); } while (0); } while (0) |
314 | "%s: Nothing to resume after delete during walk (yield)",do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: Nothing to resume after delete during walk (yield)" ), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 315, "lib/northbound_oper.c", __func__, }, .fmtstring = ("%s: Nothing to resume after delete during walk (yield)" ), .priority = (7), .ec = (0), .args = ("__func__"), }; static const struct xref * const xref_p_268 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Nothing to resume after delete during walk (yield)" ), __func__); } while (0); } while (0) |
315 | __func__)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: Nothing to resume after delete during walk (yield)" ), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 315, "lib/northbound_oper.c", __func__, }, .fmtstring = ("%s: Nothing to resume after delete during walk (yield)" ), .priority = (7), .ec = (0), .args = ("__func__"), }; static const struct xref * const xref_p_268 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Nothing to resume after delete during walk (yield)" ), __func__); } while (0); } while (0); |
316 | return; |
317 | } |
318 | } |
319 | } |
320 | |
321 | /* |
322 | * Can only yield if all list nodes to root have lookup_next() callbacks |
323 | * |
324 | * In order to support lookup_next() the list_node get_next() callback |
325 | * needs to return ordered (i.e., sorted) results. |
326 | */ |
327 | |
328 | /* ======================= */ |
329 | /* Start of walk init code */ |
330 | /* ======================= */ |
331 | |
332 | /** |
333 | * __xpath_pop_node() - remove the last node from xpath string |
334 | * @xpath: an xpath string |
335 | * |
336 | * Return: NB_OK or NB_ERR_NOT_FOUND if nothing left to pop. |
337 | */ |
338 | static int __xpath_pop_node(char *xpath) |
339 | { |
340 | int len = strlen(xpath); |
341 | bool_Bool abs = xpath[0] == '/'; |
342 | char *slash; |
343 | |
344 | /* "//" or "/" => NULL */ |
345 | if (abs && (len == 1 || (len == 2 && xpath[1] == '/'))) |
346 | return NB_ERR_NOT_FOUND; |
347 | |
348 | slash = (char *)frrstr_back_to_char(xpath, '/'); |
349 | /* "/foo/bar/" or "/foo/bar//" => "/foo " */ |
350 | if (slash && slash == &xpath[len - 1]) { |
351 | xpath[--len] = 0; |
352 | slash = (char *)frrstr_back_to_char(xpath, '/'); |
353 | if (slash && slash == &xpath[len - 1]) { |
354 | xpath[--len] = 0; |
355 | slash = (char *)frrstr_back_to_char(xpath, '/'); |
356 | } |
357 | } |
358 | if (!slash) |
359 | return NB_ERR_NOT_FOUND; |
360 | *slash = 0; |
361 | return NB_OK; |
362 | } |
363 | |
364 | /** |
365 | * nb_op_xpath_to_trunk() - generate a lyd_node tree (trunk) using an xpath. |
366 | * @xpath_in: xpath query string to build trunk from. |
367 | * @dnode: resulting tree (trunk) |
368 | * |
369 | * Use the longest prefix of @xpath_in as possible to resolve to a tree (trunk). |
370 | * This is logically as if we walked along the xpath string resolving each |
371 | * nodename reference (in particular list nodes) until we could not. |
372 | * |
373 | * Return: error if any, if no error then @dnode contains the tree (trunk). |
374 | */ |
375 | static enum nb_error nb_op_xpath_to_trunk(const char *xpath_in, |
376 | struct lyd_node **trunk) |
377 | { |
378 | char *xpath = NULL((void*)0); |
379 | enum nb_error ret = NB_OK; |
380 | LY_ERR err; |
381 | |
382 | darr_in_strdup(xpath, xpath_in)({ size_t __size = strlen(xpath_in) + 1; do { if ((xpath)) (( (struct darr_metadata *)(xpath)) - 1)->len = 0; } while (0 ); ({ if ((ssize_t)(((xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath)) - 1)->cap) < (ssize_t)(((size_t)(1) > __size ) ? (size_t)(1) : __size)) ({ ((xpath)) = __darr_resize((xpath ), (((size_t)(1) > __size) ? (size_t)(1) : __size), sizeof (((xpath))[0]), MTYPE_DARR_STR); }); (xpath); }); strlcpy(xpath , (xpath_in), (((xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath)) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 382, "lib/northbound_oper.c", __func__, }, .expr = "((xpath)) || !((size_t)__size)" , }; static const struct xref * const xref_p_269 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((xpath)) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((xpath)) || !((size_t)__size )); }); if (((xpath))) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 382, "lib/northbound_oper.c", __func__, }, .expr = "(long long)darr_cap((xpath)) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_270 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)((((xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((xpath))) - 1)->cap) >= (long long)((size_t)__size) ) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0 )); } while ((long long)((((xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((xpath))) - 1)->cap) >= (long long)(( size_t)__size)); }); (((struct darr_metadata *)((xpath))) - 1 )->len = ((size_t)__size); } } while (0); xpath; }); |
383 | for (;;) { |
384 | err = lyd_new_path2(NULL((void*)0), ly_native_ctx, xpath, NULL((void*)0), 0, 0, |
385 | LYD_NEW_PATH_UPDATE0x01, NULL((void*)0), trunk); |
386 | if (err == LY_SUCCESS) |
387 | break; |
388 | |
389 | ret = __xpath_pop_node(xpath); |
390 | if (ret != NB_OK) |
391 | break; |
392 | } |
393 | darr_free(xpath)do { if ((xpath)) { struct darr_metadata *__meta = (((struct darr_metadata *)(xpath)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (xpath) = ((void*)0); } } while ( 0); |
394 | return ret; |
395 | } |
396 | |
397 | /* |
398 | * Finish initializing the node info based on the xpath string, and previous |
399 | * node_infos on the stack. If this node is a list node, obtain the specific |
400 | * list-entry object. |
401 | */ |
402 | static enum nb_error nb_op_ys_finalize_node_info(struct nb_op_yield_state *ys, |
403 | uint index) |
404 | { |
405 | struct nb_op_node_info *ni = &ys->node_infos[index]; |
406 | struct lyd_node_inner *inner = ni->inner; |
407 | struct nb_node *nn = ni->schema->priv; |
408 | bool_Bool yield_ok = ys->finish != NULL((void*)0); |
409 | |
410 | ni->has_lookup_next = nn->cbs.lookup_next != NULL((void*)0); |
411 | |
412 | /* track the last list_entry until updated by new list node */ |
413 | ni->list_entry = index == 0 ? NULL((void*)0) : ni[-1].list_entry; |
414 | |
415 | /* Assert that we are walking the rightmost branch */ |
416 | assert(!inner->parent || &inner->node == inner->parent->child->prev)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 416, "lib/northbound_oper.c" , __func__, }, .expr = "!inner->parent || &inner->node == inner->parent->child->prev" , }; static const struct xref * const xref_p_271 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!inner->parent || &inner->node == inner->parent ->child->prev) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while (!inner->parent || &inner-> node == inner->parent->child->prev); }); |
417 | |
418 | if (CHECK_FLAG(inner->schema->nodetype, LYS_CONTAINER)((inner->schema->nodetype) & (0x0001))) { |
419 | /* containers have only zero or one child on a branch of a tree */ |
420 | inner = (struct lyd_node_inner *)inner->child; |
421 | assert(!inner || inner->prev == &inner->node)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 421, "lib/northbound_oper.c" , __func__, }, .expr = "!inner || inner->prev == &inner->node" , }; static const struct xref * const xref_p_272 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!inner || inner->prev == &inner->node) ? 0 : 1, 0 )) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( !inner || inner->prev == &inner->node); }); |
422 | ni->lookup_next_ok = yield_ok && |
423 | (index == 0 || ni[-1].lookup_next_ok); |
424 | return NB_OK; |
425 | } |
426 | |
427 | assert(CHECK_FLAG(inner->schema->nodetype, LYS_LIST))({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 427, "lib/northbound_oper.c" , __func__, }, .expr = "CHECK_FLAG(inner->schema->nodetype, LYS_LIST)" , }; static const struct xref * const xref_p_273 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((inner->schema->nodetype) & (0x0010))) ? 0 : 1, 0 )) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( ((inner->schema->nodetype) & (0x0010))); }); |
428 | |
429 | ni->lookup_next_ok = yield_ok && ni->has_lookup_next && |
430 | (index == 0 || ni[-1].lookup_next_ok); |
431 | |
432 | nb_op_get_keys(inner, &ni->keys); |
433 | |
434 | /* A list entry cannot be present in a tree w/o it's keys */ |
435 | assert(ni->keys.num == yang_snode_num_keys(inner->schema))({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 435, "lib/northbound_oper.c" , __func__, }, .expr = "ni->keys.num == yang_snode_num_keys(inner->schema)" , }; static const struct xref * const xref_p_274 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((ni->keys.num == yang_snode_num_keys(inner->schema)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (ni->keys.num == yang_snode_num_keys(inner->schema )); }); |
436 | |
437 | /* |
438 | * Get this nodes opaque list_entry object |
439 | */ |
440 | |
441 | if (!nn->cbs.lookup_entry) { |
442 | flog_warn(EC_LIB_NB_OPERATIONAL_DATA,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: data path doesn't support iteration over operational data: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 444, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: data path doesn't support iteration over operational data: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->xpath"), }; static const struct xref * const xref_p_275 __attribute__((used, section("xref_array"))) = & (_xref.xref); zlog_ref(&_xref, ("%s: data path doesn't support iteration over operational data: %s" ), __func__, ys->xpath); } while (0) |
443 | "%s: data path doesn't support iteration over operational data: %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: data path doesn't support iteration over operational data: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 444, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: data path doesn't support iteration over operational data: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->xpath"), }; static const struct xref * const xref_p_275 __attribute__((used, section("xref_array"))) = & (_xref.xref); zlog_ref(&_xref, ("%s: data path doesn't support iteration over operational data: %s" ), __func__, ys->xpath); } while (0) |
444 | __func__, ys->xpath)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: data path doesn't support iteration over operational data: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 444, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: data path doesn't support iteration over operational data: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->xpath"), }; static const struct xref * const xref_p_275 __attribute__((used, section("xref_array"))) = & (_xref.xref); zlog_ref(&_xref, ("%s: data path doesn't support iteration over operational data: %s" ), __func__, ys->xpath); } while (0); |
445 | return NB_ERR_NOT_FOUND; |
446 | } |
447 | |
448 | /* ni->list_entry starts as the parent entry of this node */ |
449 | ni->list_entry = nb_callback_lookup_entry(nn, ni->list_entry, &ni->keys); |
450 | if (ni->list_entry == NULL((void*)0)) { |
451 | flog_warn(EC_LIB_NB_OPERATIONAL_DATA,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: list entry lookup failed" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 452, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: list entry lookup failed"), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__"), }; static const struct xref * const xref_p_276 __attribute__((used, section("xref_array"))) = &(_xref.xref ); zlog_ref(&_xref, ("%s: list entry lookup failed"), __func__ ); } while (0) |
452 | "%s: list entry lookup failed", __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: list entry lookup failed" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 452, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: list entry lookup failed"), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__"), }; static const struct xref * const xref_p_276 __attribute__((used, section("xref_array"))) = &(_xref.xref ); zlog_ref(&_xref, ("%s: list entry lookup failed"), __func__ ); } while (0); |
453 | return NB_ERR_NOT_FOUND; |
454 | } |
455 | |
456 | /* |
457 | * By definition any list element we can get a specific list_entry for |
458 | * is specific. |
459 | */ |
460 | ni->query_specific_entry = true1; |
461 | |
462 | return NB_OK; |
463 | } |
464 | |
465 | /** |
466 | * nb_op_ys_init_node_infos() - initialize the node info stack from the query. |
467 | * @ys: the yield state for this tree walk. |
468 | * |
469 | * On starting a walk we initialize the node_info stack as deeply as possible |
470 | * based on specific node references in the query string. We will stop at the |
471 | * point in the query string that is not specific (e.g., a list element without |
472 | * it's keys predicate) |
473 | * |
474 | * Return: northbound return value (enum nb_error) |
475 | */ |
476 | static enum nb_error nb_op_ys_init_node_infos(struct nb_op_yield_state *ys) |
477 | { |
478 | struct nb_op_node_info *ni; |
479 | struct lyd_node_inner *inner; |
480 | struct lyd_node *node; |
481 | enum nb_error ret; |
482 | uint i, len; |
483 | char *tmp; |
484 | |
485 | /* |
486 | * Obtain the trunk of the data node tree of the query. |
487 | * |
488 | * These are the nodes from the root that could be specifically |
489 | * identified with the query string. The trunk ends when a no specific |
490 | * node could be identified (e.g., a list-node name with no keys). |
491 | */ |
492 | |
493 | ret = nb_op_xpath_to_trunk(ys->xpath, &node); |
494 | if (ret || !node) { |
495 | flog_warn(EC_LIB_LIBYANG,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: can't instantiate concrete path using xpath: %s" ), .hashu32 = {(4), (EC_LIB_LIBYANG)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (& _xrefdata.xrefdata), (XREFT_LOGMSG), 497, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: can't instantiate concrete path using xpath: %s" ), .priority = (4), .ec = (EC_LIB_LIBYANG), .args = ("__func__, ys->xpath" ), }; static const struct xref * const xref_p_277 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: can't instantiate concrete path using xpath: %s" ), __func__, ys->xpath); } while (0) |
496 | "%s: can't instantiate concrete path using xpath: %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: can't instantiate concrete path using xpath: %s" ), .hashu32 = {(4), (EC_LIB_LIBYANG)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (& _xrefdata.xrefdata), (XREFT_LOGMSG), 497, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: can't instantiate concrete path using xpath: %s" ), .priority = (4), .ec = (EC_LIB_LIBYANG), .args = ("__func__, ys->xpath" ), }; static const struct xref * const xref_p_277 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: can't instantiate concrete path using xpath: %s" ), __func__, ys->xpath); } while (0) |
497 | __func__, ys->xpath)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: can't instantiate concrete path using xpath: %s" ), .hashu32 = {(4), (EC_LIB_LIBYANG)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (& _xrefdata.xrefdata), (XREFT_LOGMSG), 497, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: can't instantiate concrete path using xpath: %s" ), .priority = (4), .ec = (EC_LIB_LIBYANG), .args = ("__func__, ys->xpath" ), }; static const struct xref * const xref_p_277 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: can't instantiate concrete path using xpath: %s" ), __func__, ys->xpath); } while (0); |
498 | if (!ret) |
499 | ret = NB_ERR_NOT_FOUND; |
500 | return ret; |
501 | } |
502 | while (node && |
503 | !CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST)((node->schema->nodetype) & (0x0001 | 0x0010))) |
504 | node = &node->parent->node; |
505 | if (!node) |
506 | return NB_ERR_NOT_FOUND; |
507 | |
508 | inner = (struct lyd_node_inner *)node; |
509 | for (len = 1; inner->parent; len++) |
510 | inner = inner->parent; |
511 | |
512 | |
513 | darr_append_nz_mt(ys->node_infos, len, MTYPE_NB_NODE_INFOS)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( { if ((ssize_t)(((ys->node_infos) == ((void*)0)) ? 0 : ((( struct darr_metadata *)(ys->node_infos)) - 1)->cap) < (ssize_t)(__len + (len))) ({ ((ys->node_infos)) = __darr_resize ((ys->node_infos), (__len + (len)), sizeof(((ys->node_infos ))[0]), MTYPE_NB_NODE_INFOS); }); (ys->node_infos); }); (( (struct darr_metadata *)(ys->node_infos)) - 1)->len = __len + (len); if (1) memset(&(ys->node_infos)[__len], 0, ( len)*sizeof((ys->node_infos)[0])); &(ys->node_infos )[__len]; }); |
514 | |
515 | /* |
516 | * For each node find the prefix of the xpath query that identified it |
517 | * -- save the prefix length. |
518 | */ |
519 | inner = (struct lyd_node_inner *)node; |
520 | for (i = len; i > 0; i--, inner = inner->parent) { |
521 | ni = &ys->node_infos[i - 1]; |
522 | ni->inner = inner; |
523 | ni->schema = inner->schema; |
524 | /* |
525 | * NOTE: we could build this by hand with a litte more effort, |
526 | * but this simple implementation works and won't be expensive |
527 | * since the number of nodes is small and only done once per |
528 | * query. |
529 | */ |
530 | tmp = yang_dnode_get_path(&inner->node, NULL((void*)0), 0); |
531 | ni->xpath_len = strlen(tmp); |
532 | |
533 | /* Replace users supplied xpath with the libyang returned value */ |
534 | if (i == len) |
535 | darr_in_strdup(ys->xpath, tmp)({ size_t __size = strlen(tmp) + 1; do { if ((ys->xpath)) ( ((struct darr_metadata *)(ys->xpath)) - 1)->len = 0; } while (0); ({ if ((ssize_t)(((ys->xpath) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->xpath)) - 1)->cap) < ( ssize_t)(((size_t)(1) > __size) ? (size_t)(1) : __size)) ( { ((ys->xpath)) = __darr_resize((ys->xpath), (((size_t) (1) > __size) ? (size_t)(1) : __size), sizeof(((ys->xpath ))[0]), MTYPE_DARR_STR); }); (ys->xpath); }); strlcpy(ys-> xpath, (tmp), (((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 535, "lib/northbound_oper.c" , __func__, }, .expr = "((ys->xpath)) || !((size_t)__size)" , }; static const struct xref * const xref_p_278 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((ys->xpath)) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((ys->xpath)) || !((size_t )__size)); }); if (((ys->xpath))) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void *)0)), (XREFT_ASSERT), 535, "lib/northbound_oper.c", __func__ , }, .expr = "(long long)darr_cap((ys->xpath)) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_279 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)((((ys->xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((ys->xpath))) - 1)->cap) >= (long long )((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while ((long long)((((ys->xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((ys->xpath)) ) - 1)->cap) >= (long long)((size_t)__size)); }); (((struct darr_metadata *)((ys->xpath))) - 1)->len = ((size_t)__size ); } } while (0); ys->xpath; }); |
536 | |
537 | /* The prefix must match the prefix of the stored xpath */ |
538 | assert(!strncmp(tmp, ys->xpath, ni->xpath_len))({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 538, "lib/northbound_oper.c" , __func__, }, .expr = "!strncmp(tmp, ys->xpath, ni->xpath_len)" , }; static const struct xref * const xref_p_280 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!strncmp(tmp, ys->xpath, ni->xpath_len)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (! strncmp(tmp, ys->xpath, ni->xpath_len)); }); |
539 | free(tmp); |
540 | } |
541 | |
542 | /* |
543 | * Obtain the specific list-entry objects for each list node on the |
544 | * trunk and finish initializing the node_info structs. |
545 | */ |
546 | |
547 | darr_foreach_i (ys->node_infos, i)for ((i) = 0; (i) < (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)-> len); (i)++) { |
548 | ret = nb_op_ys_finalize_node_info(ys, i); |
549 | if (ret != NB_OK) { |
550 | darr_free(ys->node_infos)do { if ((ys->node_infos)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->node_infos)) - 1); do { qfree (__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->node_infos) = ((void*)0); } } while (0); |
551 | return ret; |
552 | } |
553 | } |
554 | |
555 | ys->walk_start_level = darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); |
556 | |
557 | ys->walk_root_level = (int)ys->walk_start_level - 1; |
558 | |
559 | return NB_OK; |
560 | } |
561 | |
562 | /* ================ */ |
563 | /* End of init code */ |
564 | /* ================ */ |
565 | |
566 | /** |
567 | * nb_op_add_leaf() - Add leaf data to the get tree results |
568 | * @ys - the yield state for this tree walk. |
569 | * @nb_node - the northbound node representing this leaf. |
570 | * @xpath - the xpath (with key predicates) to this leaf value. |
571 | * |
572 | * Return: northbound return value (enum nb_error) |
573 | */ |
574 | static enum nb_error nb_op_iter_leaf(struct nb_op_yield_state *ys, |
575 | const struct nb_node *nb_node, |
576 | const char *xpath) |
577 | { |
578 | const struct lysc_node *snode = nb_node->snode; |
579 | struct nb_op_node_info *ni = darr_last(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); }); |
580 | struct yang_data *data; |
581 | enum nb_error ret = NB_OK; |
582 | LY_ERR err; |
583 | |
584 | if (CHECK_FLAG(snode->flags, LYS_CONFIG_W)((snode->flags) & (0x01))) |
585 | return NB_OK; |
586 | |
587 | /* Ignore list keys. */ |
588 | if (lysc_is_key(snode)((!snode || (snode->nodetype != 0x0004) || !(snode->flags & 0x0100)) ? 0 : 1)) |
589 | return NB_OK; |
590 | |
591 | data = nb_callback_get_elem(nb_node, xpath, ni->list_entry); |
592 | if (data == NULL((void*)0)) |
593 | return NB_OK; |
594 | |
595 | /* Add a dnode to our tree */ |
596 | err = lyd_new_term(&ni->inner->node, snode->module, snode->name, |
597 | data->value, false0, NULL((void*)0)); |
598 | if (err) { |
599 | yang_data_free(data); |
600 | return NB_ERR_RESOURCE; |
601 | } |
602 | |
603 | if (ys->cb) |
604 | ret = (*ys->cb)(nb_node->snode, ys->translator, data, |
605 | ys->cb_arg); |
606 | yang_data_free(data); |
607 | |
608 | return ret; |
609 | } |
610 | |
611 | static enum nb_error nb_op_iter_leaflist(struct nb_op_yield_state *ys, |
612 | const struct nb_node *nb_node, |
613 | const char *xpath) |
614 | { |
615 | const struct lysc_node *snode = nb_node->snode; |
616 | struct nb_op_node_info *ni = darr_last(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); }); |
617 | const void *list_entry = NULL((void*)0); |
618 | enum nb_error ret = NB_OK; |
619 | LY_ERR err; |
620 | |
621 | if (CHECK_FLAG(snode->flags, LYS_CONFIG_W)((snode->flags) & (0x01))) |
622 | return NB_OK; |
623 | |
624 | do { |
625 | struct yang_data *data; |
626 | |
627 | list_entry = nb_callback_get_next(nb_node, ni->list_entry, |
628 | list_entry); |
629 | if (!list_entry) |
630 | /* End of the list. */ |
631 | break; |
632 | |
633 | data = nb_callback_get_elem(nb_node, xpath, list_entry); |
634 | if (data == NULL((void*)0)) |
635 | continue; |
636 | |
637 | /* Add a dnode to our tree */ |
638 | err = lyd_new_term(&ni->inner->node, snode->module, snode->name, |
639 | data->value, false0, NULL((void*)0)); |
640 | if (err) { |
641 | yang_data_free(data); |
642 | return NB_ERR_RESOURCE; |
643 | } |
644 | |
645 | if (ys->cb) |
646 | ret = (*ys->cb)(nb_node->snode, ys->translator, data, |
647 | ys->cb_arg); |
648 | yang_data_free(data); |
649 | } while (ret == NB_OK && list_entry); |
650 | |
651 | return ret; |
652 | } |
653 | |
654 | |
655 | static bool_Bool nb_op_schema_path_has_predicate(struct nb_op_yield_state *ys, |
656 | int level) |
657 | { |
658 | if (level > darr_lasti(ys->query_tokens)((((ys->query_tokens) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->query_tokens)) - 1)->len) - 1)) |
659 | return false0; |
660 | return strchr(ys->query_tokens[level], '[') != NULL((void*)0); |
661 | } |
662 | |
663 | /** |
664 | * nb_op_empty_container_ok() - determine if should keep empty container node. |
665 | * |
666 | * Return: true if the empty container should be kept. |
667 | */ |
668 | static bool_Bool nb_op_empty_container_ok(const struct lysc_node *snode, |
669 | const char *xpath, const void *list_entry) |
670 | { |
671 | struct nb_node *nn = snode->priv; |
672 | struct yang_data *data; |
673 | |
674 | if (!CHECK_FLAG(snode->flags, LYS_PRESENCE)((snode->flags) & (0x80))) |
675 | return false0; |
676 | |
677 | if (!nn->cbs.get_elem) |
678 | return false0; |
679 | |
680 | data = nb_callback_get_elem(nn, xpath, list_entry); |
681 | if (data) { |
682 | yang_data_free(data); |
683 | return true1; |
684 | } |
685 | return false0; |
686 | } |
687 | |
688 | /** |
689 | * nb_op_get_child_path() - add child node name to the xpath. |
690 | * @xpath_parent - a darr string for the parent node. |
691 | * @schild - the child schema node. |
692 | * @xpath_child - a previous return value from this function to reuse. |
693 | */ |
694 | static char *nb_op_get_child_path(const char *xpath_parent, |
695 | const struct lysc_node *schild, |
696 | char *xpath_child) |
697 | { |
698 | /* "/childname" */ |
699 | uint space, extra = strlen(schild->name) + 1; |
700 | bool_Bool new_mod = (!schild->parent || |
701 | schild->parent->module != schild->module); |
702 | int n; |
703 | |
704 | if (new_mod) |
705 | /* "modulename:" */ |
706 | extra += strlen(schild->module->name) + 1; |
707 | space = darr_len(xpath_parent)(((xpath_parent) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_parent)) - 1)->len) + extra; |
708 | |
709 | if (xpath_parent == xpath_child) |
710 | darr_ensure_cap(xpath_child, space)({ if ((ssize_t)(((xpath_child) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_child)) - 1)->cap) < (ssize_t)( space)) ({ ((xpath_child)) = __darr_resize((xpath_child), (space ), sizeof(((xpath_child))[0]), MTYPE_DARR); }); (xpath_child) ; }); |
711 | else |
712 | darr_in_strdup_cap(xpath_child, xpath_parent, space)({ size_t __size = strlen(xpath_parent) + 1; do { if ((xpath_child )) (((struct darr_metadata *)(xpath_child)) - 1)->len = 0; } while (0); ({ if ((ssize_t)(((xpath_child) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_child)) - 1)->cap) < (ssize_t)(((size_t)(space) > __size) ? (size_t)(space) : __size )) ({ ((xpath_child)) = __darr_resize((xpath_child), (((size_t )(space) > __size) ? (size_t)(space) : __size), sizeof(((xpath_child ))[0]), MTYPE_DARR_STR); }); (xpath_child); }); strlcpy(xpath_child , (xpath_parent), (((xpath_child) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_child)) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 712, "lib/northbound_oper.c" , __func__, }, .expr = "((xpath_child)) || !((size_t)__size)" , }; static const struct xref * const xref_p_281 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((xpath_child)) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((xpath_child)) || !((size_t )__size)); }); if (((xpath_child))) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 712, "lib/northbound_oper.c", __func__, }, .expr = "(long long)darr_cap((xpath_child)) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_282 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)((((xpath_child)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((xpath_child))) - 1)->cap) >= (long long )((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while ((long long)((((xpath_child)) == ( (void*)0)) ? 0 : (((struct darr_metadata *)((xpath_child))) - 1)->cap) >= (long long)((size_t)__size)); }); (((struct darr_metadata *)((xpath_child))) - 1)->len = ((size_t)__size ); } } while (0); xpath_child; }); |
713 | if (new_mod) |
714 | n = snprintf(darr_strnul(xpath_child)({ uint __len = (((xpath_child) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_child)) - 1)->len); ((__len > 0 ) ? &(xpath_child)[__len - 1] : ((void*)0)); }), extra + 1, "/%s:%s", |
715 | schild->module->name, schild->name); |
716 | else |
717 | n = snprintf(darr_strnul(xpath_child)({ uint __len = (((xpath_child) == ((void*)0)) ? 0 : (((struct darr_metadata *)(xpath_child)) - 1)->len); ((__len > 0 ) ? &(xpath_child)[__len - 1] : ((void*)0)); }), extra + 1, "/%s", |
718 | schild->name); |
719 | assert(n == (int)extra)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 719, "lib/northbound_oper.c" , __func__, }, .expr = "n == (int)extra", }; static const struct xref * const xref_p_283 __attribute__((used, section("xref_array" ))) = &(_xref.xref); if (__builtin_expect((n == (int)extra ) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0 )); } while (n == (int)extra); }); |
720 | _darr_len(xpath_child)(((struct darr_metadata *)(xpath_child)) - 1)->len += extra; |
721 | return xpath_child; |
722 | } |
723 | |
724 | static bool_Bool __is_yielding_node(const struct lysc_node *snode) |
725 | { |
726 | struct nb_node *nn = snode->priv; |
727 | |
728 | return nn->cbs.lookup_next != NULL((void*)0); |
729 | } |
730 | |
731 | static const struct lysc_node *__sib_next(bool_Bool yn, const struct lysc_node *sib) |
732 | { |
733 | for (; sib; sib = sib->next) { |
734 | /* Always skip keys. */ |
735 | if (lysc_is_key(sib)((!sib || (sib->nodetype != 0x0004) || !(sib->flags & 0x0100)) ? 0 : 1)) |
736 | continue; |
737 | if (yn == __is_yielding_node(sib)) |
738 | return sib; |
739 | } |
740 | return NULL((void*)0); |
741 | } |
742 | |
743 | /** |
744 | * nb_op_sib_next() - Return the next sibling to walk to |
745 | * @ys: the yield state for this tree walk. |
746 | * @sib: the currently being visited sibling |
747 | * |
748 | * Return: the next sibling to walk to, walking non-yielding before yielding. |
749 | */ |
750 | static const struct lysc_node *nb_op_sib_next(struct nb_op_yield_state *ys, |
751 | const struct lysc_node *sib) |
752 | { |
753 | struct lysc_node *parent = sib->parent; |
754 | bool_Bool yn = __is_yielding_node(sib); |
755 | |
756 | /* |
757 | * If the node info stack is shorter than the schema path then we are |
758 | * doign specific query still on the node from the schema path (should |
759 | * match) so just return NULL. |
760 | */ |
761 | if (darr_len(ys->schema_path)(((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)->len) > darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len)) |
762 | return NULL((void*)0); |
763 | /* |
764 | * If sib is on top of the node info stack then |
765 | * 1) it's a container node -or- |
766 | * 2) it's a list node that we were walking and we've reach the last entry |
767 | * 3) if sib is a list and the list was empty we never would have |
768 | * pushed sib on the stack so the top of the stack is the parent |
769 | * |
770 | * If the query string included this node then we do not process any |
771 | * siblings as we are not walking all the parent's children just this |
772 | * specified one give by the query string. |
773 | */ |
774 | if (sib == darr_last(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); })->schema && |
775 | darr_len(ys->schema_path)(((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)->len) >= darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len)) |
776 | return NULL((void*)0); |
777 | /* case (3) */ |
778 | else if (sib->nodetype == LYS_LIST0x0010 && |
779 | parent == darr_last(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); })->schema && |
780 | darr_len(ys->schema_path)(((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)->len) > darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len)) |
781 | return NULL((void*)0); |
782 | |
783 | sib = __sib_next(yn, sib->next); |
784 | if (sib) |
785 | return sib; |
786 | if (yn) |
787 | return NULL((void*)0); |
788 | return __sib_next(true1, lysc_node_child(parent)); |
789 | } |
790 | /* |
791 | * sib_walk((struct lyd_node *)ni->inner->node.parent->parent->parent->parent->parent->parent->parent) |
792 | */ |
793 | |
794 | /** |
795 | * nb_op_sib_first() - obtain the first child to walk to |
796 | * @ys: the yield state for this tree walk. |
797 | * @parent: the parent whose child we seek |
798 | * @skip_keys: if should skip over keys |
799 | * |
800 | * Return: the first child to continue the walk to, starting with non-yielding |
801 | * siblings then yielding ones. There should be no more than 1 yielding sibling. |
802 | */ |
803 | static const struct lysc_node *nb_op_sib_first(struct nb_op_yield_state *ys, |
804 | const struct lysc_node *parent) |
805 | { |
806 | const struct lysc_node *sib = lysc_node_child(parent); |
807 | const struct lysc_node *first_sib; |
808 | |
809 | /* |
810 | * The top of the node stack points at @parent. |
811 | * |
812 | * If the schema path (original query) is longer than our current node |
813 | * info stack (current xpath location), we are building back up to the |
814 | * base of the user query, return the next schema node from the query |
815 | * string (schema_path). |
816 | */ |
817 | assert(darr_last(ys->node_infos)->schema == parent)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 817, "lib/northbound_oper.c" , __func__, }, .expr = "darr_last(ys->node_infos)->schema == parent" , }; static const struct xref * const xref_p_284 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); })->schema == parent) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (({ uint __len = (((ys-> node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys ->node_infos)) - 1)->len); ((__len > 0) ? &(ys-> node_infos)[__len - 1] : ((void*)0)); })->schema == parent ); }); |
818 | if (darr_lasti(ys->node_infos)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1) < ys->query_base_level) |
819 | return ys->schema_path[darr_lasti(ys->node_infos)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1) + 1]; |
820 | |
821 | /* We always skip keys. */ |
822 | while (sib && lysc_is_key(sib)((!sib || (sib->nodetype != 0x0004) || !(sib->flags & 0x0100)) ? 0 : 1)) |
823 | sib = sib->next; |
824 | if (!sib) |
825 | return NULL((void*)0); |
826 | |
827 | /* Return non-yielding node's first */ |
828 | first_sib = sib; |
829 | if (__is_yielding_node(sib)) { |
830 | sib = __sib_next(false0, sib); |
831 | if (sib) |
832 | return sib; |
833 | } |
834 | return first_sib; |
835 | } |
836 | |
837 | /* |
838 | * "3-dimensional" walk from base of the tree to the tip in-order. |
839 | * |
840 | * The actual tree is only 2-dimensional as list nodes are organized as adjacent |
841 | * siblings under a common parent perhaps with other siblings to each side; |
842 | * however, using 3d view here is easier to diagram. |
843 | * |
844 | * - A list node is yielding if it has a lookup_next callback. |
845 | * - All other node types are not yielding. |
846 | * - There's only one yielding node in a list of children (i.e., siblings). |
847 | * |
848 | * We visit all non-yielding children prior to the yielding child. |
849 | * That way we have the fullest tree possible even when something is deleted |
850 | * during a yield. |
851 | * --- child/parent descendant poinilnters |
852 | * ... next/prev sibling pointers |
853 | * o.o list entries pointers |
854 | * ~~~ diagram extension connector |
855 | * 1 |
856 | * / \ |
857 | * / \ o~~~~12 |
858 | * / \ . / \ |
859 | * 2.......5 o~~~9 13...14 |
860 | * / \ | . / \ |
861 | * 3...4 6 10...11 Cont Nodes: 1,2,5 |
862 | * / \ List Nodes: 6,9,12 |
863 | * 7...8 Leaf Nodes: 3,4,7,8,10,11,13,14 |
864 | * Schema Leaf A: 3 |
865 | * Schema Leaf B: 4 |
866 | * Schema Leaf C: 7,10,13 |
867 | * Schema Leaf D: 8,11,14 |
868 | */ |
869 | static enum nb_error __walk(struct nb_op_yield_state *ys, bool_Bool is_resume) |
870 | { |
871 | const struct lysc_node *walk_stem_tip = ys_get_walk_stem_tip(ys); |
872 | const struct lysc_node *sib; |
873 | const void *parent_list_entry = NULL((void*)0); |
874 | const void *list_entry = NULL((void*)0); |
875 | struct nb_op_node_info *ni, *pni; |
876 | struct lyd_node *node; |
877 | struct nb_node *nn; |
878 | char *xpath_child = NULL((void*)0); |
879 | // bool at_query_base; |
880 | bool_Bool at_root_level, list_start, is_specific_node; |
881 | enum nb_error ret = NB_OK; |
882 | LY_ERR err; |
883 | int at_clevel; |
884 | uint len; |
885 | |
886 | |
887 | monotime(&ys->start_time); |
888 | |
889 | /* Don't currently support walking all root nodes */ |
890 | if (!walk_stem_tip) |
891 | return NB_ERR_NOT_FOUND; |
892 | |
893 | /* |
894 | * If we are resuming then start with the list container on top. |
895 | * Otherwise get the first child of the container we are walking, |
896 | * starting with non-yielding children. |
897 | */ |
898 | if (is_resume) |
899 | sib = darr_last(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); })->schema; |
900 | else { |
901 | /* |
902 | * Start with non-yielding children first. |
903 | * |
904 | * When adding root level walks, the sibling list are the root |
905 | * level nodes of all modules |
906 | */ |
907 | sib = nb_op_sib_first(ys, walk_stem_tip); |
908 | if (!sib) |
909 | return NB_ERR_NOT_FOUND; |
910 | } |
911 | |
912 | |
913 | while (true1) { |
914 | /* Grab the top container/list node info on the stack */ |
915 | at_clevel = darr_lasti(ys->node_infos)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1); |
916 | ni = &ys->node_infos[at_clevel]; |
917 | |
918 | /* |
919 | * This is the level of the last specific node at init |
920 | * time. +1 would be the first non-specific list or |
921 | * non-container if present in the container node. |
922 | */ |
923 | at_root_level = at_clevel == ys->walk_root_level; |
924 | |
925 | if (!sib) { |
926 | /* |
927 | * We've reached the end of the siblings inside a |
928 | * containing node; either a container or a specific |
929 | * list node entry. |
930 | * |
931 | * We handle container node inline; however, for lists |
932 | * we are only done with a specific entry and need to |
933 | * move to the next element on the list so we drop down |
934 | * into the switch for that case. |
935 | */ |
936 | |
937 | /* Grab the containing node. */ |
938 | sib = ni->schema; |
939 | |
940 | if (sib->nodetype == LYS_CONTAINER0x0001) { |
941 | /* If we added an empty container node (no |
942 | * children) and it's not a presence container |
943 | * or it's not backed by the get_elem callback, |
944 | * remove the node from the tree. |
945 | */ |
946 | if (!lyd_child(&ni->inner->node) && |
947 | !nb_op_empty_container_ok(sib, ys->xpath, |
948 | ni->list_entry)) |
949 | lyd_free_tree(&ni->inner->node); |
950 | |
951 | /* If we have returned to our original walk base, |
952 | * then we are done with the walk. |
953 | */ |
954 | if (at_root_level) { |
955 | ret = NB_OK; |
956 | goto done; |
957 | } |
958 | /* |
959 | * Grab the sibling of the container we are |
960 | * about to pop, so we will be mid-walk on the |
961 | * parent containers children. |
962 | */ |
963 | sib = nb_op_sib_next(ys, sib); |
964 | |
965 | /* Pop container node to the parent container */ |
966 | ys_pop_inner(ys); |
967 | |
968 | /* |
969 | * If are were working on a user narrowed path |
970 | * then we are done with these siblings. |
971 | */ |
972 | if (darr_len(ys->schema_path)(((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)->len) > |
973 | darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len)) |
974 | sib = NULL((void*)0); |
975 | |
976 | /* Start over */ |
977 | continue; |
978 | } |
979 | /* |
980 | * If we are here we have reached the end of the |
981 | * children of a list entry node. sib points |
982 | * at the list node info. |
983 | */ |
984 | } |
985 | |
986 | /* TODO: old code checked for "first" here and skipped if set */ |
987 | if (CHECK_FLAG(sib->nodetype,((sib->nodetype) & (0x0004 | 0x0008 | 0x0001)) |
988 | LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER)((sib->nodetype) & (0x0004 | 0x0008 | 0x0001))) |
989 | xpath_child = nb_op_get_child_path(ys->xpath, sib, |
990 | xpath_child); |
991 | nn = sib->priv; |
992 | |
993 | switch (sib->nodetype) { |
994 | case LYS_LEAF0x0004: |
995 | /* |
996 | * If we have a non-specific walk to a specific leaf |
997 | * (e.g., "..../route-entry/metric") and the leaf value |
998 | * is not present, then we are left with the data nodes |
999 | * of the stem of the branch to the missing leaf data. |
1000 | * For containers this will get cleaned up by the |
1001 | * container code above that looks for no children; |
1002 | * however, this doesn't work for lists. |
1003 | * |
1004 | * (FN:A) We need a similar check for empty list |
1005 | * elements. Empty list elements below the |
1006 | * query_base_level (i.e., the schema path length) |
1007 | * should be cleaned up as they don't support anything |
1008 | * the user is querying for, if they are above the |
1009 | * query_base_level then they are part of the walk and |
1010 | * should be kept. |
1011 | */ |
1012 | ret = nb_op_iter_leaf(ys, nn, xpath_child); |
Value stored to 'ret' is never read | |
1013 | sib = nb_op_sib_next(ys, sib); |
1014 | continue; |
1015 | case LYS_LEAFLIST0x0008: |
1016 | ret = nb_op_iter_leaflist(ys, nn, xpath_child); |
1017 | sib = nb_op_sib_next(ys, sib); |
1018 | continue; |
1019 | case LYS_CONTAINER0x0001: |
1020 | if (CHECK_FLAG(nn->flags, F_NB_NODE_CONFIG_ONLY)((nn->flags) & (0x01))) { |
1021 | sib = nb_op_sib_next(ys, sib); |
1022 | continue; |
1023 | } |
1024 | |
1025 | node = NULL((void*)0); |
1026 | err = lyd_new_inner(&ni->inner->node, sib->module, |
1027 | sib->name, false0, &node); |
1028 | if (err) { |
1029 | ret = NB_ERR_RESOURCE; |
1030 | goto done; |
1031 | } |
1032 | |
1033 | /* push this container node on top of the stack */ |
1034 | ni = darr_appendz(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( { if ((ssize_t)(((ys->node_infos) == ((void*)0)) ? 0 : ((( struct darr_metadata *)(ys->node_infos)) - 1)->cap) < (ssize_t)(__len + (1))) ({ ((ys->node_infos)) = __darr_resize ((ys->node_infos), (__len + (1)), sizeof(((ys->node_infos ))[0]), MTYPE_DARR); }); (ys->node_infos); }); (((struct darr_metadata *)(ys->node_infos)) - 1)->len = __len + (1); if (1) memset (&(ys->node_infos)[__len], 0, (1)*sizeof((ys->node_infos )[0])); &(ys->node_infos)[__len]; }); |
1035 | ni->inner = (struct lyd_node_inner *)node; |
1036 | ni->schema = node->schema; |
1037 | ni->niters = 0; |
1038 | ni->nents = 0; |
1039 | ni->has_lookup_next = false0; |
1040 | ni->lookup_next_ok = ni[-1].lookup_next_ok; |
1041 | ni->list_entry = ni[-1].list_entry; |
1042 | |
1043 | darr_in_strdup(ys->xpath, xpath_child)({ size_t __size = strlen(xpath_child) + 1; do { if ((ys-> xpath)) (((struct darr_metadata *)(ys->xpath)) - 1)->len = 0; } while (0); ({ if ((ssize_t)(((ys->xpath) == ((void *)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)-> cap) < (ssize_t)(((size_t)(1) > __size) ? (size_t)(1) : __size)) ({ ((ys->xpath)) = __darr_resize((ys->xpath), (((size_t)(1) > __size) ? (size_t)(1) : __size), sizeof(( (ys->xpath))[0]), MTYPE_DARR_STR); }); (ys->xpath); }); strlcpy(ys->xpath, (xpath_child), (((ys->xpath) == ((void *)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)-> cap)); do { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1043, "lib/northbound_oper.c" , __func__, }, .expr = "((ys->xpath)) || !((size_t)__size)" , }; static const struct xref * const xref_p_285 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((ys->xpath)) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((ys->xpath)) || !((size_t )__size)); }); if (((ys->xpath))) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void *)0)), (XREFT_ASSERT), 1043, "lib/northbound_oper.c", __func__ , }, .expr = "(long long)darr_cap((ys->xpath)) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_286 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)((((ys->xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((ys->xpath))) - 1)->cap) >= (long long )((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while ((long long)((((ys->xpath)) == ((void*)0)) ? 0 : (((struct darr_metadata *)((ys->xpath)) ) - 1)->cap) >= (long long)((size_t)__size)); }); (((struct darr_metadata *)((ys->xpath))) - 1)->len = ((size_t)__size ); } } while (0); ys->xpath; }); |
1044 | ni->xpath_len = darr_strlen(ys->xpath)({ uint __size = (((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->len); if (__size) __size -= 1; ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1044, "lib/northbound_oper.c" , __func__, }, .expr = "!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0" , }; static const struct xref * const xref_p_287 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0); }); __size; }); |
1045 | |
1046 | sib = nb_op_sib_first(ys, sib); |
1047 | continue; |
1048 | case LYS_LIST0x0010: |
1049 | |
1050 | /* |
1051 | * Notes: |
1052 | * |
1053 | * NOTE: ni->inner may be NULL here if we resumed and it |
1054 | * was gone. ni->schema and ni->keys will still be |
1055 | * valid. |
1056 | * |
1057 | * NOTE: At this point sib is never NULL; however, if it |
1058 | * was NULL at the top of the loop, then we were done |
1059 | * working on a list element's children and will be |
1060 | * attempting to get the next list element here so sib |
1061 | * == ni->schema (i.e., !list_start). |
1062 | * |
1063 | * (FN:A): Before doing this let's remove empty list |
1064 | * elements that are "inside" the query string as they |
1065 | * represent a stem which didn't lead to actual data |
1066 | * being requested by the user -- for example, |
1067 | * ".../route-entry/metric" if metric is not present we |
1068 | * don't want to return an empty route-entry to the |
1069 | * user. |
1070 | */ |
1071 | |
1072 | node = NULL((void*)0); |
1073 | list_start = ni->schema != sib; |
1074 | if (list_start) { |
1075 | /* |
1076 | * List iteration: First Element |
1077 | * ----------------------------- |
1078 | * |
1079 | * Our node info wasn't on top (wasn't an entry |
1080 | * for sib) so this is a new list iteration, we |
1081 | * will push our node info below. The top is our |
1082 | * parent. |
1083 | */ |
1084 | if (CHECK_FLAG(nn->flags,((nn->flags) & (0x01)) |
1085 | F_NB_NODE_CONFIG_ONLY)((nn->flags) & (0x01))) { |
1086 | sib = nb_op_sib_next(ys, sib); |
1087 | continue; |
1088 | } |
1089 | /* we are now at one level higher */ |
1090 | at_clevel += 1; |
1091 | pni = ni; |
1092 | ni = NULL((void*)0); |
1093 | } else { |
1094 | /* |
1095 | * List iteration: Next Element |
1096 | * ---------------------------- |
1097 | * |
1098 | * This is the case where `sib == NULL` at the |
1099 | * top of the loop, so, we just completed the |
1100 | * walking the children of a list entry, i.e., |
1101 | * we are done with that list entry. |
1102 | * |
1103 | * `sib` was reset to point at the our list node |
1104 | * at the top of node_infos. |
1105 | * |
1106 | * Within this node_info, `ys->xpath`, `inner`, |
1107 | * `list_entry`, and `xpath_len` are for the |
1108 | * previous list entry, and need to be updated. |
1109 | */ |
1110 | pni = darr_len(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len) > 1 ? &ni[-1] |
1111 | : NULL((void*)0); |
1112 | } |
1113 | |
1114 | parent_list_entry = pni ? pni->list_entry : NULL((void*)0); |
1115 | list_entry = ni ? ni->list_entry : NULL((void*)0); |
1116 | |
1117 | /* |
1118 | * Before yielding we check to see if we are doing a |
1119 | * specific list entry instead of a full list iteration. |
1120 | * We do not want to yield during specific list entry |
1121 | * processing. |
1122 | */ |
1123 | |
1124 | /* |
1125 | * If we are at a list start check to see if the node |
1126 | * has a predicate. If so we will try and fetch the data |
1127 | * node now that we've built part of the tree, if the |
1128 | * predicates are keys or only depend on the tree already |
1129 | * built, it should create the element for us. |
1130 | */ |
1131 | is_specific_node = false0; |
1132 | if (list_start && |
1133 | at_clevel <= darr_lasti(ys->query_tokens)((((ys->query_tokens) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->query_tokens)) - 1)->len) - 1) && |
1134 | nb_op_schema_path_has_predicate(ys, at_clevel)) { |
1135 | err = lyd_new_path(&pni->inner->node, NULL((void*)0), |
1136 | ys->query_tokens[at_clevel], |
1137 | NULL((void*)0), 0, &node); |
1138 | if (!err) |
1139 | /* predicate resolved to specific node */ |
1140 | is_specific_node = true1; |
1141 | else { |
1142 | flog_warn(EC_LIB_NB_OPERATIONAL_DATA,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unable to create node for specific query string: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1145, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unable to create node for specific query string: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->query_tokens[at_clevel]"), }; static const struct xref * const xref_p_288 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unable to create node for specific query string: %s" ), __func__, ys->query_tokens[at_clevel]); } while (0) |
1143 | "%s: unable to create node for specific query string: %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unable to create node for specific query string: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1145, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unable to create node for specific query string: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->query_tokens[at_clevel]"), }; static const struct xref * const xref_p_288 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unable to create node for specific query string: %s" ), __func__, ys->query_tokens[at_clevel]); } while (0) |
1144 | __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unable to create node for specific query string: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1145, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unable to create node for specific query string: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->query_tokens[at_clevel]"), }; static const struct xref * const xref_p_288 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unable to create node for specific query string: %s" ), __func__, ys->query_tokens[at_clevel]); } while (0) |
1145 | ys->query_tokens[at_clevel])do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unable to create node for specific query string: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1145, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unable to create node for specific query string: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, ys->query_tokens[at_clevel]"), }; static const struct xref * const xref_p_288 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unable to create node for specific query string: %s" ), __func__, ys->query_tokens[at_clevel]); } while (0); |
1146 | } |
1147 | } |
1148 | |
1149 | if (list_entry && ni->query_specific_entry) { |
1150 | /* |
1151 | * Ending specific list entry processing. |
1152 | */ |
1153 | assert(!list_start)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1153, "lib/northbound_oper.c" , __func__, }, .expr = "!list_start", }; static const struct xref * const xref_p_289 __attribute__((used, section("xref_array" ))) = &(_xref.xref); if (__builtin_expect((!list_start) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (!list_start); }); |
1154 | is_specific_node = true1; |
1155 | list_entry = NULL((void*)0); |
1156 | } |
1157 | |
1158 | /* |
1159 | * Should we yield? |
1160 | * |
1161 | * Don't yield if we have a specific entry. |
1162 | */ |
1163 | if (!is_specific_node && ni && ni->lookup_next_ok && |
1164 | // make sure we advance, if the interval is |
1165 | // fast and we are very slow. |
1166 | ((monotime_since(&ys->start_time, NULL((void*)0)) > |
1167 | NB_OP_WALK_INTERVAL_US(50 * 1000) && |
1168 | ni->niters) || |
1169 | (ni->niters + 1) % 10000 == 0)) { |
1170 | /* This is a yield supporting list node and |
1171 | * we've been running at least our yield |
1172 | * interval, so yield. |
1173 | * |
1174 | * NOTE: we never yield on list_start, and we |
1175 | * are always about to be doing a get_next. |
1176 | */ |
1177 | DEBUGD(&nb_dbg_events,do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: yielding after %u iterations"), .hashu32 = {( 7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1179, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "%s: yielding after %u iterations"), .priority = (7), .ec = ( 0), .args = ("__func__, ni->niters"), }; static const struct xref * const xref_p_290 __attribute__((used, section("xref_array" ))) = &(_xref.xref); zlog_ref(&_xref, ("%s: yielding after %u iterations" ), __func__, ni->niters); } while (0); } while (0) |
1178 | "%s: yielding after %u iterations",do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: yielding after %u iterations"), .hashu32 = {( 7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1179, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "%s: yielding after %u iterations"), .priority = (7), .ec = ( 0), .args = ("__func__, ni->niters"), }; static const struct xref * const xref_p_290 __attribute__((used, section("xref_array" ))) = &(_xref.xref); zlog_ref(&_xref, ("%s: yielding after %u iterations" ), __func__, ni->niters); } while (0); } while (0) |
1179 | __func__, ni->niters)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("%s: yielding after %u iterations"), .hashu32 = {( 7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1179, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "%s: yielding after %u iterations"), .priority = (7), .ec = ( 0), .args = ("__func__, ni->niters"), }; static const struct xref * const xref_p_290 __attribute__((used, section("xref_array" ))) = &(_xref.xref); zlog_ref(&_xref, ("%s: yielding after %u iterations" ), __func__, ni->niters); } while (0); } while (0); |
1180 | |
1181 | ni->niters = 0; |
1182 | ret = NB_YIELD; |
1183 | goto done; |
1184 | } |
1185 | |
1186 | /* |
1187 | * Now get the backend list_entry opaque object for |
1188 | * this list entry from the backend. |
1189 | */ |
1190 | |
1191 | if (is_specific_node) { |
1192 | /* |
1193 | * Specific List Entry: |
1194 | * -------------------- |
1195 | */ |
1196 | if (list_start) { |
1197 | list_entry = |
1198 | nb_callback_lookup_node_entry( |
1199 | node, parent_list_entry); |
1200 | /* |
1201 | * If the node we created from a |
1202 | * specific predicate entry is not |
1203 | * actually there we need to delete the |
1204 | * node from our data tree |
1205 | */ |
1206 | if (!list_entry) { |
1207 | lyd_free_tree(node); |
1208 | node = NULL((void*)0); |
1209 | } |
1210 | } |
1211 | } else if (!list_start && !list_entry && |
1212 | ni->has_lookup_next) { |
1213 | /* |
1214 | * After Yield: |
1215 | * ------------ |
1216 | * After a yield the list_entry may have become |
1217 | * invalid, so use lookup_next callback with |
1218 | * parent and keys instead to find next element. |
1219 | */ |
1220 | list_entry = |
1221 | nb_callback_lookup_next(nn, |
1222 | parent_list_entry, |
1223 | &ni->keys); |
1224 | } else { |
1225 | /* |
1226 | * Normal List Iteration: |
1227 | * ---------------------- |
1228 | * Start (list_entry == NULL) or continue |
1229 | * (list_entry != NULL) the list iteration. |
1230 | */ |
1231 | /* Obtain [next] list entry. */ |
1232 | list_entry = |
1233 | nb_callback_get_next(nn, |
1234 | parent_list_entry, |
1235 | list_entry); |
1236 | } |
1237 | |
1238 | /* |
1239 | * (FN:A) Reap empty list element? Check to see if we |
1240 | * should reap an empty list element. We do this if the |
1241 | * empty list element exists at or below the query base |
1242 | * (i.e., it's not part of the walk, but a failed find |
1243 | * on a more specific query e.g., for below the |
1244 | * `route-entry` element for a query |
1245 | * `.../route-entry/metric` where the list element had |
1246 | * no metric value. |
1247 | * |
1248 | * However, if the user query is for a key of a list |
1249 | * element, then when we reach that list element it will |
1250 | * have no non-key children, check for this condition |
1251 | * and do not reap if true. |
1252 | */ |
1253 | if (!list_start && ni->inner && |
1254 | !lyd_child_no_keys(&ni->inner->node) && |
1255 | /* not the top element with a key match */ |
1256 | !((darr_ilen(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) == |
1257 | darr_ilen(ys->schema_path)(((ys->schema_path) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->schema_path)) - 1)->len) - 1) && |
1258 | lysc_is_key((*darr_last(ys->schema_path)))((!(*({ uint __len = (((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)->len ); ((__len > 0) ? &(ys->schema_path)[__len - 1] : ( (void*)0)); })) || ((*({ uint __len = (((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path )) - 1)->len); ((__len > 0) ? &(ys->schema_path) [__len - 1] : ((void*)0)); }))->nodetype != 0x0004) || !(( *({ uint __len = (((ys->schema_path) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->schema_path)) - 1)->len); ((__len > 0) ? &(ys->schema_path)[__len - 1] : ((void *)0)); }))->flags & 0x0100)) ? 0 : 1)) && |
1259 | /* is this at or below the base? */ |
1260 | darr_ilen(ys->node_infos)(((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) <= ys->query_base_level) |
1261 | lyd_free_tree(&ni->inner->node); |
1262 | |
1263 | |
1264 | if (!list_entry) { |
1265 | /* |
1266 | * List Iteration Done |
1267 | * ------------------- |
1268 | */ |
1269 | |
1270 | /* |
1271 | * Grab next sibling of the list node |
1272 | */ |
1273 | if (is_specific_node) |
1274 | sib = NULL((void*)0); |
1275 | else |
1276 | sib = nb_op_sib_next(ys, sib); |
1277 | |
1278 | /* |
1279 | * If we are at the walk root (base) level then |
1280 | * that specifies a list and we are done iterating |
1281 | * the list, so we are done with the walk entirely. |
1282 | */ |
1283 | if (!sib && at_clevel == ys->walk_root_level) { |
1284 | ret = NB_OK; |
1285 | goto done; |
1286 | } |
1287 | |
1288 | /* |
1289 | * Pop the our list node info back to our |
1290 | * parent. |
1291 | * |
1292 | * We only do this if we've already pushed a |
1293 | * node for the current list schema. For |
1294 | * `list_start` this hasn't happened yet, as |
1295 | * would have happened below. So when list_start |
1296 | * is true but list_entry if NULL we |
1297 | * are processing an empty list. |
1298 | */ |
1299 | if (!list_start) |
1300 | ys_pop_inner(ys); |
1301 | |
1302 | /* |
1303 | * We should never be below the walk root |
1304 | */ |
1305 | assert(darr_lasti(ys->node_infos) >=({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1306, "lib/northbound_oper.c" , __func__, }, .expr = "darr_lasti(ys->node_infos) >= ys->walk_root_level" , }; static const struct xref * const xref_p_291 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1) >= ys->walk_root_level) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((((ys->node_infos) == ( (void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos )) - 1)->len) - 1) >= ys->walk_root_level); }) |
1306 | ys->walk_root_level)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1306, "lib/northbound_oper.c" , __func__, }, .expr = "darr_lasti(ys->node_infos) >= ys->walk_root_level" , }; static const struct xref * const xref_p_291 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1) >= ys->walk_root_level) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (((((ys->node_infos) == ( (void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos )) - 1)->len) - 1) >= ys->walk_root_level); }); |
1307 | |
1308 | /* Move on to the sibling of the list node */ |
1309 | continue; |
1310 | } |
1311 | |
1312 | /* |
1313 | * From here on, we have selected a new top node_info |
1314 | * list entry (either newly pushed or replacing the |
1315 | * previous entry in the walk), and we are filling in |
1316 | * the details. |
1317 | */ |
1318 | |
1319 | if (list_start) { |
1320 | /* |
1321 | * Starting iteration of a list type or |
1322 | * processing a specific entry, push the list |
1323 | * node_info on stack. |
1324 | */ |
1325 | ni = darr_appendz(ys->node_infos)({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->node_infos)) - 1)->len); ( { if ((ssize_t)(((ys->node_infos) == ((void*)0)) ? 0 : ((( struct darr_metadata *)(ys->node_infos)) - 1)->cap) < (ssize_t)(__len + (1))) ({ ((ys->node_infos)) = __darr_resize ((ys->node_infos), (__len + (1)), sizeof(((ys->node_infos ))[0]), MTYPE_DARR); }); (ys->node_infos); }); (((struct darr_metadata *)(ys->node_infos)) - 1)->len = __len + (1); if (1) memset (&(ys->node_infos)[__len], 0, (1)*sizeof((ys->node_infos )[0])); &(ys->node_infos)[__len]; }); |
1326 | pni = &ni[-1]; /* memory may have moved */ |
1327 | ni->has_lookup_next = nn->cbs.lookup_next != |
1328 | NULL((void*)0); |
1329 | ni->lookup_next_ok = ((!pni && ys->finish) || |
1330 | pni->lookup_next_ok) && |
1331 | ni->has_lookup_next; |
1332 | ni->query_specific_entry = is_specific_node; |
1333 | ni->niters = 0; |
1334 | ni->nents = 0; |
1335 | |
1336 | /* this will be our predicate-less xpath */ |
1337 | ys->xpath = nb_op_get_child_path(ys->xpath, sib, |
1338 | ys->xpath); |
1339 | } else { |
1340 | /* |
1341 | * Reset our xpath to the list node (i.e., |
1342 | * remove the entry predicates) |
1343 | */ |
1344 | if (ni->query_specific_entry) { |
1345 | flog_warn(EC_LIB_NB_OPERATIONAL_DATA,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unexpected state" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1347, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unexpected state"), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__" ), }; static const struct xref * const xref_p_292 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: unexpected state"), __func__); } while (0) |
1346 | "%s: unexpected state",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unexpected state" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1347, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unexpected state"), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__" ), }; static const struct xref * const xref_p_292 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: unexpected state"), __func__); } while (0) |
1347 | __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unexpected state" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1347, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unexpected state"), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__" ), }; static const struct xref * const xref_p_292 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: unexpected state"), __func__); } while (0); |
1348 | } |
1349 | assert(!ni->query_specific_entry)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1349, "lib/northbound_oper.c" , __func__, }, .expr = "!ni->query_specific_entry", }; static const struct xref * const xref_p_293 __attribute__((used, section ("xref_array"))) = &(_xref.xref); if (__builtin_expect((! ni->query_specific_entry) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (!ni->query_specific_entry ); }); |
1350 | len = strlen(sib->name) + 1; /* "/sibname" */ |
1351 | if (pni) |
1352 | len += pni->xpath_len; |
1353 | darr_setlen(ys->xpath, len + 1)do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1353, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->xpath) || !(len + 1)", }; static const struct xref * const xref_p_294 __attribute__((used, section ("xref_array"))) = &(_xref.xref); if (__builtin_expect((( ys->xpath) || !(len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((ys->xpath) || !(len + 1 )); }); if ((ys->xpath)) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 1353, "lib/northbound_oper.c", __func__, }, .expr = "(long long)darr_cap(ys->xpath) >= (long long)(len + 1)" , }; static const struct xref * const xref_p_295 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((long long)(((ys->xpath) == ((void*)0)) ? 0 : (( (struct darr_metadata *)(ys->xpath)) - 1)->cap) >= ( long long)(len + 1)); }); (((struct darr_metadata *)(ys->xpath )) - 1)->len = (len + 1); } } while (0); |
1354 | ys->xpath[len] = 0; |
1355 | ni->xpath_len = len; |
1356 | } |
1357 | |
1358 | /* Need to get keys. */ |
1359 | |
1360 | if (!CHECK_FLAG(nn->flags, F_NB_NODE_KEYLESS_LIST)((nn->flags) & (0x02))) { |
1361 | ret = nb_callback_get_keys(nn, list_entry, |
1362 | &ni->keys); |
1363 | if (ret) { |
1364 | darr_pop(ys->node_infos)({ uint __len = (((struct darr_metadata *)(ys->node_infos) ) - 1)->len; ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1364, "lib/northbound_oper.c" , __func__, }, .expr = "__len", }; static const struct xref * const xref_p_296 __attribute__((used, section("xref_array")) ) = &(_xref.xref); if (__builtin_expect((__len) ? 0 : 1, 0 )) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( __len); }); do { uint __i = (__len - 1); uint __n = (1); uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); if (!__len ) break; else if (__i + __n < __len) { memmove(&(ys-> node_infos)[__i], &(ys->node_infos)[__i + __n], sizeof ((ys->node_infos)[0]) * (__len - (__i + __n))); (((struct darr_metadata *)(ys->node_infos)) - 1)->len = __len - __n; } else (( (struct darr_metadata *)(ys->node_infos)) - 1)->len = __i ; } while (0); (ys->node_infos)[__len - 1]; }); |
1365 | ret = NB_ERR_RESOURCE; |
1366 | goto done; |
1367 | } |
1368 | } |
1369 | /* |
1370 | * Append predicates to xpath. |
1371 | */ |
1372 | len = darr_strlen(ys->xpath)({ uint __size = (((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->len); if (__size) __size -= 1; ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1372, "lib/northbound_oper.c" , __func__, }, .expr = "!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0" , }; static const struct xref * const xref_p_297 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0); }); __size; }); |
1373 | if (ni->keys.num) { |
1374 | yang_get_key_preds(ys->xpath + len, sib, |
1375 | &ni->keys, |
1376 | darr_cap(ys->xpath)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) - len); |
1377 | } else { |
1378 | /* add a position predicate (1s based?) */ |
1379 | darr_ensure_avail(ys->xpath, 10)({ ssize_t need = (ssize_t)(10) - (ssize_t)((((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) - (((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->len)); if (need > 0) ({ ((ys->xpath)) = __darr_resize((ys->xpath), (((ys ->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys ->xpath)) - 1)->cap) + need, sizeof(((ys->xpath))[0] ), MTYPE_DARR); }); (ys->xpath); }); |
1380 | snprintf(ys->xpath + len, |
1381 | darr_cap(ys->xpath)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) - len + 1, "[%u]", |
1382 | ni->nents + 1); |
1383 | } |
1384 | darr_setlen(ys->xpath,do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1385, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->xpath) || !(strlen(ys->xpath + len) + len + 1)" , }; static const struct xref * const xref_p_298 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((ys->xpath) || !(strlen(ys->xpath + len) + len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((ys->xpath) || !(strlen(ys->xpath + len) + len + 1)); }); if ((ys->xpath)) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 1385, "lib/northbound_oper.c", __func__, }, .expr = "(long long)darr_cap(ys->xpath) >= (long long)(strlen(ys->xpath + len) + len + 1)" , }; static const struct xref * const xref_p_299 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(strlen(ys-> xpath + len) + len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((long long)(((ys->xpath ) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath )) - 1)->cap) >= (long long)(strlen(ys->xpath + len) + len + 1)); }); (((struct darr_metadata *)(ys->xpath)) - 1)->len = (strlen(ys->xpath + len) + len + 1); } } while (0) |
1385 | strlen(ys->xpath + len) + len + 1)do { ({ static const struct xref_assert _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1385, "lib/northbound_oper.c" , __func__, }, .expr = "(ys->xpath) || !(strlen(ys->xpath + len) + len + 1)" , }; static const struct xref * const xref_p_298 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((ys->xpath) || !(strlen(ys->xpath + len) + len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((ys->xpath) || !(strlen(ys->xpath + len) + len + 1)); }); if ((ys->xpath)) { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 1385, "lib/northbound_oper.c", __func__, }, .expr = "(long long)darr_cap(ys->xpath) >= (long long)(strlen(ys->xpath + len) + len + 1)" , }; static const struct xref * const xref_p_299 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->cap) >= (long long)(strlen(ys-> xpath + len) + len + 1)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((long long)(((ys->xpath ) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath )) - 1)->cap) >= (long long)(strlen(ys->xpath + len) + len + 1)); }); (((struct darr_metadata *)(ys->xpath)) - 1)->len = (strlen(ys->xpath + len) + len + 1); } } while (0); |
1386 | ni->xpath_len = darr_strlen(ys->xpath)({ uint __size = (((ys->xpath) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->xpath)) - 1)->len); if (__size) __size -= 1; ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1386, "lib/northbound_oper.c" , __func__, }, .expr = "!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0" , }; static const struct xref * const xref_p_300 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (!(ys->xpath) || ((char *)(ys->xpath))[__size] == 0); }); __size; }); |
1387 | |
1388 | /* |
1389 | * Create the new list entry node. |
1390 | */ |
1391 | |
1392 | if (!node) { |
1393 | /* NOTE: can also use lyd_new_list2 here when available */ |
1394 | err = yang_lyd_new_list(ni[-1].inner, sib, |
1395 | &ni->keys, |
1396 | (struct lyd_node_inner * |
1397 | *)&node); |
1398 | if (err) { |
1399 | darr_pop(ys->node_infos)({ uint __len = (((struct darr_metadata *)(ys->node_infos) ) - 1)->len; ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1399, "lib/northbound_oper.c" , __func__, }, .expr = "__len", }; static const struct xref * const xref_p_301 __attribute__((used, section("xref_array")) ) = &(_xref.xref); if (__builtin_expect((__len) ? 0 : 1, 0 )) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ( __len); }); do { uint __i = (__len - 1); uint __n = (1); uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->node_infos)) - 1)->len); if (!__len ) break; else if (__i + __n < __len) { memmove(&(ys-> node_infos)[__i], &(ys->node_infos)[__i + __n], sizeof ((ys->node_infos)[0]) * (__len - (__i + __n))); (((struct darr_metadata *)(ys->node_infos)) - 1)->len = __len - __n; } else (( (struct darr_metadata *)(ys->node_infos)) - 1)->len = __i ; } while (0); (ys->node_infos)[__len - 1]; }); |
1400 | ret = NB_ERR_RESOURCE; |
1401 | goto done; |
1402 | } |
1403 | } |
1404 | |
1405 | /* |
1406 | * Save the new list entry with the list node info |
1407 | */ |
1408 | ni->inner = (struct lyd_node_inner *)node; |
1409 | ni->schema = node->schema; |
1410 | ni->list_entry = list_entry; |
1411 | ni->niters += 1; |
1412 | ni->nents += 1; |
1413 | |
1414 | /* Skip over the key children, they've been created. */ |
1415 | sib = nb_op_sib_first(ys, sib); |
1416 | continue; |
1417 | |
1418 | case LYS_CHOICE0x0002: |
1419 | /* Container type with no data */ |
1420 | /*FALLTHROUGH*/ |
1421 | case LYS_CASE0x0080: |
1422 | /* Container type with no data */ |
1423 | /*FALLTHROUGH*/ |
1424 | default: |
1425 | /*FALLTHROUGH*/ |
1426 | case LYS_ANYXML0x0020: |
1427 | case LYS_ANYDATA0x0060: |
1428 | /* These schema types are not currently handled */ |
1429 | flog_warn(EC_LIB_NB_OPERATIONAL_DATA,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unsupported schema node type: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1431, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unsupported schema node type: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, lys_nodetype2str(sib->nodetype)"), }; static const struct xref * const xref_p_302 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unsupported schema node type: %s" ), __func__, lys_nodetype2str(sib->nodetype)); } while (0) |
1430 | "%s: unsupported schema node type: %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unsupported schema node type: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1431, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unsupported schema node type: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, lys_nodetype2str(sib->nodetype)"), }; static const struct xref * const xref_p_302 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unsupported schema node type: %s" ), __func__, lys_nodetype2str(sib->nodetype)); } while (0) |
1431 | __func__, lys_nodetype2str(sib->nodetype))do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unsupported schema node type: %s" ), .hashu32 = {(4), (EC_LIB_NB_OPERATIONAL_DATA)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1431, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unsupported schema node type: %s" ), .priority = (4), .ec = (EC_LIB_NB_OPERATIONAL_DATA), .args = ("__func__, lys_nodetype2str(sib->nodetype)"), }; static const struct xref * const xref_p_302 __attribute__((used, section ("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: unsupported schema node type: %s" ), __func__, lys_nodetype2str(sib->nodetype)); } while (0); |
1432 | sib = nb_op_sib_next(ys, sib); |
1433 | continue; |
1434 | } |
1435 | } |
1436 | |
1437 | done: |
1438 | darr_free(xpath_child)do { if ((xpath_child)) { struct darr_metadata *__meta = (((struct darr_metadata *)(xpath_child)) - 1); do { qfree(__meta->mtype , __meta); __meta = ((void*)0); } while (0); (xpath_child) = ( (void*)0); } } while (0); |
1439 | return ret; |
1440 | } |
1441 | |
1442 | static void nb_op_walk_continue(struct event *thread) |
1443 | { |
1444 | struct nb_op_yield_state *ys = EVENT_ARG(thread)((thread)->arg); |
1445 | enum nb_error ret = NB_OK; |
1446 | |
1447 | DEBUGD(&nb_dbg_cbs_state, "northbound oper-state: resuming %s",do { if (((__c11_atomic_load(&(&nb_dbg_cbs_state)-> flags, memory_order_seq_cst)) & (((0x01000000 | 0x02000000 ))&(0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("northbound oper-state: resuming %s"), .hashu32 = { (7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1448, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "northbound oper-state: resuming %s"), .priority = (7), .ec = (0), .args = ("ys->xpath"), }; static const struct xref * const xref_p_303 __attribute__((used, section("xref_array")) ) = &(_xref.xref); zlog_ref(&_xref, ("northbound oper-state: resuming %s" ), ys->xpath); } while (0); } while (0) |
1448 | ys->xpath)do { if (((__c11_atomic_load(&(&nb_dbg_cbs_state)-> flags, memory_order_seq_cst)) & (((0x01000000 | 0x02000000 ))&(0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("northbound oper-state: resuming %s"), .hashu32 = { (7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1448, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "northbound oper-state: resuming %s"), .priority = (7), .ec = (0), .args = ("ys->xpath"), }; static const struct xref * const xref_p_303 __attribute__((used, section("xref_array")) ) = &(_xref.xref); zlog_ref(&_xref, ("northbound oper-state: resuming %s" ), ys->xpath); } while (0); } while (0); |
1449 | |
1450 | nb_op_resume_data_tree(ys); |
1451 | |
1452 | /* if we've popped past the walk start level we're done */ |
1453 | if (darr_lasti(ys->node_infos)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1) < ys->walk_root_level) |
1454 | goto finish; |
1455 | |
1456 | /* otherwise we are at a resumable node */ |
1457 | assert(darr_last(ys->node_infos)->has_lookup_next)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1457, "lib/northbound_oper.c" , __func__, }, .expr = "darr_last(ys->node_infos)->has_lookup_next" , }; static const struct xref * const xref_p_304 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((({ uint __len = (((ys->node_infos) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->node_infos)) - 1)->len); ( (__len > 0) ? &(ys->node_infos)[__len - 1] : ((void *)0)); })->has_lookup_next) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while (({ uint __len = (((ys-> node_infos) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys ->node_infos)) - 1)->len); ((__len > 0) ? &(ys-> node_infos)[__len - 1] : ((void*)0)); })->has_lookup_next) ; }); |
1458 | |
1459 | ret = __walk(ys, true1); |
1460 | if (ret == NB_YIELD) { |
1461 | if (nb_op_yield(ys) != NB_OK) { |
1462 | if (ys->should_batch) |
1463 | goto stopped; |
1464 | else |
1465 | goto finish; |
1466 | } |
1467 | return; |
1468 | } |
1469 | finish: |
1470 | (*ys->finish)(ys_root_node(ys), ys->finish_arg, ret); |
1471 | stopped: |
1472 | nb_op_free_yield_state(ys, false0); |
1473 | } |
1474 | |
1475 | static void __free_siblings(struct lyd_node *this) |
1476 | { |
1477 | struct lyd_node *next, *sib; |
1478 | uint count = 0; |
1479 | |
1480 | LY_LIST_FOR_SAFE(lyd_first_sibling(this), next, sib)for ((sib) = (lyd_first_sibling(this)); (sib) ? (next = (sib) ->next, 1) : 0; (sib) = (next)) |
1481 | { |
1482 | if (lysc_is_key(sib->schema)((!sib->schema || (sib->schema->nodetype != 0x0004) || !(sib->schema->flags & 0x0100)) ? 0 : 1)) |
1483 | continue; |
1484 | if (sib == this) |
1485 | continue; |
1486 | lyd_free_tree(sib); |
1487 | count++; |
1488 | } |
1489 | DEBUGD(&nb_dbg_events, "NB oper-state: deleted %u siblings", count)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: deleted %u siblings"), .hashu32 = { (7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1489, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "NB oper-state: deleted %u siblings"), .priority = (7), .ec = (0), .args = ("count"), }; static const struct xref * const xref_p_305 __attribute__((used, section("xref_array"))) = &(_xref.xref ); zlog_ref(&_xref, ("NB oper-state: deleted %u siblings" ), count); } while (0); } while (0); |
1490 | } |
1491 | |
1492 | /* |
1493 | * Trim Algorithm: |
1494 | * |
1495 | * Delete final lookup-next list node and subtree, leave stack slot with keys. |
1496 | * |
1497 | * Then walking up the stack, delete all siblings except: |
1498 | * 1. right-most container or list node (must be lookup-next by design) |
1499 | * 2. keys supporting existing parent list node. |
1500 | * |
1501 | * NOTE the topmost node on the stack will be the final lookup-nexxt list node, |
1502 | * as we only yield on lookup-next list nodes. |
1503 | * |
1504 | */ |
1505 | static void nb_op_trim_yield_state(struct nb_op_yield_state *ys) |
1506 | { |
1507 | struct nb_op_node_info *ni; |
1508 | int i = darr_lasti(ys->node_infos)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1); |
1509 | |
1510 | assert(i >= 0)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1510, "lib/northbound_oper.c" , __func__, }, .expr = "i >= 0", }; static const struct xref * const xref_p_306 __attribute__((used, section("xref_array" ))) = &(_xref.xref); if (__builtin_expect((i >= 0) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (i >= 0); }); |
1511 | |
1512 | DEBUGD(&nb_dbg_events, "NB oper-state: start trimming: top: %d", i)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: start trimming: top: %d"), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1512, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "NB oper-state: start trimming: top: %d"), .priority = (7), . ec = (0), .args = ("i"), }; static const struct xref * const xref_p_307 __attribute__((used, section("xref_array"))) = &(_xref.xref ); zlog_ref(&_xref, ("NB oper-state: start trimming: top: %d" ), i); } while (0); } while (0); |
1513 | |
1514 | ni = &ys->node_infos[i]; |
1515 | assert(ni->has_lookup_next)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1515, "lib/northbound_oper.c" , __func__, }, .expr = "ni->has_lookup_next", }; static const struct xref * const xref_p_308 __attribute__((used, section( "xref_array"))) = &(_xref.xref); if (__builtin_expect((ni ->has_lookup_next) ? 0 : 1, 0)) do { _zlog_assert_failed(& _xref, ((void*)0)); } while (ni->has_lookup_next); }); |
1516 | |
1517 | DEBUGD(&nb_dbg_events, "NB oper-state: deleting tree at level %d", i)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: deleting tree at level %d"), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1517, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "NB oper-state: deleting tree at level %d"), .priority = (7), .ec = (0), .args = ("i"), }; static const struct xref * const xref_p_309 __attribute__((used, section("xref_array"))) = & (_xref.xref); zlog_ref(&_xref, ("NB oper-state: deleting tree at level %d" ), i); } while (0); } while (0); |
1518 | __free_siblings(&ni->inner->node); |
1519 | lyd_free_tree(&ni->inner->node); |
1520 | ni->inner = NULL((void*)0); |
1521 | |
1522 | while (--i > 0) { |
1523 | DEBUGD(&nb_dbg_events,do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: deleting siblings at level: %d"), . hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 1524, "lib/northbound_oper.c", __func__, } , .fmtstring = ("NB oper-state: deleting siblings at level: %d" ), .priority = (7), .ec = (0), .args = ("i"), }; static const struct xref * const xref_p_310 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("NB oper-state: deleting siblings at level: %d" ), i); } while (0); } while (0) |
1524 | "NB oper-state: deleting siblings at level: %d", i)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: deleting siblings at level: %d"), . hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 1524, "lib/northbound_oper.c", __func__, } , .fmtstring = ("NB oper-state: deleting siblings at level: %d" ), .priority = (7), .ec = (0), .args = ("i"), }; static const struct xref * const xref_p_310 __attribute__((used, section( "xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("NB oper-state: deleting siblings at level: %d" ), i); } while (0); } while (0); |
1525 | __free_siblings(&ys->node_infos[i].inner->node); |
1526 | } |
1527 | DEBUGD(&nb_dbg_events, "NB oper-state: stop trimming: new top: %d",do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: stop trimming: new top: %d"), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1528, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "NB oper-state: stop trimming: new top: %d"), .priority = (7) , .ec = (0), .args = ("(int)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1)" ), }; static const struct xref * const xref_p_311 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("NB oper-state: stop trimming: new top: %d"), ( int)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1)); } while (0); } while (0) |
1528 | (int)darr_lasti(ys->node_infos))do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: stop trimming: new top: %d"), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__ ( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG ), 1528, "lib/northbound_oper.c", __func__, }, .fmtstring = ( "NB oper-state: stop trimming: new top: %d"), .priority = (7) , .ec = (0), .args = ("(int)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1)" ), }; static const struct xref * const xref_p_311 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("NB oper-state: stop trimming: new top: %d"), ( int)((((ys->node_infos) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->node_infos)) - 1)->len) - 1)); } while (0); } while (0); |
1529 | } |
1530 | |
1531 | static enum nb_error nb_op_yield(struct nb_op_yield_state *ys) |
1532 | { |
1533 | enum nb_error ret; |
1534 | unsigned long min_us = MAX(1, NB_OP_WALK_INTERVAL_US / 50000)(((1)>((50 * 1000) / 50000))?(1):((50 * 1000) / 50000)); |
1535 | struct timeval tv = { .tv_sec = 0, .tv_usec = min_us }; |
1536 | |
1537 | DEBUGD(&nb_dbg_events, "NB oper-state: yielding %s for %lus (should_batch %d)",do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: yielding %s for %lus (should_batch %d)" ), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 1538, "lib/northbound_oper.c", __func__, } , .fmtstring = ("NB oper-state: yielding %s for %lus (should_batch %d)" ), .priority = (7), .ec = (0), .args = ("ys->xpath, tv.tv_usec, ys->should_batch" ), }; static const struct xref * const xref_p_312 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("NB oper-state: yielding %s for %lus (should_batch %d)" ), ys->xpath, tv.tv_usec, ys->should_batch); } while (0 ); } while (0) |
1538 | ys->xpath, tv.tv_usec, ys->should_batch)do { if (((__c11_atomic_load(&(&nb_dbg_events)->flags , memory_order_seq_cst)) & (((0x01000000 | 0x02000000))& (0x01000000 | 0x02000000)))) do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, . hashstr = ("NB oper-state: yielding %s for %lus (should_batch %d)" ), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata ), (XREFT_LOGMSG), 1538, "lib/northbound_oper.c", __func__, } , .fmtstring = ("NB oper-state: yielding %s for %lus (should_batch %d)" ), .priority = (7), .ec = (0), .args = ("ys->xpath, tv.tv_usec, ys->should_batch" ), }; static const struct xref * const xref_p_312 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("NB oper-state: yielding %s for %lus (should_batch %d)" ), ys->xpath, tv.tv_usec, ys->should_batch); } while (0 ); } while (0); |
1539 | |
1540 | if (ys->should_batch) { |
1541 | /* |
1542 | * TODO: add ability of finish to influence the timer. |
1543 | * This will allow, for example, flow control based on how long |
1544 | * it takes finish to process the batch. |
1545 | */ |
1546 | ret = (*ys->finish)(ys_root_node(ys), ys->finish_arg, NB_YIELD); |
1547 | if (ret != NB_OK) |
1548 | return ret; |
1549 | /* now trim out that data we just "finished" */ |
1550 | nb_op_trim_yield_state(ys); |
1551 | |
1552 | } |
1553 | |
1554 | event_add_timer_tv(event_loop, nb_op_walk_continue, ys, &tv,({ static const struct xref_eventsched _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1555, "lib/northbound_oper.c" , __func__, }, .funcname = "nb_op_walk_continue", .dest = "&ys->walk_ev" , .event_type = EVENT_TIMER, }; static const struct xref * const xref_p_313 __attribute__((used, section("xref_array"))) = & (_xref.xref); _event_add_timer_tv(&_xref, event_loop, nb_op_walk_continue , ys, &tv, &ys->walk_ev); }) |
1555 | &ys->walk_ev)({ static const struct xref_eventsched _xref __attribute__( ( used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1555, "lib/northbound_oper.c" , __func__, }, .funcname = "nb_op_walk_continue", .dest = "&ys->walk_ev" , .event_type = EVENT_TIMER, }; static const struct xref * const xref_p_313 __attribute__((used, section("xref_array"))) = & (_xref.xref); _event_add_timer_tv(&_xref, event_loop, nb_op_walk_continue , ys, &tv, &ys->walk_ev); }); |
1556 | return NB_OK; |
1557 | } |
1558 | |
1559 | static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, |
1560 | struct nb_node **last) |
1561 | { |
1562 | const struct lysc_node *sn; |
1563 | struct nb_node *nblast; |
1564 | char *s, *s2; |
1565 | int count; |
1566 | uint i; |
1567 | |
1568 | /* |
1569 | * Get the schema node stack for the entire query string |
1570 | * |
1571 | * The user might pass in something like "//metric" which may resolve to |
1572 | * more than one schema node ("trunks"). nb_node_find() returns a single |
1573 | * node though. We should expand the functionality to get the set of |
1574 | * nodes that matches the xpath (not path) query and save that set in |
1575 | * the yield state. Then we should do a walk using the users query |
1576 | * string over each schema trunk in the set. |
1577 | */ |
1578 | nblast = nb_node_find(ys->xpath); |
1579 | if (!nblast) { |
1580 | flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unknown data path: %s" ), .hashu32 = {(4), (EC_LIB_YANG_UNKNOWN_DATA_PATH)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1581, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unknown data path: %s"), .priority = (4), .ec = (EC_LIB_YANG_UNKNOWN_DATA_PATH), .args = ("__func__, ys->xpath" ), }; static const struct xref * const xref_p_314 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: unknown data path: %s"), __func__, ys-> xpath); } while (0) |
1581 | "%s: unknown data path: %s", __func__, ys->xpath)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = { .xref = ((void*)0), .uid = {}, .hashstr = ("%s: unknown data path: %s" ), .hashu32 = {(4), (EC_LIB_YANG_UNKNOWN_DATA_PATH)}, }, }; static const struct xref_logmsg _xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 1581, "lib/northbound_oper.c" , __func__, }, .fmtstring = ("%s: unknown data path: %s"), .priority = (4), .ec = (EC_LIB_YANG_UNKNOWN_DATA_PATH), .args = ("__func__, ys->xpath" ), }; static const struct xref * const xref_p_314 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); zlog_ref (&_xref, ("%s: unknown data path: %s"), __func__, ys-> xpath); } while (0); |
1582 | return NB_ERR; |
1583 | } |
1584 | *last = nblast; |
1585 | |
1586 | /* |
1587 | * Create a stack of schema nodes one element per node in the query |
1588 | * path, only the top (last) element may be a non-container type. |
1589 | * |
1590 | * NOTE: appears to be a bug in nb_node linkage where parent can be NULL, |
1591 | * or I'm misunderstanding the code, in any case we use the libyang |
1592 | * linkage to walk which works fine. |
1593 | * |
1594 | * XXX: we don't actually support choice/case yet, they are container |
1595 | * types in the libyang schema, but won't be in data so our length |
1596 | * checking gets messed up. |
1597 | */ |
1598 | for (sn = nblast->snode, count = 0; sn; count++, sn = sn->parent) |
1599 | if (sn != nblast->snode) |
1600 | assert(CHECK_FLAG(sn->nodetype,({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1602, "lib/northbound_oper.c" , __func__, }, .expr = "CHECK_FLAG(sn->nodetype, LYS_CONTAINER | LYS_LIST | LYS_CHOICE | LYS_CASE)" , }; static const struct xref * const xref_p_315 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080 ))) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void* )0)); } while (((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080))); }) |
1601 | LYS_CONTAINER | LYS_LIST |({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1602, "lib/northbound_oper.c" , __func__, }, .expr = "CHECK_FLAG(sn->nodetype, LYS_CONTAINER | LYS_LIST | LYS_CHOICE | LYS_CASE)" , }; static const struct xref * const xref_p_315 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080 ))) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void* )0)); } while (((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080))); }) |
1602 | LYS_CHOICE | LYS_CASE))({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1602, "lib/northbound_oper.c" , __func__, }, .expr = "CHECK_FLAG(sn->nodetype, LYS_CONTAINER | LYS_LIST | LYS_CHOICE | LYS_CASE)" , }; static const struct xref * const xref_p_315 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect ((((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080 ))) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void* )0)); } while (((sn->nodetype) & (0x0001 | 0x0010 | 0x0002 | 0x0080))); }); |
1603 | /* create our arrays */ |
1604 | darr_append_n(ys->schema_path, count)({ uint __len = (((ys->schema_path) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->schema_path)) - 1)->len); ({ if ((ssize_t)(((ys->schema_path) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->schema_path)) - 1)->cap) < (ssize_t)(__len + (count))) ({ ((ys->schema_path)) = __darr_resize ((ys->schema_path), (__len + (count)), sizeof(((ys->schema_path ))[0]), MTYPE_DARR); }); (ys->schema_path); }); (((struct darr_metadata *)(ys->schema_path)) - 1)->len = __len + (count); if ( 0) memset(&(ys->schema_path)[__len], 0, (count)*sizeof ((ys->schema_path)[0])); &(ys->schema_path)[__len]; }); |
1605 | darr_append_n(ys->query_tokens, count)({ uint __len = (((ys->query_tokens) == ((void*)0)) ? 0 : ( ((struct darr_metadata *)(ys->query_tokens)) - 1)->len) ; ({ if ((ssize_t)(((ys->query_tokens) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->query_tokens)) - 1)->cap ) < (ssize_t)(__len + (count))) ({ ((ys->query_tokens)) = __darr_resize((ys->query_tokens), (__len + (count)), sizeof (((ys->query_tokens))[0]), MTYPE_DARR); }); (ys->query_tokens ); }); (((struct darr_metadata *)(ys->query_tokens)) - 1)-> len = __len + (count); if (0) memset(&(ys->query_tokens )[__len], 0, (count)*sizeof((ys->query_tokens)[0])); & (ys->query_tokens)[__len]; }); |
1606 | for (sn = nblast->snode; sn; sn = sn->parent) |
1607 | ys->schema_path[--count] = sn; |
1608 | |
1609 | /* |
1610 | * Now tokenize the query string and get pointers to each token |
1611 | */ |
1612 | |
1613 | /* Get copy of query string start after initial '/'s */ |
1614 | s = ys->xpath; |
1615 | while (*s && *s == '/') |
1616 | s++; |
1617 | ys->query_tokstr = darr_strdup(s)({ size_t __size = strlen(s) + 1; char *__s = ((void*)0); ({ if ((ssize_t)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) < (ssize_t)(((ssize_t)(0) > (ssize_t )__size) ? (size_t)(0) : __size)) ({ ((__s)) = __darr_resize( (__s), (((ssize_t)(0) > (ssize_t)__size) ? (size_t)(0) : __size ), sizeof(((__s))[0]), MTYPE_DARR_STR); }); (__s); }); strlcpy (__s, (s), (((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap)); do { ({ static const struct xref_assert _xref __attribute__( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT ), 1617, "lib/northbound_oper.c", __func__, }, .expr = "(__s) || !((size_t)__size)" , }; static const struct xref * const xref_p_316 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((__s) || !((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed (&_xref, ((void*)0)); } while ((__s) || !((size_t)__size) ); }); if ((__s)) { ({ static const struct xref_assert _xref __attribute__ ( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1617, "lib/northbound_oper.c" , __func__, }, .expr = "(long long)darr_cap(__s) >= (long long)((size_t)__size)" , }; static const struct xref * const xref_p_317 __attribute__ ((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect (((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while ((long long)(((__s) == ((void*)0)) ? 0 : (((struct darr_metadata *)(__s)) - 1)->cap) >= (long long)((size_t)__size)); } ); (((struct darr_metadata *)(__s)) - 1)->len = ((size_t)__size ); } } while (0); __s; }); |
1618 | s = ys->query_tokstr; |
1619 | |
1620 | darr_foreach_i (ys->schema_path, i)for ((i) = 0; (i) < (((ys->schema_path) == ((void*)0)) ? 0 : (((struct darr_metadata *)(ys->schema_path)) - 1)-> len); (i)++) { |
1621 | const char *modname = ys->schema_path[i]->module->name; |
1622 | const char *name = ys->schema_path[i]->name; |
1623 | int nlen = strlen(name); |
1624 | int mnlen = 0; |
1625 | |
1626 | while (true1) { |
1627 | s2 = strstr(s, name); |
1628 | if (!s2) |
1629 | goto error; |
1630 | |
1631 | if (s2[-1] == ':') { |
1632 | mnlen = strlen(modname) + 1; |
1633 | if (ys->query_tokstr > s2 - mnlen || |
1634 | strncmp(s2 - mnlen, modname, mnlen - 1)) |
1635 | goto error; |
1636 | s2 -= mnlen; |
1637 | nlen += mnlen; |
1638 | } |
1639 | |
1640 | s = s2; |
1641 | if ((i == 0 || s[-1] == '/') && |
1642 | (s[nlen] == 0 || s[nlen] == '[' || s[nlen] == '/')) |
1643 | break; |
1644 | /* |
1645 | * Advance past the incorrect match, must have been |
1646 | * part of previous predicate. |
1647 | */ |
1648 | s += nlen; |
1649 | } |
1650 | |
1651 | /* NUL terminate previous token and save this one */ |
1652 | if (i > 0) |
1653 | s[-1] = 0; |
1654 | ys->query_tokens[i] = s; |
1655 | s += nlen; |
1656 | } |
1657 | |
1658 | /* NOTE: need to subtract choice/case nodes when these are supported */ |
1659 | ys->query_base_level = darr_lasti(ys->schema_path)((((ys->schema_path) == ((void*)0)) ? 0 : (ssize_t)(((struct darr_metadata *)(ys->schema_path)) - 1)->len) - 1); |
1660 | |
1661 | return NB_OK; |
1662 | |
1663 | error: |
1664 | darr_free(ys->query_tokstr)do { if ((ys->query_tokstr)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->query_tokstr)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->query_tokstr) = ((void*)0); } } while (0); |
1665 | darr_free(ys->schema_path)do { if ((ys->schema_path)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->schema_path)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->schema_path) = ((void*)0); } } while (0); |
1666 | darr_free(ys->query_tokens)do { if ((ys->query_tokens)) { struct darr_metadata *__meta = (((struct darr_metadata *)(ys->query_tokens)) - 1); do { qfree(__meta->mtype, __meta); __meta = ((void*)0); } while (0); (ys->query_tokens) = ((void*)0); } } while (0); |
1667 | return NB_ERR; |
1668 | } |
1669 | |
1670 | |
1671 | /** |
1672 | * nb_op_walk_start() - Start walking oper-state directed by query string. |
1673 | * @ys: partially initialized yield state for this walk. |
1674 | * |
1675 | */ |
1676 | static enum nb_error nb_op_walk_start(struct nb_op_yield_state *ys) |
1677 | { |
1678 | struct nb_node *nblast; |
1679 | enum nb_error ret; |
1680 | |
1681 | /* |
1682 | * Get nb_node path (stack) corresponding to the xpath query |
1683 | */ |
1684 | ret = nb_op_ys_init_schema_path(ys, &nblast); |
1685 | if (ret != NB_OK) |
1686 | return ret; |
1687 | |
1688 | |
1689 | /* |
1690 | * Get the node_info path (stack) corresponding to the uniquely |
1691 | * resolvable data nodes from the beginning of the xpath query. |
1692 | */ |
1693 | ret = nb_op_ys_init_node_infos(ys); |
1694 | if (ret != NB_OK) |
1695 | return ret; |
1696 | |
1697 | return __walk(ys, false0); |
1698 | } |
1699 | |
1700 | |
1701 | void *nb_oper_walk(const char *xpath, struct yang_translator *translator, |
1702 | uint32_t flags, bool_Bool should_batch, nb_oper_data_cb cb, |
1703 | void *cb_arg, nb_oper_data_finish_cb finish, void *finish_arg) |
1704 | { |
1705 | struct nb_op_yield_state *ys; |
1706 | enum nb_error ret; |
1707 | |
1708 | ys = nb_op_create_yield_state(xpath, translator, flags, should_batch, |
1709 | cb, cb_arg, finish, finish_arg); |
1710 | |
1711 | ret = nb_op_walk_start(ys); |
1712 | if (ret == NB_YIELD) { |
1713 | if (nb_op_yield(ys) != NB_OK) { |
1714 | if (ys->should_batch) |
1715 | goto stopped; |
1716 | else |
1717 | goto finish; |
1718 | } |
1719 | return ys; |
1720 | } |
1721 | finish: |
1722 | (void)(*ys->finish)(ys_root_node(ys), ys->finish_arg, ret); |
1723 | stopped: |
1724 | nb_op_free_yield_state(ys, false0); |
1725 | return NULL((void*)0); |
1726 | } |
1727 | |
1728 | |
1729 | void nb_oper_cancel_walk(void *walk) |
1730 | { |
1731 | if (walk) |
1732 | nb_op_free_yield_state(walk, false0); |
1733 | } |
1734 | |
1735 | |
1736 | void nb_oper_cancel_all_walks(void) |
1737 | { |
1738 | struct nb_op_yield_state *ys; |
1739 | |
1740 | frr_each_safe (nb_op_walks, &nb_op_walks, ys)for (typeof(nb_op_walks_next_safe(&nb_op_walks, ((void*)0 ))) nb_op_walks_safe = nb_op_walks_next_safe(&nb_op_walks , (ys = nb_op_walks_first(&nb_op_walks))); ys; ys = nb_op_walks_safe , nb_op_walks_safe = nb_op_walks_next_safe(&nb_op_walks, nb_op_walks_safe )) |
1741 | nb_oper_cancel_walk(ys); |
1742 | } |
1743 | |
1744 | |
1745 | /* |
1746 | * The old API -- remove when we've update the users to yielding. |
1747 | */ |
1748 | enum nb_error nb_oper_iterate_legacy(const char *xpath, |
1749 | struct yang_translator *translator, |
1750 | uint32_t flags, nb_oper_data_cb cb, |
1751 | void *cb_arg, struct lyd_node **tree) |
1752 | { |
1753 | struct nb_op_yield_state *ys; |
1754 | enum nb_error ret; |
1755 | |
1756 | ys = nb_op_create_yield_state(xpath, translator, flags, false0, cb, |
1757 | cb_arg, NULL((void*)0), NULL((void*)0)); |
1758 | |
1759 | ret = nb_op_walk_start(ys); |
1760 | assert(ret != NB_YIELD)({ static const struct xref_assert _xref __attribute__( (used )) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1760, "lib/northbound_oper.c" , __func__, }, .expr = "ret != NB_YIELD", }; static const struct xref * const xref_p_318 __attribute__((used, section("xref_array" ))) = &(_xref.xref); if (__builtin_expect((ret != NB_YIELD ) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0 )); } while (ret != NB_YIELD); }); |
1761 | |
1762 | if (tree && ret == NB_OK) |
1763 | *tree = ys_root_node(ys); |
1764 | else { |
1765 | if (ys_root_node(ys)) |
1766 | yang_dnode_free(ys_root_node(ys)); |
1767 | if (tree) |
1768 | *tree = NULL((void*)0); |
1769 | } |
1770 | |
1771 | nb_op_free_yield_state(ys, true1); |
1772 | return ret; |
1773 | } |
1774 | |
1775 | void nb_oper_init(struct event_loop *loop) |
1776 | { |
1777 | event_loop = loop; |
1778 | nb_op_walks_init(&nb_op_walks); |
1779 | } |
1780 | |
1781 | void nb_oper_terminate(void) |
1782 | { |
1783 | nb_oper_cancel_all_walks(); |
1784 | } |