Skip to content

Commit ea103da

Browse files
authored
New INFO section for scripting engines (valkey-io#2738)
This commit adds a new `INFO` section called "Scripting Engines" that shows the information of the current scripting engines available in the server. Here's an output example: ``` > info scriptingengines # Scripting Engines engines_count:2 engines_total_used_memory:68608 engines_total_memory_overhead:56 engine_0:name=LUA,module=built-in,abi_version=4,used_memory=68608,memory_overhead=16 engine_1:name=HELLO,module=helloengine,abi_version=4,used_memory=0,memory_overhead=40 ``` --------- Signed-off-by: Ricardo Dias <ricardo.dias@percona.com>
1 parent e381182 commit ea103da

4 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/scripting_engine.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ ValkeyModule *scriptingEngineGetModule(scriptingEngine *engine) {
227227
return engine->module;
228228
}
229229

230+
uint64_t scriptingEngineGetAbiVersion(scriptingEngine *engine) {
231+
return engine->impl.methods.version;
232+
}
233+
230234
/*
231235
* Iterates the list of engines registered in the engine manager and calls the
232236
* callback function with each engine.

src/scripting_engine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void scriptingEngineManagerForEachEngine(engineIterCallback callback, void *cont
5353
sds scriptingEngineGetName(scriptingEngine *engine);
5454
client *scriptingEngineGetClient(scriptingEngine *engine);
5555
ValkeyModule *scriptingEngineGetModule(scriptingEngine *engine);
56+
uint64_t scriptingEngineGetAbiVersion(scriptingEngine *engine);
5657

5758
/*
5859
* API to call engine callback functions.

src/server.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5736,6 +5736,62 @@ void releaseInfoSectionDict(dict *sec) {
57365736
if (sec != cached_default_info_sections) dictRelease(sec);
57375737
}
57385738

5739+
typedef struct scriptingEngineInfoCollector {
5740+
sds info;
5741+
int total_engines;
5742+
size_t total_used_memory;
5743+
size_t total_overhead;
5744+
} scriptingEngineInfoCollector;
5745+
5746+
static void collectScriptingEngineInfo(scriptingEngine *engine, void *context) {
5747+
scriptingEngineInfoCollector *collector = (scriptingEngineInfoCollector *)context;
5748+
5749+
sds engine_name = scriptingEngineGetName(engine);
5750+
ValkeyModule *module = scriptingEngineGetModule(engine);
5751+
uint64_t abi_version = scriptingEngineGetAbiVersion(engine);
5752+
5753+
/* Get memory information for the engine */
5754+
engineMemoryInfo mem_info = scriptingEngineCallGetMemoryInfo(engine, VMSE_ALL);
5755+
5756+
collector->info = sdscatprintf(collector->info,
5757+
"engine_%d:name=%s,module=%s,abi_version=%lu,used_memory=%zu,memory_overhead=%zu\r\n",
5758+
collector->total_engines,
5759+
engine_name,
5760+
module ? module->name : "built-in",
5761+
(unsigned long)abi_version,
5762+
mem_info.used_memory,
5763+
mem_info.engine_memory_overhead);
5764+
5765+
collector->total_engines++;
5766+
collector->total_used_memory += mem_info.used_memory;
5767+
collector->total_overhead += mem_info.engine_memory_overhead;
5768+
}
5769+
5770+
sds genValkeyInfoStringScriptingEngines(sds info) {
5771+
scriptingEngineInfoCollector collector = {
5772+
.info = sdsempty(),
5773+
.total_engines = 0,
5774+
.total_used_memory = 0,
5775+
.total_overhead = 0};
5776+
5777+
/* Collect information from all registered engines */
5778+
scriptingEngineManagerForEachEngine(collectScriptingEngineInfo, &collector);
5779+
5780+
info = sdscatprintf(info,
5781+
"# Scripting Engines\r\n"
5782+
"engines_count:%d\r\n"
5783+
"engines_total_used_memory:%zu\r\n"
5784+
"engines_total_memory_overhead:%zu\r\n"
5785+
"%s",
5786+
collector.total_engines,
5787+
collector.total_used_memory,
5788+
collector.total_overhead,
5789+
collector.info);
5790+
5791+
sdsfree(collector.info);
5792+
return info;
5793+
}
5794+
57395795
/* Create a dictionary with unique section names to be used by genValkeyInfoString.
57405796
* 'argv' and 'argc' are list of arguments for INFO.
57415797
* 'defaults' is an optional null terminated list of default sections.
@@ -6409,6 +6465,12 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) {
64096465
server.cluster_enabled);
64106466
}
64116467

6468+
/* Scripting engines */
6469+
if (all_sections || (dictFind(section_dict, "scriptingengines") != NULL)) {
6470+
if (sections++) info = sdscat(info, "\r\n");
6471+
info = genValkeyInfoStringScriptingEngines(info);
6472+
}
6473+
64126474
/* Key space */
64136475
if (all_sections || (dictFind(section_dict, "keyspace") != NULL)) {
64146476
if (sections++) info = sdscat(info, "\r\n");
@@ -7483,7 +7545,7 @@ int parseExtendedCommandArgumentsOrReply(client *c, int *flags, int *unit, robj
74837545
(opt[1] == 'f' || opt[1] == 'F') &&
74847546
(opt[2] == 'e' || opt[2] == 'E') &&
74857547
(opt[3] == 'q' || opt[3] == 'Q') && opt[4] == '\0' &&
7486-
next &&
7548+
next &&
74877549
!(*flags & ARGS_SET_NX || *flags & ARGS_SET_XX || *flags & ARGS_SET_IFEQ) && (command_type == COMMAND_SET))
74887550
{
74897551
*flags |= ARGS_SET_IFEQ;

tests/unit/moduleapi/scriptingengine.tcl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,42 @@ start_server {tags {"modules"}} {
200200
assert_equal [r ping] {PONG}
201201
}
202202

203+
test {Test INFO scriptingengines section} {
204+
# Get the scripting engines info section
205+
set info [r info scriptingengines]
206+
207+
# Verify the section header exists
208+
assert_match "*# Scripting Engines*" $info
209+
210+
# Verify we have exactly 2 engines (LUA + HELLO)
211+
assert_match "*engines_count:*" $info
212+
regexp {engines_count:([0-9]+)} $info -> engines_count
213+
assert_equal $engines_count 2
214+
215+
# Verify memory fields exist and are non-negative numbers
216+
assert_match "*engines_total_used_memory:*" $info
217+
assert_match "*engines_total_memory_overhead:*" $info
218+
regexp {engines_total_used_memory:([0-9]+)} $info -> total_memory
219+
regexp {engines_total_memory_overhead:([0-9]+)} $info -> total_overhead
220+
assert {$total_memory >= 0}
221+
assert {$total_overhead >= 0}
222+
223+
# Verify individual engine information exists
224+
assert_match "*engine_0:*" $info
225+
assert_match "*engine_1:*" $info
226+
227+
# Check that engines have proper format including abi_version
228+
assert_match "*engine_*:name=*,module=*,abi_version=*,used_memory=*,memory_overhead=*" $info
229+
230+
# Verify both LUA and HELLO engines are present
231+
assert_match "*name=LUA*" $info
232+
assert_match "*name=HELLO*" $info
233+
234+
# Verify LUA is built-in and HELLO is from module
235+
assert_match "*name=LUA,module=built-in*" $info
236+
assert_match "*name=HELLO,module=helloengine*" $info
237+
}
238+
203239
test {Unload scripting engine module} {
204240
set result [r module unload helloengine]
205241
assert_equal $result "OK"

0 commit comments

Comments
 (0)