Skip to content

Commit

Permalink
hash table BUGFIX even shrink the dictionary with a special callback
Browse files Browse the repository at this point in the history
Refs #1093
  • Loading branch information
michalvasko committed May 28, 2020
1 parent 0dce093 commit bc14b0f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 31 deletions.
77 changes: 46 additions & 31 deletions src/hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,35 @@ dict_hash_multi(uint32_t hash, const char *key_part, size_t len)
return hash;
}

static int
lydict_resize_val_eq(void *val1_p, void *val2_p, int mod, void *cb_data)
{
if (!val1_p || !val2_p) {
LOGARG;
return 0;
}

const char *str1 = ((struct dict_rec *)val1_p)->value;
const char *str2 = ((struct dict_rec *)val2_p)->value;

if (!str1 || !str2) {
LOGARG;
return 0;
}

if (mod) {
/* used when inserting new values */
if (strcmp(str1, str2) == 0) {
return 1;
}
} else {
/* used when finding the original value again in the resized table */
return lydict_val_eq(val1_p, val2_p, mod, cb_data);
}

return 0;
}

API void
lydict_remove(struct ly_ctx *ctx, const char *value)
{
Expand Down Expand Up @@ -181,7 +210,7 @@ lydict_remove(struct ly_ctx *ctx, const char *value)
* free it after it is removed from hash table
*/
val_p = match->value;
ret = lyht_remove(ctx->dict.hash_tab, &rec, hash);
ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq);
free(val_p);
LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish);
}
Expand All @@ -191,35 +220,6 @@ lydict_remove(struct ly_ctx *ctx, const char *value)
pthread_mutex_unlock(&ctx->dict.lock);
}

static int
lydict_resize_val_eq(void *val1_p, void *val2_p, int mod, void *cb_data)
{
if (!val1_p || !val2_p) {
LOGARG;
return 0;
}

const char *str1 = ((struct dict_rec *)val1_p)->value;
const char *str2 = ((struct dict_rec *)val2_p)->value;

if (!str1 || !str2) {
LOGARG;
return 0;
}

if (mod) {
/* used when inserting new values */
if (strcmp(str1, str2) == 0) {
return 1;
}
} else {
/* used when finding the original value again in the resized table */
return lydict_val_eq(val1_p, val2_p, mod, cb_data);
}

return 0;
}

static char *
dict_insert(struct ly_ctx *ctx, char *value, size_t len, int zerocopy)
{
Expand Down Expand Up @@ -815,11 +815,12 @@ lyht_insert(struct hash_table *ht, void *val_p, uint32_t hash, void **match_p)
}

int
lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash)
lyht_remove_with_resize_cb(struct hash_table *ht, void *val_p, uint32_t hash, values_equal_cb resize_val_equal)
{
struct ht_rec *rec, *crec;
int32_t i;
int first_matched = 0, r, ret;
values_equal_cb old_val_equal;

lyht_dbgprint_ht(ht, "before");
lyht_dbgprint_value(val_p, hash, ht->rec_size, "removing");
Expand Down Expand Up @@ -874,11 +875,25 @@ lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash)
if (ht->resize == 2) {
r = (ht->used * 100) / ht->size;
if ((r < LYHT_SHRINK_PERCENTAGE) && (ht->size > LYHT_MIN_SIZE)) {
if (resize_val_equal) {
old_val_equal = lyht_set_cb(ht, resize_val_equal);
}

/* shrink */
ret = lyht_resize(ht, 0);

if (resize_val_equal) {
lyht_set_cb(ht, old_val_equal);
}
}
}

lyht_dbgprint_ht(ht, "after");
return ret;
}

int
lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash)
{
return lyht_remove_with_resize_cb(ht, val_p, hash, NULL);
}
14 changes: 14 additions & 0 deletions src/hash_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,18 @@ int lyht_insert_with_resize_cb(struct hash_table *ht, void *val_p, uint32_t hash
*/
int lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash);

/**
* @brief Remove a value from a hash table. Same functionality as lyht_remove()
* but allows to specify a temporary val equal callback to be used in case the hash table
* will be resized after successful removal.
*
* @param[in] ht Hash table to remove from.
* @param[in] value_p Pointer to value to be removed. Be careful, if the values stored in the hash table
* are pointers, \p value_p must be a pointer to a pointer.
* @param[in] hash Hash of the stored value.
* @param[in] resize_val_equal Val equal callback to use for resizing.
* @return 0 on success, 1 if value was not found, -1 on error.
*/
int lyht_remove_with_resize_cb(struct hash_table *ht, void *val_p, uint32_t hash, values_equal_cb resize_val_equal);

#endif /* LY_HASH_TABLE_H_ */

0 comments on commit bc14b0f

Please sign in to comment.