Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file lyb.c |
3 | | * @author Michal Vasko <mvasko@cesnet.cz> |
4 | | * @brief LYB format common functionality. |
5 | | * |
6 | | * Copyright (c) 2021 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 | | |
15 | | #include "lyb.h" |
16 | | |
17 | | #include <assert.h> |
18 | | #include <pthread.h> |
19 | | #include <stdint.h> |
20 | | #include <stdlib.h> |
21 | | #include <string.h> |
22 | | |
23 | | #include "common.h" |
24 | | #include "compat.h" |
25 | | #include "tree_schema.h" |
26 | | |
27 | | /** |
28 | | * @brief Generate single hash for a schema node to be used for LYB data. |
29 | | * |
30 | | * @param[in] node Node to hash. |
31 | | * @param[in] collision_id Collision ID of the hash to generate. |
32 | | * @return Generated hash. |
33 | | */ |
34 | | static LYB_HASH |
35 | | lyb_generate_hash(const struct lysc_node *node, uint8_t collision_id) |
36 | 0 | { |
37 | 0 | const struct lys_module *mod = node->module; |
38 | 0 | uint32_t full_hash; |
39 | 0 | LYB_HASH hash; |
40 | | |
41 | | /* generate full hash */ |
42 | 0 | full_hash = dict_hash_multi(0, mod->name, strlen(mod->name)); |
43 | 0 | full_hash = dict_hash_multi(full_hash, node->name, strlen(node->name)); |
44 | 0 | if (collision_id) { |
45 | 0 | size_t ext_len; |
46 | |
|
47 | 0 | if (collision_id > strlen(mod->name)) { |
48 | | /* fine, we will not hash more bytes, just use more bits from the hash than previously */ |
49 | 0 | ext_len = strlen(mod->name); |
50 | 0 | } else { |
51 | | /* use one more byte from the module name than before */ |
52 | 0 | ext_len = collision_id; |
53 | 0 | } |
54 | 0 | full_hash = dict_hash_multi(full_hash, mod->name, ext_len); |
55 | 0 | } |
56 | 0 | full_hash = dict_hash_multi(full_hash, NULL, 0); |
57 | | |
58 | | /* use the shortened hash */ |
59 | 0 | hash = full_hash & (LYB_HASH_MASK >> collision_id); |
60 | | /* add collision identificator */ |
61 | 0 | hash |= LYB_HASH_COLLISION_ID >> collision_id; |
62 | |
|
63 | 0 | return hash; |
64 | 0 | } |
65 | | |
66 | | LYB_HASH |
67 | | lyb_get_hash(const struct lysc_node *node, uint8_t collision_id) |
68 | 0 | { |
69 | | /* hashes must be cached */ |
70 | 0 | assert(node->hash[0]); |
71 | |
|
72 | 0 | if (collision_id < LYS_NODE_HASH_COUNT) { |
73 | | /* read from cache */ |
74 | 0 | return node->hash[collision_id]; |
75 | 0 | } |
76 | | |
77 | | /* generate */ |
78 | 0 | return lyb_generate_hash(node, collision_id); |
79 | 0 | } |
80 | | |
81 | | /** |
82 | | * @brief Module DFS callback filling all cached hashes of a schema node. |
83 | | */ |
84 | | static LY_ERR |
85 | | lyb_cache_node_hash_cb(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUSED(dfs_continue)) |
86 | 0 | { |
87 | 0 | if (node->hash[0]) { |
88 | | /* already cached, stop the DFS */ |
89 | 0 | return LY_EEXIST; |
90 | 0 | } |
91 | | |
92 | 0 | for (uint8_t i = 0; i < LYS_NODE_HASH_COUNT; ++i) { |
93 | | /* store the hash in the cache */ |
94 | 0 | node->hash[i] = lyb_generate_hash(node, i); |
95 | 0 | } |
96 | |
|
97 | 0 | return LY_SUCCESS; |
98 | 0 | } |
99 | | |
100 | | void |
101 | | lyb_cache_module_hash(const struct lys_module *mod) |
102 | 0 | { |
103 | | /* LOCK */ |
104 | 0 | pthread_mutex_lock(&mod->ctx->lyb_hash_lock); |
105 | | |
106 | | /* store all cached hashes for all the nodes */ |
107 | 0 | lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); |
108 | | |
109 | | /* UNLOCK */ |
110 | 0 | pthread_mutex_unlock(&mod->ctx->lyb_hash_lock); |
111 | 0 | } |
112 | | |
113 | | ly_bool |
114 | | lyb_has_schema_model(const struct lysc_node *node, const struct lys_module **models) |
115 | 0 | { |
116 | 0 | LY_ARRAY_COUNT_TYPE u; |
117 | |
|
118 | 0 | LY_ARRAY_FOR(models, u) { |
119 | 0 | if (node->module == models[u]) { |
120 | 0 | return 1; |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | 0 | return 0; |
125 | 0 | } |