Skip to content

Commit 58f217a

Browse files
committed
Move Lua scripting engine into a Valkey module
This commit restructures the Lua scripting functionality by extracting it from the core Valkey server into a separate Valkey module. This change enables the possibility of a backwards compatible Lua engine upgrade, as well as, the flexibility in building Valkey without the Lua engine. **Important**: from a user's point of view, there's no difference in using the `EVAL` of `FUNCTION/FCALL` scripts. This PR is fully backward compatible with respect to the public API. The main code change is the move and adaptation of the Lua engine source files from `src/lua` to `src/modules/lua`. The original Lua engine code is adapted to use the module API to compile and execute scripts. The main difference between the original code and the new, is the serialization and deserialization of Valkey RESP values into, and from, Lua values. While in the original implementation the parsing of RESP values was done directly from the client buffer, in the new implementation the parsing is done from the `ValkeyModuleCallReply` object and respective API. The Makefile and CMake build systems were also updated to build and integrate the new Lua engine module, within the Valkey server build workflow. When the Valkey server is built, the Lua engine module is also built, and, the Lua module is loaded automatically by the server upon startup. When running `make install` the Lua engine module is installed in the default system library directory. There's a new build option, called `WITHOUT_LUA`, that if set allows to build Valkey server without building the Lua engine. This modular architecture enables future development of additional Lua engine modules with newer Lua versions that can be loaded alongside the current engine, facilitating gradual migration paths for users. Signed-off-by: Ricardo Dias <[email protected]>
1 parent 9836bc7 commit 58f217a

31 files changed

+2004
-1657
lines changed

