Skip to content

Commit bac4f14

Browse files
committed
validation OPTIMIZE avoid finding HT record twice
Required changes to lyd_find_with_col_cb function behavior.
1 parent 538243a commit bac4f14

File tree

4 files changed

+35
-17
lines changed

4 files changed

+35
-17
lines changed

src/hash_table.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,14 @@ lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
309309

310310
LIBYANG_API_DEF LY_ERR
311311
lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
312-
lyht_value_equal_cb collision_val_equal, void **match_p)
312+
lyht_value_equal_cb val_equal, void **match_p)
313313
{
314314
struct ly_ht_rec *rec;
315315
uint32_t rec_idx;
316316
uint32_t i;
317317

318318
/* find the record of the previously found value */
319-
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &i, &rec)) {
319+
if (lyht_find_rec(ht, val_p, hash, 1, val_equal ? val_equal : ht->val_equal, &i, &rec)) {
320320
/* not found, cannot happen */
321321
LOGINT_RET(NULL);
322322
}
@@ -329,8 +329,8 @@ lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t h
329329
continue;
330330
}
331331

332-
if (collision_val_equal) {
333-
if (collision_val_equal(val_p, &rec->val, 0, ht->cb_data)) {
332+
if (val_equal) {
333+
if (val_equal(val_p, &rec->val, 0, ht->cb_data)) {
334334
/* even the value matches */
335335
if (match_p) {
336336
*match_p = rec->val;

src/hash_table.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,14 @@ LIBYANG_API_DECL LY_ERR lyht_find_next(const struct ly_ht *ht, void *val_p, uint
163163
* @param[in] ht Hash table to search in.
164164
* @param[in] val_p Pointer to the previously found value in @p ht.
165165
* @param[in] hash Hash of the previously found value.
166-
* @param[in] collision_val_equal Val equal callback to use for checking collisions.
166+
* @param[in] val_equal Callback for checking value equivalence. Called with @p mod 1 when searching for the first value
167+
* and then uses @p mod 0 to check all the following collisions.
167168
* @param[out] match_p Pointer to the matching value, optional.
168169
* @return LY_SUCCESS if value was found,
169170
* @return LY_ENOTFOUND if not found.
170171
*/
171172
LIBYANG_API_DECL LY_ERR lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
172-
lyht_value_equal_cb collision_val_equal, void **match_p);
173+
lyht_value_equal_cb val_equal, void **match_p);
173174

174175
/**
175176
* @brief Insert a value into a hash table.

src/printer_lyb.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ lyb_ptr_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(c
7070
return 0;
7171
}
7272

73+
/**
74+
* @brief Hash table equal callback for checking collisions.
75+
*
76+
* Implementation of ::lyht_value_equal_cb.
77+
*/
78+
static ly_bool
79+
lyb_col_equal_cb(void *val1_p, void *val2_p, ly_bool mod, void *cb_data)
80+
{
81+
/* for first value check use lyb_ptr_equal_cb, for collisions lyb_hash_equal_cb */
82+
return mod ? lyb_ptr_equal_cb(val1_p, val2_p, mod, cb_data) : lyb_hash_equal_cb(val1_p, val2_p, mod, cb_data);
83+
}
84+
7385
/**
7486
* @brief Check that sibling collision hash is safe to insert into hash table.
7587
*
@@ -91,7 +103,6 @@ lyb_hash_sequence_check(struct ly_ht *ht, struct lysc_node *sibling, LYB_HASH ht
91103
return LY_SUCCESS;
92104
}
93105

94-
lyht_set_cb(ht, lyb_ptr_equal_cb);
95106
do {
96107
int64_t j;
97108

@@ -103,15 +114,13 @@ lyb_hash_sequence_check(struct ly_ht *ht, struct lysc_node *sibling, LYB_HASH ht
103114
}
104115
if (j == -1) {
105116
/* all whole hash sequences of nodes inserted with last hash col ID compare_col_id collide */
106-
lyht_set_cb(ht, lyb_hash_equal_cb);
107117
return LY_EEXIST;
108118
}
109119

110120
/* get next node inserted with last hash col ID ht_col_id */
111-
} while (!lyht_find_next_with_collision_cb(ht, col_node, lyb_get_hash(*col_node, ht_col_id), lyb_hash_equal_cb,
121+
} while (!lyht_find_next_with_collision_cb(ht, col_node, lyb_get_hash(*col_node, ht_col_id), lyb_col_equal_cb,
112122
(void **)&col_node));
113123

114-
lyht_set_cb(ht, lyb_hash_equal_cb);
115124
return LY_SUCCESS;
116125
}
117126

src/validation.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,18 @@ lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum ly
533533
return rc;
534534
}
535535

536+
/**
537+
* @brief Compare callback for finding duplicates in hash table.
538+
*
539+
* Implementation of ::lyht_value_equal_cb.
540+
*/
541+
static ly_bool
542+
lyd_val_dup_val_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data)
543+
{
544+
/* always find the same instance, not the exact same pointer (set mod = 0) */
545+
return lyd_hash_table_val_equal(val1_p, val2_p, 0, cb_data);
546+
}
547+
536548
/**
537549
* @brief Validate instance duplication.
538550
*
@@ -544,7 +556,6 @@ lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum ly
544556
static LY_ERR
545557
lyd_validate_duplicates(const struct lyd_node *first, const struct lyd_node *node, uint32_t val_opts)
546558
{
547-
struct lyd_node **match_p, *match;
548559
ly_bool fail = 0;
549560

550561
assert(node->flags & LYD_NEW);
@@ -557,12 +568,9 @@ lyd_validate_duplicates(const struct lyd_node *first, const struct lyd_node *nod
557568

558569
/* find exactly the same next instance using hashes if possible */
559570
if (node->parent && node->parent->children_ht) {
560-
lyd_find_sibling_first(first, node, &match);
561-
assert(match);
562-
563-
if (match != node) {
564-
fail = 1;
565-
} else if (!lyht_find_next(node->parent->children_ht, &node, node->hash, (void **)&match_p)) {
571+
/* because of the callback used, an instance must always be found (pointer may or may not be equal to node),
572+
* so if we find another instance, there is a duplicate */
573+
if (!lyht_find_next_with_collision_cb(node->parent->children_ht, &node, node->hash, lyd_val_dup_val_equal, NULL)) {
566574
fail = 1;
567575
}
568576
} else {

0 commit comments

Comments
 (0)