blob: 33104ccf32ef31ada78bec22aedbf9d488dd0362 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file tree_data_hash.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Functions to manipulate with the data node's hashes.
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#include "common.h"
15
16#include "hash_table.h"
17#include "tree_data.h"
Radek Krejci1f05b6a2019-07-18 16:15:06 +020018#include "plugins_types.h"
19
20
21static void
22lyd_hash_keyless_list_dfs(struct lyd_node *child, uint32_t *hash)
23{
24 struct lyd_node *iter;
25
26 LY_LIST_FOR(child, iter) {
27 switch (iter->schema->nodetype) {
28 case LYS_CONTAINER:
29 case LYS_LIST:
30 lyd_hash_keyless_list_dfs(((struct lyd_node_inner*)iter)->child, hash);
31 break;
32 case LYS_LEAFLIST:
33 case LYS_ANYXML:
34 case LYS_ANYDATA:
35 case LYS_LEAF:
36 *hash = dict_hash_multi(*hash, (char *)&iter->hash, sizeof iter->hash);
37 break;
38 default:
39 LOGINT(NULL);
40 }
41 }
42}
43
44LY_ERR
45lyd_hash(struct lyd_node *node)
46{
47 struct lyd_node *iter;
48
49 node->hash = dict_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
50 node->hash = dict_hash_multi(node->hash, node->schema->name, strlen(node->schema->name));
51
52 if (node->schema->nodetype == LYS_LIST) {
53 struct lyd_node_inner *list = (struct lyd_node_inner*)node;
Radek Krejci0fe9b512019-07-26 17:51:05 +020054 if (!(node->schema->flags & LYS_KEYLESS)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +020055 /* list's hash is made of its keys */
Radek Krejci0fe9b512019-07-26 17:51:05 +020056 struct lysc_node *key;
57 for (key = ((struct lysc_node_list*)node->schema)->child, iter = list->child;
58 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY) && iter;
59 key = key->next, iter = iter->next) {
60 for ( ; iter && iter->schema != key; iter = iter->next);
61 if (!iter) {
62 break;
63 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +020064 int dynamic = 0;
65 struct lysc_type *type = ((struct lysc_node_leaf*)iter->schema)->type;
Radek Krejci13a57b62019-07-19 13:04:09 +020066 const char *value = type->plugin->print(&((struct lyd_node_term*)iter)->value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
Radek Krejci1f05b6a2019-07-18 16:15:06 +020067 node->hash = dict_hash_multi(node->hash, value, strlen(value));
68 if (dynamic) {
69 free((char*)value);
70 }
71 }
72 } else {
73 /* keyless status list */
74 lyd_hash_keyless_list_dfs(list->child, &node->hash);
75 }
76 } else if (node->schema->nodetype == LYS_LEAFLIST) {
77 struct lyd_node_term *llist = (struct lyd_node_term*)node;
78 int dynamic = 0;
Radek Krejci13a57b62019-07-19 13:04:09 +020079 const char *value = ((struct lysc_node_leaflist*)node->schema)->type->plugin->print(&llist->value, LYD_JSON,
80 json_print_get_prefix, NULL, &dynamic);
Radek Krejci1f05b6a2019-07-18 16:15:06 +020081 node->hash = dict_hash_multi(node->hash, value, strlen(value));
82 if (dynamic) {
83 free((char*)value);
84 }
85 }
86 /* finish the hash */
87 node->hash = dict_hash_multi(node->hash, NULL, 0);
88
89 return LY_SUCCESS;
90}
91
92static int
93lyd_hash_table_val_equal(void *val1_p, void *val2_p, int mod, void *UNUSED(cb_data))
94{
95 struct lyd_node *val1, *val2;
96
97 val1 = *((struct lyd_node **)val1_p);
98 val2 = *((struct lyd_node **)val2_p);
99
100 if (mod) {
101 if (val1 == val2) {
102 return 1;
103 } else {
104 return 0;
105 }
106 }
107
108 if (!lyd_compare(val1, val2, 0)) {
109 return 1;
110 } else {
111 return 0;
112 }
113}
114
115LY_ERR
116lyd_insert_hash(struct lyd_node *node)
117{
118 struct lyd_node *iter;
119
120 if (!node->parent) {
121 /* nothing to do */
122 return LY_SUCCESS;
123 }
124
125 /* create parent hash table if required, otherwise just add the new child */
126 if (!node->parent->children_ht) {
127 unsigned int u;
128
129 /* the hash table is created only when the number of children in a node exceeds the
130 * defined minimal limit LY_CACHE_HT_MIN_CHILDREN
131 */
132 for (u = 0, iter = node->parent->child; iter; ++u, iter = iter->next);
133 if (u >= LYD_HT_MIN_ITEMS) {
134 /* create hash table, insert all the children */
135 node->parent->children_ht = lyht_new(1, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
136 LY_LIST_FOR(node->parent->child, iter) {
137 if (lyht_insert(node->parent->children_ht, &iter, iter->hash, NULL)) {
138 LOGINT(node->schema->module->ctx);
139 return LY_EINT;
140 }
141 }
142 }
143 } else {
144 if (lyht_insert(node->parent->children_ht, &node, node->hash, NULL)) {
145 LOGINT(node->schema->module->ctx);
146 return LY_EINT;
147 }
148 }
149
150 return LY_SUCCESS;
151}
Radek Krejcie7b95092019-05-15 11:03:07 +0200152
153void
154lyd_unlink_hash(struct lyd_node *node)
155{
156 if (node->parent && node->parent->children_ht) {
157 lyht_remove(node->parent->children_ht, &node, node->hash);
158 }
159}