blob: 188b52c98aeccc52a8231b4fdad85926055e9f8e [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 Krejci77114102021-03-10 15:21:57 +010018#include "dict.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020019#include "hash_table.h"
Radek Krejci47fab892020-11-05 17:02:41 +010020#include "log.h"
Michal Vasko8f702ee2024-02-20 15:44:24 +010021#include "ly_common.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"
aPiecek6cf1d162023-11-08 16:07:00 +010027#include "tree_data_sorted.h"
Michal Vasko69730152020-10-09 16:30:07 +020028#include "tree_schema.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020029
Michal Vasko3a41dff2020-07-15 14:30:28 +020030static void
Radek Krejci857189e2020-09-01 13:26:36 +020031lyd_free_meta(struct lyd_meta *meta, ly_bool siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020032{
Michal Vasko9f96a052020-03-10 09:41:45 +010033 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020034
Michal Vasko9f96a052020-03-10 09:41:45 +010035 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020036 return;
37 }
38
Michal Vasko9f96a052020-03-10 09:41:45 +010039 if (meta->parent) {
40 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020041 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010042 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020043 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010044 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020045 }
46 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020047 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020048 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020049 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020050 iter->next = NULL;
51 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010052 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020053 }
54 }
55 }
56 }
57
Michal Vasko3a41dff2020-07-15 14:30:28 +020058 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010059 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020060 }
61
Michal Vasko52927e22020-03-16 17:26:14 +010062 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010063 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020064 iter = iter->next;
65
Michal Vaskoe180ed02021-02-05 16:31:20 +010066 lydict_remove(meta->annotation->module->ctx, meta->name);
Michal Vasko3a41dff2020-07-15 14:30:28 +020067 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010068 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020069 }
70}
71
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010072LIBYANG_API_DEF void
Michal Vasko3a41dff2020-07-15 14:30:28 +020073lyd_free_meta_single(struct lyd_meta *meta)
74{
75 lyd_free_meta(meta, 0);
76}
77
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010078LIBYANG_API_DEF void
Michal Vasko3a41dff2020-07-15 14:30:28 +020079lyd_free_meta_siblings(struct lyd_meta *meta)
80{
81 lyd_free_meta(meta, 1);
82}
83
84static void
Radek Krejci011e4aa2020-09-04 15:22:31 +020085lyd_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, ly_bool siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010086{
Radek Krejci1798aae2020-07-14 13:26:06 +020087 struct lyd_attr *iter;
Michal Vasko52927e22020-03-16 17:26:14 +010088
89 LY_CHECK_ARG_RET(NULL, ctx, );
90 if (!attr) {
91 return;
92 }
93
94 if (attr->parent) {
95 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020096 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +010097 attr->parent->attr = NULL;
98 } else {
99 attr->parent->attr = attr->next;
100 }
101 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200102 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +0100103 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200104 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100105 iter->next = NULL;
106 } else {
107 iter->next = attr->next;
108 }
109 }
110 }
111 }
112
Michal Vasko3a41dff2020-07-15 14:30:28 +0200113 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100114 attr->next = NULL;
115 }
116
117 for (iter = attr; iter; ) {
118 attr = iter;
119 iter = iter->next;
120
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100121 ly_free_prefix_data(attr->format, attr->val_prefix_data);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100122 lydict_remove(ctx, attr->name.name);
123 lydict_remove(ctx, attr->name.prefix);
124 lydict_remove(ctx, attr->name.module_ns);
125 lydict_remove(ctx, attr->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100126 free(attr);
127 }
128}
129
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100130LIBYANG_API_DEF void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200131lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200132{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200133 lyd_free_attr(ctx, attr, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200134}
135
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100136LIBYANG_API_DEF void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200137lyd_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200138{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200139 lyd_free_attr(ctx, attr, 1);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200140}
141
stewegf9041a22024-01-18 13:29:12 +0100142void
143lyd_free_leafref_links_rec(struct lyd_leafref_links_rec *rec)
144{
145 LY_ARRAY_COUNT_TYPE u;
steweg67388952024-01-25 12:14:50 +0100146 struct lyd_leafref_links_rec *rec2;
stewegf9041a22024-01-18 13:29:12 +0100147
148 assert(rec);
149
steweg67388952024-01-25 12:14:50 +0100150 /* remove links of leafref nodes */
stewegf9041a22024-01-18 13:29:12 +0100151 LY_ARRAY_FOR(rec->leafref_nodes, u) {
steweg67388952024-01-25 12:14:50 +0100152 if (lyd_get_or_create_leafref_links_record(rec->leafref_nodes[u], &rec2, 0) == LY_SUCCESS) {
153 LY_ARRAY_REMOVE_VALUE(rec2->target_nodes, rec->node);
154 if ((LY_ARRAY_COUNT(rec2->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec2->target_nodes) == 0)) {
stewegf9041a22024-01-18 13:29:12 +0100155 lyd_free_leafref_nodes(rec->leafref_nodes[u]);
156 }
157 }
158 }
159 LY_ARRAY_FREE(rec->leafref_nodes);
160 rec->leafref_nodes = NULL;
Michal Vaskob46061d2024-01-18 13:58:13 +0100161
steweg67388952024-01-25 12:14:50 +0100162 /* remove links of target nodes */
163 LY_ARRAY_FOR(rec->target_nodes, u) {
164 if (lyd_get_or_create_leafref_links_record(rec->target_nodes[u], &rec2, 0) == LY_SUCCESS) {
165 LY_ARRAY_REMOVE_VALUE(rec2->leafref_nodes, rec->node);
166 if ((LY_ARRAY_COUNT(rec2->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec2->target_nodes) == 0)) {
167 lyd_free_leafref_nodes(rec->target_nodes[u]);
168 }
169 }
stewegf9041a22024-01-18 13:29:12 +0100170 }
steweg67388952024-01-25 12:14:50 +0100171 LY_ARRAY_FREE(rec->target_nodes);
172 rec->target_nodes = NULL;
stewegf9041a22024-01-18 13:29:12 +0100173}
174
175void
176lyd_free_leafref_nodes(const struct lyd_node_term *node)
177{
178 struct ly_ht *ht;
179 uint32_t hash;
180 struct lyd_leafref_links_rec *rec;
181
182 assert(node);
183
Michal Vaskob46061d2024-01-18 13:58:13 +0100184 if (lyd_get_or_create_leafref_links_record(node, &rec, 0)) {
stewegf9041a22024-01-18 13:29:12 +0100185 return;
186 }
187
188 /* free entry content */
189 lyd_free_leafref_links_rec(rec);
190
191 /* free entry itself from hash table */
192 ht = LYD_CTX(node)->leafref_links_ht;
Michal Vasko67bf5872024-01-18 13:58:25 +0100193 hash = lyht_hash((const char *)&node, sizeof node);
stewegf9041a22024-01-18 13:29:12 +0100194 lyht_remove(ht, rec, hash);
195}
196
Radek Krejcie7b95092019-05-15 11:03:07 +0200197/**
198 * @brief Free Data (sub)tree.
Michal Vaskob46061d2024-01-18 13:58:13 +0100199 *
Radek Krejcie7b95092019-05-15 11:03:07 +0200200 * @param[in] node Data node to be freed.
Radek Krejcie7b95092019-05-15 11:03:07 +0200201 */
202static void
aPiecek852d93f2023-11-24 13:59:07 +0100203lyd_free_subtree(struct lyd_node *node)
Radek Krejcie7b95092019-05-15 11:03:07 +0200204{
205 struct lyd_node *iter, *next;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200206 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200207
208 assert(node);
209
Michal Vasko52927e22020-03-16 17:26:14 +0100210 if (!node->schema) {
211 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200212
213 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100214 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
aPiecek852d93f2023-11-24 13:59:07 +0100215 lyd_free_subtree(iter);
Michal Vasko52927e22020-03-16 17:26:14 +0100216 }
217
Michal Vaskoe180ed02021-02-05 16:31:20 +0100218 lydict_remove(LYD_CTX(opaq), opaq->name.name);
219 lydict_remove(LYD_CTX(opaq), opaq->name.prefix);
220 lydict_remove(LYD_CTX(opaq), opaq->name.module_ns);
221 lydict_remove(LYD_CTX(opaq), opaq->value);
Michal Vasko501af032020-11-11 20:27:44 +0100222 ly_free_prefix_data(opaq->format, opaq->val_prefix_data);
Michal Vasko52927e22020-03-16 17:26:14 +0100223 } else if (node->schema->nodetype & LYD_NODE_INNER) {
224 /* remove children hash table in case of inner data node */
Michal Vasko77b7f90a2023-01-31 15:42:41 +0100225 lyht_free(((struct lyd_node_inner *)node)->children_ht, NULL);
Michal Vasko52927e22020-03-16 17:26:14 +0100226
227 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100228 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
aPiecek852d93f2023-11-24 13:59:07 +0100229 lyd_free_subtree(iter);
Radek Krejcie7b95092019-05-15 11:03:07 +0200230 }
231 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200232 /* only frees the value this way */
233 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200234 } else if (node->schema->nodetype & LYD_NODE_TERM) {
stewegf9041a22024-01-18 13:29:12 +0100235 struct lyd_node_term *node_term = (struct lyd_node_term *)node;
236
237 ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_CTX(node), &node_term->value);
238 lyd_free_leafref_nodes(node_term);
Radek Krejcie7b95092019-05-15 11:03:07 +0200239 }
240
Michal Vasko52927e22020-03-16 17:26:14 +0100241 if (!node->schema) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200242 lyd_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100243 } else {
244 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200245 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100246 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200247
Radek Krejcie7b95092019-05-15 11:03:07 +0200248 free(node);
249}
250
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100251LIBYANG_API_DEF void
Radek Krejcie7b95092019-05-15 11:03:07 +0200252lyd_free_tree(struct lyd_node *node)
253{
254 if (!node) {
255 return;
256 }
257
Michal Vasko0dc4a262023-09-04 09:27:24 +0200258 if (lysc_is_key(node->schema) && node->parent) {
259 LOGERR(LYD_CTX(node), LY_EINVAL, "Cannot free a list key \"%s\", free the list instance instead.", LYD_NAME(node));
260 return;
261 }
262
aPiecek852d93f2023-11-24 13:59:07 +0100263 lyd_unlink(node);
264 lyd_free_subtree(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200265}
266
Radek Krejcib0849a22019-07-25 12:31:04 +0200267static void
aPiecek852d93f2023-11-24 13:59:07 +0100268lyd_free_(struct lyd_node *node)
Radek Krejcie7b95092019-05-15 11:03:07 +0200269{
270 struct lyd_node *iter, *next;
271
272 if (!node) {
273 return;
274 }
275
aPiecek852d93f2023-11-24 13:59:07 +0100276 /* get the first sibling */
Radek Krejcie7b95092019-05-15 11:03:07 +0200277 while (node->prev->next) {
278 node = node->prev;
279 }
280
281 LY_LIST_FOR_SAFE(node, next, iter) {
Michal Vasko0dc4a262023-09-04 09:27:24 +0200282 if (lysc_is_key(iter->schema) && iter->parent) {
Michal Vasko687609f2023-09-04 10:29:11 +0200283 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 +0200284 return;
285 }
286
Radek Krejcie7b95092019-05-15 11:03:07 +0200287 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
aPiecek852d93f2023-11-24 13:59:07 +0100288 if (iter->parent) {
aPiecek6cf1d162023-11-08 16:07:00 +0100289 lyds_free_metadata(iter);
aPiecek852d93f2023-11-24 13:59:07 +0100290 lyd_unlink(iter);
291 }
292 lyd_free_subtree(iter);
Radek Krejcie7b95092019-05-15 11:03:07 +0200293 }
294}
Radek Krejcib0849a22019-07-25 12:31:04 +0200295
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100296LIBYANG_API_DEF void
Michal Vaskof03ed032020-03-04 13:31:44 +0100297lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200298{
aPiecek852d93f2023-11-24 13:59:07 +0100299 lyd_free_(node);
Radek Krejcib0849a22019-07-25 12:31:04 +0200300}
301
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100302LIBYANG_API_DEF void
Radek Krejcib0849a22019-07-25 12:31:04 +0200303lyd_free_all(struct lyd_node *node)
304{
aPiecek852d93f2023-11-24 13:59:07 +0100305 if (!node) {
306 return;
307 }
308
309 /* get top-level node */
310 for ( ; node->parent; node = lyd_parent(node)) {}
311
312 lyd_free_(node);
Radek Krejcib0849a22019-07-25 12:31:04 +0200313}