Skip to content

Commit e736762

Browse files
Roytakmichalvasko
authored andcommitted
ly_common UPDATE pattern caching and freeing
1 parent f465f2e commit e736762

File tree

6 files changed

+64
-39
lines changed

6 files changed

+64
-39
lines changed

src/ly_common.c

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,6 @@ ly_ctx_ht_pattern_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void
141141
return !strcmp(val1->pattern, val2->pattern);
142142
}
143143

144-
/**
145-
* @brief Callback for freeing a pattern record.
146-
*/
147-
static void
148-
ly_ctx_ht_pattern_free_cb(void *val_p)
149-
{
150-
struct ly_pattern_ht_rec *val = val_p;
151-
152-
if (val->pcode) {
153-
/* free the pcode */
154-
pcre2_code_free(val->pcode);
155-
}
156-
}
157-
158144
/**
159145
* @brief Remove private context data from the sized array and free its contents.
160146
*
@@ -304,8 +290,11 @@ ly_ctx_shared_data_remove_and_free(struct ly_ctx_shared_data *shared_data)
304290
return;
305291
}
306292

307-
/* free all the cached pattern pcodes */
308-
lyht_free(shared_data->pattern_ht, ly_ctx_ht_pattern_free_cb);
293+
/* all the patterns must have been removed already,
294+
* either while free compiled modules (standard behavior)
295+
* or when assigning a parent to a context, it's shared data will be used (schema mount) */
296+
assert(shared_data->pattern_ht->used == 0);
297+
lyht_free(shared_data->pattern_ht, NULL);
309298

310299
/* free rest of the members */
311300
lydict_clean(shared_data->data_dict);
@@ -544,6 +533,16 @@ ly_ctx_data_del(const struct ly_ctx *ctx)
544533
pthread_rwlock_unlock(&ly_ctx_data_rwlock);
545534
}
546535

536+
void
537+
ly_ctx_ht_pattern_rec_free(struct ly_pattern_ht_rec *rec)
538+
{
539+
if (!rec) {
540+
return;
541+
}
542+
543+
pcre2_code_free(rec->pcode);
544+
}
545+
547546
LY_ERR
548547
ly_ctx_shared_data_pattern_get(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode)
549548
{
@@ -559,39 +558,36 @@ ly_ctx_shared_data_pattern_get(const struct ly_ctx *ctx, const char *pattern, co
559558
*pcode = NULL;
560559
}
561560

561+
/* get the context shared data */
562562
ctx_data = ly_ctx_shared_data_get(ctx);
563563
LY_CHECK_RET(!ctx_data, LY_EINT);
564564

565565
/* try to find the pattern code in the pattern ht */
566566
hash = lyht_hash(pattern, strlen(pattern));
567567
rec.pattern = pattern;
568568
if (!lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) {
569-
/* found it, return it */
569+
/* pcode cached */
570570
if (pcode) {
571571
*pcode = found_rec->pcode;
572572
}
573573
goto cleanup;
574574
}
575575

576-
/* didnt find it, need to compile it */
576+
/* didnt find it, either it's the first time or using printed context (which compiles the pcodes on the fly) */
577+
assert(!pcode || ly_ctx_is_printed(ctx));
577578
LY_CHECK_GOTO(rc = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup);
578579

579580
/* store the compiled pattern code in the hash table */
580-
hash = lyht_hash(pattern, strlen(pattern));
581-
rec.pattern = pattern;
582581
rec.pcode = pcode_tmp;
583582
LY_CHECK_GOTO(rc = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, NULL), cleanup);
584583

585584
if (pcode) {
586585
*pcode = pcode_tmp;
587-
pcode_tmp = NULL;
588586
}
587+
pcode_tmp = NULL;
589588

590589
cleanup:
591-
if (rc) {
592-
/* only free the pcode if we failed, because it belongs to the hash table */
593-
pcre2_code_free(pcode_tmp);
594-
}
590+
pcre2_code_free(pcode_tmp);
595591
return rc;
596592
}
597593

@@ -613,7 +609,8 @@ ly_ctx_shared_data_pattern_del(const struct ly_ctx *ctx, const char *pattern)
613609
rec.pattern = pattern;
614610

615611
if (lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) {
616-
/* pattern code not cached yet */
612+
/* pattern code not cached, this may happen when using printed context,
613+
* because then the pcodes are obtained on demand */
617614
return;
618615
}
619616

src/ly_common.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,15 @@ int LY_VCODE_INSTREXP_len(const char *str);
326326
* Context
327327
*****************************************************************************/
328328

