diff --git a/include/session.h b/include/session.h index d16b0e7ba4b55d062138b93d2e33f1beb34faa2c..5aaf652589bd24d6c0764d917dccf43f346dd34a 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 fed6eef06239cea3113fef06c3ad0d48cd33184e..ad01a6cad51317dafbd67c43bd1167faab889a88 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 a0fba2f42182693a9d179034cc153b02b15f4430..1fe6e2e09b19625c4d7a8aabcb30c54356485739 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 be2f6d56066cff5f0cfae8b75d1cee970777d9a6..aff039821dea273a450127304ea08e445d5cb250 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 (...) {