Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ int evalExtractShebangFlags(sds body,
int numflags, jj;
sds *flags = sdssplitlen(parts[j], sdslen(parts[j]), ",", 1, &numflags);
for (jj = 0; jj < numflags; jj++) {
scriptFlag *sf;
for (sf = scripts_flags_def; sf->flag; sf++) {
scriptFlagStr *sf;
for (sf = scriptFlags; sf->flag; sf++) {
if (!strcmp(flags[jj], sf->str)) break;
}
if (!sf->flag) {
Expand Down
4 changes: 2 additions & 2 deletions src/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,15 +504,15 @@ void functionStatsCommand(client *c) {
static void functionListReplyFlags(client *c, functionInfo *fi) {
/* First count the number of flags we have */
int flagcount = 0;
for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
if (fi->compiled_function->f_flags & flag->flag) {
++flagcount;
}
}

addReplySetLen(c, flagcount);

for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
if (fi->compiled_function->f_flags & flag->flag) {
addReplyStatus(c, flag->str);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lua/function_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int luaRegisterFunctionReadFlags(lua_State *lua, uint64_t *flags) {

const char *flag_str = lua_tostring(lua, -1);
int found = 0;
for (scriptFlag *flag = scripts_flags_def; flag->str; ++flag) {
for (scriptFlagStr *flag = scriptFlags; flag->str; ++flag) {
if (!strcasecmp(flag->str, flag_str)) {
f_flags |= flag->flag;
found = 1;
Expand Down
12 changes: 6 additions & 6 deletions src/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
#include "cluster_slot_stats.h"
#include "module.h"

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

Expand Down
8 changes: 4 additions & 4 deletions src/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ struct scriptRunCtx {
#define SCRIPT_FLAG_ALLOW_CROSS_SLOT (1ULL << 5)

/* Defines a script flags */
typedef struct scriptFlag {
uint64_t flag;
typedef struct scriptFlagStr {
ValkeyModuleScriptingEngineScriptFlag flag;
const char *str;
} scriptFlag;
} scriptFlagStr;

extern scriptFlag scripts_flags_def[];
extern scriptFlagStr scriptFlags[];

uint64_t scriptFlagsToCmdFlags(uint64_t cmd_flags, uint64_t script_flags);
int scriptPrepareForRun(scriptRunCtx *r_ctx,
Expand Down
9 changes: 9 additions & 0 deletions src/valkeymodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,15 @@ typedef enum ValkeyModuleScriptingEngineExecutionState {
VMSE_STATE_KILLED,
} ValkeyModuleScriptingEngineExecutionState;

typedef enum ValkeyModuleScriptingEngineScriptFlag {
VMSE_SCRIPT_FLAG_NO_WRITES = (1ULL << 0),
VMSE_SCRIPT_FLAG_ALLOW_OOM = (1ULL << 1),
VMSE_SCRIPT_FLAG_ALLOW_STALE = (1ULL << 2),
VMSE_SCRIPT_FLAG_NO_CLUSTER = (1ULL << 3),
VMSE_SCRIPT_FLAG_EVAL_COMPAT_MODE = (1ULL << 4), /* EVAL Script backwards compatible behavior, no shebang provided */
VMSE_SCRIPT_FLAG_ALLOW_CROSS_SLOT = (1ULL << 5),
} ValkeyModuleScriptingEngineScriptFlag;

typedef struct ValkeyModuleScriptingEngineCallableLazyEnvReset {
void *context;

Expand Down
15 changes: 11 additions & 4 deletions tests/modules/helloscripting.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* RETURN # returns the current value on the top of the stack and marks
* # the end of the function declaration
*
* FUNCTION bar # declaration of function 'bar'
* RFUNCTION bar # declaration of read-only function 'bar'
* CONSTI 432 # pushes the value 432 to the top of the stack
* RETURN # returns the current value on the top of the stack and marks
* # the end of the function declaration.
Expand Down Expand Up @@ -55,6 +55,7 @@
*/
typedef enum HelloInstKind {
FUNCTION = 0,
RFUNCTION,
CONSTI,
CONSTS,
ARGS,
Expand All @@ -69,6 +70,7 @@ typedef enum HelloInstKind {
*/
const char *HelloInstKindStr[] = {
"FUNCTION",
"RFUNCTION",
"CONSTI",
"CONSTS",
"ARGS",
Expand Down Expand Up @@ -119,6 +121,7 @@ typedef struct HelloFunc {
HelloInst instructions[256];
uint32_t num_instructions;
uint32_t index;
int read_only;
} HelloFunc;

/*
Expand Down Expand Up @@ -207,11 +210,12 @@ static HelloInstKind helloLangParseInstruction(const char *token) {
/*
* Parses the function param.
*/
static void helloLangParseFunction(HelloFunc *func) {
static void helloLangParseFunction(HelloFunc *func, int read_only) {
char *token = strtok(NULL, " \n");
ValkeyModule_Assert(token != NULL);
func->name = ValkeyModule_Alloc(sizeof(char) * strlen(token) + 1);
strcpy(func->name, token);
func->read_only = read_only;
}

/*
Expand Down Expand Up @@ -283,12 +287,13 @@ static int helloLangParseCode(const char *code,

switch (kind) {
case FUNCTION:
case RFUNCTION:
ValkeyModule_Assert(currentFunc == NULL);
currentFunc = ValkeyModule_Alloc(sizeof(HelloFunc));
memset(currentFunc, 0, sizeof(HelloFunc));
currentFunc->index = program->num_functions;
program->functions[program->num_functions++] = currentFunc;
helloLangParseFunction(currentFunc);
helloLangParseFunction(currentFunc, kind == RFUNCTION);
break;
case CONSTI:
ValkeyModule_Assert(currentFunc != NULL);
Expand Down Expand Up @@ -424,6 +429,7 @@ static void helloDebuggerLogCurrentInstr(uint32_t pc, HelloInst *instr) {
msg = ValkeyModule_CreateStringPrintf(NULL, ">>> %3u: %s", pc, HelloInstKindStr[instr->kind]);
break;
case FUNCTION:
case RFUNCTION:
case _NUM_INSTRUCTIONS:
ValkeyModule_Assert(0);
}
Expand Down Expand Up @@ -528,6 +534,7 @@ static HelloExecutionState executeHelloLangFunction(ValkeyModuleCtx *module_ctx,
return FINISHED;
}
case FUNCTION:
case RFUNCTION:
case _NUM_INSTRUCTIONS:
ValkeyModule_Assert(0);
}
Expand Down Expand Up @@ -646,7 +653,7 @@ static ValkeyModuleScriptingEngineCompiledFunction **createHelloLangEngine(Valke
.name = ValkeyModule_CreateString(NULL, func->name, strlen(func->name)),
.function = func,
.desc = NULL,
.f_flags = 0,
.f_flags = func->read_only ? VMSE_SCRIPT_FLAG_NO_WRITES : 0,
};

compiled_functions[i] = cfunc;
Expand Down
13 changes: 12 additions & 1 deletion tests/unit/moduleapi/scriptingengine.tcl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set testmodule [file normalize tests/modules/helloscripting.so]

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

start_server {tags {"modules"}} {
r module load $testmodule
Expand Down Expand Up @@ -197,6 +197,16 @@ start_server {tags {"modules"}} {
RETURN
} 0
}

r function load {#!hello name=errlib
RFUNCTION callcmd
CONSTS x
CONSTI 43
CONSTI 2
CALL SET
RETURN
}
assert_error {ERR Write commands are not allowed*} {r fcall callcmd 0}
}

test {Call server command when OOM} {
Expand Down Expand Up @@ -301,6 +311,7 @@ start_server {tags {"modules"}} {
}

test {List scripting engine functions} {
r function flush sync
r function load replace "#!hello name=mylib\nFUNCTION foobar\nARGS 0\nRETURN"
r function list
} {{library_name mylib engine HELLO functions {{name foobar description {} flags {}}}}}
Expand Down
Loading