329+
/**
330+
* @brief Internal pattern hash table record.
331+
*/
332+
struct ly_pattern_ht_rec {
333+
const char *pattern; /**< Pattern expression, used both as key to hash and value to search for.
334+
* Not stored in a dictionary, but a direct reference to ::lysc_pattern.expr. */
335+
pcre2_code *pcode; /**< Compiled PCRE2 pattern code. */
336+
};
337+
329338
/**
330339
* @brief Private run-time context data.
331340
*
@@ -493,6 +502,13 @@ LY_ERR ly_ctx_shared_data_pattern_get(const struct ly_ctx *ctx, const char *patt
493502
*/
494503
void ly_ctx_shared_data_pattern_del(const struct ly_ctx *ctx, const char *pattern);
495504

505+
/**
506+
* @brief Free members of a pattern record stored in the context hash table.
507+
*
508+
* @param[in] rec Pattern records whose members to free.
509+
*/
510+
void ly_ctx_ht_pattern_rec_free(struct ly_pattern_ht_rec *rec);
511+
496512
/******************************************************************************
497513
* Dictionary
498514
*****************************************************************************/

src/plugins_exts.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,10 @@ LIBYANG_API_DEF LY_ERR
763763
lyplg_ext_set_parent_ctx(struct ly_ctx *ctx, const struct ly_ctx *parent_ctx)
764764
{
765765
const struct ly_ctx *c;
766+
struct ly_ctx_shared_data *ctx_data;
767+
struct ly_ht_rec *rec;
768+
uint32_t hlist_idx;
769+
uint32_t rec_idx;
766770

767771
LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL);
768772

@@ -787,7 +791,16 @@ lyplg_ext_set_parent_ctx(struct ly_ctx *ctx, const struct ly_ctx *parent_ctx)
787791
* contexts, there is no ext callback for freeing the compiled extension data with the contexts) */
788792
ly_ctx_destroy(ctx);
789793
} else {
790-
/* remove its shared and private data */
794+
/* remove its shared and private data, this is an exception as we need to free compiled patterns
795+
* manually, since we are not destroying the whole context, we will just be using the parent's ctx data instead */
796+
ctx_data = ly_ctx_shared_data_get(ctx);
797+
LYHT_ITER_ALL_RECS(ctx_data->pattern_ht, hlist_idx, rec_idx, rec) {
798+
ly_ctx_ht_pattern_rec_free((struct ly_pattern_ht_rec *)&rec->val);
799+
}
800+
801+
/* we have removed all patterns (so it is empty), we can not free the ht here though, to avoid
802+
* double free, but just trick it to look empty */
803+
ctx_data->pattern_ht->used = 0;
791804
ly_ctx_data_del(ctx);
792805
}
793806
} else if (!parent_ctx) {

src/schema_compile_node.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
13851385
LY_ARRAY_FOR(patterns_p, u) {
13861386
LY_ARRAY_NEW_RET(ctx->ctx, (*patterns), pattern, LY_EMEM);
13871387
*pattern = calloc(1, sizeof **pattern);
1388-
++(*pattern)->refcount;
1389-
1390-
/* compile and insert the pattern into the context hash table, if it wasnt already compiled */
1391-
LY_CHECK_GOTO(ret = ly_ctx_shared_data_pattern_get(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done);
1388+
(*pattern)->refcount = 1;
13921389

13931390
if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
13941391
(*pattern)->inverted = 1;
@@ -1399,6 +1396,12 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
13991396
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done);
14001397
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].ref, (*pattern)->ref, ret, done);
14011398
COMPILE_EXTS_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts, (*pattern), ret, done);
1399+
1400+
/* compile the pattern, if it wasnt already compiled (e.g. same expression but different module)
1401+
* we do this now to verify the pattern right away while compiling the type
1402+
* and so we can store it in the cache so we dont have to recompile it again later
1403+
*/
1404+
LY_CHECK_GOTO(ret = ly_ctx_shared_data_pattern_get(ctx->ctx, (*pattern)->expr, NULL), done);
14021405
}
14031406

14041407
done:

src/tree_schema_free.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,10 @@ lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern)
825825
if (--(*pattern)->refcount) {
826826
return;
827827
}
828+
829+
/* free the shared pattern first, before removing from the dictionary */
830+
ly_ctx_shared_data_pattern_del(ctx, (*pattern)->expr);
831+
828832
lysdict_remove(ctx, (*pattern)->expr);
829833
lysdict_remove(ctx, (*pattern)->eapptag);
830834
lysdict_remove(ctx, (*pattern)->emsg);

src/tree_schema_internal.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,6 @@ struct lysp_yin_ctx {
181181
struct lyxml_ctx *xmlctx; /**< context for xml parser */
182182
};
183183

184-
/**
185-
* @brief Internal pattern hash table record.
186-
*/
187-
struct ly_pattern_ht_rec {
188-
const char *pattern; /**< Pattern string, used both as key to hash and value to search for. */
189-
pcre2_code *pcode; /**< Compiled PCRE2 pattern code. */
190-
};
191-
192184
/**
193185
* @brief Check that @p c is valid UTF8 code point for YANG string.
194186
*

0 commit comments

Comments
 (0)