Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize duplicating values #2286

Merged
merged 2 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 48 additions & 7 deletions src/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_da
str1 = ((struct ly_dict_rec *)val1_p)->value;
str2 = ((struct ly_dict_rec *)val2_p)->value;

LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);

if (mod) {
/* used when inserting new values */
if (strcmp(str1, str2) == 0) {
Expand Down Expand Up @@ -177,7 +174,7 @@ lydict_remove(const struct ly_ctx *ctx, const char *value)
return ret;
}

LY_ERR
static LY_ERR
dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
{
LY_ERR ret = LY_SUCCESS;
Expand Down Expand Up @@ -221,9 +218,7 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy,
return ret;
}

if (str_p) {
*str_p = match->value;
}
*str_p = match->value;

return ret;
}
Expand Down Expand Up @@ -269,3 +264,49 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)

return result;
}

static LY_ERR
dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p)
michalvasko marked this conversation as resolved.
Show resolved Hide resolved
{
LY_ERR ret = LY_SUCCESS;
struct ly_dict_rec *match = NULL, rec;
uint32_t hash;

/* set new callback to only compare memory addresses */
michalvasko marked this conversation as resolved.
Show resolved Hide resolved
lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq);

LOGDBG(LY_LDGDICT, "duplicating %s", value);
hash = lyht_hash(value, strlen(value));
rec.value = value;

ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
if (ret == LY_SUCCESS) {
/* record found, increase refcount */
match->refcount++;
*str_p = match->value;
}

/* restore callback */
lyht_set_cb(ctx->dict.hash_tab, prev);

return ret;
}

LIBYANG_API_DEF LY_ERR
lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
{
LY_ERR result;

LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);

if (!value) {
*str_p = NULL;
return LY_SUCCESS;
}

pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
result = dict_dup(ctx, (char *)value, str_p);
pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);

return result;
}
12 changes: 12 additions & 0 deletions src/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value,
*/
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);

/**
* @brief Duplicate string in dictionary. Only a reference counter is incremented.
*
* @param[in] ctx libyang context handler
* @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented).
* @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
* @return LY_SUCCESS in case the string already exists in the dictionary.
* @return LY_ENOTFOUND in case the string was not found.
* @return LY_ERR on other errors
*/
LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p);

/** @} dict */

#ifdef __cplusplus
Expand Down
21 changes: 7 additions & 14 deletions src/hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,33 +247,26 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
* @param[in] hash Hash to find.
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find).
* @param[in] val_equal Callback for checking value equivalence.
* @param[out] crec_p Optional found first record.
* @param[out] col Optional collision number of @p rec_p, 0 for no collision.
* @param[out] rec_p Found exact matching record, may be a collision of @p crec_p.
* @return LY_ENOTFOUND if no record found,
* @return LY_SUCCESS if record was found.
*/
static LY_ERR
lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, lyht_value_equal_cb val_equal,
struct ly_ht_rec **crec_p, uint32_t *col, struct ly_ht_rec **rec_p)
uint32_t *col, struct ly_ht_rec **rec_p)
{
uint32_t hlist_idx = hash & (ht->size - 1);
struct ly_ht_rec *rec;
uint32_t rec_idx;

if (crec_p) {
*crec_p = NULL;
}
if (col) {
*col = 0;
}
*rec_p = NULL;

LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
if ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) {
if (crec_p) {
*crec_p = rec;
}
*rec_p = rec;
return LY_SUCCESS;
}
Expand All @@ -292,7 +285,7 @@ lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
struct ly_ht_rec *rec;

lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, NULL, &rec);
lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, &rec);

if (rec && match_p) {
*match_p = rec->val;
Expand All @@ -305,7 +298,7 @@ lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
{
struct ly_ht_rec *rec;

lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, NULL, &rec);
lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, &rec);

if (rec && match_p) {
*match_p = rec->val;
Expand All @@ -317,12 +310,12 @@ LIBYANG_API_DEF LY_ERR
lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
lyht_value_equal_cb collision_val_equal, void **match_p)
{
struct ly_ht_rec *rec, *crec;
struct ly_ht_rec *rec;
uint32_t rec_idx;
uint32_t i;

/* find the record of the previously found value */
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &crec, &i, &rec)) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &i, &rec)) {
/* not found, cannot happen */
LOGINT_RET(NULL);
}
Expand Down Expand Up @@ -373,7 +366,7 @@ _lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
uint32_t rec_idx;

if (check) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &rec) == LY_SUCCESS) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &rec) == LY_SUCCESS) {
if (rec && match_p) {
*match_p = rec->val;
}
Expand Down Expand Up @@ -459,7 +452,7 @@ lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_va
uint32_t prev_rec_idx;
uint32_t rec_idx;

if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &found_rec)) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &found_rec)) {
LOGARG(NULL, hash);
return LY_ENOTFOUND;
}
Expand Down
26 changes: 12 additions & 14 deletions src/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_

/* store the value */
LOG_LOCSET(key, NULL);
ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
Expand Down Expand Up @@ -736,7 +736,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
/* names (keys) are unique - it was checked when parsing */
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
ly_path_predicates_free(ctx, *predicates);
ly_path_predicates_free(ctx_node->module->ctx, *predicates);
*predicates = NULL;
ret = LY_EVALID;
goto cleanup;
Expand Down Expand Up @@ -771,12 +771,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
}