cmake/Modules/SourceFiles.cmake

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,9 @@ set(VALKEY_SERVER_SRCS
100100
${CMAKE_SOURCE_DIR}/src/mt19937-64.c
101101
${CMAKE_SOURCE_DIR}/src/resp_parser.c
102102
${CMAKE_SOURCE_DIR}/src/call_reply.c
103-
${CMAKE_SOURCE_DIR}/src/lua/script_lua.c
104103
${CMAKE_SOURCE_DIR}/src/script.c
105104
${CMAKE_SOURCE_DIR}/src/functions.c
106105
${CMAKE_SOURCE_DIR}/src/scripting_engine.c
107-
${CMAKE_SOURCE_DIR}/src/lua/function_lua.c
108-
${CMAKE_SOURCE_DIR}/src/lua/engine_lua.c
109-
${CMAKE_SOURCE_DIR}/src/lua/debug_lua.c
110106
${CMAKE_SOURCE_DIR}/src/trace/trace.c
111107
${CMAKE_SOURCE_DIR}/src/trace/trace_rdb.c
112108
${CMAKE_SOURCE_DIR}/src/trace/trace_aof.c

cmake/Modules/ValkeySetup.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ if (BUILD_SANITIZER)
278278
endif ()
279279

280280
include_directories("${CMAKE_SOURCE_DIR}/deps/libvalkey/include")
281+
include_directories("${CMAKE_SOURCE_DIR}/src/modules/lua")
281282
include_directories("${CMAKE_SOURCE_DIR}/deps/linenoise")
282-
include_directories("${CMAKE_SOURCE_DIR}/deps/lua/src")
283283
include_directories("${CMAKE_SOURCE_DIR}/deps/hdr_histogram")
284284
include_directories("${CMAKE_SOURCE_DIR}/deps/fpconv")
285285

deps/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ hdr_histogram: .make-prerequisites
7676

7777
fpconv: .make-prerequisites
7878
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
79-
cd fpconv && $(MAKE)
79+
cd fpconv && $(MAKE) CFLAGS="-fPIC"
8080

8181
.PHONY: fpconv
8282

@@ -85,7 +85,7 @@ ifeq ($(uname_S),SunOS)
8585
LUA_CFLAGS= -D__C99FEATURES__=1
8686
endif
8787

88-
LUA_CFLAGS+= -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DLUA_USE_MKSTEMP $(CFLAGS)
88+
LUA_CFLAGS+= -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DLUA_USE_MKSTEMP $(CFLAGS) -fPIC
8989
LUA_LDFLAGS+= $(LDFLAGS)
9090
ifeq ($(LUA_DEBUG),yes)
9191
LUA_CFLAGS+= -O0 -g -DLUA_USE_APICHECK

deps/lua/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ set(LUA_SRCS
4444
add_library(lualib STATIC "${LUA_SRCS}")
4545
target_include_directories(lualib PUBLIC "${LUA_SRC_DIR}")
4646
target_compile_definitions(lualib PRIVATE ENABLE_CJSON_GLOBAL)
47+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
4748

4849
# Use mkstemp if available
4950
check_function_exists(mkstemp HAVE_MKSTEMP)

src/CMakeLists.txt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,29 @@ message(STATUS "CFLAGS: ${CMAKE_C_FLAGS}")
99

1010
get_valkey_server_linker_option(VALKEY_SERVER_LDFLAGS)
1111
list(APPEND SERVER_LIBS "fpconv")
12-
list(APPEND SERVER_LIBS "lualib")
1312
list(APPEND SERVER_LIBS "hdr_histogram")
1413
valkey_build_and_install_bin(valkey-server "${VALKEY_SERVER_SRCS}" "${VALKEY_SERVER_LDFLAGS}" "${SERVER_LIBS}"
1514
"redis-server")
1615
add_dependencies(valkey-server generate_commands_def)
1716
add_dependencies(valkey-server generate_fmtargs_h)
1817
add_dependencies(valkey-server release_header)
1918

19+
if (NOT WITHOUT_LUA)
20+
message(STATUS "Build Lua scripting engine module")
21+
add_subdirectory(modules/lua)
22+
add_dependencies(valkey-server luaengine)
23+
target_compile_definitions(valkey-server PRIVATE LUA_ENGINE_ENABLED)
24+
target_compile_definitions(valkey-server PRIVATE LUA_ENGINE_LIB=libluaengine.so)
25+
26+
set(VALKEY_INSTALL_RPATH "")
27+
set_target_properties(valkey-server PROPERTIES
28+
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR};${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
29+
INSTALL_RPATH_USE_LINK_PATH TRUE
30+
BUILD_WITH_INSTALL_RPATH TRUE
31+
)
32+
endif()
33+
unset(WITHOUT_LUA CACHE)
34+
2035
if (VALKEY_RELEASE_BUILD)
2136
# Enable LTO for Release build
2237
set_property(TARGET valkey-server PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)

src/Makefile

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ endif
3131
ifneq ($(OPTIMIZATION),-O0)
3232
OPTIMIZATION+=-fno-omit-frame-pointer
3333
endif
34-
DEPENDENCY_TARGETS=libvalkey linenoise lua hdr_histogram fpconv
34+
DEPENDENCY_TARGETS=libvalkey linenoise hdr_histogram fpconv
3535
NODEPS:=clean distclean
3636

3737
# Default settings
@@ -63,6 +63,7 @@ endif
6363

6464
PREFIX?=/usr/local
6565
INSTALL_BIN=$(PREFIX)/bin
66+
INSTALL_LIB=$(PREFIX)/lib
6667
INSTALL=install
6768
PKG_CONFIG?=pkg-config
6869

@@ -250,7 +251,23 @@ ifdef OPENSSL_PREFIX
250251
endif
251252

252253
# Include paths to dependencies
253-
FINAL_CFLAGS+= -I../deps/libvalkey/include -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram -I../deps/fpconv
254+
FINAL_CFLAGS+= -I../deps/libvalkey/include -I../deps/linenoise -I../deps/hdr_histogram -I../deps/fpconv
255+
256+
# Lua scripting engine module
257+
LUA_MODULE=
258+
LUA_MODULE_INSTALL=
259+
LUA_MODULE_NAME:=modules/lua/libluaengine.so
260+
261+
ifneq ($(WITHOUT_LUA),yes)
262+
LUA_MODULE=$(LUA_MODULE_NAME)
263+
endif
264+
265+
ifeq ($(LUA_MODULE),$(LUA_MODULE_NAME))
266+
current_dir = $(shell pwd)
267+
FINAL_CFLAGS+=-DLUA_ENGINE_ENABLED -DLUA_ENGINE_LIB=libluaengine.so
268+
FINAL_LDFLAGS+= -Wl,-rpath=$(PREFIX)/lib:$(current_dir)/modules/lua -Wl,--disable-new-dtags
269+
LUA_MODULE_INSTALL=install-lua-module
270+
endif
254271

255272
# Determine systemd support and/or build preference (defaulting to auto-detection)
256273
BUILD_WITH_SYSTEMD=no
@@ -423,7 +440,7 @@ ENGINE_NAME=valkey
423440
SERVER_NAME=$(ENGINE_NAME)-server$(PROG_SUFFIX)
424441
ENGINE_SENTINEL_NAME=$(ENGINE_NAME)-sentinel$(PROG_SUFFIX)
425442
ENGINE_TRACE_OBJ=trace/trace.o trace/trace_commands.o trace/trace_db.o trace/trace_cluster.o trace/trace_server.o trace/trace_rdb.o trace/trace_aof.o
426-
ENGINE_SERVER_OBJ=threads_mngr.o adlist.o vector.o quicklist.o ae.o anet.o dict.o hashtable.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o memory_prefetch.o io_threads.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o cluster_slot_stats.o crc16.o cluster_migrateslots.o endianconv.o commandlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o valkey-check-rdb.o valkey-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o allocator_defrag.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o lolwut9.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script.o functions.o commands.o strl.o connection.o unix.o logreqres.o rdma.o scripting_engine.o entry.o vset.o lua/script_lua.o lua/function_lua.o lua/engine_lua.o lua/debug_lua.o
443+
ENGINE_SERVER_OBJ=threads_mngr.o adlist.o vector.o quicklist.o ae.o anet.o dict.o hashtable.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o memory_prefetch.o io_threads.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o cluster_slot_stats.o crc16.o cluster_migrateslots.o endianconv.o commandlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o valkey-check-rdb.o valkey-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o allocator_defrag.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o lolwut9.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script.o functions.o commands.o strl.o connection.o unix.o logreqres.o rdma.o scripting_engine.o entry.o vset.o
427444
ENGINE_SERVER_OBJ+=$(ENGINE_TRACE_OBJ)
428445
ENGINE_CLI_NAME=$(ENGINE_NAME)-cli$(PROG_SUFFIX)
429446
ENGINE_CLI_OBJ=anet.o adlist.o dict.o valkey-cli.o zmalloc.o release.o ae.o serverassert.o crcspeed.o crccombine.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o cli_commands.o sds.o util.o sha256.o
@@ -448,7 +465,7 @@ ifeq ($(USE_FAST_FLOAT),yes)
448465
FINAL_LIBS += $(FAST_FLOAT_STRTOD_OBJECT)
449466
endif
450467

451-
all: $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(TLS_MODULE) $(RDMA_MODULE)
468+
all: $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(TLS_MODULE) $(RDMA_MODULE) $(LUA_MODULE)
452469
@echo ""
453470
@echo "Hint: It's a good idea to run 'make test' ;)"
454471
@echo ""
@@ -473,6 +490,7 @@ persist-settings: distclean
473490
echo BUILD_TLS=$(BUILD_TLS) >> .make-settings
474491
echo BUILD_RDMA=$(BUILD_RDMA) >> .make-settings
475492
echo USE_SYSTEMD=$(USE_SYSTEMD) >> .make-settings
493+
echo WITHOUT_LUA=$(WITHOUT_LUA) >> .make-settings
476494
echo CFLAGS=$(CFLAGS) >> .make-settings
477495
echo LDFLAGS=$(LDFLAGS) >> .make-settings
478496
echo SERVER_CFLAGS=$(SERVER_CFLAGS) >> .make-settings
@@ -498,15 +516,15 @@ endif
498516

499517
# valkey-server
500518
$(SERVER_NAME): $(ENGINE_SERVER_OBJ)
501-
$(SERVER_LD) -o $@ $^ ../deps/libvalkey/lib/libvalkey.a ../deps/lua/src/liblua.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS)
519+
$(SERVER_LD) -o $@ $^ ../deps/libvalkey/lib/libvalkey.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS)
502520

