[kamailio/kamailio] KEMI: Add htable count/match API equivalent to $shtcn() (to avoid pv_cache growth with dynamic PV strings) (Issue #4426)
wedhornsipgate created an issue (kamailio/kamailio#4426) **Description:** We're missing a KEMI function in the htable module that provides the same functionality as the PV function `$shtcn(table=>pattern)` to count the number of keys in an htable that match a given pattern (prefix/suffix/regex). The goal is to let KEMI scripts perform pattern counts without constructing dynamic PV expressions, which currently causes unbounded pv_cache growth in PKG memory. **Use case / motivation:** We implemented rolling-window rate limiting by writing short-lived, per-call entries into an htable and then counting keys that match a number-derived pattern. Using $shtcn() works well for the logic, but in KEMI (JS/TypeScript) we must call it via pv.gete("$shtcn(...)"). Because the PV string varies per INVITE (different pattern/key each time), these dynamic PV expressions accumulate in the PV cache, growing PKG/private memory over time. We’d like a native KEMI function to perform the same count/match so we can avoid the PV layer entirely. **Environment** Kamailio: 5.8.6 on Debian 12 Scripting: KEMI (JavaScript/TypeScript) Symptom: steady PKG/private memory increase over ~24h under load when using pv.gete("$shtcn(...)"). Disabling the $shtcn() call stops the growth. Related log line: the one discussed in [#3440](https://github.com/kamailio/kamailio/issues/3440) (“pv cache … pkg memory may get filled with pv declarations”). Current line in our script: ```if (ksr.pv.gete(`$shtcn(${htable_count}=>%~${number})`) > threshold) { ... }``` **Current workaround** Restarting the Kamailio every day or disabling rate limit on instances with KEMI. **Idea for API** Minimal, PV-parity: ``` // KEMI export int shtcn_match(str table, str pattern, int mode /* 0=exact, 1=prefix, 2=suffix, 3=regex */); ``` JS example: `const n = KSR.htable.shtcn_match("from_number_count", number, 3); // regex` More explicit helpers (avoids integer modes): ``` KSR.htable.shtcn_exact(table, key) -> int KSR.htable.shtcn_prefix(table, prefix) -> int KSR.htable.shtcn_suffix(table, suffix) -> int KSR.htable.shtcn_regex(table, pattern) -> int ``` **Behavioral notes / expectations** Should mirror $shtcn() semantics where reasonable (esp. regex behavior), but returning an integer directly to KEMI. Must not allocate PV expressions or interact with pv_cache. **Why this belongs in htable KEMI** $shtcn() is already offered at the PV level; parity in KEMI keeps feature consistency across scripting engines. It enables memory-safe implementations of rolling-window rate limits and similar patterns (without touching PV). **Alternatives considered** Replace pattern counting with per-bucket counters (sht_inc), which leads to other problems like increment/decrement handling and locking. Use ratelimit/pike modules—useful for IP/method limits, but our use case is PAI/From/To based and currently hinges on pattern counts. **Acceptance criteria** A KEMI function exists to count matching keys in an htable without PV parsing. Verified that repeated calls with dynamic patterns do not grow PV cache / PKG memory. Basic tests for exact/prefix/suffix/regex modes (and skip_expired if implemented). Thank you! This would let KEMI users keep $shtcn()-style logic with the same performance characteristics, but without the PV-cache side effects. -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issues/4426@github.com>
xkaraman left a comment (kamailio/kamailio#4426) Hey @wedhornsipgate, I have implement these extra KEMI functions in https://github.com/xkaraman/kamailio/tree/htable_kemi. You can have a look and try it your self and give any feedback. Here is how i am using it with KEMI Python engine ``` python KSR.htable.sht_setxs("ipban", "pattern1", "value",50) KSR.htable.sht_setxs("ipban", "pattern2", "value1",50) KSR.htable.sht_setxs("ipban", "nopatter23", "value52",50) KSR.htable.sht_setxs("ipban", "abcd2", "empty1",50) # KSR.htable.sht_print() exact="pattern1" count_exact = KSR.htable.shtcn_match("ipban", exact, 0) KSR.info("Exact match count for pattern [%s]: %d\n" % (exact, count_exact)) count_exact = KSR.htable.shtcn_exact("ipban", exact) KSR.info("Exact match count (exact) for pattern [%s]: %d\n" % (exact, count_exact)) startwith="pattern" count_startwith = KSR.htable.shtcn_match("ipban", startwith, 1) KSR.info("Startwith match count for pattern [%s]: %d\n" % (startwith, count_startwith)) count_startwith = KSR.htable.shtcn_prefix("ipban", startwith) KSR.info("Startwith match count (prefix) for pattern [%s]: %d\n" % (startwith, count_startwith)) endwith="2" count_endwith = KSR.htable.shtcn_match("ipban", endwith, 2) KSR.info("Endwith match count for pattern [%s]: %d\n" % (endwith, count_endwith)) count_endwith = KSR.htable.shtcn_suffix("ipban", endwith) KSR.info("Endwith match count (suffix) for pattern [%s]: %d\n" % (endwith, count_endwith)) regex="^pat.*2$" count_regex = KSR.htable.shtcn_match("ipban", regex, 3) KSR.info("Regex match count for pattern [%s]: %d\n" % (regex, count_regex)) count_regex = KSR.htable.shtcn_regex("ipban", regex) KSR.info("Regex match count (regex) for pattern [%s]: %d\n" % (regex, count_regex)) ``` and the respective output logs: ``` python Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): ===== request - from kamailio python script Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Exact match count for pattern [pattern1]: 1 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Exact match count (exact) for pattern [pattern1]: 1 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Startwith match count for pattern [pattern]: 2 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Startwith match count (prefix) for pattern [pattern]: 2 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Endwith match count for pattern [2]: 2 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Endwith match count (suffix) for pattern [2]: 2 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Regex match count for pattern [^pat.*2$]: 1 Nov 5 11:00:18 app01 sbin/kamailio[3338583]: INFO: {1 2426 REGISTER u30SqMAHWR} <core> [core/kemi.c:109]: sr_kemi_core_info(): Regex match count (regex) for pattern [^pat.*2$]: 1 ``` -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426#issuecomment-3490573129 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issues/4426/3490573129@github.com>
boettner left a comment (kamailio/kamailio#4426) Hey @xkaraman, thanks a lot the feature. We tested it, and it worked perfectly for our use case. We did not integrate it in production yet so we cannot rule out high memory consumption over time (like using pv.get($shtcn, ...). -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426#issuecomment-3533177583 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issues/4426/3533177583@github.com>
Closed #4426 as completed. -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426#event-21425716298 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issue/4426/issue_event/21425716298@github.com>
miconda left a comment (kamailio/kamailio#4426) The function was added to git devel branch, but with a different name and prototype: `KSR.htable.sht_cn(htable, op, value)`. -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426#issuecomment-3626733324 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issues/4426/3626733324@github.com>
SipSeb left a comment (kamailio/kamailio#4426) @miconda Actually, had this ticket on some kind of watchlist. I searched the KEMI documentation for `sht_cn` but could not find anything, even in devel version. Which version did it make it into? Was the documentation forgotten? -- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/4426#issuecomment-4485570595 You are receiving this because you are subscribed to this thread. Message ID: <kamailio/kamailio/issues/4426/4485570595@github.com>
participants (5)
-
Daniel-Constantin Mierla -
Hendrik Wedhorn -
Jonas -
Sebastian Damm -
Xenofon Karamanos