/* store the value */
if (ctx_node) {
LOG_LOCSET(ctx_node, NULL);
}
ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
LOG_LOCSET(ctx_node, NULL);
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
LOG_LOCBACK(ctx_node ? 1 : 0, 0);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
++(*tok_idx);

Expand Down Expand Up @@ -1093,15 +1091,15 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
}
lref = (const struct lysc_type_leafref *)deref_leaf_node->type;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2);
ly_path_free(path2);
path2 = NULL;

/* compile dereferenced leafref expression and append it to the path */
LY_CHECK_GOTO(ret = ly_path_compile_leafref(ctx, node2, top_ext, lref->path, oper, target, format, prefix_data,
&path2), cleanup);
node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2);
ly_path_free(path2);
path2 = NULL;

/* properly parsed path must always continue with ')' and '/' */
Expand All @@ -1125,9 +1123,9 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);

cleanup:
ly_path_free(ctx, path2);
ly_path_free(path2);
if (ret) {
ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}
return ret;
Expand Down Expand Up @@ -1283,7 +1281,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con

cleanup:
if (ret) {
ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}
LOG_LOCBACK(cur_node ? 1 : 0, 0);
Expand Down Expand Up @@ -1488,7 +1486,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred
}

void
ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
ly_path_free(struct ly_path *path)
{
LY_ARRAY_COUNT_TYPE u;

Expand All @@ -1497,7 +1495,7 @@ ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
}

LY_ARRAY_FOR(path, u) {
ly_path_predicates_free(ctx, path[u].predicates);
ly_path_predicates_free(path[u].node->module->ctx, path[u].predicates);
}
LY_ARRAY_FREE(path);
}
3 changes: 1 addition & 2 deletions src/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,8 @@ void ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate
/**
* @brief Free ly_path structure.
*
* @param[in] ctx libyang context.
* @param[in] path The structure ([sized array](@ref sizedarrays)) to free.
*/
void ly_path_free(const struct ly_ctx *ctx, struct ly_path *path);
void ly_path_free(struct ly_path *path);

#endif /* LY_PATH_H_ */
18 changes: 12 additions & 6 deletions src/plugins_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,16 @@ lyplg_type_print_simple(const struct ly_ctx *UNUSED(ctx), const struct lyd_value
LIBYANG_API_DEF LY_ERR
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
memset(dup, 0, sizeof *dup);
LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical));
LY_ERR r;

if ((r = lydict_dup(ctx, original->_canonical, &dup->_canonical))) {
/* in case of error NULL the values so that freeing does not fail */
memset(dup, 0, sizeof *dup);
return r;
}
memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
dup->realtype = original->realtype;

return LY_SUCCESS;
}

Expand Down Expand Up @@ -888,17 +894,17 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_
ly_err_clean((struct ly_ctx *)ctx, e);
}

ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}

return ret;
}

LIBYANG_API_DEF void
lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path)
michalvasko marked this conversation as resolved.
Show resolved Hide resolved
lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path)
{
ly_path_free(ctx, path);
ly_path_free(path);
}

LIBYANG_API_DEF LY_ERR
Expand Down Expand Up @@ -1007,7 +1013,7 @@ lyplg_type_resolve_leafref_get_target_path(const struct lyxp_expr *path, const s
LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup);

cleanup:
ly_path_free(ctx_node->module->ctx, p);
ly_path_free(p);
free(str_path);
return rc;
}
Expand Down
2 changes: 1 addition & 1 deletion src/plugins_types/instanceid.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
{
lydict_remove(ctx, value->_canonical);
value->_canonical = NULL;
ly_path_free(ctx, value->target);
ly_path_free(value->target);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/schema_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st

/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(node->module->ctx, p);
ly_path_free(p);

if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
Expand Down Expand Up @@ -1456,7 +1456,7 @@ lys_compile_unres_depset(struct ly_ctx *ctx, struct lys_glob_unres *unres)
ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path,
(l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
ly_path_free(l->node->module->ctx, path);
ly_path_free(path);

assert(ret != LY_ERECOMPILE);
if (ret) {
Expand Down
2 changes: 1 addition & 1 deletion src/tree_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -3624,7 +3624,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,

cleanup:
lyxp_expr_free(LYD_CTX(ctx_node), expr);
ly_path_free(LYD_CTX(ctx_node), lypath);
ly_path_free(lypath);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion src/tree_data_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
LY_ARRAY_INCREMENT(p);
}
}
ly_path_free(ctx, p);
ly_path_free(p);
if (!ret) {
/* set out params only on success */
if (new_parent) {
Expand Down
4 changes: 2 additions & 2 deletions src/tree_schema.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
ret = lys_find_lypath_atoms(p, set);

cleanup:
ly_path_free(ctx, p);
ly_path_free(p);
lyxp_expr_free(ctx, expr);
return ret;
}
Expand Down Expand Up @@ -679,7 +679,7 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
snode = p[LY_ARRAY_COUNT(p) - 1].node;

cleanup:
ly_path_free(ctx, p);
ly_path_free(p);
lyxp_expr_free(ctx, expr);
return snode;
}
Expand Down
Loading
Loading