[tarantool-patches] [PATCH v3 3/4] Use fiber lua state for triggers if possible
Georgy Kirichenko
georgy at tarantool.org
Wed Oct 31 13:49:12 MSK 2018
Lua trigger invocation reuses a fiber lua state if exists instead of
creating of new one for each new invocation. This is needed for a lua
stack reconstruction during backtracing.
Relates: #3538
---
src/box/lua/space.cc | 12 ++++++------
src/fiber.h | 32 ++++++++++++++------------------
src/lua/trigger.c | 19 ++++++++++++++-----
src/lua/trigger.h | 2 +-
4 files changed, 35 insertions(+), 30 deletions(-)
diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc
index 25b7e36da..df698810b 100644
--- a/src/box/lua/space.cc
+++ b/src/box/lua/space.cc
@@ -73,20 +73,20 @@ lbox_push_txn_stmt(struct lua_State *L, void *event)
}
static int
-lbox_pop_txn_stmt(struct lua_State *L, void *event)
+lbox_pop_txn_stmt(struct lua_State *L, int nret, void *event)
{
struct txn_stmt *stmt = txn_current_stmt((struct txn *) event);
- if (lua_gettop(L) < 1) {
+ if (nret < 1) {
/* No return value - nothing to do. */
return 0;
}
-
- struct tuple *result = luaT_istuple(L, 1);
- if (result == NULL && !lua_isnil(L, 1) && !luaL_isnull(L, 1)) {
+ int top = lua_gettop(L) - nret + 1;
+ struct tuple *result = luaT_istuple(L, top);
+ if (result == NULL && !lua_isnil(L, top) && !luaL_isnull(L, top)) {
/* Invalid return value - raise error. */
diag_set(ClientError, ER_BEFORE_REPLACE_RET,
- lua_typename(L, lua_type(L, 1)));
+ lua_typename(L, lua_type(L, top)));
return -1;
}
diff --git a/src/fiber.h b/src/fiber.h
index bb5343fdc..d4ed1193a 100644
--- a/src/fiber.h
+++ b/src/fiber.h
@@ -398,24 +398,20 @@ struct fiber {
struct session *session;
struct credentials *credentials;
struct txn *txn;
- union {
- /**
- * Fields used by a fiber created in Lua:
- * Lua stack and the optional
- * fiber.storage Lua reference.
- */
- struct {
- struct lua_State *stack;
- int ref;
- } lua;
- /**
- * Fields used by a fiber created to
- * process an iproto request.
- */
- struct {
- uint64_t sync;
- } net;
- };
+ /**
+ * Lua stack and the optional
+ * fiber.storage Lua reference.
+ */
+ struct {
+ struct lua_State *stack;
+ int ref;
+ } lua;
+ /**
+ * Iproto sync.
+ */
+ struct {
+ uint64_t sync;
+ } net;
} storage;
/** An object to wait for incoming message or a reader. */
struct ipc_wait_pad *wait_pad;
diff --git a/src/lua/trigger.c b/src/lua/trigger.c
index c758e47ea..2c2ede212 100644
--- a/src/lua/trigger.c
+++ b/src/lua/trigger.c
@@ -80,16 +80,25 @@ lbox_trigger_run(struct trigger *ptr, void *event)
* invocation, and in future we plan to hack into Lua
* C API to fix this.
*/
- struct lua_State *L = lua_newthread(tarantool_L);
- int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
+ struct lua_State *L;
+ int coro_ref;
+ if (fiber()->storage.lua.stack == NULL) {
+ L = lua_newthread(tarantool_L);
+ coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
+ } else {
+ L = fiber()->storage.lua.stack;
+ coro_ref = LUA_REFNIL;
+ }
+ int top = lua_gettop(L);
lua_rawgeti(L, LUA_REGISTRYINDEX, trigger->ref);
- int top = trigger->push_event(L, event);
- if (luaT_call(L, top, LUA_MULTRET)) {
+ int nargs = trigger->push_event(L, event);
+ if (luaT_call(L, nargs, LUA_MULTRET)) {
luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
diag_raise();
}
+ int nret = lua_gettop(L) - top;
if (trigger->pop_event != NULL &&
- trigger->pop_event(L, event) != 0) {
+ trigger->pop_event(L, nret, event) != 0) {
luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
diag_raise();
}
diff --git a/src/lua/trigger.h b/src/lua/trigger.h
index 8901f5dea..1d1dcce35 100644
--- a/src/lua/trigger.h
+++ b/src/lua/trigger.h
@@ -52,7 +52,7 @@ typedef int
* error will be raised for the caller.
*/
typedef int
-(*lbox_pop_event_f)(struct lua_State *L, void *event);
+(*lbox_pop_event_f)(struct lua_State *L, int nret, void *event);
/**
* Create a Lua trigger, replace an existing one,
--
2.19.1
More information about the Tarantool-patches
mailing list