blob: ce4e5269a3b79ba81f1f9dc4643c99b7351365f2 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file tree_data_free.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Freeing functions for data tree structures
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Radek Krejcie7b95092019-05-15 11:03:07 +020015#include <assert.h>
16#include <stdlib.h>
17
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include "common.h"
Radek Krejci77114102021-03-10 15:21:57 +010019#include "dict.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020020#include "hash_table.h"
Radek Krejci47fab892020-11-05 17:02:41 +010021#include "log.h"
Michal Vaskob4750962022-10-06 15:33:35 +020022#include "plugins_exts/metadata.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020023#include "plugins_types.h"
Michal Vasko69730152020-10-09 16:30:07 +020024#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010025#include "tree_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020026#include "tree_data_internal.h"
27#include "tree_schema.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020028
Michal Vasko3a41dff2020-07-15 14:30:28 +020029static void
Radek Krejci857189e2020-09-01 13:26:36 +020030lyd_free_meta(struct lyd_meta *meta, ly_bool siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020031{
Michal Vasko9f96a052020-03-10 09:41:45 +010032 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020033
Michal Vasko9f96a052020-03-10 09:41:45 +010034 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020035 return;
36 }
37
Michal Vasko9f96a052020-03-10 09:41:45 +010038 if (meta->parent) {
39 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020040 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010041 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020042 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010043 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020044 }
45 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020046 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020047 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020048 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020049 iter->next = NULL;
50 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010051 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020052 }
53 }
54 }
55 }
56
Michal Vasko3a41dff2020-07-15 14:30:28 +020057 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010058 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020059 }
60
Michal Vasko52927e22020-03-16 17:26:14 +010061 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010062 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020063 iter = iter->next;
64
Michal Vaskoe180ed02021-02-05 16:31:20 +010065 lydict_remove(meta->annotation->module->ctx, meta->name);
Michal Vasko3a41dff2020-07-15 14:30:28 +020066 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010067 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020068 }
69}
70
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010071LIBYANG_API_DEF void
Michal Vasko3a41dff2020-07-15 14:30:28 +020072lyd_free_meta_single(struct lyd_meta *meta)
73{
74 lyd_free_meta(meta, 0);
75}
76
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010077LIBYANG_API_DEF void
Michal Vasko3a41dff2020-07-15 14:30:28 +020078lyd_free_meta_siblings(struct lyd_meta *meta)
79{
80 lyd_free_meta(meta, 1);
81}
82
83static void
Radek Krejci011e4aa2020-09-04 15:22:31 +020084lyd_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, ly_bool siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010085{
Radek Krejci1798aae2020-07-14 13:26:06 +020086 struct lyd_attr *iter;
Michal Vasko52927e22020-03-16 17:26:14 +010087
88 LY_CHECK_ARG_RET(NULL, ctx, );
89 if (!attr) {
90 return;
91 }
92
93 if (attr->parent) {
94 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020095 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +010096 attr->parent->attr = NULL;
97 } else {
98 attr->parent->attr = attr->next;
99 }
100 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200101 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +0100102 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200103 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100104 iter->next = NULL;
105 } else {
106 iter->next = attr->next;
107 }
108 }
109 }
110 }
111
Michal Vasko3a41dff2020-07-15 14:30:28 +0200112 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100113 attr->next = NULL;
114 }
115
116 for (iter = attr; iter; ) {
117 attr = iter;
118 iter = iter->next;
119
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100120 ly_free_prefix_data(attr->format, attr->val_prefix_data);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100121 lydict_remove(ctx, attr->name.name);
122 lydict_remove(ctx, attr->name.prefix);
123 lydict_remove(ctx, attr->name.module_ns);
124 lydict_remove(ctx, attr->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100125 free(attr);
126 }
127}
128
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100129LIBYANG_API_DEF void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200130lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200131{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200132 lyd_free_attr(ctx, attr, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200133}
134
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100135LIBYANG_API_DEF void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200136lyd_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200137{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200138 lyd_free_attr(ctx, attr, 1);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200139}
140
stewegf9041a22024-01-18 13:29:12 +0100141void
142lyd_free_leafref_links_rec(struct lyd_leafref_links_rec *rec)
143{
144 LY_ARRAY_COUNT_TYPE u;
145 struct lyd_leafref_links_rec *leafref_rec;
146
147 assert(rec);
148
149 /* remove stored leafref nodes */
150 LY_ARRAY_FOR(rec->leafref_nodes, u) {
151 if (lyd_get_or_create_leafref_links_record(rec->leafref_nodes[u], &leafref_rec, 0) == LY_SUCCESS) {
152 leafref_rec->target_node = NULL;
Michal Vaskob46061d2024-01-18 13:58:13 +0100153 if (!LY_ARRAY_COUNT(leafref_rec->leafref_nodes) && !leafref_rec->target_node) {
stewegf9041a22024-01-18 13:29:12 +0100154 lyd_free_leafref_nodes(rec->leafref_nodes[u]);
155 }
156 }
157 }
158 LY_ARRAY_FREE(rec->leafref_nodes);
159 rec->leafref_nodes = NULL;
Michal Vaskob46061d2024-01-18 13:58:13 +0100160
stewegf9041a22024-01-18 13:29:12 +0100161 /* remove stored target node */
162 if (rec->target_node) {
163 lyd_unlink_leafref_node(rec->target_node, rec->node);
164 }
165}
166
167void
168lyd_free_leafref_nodes(const struct lyd_node_term *node)
169{
170 struct ly_ht *ht;
171 uint32_t hash;
172 struct lyd_leafref_links_rec *rec;
173
174 assert(node);
175
Michal Vaskob46061d2024-01-18 13:58:13 +0100176 if (lyd_get_or_create_leafref_links_record(node, &rec, 0)) {
stewegf9041a22024-01-18 13:29:12 +0100177 return;
178 }
179
180 /* free entry content */
181 lyd_free_leafref_links_rec(rec);
182
183 /* free entry itself from hash table */
184 ht = LYD_CTX(node)->leafref_links_ht;
Michal Vasko67bf5872024-01-18 13:58:25 +0100185 hash = lyht_hash((const char *)&node, sizeof node);
stewegf9041a22024-01-18 13:29:12 +0100186 lyht_remove(ht, rec, hash);
187}
188
Radek Krejcie7b95092019-05-15 11:03:07 +0200189/**
190 * @brief Free Data (sub)tree.
Michal Vaskob46061d2024-01-18 13:58:13 +0100191 *
Radek Krejcie7b95092019-05-15 11:03:07 +0200192 * @param[in] node Data node to be freed.
193 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
194 */
195static void
Radek Krejci857189e2020-09-01 13:26:36 +0200196lyd_free_subtree(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200197{
198 struct lyd_node *iter, *next;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200199 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200200
201 assert(node);
202
Michal Vasko52927e22020-03-16 17:26:14 +0100203 if (!node->schema) {
204 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200205
206 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100207 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100208 lyd_free_subtree(iter, 0);
209 }
210
Michal Vaskoe180ed02021-02-05 16:31:20 +0100211 lydict_remove(LYD_CTX(opaq), opaq->name.name);
212 lydict_remove(LYD_CTX(opaq), opaq->name.prefix);
213 lydict_remove(LYD_CTX(opaq), opaq->name.module_ns);
214 lydict_remove(LYD_CTX(opaq), opaq->value);
Michal Vasko501af032020-11-11 20:27:44 +0100215 ly_free_prefix_data(opaq->format, opaq->val_prefix_data);
Michal Vasko52927e22020-03-16 17:26:14 +0100216 } else if (node->schema->nodetype & LYD_NODE_INNER) {
217 /* remove children hash table in case of inner data node */
Michal Vasko77b7f90a2023-01-31 15:42:41 +0100218 lyht_free(((struct lyd_node_inner *)node)->children_ht, NULL);
Michal Vasko52927e22020-03-16 17:26:14 +0100219 ((struct lyd_node_inner *)node)->children_ht = NULL;
220
221 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100222 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100223 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200224 }
225 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200226 /* only frees the value this way */
227 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200228 } else if (node->schema->nodetype & LYD_NODE_TERM) {
stewegf9041a22024-01-18 13:29:12 +0100229 struct lyd_node_term *node_term = (struct lyd_node_term *)node;
230
231 ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_CTX(node), &node_term->value);
232 lyd_free_leafref_nodes(node_term);
Radek Krejcie7b95092019-05-15 11:03:07 +0200233 }
234
Michal Vasko52927e22020-03-16 17:26:14 +0100235 if (!node->schema) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200236 lyd_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100237 } else {
238 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200239 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100240 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200241
242 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
243 if (top) {
Michal Vasko2e784f82024-01-11 09:51:22 +0100244 lyd_unlink(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200245 }
246
247 free(node);
248}
249
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100250LIBYANG_API_DEF void
Radek Krejcie7b95092019-05-15 11:03:07 +0200251lyd_free_tree(struct lyd_node *node)
252{
253 if (!node) {
254 return;
255 }
256
Michal Vasko0dc4a262023-09-04 09:27:24 +0200257 if (lysc_is_key(node->schema) && node->parent) {
258 LOGERR(LYD_CTX(node), LY_EINVAL, "Cannot free a list key \"%s\", free the list instance instead.", LYD_NAME(node));
259 return;
260 }
261
Michal Vasko52927e22020-03-16 17:26:14 +0100262 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200263}
264
Radek Krejcib0849a22019-07-25 12:31:04 +0200265static void
Radek Krejci857189e2020-09-01 13:26:36 +0200266lyd_free_(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200267{
268 struct lyd_node *iter, *next;
269
270 if (!node) {
271 return;
272 }
273
Radek Krejcib0849a22019-07-25 12:31:04 +0200274 /* get the first (top-level) sibling */
275 if (top) {
Michal Vasko9e685082021-01-29 14:49:09 +0100276 for ( ; node->parent; node = lyd_parent(node)) {}
Radek Krejcib0849a22019-07-25 12:31:04 +0200277 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200278 while (node->prev->next) {
279 node = node->prev;
280 }
281
282 LY_LIST_FOR_SAFE(node, next, iter) {
Michal Vasko0dc4a262023-09-04 09:27:24 +0200283 if (lysc_is_key(iter->schema) && iter->parent) {
Michal Vasko687609f2023-09-04 10:29:11 +0200284 LOGERR(LYD_CTX(iter), LY_EINVAL, "Cannot free a list key \"%s\", free the list instance instead.", LYD_NAME(iter));
Michal Vasko0dc4a262023-09-04 09:27:24 +0200285 return;
286 }
287
Radek Krejcie7b95092019-05-15 11:03:07 +0200288 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100289 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200290 }
291}
Radek Krejcib0849a22019-07-25 12:31:04 +0200292
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100293LIBYANG_API_DEF void
Michal Vaskof03ed032020-03-04 13:31:44 +0100294lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200295{
296 lyd_free_(node, 0);
297}
298
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100299LIBYANG_API_DEF void
Radek Krejcib0849a22019-07-25 12:31:04 +0200300lyd_free_all(struct lyd_node *node)
301{
302 lyd_free_(node, 1);
303}