[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