From 65128730e4c2a33b91e8c348e4c6a3abc9bdc445 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Tue, 20 Aug 2013 20:36:24 +0400
Subject: [PATCH] Improve trigger API to accept context and allow a list of
 triggers.

---
 include/session.h  |  4 ++--
 include/trigger.h  | 54 +++++++++++++++++++++++++++++++++++++---------
 src/lua/session.cc | 26 +++++++++++-----------
 src/session.cc     |  8 +++----
 4 files changed, 64 insertions(+), 28 deletions(-)

diff --git a/include/session.h b/include/session.h
index d16b0e7ba4..5aaf652589 100644
--- a/include/session.h
+++ b/include/session.h
@@ -84,9 +84,9 @@ session_exists(uint32_t sid)
 }
 
 /* The global on-connect trigger. */
-extern struct trigger session_on_connect;
+extern struct rlist session_on_connect;
 /* The global on-disconnect trigger. */
-extern struct trigger session_on_disconnect;
+extern struct rlist session_on_disconnect;
 
 void
 session_init();
diff --git a/include/trigger.h b/include/trigger.h
index fed6eef062..ad01a6cad5 100644
--- a/include/trigger.h
+++ b/include/trigger.h
@@ -1,30 +1,64 @@
 #ifndef INCLUDES_TARANTOOL_TRIGGER_H
 #define INCLUDES_TARANTOOL_TRIGGER_H
-#
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "rlist.h"
 /**
  * Type of the callback which may be invoked
  * on an event.
  */
-typedef void (*trigger_f)(void *);
+typedef void (*trigger_f)(struct trigger *trigger, void *event);
 
 struct trigger
 {
-	trigger_f trigger;
-	void *param;
+	struct rlist link;
+	trigger_f run;
 };
 
 static inline void
-trigger_run(struct trigger *trigger)
+trigger_run(struct rlist *list, void *event)
+{
+	struct trigger *trigger;
+	rlist_foreach_entry(trigger, list, link)
+		trigger->run(trigger, event);
+}
+
+static inline void
+trigger_set(struct rlist *list, struct trigger *trigger)
 {
-	if (trigger->trigger)
-		trigger->trigger(trigger->param);
+	rlist_add_entry(list, trigger, link);
 }
 
 static inline void
-trigger_set(struct trigger *trigger, trigger_f func, void *param)
+trigger_clear(struct trigger *trigger)
 {
-	trigger->trigger = func;
-	trigger->param = param;
+	rlist_del_entry(trigger, link);
 }
 
 #endif /* INCLUDES_TARANTOOL_TRIGGER_H */
diff --git a/src/lua/session.cc b/src/lua/session.cc
index a0fba2f421..1fe6e2e09b 100644
--- a/src/lua/session.cc
+++ b/src/lua/session.cc
@@ -92,20 +92,15 @@ lbox_session_peer(struct lua_State *L)
 
 struct lbox_session_trigger
 {
-	struct trigger *trigger;
+	struct trigger trigger;
 	int ref;
 };
 
-static struct lbox_session_trigger on_connect =
-	{ &session_on_connect, LUA_NOREF};
-static struct lbox_session_trigger on_disconnect =
-	{ &session_on_disconnect, LUA_NOREF};
-
 static void
-lbox_session_run_trigger(void *param)
+lbox_session_run_trigger(struct trigger *trg, void * /* event */)
 {
 	struct lbox_session_trigger *trigger =
-			(struct lbox_session_trigger *) param;
+			(struct lbox_session_trigger *) trg;
 	/* Copy the referenced callable object object stack. */
 	lua_State *L = lua_newthread(tarantool_L);
 	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
@@ -125,8 +120,14 @@ lbox_session_run_trigger(void *param)
 	}
 }
 
+static struct lbox_session_trigger on_connect =
+	{ { rlist_nil, lbox_session_run_trigger }, LUA_NOREF};
+static struct lbox_session_trigger on_disconnect =
+	{ { rlist_nil, lbox_session_run_trigger }, LUA_NOREF};
+
 static int
 lbox_session_set_trigger(struct lua_State *L,
+			 struct rlist *list,
 			 struct lbox_session_trigger *trigger)
 {
 	if (lua_gettop(L) != 1 ||
@@ -139,6 +140,7 @@ lbox_session_set_trigger(struct lua_State *L,
 	if (trigger->ref != LUA_NOREF) {
 		lua_rawgeti(L, LUA_REGISTRYINDEX, trigger->ref);
 		luaL_unref(L, LUA_REGISTRYINDEX, trigger->ref);
+		trigger_clear(&trigger->trigger);
 	} else {
 		lua_pushnil(L);
 	}
@@ -149,13 +151,12 @@ lbox_session_set_trigger(struct lua_State *L,
 	 */
 	if (lua_type(L, -2) == LUA_TNIL) {
 		trigger->ref = LUA_NOREF;
-		trigger_set(trigger->trigger, NULL, NULL);
 	} else {
 		/* Move the trigger to the top of the stack. */
 		lua_insert(L, -2);
 		/* Reference the new trigger. Pops it. */
 		trigger->ref = luaL_ref(L, LUA_REGISTRYINDEX);
-		trigger_set(trigger->trigger, lbox_session_run_trigger, trigger);
+		trigger_set(list, &trigger->trigger);
 	}
 	/* Return the old trigger. */
 	return 1;
@@ -164,13 +165,14 @@ lbox_session_set_trigger(struct lua_State *L,
 static int
 lbox_session_on_connect(struct lua_State *L)
 {
-	return lbox_session_set_trigger(L, &on_connect);
+	return lbox_session_set_trigger(L, &session_on_connect, &on_connect);
 }
 
 static int
 lbox_session_on_disconnect(struct lua_State *L)
 {
-	return lbox_session_set_trigger(L, &on_disconnect);
+	return lbox_session_set_trigger(L, &session_on_disconnect,
+					&on_disconnect);
 }
 
 static const struct luaL_reg lbox_session_meta [] = {
diff --git a/src/session.cc b/src/session.cc
index be2f6d5606..aff039821d 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -37,8 +37,8 @@ uint32_t sid_max;
 
 static struct mh_i32ptr_t *session_registry;
 
-struct trigger session_on_connect;
-struct trigger session_on_disconnect;
+RLIST_HEAD(session_on_connect);
+RLIST_HEAD(session_on_disconnect);
 
 uint32_t
 session_create(int fd)
@@ -64,7 +64,7 @@ session_create(int fd)
 	 */
 	fiber_set_sid(fiber, sid);
 	try {
-		trigger_run(&session_on_connect);
+		trigger_run(&session_on_connect, NULL);
 	} catch (const Exception& e) {
 		fiber_set_sid(fiber, 0);
 		mh_i32ptr_remove(session_registry, &node, NULL);
@@ -80,7 +80,7 @@ session_destroy(uint32_t sid)
 		return;
 
 	try {
-		trigger_run(&session_on_disconnect);
+		trigger_run(&session_on_disconnect, NULL);
 	} catch (const Exception& e) {
 		e.log();
 	} catch (...) {
-- 
GitLab