503521
# Valkey static library, used to compile against for unit testing
504522
$(ENGINE_LIB_NAME): $(ENGINE_SERVER_OBJ)
505523
$(SERVER_AR) rcs $@ $^
506524

507525
# valkey-unit-tests
508526
$(ENGINE_UNIT_TESTS): $(ENGINE_TEST_OBJ) $(ENGINE_LIB_NAME)
509-
$(SERVER_LD) -o $@ $^ ../deps/libvalkey/lib/libvalkey.a ../deps/lua/src/liblua.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS)
527+
$(SERVER_LD) -o $@ $^ ../deps/libvalkey/lib/libvalkey.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS)
510528

511529
# valkey-sentinel
512530
$(ENGINE_SENTINEL_NAME): $(SERVER_NAME)
@@ -528,6 +546,10 @@ $(TLS_MODULE_NAME): $(SERVER_NAME)
528546
$(RDMA_MODULE_NAME): $(SERVER_NAME)
529547
$(QUIET_CC)$(CC) -o $@ rdma.c -shared -fPIC $(RDMA_MODULE_CFLAGS)
530548

549+
# engine_lua.so
550+
$(LUA_MODULE_NAME): $(SERVER_NAME)
551+
cd modules/lua && $(MAKE) OPTIMIZATION="$(OPTIMIZATION)"
552+
531553
# valkey-cli
532554
$(ENGINE_CLI_NAME): $(ENGINE_CLI_OBJ)
533555
$(SERVER_LD) -o $@ $^ ../deps/libvalkey/lib/libvalkey.a ../deps/linenoise/linenoise.o ../deps/fpconv/libfpconv.a $(FINAL_LIBS) $(TLS_CLIENT_LIBS) $(RDMA_CLIENT_LIBS)
@@ -545,9 +567,6 @@ DEP = $(ENGINE_SERVER_OBJ:%.o=%.d) $(ENGINE_CLI_OBJ:%.o=%.d) $(ENGINE_BENCHMARK_
545567
%.o: %.c .make-prerequisites
546568
$(SERVER_CC) -MMD -o $@ -c $<
547569

548-
lua/%.o: lua/%.c .make-prerequisites
549-
$(SERVER_CC) -MMD -o $@ -c $<
550-
551570
trace/%.o: trace/%.c .make-prerequisites
552571
$(SERVER_CC) -Itrace -MMD -o $@ -c $<
553572

@@ -574,8 +593,9 @@ endif
574593
commands.c: $(COMMANDS_DEF_FILENAME).def
575594

576595
clean:
577-
rm -rf $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(ENGINE_UNIT_TESTS) $(ENGINE_LIB_NAME) unit/*.o unit/*.d lua/*.o lua/*.d trace/*.o trace/*.d *.o *.gcda *.gcno *.gcov valkey.info lcov-html Makefile.dep *.so
596+
rm -rf $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(ENGINE_UNIT_TESTS) $(ENGINE_LIB_NAME) unit/*.o unit/*.d trace/*.o trace/*.d *.o *.gcda *.gcno *.gcov valkey.info lcov-html Makefile.dep *.so
578597
rm -f $(DEP)
598+
-(cd modules/lua && $(MAKE) clean)
579599

580600
.PHONY: clean
581601

@@ -634,7 +654,7 @@ valgrind:
634654
helgrind:
635655
$(MAKE) OPTIMIZATION="-O0" MALLOC="libc" CFLAGS="-D__ATOMIC_VAR_FORCE_SYNC_MACROS" SERVER_CFLAGS="-I/usr/local/include" SERVER_LDFLAGS="-L/usr/local/lib"
636656

637-
install: all
657+
install: all $(LUA_MODULE_INSTALL)
638658
@mkdir -p $(INSTALL_BIN)
639659
$(call MAKE_INSTALL,$(SERVER_NAME),$(INSTALL_BIN))
640660
$(call MAKE_INSTALL,$(ENGINE_BENCHMARK_NAME),$(INSTALL_BIN))
@@ -649,6 +669,10 @@ install: all
649669
$(call MAYBE_INSTALL_REDIS_SYMLINK,$(ENGINE_CHECK_AOF_NAME),$(INSTALL_BIN))
650670
$(call MAYBE_INSTALL_REDIS_SYMLINK,$(ENGINE_SENTINEL_NAME),$(INSTALL_BIN))
651671

672+
install-lua-module: $(LUA_MODULE)
673+
@mkdir -p $(INSTALL_LIB)
674+
$(call MAKE_INSTALL,$(LUA_MODULE),$(INSTALL_LIB))
675+
652676
uninstall:
653677
@rm -f $(INSTALL_BIN)/{$(SERVER_NAME),$(ENGINE_BENCHMARK_NAME),$(ENGINE_CLI_NAME),$(ENGINE_CHECK_RDB_NAME),$(ENGINE_CHECK_AOF_NAME),$(ENGINE_SENTINEL_NAME)}
654678
$(call MAYBE_UNINSTALL_REDIS_SYMLINK,$(INSTALL_BIN),$(SERVER_NAME))

src/config.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*/
3030

3131
#include "io_threads.h"
32+
#include "sds.h"
3233
#include "server.h"
3334
#include "cluster.h"
3435
#include "connection.h"
@@ -2635,7 +2636,12 @@ int invalidateClusterSlotsResp(const char **err) {
26352636
static int updateLuaEnableInsecureApi(const char **err) {
26362637
UNUSED(err);
26372638
if (server.lua_insecure_api_current != server.lua_enable_insecure_api) {
2639+
sds config_name = sdsnew("lua.lua-enable-insecure-api");
2640+
standardConfig *config = lookupConfig(config_name);
2641+
serverAssert(config && config->flags & MODULE_CONFIG);
2642+
setModuleBoolConfig(config->privdata, server.lua_enable_insecure_api, NULL);
26382643
evalReset(server.lazyfree_lazy_user_flush ? 1 : 0);
2644+
sdsfree(config_name);
26392645
}
26402646
server.lua_insecure_api_current = server.lua_enable_insecure_api;
26412647
return 1;

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ static int evalRegisterNewScript(client *c, robj *body, char **sha) {
442442
}
443443
es->body = body;
444444
int retval = dictAdd(evalCtx.scripts, _sha, es);
445-
serverAssertWithInfo(c ? c : scriptingEngineGetClient(engine), NULL, retval == DICT_OK);
445+
serverAssert(retval == DICT_OK);
446446
evalCtx.scripts_mem += sdsAllocSize(_sha) + getStringObjectSdsUsedMemory(body);
447447
incrRefCount(body);
448448
zfree(functions);

0 commit comments

Comments
 (0)