Skip to content

Commit 350d4c6

Browse files
alexey-tikhonovsssd-bot
authored andcommitted
UTIL: sss_create_internal_fqname() optimization (caching)
This helper is heavily used, including in hot paths. Since number of domains used is very limited, hash table used for caching should be very small and lookup much more efficient as compared with `sss_tc_utf8_str_tolower()` Assisted-by: Claude Code (Opus 4.6) Reviewed-by: Justin Stephenson <jstephen@redhat.com> Reviewed-by: Sumit Bose <sbose@redhat.com> (cherry picked from commit a5b77e4)
1 parent 24cbcbb commit 350d4c6

File tree

1 file changed

+58
-8
lines changed

1 file changed

+58
-8
lines changed

src/util/usertools.c

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -638,29 +638,79 @@ errno_t sss_parse_internal_fqname(TALLOC_CTX *mem_ctx,
638638
return EOK;
639639
}
640640

641+
/* This is a wrapper around `sss_tc_utf8_str_tolower()` that
642+
* maintains run time cache.
643+
*/
644+
static const char *sss_get_lc_dom_name(const char *dom_name)
645+
{
646+
static TALLOC_CTX *cache_ctx;
647+
static hash_table_t *lc_dom_name_cache;
648+
hash_key_t key;
649+
hash_value_t value;
650+
char *lc_dom_name;
651+
int hret;
652+
653+
key.type = HASH_KEY_CONST_STRING;
654+
key.c_str = dom_name;
655+
656+
if (lc_dom_name_cache != NULL) {
657+
hret = hash_lookup(lc_dom_name_cache, &key, &value);
658+
if (hret == HASH_SUCCESS) {
659+
return (const char *)value.ptr;
660+
}
661+
} else {
662+
cache_ctx = talloc_new(NULL);
663+
if (cache_ctx == NULL) {
664+
return NULL;
665+
}
666+
hret = hash_create(0, &lc_dom_name_cache, NULL, NULL);
667+
if (hret != HASH_SUCCESS) {
668+
DEBUG(SSSDBG_CRIT_FAILURE,
669+
"hash_create() failed [%s]\n", hash_error_string(hret));
670+
lc_dom_name_cache = NULL;
671+
talloc_zfree(cache_ctx);
672+
return NULL;
673+
}
674+
}
675+
676+
lc_dom_name = sss_tc_utf8_str_tolower(cache_ctx, dom_name);
677+
if (lc_dom_name == NULL) {
678+
return NULL;
679+
}
680+
681+
value.type = HASH_VALUE_PTR;
682+
value.ptr = lc_dom_name;
683+
684+
hret = hash_enter(lc_dom_name_cache, &key, &value);
685+
if (hret != HASH_SUCCESS) {
686+
DEBUG(SSSDBG_CRIT_FAILURE,
687+
"hash_enter() failed [%s]\n", hash_error_string(hret));
688+
talloc_free(lc_dom_name);
689+
return NULL;
690+
}
691+
692+
return lc_dom_name;
693+
}
694+
641695
/* Creates internal fqname in format shortname@domname.
642696
* The domain portion is lowercased. */
643697
char *sss_create_internal_fqname(TALLOC_CTX *mem_ctx,
644698
const char *shortname,
645699
const char *dom_name)
646700
{
647-
char *lc_dom_name;
648-
char *fqname = NULL;
701+
const char *lc_dom_name;
649702

650703
if (shortname == NULL || dom_name == NULL) {
651704
/* Avoid allocating null@null */
652705
return NULL;
653706
}
654707

655-
lc_dom_name = sss_tc_utf8_str_tolower(mem_ctx, dom_name);
708+
lc_dom_name = sss_get_lc_dom_name(dom_name);
656709
if (lc_dom_name == NULL) {
657-
goto done;
710+
return NULL;
658711
}
659712

660-
fqname = talloc_asprintf(mem_ctx, "%s@%s", shortname, lc_dom_name);
661-
talloc_free(lc_dom_name);
662-
done:
663-
return fqname;
713+
return talloc_asprintf(mem_ctx, "%s@%s", shortname, lc_dom_name);
664714
}
665715

666716
/* Creates a list of internal fqnames in format shortname@domname.

0 commit comments

Comments
 (0)