mirror of https://github.com/valkey-io/valkey
Add script function flags in the module API (#2836)
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 <ricardo.dias@percona.com>
This commit is contained in:
parent
ed8856bdfc
commit
05540af405
10
src/script.c
10
src/script.c
|
|
@ -34,11 +34,11 @@
|
|||
#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"},
|
||||
{.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 */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ struct scriptRunCtx {
|
|||
|
||||
/* Defines a script flags */
|
||||
typedef struct scriptFlag {
|
||||
uint64_t flag;
|
||||
ValkeyModuleScriptingEngineScriptFlag flag;
|
||||
const char *str;
|
||||
} scriptFlag;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
*/
|
||||
typedef enum HelloInstKind {
|
||||
FUNCTION = 0,
|
||||
RFUNCTION,
|
||||
CONSTI,
|
||||
CONSTS,
|
||||
ARGS,
|
||||
|
|
@ -69,6 +70,7 @@ typedef enum HelloInstKind {
|
|||
*/
|
||||
const char *HelloInstKindStr[] = {
|
||||
"FUNCTION",
|
||||
"RFUNCTION",
|
||||
"CONSTI",
|
||||
"CONSTS",
|
||||
"ARGS",
|
||||
|
|
@ -119,6 +121,7 @@ typedef struct HelloFunc {
|
|||
HelloInst instructions[256];
|
||||
uint32_t num_instructions;
|
||||
uint32_t index;
|
||||
int read_only;
|
||||
} HelloFunc;
|
||||
|
||||
/*
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -528,6 +534,7 @@ static HelloExecutionState executeHelloLangFunction(ValkeyModuleCtx *module_ctx,
|
|||
return FINISHED;
|
||||
}
|
||||
case FUNCTION:
|
||||
case RFUNCTION:
|
||||
case _NUM_INSTRUCTIONS:
|
||||
ValkeyModule_Assert(0);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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} {
|
||||
|
|
@ -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 {}}}}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue