Skip to content

Commit 9836bc7

Browse files
committed
Add script function flags in the module API
This commit adds script function flags to the module API, which allows function scripts to specify the function flags programmatically. When the scripting engine compiles the script code can extract the flags from the code and set the flags on the compiled function objects. Signed-off-by: Ricardo Dias <[email protected]>
1 parent e19ceb7 commit 9836bc7

File tree

8 files changed

+47
-20
lines changed

8 files changed

+47
-20
lines changed

src/eval.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ int evalExtractShebangFlags(sds body,
252252
int numflags, jj;
253253
sds *flags = sdssplitlen(parts[j], sdslen(parts[j]), ",", 1, &numflags);
254254
for (jj = 0; jj < numflags; jj++) {
255-
scriptFlag *sf;
256-
for (sf = scripts_flags_def; sf->flag; sf++) {
255+
scriptFlagStr *sf;
256+
for (sf = scriptFlags; sf->flag; sf++) {
257257
if (!strcmp(flags[jj], sf->str)) break;
258258
}
259259
if (!sf->flag) {

src/functions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,15 +504,15 @@ void functionStatsCommand(client *c) {
504504
static void functionListReplyFlags(client *c, functionInfo *fi) {
505505
/* First count the number of flags we have */
506506
int flagcount = 0;
507-
for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
507+
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
508508
if (fi->compiled_function->f_flags & flag->flag) {
509509
++flagcount;
510510
}
511511
}
512512

513513
addReplySetLen(c, flagcount);
514514

515-
for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
515+
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
516516
if (fi->compiled_function->f_flags & flag->flag) {
517517
addReplyStatus(c, flag->str);
518518
}

src/lua/function_lua.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ static int luaRegisterFunctionReadFlags(lua_State *lua, uint64_t *flags) {
212212

213213
const char *flag_str = lua_tostring(lua, -1);
214214
int found = 0;
215-
for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
215+
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
216216
if (!strcasecmp(flag->str, flag_str)) {
217217
f_flags |= flag->flag;
218218
found = 1;

src/script.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
#include "cluster_slot_stats.h"
3434
#include "module.h"
3535

36-
scriptFlag scripts_flags_def[] = {
37-
{.flag = SCRIPT_FLAG_NO_WRITES, .str = "no-writes"},
38-
{.flag = SCRIPT_FLAG_ALLOW_OOM, .str = "allow-oom"},
39-
{.flag = SCRIPT_FLAG_ALLOW_STALE, .str = "allow-stale"},
40-
{.flag = SCRIPT_FLAG_NO_CLUSTER, .str = "no-cluster"},
41-
{.flag = SCRIPT_FLAG_ALLOW_CROSS_SLOT, .str = "allow-cross-slot-keys"},
36+
scriptFlagStr scriptFlags[] = {
37+
{.flag = VMSE_SCRIPT_FLAG_NO_WRITES, .str = "no-writes"},
38+
{.flag = VMSE_SCRIPT_FLAG_ALLOW_OOM, .str = "allow-oom"},
39+
{.flag = VMSE_SCRIPT_FLAG_ALLOW_STALE, .str = "allow-stale"},
40+
{.flag = VMSE_SCRIPT_FLAG_NO_CLUSTER, .str = "no-cluster"},
41+
{.flag = VMSE_SCRIPT_FLAG_ALLOW_CROSS_SLOT, .str = "allow-cross-slot-keys"},
4242
{.flag = 0, .str = NULL}, /* flags array end */
4343
};
4444

src/script.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ struct scriptRunCtx {
9191
#define SCRIPT_FLAG_ALLOW_CROSS_SLOT (1ULL << 5)
9292

9393
/* Defines a script flags */
94-
typedef struct scriptFlag {
95-
uint64_t flag;
94+
typedef struct scriptFlagStr {
95+
ValkeyModuleScriptingEngineScriptFlag flag;
9696
const char *str;
97-
} scriptFlag;
97+
} scriptFlagStr;
9898

99-
extern scriptFlag scripts_flags_def[];
99+
extern scriptFlagStr scriptFlags[];
100100

101101
uint64_t scriptFlagsToCmdFlags(uint64_t cmd_flags, uint64_t script_flags);
102102
int scriptPrepareForRun(scriptRunCtx *r_ctx,

src/valkeymodule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,15 @@ typedef enum ValkeyModuleScriptingEngineExecutionState {
907907
VMSE_STATE_KILLED,
908908
} ValkeyModuleScriptingEngineExecutionState;
909909

910+
typedef enum ValkeyModuleScriptingEngineScriptFlag {
911+
VMSE_SCRIPT_FLAG_NO_WRITES = (1ULL << 0),
912+
VMSE_SCRIPT_FLAG_ALLOW_OOM = (1ULL << 1),
913+
VMSE_SCRIPT_FLAG_ALLOW_STALE = (1ULL << 2),
914+
VMSE_SCRIPT_FLAG_NO_CLUSTER = (1ULL << 3),
915+
VMSE_SCRIPT_FLAG_EVAL_COMPAT_MODE = (1ULL << 4), /* EVAL Script backwards compatible behavior, no shebang provided */
916+
VMSE_SCRIPT_FLAG_ALLOW_CROSS_SLOT = (1ULL << 5),
917+
} ValkeyModuleScriptingEngineScriptFlag;
918+
910919
typedef struct ValkeyModuleScriptingEngineCallableLazyEnvReset {
911920
void *context;
912921

tests/modules/helloscripting.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* RETURN # returns the current value on the top of the stack and marks
2828
* # the end of the function declaration
2929
*
30-
* FUNCTION bar # declaration of function 'bar'
30+
* RFUNCTION bar # declaration of read-only function 'bar'
3131
* CONSTI 432 # pushes the value 432 to the top of the stack
3232
* RETURN # returns the current value on the top of the stack and marks
3333
* # the end of the function declaration.
@@ -55,6 +55,7 @@
5555
*/
5656
typedef enum HelloInstKind {
5757
FUNCTION = 0,
58+
RFUNCTION,
5859
CONSTI,
5960
CONSTS,
6061
ARGS,
@@ -69,6 +70,7 @@ typedef enum HelloInstKind {
6970
*/
7071
const char *HelloInstKindStr[] = {
7172
"FUNCTION",
73+
"RFUNCTION",
7274
"CONSTI",
7375
"CONSTS",
7476
"ARGS",
@@ -119,6 +121,7 @@ typedef struct HelloFunc {
119121
HelloInst instructions[256];
120122
uint32_t num_instructions;
121123
uint32_t index;
124+
int read_only;
122125
} HelloFunc;
123126

124127
/*
@@ -207,11 +210,12 @@ static HelloInstKind helloLangParseInstruction(const char *token) {
207210
/*
208211
* Parses the function param.
209212
*/
210-
static void helloLangParseFunction(HelloFunc *func) {
213+
static void helloLangParseFunction(HelloFunc *func, int read_only) {
211214
char *token = strtok(NULL, " \n");
212215
ValkeyModule_Assert(token != NULL);
213216
func->name = ValkeyModule_Alloc(sizeof(char) * strlen(token) + 1);
214217
strcpy(func->name, token);
218+
func->read_only = read_only;
215219
}
216220

217221
/*
@@ -283,12 +287,13 @@ static int helloLangParseCode(const char *code,
283287

284288
switch (kind) {
285289
case FUNCTION:
290+
case RFUNCTION:
286291
ValkeyModule_Assert(currentFunc == NULL);
287292
currentFunc = ValkeyModule_Alloc(sizeof(HelloFunc));
288293
memset(currentFunc, 0, sizeof(HelloFunc));
289294
currentFunc->index = program->num_functions;
290295
program->functions[program->num_functions++] = currentFunc;
291-
helloLangParseFunction(currentFunc);
296+
helloLangParseFunction(currentFunc, kind == RFUNCTION);
292297
break;
293298
case CONSTI:
294299
ValkeyModule_Assert(currentFunc != NULL);
@@ -424,6 +429,7 @@ static void helloDebuggerLogCurrentInstr(uint32_t pc, HelloInst *instr) {
424429
msg = ValkeyModule_CreateStringPrintf(NULL, ">>> %3u: %s", pc, HelloInstKindStr[instr->kind]);
425430
break;
426431
case FUNCTION:
432+
case RFUNCTION:
427433
case _NUM_INSTRUCTIONS:
428434
ValkeyModule_Assert(0);
429435
}
@@ -528,6 +534,7 @@ static HelloExecutionState executeHelloLangFunction(ValkeyModuleCtx *module_ctx,
528534
return FINISHED;
529535
}
530536
case FUNCTION:
537+
case RFUNCTION:
531538
case _NUM_INSTRUCTIONS:
532539
ValkeyModule_Assert(0);
533540
}
@@ -646,7 +653,7 @@ static ValkeyModuleScriptingEngineCompiledFunction **createHelloLangEngine(Valke
646653
.name = ValkeyModule_CreateString(NULL, func->name, strlen(func->name)),
647654
.function = func,
648655
.desc = NULL,
649-
.f_flags = 0,
656+
.f_flags = func->read_only ? VMSE_SCRIPT_FLAG_NO_WRITES : 0,
650657
};
651658

652659
compiled_functions[i] = cfunc;

tests/unit/moduleapi/scriptingengine.tcl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
set testmodule [file normalize tests/modules/helloscripting.so]
22

3-
set HELLO_PROGRAM "#!hello name=mylib\nFUNCTION foo\nARGS 0\nRETURN\nFUNCTION bar\nCONSTI 432\nRETURN"
3+
set HELLO_PROGRAM "#!hello name=mylib\nRFUNCTION foo\nARGS 0\nRETURN\nFUNCTION bar\nCONSTI 432\nRETURN"
44

55
start_server {tags {"modules"}} {
66
r module load $testmodule
@@ -197,6 +197,16 @@ start_server {tags {"modules"}} {
197197
RETURN
198198
} 0
199199
}
200+
201+
r function load {#!hello name=errlib
202+
RFUNCTION callcmd
203+
CONSTS x
204+
CONSTI 43
205+
CONSTI 2
206+
CALL SET
207+
RETURN
208+
}
209+
assert_error {ERR Write commands are not allowed*} {r fcall callcmd 0}
200210
}
201211

202212
test {Call server command when OOM} {
@@ -301,6 +311,7 @@ start_server {tags {"modules"}} {
301311
}
302312

303313
test {List scripting engine functions} {
314+
r function flush sync
304315
r function load replace "#!hello name=mylib\nFUNCTION foobar\nARGS 0\nRETURN"
305316
r function list
306317
} {{library_name mylib engine HELLO functions {{name foobar description {} flags {}}}}}

0 commit comments

Comments
 (0)