From f8dcaabfbdd3b00113251d220dce231ef1696205 Mon Sep 17 00:00:00 2001 From: niubinghui Date: Fri, 6 Sep 2024 16:29:07 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E6=A2=B3=E7=90=86=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=B9=B6=E9=87=8D=E6=9E=84=E9=83=A8=E5=88=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.sh | 1 - include/lua_plugin_manage.h | 42 +- src/Makefile | 14 +- src/lpm_log.h | 22 - src/lua_binding_function.c | 576 ++++++++++++ src/lua_binding_function.h | 50 ++ src/lua_binding_functions.c | 830 ------------------ src/lua_binding_functions.h | 54 -- src/lua_plugin_binding.c | 472 ---------- src/lua_plugin_cfunc.c | 359 +++----- src/lua_plugin_chunk.c | 107 --- src/lua_plugin_data.c | 214 ----- src/lua_plugin_manage.c | 1415 ++++++++++++++++++------------ src/lua_plugin_manage_internal.h | 441 ++++------ 14 files changed, 1778 insertions(+), 2819 deletions(-) delete mode 100644 src/lpm_log.h create mode 100644 src/lua_binding_function.c create mode 100644 src/lua_binding_function.h delete mode 100644 src/lua_binding_functions.c delete mode 100644 src/lua_binding_functions.h delete mode 100644 src/lua_plugin_binding.c delete mode 100644 src/lua_plugin_chunk.c delete mode 100644 src/lua_plugin_data.c diff --git a/build.sh b/build.sh index ad8077d..1e6303a 100755 --- a/build.sh +++ b/build.sh @@ -5,4 +5,3 @@ cd - cp -rf config/* output/conf/ cp -rf include/* output/include/ -cp -rf dependence/include/stellar.h output/include/ diff --git a/include/lua_plugin_manage.h b/include/lua_plugin_manage.h index a76d785..99f1686 100644 --- a/include/lua_plugin_manage.h +++ b/include/lua_plugin_manage.h @@ -1,43 +1,17 @@ -/************************************************************************* - > File Name: lua_plugin_manage.h - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * version - * [ v0.1 ] - * 08-01 - * 1. 修改外部暴露接口 - * lua_plugin_manage_init - * lua_plugin_manage_exit - * 2. 声明数据结构 - * struct lua_plugin_manage_schema - * - * 08-09 - * 1. 修改参数函数原型, 传入参数修改为已经加载的配置信息 - ************************************************************************/ #pragma once #include "stellar/stellar.h" -struct lua_config_specific +struct lua_config_spec { - /* 插件需要使用的文件名 */ - char *config_specific_file; - /* 加载插件需要调用的函数名称 */ - char *config_specific_load_func; - /* 卸载插件需要调用的函数名称 */ - char *config_specific_unload_func; + char *spec_file_path; /* 插件需要使用的文件名 */ + char *spec_load_func_name; /* 加载插件需要调用的函数名称 */ + char *spec_unload_func_name; /* 卸载插件需要调用的函数名称 */ }; -struct lua_plugin_manage_schema; +struct lua_plugin_manage; -struct lua_plugin_manage_schema *lua_plugin_manage_init(struct stellar *st, int specific_count, struct lua_config_specific *specifics); -int lua_plugin_manage_load_one_specific(struct lua_plugin_manage_schema *schema, struct lua_config_specific *specific); -void lua_plugin_manage_exit(struct lua_plugin_manage_schema *lua_plug_mgr); +struct lua_plugin_manage *lua_plugin_manage_init(struct stellar *st, struct lua_config_spec specifics[], size_t specific_num); +void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr); -void lua_plugin_get_statistics(int plugin_id, int thread_id, int *new_success, int *new_fail, int *free_success, int *free_fail); - -void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema); \ No newline at end of file +// void debug_lua_plugin_manage_schema(struct lua_plugin_manage *schema); \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index fac74b8..a9b8b6c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,18 +5,12 @@ TARGET=libluaplugin.so # TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST -SRC := lua_plugin_data.c \ - lua_plugin_chunk.c \ - lua_plugin_cfunc.c \ - lua_binding_functions.c \ - lua_plugin_binding.c \ +SRC := lua_plugin_cfunc.c \ + lua_binding_function.c \ lua_plugin_manage.c -OBJECTS := lua_plugin_data.o \ - lua_plugin_chunk.o \ - lua_plugin_cfunc.o \ - lua_binding_functions.o \ - lua_plugin_binding.o \ +OBJECTS := lua_plugin_cfunc.o \ + lua_binding_function.o \ lua_plugin_manage.o INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include diff --git a/src/lpm_log.h b/src/lpm_log.h deleted file mode 100644 index 09b8ab4..0000000 --- a/src/lpm_log.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef LUA_PLUGIN_MANAGE_LPM_LOG_H -#define LUA_PLUGIN_MANAGE_LPM_LOG_H - -#include - -/* 简单定义一个日志输出, 可根据实际的日志输出调整定义 */ -/* define some basic log macros */ -#define LOG(level, format, ...) printf("[%s][%s]%d: " format "\n", #level, __FUNCTION__, __LINE__, ##__VA_ARGS__); -#define LOGDEBUG(...) LOG(DEBUG, __VA_ARGS__) -// #define LOGDEBUG(...) -#define LOGINFO(...) LOG(INFO, __VA_ARGS__) -// #define LOGINFO(...) -#define LOGNOTICE(...) LOG(INFO, __VA_ARGS__) -// #define LOGNOTICE(...) -#define LOGWARN(...) LOG(WARNING, __VA_ARGS__) -// #define LOGWARN(...) -#define LOGERROR(...) LOG(ERROR, __VA_ARGS__) -// #define LOGERROR(...) -#define LOGFATAL(...) LOG(FALT, __VA_ARGS__) -// #define LOGFATAL(...) - -#endif \ No newline at end of file diff --git a/src/lua_binding_function.c b/src/lua_binding_function.c new file mode 100644 index 0000000..620a49c --- /dev/null +++ b/src/lua_binding_function.c @@ -0,0 +1,576 @@ +#include +#include + +#include +#include +#include + +#include "lua_binding_function.h" + +/* ***** ***** ***** ***** ***** ***** */ +int lua_get_worker_thread_num(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 1) + { + lua_settop(L, 0); + return 0; + } + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + int thread_num = stellar_get_worker_thread_num(st); + lua_pushinteger(L, thread_num); + return 1; +} + +int lua_get_current_thread_id(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 1) + { + lua_settop(L, 0); + return 0; + } + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + int thread_id = stellar_get_current_thread_id(st); + lua_pushinteger(L, thread_id); + return 1; +} + +int lua_get_stellar_pointer(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + lua_settop(L, 0); + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + struct stellar *st = plugin_manage->st; + lua_pushlightuserdata(L, (void *)st); + return 1; +} + +/* +int lua_get_plugin_manage_pointer(struct lua_state *state) +{ + lua_settop((lua_State *)state, 0); + struct lua_plugin_manage * plugin_manage = lua_state_get_plugin_manage(state); + lua_pushlightuserdata((lua_State *)state, (void *)plugin_manage); + return 1; +} +*/ + +/* ***** ***** ***** ***** ***** ***** */ +int lua_session_plugin_regist(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA) + { + lua_settop(L, 0); + return 0; + } + + /* stack -1 */ + int plugin_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (plugin_env_ref_id == LUA_REFNIL) + plugin_env_ref_id = 0; + + /* stack -2 */ + int ctx_free_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + ctx_free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + /* stack -3 */ + int ctx_new_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + ctx_new_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + /* stack -4 */ + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + struct lua_session_plugin_env *new_plugin_env = (struct lua_session_plugin_env *)calloc(1, sizeof(struct lua_session_plugin_env)); + memset(new_plugin_env, 0, sizeof(struct lua_session_plugin_env)); + new_plugin_env->lua_ctx_new_fn_ref_id = ctx_new_fn_ref_id; + new_plugin_env->lua_ctx_free_fn_ref_id = ctx_free_fn_ref_id; + new_plugin_env->lua_plug_env_ref_id = plugin_env_ref_id; + + int plugin_id = stellar_session_plugin_register(st, lpm_ctx_new_func, lpm_ctx_free_func, (void *)new_plugin_env); + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + LL_APPEND(plugin_manage->session_plugin_env_list, new_plugin_env); + new_plugin_env->plugin_manage = plugin_manage; + + lua_settop(L, 0); + lua_pushinteger(L, plugin_id); + + return 1; +} + +int lua_packet_plugin_regist(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA) + { + lua_settop(L, 0); + return 0; + } + + /* stack -1 */ + int plugin_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (plugin_env_ref_id == LUA_REFNIL) + plugin_env_ref_id = 0; + + /* stack -2 */ + int on_packet_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + on_packet_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + /* stack -3 */ + int ip_protocol = lua_tointeger(L, -1); + lua_pop(L, 1); + + /* stack -4 */ + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + struct lua_packet_plugin_env *new_plugin_env = (struct lua_packet_plugin_env *)calloc(1, sizeof(struct lua_packet_plugin_env)); + memset(new_plugin_env, 0, sizeof(struct lua_packet_plugin_env)); + new_plugin_env->lua_plug_env_ref_id = plugin_env_ref_id; + new_plugin_env->lua_on_packet_fn_ref_id = on_packet_fn_ref_id; + + int plugin_id = stellar_packet_plugin_register(st, (unsigned char)ip_protocol, lpm_on_packet_func, (void *)new_plugin_env); + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + LL_APPEND(plugin_manage->packet_plugin_env_list, new_plugin_env); + new_plugin_env->plugin_manage = plugin_manage; + + lua_settop(L, 0); + lua_pushinteger(L, plugin_id); + + return 1; +} + +/* ***** ***** ***** ***** ***** ***** */ +int lua_session_get_type(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 1 || lua_type(L, -1) != LUA_TLIGHTUSERDATA) + { + lua_settop(L, 0); + return 0; + } + + struct session *sess = (struct session *)lua_topointer(L, -1); + lua_settop(L, 0); + if (!sess) + return 0; + + lua_pushinteger(L, (int)session_get_type(sess)); + return 1; +} + +/* ***** ***** ***** ***** ***** ***** */ +#define MQ_TYPE_PACKET 1 +#define MQ_TYPE_SESSION 2 +static int lua_plugin_manage_msg_mq_create_topic(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4 || lua_type(L, -3) != LUA_TSTRING || lua_type(L, -4) != LUA_TLIGHTUSERDATA) + { + lua_settop(L, 0); + return 0; + } + + /* stack -1 */ + int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (free_arg_ref_id == LUA_REFNIL) + free_arg_ref_id = 0; + + /* stack -2 */ + int free_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + /* stack -3 */ + char *topic_name = strdup((char *)lua_tostring(L, -1)); + lua_pop(L, 1); + + /* stack -4 */ + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + struct lua_message_free_arg *new_message_free_arg = (struct lua_message_free_arg *)calloc(1, sizeof(struct lua_message_free_arg)); + memset(new_message_free_arg, 0, sizeof(struct lua_message_free_arg)); + new_message_free_arg->lua_msg_free_fn_ref_id = free_fn_ref_id; + new_message_free_arg->lua_msg_free_arg_ref_id = free_arg_ref_id; + int topic_id = -1; + if (type == MQ_TYPE_PACKET) + stellar_packet_mq_create_topic(st, (const char *)topic_name, lpm_packet_message_free_func, new_message_free_arg); + else if (type == MQ_TYPE_SESSION) + stellar_session_mq_create_topic(st, (const char *)topic_name, lpm_session_message_free_func, new_message_free_arg); + if (topic_id >= 0) + { + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + LL_APPEND(plugin_manage->message_free_arg_list, new_message_free_arg); + new_message_free_arg->topic_id = topic_id; + new_message_free_arg->plugin_manage = plugin_manage; + lua_pop(L, 1); + } + else + { + if (new_message_free_arg) + free(new_message_free_arg); + return 0; + } + + lua_pushinteger(L, topic_id); + return 1; +} + +static int lua_plugin_manage_msg_mq_get_topic_id(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 2 || lua_type(L, -1) != LUA_TSTRING || lua_type(L, -2) != LUA_TLIGHTUSERDATA) + { + lua_settop(L, 0); + return 0; + } + + char *topic_name = strdup(lua_tostring(L, -1)); + lua_pop(L, 1); + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + int topic_id = -1; + if (type == MQ_TYPE_PACKET) + stellar_packet_mq_get_topic_id(st, (const char *)topic_name); + else if (type == MQ_TYPE_SESSION) + stellar_session_mq_get_topic_id(st, (const char *)topic_name); + if (topic_name) + free(topic_name); + + lua_pushinteger(L, topic_id); + return 1; +} + +static int lua_plugin_manage_msg_mq_update_topic(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4 || lua_type(L, -3) != LUA_TNUMBER || lua_type(L, -4) != LUA_TLIGHTUSERDATA) + goto err; + + /* stack -1 */ + int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (free_arg_ref_id == LUA_REFNIL) + free_arg_ref_id = 0; + + /* stack -2 */ + int free_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + /* stack -3 */ + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + /* stack -4 */ + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + struct lua_message_free_arg *new_message_free_arg = (struct lua_message_free_arg *)calloc(1, sizeof(struct lua_message_free_arg)); + memset(new_message_free_arg, 0, sizeof(struct lua_message_free_arg)); + new_message_free_arg->topic_id = topic_id; + new_message_free_arg->lua_msg_free_fn_ref_id = free_fn_ref_id; + new_message_free_arg->lua_msg_free_arg_ref_id = free_arg_ref_id; + int update_result = -1; + if (type == MQ_TYPE_PACKET) + update_result = stellar_packet_mq_update_topic(st, topic_id, lpm_packet_message_free_func, new_message_free_arg); + else if (type == MQ_TYPE_SESSION) + update_result = stellar_session_mq_update_topic(st, topic_id, lpm_session_message_free_func, new_message_free_arg); + if (update_result) + { + if (new_message_free_arg) + free(new_message_free_arg); + goto err; + } + + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + new_message_free_arg->plugin_manage = plugin_manage; + LL_APPEND(plugin_manage->message_free_arg_list, new_message_free_arg); + lua_settop(L, 0); + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} + +static int lua_plugin_manage_msg_mq_destory_topic(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 2) + goto err; + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + int destory_result = -1; + if (type == MQ_TYPE_PACKET) + destory_result = stellar_packet_mq_destroy_topic(st, topic_id); + else if (type == MQ_TYPE_SESSION) + destory_result = stellar_session_mq_destroy_topic(st, topic_id); + if (destory_result < 0) + goto err; + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} + +static int lua_plugin_manage_msg_mq_subscribe_topic(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA) + goto err; + + int plugin_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + int on_message_fn_ref_id = 0; + if (lua_type(L, -1) == LUA_TFUNCTION) + on_message_fn_ref_id = luaL_ref(L, -1); + else + lua_pop(L, 1); + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + struct stellar *st = (struct stellar *)lua_topointer(L, -1); + lua_settop(L, 0); + + int subscribe_result = -1; + if (type == MQ_TYPE_PACKET) + subscribe_result = stellar_packet_mq_subscribe(st, topic_id, lpm_on_packet_msg_func, plugin_id); + else if (type == MQ_TYPE_SESSION) + subscribe_result = stellar_session_mq_subscribe(st, topic_id, lpm_on_session_msg_func, plugin_id); + if (subscribe_result) + goto err; + + struct lua_on_message_fn *on_message = NULL; + struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state); + if (type == MQ_TYPE_PACKET) + on_message = hash_find_on_msg_fn(plugin_manage->on_packet_message_hashlist, topic_id, plugin_id); + else if (type == MQ_TYPE_SESSION) + on_message = hash_find_on_msg_fn(plugin_manage->on_session_message_hashlist, topic_id, plugin_id); + if (on_message) + { + on_message->lua_on_msg_fn_ref_id = on_message_fn_ref_id; + } + else + { + if (type == MQ_TYPE_PACKET) + on_message = hash_on_msg_fn_insert(plugin_manage->on_packet_message_hashlist, topic_id, plugin_id); + else if (type == MQ_TYPE_SESSION) + on_message = hash_on_msg_fn_insert(plugin_manage->on_session_message_hashlist, topic_id, plugin_id); + if (!on_message) + goto err; + else + on_message->lua_on_msg_fn_ref_id = on_message_fn_ref_id; + } + + lua_settop(L, 0); + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} + +static int lua_plugin_manage_msg_mq_publish_message(struct lua_state *state, int type) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 3) + goto err; + + int msg_ref_id = luaL_ref(L, -1); + if (msg_ref_id == LUA_REFNIL) + msg_ref_id = 0; + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + void *p = (void *)lua_topointer(L, -1); + lua_settop(L, 0); + + struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); + new_context->lua_context_ref_id = msg_ref_id; + + int publish_result = -1; + if (type == MQ_TYPE_PACKET) + publish_result = packet_mq_publish_message((struct packet *)p, topic_id, new_context); + else if (type == MQ_TYPE_SESSION) + publish_result = session_mq_publish_message((struct session *)p, topic_id, new_context); + if (publish_result) + { + luaL_unref(L, LUA_REGISTRYINDEX, new_context->lua_context_ref_id); + free(new_context); + goto err; + } + + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} + +/* ***** ***** ***** ***** ***** ***** */ +int lua_packet_mq_create_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_create_topic(state, MQ_TYPE_PACKET); +} + +int lua_packet_mq_get_topic_id(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_get_topic_id(state, MQ_TYPE_PACKET); +} + +int lua_packet_mq_update_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_update_topic(state, MQ_TYPE_PACKET); +} + +int lua_packet_mq_destory_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_destory_topic(state, MQ_TYPE_PACKET); +} + +int lua_packet_mq_subscribe_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_subscribe_topic(state, MQ_TYPE_PACKET); +} + +int lua_packet_mq_publish_message(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_publish_message(state, MQ_TYPE_PACKET); +} + +/* ***** ***** ***** ***** ***** ***** */ +int lua_session_mq_create_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_create_topic(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_get_topic_id(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_get_topic_id(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_update_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_update_topic(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_destory_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_destory_topic(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_subscribe_topic(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_subscribe_topic(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_publish_message(struct lua_state *state) +{ + return lua_plugin_manage_msg_mq_publish_message(state, MQ_TYPE_SESSION); +} + +int lua_session_mq_ignore_message(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 3) + goto err; + + int plugin_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + struct session *sess = (struct session *)lua_topointer(L, -1); + lua_settop(L, 0); + + if (session_mq_ignore_message(sess, topic_id, plugin_id)) + goto err; + + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} + +int lua_session_mq_unignore_message(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 4) + goto err; + + int plugin_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + struct session *sess = (struct session *)lua_topointer(L, -1); + lua_settop(L, 0); + + if (session_mq_unignore_message(sess, topic_id, plugin_id)) + goto err; + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + + return 1; +} + +int lua_session_mq_topic_is_active(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + if (lua_gettop(L) != 2) + goto err; + + int topic_id = lua_tointeger(L, -1); + lua_pop(L, 1); + + struct session *sess = (struct session *)lua_topointer(L, -1); + lua_settop(L, 0); + + /* 1 means active */ + if (session_mq_topic_is_active(sess, topic_id) != 1) + goto err; + lua_pushboolean(L, 1); + return 1; +err: + lua_settop(L, 0); + lua_pushboolean(L, 0); + return 1; +} \ No newline at end of file diff --git a/src/lua_binding_function.h b/src/lua_binding_function.h new file mode 100644 index 0000000..0a063ae --- /dev/null +++ b/src/lua_binding_function.h @@ -0,0 +1,50 @@ +#include "stellar/stellar.h" +#include "stellar/packet_mq.h" +#include "stellar/session.h" +#include "stellar/session_mq.h" + +#include "lua_plugin_manage_internal.h" + +/* ***** ***** ***** ***** ***** ***** */ +/* 需要注册至lua中供lua调用的所有函数原型 */ +/* 通用函数 */ +int lua_get_worker_thread_num(struct lua_state * state); +int lua_get_current_thread_id(struct lua_state * state); +int lua_get_stellar_pointer(struct lua_state * state); +// int lua_get_plugin_manage_pointer(struct lua_state *state); + +/* 注册函数 */ +int lua_session_plugin_regist(struct lua_state *state); +int lua_packet_plugin_regist(struct lua_state *state); + +/* struct session结构相关的函数 */ +int lua_session_get_type(struct lua_state *state); + +/* packet message mq相关的函数 */ +int lua_packet_mq_create_topic(struct lua_state * state); +int lua_packet_mq_get_topic_id(struct lua_state * state); +int lua_packet_mq_update_topic(struct lua_state * state); +int lua_packet_mq_destory_topic(struct lua_state * state); +int lua_packet_mq_subscribe_topic(struct lua_state * state); +int lua_packet_mq_publish_message(struct lua_state * state); + +/* session message mq相关的函数 */ +int lua_session_mq_create_topic(struct lua_state *state); +int lua_session_mq_get_topic_id(struct lua_state *state); +int lua_session_mq_update_topic(struct lua_state *state); +int lua_session_mq_destory_topic(struct lua_state *state); +int lua_session_mq_subscribe_topic(struct lua_state *state); +int lua_session_mq_publish_message(struct lua_state *state); +int lua_session_mq_topic_is_active(struct lua_state *state); +int lua_session_mq_ignore_message(struct lua_state *state); +int lua_session_mq_unignore_message(struct lua_state *state); + +/* ***** ***** ***** ***** ***** ***** */ +/* 此部分为注册至C中的lua通用函数, 实现在lua_plugin_cfunc.c中 */ +void *lpm_ctx_new_func(struct session *sess, void *plugin_env); +void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env); +void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg); +void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env); +void lpm_on_packet_func(struct packet * pkt, unsigned char ip_protocol, void * plugin_env); +void lpm_packet_message_free_func(struct packet *pkt, void * msg, void * msg_free_arg); +void lpm_on_packet_msg_func(struct packet *pkt, int topic_id, const void *msg, void * plugin_env); \ No newline at end of file diff --git a/src/lua_binding_functions.c b/src/lua_binding_functions.c deleted file mode 100644 index 791a474..0000000 --- a/src/lua_binding_functions.c +++ /dev/null @@ -1,830 +0,0 @@ -/************************************************************************* - > File Name: lua_binding_functions.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * 声明并定义所有需要在lua状态机中绑定的函数 - * version - * [ v0.1 ] - * 08-14 - * 1. 实现函数 - * 新增插件注册函数 - * int lua_plugin_manage_regist - * 新增会话相关函数 - * int lua_session_get_id - * int lua_session_set_id - * int lua_session_get_type - * int lua_session_set_type - * 新增message相关函数 - * int lua_mq_create_topic - * int lua_mq_get_topic_id - * int lua_mq_update_topic - * int lua_mq_destory_topic - * int lua_mq_subscribe_topic - * int lua_mq_topic_is_active - * int lua_mq_publish_message - * int lua_mq_ignore_message - * int lua_mq_unignore_message - * - * 08-29 - * 修改create_topic逻辑, 允许创建一个空的topic - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -#include "stellar/session.h" -#include "stellar/session_mq.h" - -int global_max_plugin_id = 0; - -/* ***** ***** ***** ***** ***** ***** */ -int lua_plugin_manage_regist(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION || - lua_type(state, -3) != LUA_TFUNCTION || lua_type(state, -4) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 取出处理第四个参数 */ - lua_getfield(state, -1, LUA_PLUGIN_ENV_DEFAULT_KEY); /* stack 4, table中取出对应结构的指针 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - struct lua_model *plugin_env = (struct lua_model *)lua_topointer(state, -1); - lua_pop(state, 2); - // debug_lua_state_stack(state, 0, "here"); - // printf("env pointer is %p\n", plugin_env); - - /* 取出处理第三个参数 */ - int ctx_free_id = luaL_ref(state, LUA_REGISTRYINDEX); /* stack 3 */ - if (ctx_free_id == LUA_REFNIL) - { - lua_settop(state, 0); - return 0; - } - - /* 取出处理第二个参数 */ - int ctx_new_id = luaL_ref(state, LUA_REGISTRYINDEX); /* stack 2 */ - if (ctx_new_id == LUA_REFNIL) - { - luaL_unref(state, LUA_REGISTRYINDEX, ctx_free_id); - lua_settop(state, 0); - return 0; - } - - /* 取出处理第一个参数 */ - struct stellar *st = (struct stellar *)lua_topointer(state, -1); /* stack 1 */ - if (!st) - { - luaL_unref(state, LUA_REGISTRYINDEX, ctx_new_id); - luaL_unref(state, LUA_REGISTRYINDEX, ctx_free_id); - lua_settop(state, 0); - return 0; - } - lua_pop(state, 1); - - /* 在stellar中注册, 获取注册id */ - int plugin_id = stellar_session_plugin_register(st, lpm_ctx_new_func, lpm_ctx_free_func, (void *)plugin_env); -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("now regist new plugin, plugin id is %d, %d, %d\n", plugin_id, ctx_new_id, ctx_free_id); -#endif - - /* TODO: 如果运行完全符合预期的话, 理论上仅有thread 0在此处需要插入新的插件, 且不应该有错误 - * 对于其他线程这里应该直接检查ref id是否一致即可, 按理说不应该再插入新插件 - * 后续可以修改为根据线程号执行不同的处理流程 - */ - /* 如果在其他线程中已经完成过注册 */ - struct lua_plugin *search_plugin = NULL; - while ((search_plugin = utarray_next(plugin_env->plugin_array, search_plugin))) - { - if (search_plugin->plugin_id == plugin_id) - { - /* 初始化过程中已经进行过加载 */ - if (search_plugin->ctx_new_ref != ctx_new_id || search_plugin->ctx_free_ref != ctx_free_id) - { - LOGERROR("regist plugin, same id with different function ref"); - LOGERROR("plugin id %d, registed %d, %d, new ref %d, %d", plugin_id, - search_plugin->ctx_new_ref, search_plugin->ctx_free_ref, - ctx_new_id, ctx_free_id); - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - lua_pushinteger(state, plugin_id); - return 1; - } - } - /* 统计记录一下当前最大的plugin_id编号 */ - if (plugin_id > global_max_plugin_id) - global_max_plugin_id = plugin_id; - - /* 将注册完成的新插件插入到队列中 */ - struct lua_plugin new_plugin; - memset(&new_plugin, 0, sizeof(new_plugin)); - new_plugin.plugin_id = plugin_id; - new_plugin.ctx_new_ref = ctx_new_id; - new_plugin.ctx_free_ref = ctx_free_id; - utarray_push_back(plugin_env->plugin_array, &new_plugin); - plugin_env->plugin_count += 1; - global_schema->plugin_count += 1; - - lua_settop(state, 0); - lua_pushinteger(state, plugin_id); - - return 1; -} - -/* ***** ***** ***** ***** ***** ***** */ -#if 0 -int lua_session_get_id(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 1) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - lua_settop(state, 0); - return 0; - } - lua_pop(state, 1); - - lua_pushinteger(state, session_get_id(sess)); - return 1; -} - -int lua_session_set_id(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 2) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - int setid = lua_tointeger(state, -1); - lua_pop(state, 1); - struct session *sess = (struct session *)lua_topointer(state, -1); - lua_pop(state, 1); - - session_set_id(sess, setid); - return 0; -} - -int lua_session_set_type(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 2) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - int settype = lua_tointeger(state, -1); - lua_pop(state, 1); - struct session *sess = (struct session *)lua_topointer(state, -1); - lua_pop(state, 1); - - session_set_type(sess, settype); - return 0; -} -#endif - -int lua_session_get_type(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 1) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - lua_settop(state, 0); - return 0; - } - lua_pop(state, 1); - - lua_pushinteger(state, (int)session_get_type(sess)); - return 1; -} - -/* ***** ***** ***** ***** ***** ***** */ -/* - * TODO: 未完整考虑线程安全问题, 例如 - * 多个线程同时注册一个topic, 是否需要做处理等。 - */ -static UT_icd lua_plugin_mq_icd = {sizeof(struct lua_plugin_mq), NULL, NULL, NULL}; - -int lua_mq_create_topic(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (((lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION) && - (lua_type(state, -1) != LUA_TNIL || lua_type(state, -2) != LUA_TNIL)) || - lua_type(state, -3) != LUA_TSTRING || lua_type(state, -4) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 创建对该table的引用, 防止该table被回收 */ - int private_ref = 0; - if (lua_type(state, -1) != LUA_TNIL) - { - private_ref = luaL_ref(state, LUA_REGISTRYINDEX); /* stack top function */ - if (private_ref == LUA_REFNIL) - { - lua_settop(state, 0); - return 0; - } - } - - /* 导出free message的调用函数 */ - int free_ref = 0; - if (lua_type(state, -1) != LUA_TFUNCTION) - { - free_ref = luaL_ref(state, LUA_REGISTRYINDEX); - if (free_ref == LUA_REFNIL) - { - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - lua_settop(state, 0); - return 0; - } - } - - /* 出栈队列名称 */ - char *name = strdup((char *)lua_tostring(state, -1)); - lua_pop(state, 1); - - /* 出栈传入的stellar */ - struct stellar *st = (struct stellar *)lua_topointer(state, -1); - if (!st) - { - luaL_unref(state, LUA_REGISTRYINDEX, free_ref); - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - if (name) - free(name); - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - /* 插入新的元素 */ - int topic_id = -1; - if (private_ref && free_ref) - { - struct lua_message_mq new_mq; - memset(&new_mq, 0, sizeof(new_mq)); - utarray_push_back(global_schema->message_mq_array, &new_mq); - /* 从队列尾部取出最后一个元素 */ - struct lua_message_mq *mq = utarray_eltptr(global_schema->message_mq_array, (utarray_len(global_schema->message_mq_array) - 1)); - mq->freemessage_ref = free_ref; - mq->mq_private_ref = private_ref; - /* 调用stellar中mq的topic创建函数 */ - /* BugFix: 仔细看了代码, 在stellar中没有对name做拷贝处理, 这里name不能释放 */ - topic_id = stellar_session_mq_create_topic(st, (const char *)name, lpm_message_free_func, mq); - - /* 创建topic失败, 还原创建topic之前的状态 */ - if (topic_id < 0) - { - utarray_pop_back(global_schema->message_mq_array); - luaL_unref(state, LUA_REGISTRYINDEX, free_ref); - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - if (name) - free(name); - return 0; - } - global_schema->mq_count += 1; - - lua_rawgeti(state, LUA_REGISTRYINDEX, mq->mq_private_ref); -#if 0 - /* 不检查了, 直接覆盖 */ - /* 在传入的table中检查是否存在与mq_private_env同名的元素 */ - lua_getfield(state, -1, LUA_MQ_ENV_DEFAULT_KEY); /* stack top nil */ - if (lua_type(state, -1) != LUA_TNIL) { - lua_settop(state, 0); - return 0; - } - lua_pop(state, 1); /* stack top table */ -#endif - /* 在该table中加入新元素 */ - lua_pushlightuserdata(state, (void *)mq); /* stack top new_mq */ - lua_setfield(state, -2, LUA_MQ_ENV_DEFAULT_KEY); /* stack top table */ - mq->topic_id = topic_id; - } - else - { - /* 只是创建一个新的空topic */ - topic_id = stellar_session_mq_create_topic(st, (const char *)name, NULL, NULL); - if (topic_id < 0) - { - if (name) - free(name); - return 0; - } - } - - lua_settop(state, 0); - lua_pushinteger(state, topic_id); - - return 1; -} - -int lua_mq_get_topic_id(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 2) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TSTRING || lua_type(state, -2) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 出栈队列名称 */ - char *name = strdup(lua_tostring(state, -1)); - lua_pop(state, 1); - - /* 出栈传入的stellar */ - struct stellar *st = (struct stellar *)lua_topointer(state, -1); - if (!st) - { - if (name) - free(name); - return 0; - } - lua_pop(state, 1); - - int topic_id = stellar_session_mq_get_topic_id(st, (const char *)name); - if (name) - free(name); - - lua_settop(state, 0); - lua_pushinteger(state, topic_id); - return 1; -} - -int lua_mq_update_topic(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION || - lua_type(state, -3) != LUA_TNUMBER || lua_type(state, -4) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 创建对该table的引用, 防止该table被回收 */ - int private_ref = luaL_ref(state, LUA_REGISTRYINDEX); /* stack top function */ - if (private_ref == LUA_REFNIL) - { - lua_settop(state, 0); - return 0; - } - - /* 导出free message的调用函数 */ - int free_ref = luaL_ref(state, LUA_REGISTRYINDEX); - if (free_ref == LUA_REFNIL) - { - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - lua_settop(state, 0); - return 0; - } - - /* topic_id */ - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - /* 出栈传入的stellar */ - struct stellar *st = (struct stellar *)lua_topointer(state, -1); - if (!st) - { - luaL_unref(state, LUA_REGISTRYINDEX, free_ref); - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - struct lua_message_mq *mq = search_message_mq_by_id(topic_id); - if (!mq || mq->topic_id != topic_id) - { - /* 如果topic不是lua创建的, 需要加入管理 */ - struct lua_message_mq new_mq; - memset(&new_mq, 0, sizeof(new_mq)); - utarray_push_back(global_schema->message_mq_array, &new_mq); - mq = utarray_eltptr(global_schema->message_mq_array, (utarray_len(global_schema->message_mq_array) - 1)); - - if (stellar_session_mq_update_topic(st, topic_id, lpm_message_free_func, mq)) - { - utarray_pop_back(global_schema->message_mq_array); - luaL_unref(state, LUA_REGISTRYINDEX, free_ref); - luaL_unref(state, LUA_REGISTRYINDEX, private_ref); - return 0; - } -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("update topic, id %d %d %d", topic_id, private_ref, free_ref); -#endif - - mq->freemessage_ref = free_ref; - mq->mq_private_ref = private_ref; - mq->topic_id = topic_id; - lua_pushboolean(state, 1); - return 1; - } - else - { - /* 本身是由lua创建的 */ - /* 更新private_ref */ - lua_rawgeti(state, LUA_REGISTRYINDEX, private_ref); - lua_pushlightuserdata(state, (void *)mq); /* stack top new_mq */ - lua_setfield(state, -2, LUA_MQ_ENV_DEFAULT_KEY); /* stack top table */ - // luaL_unref(state, LUA_REGISTRYINDEX, mq->mq_private_ref); - mq->mq_private_ref = private_ref; - /* 更新free function ref */ - // luaL_unref(state, LUA_REGISTRYINDEX, mq->freemessage_ref); - mq->freemessage_ref = free_ref; - -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("update topic, id %d %d %d", topic_id, private_ref, free_ref); -#endif - } - - lua_settop(state, 0); - lua_pushboolean(state, 1); - - return 1; -} - -int lua_mq_destory_topic(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 2) - { - lua_settop(state, 0); - return 0; - } - - /* topic_id */ - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - /* 出栈传入的stellar */ - struct stellar *st = (struct stellar *)lua_topointer(state, -1); - if (!st) - { - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - /* 优先调用C函数进行卸载 */ - if (stellar_session_mq_destroy_topic(st, topic_id) < 0) - { - return 0; - } - - /* 不方便删除, 将id置为-1, 确保匹配不到 */ - struct lua_message_mq *mq = search_message_mq_by_id(topic_id); - if (mq) - { - mq->topic_id = -1; - luaL_unref(state, LUA_REGISTRYINDEX, mq->mq_private_ref); - luaL_unref(state, LUA_REGISTRYINDEX, mq->freemessage_ref); - mq->freemessage_ref = 0; - mq->mq_private_ref = 0; - } - - lua_pushboolean(state, 1); - return 1; -} - -int lua_mq_subscribe_topic(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TFUNCTION || - lua_type(state, -3) != LUA_TNUMBER || lua_type(state, -4) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 读取参数 */ - int plugin_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - int on_message_ref = luaL_ref(state, LUA_REGISTRYINDEX); - if (on_message_ref == LUA_REFNIL) - { - lua_settop(state, 0); - return 0; - } - - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - struct stellar *st = (struct stellar *)lua_topointer(state, -1); - if (!st) - { - lua_settop(state, 0); - return 0; - } - lua_pop(state, 1); - - lua_settop(state, 0); - if (stellar_session_mq_subscribe(st, topic_id, lpm_on_session_msg_func, plugin_id)) - { - - /* 订阅失败, 返回false */ - lua_pushboolean(state, 0); - } - else - { - struct lua_plugin *plugin = search_plugin_by_id(plugin_id); - if (plugin) - { - if (!plugin->sub_topic_array) - { - /* 该插件尚未注册任何topic, 注册第一个topic时将创建接收的topic列表 */ - utarray_new(plugin->sub_topic_array, &lua_plugin_mq_icd); - } - else - { - /* 如果该插件中之前已经订阅过该消息, 更新message函数 */ - struct lua_plugin_mq *mq = NULL; - while ((mq = utarray_next(plugin->sub_topic_array, mq))) - { - if (mq->topic_id == topic_id) - { - luaL_unref(state, LUA_REGISTRYINDEX, mq->onmessage_ref); - mq->onmessage_ref = on_message_ref; - lua_pushboolean(state, 1); - return 1; - } - } - } - - struct lua_plugin_mq new_mq; - memset(&new_mq, 0, sizeof(new_mq)); - new_mq.topic_id = topic_id; - new_mq.onmessage_ref = on_message_ref; - utarray_push_back(plugin->sub_topic_array, &new_mq); - } - /* 订阅成功, 返回true */ - lua_pushboolean(state, 1); - } - - return 1; -} - -int lua_mq_publish_message(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 3) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TNUMBER || - lua_type(state, -3) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 倒序依次获取参数 */ - int mess_ref = luaL_ref(state, LUA_REGISTRYINDEX); - if (mess_ref == LUA_REFNIL) - { - lua_settop(state, 0); - return 0; - } - - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - luaL_unref(state, LUA_REGISTRYINDEX, mess_ref); - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - /* 创建一段数据引用 */ - struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); - if (__glibc_unlikely(!new_context)) - { - luaL_unref(state, LUA_REGISTRYINDEX, mess_ref); - return 0; - } - new_context->context_ref_id = mess_ref; - - /* 调用C接口发布消息 */ - if (session_mq_publish_message(sess, topic_id, new_context)) - { - luaL_unref(state, LUA_REGISTRYINDEX, new_context->context_ref_id); - free(new_context); - lua_pushboolean(state, 0); - } - else - { - lua_pushboolean(state, 1); - } - - return 1; -} - -int lua_mq_ignore_message(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TNUMBER || - lua_type(state, -3) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 倒序获取参数 */ - int plugin_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - if (session_mq_ignore_message(sess, topic_id, plugin_id)) - lua_pushboolean(state, 0); - else - lua_pushboolean(state, 1); - - return 1; -} - -int lua_mq_unignore_message(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TNUMBER || - lua_type(state, -3) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 倒序获取参数 */ - int plugin_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - if (session_mq_unignore_message(sess, topic_id, plugin_id)) - lua_pushboolean(state, 0); - else - lua_pushboolean(state, 1); - - return 1; -} - -int lua_mq_topic_is_active(lua_State *state) -{ - /* 参数个数检查 */ - if (lua_gettop(state) != 4) - { - lua_settop(state, 0); - return 0; - } - - /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA) - { - lua_settop(state, 0); - return 0; - } - - /* 倒序获取参数 */ - int topic_id = lua_tointeger(state, -1); - lua_pop(state, 1); - - struct session *sess = (struct session *)lua_topointer(state, -1); - if (!sess) - { - lua_settop(state, 0); - return 0; - } - lua_settop(state, 0); - - /* 1 means active */ - if (session_mq_topic_is_active(sess, topic_id) == 1) - lua_pushboolean(state, 1); - else - lua_pushboolean(state, 0); - - return 1; -} \ No newline at end of file diff --git a/src/lua_binding_functions.h b/src/lua_binding_functions.h deleted file mode 100644 index b80c074..0000000 --- a/src/lua_binding_functions.h +++ /dev/null @@ -1,54 +0,0 @@ -/************************************************************************* - > File Name: lua_binding_functions.h - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * 声明并定义所有需要在lua状态机中绑定的函数 - * version - * [ v0.1 ] - * 08-14 - * 1. 新增函数声明 - * 新增插件注册函数 - * int lua_plugin_manage_regist - * 新增会话相关函数 - * int lua_session_get_id - * int lua_session_set_id - * int lua_session_get_type - * int lua_session_set_type - * 新增message相关函数 - * int lua_mq_create_topic - * int lua_mq_get_topic_id - * int lua_mq_update_topic - * int lua_mq_destory_topic - * int lua_mq_subscribe_topic - * int lua_mq_topic_is_active - * int lua_mq_publish_message - * int lua_mq_ignore_message - * int lua_mq_unignore_message - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -/* 需要注册至lua中供lua调用的所有函数原型 */ -int lua_plugin_manage_regist(lua_State *state); - -/* 与struct session结构相关的函数 */ -#if 0 -int lua_session_get_id(lua_State *state); -int lua_session_set_id(lua_State *state); -int lua_session_set_type(lua_State *state); -#endif -int lua_session_get_type(lua_State *state); - -/* 与stellar message mq相关的函数 */ -int lua_mq_create_topic(lua_State * state); -int lua_mq_get_topic_id(lua_State * state); -int lua_mq_update_topic(lua_State * state); -int lua_mq_destory_topic(lua_State * state); -int lua_mq_subscribe_topic(lua_State * state); -int lua_mq_topic_is_active(lua_State * state); -int lua_mq_publish_message(lua_State * state); -int lua_mq_ignore_message(lua_State * state); -int lua_mq_unignore_message(lua_State * state); diff --git a/src/lua_plugin_binding.c b/src/lua_plugin_binding.c deleted file mode 100644 index 083da96..0000000 --- a/src/lua_plugin_binding.c +++ /dev/null @@ -1,472 +0,0 @@ -/************************************************************************* - > File Name: lua_plugin_binding.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * version - * [ v0.1 ] - * 08 -02 - * 1. 实现函数 - * int lua_cbinding_function; - * int lua_cbinding_function_remove; - * int lua_cbinding_data; - * int lua_cbinding_data_remove; - * int lua_cbinding_functions; - * int lua_cbinding_datas; - * int lua_plugin_manage_regist; - * ** 注册函数lua_plugin_manage_session_regist还需要补充 - * - * 08-12 - * 1. 修改函数lua_cbinding_function, 参数与lua_cbinding_data保持统一 - * 2. 修改部分函数返回值, 使用枚举代替错误码返回值, 方便统一处理 - * - * 08-14 - * 1. 将所有待注册函数移动至新文件中, 不再此文件中实现 - ************************************************************************/ -#include "lua_plugin_manage_internal.h" -#include "lua_binding_functions.h" - -#include -#include - -/* 需要注册至状态机中的函数定义在链表中, 会依次完成注册 */ -struct lua_binding_function lua_bind_functions[] = { - {lua_plugin_manage_regist, "register", "plugin_manage"}, - // {lua_session_get_id, "getid", "session"}, - // {lua_session_set_id, "setid", "session"}, - {lua_session_get_type, "gettype", "session"}, - // {lua_session_set_type, "settype", "session"}, - {lua_mq_create_topic, "createtopic", "message"}, - {lua_mq_get_topic_id, "gettopicid", "message"}, - {lua_mq_update_topic, "updatetopic", "message"}, - {lua_mq_destory_topic, "destorytopic", "message"}, - {lua_mq_subscribe_topic, "subscribetopic", "message"}, - {lua_mq_topic_is_active, "topicisactive", "message"}, - {lua_mq_publish_message, "publishmessage", "message"}, - {lua_mq_ignore_message, "ignoremessage", "message"}, - {lua_mq_unignore_message, "unignoremessage", "message"}, - {NULL, NULL, NULL}, -}; - -/* 需要注册至状态机中的数据定义在链表中, 会依次完成注册 */ -/* 为了实现注册过程的统一, 所有数据类型均使用string作为value格式 */ -struct lua_binding_data lua_bind_datas[] = { - {DATATYPE_BOOL, "true", "test_data_bool", "plugin_manage"}, - {DATATYPE_INT, "1000", "test_data_int", "plugin_manage"}, - {DATATYPE_NUM, "100.001", "test_data_double", "plugin_manage"}, - {DATATYPE_STRING, "this is a string test", "test_data_string", "plugin_manage"}, - {DATATYPE_END, NULL, NULL, NULL}, -}; - -/* 向lua状态机中注册一个函数 */ -int lua_cbinding_function(lua_State *state, struct lua_binding_function *function); -/* 从lua状态机中移除一个已经注册的函数 */ -int lua_cbinding_function_remove(lua_State *state, const char *function_name, const char *space_name); -/* 将一个全局数据注册至状态机中 */ -int lua_cbinding_data(lua_State *state, struct lua_binding_data *data); -/* 从状态机中移除一个已经注册的全局数据 */ -int lua_cbinding_data_remove(lua_State *state, const char *data_name, const char *space_name); - -/* - * Function: lua_cbinding_function - * Input: | lua_State * | state | 需要注册函数的状态机 - * | struct lua_binding_function * | function | 需要绑定的function函数结构 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 将一个C函数注册至lua中 - */ -int lua_cbinding_function( - lua_State *state, - struct lua_binding_function *bind_function) -{ - if (__glibc_unlikely(!state || !bind_function)) - return PARAM_ERR; - if (__glibc_unlikely(!bind_function->function || !bind_function->function_name)) - return PARAM_ERR; -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("bind function to state, function %p, name %s, spacename %s", - bind_function->function, - bind_function->function_name, - (bind_function->space_name) ? bind_function->space_name : "no"); -#endif - - if (bind_function->space_name) - { - /* 包含space_name, 调用时为 space_name.function_name */ - lua_getglobal(state, bind_function->space_name); - if (lua_gettop(state) == 0 || lua_type(state, -1) == LUA_TNIL) - { - /* 没有该命名空间, 创建一个 */ - lua_newtable(state); - lua_setglobal(state, bind_function->space_name); - lua_settop(state, 0); - lua_getglobal(state, bind_function->space_name); - } - else - { - /* 该全局已经存在 */ - if (lua_type(state, -1) != LUA_TTABLE) - { - /* spacename已经被占用, 并且不是table, 无法插入数据 */ - lua_settop(state, 0); - return BIND_NAMESPACE_TYPE_ERR; - } - - lua_getfield(state, -1, bind_function->function_name); - if (lua_type(state, -1) != LUA_TNIL) - { - /* 在待插入的global table中存在与function_name重名的成员 */ - lua_settop(state, 0); - return BIND_FUNCTION_TYPE_ERR; - } - lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */ - } - - lua_pushcfunction(state, bind_function->function); - lua_setfield(state, -2, bind_function->function_name); - } - else - { - lua_getglobal(state, bind_function->function_name); - if (lua_type(state, -1) != LUA_TNIL) - { - /* 存在与function_name重名的全局成员 */ - lua_settop(state, 0); - return BIND_FUNCTION_TYPE_ERR; - } - lua_pop(state, 1); - - /* 不包含space_name, 调用时直接使用function_name调用 */ - lua_pushcfunction(state, bind_function->function); - lua_setglobal(state, bind_function->function_name); - } - - lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return SUCCESS; -} - -/* - * Function: lua_cbinding_function_remove - * Input: | lua_State * | state | 需要删除注册函数的状态机 - * | const char * | function_name | 需要删除的函数名称 - * | const char * | space_name | 需要删除的命名空间名称 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 从状态机中删除一个C注册的函数, 删除过程中将该函数在lua状态的引用置为nil - */ -int lua_cbinding_function_remove( - lua_State *state, - const char *function_name, - const char *space_name) -{ - if (__glibc_unlikely(!state || !function_name)) - return PARAM_ERR; - - if (space_name) - { - /* 检查该命名空间是否存在 */ - lua_getglobal(state, space_name); - if (lua_type(state, -1) != LUA_TTABLE) - { - /* 命名空间存在且不是table */ - lua_settop(state, 0); - return BIND_NAMESPACE_TYPE_ERR; - } - /* 检查该命名空间内是否存在function_name */ - lua_getfield(state, -1, function_name); - if (lua_type(state, -1) != LUA_TFUNCTION) - { - /* 命名空间存在内部元素名称为function_name, 但是类型不符 */ - lua_settop(state, 0); - return BIND_FUNCTION_TYPE_ERR; - } - /* 删除该函数 */ - lua_pop(state, 1); - lua_pushnil(state); - lua_setfield(state, -2, function_name); - } - else - { - /* 获取全局数据, 检查function_name */ - lua_getglobal(state, function_name); - if (lua_type(state, -1) != LUA_TFUNCTION) - { - /* 类型不符 */ - lua_settop(state, 0); - return BIND_FUNCTION_TYPE_ERR; - } - /* 删除该函数 */ - lua_pop(state, 1); - lua_pushnil(state); - lua_setglobal(state, function_name); - } - - lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return SUCCESS; -} - -/* - * Function: lua_cbinding_data - * Input: | lua_State * | state | 需要注册数据的状态机 - * | struct lua_binding_data * | data | 需要注册至状态机中的数据 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 将一个变量注册至lua状态机中 - */ -int lua_cbinding_data( - lua_State *state, - struct lua_binding_data *data) -{ - if (__glibc_unlikely(!state || !data)) - { - return PARAM_ERR; - } - enum DATATYPE data_type = data->data_type; - char *value = data->data_value; - char *data_name = data->data_name; - char *space_name = data->space_name; - if (__glibc_unlikely(!value || !data_name)) - return PARAM_ERR; -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("bind data to state, type %d, data %s, name %s, spacename %s", - data_type, value, data_name, (space_name) ? space_name : "no"); -#endif - - if (space_name) - { - /* 包含space_name */ - lua_getglobal(state, space_name); - if (lua_gettop(state) == 0 || lua_type(state, -1) == LUA_TNIL) - { - /* 没有该命名空间, 创建一个 */ - lua_newtable(state); - lua_setglobal(state, space_name); - lua_settop(state, 0); - lua_getglobal(state, space_name); - } - else - { - /* 该全局已经存在 */ - if (lua_type(state, -1) != LUA_TTABLE) - { - /* spacename已经被占用, 并且不是table, 无法插入数据 */ - lua_settop(state, 0); - return BIND_NAMESPACE_TYPE_ERR; - } - - lua_getfield(state, -1, data_name); - if (lua_type(state, -1) != LUA_TNIL) - { - /* 在待插入的global table中存在与function_name重名的成员 */ - lua_settop(state, 0); - return BIND_DATA_TYPE_ERR; - } - lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */ - } - - /* 不同类型需要使用不同的入栈函数 */ - switch (data_type) - { - case DATATYPE_BOOL: - if (strstr(value, "true") || strstr(value, "TRUE")) - lua_pushboolean(state, 1); - else if (strstr(value, "false") || strstr(value, "FALSE")) - lua_pushboolean(state, 0); - break; - case DATATYPE_INT: - lua_pushinteger(state, atoi(value)); - break; - case DATATYPE_NUM: - lua_pushnumber(state, (lua_Number)atof(value)); - break; - case DATATYPE_STRING: - lua_pushstring(state, (const char *)value); - break; - default: - /* 未识别的类型 */ - lua_settop(state, 0); - return BIND_DATA_TYPE_UNKNOWN; - } - lua_setfield(state, -2, data_name); - } - else - { - lua_getglobal(state, data_name); - if (lua_type(state, -1) != LUA_TNIL) - { - lua_settop(state, 0); - /* 存在与data_name重名的全局成员 */ - return BIND_DATA_TYPE_ERR; - } - lua_pop(state, 1); - - /* 不同类型需要使用不同的入栈函数 */ - switch (data_type) - { - case DATATYPE_BOOL: - if (strstr(value, "true") || strstr(value, "TRUE")) - lua_pushboolean(state, 1); - else if (strstr(value, "false") || strstr(value, "FALSE")) - lua_pushboolean(state, 0); - break; - case DATATYPE_INT: - lua_pushinteger(state, atoi(value)); - break; - case DATATYPE_NUM: - lua_pushnumber(state, (lua_Number)atof(value)); - break; - case DATATYPE_STRING: - lua_pushstring(state, (const char *)value); - break; - default: - /* 未识别的类型 */ - lua_settop(state, 0); - return BIND_DATA_TYPE_UNKNOWN; - } - lua_setglobal(state, data_name); - } - - lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return SUCCESS; -} - -/* - * Function: lua_cbinding_data_remove - * Input: | lua_State * | state | 需要删除注册数据的状态机 - * | const char * | data_name | 需要删除的数据名称 - * | const char * | space_name | 需要删除的命名空间名称 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 从状态机中删除一个C注册的数据, 删除过程中将该名称在lua状态的引用置为nil - */ -int lua_cbinding_data_remove( - lua_State *state, - const char *data_name, - const char *space_name) -{ - if (__glibc_unlikely(!state || !data_name)) - return PARAM_ERR; - - if (space_name) - { - /* 检查该命名空间是否存在 */ - lua_getglobal(state, space_name); - if (lua_type(state, -1) != LUA_TTABLE) - { - /* 命名空间存在且不是table */ - lua_settop(state, 0); - return BIND_NAMESPACE_TYPE_ERR; - } - /* 检查该命名空间内是否存在data_name */ - lua_getfield(state, -1, data_name); - int data_type = lua_type(state, -1); - if (data_type != LUA_TSTRING && data_type != LUA_TNUMBER && data_type != LUA_TBOOLEAN) - { - /* 命名空间存在内部元素名称为data_name, 但是类型不符 */ - lua_settop(state, 0); - return BIND_DATA_TYPE_ERR; - } - else if (data_type == LUA_TNIL) - { - /* 没有该名称的元素 */ - lua_settop(state, 0); - return SUCCESS; - } - /* 删除该函数 */ - lua_pop(state, 1); - lua_pushnil(state); - lua_setfield(state, -2, data_name); - } - else - { - /* 获取全局数据, 检查function_name */ - lua_getglobal(state, data_name); - int data_type = lua_type(state, -1); - if (data_type != LUA_TSTRING && data_type != LUA_TNUMBER && data_type != LUA_TBOOLEAN) - { - /* 类型不符 */ - lua_settop(state, 0); - return BIND_DATA_TYPE_ERR; - } - else if (data_type == LUA_TNIL) - { - /* 没有该名称的元素 */ - lua_settop(state, 0); - return SUCCESS; - } - /* 删除该函数 */ - lua_pop(state, 1); - lua_pushnil(state); - lua_setglobal(state, data_name); - } - - lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return SUCCESS; -} - -/* - * Function: lua_cbinding_functions - * Input: | lua_State * | state | 需要绑定函数的状态机实例 - * Output: - * Return: | -1 | 参数错误 - * | 0 | 成功 - * | >0 | 绑定出错的数据数量 - * Description: 绑定所有需要在lua中调用的C函数 - */ -int lua_cbinding_functions(lua_State *state) -{ - if (__glibc_unlikely(!state)) - return PARAM_ERR; - int bind_function_count = sizeof(lua_bind_functions) / sizeof(struct lua_binding_function); - - int bind_ret = 0; - int failed_count = 0; - for (int i = 0; i < bind_function_count; ++i) - { - if (lua_bind_functions[i].function && lua_bind_functions[i].function_name) - { - bind_ret = lua_cbinding_function(state, &lua_bind_functions[i]); - if (bind_ret) - { - LOGERROR("binding function failed, ret is %d, function name is %s\n", bind_ret, lua_bind_functions[i].function_name); - failed_count += 1; - } - } - } - return failed_count; -} - -/* - * Function: lua_cbinding_datas - * Input: | lua_State * | state | 需要绑定数据的状态机实例 - * Output: - * Return: | -1 | 参数错误 - * | 0 | 成功 - * | >0 | 绑定出错的数据数量 - * Description: 绑定所有data数据 - */ -int lua_cbinding_datas(lua_State *state) -{ - if (__glibc_unlikely(!state)) - return -1; - int bind_data_count = sizeof(lua_bind_datas) / sizeof(struct lua_binding_data); - - int bind_ret = 0; - int failed_count = 0; - for (int i = 0; i < bind_data_count; ++i) - { - if (lua_bind_datas[i].data_value && lua_bind_datas[i].data_name) - { - bind_ret = lua_cbinding_data(state, &lua_bind_datas[i]); - if (bind_ret) - { - LOGERROR("binding data failed, ret is %d, data is [%s]%s", bind_ret, lua_bind_datas[i].data_name, lua_bind_datas[i].data_value); - failed_count += 1; - } - } - } - return failed_count; -} diff --git a/src/lua_plugin_cfunc.c b/src/lua_plugin_cfunc.c index 04603c8..c3363a1 100644 --- a/src/lua_plugin_cfunc.c +++ b/src/lua_plugin_cfunc.c @@ -1,266 +1,183 @@ -/************************************************************************* - > File Name: lua_plugin_cfunc.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ +#include "lua_binding_function.h" -/************************************************************************* - * version - * [ v0.1 ] - * 08-06 - * 1. 实现函数 - * void *lpm_ctx_new_func; - * void lpm_ctx_free_func; - * - * 08-13 - * 1. 由于context结构体修改, 部分函数调用及处理逻辑需要同步修改 - * - * 08-15 - * 1. 实现函数 - * void lpm_message_free_func - * void lpm_on_session_msg_func - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -#include "stellar/session.h" - -/* 内存分配过程中可能存在内存浪费的情况, 其他即使不是Lua的插件也分配了内存 */ -/* 但是从调用的角度来说能够提高访问速度, 不需要做ID映射, 浪费内存也是以B为单位 */ -struct lua_plugin_statistics *global_plugin_statistics = NULL; - -/* - * Function: lpm_ctx_new_func - * Input: | struct session * | sess | 会话信息 - * | void * | plugin_env | 插件运行环境 - * Output: - * Return: | NULL | 运行函数错误 - * | pointer | 运行插件上的ctx_new函数成功, 返回context - * Description: 与C插件管理器保持一致的ctx_new_func - */ -void *lpm_ctx_new_func( - struct session *sess, - void *plugin_env) +void *lpm_ctx_new_func(struct session *sess, void *plugin_env) { - if (__glibc_unlikely(!sess || !plugin_env)) + if (!plugin_env) return NULL; - struct lua_model *env = (struct lua_model *)plugin_env; + struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env; + struct lua_plugin_manage *plugin_manage = env->plugin_manage; + struct stellar *st = plugin_manage->st; - /* 获取插件ID并找到该插件 */ - int plugin_id = session_get_current_plugin_id(sess); - // int plugin_id = 1; - struct lua_plugin *plugin = NULL; - while ((plugin = utarray_next(env->plugin_array, plugin))) - { - if (plugin->plugin_id == plugin_id) - break; - } - // LOGDEBUG("%d call plugin id %d, ref %d\n", plugin_id, plugin->plugin_id, plugin->ctx_new_ref); - if (!plugin || plugin->plugin_id != plugin_id) - /* 未找到该插件 */ - return NULL; - - /* 获取当前的线程id并找到该线程对应的state */ - int thread_id = session_get_current_thread_id(sess); - if (thread_id > global_schema->state_count) - return NULL; - lua_State *state = global_schema->thread_state[thread_id]; + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = (struct lua_state *)plugin_manage->state[thread_id]; struct lua_context *new_context = lua_context_new(state); - if (__glibc_unlikely(!new_context)) - /* 创建新的context失败 */ - return NULL; - - int statisitc_id = thread_id * global_max_plugin_id + plugin_id; struct lua_cdata param[3] = {0}; - param[0].cdata_type = DATATYPE_POINTER; - param[0].cdata_pointer = sess; - param[1].cdata_type = DATATYPE_TABLE; - param[1].cdata_table = env->private_env_ref; - param[2].cdata_type = DATATYPE_CONTEXT; - param[2].cdata_context = new_context; + param[0].type = DATATYPE_POINTER; + param[0].pointer = sess; + param[1].type = DATATYPE_TABLE; + param[1].table = env->lua_plug_env_ref_id; + param[2].type = DATATYPE_CONTEXT; + param[2].context = new_context; - if (lua_chunk_execute(state, plugin->ctx_new_ref, 3, param, 0, NULL)) + if (lua_chunk_execute(state, env->lua_ctx_new_fn_ref_id, param, 3, NULL, 0, NULL, 0)) { - /* 脚本执行失败 */ - ++global_plugin_statistics[statisitc_id].new_failed_count; - lua_context_free(state, new_context); + lua_context_free(new_context); return NULL; } - ++global_plugin_statistics[statisitc_id].new_success_count; - return (void *)new_context; } -/* - * Function: lpm_ctx_free_func - * Input: | struct session * | sess | 会话信息 - * | void * | sess_ctx | 会话中的私有数据 - * | void * | plugin_env | 插件运行环境 - * Output: - * Return: - * Description: 与C插件管理器保持一致的ctx_free_func - */ -void lpm_ctx_free_func( - struct session *sess, - void *sess_ctx, - void *plugin_env) +void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env) { - if (__glibc_unlikely(!sess || !sess_ctx || !plugin_env)) + if (!plugin_env) return; - struct lua_model *env = (struct lua_model *)plugin_env; + struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env; + struct lua_plugin_manage *plugin_manage = env->plugin_manage; + struct stellar *st = plugin_manage->st; - /* 获取插件ID并找到该插件 */ - int plugin_id = session_get_current_plugin_id(sess); - // int plugin_id = 1; - struct lua_plugin *plugin = NULL; - while ((plugin = utarray_next(env->plugin_array, plugin))) - { - if (plugin->plugin_id == plugin_id) - break; - } - if (!plugin || plugin->plugin_id != plugin_id) - /* 未找到该插件 */ - return; - - int thread_id = session_get_current_thread_id(sess); - if (thread_id > global_schema->state_count) - return; - lua_State *state = global_schema->thread_state[thread_id]; - - int statistic_id = thread_id * global_max_plugin_id + plugin_id; + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; struct lua_cdata param[3] = {0}; - param[0].cdata_type = DATATYPE_POINTER; - param[0].cdata_pointer = sess; - param[1].cdata_type = DATATYPE_CONTEXT; - param[1].cdata_context = (struct lua_context *)sess_ctx; - param[2].cdata_type = DATATYPE_TABLE; - param[2].cdata_table = env->private_env_ref; - - if (lua_chunk_execute(state, plugin->ctx_free_ref, 3, param, 0, NULL)) - ++global_plugin_statistics[statistic_id].free_failed_count; - else - ++global_plugin_statistics[statistic_id].free_success_count; - lua_context_free(state, (struct lua_context *)sess_ctx); + param[0].type = DATATYPE_POINTER; + param[0].pointer = sess; + param[1].type = DATATYPE_CONTEXT; + param[1].context = (struct lua_context *)sess_ctx; + param[2].type = DATATYPE_TABLE; + param[2].table = env->lua_plug_env_ref_id; + lua_chunk_execute(state, env->lua_ctx_free_fn_ref_id, param, 3, NULL, 0, NULL, 0); + lua_context_free((struct lua_context *)sess_ctx); return; } -/* - * Function: lpm_message_free_func - * Input: | struct session * | sess | 释放message对应的session - * | void * | msg | 需要释放的message消息 - * | void * | msg_free_arg | 释放函数需要存储的私有数据 - * Output: - * Return: - * Description: 与C插件保持一致的session_msg_free_cb_func, 作为lua插件实现对应功能的通用函数 - */ -void lpm_message_free_func( - struct session *sess, - void *msg, - void *msg_free_arg) +void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg) { - if (__glibc_unlikely(!sess || !msg || !msg_free_arg)) + if (!msg_free_arg) return; - struct lua_message_mq *plugin_mq = (struct lua_message_mq *)msg_free_arg; + struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg; + struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage; + struct stellar *st = plugin_manage->st; - int thread_id = session_get_current_thread_id(sess); - if (thread_id > global_schema->state_count) - return; - lua_State *state = global_schema->thread_state[thread_id]; + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; struct lua_cdata param[3] = {0}; - param[0].cdata_type = DATATYPE_POINTER; - param[0].cdata_pointer = sess; - param[1].cdata_type = DATATYPE_CONTEXT; - param[1].cdata_context = (struct lua_context *)msg; - param[2].cdata_type = DATATYPE_TABLE; - param[2].cdata_table = plugin_mq->mq_private_ref; - - lua_chunk_execute(state, plugin_mq->freemessage_ref, 3, param, 0, NULL); - lua_context_free(state, (struct lua_context *)msg); + param[0].type = DATATYPE_POINTER; + param[0].pointer = sess; + param[1].type = DATATYPE_CONTEXT; + param[1].context = (struct lua_context *)msg; + param[2].type = DATATYPE_TABLE; + param[2].table = free_arg->lua_msg_free_arg_ref_id; + lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0); + lua_context_free((struct lua_context *)msg); return; } -/* - * Function: lpm_on_session_msg_func - * Input: | struct session * | sess | 会话信息 - * | int | topic_id | 处理的message topic id - * | const void * | msg | 需要处理的消息信息 - * | void * | sess_ctx | 会话中的私有数据 - * | void * | plugin_env | 插件运行环境 - * Output: - * Return: - * Description: 与C插件管理器保持一致的ctx_free_func - */ -void lpm_on_session_msg_func( - struct session *sess, - int topic_id, - const void *msg, - void *sess_ctx, - void *plugin_env) +void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env) { - if (__glibc_unlikely(!sess || !sess || !plugin_env)) + if (!plugin_env) return; - struct lua_context *sess_context = (struct lua_context *)sess_ctx; - struct lua_model *env = (struct lua_model *)plugin_env; + struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env; + struct lua_plugin_manage *plugin_manage = env->plugin_manage; + struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_session_message_hashlist, topic_id, env->session_plugin_id); + struct stellar *st = plugin_manage->st; - /* 获取插件ID并找到该插件 */ - int plugin_id = session_get_current_plugin_id(sess); - // int plugin_id = 1; - struct lua_plugin *plugin = NULL; - while ((plugin = utarray_next(env->plugin_array, plugin))) - { - if (plugin->plugin_id == plugin_id) - break; - } - if (!plugin || plugin->plugin_id != plugin_id || !plugin->sub_topic_array) - /* 未找到该插件, 或者在该插件中未发现注册的topic_id */ - return; - struct lua_plugin_mq *mq = NULL; - while ((mq = utarray_next(plugin->sub_topic_array, mq))) - { - if (mq->topic_id == topic_id) - break; - } - if (!mq || mq->topic_id != topic_id) - /* 未找到对应的消息处理函数 */ + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; + + struct lua_cdata param[5] = {0}; + param[0].type = DATATYPE_POINTER; + param[0].pointer = sess; + param[1].type = DATATYPE_INT; + param[1].integer = topic_id; + /* 后续统一为相同结构 */ + param[2].type = DATATYPE_CONTEXT; + param[2].context = (struct lua_context *)msg; + param[3].type = DATATYPE_CONTEXT; + param[3].context = (struct lua_context *)sess_ctx; + param[4].type = DATATYPE_TABLE; + param[4].table = env->lua_plug_env_ref_id; + + lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0); + return; +} + +void lpm_on_packet_func(struct packet *pkt, unsigned char ip_protocol, void *plugin_env) +{ + if (!plugin_env) return; - /* 判断该消息是由C端插件产生的还是由Lua插件产生的 */ - struct lua_message_mq *message_mq = search_message_mq_by_id(topic_id); + struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env; + struct lua_plugin_manage *plugin_manage = env->plugin_manage; + struct stellar *st = plugin_manage->st; - int thread_id = session_get_current_thread_id(sess); - if (thread_id > global_schema->state_count) + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; + + struct lua_cdata param[3] = {0}; + param[0].type = DATATYPE_POINTER; + param[0].pointer = pkt; + param[1].type = DATATYPE_INT; + param[1].integer = (int)ip_protocol; + param[2].type = DATATYPE_TABLE; + param[2].table = env->lua_plug_env_ref_id; + + lua_chunk_execute(state, env->lua_on_packet_fn_ref_id, param, 3, NULL, 0, NULL, 0); + return; +} + +void lpm_packet_message_free_func(struct packet *pkt, void *msg, void *msg_free_arg) +{ + if (!msg_free_arg) return; - lua_State *state = global_schema->thread_state[thread_id]; + struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg; + struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage; + struct stellar *st = plugin_manage->st; - struct lua_cdata params[5] = {0}; - params[0].cdata_type = DATATYPE_POINTER; - params[0].cdata_pointer = sess; - params[1].cdata_type = DATATYPE_INT; - params[1].cdata_int = topic_id; - if (!message_mq) - { - /* C端产生的直接使用指针 */ - params[2].cdata_type = DATATYPE_POINTER; - params[2].cdata_pointer = (void *)msg; - } - else - { - /* lua端产生的为一个context结构 */ - params[2].cdata_type = DATATYPE_CONTEXT; - params[2].cdata_context = (struct lua_context *)msg; - } - params[3].cdata_type = DATATYPE_CONTEXT; - params[3].cdata_context = sess_context; - params[4].cdata_type = DATATYPE_TABLE; - params[4].cdata_table = env->private_env_ref; + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; - lua_chunk_execute(state, mq->onmessage_ref, 5, params, 0, NULL); + struct lua_cdata param[3] = {0}; + param[0].type = DATATYPE_POINTER; + param[0].pointer = pkt; + param[1].type = DATATYPE_CONTEXT; + param[1].context = (struct lua_context *)msg; + param[2].type = DATATYPE_TABLE; + param[2].table = free_arg->lua_msg_free_arg_ref_id; + lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0); + lua_context_free((struct lua_context *)msg); + return; +} + +void lpm_on_packet_msg_func(struct packet *pkt, int topic_id, const void *msg, void *plugin_env) +{ + if (!plugin_env) + return; + + struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env; + struct lua_plugin_manage *plugin_manage = env->plugin_manage; + struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_packet_message_hashlist, topic_id, env->packet_plugin_id); + struct stellar *st = plugin_manage->st; + + int thread_id = stellar_get_current_thread_id(st); + struct lua_state *state = plugin_manage->state[thread_id]; + + struct lua_cdata param[4] = {0}; + param[0].type = DATATYPE_POINTER; + param[0].pointer = pkt; + param[1].type = DATATYPE_INT; + param[1].integer = topic_id; + /* 后续统一为相同结构 */ + param[2].type = DATATYPE_CONTEXT; + param[2].context = (struct lua_context *)msg; + param[3].type = DATATYPE_TABLE; + param[3].table = env->lua_plug_env_ref_id; + + lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0); return; } \ No newline at end of file diff --git a/src/lua_plugin_chunk.c b/src/lua_plugin_chunk.c deleted file mode 100644 index 3ec9bdc..0000000 --- a/src/lua_plugin_chunk.c +++ /dev/null @@ -1,107 +0,0 @@ -/************************************************************************* - > File Name: lua_plugin_chunk.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * 实现代码块相关操作 - * version - * [ v0.1 ] - * 08-12 - * 1. 实现函数 - * int lua_chunk_execute; - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -/* - * Function: lua_chunk_execute - * Input: | lua_State * | state | 执行该代码块使用的状态机 - * | int | ref_id | 代码块在状态机中的引用ID - * | int | pcount | 执行过程中传入的参数个数 - * | struct lua_cdata * | params | 执行过程中传入的参数 - * | int | rcount | 执行结束后返回值的个数 - * | struct lua_cdata * | returns | 执行结束后返回值 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 在lua状态机中执行一段代码块, 执行的代码块需要提前在状态机中完成注册 - * 并已经生成相关的引用ID, 根据该ID进行调用 - */ -int lua_chunk_execute( - lua_State *state, - int ref_id, - int pcount, - struct lua_cdata *params, - int rcount, - struct lua_cdata *returns) -{ - if (__glibc_unlikely(!state || ref_id == LUA_REFNIL)) - return PARAM_ERR; - if ((pcount && !params) || (pcount < 0)) - return PARAM_ERR; - if ((rcount && !returns) || (rcount < 0)) - return PARAM_ERR; -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("now execute chunk, %p, %d", state, ref_id); -#endif - - /* 需要调用的函数入栈, 由于后续在读取参数个数的时候对栈操作较多, 需要先将函数入栈 */ - lua_rawgeti(state, LUA_REGISTRYINDEX, ref_id); - if (lua_gettop(state) == 0 || lua_type(state, -1) != LUA_TFUNCTION) - { - lua_settop(state, 0); - return CHUNK_TYPE_NOT_FUNCTION; - } - - /* 参数入栈 */ - int pushret = 0; - for (int i = 0; i < pcount; ++i) - { - if ((pushret = lua_cdata_push_stack(state, ¶ms[i]))) - { - lua_settop(state, 0); - return pushret; - } - } - - /* 执行该脚本并记录执行时间 */ - // clock_t start_time, end_time; - // start_time = clock(); - /* 调用该脚本 or 代码片段 */ - if (lua_pcall(state, pcount, LUA_MULTRET, 0)) - { - // end_time = clock(); - LOGERROR("run script failed, mess is %s\n", lua_tostring(state, -1)); - /* 仅函数运行过程中出错记入出错记录, 由于参数错误等原因导致的错误不记录 */ - lua_settop(state, 0); - return CHUNK_RUN_CODE_FAIL; - } - // end_time = clock(); - - /* 返回值出栈 */ - if (rcount > 0) - { - /* 如果rmaxcount为0, 说明在期望中不准备接收返回值, 也不必处理 */ - int count = lua_gettop(state); - if (count > rcount) - { - lua_settop(state, 0); - return CHUNK_RCOUNT_ERR; - } - int pop_ret = 0; - for (int i = (count - 1); i >= 0; --i) - { - if ((pop_ret = lua_cdata_pop_stack(state, &(returns[i])))) - { - lua_settop(state, 0); - return pop_ret; - } - } - } - - lua_settop(state, 0); - /* TODO: 记录耗时等数据 */ - - return SUCCESS; -} \ No newline at end of file diff --git a/src/lua_plugin_data.c b/src/lua_plugin_data.c deleted file mode 100644 index 128676f..0000000 --- a/src/lua_plugin_data.c +++ /dev/null @@ -1,214 +0,0 @@ -/************************************************************************* - > File Name: lua_plugin_data.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * version - * [ v0.1 ] - * 08-06 - * 1. 实现函数 - * int lua_cdata_push_stack; - * int lua_cdata_pop_stack; - * void lua_cdata_destory; - * struct lua_context * lua_context_new; - * int lua_context_push_stack; - * void lua_context_free; - * - * 08-12 - * 1. 修改部分函数返回值, 使用统一的错误码, 方便统一处理 - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -/* - * Function: lua_cdata_push_stack - * Input: | lua_State * | state | 入栈数据使用的状态机 - * | struct lua_cdata * | cdata | 需要入栈的数据 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 将一个数据元素入栈 - */ -int lua_cdata_push_stack( - lua_State *state, - struct lua_cdata *cdata) -{ - if (__glibc_unlikely(!state || !cdata)) - return PARAM_ERR; - - switch (cdata->cdata_type) - { - /* 不同的数据类型入栈方式不同 */ - case DATATYPE_NIL: - lua_pushnil(state); - return SUCCESS; - case DATATYPE_BOOL: - lua_pushboolean(state, cdata->cdata_bool); - return SUCCESS; - case DATATYPE_INT: - lua_pushinteger(state, cdata->cdata_int); - return SUCCESS; - case DATATYPE_NUM: - lua_pushnumber(state, cdata->cdata_num); - return SUCCESS; - case DATATYPE_STRING: - if (lua_pushstring(state, cdata->cdata_string) == NULL) - return DATA_PUSHSTACK_ERR; - return SUCCESS; - case DATATYPE_TABLE: - lua_rawgeti(state, LUA_REGISTRYINDEX, cdata->cdata_table); - return SUCCESS; - case DATATYPE_POINTER: - lua_pushlightuserdata(state, (void *)cdata->cdata_pointer); - return SUCCESS; - case DATATYPE_CONTEXT: - if (lua_context_push_stack(state, cdata->cdata_context)) - return DATA_PUSHSTACK_ERR; - return SUCCESS; - default: - LOGERROR("can't recorgnize data type %d", cdata->cdata_type); - } - - return DATA_TYPE_UNKNOWN; -} - -/* - * Function: lua_cdata_pop_stack - * Input: | lua_State * | state | 出栈数据使用的状态机 - * | struct lua_cdata * | cdata | 保存出栈的元素 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 将一个数据元素出栈, 出栈过程中无法出栈context与table类型 - * TODO: 扩展类型, 支持更多数据类型 - */ -int lua_cdata_pop_stack( - lua_State *state, - struct lua_cdata *cdata) -{ - if (__glibc_unlikely(!state || !cdata)) - return PARAM_ERR; - if (!lua_gettop(state)) - return DATA_POPSTACK_NODATA; - - switch (lua_type(state, -1)) - { - case LUA_TNIL: - cdata->cdata_type = DATATYPE_NIL; - break; - case LUA_TBOOLEAN: - cdata->cdata_type = DATATYPE_BOOL; - cdata->cdata_bool = lua_toboolean(state, -1); - break; - case LUA_TNUMBER: - cdata->cdata_type = DATATYPE_NUM; - cdata->cdata_num = lua_tonumber(state, -1); - int try_int = (int)cdata->cdata_num; - if ((double)try_int == cdata->cdata_num) - { - cdata->cdata_type = DATATYPE_INT; - cdata->cdata_int = lua_tointeger(state, -1); - } - break; - case LUA_TSTRING: - cdata->cdata_type = DATATYPE_STRING; - cdata->cdata_string = (char *)strdup(lua_tostring(state, -1)); - break; - case LUA_TLIGHTUSERDATA: - cdata->cdata_type = DATATYPE_POINTER; - cdata->cdata_pointer = (void *)lua_topointer(state, -1); - break; - default: - /* TODO: 其他数据类型之后处理 */ - LOGERROR("other lua type can't pop out, %d", lua_type(state, -1)); - return DATA_TYPE_UNKNOWN; - } - - lua_pop(state, 1); - return SUCCESS; -} - -/* - * Function: lua_cdata_destory - * Input: | struct lua_cdata * | cdata | 待销毁的data结构 - * Output: - * Return: - * Description: 销毁是一个data结构, 释放内部占用内存 - * 目前该函数仅数据类型为string的时候需要调用一次 - */ -void lua_cdata_destory(struct lua_cdata *cdata) -{ - if (__glibc_unlikely(!cdata)) - return; - if (cdata->cdata_type == DATATYPE_STRING && cdata->cdata_string) - free(cdata->cdata_string); - return; -} - -/* - * Function: lua_context_new - * Input: | lua_State * | state | 创建context使用的状态机 - * Output: - * Return: | NULL | 创建失败 - * | pointer | 创建成功, 返回创建的context指针 - * Description: 创建一个context结构, 由于context结构使用需要在状态机中生成引用值, 单独重写一个new函数 - */ -struct lua_context *lua_context_new(lua_State *state) -{ - if (__glibc_unlikely(!state)) - return NULL; - - lua_newtable(state); - int ref_id = luaL_ref(state, LUA_REGISTRYINDEX); -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("create new context, ref id is %d\n", ref_id); -#endif - lua_settop(state, 0); - if (ref_id == LUA_REFNIL) - return NULL; - - struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); - if (__glibc_unlikely(!new_context)) - { - luaL_unref(state, LUA_REGISTRYINDEX, ref_id); - return NULL; - } - // new_context->context_state = state; - new_context->context_ref_id = ref_id; - return new_context; -} - -/* - * Function: lua_context_push_stack - * Input: | lua_State * | state | 将该context入栈 - * | struct lua_context * | context | 待入栈的context结构 - * Output: - * Return: | 0 | 入栈成功 - * | -1 | 参数错误 - * Description: 将一个context入栈, 实际入栈流程与table一致 - */ -int lua_context_push_stack(lua_State *state, struct lua_context *context) -{ - if (luai_unlikely(!state || !context)) - return PARAM_ERR; - - lua_rawgeti(state, LUA_REGISTRYINDEX, context->context_ref_id); - return SUCCESS; -} - -/* - * Function: lua_context_free - * Input: | lua_State * | state | 在该状态机中删除context - * | struct lua_context * | context | 释放一个context - * Output: - * Return: - * Description: 释放一个context - */ -void lua_context_free(lua_State *state, struct lua_context *context) -{ - if (__glibc_unlikely(!state || !context)) - return; - luaL_unref(state, LUA_REGISTRYINDEX, context->context_ref_id); - free(context); - return; -} \ No newline at end of file diff --git a/src/lua_plugin_manage.c b/src/lua_plugin_manage.c index 84170c6..5bdd2f7 100644 --- a/src/lua_plugin_manage.c +++ b/src/lua_plugin_manage.c @@ -1,630 +1,919 @@ -/************************************************************************* - > File Name: lua_plugin_manage.c - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * version - * [ v0.1 ] - * 08-05 - * 1. 实现函数 - * void specific_instance_copy; - * void specific_instance_destory; - * int script_instance_init_byname; - * int script_instance_init_byrefid; - * void script_instance_clean; - * int script_execute; (暂未实现) - * int session_plugin_instance_init; - * void session_plugin_instance_destory; - * int plugin_env_instance_init; - * void plugin_env_instance_destory; - * int thread_state_instance_init; - * void thread_state_instance_destory; - * int thread_state_instance_load; - * int lua_plugin_manage_config_load; - * int lua_plugin_manage_thread_load; - * - * 08-06 - * 1. 实现函数 - * int script_execute; - * - * 08-13 - * 1. 修改部分创建列表使用的结构 - * 2. 实现函数 - * struct lua_plugin * search_plugin_by_id - * struct lua_message_mq * search_message_mq_by_id - ************************************************************************/ -#include "lua_plugin_manage_internal.h" - -#include +#include #include #include #include +#include -struct lua_plugin_manage_schema *global_schema = NULL; +#include +#include -#if 0 -void lua_message_mq_destory(void * elt) +#include "lua_binding_function.h" + +struct lua_bind_function_spec lua_bind_function[] = { + {lua_get_worker_thread_num, "get_worker_thread_num", "stellar"}, + {lua_get_current_thread_id, "get_current_thread_id", "stellar"}, + {lua_get_stellar_pointer, "get_stellar", "stellar"}, + + {lua_session_plugin_regist, "register", "session_plugin"}, + {lua_packet_plugin_regist, "register", "packet_plugin"}, + + {lua_session_get_type, "get_type", "session"}, + + {lua_packet_mq_create_topic, "create_topic", "packet_mq"}, + {lua_packet_mq_get_topic_id, "get_topic_id", "packet_mq"}, + {lua_packet_mq_update_topic, "update_topic", "packet_mq"}, + {lua_packet_mq_destory_topic, "destory_topic", "packet_mq"}, + {lua_packet_mq_subscribe_topic, "subscribe_topic", "packet_mq"}, + {lua_packet_mq_publish_message, "publish_message", "packet_mq"}, + + {lua_session_mq_create_topic, "create_topic", "session_mq"}, + {lua_session_mq_get_topic_id, "get_topic_id", "session_mq"}, + {lua_session_mq_update_topic, "update_topic", "session_mq"}, + {lua_session_mq_destory_topic, "destory_topic", "session_mq"}, + {lua_session_mq_subscribe_topic, "subscribe_topic", "session_mq"}, + {lua_session_mq_topic_is_active, "topic_is_active", "session_mq"}, + {lua_session_mq_publish_message, "publish_message", "session_mq"}, + {lua_session_mq_ignore_message, "ignore_message", "session_mq"}, + {lua_session_mq_unignore_message, "unignore_message", "session_mq"}, + {NULL, NULL, NULL}, +}; + +struct lua_bind_data_spec lua_bind_data[] = { + {DATATYPE_BOOL, "true", "test_data_bool", "plugin_manage"}, + {DATATYPE_INT, "1000", "test_data_int", "plugin_manage"}, + {DATATYPE_NUM, "100.001", "test_data_double", "plugin_manage"}, + {DATATYPE_STRING, "this is a string test", "test_data_string", "plugin_manage"}, + {DATATYPE_END, NULL, NULL, NULL}, +}; + +struct lua_state { - if (!elt) return; - struct lua_message_mq * mq = (struct lua_message_mq *)elt; - if ( mq->topic_name ) - free(mq->topic_name); - return; -} -#endif -static UT_icd lua_message_mq_icd = {sizeof(struct lua_message_mq), NULL, NULL, NULL}; + lua_State *state; +}; -void lua_plugin_destory(void *elt) +/* ***** ***** ***** ***** ***** ***** */ +/* cbinding */ +/* ***** ***** ***** ***** ***** ***** */ +static int lua_cbinding_single_function(struct lua_state *state, struct lua_bind_function_spec *function_spec) { - if (!elt) - return; - struct lua_plugin *plugin = (struct lua_plugin *)elt; - if (plugin->sub_topic_array) - utarray_free(plugin->sub_topic_array); - return; -} -static UT_icd lua_plugin_icd = {sizeof(struct lua_plugin), NULL, NULL, lua_plugin_destory}; + if (!state || !function_spec || !function_spec->function || !function_spec->func_name) + return PARAM_ERR; + lua_State *L = (lua_State *)state; -/* - * Function: search_plugin_by_id - * Input: | int | plugin_id | 需要查找plugin数据的id - * Output: - * Return: 查找得到的plugin结构 - * Description: 在global schema中根据plugin_id查找一个plugin - */ -struct lua_plugin *search_plugin_by_id(int plugin_id) -{ - for (int i = 0; i < global_schema->model_count; ++i) + if (function_spec->space_name) { - struct lua_model *model = global_schema->model[i]; - - struct lua_plugin *plugin = NULL; - while ((plugin = utarray_next(model->plugin_array, plugin))) + lua_getglobal(L, function_spec->space_name); + if (lua_type(L, -1) == LUA_TNIL) { - if (plugin->plugin_id == plugin_id) - return plugin; - else if (plugin->plugin_id > plugin_id) - return NULL; + lua_newtable(L); + lua_setglobal(L, function_spec->space_name); + lua_settop(L, 0); + lua_getglobal(L, function_spec->space_name); } - } - return NULL; -} + else + { + if (lua_type(L, -1) != LUA_TTABLE) + { + lua_settop(L, 0); + return BIND_NAMESPACE_TYPE_ERR; + } -/* - * Function: search_message_mq_by_id - * Input: | int | topic_id | 需要查找的topic_id - * Output: - * Return: 查找得到的message_mq结构 - * Description: 在global schema中根据topic_id查找一个message_mq - */ -struct lua_message_mq *search_message_mq_by_id(int topic_id) -{ - struct lua_message_mq *mq = NULL; - while ((mq = utarray_next(global_schema->message_mq_array, mq))) + lua_getfield(L, -1, function_spec->func_name); + if (lua_type(L, -1) != LUA_TNIL) + { + lua_settop(L, 0); + return BIND_FUNCTION_TYPE_ERR; + } + lua_pop(L, 1); + } + lua_pushcfunction(L, (lua_CFunction)function_spec->function); + lua_setfield(L, -2, function_spec->func_name); + } + else { - if (mq->topic_id == topic_id) - return mq; + lua_getglobal(L, function_spec->func_name); + if (lua_type(L, -1) != LUA_TNIL) + { + lua_settop(L, 0); + return BIND_FUNCTION_TYPE_ERR; + } + lua_pop(L, 1); + + lua_pushcfunction(L, (lua_CFunction)function_spec->function); + lua_setglobal(L, function_spec->func_name); } - return NULL; + + lua_settop(L, 0); + return SUCCESS; } -/* - * Function: thread_state_init - * Input: | int | thread_id | 创建状态机的线程号 - * Output: - * Return: 创建完成的状态机实例指针 - * Description: 创建一个lua的状态机实例, 在每个线程中创建一个 - */ -lua_State *thread_state_init(int thread_id) +static int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec) { - lua_State *new_state = luaL_newstate(); - if (__glibc_unlikely(!new_state)) + if (!state || !data_spec || !data_spec->data_value || !data_spec->data_name) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + + if (data_spec->space_name) + { + lua_getglobal(L, data_spec->space_name); + if (lua_gettop(L) == 0 || lua_type(L, -1) == LUA_TNIL) + { + lua_newtable(L); + lua_setglobal(L, data_spec->space_name); + lua_settop(L, 0); + lua_getglobal(L, data_spec->space_name); + } + else + { + if (lua_type(L, -1) != LUA_TTABLE) + { + lua_settop(L, 0); + return BIND_NAMESPACE_TYPE_ERR; + } + + lua_getfield(L, -1, data_spec->data_name); + if (lua_type(L, -1) != LUA_TNIL) + { + lua_settop(L, 0); + return BIND_DATA_TYPE_ERR; + } + lua_pop(L, 1); + } + + switch (data_spec->data_type) + { + case DATATYPE_BOOL: + if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE")) + lua_pushboolean(L, 1); + else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE")) + lua_pushboolean(L, 0); + break; + case DATATYPE_INT: + lua_pushinteger(L, atoi(data_spec->data_value)); + break; + case DATATYPE_NUM: + lua_pushnumber(L, (lua_Number)atof(data_spec->data_value)); + break; + case DATATYPE_STRING: + lua_pushstring(L, (const char *)data_spec->data_value); + break; + default: + /* 其他类型不支持 */ + lua_settop(L, 0); + return BIND_DATA_TYPE_UNKNOWN; + } + lua_setfield(L, -2, data_spec->data_name); + } + else + { + lua_getglobal(L, data_spec->data_name); + if (lua_type(L, -1) != LUA_TNIL) + { + lua_settop(L, 0); + return BIND_DATA_TYPE_ERR; + } + lua_pop(L, 1); + + switch (data_spec->data_type) + { + case DATATYPE_BOOL: + if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE")) + lua_pushboolean(L, 1); + else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE")) + lua_pushboolean(L, 0); + break; + case DATATYPE_INT: + lua_pushinteger(L, atoi(data_spec->data_value)); + break; + case DATATYPE_NUM: + lua_pushnumber(L, (lua_Number)atof(data_spec->data_value)); + break; + case DATATYPE_STRING: + lua_pushstring(L, (const char *)data_spec->data_value); + break; + default: + /* 其他类型不支持 */ + lua_settop(L, 0); + return BIND_DATA_TYPE_UNKNOWN; + } + lua_setglobal(L, data_spec->data_name); + } + + lua_settop(L, 0); + return SUCCESS; +} + +int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num) +{ + int failed_count = 0; + for (unsigned index = 0; index < bind_func_num; index++) + { + if (lua_cbinding_single_function(state, &bind_function[index])) + failed_count++; + } + return failed_count; +} + +int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num) +{ + int failed_count = 0; + for (unsigned index = 0; index < bind_data_num; index++) + { + if (lua_cbinding_single_data(state, &bind_data[index])) + failed_count++; + } + return failed_count; +} + +/* ***** ***** ***** ***** ***** ***** */ +/* context */ +/* ***** ***** ***** ***** ***** ***** */ +struct lua_context *lua_context_new(struct lua_state *state) +{ + if (!state) + return NULL; + lua_State *L = (lua_State *)state; + + lua_newtable(L); + int ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (ref_id == LUA_REFNIL) return NULL; - luaL_openlibs(new_state); - /* 绑定所有注册函数 */ - lua_cbinding_functions(new_state); - /* 绑定所有全局变量 */ - lua_cbinding_datas(new_state); + struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); + new_context->lua_context_ref_id = ref_id; + return new_context; +} - lua_pushinteger(new_state, thread_id); - lua_setglobal(new_state, LUA_STATE_THREAD_ID_KEY); +void lua_context_free(struct lua_context *context) +{ + if (!context) + return; + luaL_unref((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id); + free(context); + return; +} - lua_settop(new_state, 0); +void lua_context_push_stack(struct lua_context *context) +{ + if (!context) + return; + if (context->lua_context_ref_id) + lua_rawgeti((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id); + return; +} +/* ***** ***** ***** ***** ***** ***** */ +/* trans data between lua table and C */ +/* ***** ***** ***** ***** ***** ***** */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +static int lua_function_writer(lua_State *state, const void *p, size_t sz, void *ud) +{ + /* TODO: 这个函数在lua中会被大量调用, 频繁的realloc可能会导致内存碎片化, 后续调整一下内存分配机制 */ + struct lua_cdata *data = (struct lua_cdata *)ud; + data->type = DATATYPE_FUNCTION; + if (!data->function) + data->function = (void *)calloc(1, sizeof(sz)); + else + data->function = (void *)realloc(data->function, (data->data_len + sz)); + memcpy((data->function + data->data_len), p, sz); + data->data_len += sz; + return 0; +} + +static const char *lua_function_reader(lua_State *state, void *ud, size_t *sz) +{ + struct lua_cdata *data = (struct lua_cdata *)ud; + *sz = data->data_len; + return (const char *)data->function; +} +#pragma GCC diagnostic pop + +struct lua_cdata *lua_cdata_new(void) +{ + struct lua_cdata *new_data = (struct lua_cdata *)calloc(1, sizeof(struct lua_cdata)); + memset(new_data, 0, sizeof(struct lua_cdata)); + return new_data; +} + +static void lua_cdata_inner_data_free(struct lua_cdata *cdata) +{ + if (!cdata) + return; + cdata->type = 0; + cdata->data_len = 0; + switch (cdata->type) + { + case DATATYPE_STRING: + free(cdata->string); + break; + case DATATYPE_LUA_TABLE: + lua_ctable_free(cdata->ctable); + break; + case DATATYPE_FUNCTION: + free(cdata->function); + break; + default: + break; + } + return; +} + +void lua_cdata_free(struct lua_cdata *cdata) +{ + lua_cdata_inner_data_free(cdata); + if (cdata) + free(cdata); + return; +} + +int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata) +{ + if (!state || !cdata) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + + switch (cdata->type) + { + case DATATYPE_NIL: + lua_pushnil(L); + break; + case DATATYPE_BOOL: + lua_pushboolean(L, cdata->bool); + break; + case DATATYPE_INT: + lua_pushinteger(L, cdata->integer); + break; + case DATATYPE_NUM: + lua_pushnumber(L, cdata->number); + break; + case DATATYPE_STRING: + lua_pushstring(L, cdata->string); + break; + case DATATYPE_TABLE: + if (cdata->table) + lua_rawgeti(L, LUA_REGISTRYINDEX, cdata->table); + break; + case DATATYPE_LUA_TABLE: + lua_ctable_push_stack(state, cdata->ctable); + break; + case DATATYPE_POINTER: + lua_pushlightuserdata(L, (void *)cdata->pointer); + break; + case DATATYPE_CONTEXT: + lua_context_push_stack(cdata->context); + break; + case DATATYPE_FUNCTION: + lua_load(L, lua_function_reader, (void *)cdata, NULL, NULL); + break; + default: + return DATA_TYPE_UNKNOWN; + } + return SUCCESS; +} + +int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata) +{ + if (!state || !cdata) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + + lua_cdata_inner_data_free(cdata); + switch (lua_type(L, -1)) + { + case LUA_TNIL: + cdata->type = DATATYPE_NIL; + break; + case LUA_TBOOLEAN: + cdata->type = DATATYPE_BOOL; + cdata->bool = lua_toboolean(L, -1); + break; + case LUA_TLIGHTUSERDATA: + cdata->type = DATATYPE_POINTER; + cdata->pointer = (void *)lua_topointer(L, -1); + break; + case LUA_TNUMBER: + cdata->type = DATATYPE_NUM; + cdata->number = lua_tonumber(L, -1); + int try_int = (int)cdata->number; + if ((double)try_int == cdata->number) + { + cdata->type = DATATYPE_INT; + cdata->integer = lua_tointeger(L, -1); + } + break; + case LUA_TSTRING: + cdata->type = DATATYPE_STRING; + cdata->string = (char *)strdup(lua_tostring(L, -1)); + break; + case LUA_TTABLE: + cdata->type = DATATYPE_LUA_TABLE; + cdata->ctable = lua_ctable_new(); + lua_ctable_pop_stack(state, cdata->ctable); + break; + case LUA_TFUNCTION: + cdata->type = DATATYPE_FUNCTION; + lua_dump(L, lua_function_writer, cdata, 0); + break; + case LUA_TUSERDATA: + cdata->type = DATATYPE_POINTER; + cdata->pointer = (void *)lua_topointer(L, -1); + break; + default: + return DATA_TYPE_UNKNOWN; + } + lua_pop(L, 1); + return SUCCESS; +} + +struct lua_ctable *lua_ctable_new(void) +{ + struct lua_ctable *new_table = (struct lua_ctable *)calloc(1, sizeof(struct lua_ctable)); + memset(new_table, 0, sizeof(struct lua_ctable)); + return new_table; +} + +void lua_ctable_free(struct lua_ctable *ctable) +{ + if (!ctable) + return; + for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) + { + lua_cdata_free(ctable->array_data[array_index]); + } + for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) + { + lua_cnode_free(ctable->node_data[node_index]); + } + free(ctable->array_data); + free(ctable->node_data); + free(ctable); + return; +} + +int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable) +{ + if (!state || !ctable) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + lua_newtable(L); + for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) + { + lua_pushinteger(L, (array_index + 1)); + lua_cdata_push_stack(state, ctable->array_data[array_index]); + lua_settable(L, -3); + } + for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) + { + if (ctable->node_data[node_index]->node_string_key) + lua_pushstring(L, ctable->node_data[node_index]->node_string_key); + else + lua_pushinteger(L, ctable->node_data[node_index]->node_integer_key); + lua_cdata_push_stack(state, ctable->node_data[node_index]->node_data); + lua_settable(L, -3); + } + + return SUCCESS; +} + +int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable) +{ + if (!state || !ctable) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + + /* 获取table长度 */ + ctable->array_size = (size_t)lua_rawlen(L, -1); + lua_pushnil(L); + while (lua_next(L, -2)) + { + ctable->node_size++; + if (lua_type(L, -2) == LUA_TNUMBER) + { + int numkey = lua_tointeger(L, -2); + if (numkey > 0 && numkey <= (int)ctable->array_size) + ctable->node_size--; + } + lua_pop(L, -1); + } + + ctable->array_data = (struct lua_cdata **)calloc(ctable->array_size, sizeof(struct lua_cdata *)); + for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) + { + ctable->array_data[array_index] = lua_cdata_new(); + } + ctable->node_data = (struct lua_cnode **)calloc(ctable->node_size, sizeof(struct lua_cnode *)); + for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) + { + ctable->node_data[node_index] = lua_cnode_new(); + } + + /* 依次获取数据 */ + int key_index = 0; + lua_pushnil(L); + while (lua_next(L, -2)) + { + if (lua_type(L, -2) == LUA_TNUMBER) + { + int numkey = lua_tointeger(L, -2); + if (numkey > 0 && numkey <= (int)ctable->array_size) + lua_cdata_pop_stack(state, ctable->array_data[numkey - 1]); + else + { + lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data); + ctable->node_data[key_index]->node_integer_key = lua_tointeger(L, -1); + ++key_index; + } + } + else if (lua_type(L, -2) == LUA_TSTRING) + { + lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data); + ctable->node_data[key_index]->node_string_key = strdup((char *)lua_tostring(L, -1)); + ++key_index; + } + } + + return SUCCESS; +} + +struct lua_cnode *lua_cnode_new(void) +{ + struct lua_cnode *new_node = (struct lua_cnode *)calloc(1, sizeof(struct lua_cnode)); + memset(new_node, 0, sizeof(struct lua_cnode)); + new_node->node_data = lua_cdata_new(); + return new_node; +} + +void lua_cnode_free(struct lua_cnode *cnode) +{ + if (cnode->node_string_key) + free(cnode->node_string_key); + if (cnode->node_data) + lua_cdata_free(cnode->node_data); + free(cnode); + return; +} + +/* ***** ***** ***** ***** ***** ***** */ +/* execute one chunk */ +/* ***** ***** ***** ***** ***** ***** */ +int lua_chunk_execute( + struct lua_state *state, + int fn_ref_id, + struct lua_cdata param[], + size_t param_num, + struct lua_cdata returnvalue[], + size_t r_num, + char *errlog, + size_t err_len) +{ + if (!state || fn_ref_id <= 0 || (param_num && !param) || (r_num && !returnvalue)) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + + lua_rawgeti(L, LUA_REGISTRYINDEX, fn_ref_id); + if (lua_type(L, -1) != LUA_TFUNCTION) + { + lua_settop(L, 0); + return CHUNK_TYPE_NOT_FUNCTION; + } + + int pushret = 0; + for (unsigned param_index = 0; param_index < param_num; ++param_index) + { + if ((pushret = lua_cdata_push_stack(state, ¶m[param_index]))) + { + lua_settop(L, 0); + return pushret; + } + } + + if (lua_pcall(L, param_num, LUA_MULTRET, 0)) + { + if (errlog) + snprintf(errlog, (err_len - 1), "run script[%d] err %s\n", fn_ref_id, lua_tostring(L, -1)); + lua_settop(L, 0); + return CHUNK_RUN_CODE_FAIL; + } + + if (r_num > 0) + { + int count = lua_gettop(L); + /* 如果接收返回值数量不够, 只保留前r_num个返回值 */ + if (count > (int)r_num) + { + lua_pop(L, (count - (int)r_num)); + count = (int)r_num; + } + int pop_ret = 0; + for (int i = (count - 1); i >= 0; --i) + { + if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i])))) + { + lua_settop(L, 0); + return pop_ret; + } + } + } + + lua_settop(L, 0); + return SUCCESS; +} + +/* TODO: 这个hash函数是不是合适 */ +int calc_on_message_func_hash_key(int topic_id, int plugin_id) +{ + return (((uint32_t)plugin_id << 3) + (uint32_t)topic_id) % HASH_MAX_NUM; +} + +struct lua_on_message_fn *hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id) +{ + int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id); + struct lua_on_message_fn *insert_positon = &msg_fn_hashlist[hash_key]; + while ((insert_positon->on_use - HASH_MAX_NUM) > 0) + { + if (insert_positon->on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1)) + insert_positon = &msg_fn_hashlist[0]; + else + insert_positon++; + /* 没有空位置了 */ + if (insert_positon->on_use % HASH_MAX_NUM == hash_key) + return NULL; + } + insert_positon->on_use += (HASH_MAX_NUM + 1); + insert_positon->topic_id = topic_id; + insert_positon->plugin_id = plugin_id; + return insert_positon; +} + +struct lua_on_message_fn *hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id) +{ + int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id); + struct lua_on_message_fn *find_position = &msg_fn_hashlist[hash_key]; + if ((find_position->on_use - HASH_MAX_NUM) < 0) + return NULL; + while (find_position) + { + if (find_position->topic_id == topic_id && find_position->plugin_id == plugin_id) + { + return find_position; + } + if (find_position->on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1)) + find_position = &msg_fn_hashlist[0]; + else + find_position++; + if ((find_position->on_use % HASH_MAX_NUM == hash_key) || (find_position->on_use - HASH_MAX_NUM) < 0) + break; + } + return NULL; +} + +#define LUA_GLOBAL_VALUE_REF_ID (LUA_RIDX_LAST + 2) + +static inline struct lua_state *thread_state_init(int thread_id, struct stellar *st, struct lua_plugin_manage *plugin_manage) +{ + lua_State *new_L = luaL_newstate(); + luaL_openlibs(new_L); + + lua_newtable(new_L); + lua_pushinteger(new_L, thread_id); + lua_setfield(new_L, -2, LUA_GLOBAL_THREAD_ID_KEY); + lua_pushlightuserdata(new_L, st); + lua_setfield(new_L, -2, LUA_GLOBAL_STELLAR_POINTER); + lua_pushlightuserdata(new_L, plugin_manage); + lua_setfield(new_L, -2, LUA_GLOBAL_PLUGIN_MANGE_POINTER); + int global_ref_id = luaL_ref(new_L, LUA_REGISTRYINDEX); + printf("set global ref id is %d\n", global_ref_id); + lua_settop(new_L, 0); + + struct lua_state *new_state = (struct lua_state *)new_L; + lua_cbinding_function(new_state, lua_bind_function, (sizeof(lua_bind_function) / sizeof(struct lua_bind_function_spec))); + lua_cbinding_data(new_state, lua_bind_data, (sizeof(lua_bind_data) / sizeof(struct lua_bind_data_spec))); return new_state; } /* - * Function: thread_state_load_specific - * Input: | lua_State * | state | 进行初始化的状态机 - * | struct lua_model * | model | 需要加载的模块, 模块数量与具体配置实例的数量一致 - * | struct lua_config_specific * | specific | 加载的配置 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 在状态机中加载一个具体配置, 并将加载完成后生成的引用值保存在model中, 加载过程中会使用model进行校验 - */ -int thread_state_load_specific( - lua_State *state, - struct lua_model *model, - struct lua_config_specific *specific) +int lua_state_get_thread_id(struct lua_state * state) { - if (__glibc_unlikely(!state || !model || !specific)) - return PARAM_ERR; - if (__glibc_unlikely(!specific->config_specific_file || !specific->config_specific_load_func || !specific->config_specific_unload_func)) - return PARAM_ERR; - - /* 加载lua文件 */ - if (access(specific->config_specific_file, F_OK)) - return STATE_LOAD_FILE_ERR; - if (luaL_loadfile(state, specific->config_specific_file)) - return STATE_LOAD_FILE_ERR; - if (lua_pcall(state, 0, 0, 0)) - { - LOGERROR("load specific failed, file is %s, err is %s", specific->config_specific_file, lua_tostring(state, -1)); - lua_settop(state, 0); - return STATE_LOAD_FILE_ERR; - } - lua_settop(state, 0); - - /* 创建plugin_env */ - lua_newtable(state); - int env_ref_id = luaL_ref(state, LUA_REGISTRYINDEX); - if (env_ref_id == LUA_REFNIL) - return STATE_CREATE_ENV_FAIL; - if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->private_env_ref != env_ref_id)) - { - LOGERROR("load new model, create plugin env id is not same, %d, %d", model->private_env_ref, env_ref_id); - return STATE_CREATE_ENV_FAIL; - } - - /* 加载load函数 */ - lua_getglobal(state, specific->config_specific_load_func); - if (lua_type(state, -1) != LUA_TFUNCTION) - { - luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id); - lua_settop(state, 0); - return STATE_GET_LOAD_FAIL; - } - int load_ref_id = luaL_ref(state, LUA_REGISTRYINDEX); - if (load_ref_id == LUA_REFNIL) - { - luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id); - lua_settop(state, 0); - return STATE_GET_LOAD_FAIL; - } - if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->load_ref != load_ref_id)) - { - LOGERROR("load new model, load ref id is not same, %d, %d", model->load_ref, load_ref_id); - return STATE_GET_LOAD_FAIL; - } - - /* 加载unload函数 */ - lua_getglobal(state, specific->config_specific_unload_func); - if (lua_type(state, -1) != LUA_TFUNCTION) - { - luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id); - luaL_unref(state, LUA_REGISTRYINDEX, load_ref_id); - lua_settop(state, 0); - return STATE_GET_UNLOAD_FAIL; - } - int unload_ref_id = luaL_ref(state, LUA_REGISTRYINDEX); - if (unload_ref_id == LUA_REFNIL) - { - luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id); - luaL_unref(state, LUA_REGISTRYINDEX, load_ref_id); - lua_settop(state, 0); - return STATE_GET_UNLOAD_FAIL; - } - if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->unload_ref != unload_ref_id)) - { - LOGERROR("load new model, unload ref id is not same, %d, %d", model->unload_ref, unload_ref_id); - return STATE_GET_UNLOAD_FAIL; - } - - /* 首次加载时完成model初始化 */ - if (!(model->model_mark & MODEL_MARK_INIT_DONE)) - { - model->private_env_ref = env_ref_id; - model->load_ref = load_ref_id; - model->unload_ref = unload_ref_id; - model->model_mark |= MODEL_MARK_INIT_DONE; - } - - lua_settop(state, 0); - return SUCCESS; + lua_State * L = (lua_State *)state; + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID); + int thread_id = -1; + if ( lua_getfield(L, -1, LUA_GLOBAL_THREAD_ID_KEY) == LUA_TNUMBER ) + thread_id = lua_tointeger(L, -1); + lua_pop(L, 2); + return thread_id; } -/* - * Function: thread_state_call_load - * Input: | lua_State * | state | 进行模块加载的状态机 - * | struct lua_model * | model | 需要进行加载的lua模块 - * | struct lua_config_specific * | specific | 加载模块的配置信息 - * | struct stellar * | st | 与C插件管理保持一致, stellar作为参数传入 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 在状态机中调用一个模块的load函数, 在状态机中完成该模块的加载 - */ -int thread_state_call_load( - lua_State *state, - struct lua_model *model, - struct lua_config_specific *specific, - struct stellar *st) +struct stellar * lua_state_get_stellar(struct lua_state * state) { - if (__glibc_unlikely(!state || !model || !specific || !st)) - return PARAM_ERR; + lua_State * L = (lua_State *)state; + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID); + struct stellar * st = NULL; + if ( lua_getfield(L, -1, LUA_GLOBAL_STELLAR_POINTER) == LUA_TLIGHTUSERDATA ) + st = (struct stellar *)lua_topointer(L, -1); + lua_pop(L, 2); + return st; +} +*/ - if ((!(model->model_mark & MODEL_MARK_LOAD_DONE)) && (!model->plugin_array)) - { - utarray_new(model->plugin_array, &lua_plugin_icd); - model->model_mark |= MODEL_MARK_LOAD_DONE; - } - - lua_rawgeti(state, LUA_REGISTRYINDEX, model->private_env_ref); - lua_pushlightuserdata(state, model); - /* 在该状态机对应模块的plugin_env中创建该结构对应的指针 */ - lua_setfield(state, -2, LUA_PLUGIN_ENV_DEFAULT_KEY); - lua_settop(state, 0); - luaL_loadfile(state, specific->config_specific_file); - lua_pcall(state, 0, 0, 0); - - struct lua_cdata params[2]; - params[0].cdata_type = DATATYPE_POINTER; - params[0].cdata_pointer = st; - params[1].cdata_type = DATATYPE_TABLE; - params[1].cdata_table = model->private_env_ref; - - return lua_chunk_execute(state, model->load_ref, 2, params, 0, NULL); +struct lua_plugin_manage *lua_state_get_plugin_manage(struct lua_state *state) +{ + lua_State *L = (lua_State *)state; + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID); + struct lua_plugin_manage *plugin_manage = NULL; + if (lua_getfield(L, -1, LUA_GLOBAL_PLUGIN_MANGE_POINTER) == LUA_TLIGHTUSERDATA) + plugin_manage = (struct lua_plugin_manage *)lua_topointer(L, -1); + lua_pop(L, 2); + return plugin_manage; } -/* - * Function: thread_state_call_unload - * Input: | lua_State * | 卸载模块的状态机 - * | struct lua_model * | 需要卸载的模块 - * Output: - * Return: enum LUA_PLUGIN_RETURN - * Description: 在一个状态机中对某模块调用其卸载unload函数 - */ -int thread_state_call_unload( - lua_State *state, - struct lua_model *model) -{ - if (__glibc_unlikely(!state || !model)) - return PARAM_ERR; - - struct lua_cdata param; - param.cdata_type = DATATYPE_TABLE; - param.cdata_table = model->private_env_ref; - - return lua_chunk_execute(state, model->unload_ref, 1, ¶m, 0, NULL); -} - -/* - * Function: - * Input: - * Output: - * Return: - * Description: - */ -struct lua_plugin_manage_schema *lua_plugin_manage_init( +static int lua_state_load_one_specific( + struct lua_state *state, + struct lua_config_spec *spec, + struct lua_load_script *script, struct stellar *st, - int specific_count, - struct lua_config_specific *specific) + char *errlog, + size_t errlog_len) { - if (__glibc_unlikely(!st)) - return NULL; - if (__glibc_unlikely((specific_count && !specific) || (specific_count < 0))) - return NULL; -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("get specific count is %d", specific_count); -#endif + if (!state || !spec || !script) + return PARAM_ERR; + lua_State *L = (lua_State *)state; + if (access(spec->spec_file_path, F_OK) || luaL_loadfile(L, spec->spec_file_path)) + return STATE_LOAD_FILE_ERR; + if (lua_pcall(L, 0, 0, 0)) + { + snprintf(errlog, (errlog_len - 1), "load spec[%s] fail err is %s\n", spec->spec_file_path, lua_tostring(L, -1)); + lua_settop(L, 0); + return STATE_LOAD_FILE_ERR; + } - struct lua_plugin_manage_schema *new_schema = (struct lua_plugin_manage_schema *)calloc(1, sizeof(struct lua_plugin_manage_schema)); - if (__glibc_unlikely(!new_schema)) - return NULL; - memset(new_schema, 0, sizeof(struct lua_plugin_manage_schema)); - global_schema = new_schema; + /* 创建on_load函数及on_unload函数的引用 */ + lua_getglobal(L, spec->spec_load_func_name); + if (lua_type(L, -1) != LUA_TFUNCTION) + { + snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_load_func_name); + return STATE_REF_TYPE_ERR; + } + script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (script->lua_load_fn_ref_id <= 0) + { + snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_load_func_name, script->lua_load_fn_ref_id); + return STATE_CREATE_REF_FAIL; + } + lua_getglobal(L, spec->spec_unload_func_name); + if (lua_type(L, -1) != LUA_TFUNCTION) + { + snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_unload_func_name); + return STATE_REF_TYPE_ERR; + } + script->lua_unload_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (script->lua_unload_fn_ref_id <= 0) + { + snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_unload_func_name, script->lua_unload_fn_ref_id); + return STATE_CREATE_REF_FAIL; + } - new_schema->st = st; - /* 可能运行过程中创建新的topic, 此处进行初始化 */ - new_schema->mq_count = 0; - utarray_new(new_schema->message_mq_array, &lua_message_mq_icd); + /* 创建依赖于该script的script_env, 并调用on_load函数 */ + lua_newtable(L); + script->lua_script_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (script->lua_script_env_ref_id <= 0) + { + snprintf(errlog, (errlog_len - 1), "spec[%s] create script env failed, ref is %d\n", spec->spec_file_path, script->lua_script_env_ref_id); + return STATE_CREATE_REF_FAIL; + } + + struct lua_cdata param[2]; + param[0].type = DATATYPE_POINTER; + param[0].pointer = (void *)st; + param[1].type = DATATYPE_TABLE; + param[1].table = script->lua_script_env_ref_id; + char exec_err[1024] = {0}; + int exec_ret = lua_chunk_execute(state, script->lua_load_fn_ref_id, param, 2, NULL, 0, exec_err, sizeof(exec_err)); + if (exec_ret) + { + snprintf(errlog, (errlog_len - 1), "spec[%s]%s call fail, err num %d, err %s\n", spec->spec_file_path, spec->spec_load_func_name, exec_ret, exec_err); + return STATE_CALL_LOAD_FAILED; + } + + return SUCCESS; +}; + +// static UT_icd lua_session_plugin_icd = {sizeof(struct lua_session_plugin_env), NULL, NULL, NULL}; +// static UT_icd lua_packet_plugin_icd = {sizeof(struct lua_packet_plugin_env), NULL, NULL, NULL}; +// static UT_icd lua_message_free_icd = {sizeof(struct lua_message_free_arg), NULL, NULL, NULL}; + +struct lua_plugin_manage *lua_plugin_manage_init( + struct stellar *st, + struct lua_config_spec specific[], + size_t specific_num) +{ + if (!st) + return NULL; + char errlog[1024] = {0}; + + struct lua_plugin_manage *new_plugin_manage = (struct lua_plugin_manage *)calloc(1, sizeof(struct lua_plugin_manage)); + memset(new_plugin_manage, 0, sizeof(struct lua_plugin_manage)); + + new_plugin_manage->st = st; int thread_count = stellar_get_worker_thread_num(st); - if (thread_count == 0) - /* 无活动线程 */ - return new_schema; -#ifdef LUAPLUGIN_BASIC_UNITTEST - LOGDEBUG("get stellar thread num is %d", thread_count); -#endif - new_schema->state_count = thread_count; - /* 为后续待创建的lua_State预分配内存 */ - new_schema->thread_state = (lua_State **)calloc(thread_count, sizeof(lua_State *)); - if (__glibc_unlikely(!new_schema->thread_state)) + if (thread_count <= 0) + return new_plugin_manage; + new_plugin_manage->state_num = thread_count; + new_plugin_manage->state = (struct lua_state **)calloc(thread_count, sizeof(struct lua_state *)); + memset(new_plugin_manage->state, 0, thread_count * sizeof(struct lua_state *)); + for (int thread_index = 0; thread_index < thread_count; thread_index++) { - lua_plugin_manage_exit(new_schema); - return NULL; + new_plugin_manage->state[thread_index] = thread_state_init(thread_index, st, new_plugin_manage); } - memset(new_schema->thread_state, 0, thread_count * sizeof(lua_State *)); - /* 为将要加载的模块预分配内存 */ - new_schema->model_count = specific_count; - /* 如果没有配置, 也应该算是创建成功 */ - if (specific_count == 0) - return new_schema; - new_schema->model = (struct lua_model **)calloc(specific_count, sizeof(struct lua_model *)); - if (__glibc_unlikely(!new_schema->model)) + + for (unsigned on_message_index = 0; on_message_index < HASH_MAX_NUM; on_message_index++) { - lua_plugin_manage_exit(new_schema); - return NULL; + new_plugin_manage->on_session_message_hashlist[on_message_index].on_use = on_message_index; + new_plugin_manage->on_packet_message_hashlist[on_message_index].on_use = on_message_index; } - memset(new_schema->model, 0, specific_count * sizeof(struct lua_model *)); - /* 依次初始化每个状态机 */ - for (int thread_index = 0; thread_index < thread_count; ++thread_index) + new_plugin_manage->load_script = (struct lua_load_script *)calloc(specific_num, sizeof(struct lua_load_script)); + new_plugin_manage->load_script_num = specific_num; + for (unsigned spec_index = 0; spec_index < specific_num; spec_index++) { - /* 创建状态机 */ - new_schema->thread_state[thread_index] = thread_state_init(thread_index); - if (__glibc_unlikely(!new_schema->thread_state[thread_index])) + if (lua_state_load_one_specific(new_plugin_manage->state[0], + &specific[spec_index], + &new_plugin_manage->load_script[spec_index], + st, + errlog, + sizeof(errlog))) { - lua_plugin_manage_exit(new_schema); - return NULL; - } - - for (int spec_index = 0; spec_index < specific_count; ++spec_index) - { - /* BugFix: 由于追加model的函数, 拷贝动作可能导致model指针与注册至pluginmanage的指针不一致 */ - new_schema->model[spec_index] = (struct lua_model *)calloc(1, sizeof(struct lua_model)); - if (__glibc_unlikely(!new_schema->model[spec_index])) - { - lua_plugin_manage_exit(new_schema); - return NULL; - } - /* 在状态机中加载specific中的配置 */ - int load_ret = thread_state_load_specific(new_schema->thread_state[thread_index], - new_schema->model[spec_index], - &specific[spec_index]); - if (load_ret) - { - LOGERROR("state load specific failed, ret is %d", load_ret); - lua_plugin_manage_exit(new_schema); - return NULL; - } - - /* 调用该模块中的load函数 */ - int call_load_ret = thread_state_call_load(new_schema->thread_state[thread_index], - new_schema->model[spec_index], - &specific[spec_index], - st); - if (call_load_ret) - { - LOGERROR("call state load function failed, ret is %d", call_load_ret); - lua_plugin_manage_exit(new_schema); - return NULL; - } + printf("%s\n", errlog); + goto err; } } -#ifdef LUAPLUGIN_BASIC_UNITTEST - debug_lua_plugin_manage_schema(new_schema); -#endif - /* 初始化全局状态统计 */ - global_plugin_statistics = (struct lua_plugin_statistics *)calloc((thread_count * global_max_plugin_id), sizeof(struct lua_plugin_statistics)); - if (!global_plugin_statistics) + lua_newtable((lua_State *)new_plugin_manage->state[0]); + int lua_ref_max_id = luaL_ref((lua_State *)new_plugin_manage->state[0], LUA_REGISTRYINDEX); + struct lua_cdata *trans_data = lua_cdata_new(); + for (int ref_index = (LUA_GLOBAL_VALUE_REF_ID + 1); ref_index < lua_ref_max_id; ref_index++) { - LOGERROR("create plugin statistics failed"); - lua_plugin_manage_exit(new_schema); - return NULL; + lua_settop((lua_State *)new_plugin_manage->state[0], 0); + lua_rawgeti((lua_State *)new_plugin_manage->state[0], LUA_REGISTRYINDEX, ref_index); + lua_cdata_pop_stack(new_plugin_manage->state[0], trans_data); + for (int thread_index = 1; thread_index < thread_count; thread_index++) + { + lua_cdata_push_stack(new_plugin_manage->state[thread_index], trans_data); + int ref_id = luaL_ref((lua_State *)new_plugin_manage->state[thread_index], LUA_REGISTRYINDEX); + printf("ref to new thread, ref id is %d, %d\n", ref_index, ref_id); + } + lua_cdata_inner_data_free(trans_data); } - return new_schema; + return new_plugin_manage; + +err: + lua_plugin_manage_exit(new_plugin_manage); + return NULL; } -/* - * Function: - * Input: - * Output: - * Return: - * Description: - */ -int lua_plugin_manage_load_one_specific( - struct lua_plugin_manage_schema *schema, - struct lua_config_specific *specific) +void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr) { - if (__glibc_unlikely(!schema || !specific)) - return -1; - - if (schema->model) - { - schema->model = (struct lua_model **)realloc(schema->model, (schema->model_count + 1) * sizeof(struct lua_model *)); - schema->model_count += 1; - } - /* BugFix: 在某些情况下, 该内存未初始化会导致加载失败 */ - memset(&schema->model[schema->model_count - 1], 0, sizeof(struct lua_model *)); - schema->model[schema->model_count - 1] = (struct lua_model *)calloc(1, sizeof(struct lua_model)); - if (__glibc_unlikely(!schema->model[schema->model_count - 1])) - { - LOGERROR("calloc for new model failed\n"); - return -1; - } - - for (int thread_index = 0; thread_index < schema->state_count; ++thread_index) - { - /* 在状态机中加载specific中的配置 */ - int load_ret = thread_state_load_specific(schema->thread_state[thread_index], - schema->model[schema->model_count - 1], - specific); - if (load_ret) - { - LOGERROR("state load specific failed, ret is %d", load_ret); - return -1; - } - - /* 调用该模块中的load函数 */ - int call_load_ret = thread_state_call_load(schema->thread_state[thread_index], - schema->model[schema->model_count - 1], - specific, - schema->st); - if (call_load_ret) - { - LOGERROR("call state load function failed, ret is %d", call_load_ret); - return -1; - } - } - - if (global_plugin_statistics) - free(global_plugin_statistics); - /* 初始化全局状态统计 */ - global_plugin_statistics = (struct lua_plugin_statistics *)calloc((schema->state_count * global_max_plugin_id), sizeof(struct lua_plugin_statistics)); - if (!global_plugin_statistics) - { - LOGERROR("create plugin statistics failed"); - return -1; - } -#ifdef LUAPLUGIN_BASIC_UNITTEST - debug_lua_plugin_manage_schema(schema); -#endif - - return 0; -} - -/* - * Function: - * Input: - * Output: - * Return: - * Description: - */ -void lua_plugin_manage_exit(struct lua_plugin_manage_schema *lua_plug_mgr) -{ - if (__glibc_unlikely(!lua_plug_mgr)) + if (!lua_plug_mgr) return; - /* 释放所有的状态机 */ - for (int state_index = 0; state_index < lua_plug_mgr->state_count; ++state_index) + for (unsigned script_index = 0; script_index < lua_plug_mgr->load_script_num; script_index ++) { - for (int model_index = 0; model_index < lua_plug_mgr->model_count; ++model_index) - { - /* 在状态机中对每一个模块调用对应的卸载函数 */ - int call_unload_ret = thread_state_call_unload(lua_plug_mgr->thread_state[state_index], - lua_plug_mgr->model[model_index]); - if (call_unload_ret) - { - LOGERROR("call state unload function failed, ret is %d", call_unload_ret); - } - } - /* 销毁状态机 */ - lua_close(lua_plug_mgr->thread_state[state_index]); + struct lua_cdata param; + param.type = DATATYPE_TABLE; + param.table = lua_plug_mgr->load_script[script_index].lua_script_env_ref_id; + lua_chunk_execute(lua_plug_mgr->state[0], lua_plug_mgr->load_script[script_index].lua_unload_fn_ref_id, ¶m, 1, NULL, 0, NULL, 0); } - free(lua_plug_mgr->thread_state); + free(lua_plug_mgr->load_script); - /* 释放所有加载的模块 */ - for (int model_index = 0; model_index < lua_plug_mgr->model_count; ++model_index) + for (unsigned state_index = 0; state_index < lua_plug_mgr->state_num; ++state_index) { - utarray_free(lua_plug_mgr->model[model_index]->plugin_array); - free(lua_plug_mgr->model[model_index]); + lua_close((lua_State *)lua_plug_mgr->state[state_index]); } - free(lua_plug_mgr->model); + free(lua_plug_mgr->state); - if (lua_plug_mgr->message_mq_array) - utarray_free(lua_plug_mgr->message_mq_array); + struct lua_session_plugin_env * session_env = lua_plug_mgr->session_plugin_env_list; + while (session_env) { + struct lua_session_plugin_env * next = session_env->next; + free(session_env); + session_env = next; + } + + struct lua_packet_plugin_env * packet_env = lua_plug_mgr->packet_plugin_env_list; + while (packet_env) { + struct lua_packet_plugin_env * next = packet_env->next; + free(packet_env); + packet_env = next; + } + + struct lua_message_free_arg * message_free_arg = lua_plug_mgr->message_free_arg_list; + while (message_free_arg) { + struct lua_message_free_arg * next = message_free_arg->next; + free(message_free_arg); + message_free_arg = next; + } free(lua_plug_mgr); return; -} - -/* - * Function: - * Input: - * Output: - * Return: - * Description: 获取某插件的运行成功及失败次数 - */ -void lua_plugin_get_statistics(int plugin_id, int thread_id, int *new_success, int *new_fail, int *free_success, int *free_fail) -{ - int statistic_id = thread_id * global_max_plugin_id + plugin_id; - if (new_success) - *new_success = global_plugin_statistics[statistic_id].new_success_count; - if (new_fail) - *new_fail = global_plugin_statistics[statistic_id].new_failed_count; - if (free_success) - *free_success = global_plugin_statistics[statistic_id].free_success_count; - if (free_fail) - *free_fail = global_plugin_statistics[statistic_id].free_failed_count; - return; -} - -void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema) -{ - printf("\n***** begin to debug one lua schema *****\n"); - printf("schema.st is %p\n", schema->st); - printf("schema state count is %d\n", schema->state_count); - for (int i = 0; i < schema->state_count; ++i) - { - printf("schema state[%d]pointer is %p\n", i, schema->thread_state[i]); - } - printf("schema model count is %d\n", schema->model_count); - for (int i = 0; i < schema->model_count; ++i) - { - printf("debug model[%d] %p\n", i, &schema->model[i]); - printf("array %p, load %d, unload %d, env %d, mark %04x, count %d\n", - schema->model[i]->plugin_array, schema->model[i]->load_ref, schema->model[i]->unload_ref, - schema->model[i]->private_env_ref, schema->model[i]->model_mark, schema->model[i]->plugin_count); - struct lua_plugin *plugin = NULL; - while ((plugin = utarray_next(schema->model[i]->plugin_array, plugin))) - { - printf("%d, %d, %d\n", plugin->plugin_id, plugin->ctx_new_ref, plugin->ctx_free_ref); - } - } - printf("schema total plugin count is %d\n", schema->plugin_count); - - printf("***** end of debug one lua schema *****\n\n"); -} - -#ifdef LUAPLUGIN_BASIC_UNITTEST -void debug_lua_state_stack(lua_State *state, int mod, const char *message) -{ - int stackcount = lua_gettop(state); - /* nothing in stack */ - if (!stackcount) - { - printf("debug stack, but stack is empty"); - return; - } - - printf("\n***** begin to debug one lua stack *****\n"); - if (message) - printf("debug here: %s\n", message); - int i = stackcount; - /* print variables one by one */ - for (; i > 0; --i) - { - /* adjust variables according to mod */ - if (mod) - i = 0 - i; - int type = lua_type(state, i); - printf("stack[%d]: ", i); - switch (type) - { - case LUA_TBOOLEAN: - printf(lua_toboolean(state, i) ? "true\n" : "false\n"); - break; - case LUA_TNUMBER: - printf("%g\n", lua_tonumber(state, i)); - break; - case LUA_TSTRING: - printf("%s\n", lua_tostring(state, i)); - break; - default: - printf("this is not normal type, type is: %d[%s]\n", type, lua_typename(state, type)); - break; - } - /* adjust variables according to mod */ - if (mod) - i = 0 - i; - } - printf("***** end of debug one lua stack *****\n\n"); -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/lua_plugin_manage_internal.h b/src/lua_plugin_manage_internal.h index 2f153c2..57f6e62 100644 --- a/src/lua_plugin_manage_internal.h +++ b/src/lua_plugin_manage_internal.h @@ -1,123 +1,34 @@ -/************************************************************************* - > File Name: lua_plugin_manage_internal.h - > Author: - > Created Time: 2024-08 - > Encoding : UTF-8 - ************************************************************************/ - -/************************************************************************* - * version - * [ v0.1 ] - * 08-02 - * 完成函数注册及数据注册功能 - * 1. 声明及定义结构 - * struct lua_binding_function; - * enum BINDING_DATATYPE; - * struct lua_binding_data; - * 2. 声明函数 - * int lua_cbinding_function; - * int lua_cbinding_function_remove; - * int lua_cbinding_data; - * int lua_cbinding_data_remove; - * int lua_cbinding_functions; - * int lua_cbinding_datas; - * - * 08-05 - * 基本完成lua_plugin_manage中主流程 - * 1. 声明及定义结构 - * struct lua_config_specific; - * struct lua_script; - * struct lua_session_plugin; - * struct lua_plugin_env; - * struct lua_thread_state; - * struct lua_plugin_manage_schema; - * 2. 声明函数 - * void specific_instance_copy; - * void specific_instance_destory; - * int script_instance_init_byname; - * int script_instance_init_byrefid; - * void script_instance_clean; - * int script_execute; (暂未实现) - * int session_plugin_instance_init; - * void session_plugin_instance_destory; - * int plugin_env_instance_init; - * void plugin_env_instance_destory; - * int thread_state_instance_init; - * void thread_state_instance_destory; - * int thread_state_instance_load; - * int lua_plugin_manage_config_load; - * int lua_plugin_manage_thread_load; - * - * 08-06 - * 完成数据相关操作, 并补全函数script_execute - * 完成注册至C插件管理器中的session_ctx_new_func及session_ctx_free_func函数 - * 1. 声明并定义结构 - * struct lua_cdata; - * struct lua_context; - * 2. 声明函数 - * int lua_cdata_push_stack; - * int lua_cdata_pop_stack; - * void lua_cdata_destory; - * struct lua_context * lua_context_new; - * int lua_context_push_stack; - * void lua_context_free; - * - * void *lpm_ctx_new_func; - * void lpm_ctx_free_func; - * - * 08-07 - * BugFix: - * 修改struct lua_plugin_env, 其中增加文件路径 - * 防止在加载过程中由于函数重名导致的加载错误 - * - * 08-08 - * 整体重构状态机相关结构定义, 拆分高频访问数据与低频访问数据 - * 状态机中数据管理由树形结构修改为数组型结构 - * 经过多次验证, 相同状态机在执行相同操作后返回结果及中间产物一致, 合并一些冗余数据 - * 1. 声明并定义结构 - * struct lua_plugin_statistics; - * struct lua_plugin; - * struct lua_model; - * struct lua_plugin_manage_schema; - * - * 08-14 - * 新增message相关结构定义 - * 1. 声明并定义结构 - * struct lua_plugin_mq; - * struct lua_message_mq; - * 2. 声明函数 - * void lpm_message_free_func - * void lpm_on_session_msg_func - * struct lua_plugin * search_plugin_by_id - * struct lua_message_mq * search_message_mq_by_id - ************************************************************************/ #ifndef LUA_PLUGIN_MANAGE_INTERNAL_H #define LUA_PLUGIN_MANAGE_INTERNAL_H +#include #include "lua_plugin_manage.h" -#include "lpm_log.h" -#include -#include -#include -#include +struct lua_state; -enum LUA_PLUGIN_RETURN +enum LUA_PLUGIN_MANGE_ERR_NUM { /* 状态机相关的错误码 */ STATE_LOAD_FILE_ERR = -400, /* 状态机加载lua文件时出错, 可能原因是文件不存在或文件无法加载 */ - STATE_CREATE_ENV_FAIL, /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */ - STATE_GET_LOAD_FAIL, /* 状态机加载load函数时出现错误, 该函数不存在或引用ID有问题 */ - STATE_GET_UNLOAD_FAIL, /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */ + STATE_REF_TYPE_ERR, /* 获取函数引用ID过程中数据类型有错, 无法正常执行 */ + STATE_CREATE_REF_FAIL, /* 创建引用ID过程中失败, 无法创建refid */ + STATE_CALL_LOAD_FAILED, /* 调用on_load函数过程中运行失败 */ + STATE_CALL_UNLOAD_FAILED, /* 调用on_unload函数过程中运行失败 */ + + STATE_CREATE_ENV_FAIL, /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */ + STATE_GET_UNLOAD_FAIL, /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */ /* lua代码块运行错误码 */ CHUNK_TYPE_NOT_FUNCTION = -300, /* 获取得到的代码块类型并非可执行的lua语句, 无法执行 */ CHUNK_RUN_CODE_FAIL, /* 调用代码过程中运行失败, 失败的具体报错信息会保存在栈中, 通过日志输出 */ - CHUNK_RCOUNT_ERR, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */ + + CHUNK_RCOUNT_ERR, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */ /* lua与C之间数据转换或操作错误码 */ - DATA_PUSHSTACK_ERR = -200, /* 数据入栈过程中遇到未知的问题 */ - DATA_POPSTACK_ERR, /* 数据从状态机中出栈过程中遇到未知的问题 */ - DATA_POPSTACK_NODATA, /* 出栈过程中栈内无数据, 导致出栈失败 */ - DATA_TYPE_UNKNOWN, /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */ + DATA_TYPE_UNKNOWN = -200, /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */ + DATA_TYPE_ERR, /* 获取到了错误的数据类型 */ + + DATA_PUSHSTACK_ERR, /* 数据入栈过程中遇到未知的问题 */ + DATA_POPSTACK_ERR, /* 数据从状态机中出栈过程中遇到未知的问题 */ + DATA_POPSTACK_NODATA, /* 出栈过程中栈内无数据, 导致出栈失败 */ /* lua函数或数据绑定错误码 */ BIND_NAMESPACE_TYPE_ERR = -100, /* 绑定或删除过程中使用命名空间, 但命名空间数据类型不符 */ BIND_FUNCTION_TYPE_ERR, /* 绑定或删除函数过程中数据类型错误 */ @@ -129,236 +40,184 @@ enum LUA_PLUGIN_RETURN }; /* ***** ***** ***** ***** ***** ***** */ -/* 此部分主要功能为C向lua中注册函数及数据, 实现在lua_plugin_binding.c中 */ /* 需要注册至lua中的函数 */ -struct lua_binding_function +typedef int (*lua_cbind_func)(struct lua_state *state); +struct lua_bind_function_spec { - /* 注册函数原型 */ - lua_CFunction function; - /* 注册至lua中的函数名称 */ - char *function_name; - /* 注册至lua中的命名空间名称 */ - char *space_name; + lua_cbind_func function; /* 注册函数原型 */ + char *func_name; /* 注册至lua中的函数名称 */ + char *space_name; /* 注册至lua中的命名空间名称 */ }; +int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num); -/* 定义在lua_plugin_binding.c文件中 */ -/* 所有需要注册至lua状态机中供lua调用的函数 */ -extern struct lua_binding_function lua_bind_functions[]; +struct lua_context +{ + struct lua_state *state; + int lua_context_ref_id; +}; +struct lua_context *lua_context_new(struct lua_state *state); +void lua_context_free(struct lua_context *context); +void lua_context_push_stack(struct lua_context *context); -/* 暂时支持前四种数据类型提前注册至lua状态机中 */ -/* 其余类型用于运行lua函数等场景 */ enum DATATYPE { DATATYPE_BEGIN = 0, - /* nil类型 */ - DATATYPE_NIL, - /* bool类型 */ - DATATYPE_BOOL, - /* int类型 */ - DATATYPE_INT, - /* double类型 */ - DATATYPE_NUM, - /* 字符串类型 */ - DATATYPE_STRING, - /* 以下类型不能用于全局变量注册, 仅用于函数等场景 */ - /* table类型 */ - DATATYPE_TABLE, - /* 指针类型 */ - DATATYPE_POINTER, - /* context上下文类型 */ - DATATYPE_CONTEXT, + DATATYPE_NIL, /* nil类型 */ + DATATYPE_BOOL, /* bool类型 */ + DATATYPE_INT, /* int类型 */ + DATATYPE_NUM, /* double类型 */ + DATATYPE_STRING, /* 字符串类型 */ + /* 以下类型不能用于全局变量注册 */ + DATATYPE_TABLE, /* table类型 */ + DATATYPE_LUA_TABLE, /* 此类型用于在lua之间翻译传递数据 */ + DATATYPE_POINTER, /* 指针类型 */ + DATATYPE_CONTEXT, /* context上下文类型 */ + DATATYPE_FUNCTION, /* 函数类型 */ DATATYPE_END }; /* 需要注册至lua状态机中的数据 */ -struct lua_binding_data +struct lua_bind_data_spec { - /* 注册的数据类型 */ - enum DATATYPE data_type; - /* 注册数数据值 */ - char *data_value; - /* 注册的数据名称 */ - char *data_name; - /* 注册至lua中的命名空间名称 */ - char *space_name; + enum DATATYPE data_type; /* 注册的数据类型 */ + char *data_value; /* 注册数数据值 */ + char *data_name; /* 注册的数据名称 */ + char *space_name; /* 注册至lua中的命名空间名称 */ }; +int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num); -/* 定义在lua_plugin_binding.c中 */ -/* 所有需要注册至lua状态机中的全局数据 */ -extern struct lua_binding_data lua_bind_datas[]; - -/* 将lua_bind_functions中提前注册的所有函数注册至state状态机中 */ -int lua_cbinding_functions(lua_State *state); -/* 将lua_bind_datas中提前注册的所有数据注册至state状态机中 */ -int lua_cbinding_datas(lua_State *state); - -/* ***** ***** ***** ***** ***** ***** */ -/* 此部分主要用于lua与C之间的数据转换与传递, 实现在lua_plugin_data.c中 */ struct lua_cdata; -// struct lua_ctable; -struct lua_context; +struct lua_cnode; +struct lua_ctable; -/* 保存lua数据的结构 */ struct lua_cdata { - enum DATATYPE cdata_type; + enum DATATYPE type; + size_t data_len; /* 只有在类型为function时使用此标识 */ union { - int cdata_bool; - int cdata_int; - double cdata_num; - char *cdata_string; - /* table暂时只有plugin_env场景下使用, 暂时使用索引进行操作 */ - int cdata_table; - void *cdata_pointer; - struct lua_context *cdata_context; + int bool; + int integer; + double number; + char *string; + + int table; + void *pointer; + struct lua_context *context; + void *function; + struct lua_ctable *ctable; }; }; -/* 将一个data结构入栈 */ -int lua_cdata_push_stack(lua_State *state, struct lua_cdata *cdata); -/* 从栈中弹出一个元素, 并保存在data结构中 */ -int lua_cdata_pop_stack(lua_State *state, struct lua_cdata *cdata); -/* 销毁一个data结构, 只有string类型需要调用此函数, 其他的情况直接释放即可 */ -void lua_cdata_destory(struct lua_cdata *cdata); - -/* 上下文结构, 保存临时数据 */ -struct lua_context +struct lua_cnode { - // lua_State *context_state; - int context_ref_id; + char *node_string_key; + int node_integer_key; + struct lua_cdata *node_data; }; -/* 在状态机中生成一个context */ -struct lua_context *lua_context_new(lua_State *state); -/* 将一个context入栈 */ -int lua_context_push_stack(lua_State *state, struct lua_context *context); -/* 释放一个context */ -void lua_context_free(lua_State *state, struct lua_context *context); - -/* ***** ***** ***** ***** ***** ***** */ -/* 此部分为注册至C中的lua通用函数, 实现在lua_plugin_cfunc.c中 */ -void *lpm_ctx_new_func(struct session *sess, void *plugin_env); -void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env); -void lpm_message_free_func(struct session *sess, void *msg, void *msg_free_arg); -void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env); - -/* ***** ***** ***** ***** ***** ***** */ -/* lua代码块相关操作, 实现在lua_plugin_chunk.c中 */ -/* 执行一段lua代码块, 执行之前需要先在lua中生成一个引用ID */ -int lua_chunk_execute(lua_State *state, int ref_id, int pcount, struct lua_cdata *params, int rcount, struct lua_cdata *returns); - -/* ***** ***** ***** ***** ***** ***** */ -/* TODO:统计插件的运行情况, 暂时没想好怎么用 */ -/* 记录一个插件的运行状态 */ -struct lua_plugin_statistics +struct lua_ctable { - /* ctx_new函数调用成功的次数 */ - int new_success_count; - /* ctx_new函数调用失败的次数 */ - int new_failed_count; - /* ctx_free函数调用成功的次数 */ - int free_success_count; - /* ctx_free函数调用失败的次数 */ - int free_failed_count; + size_t array_size; + size_t node_size; + struct lua_cdata **array_data; + struct lua_cnode **node_data; }; -/* 状态机相关的一些数据结构及操作, 实现在lua_plugin_manage.c中 */ -extern struct lua_plugin_manage_schema *global_schema; -/* 保存插件的运行情况, 运行次数等信息 */ -/* 二维数组修改为一维数组, 方便使用偏移快速查找 */ -extern struct lua_plugin_statistics *global_plugin_statistics; -/* 最大插件编号 */ -extern int global_max_plugin_id; -#define LUA_MQ_ENV_DEFAULT_KEY "__mqenv_pointer" -#define LUA_MQ_TOPIC_ID_KEY "topic_id" -/* 保存lua插件注册的消息队列信息 */ -struct lua_plugin_mq +struct lua_cdata *lua_cdata_new(void); +void lua_cdata_free(struct lua_cdata *cdata); +int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata); +int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata); +struct lua_ctable *lua_ctable_new(void); +void lua_ctable_free(struct lua_ctable *ctable); +int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable); +int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable); +struct lua_cnode *lua_cnode_new(void); +void lua_cnode_free(struct lua_cnode *cnode); + +/* ***** ***** ***** ***** ***** ***** */ +int lua_chunk_execute(struct lua_state *state, int fn_ref_id, struct lua_cdata param[], size_t param_num, struct lua_cdata returnvalue[], size_t r_num, char *errlog, size_t err_len); + +/* ***** ***** ***** ***** ***** ***** */ +struct lua_load_script { - /* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */ + int lua_load_fn_ref_id; + int lua_unload_fn_ref_id; + int lua_script_env_ref_id; +}; + +struct lua_session_plugin_env +{ + struct lua_session_plugin_env *next; + struct lua_plugin_manage *plugin_manage; + int session_plugin_id; + int lua_ctx_new_fn_ref_id; + int lua_ctx_free_fn_ref_id; + int lua_plug_env_ref_id; +}; + +struct lua_packet_plugin_env +{ + struct lua_packet_plugin_env *next; + struct lua_plugin_manage * plugin_manage; + int packet_plugin_id; + int lua_on_packet_fn_ref_id; + int lua_plug_env_ref_id; +}; + +struct lua_message_free_arg +{ + struct lua_message_free_arg *next; + struct lua_plugin_manage * plugin_manage; int topic_id; - /* 如果是订阅的topic必须包含处理函数 */ - int onmessage_ref; + int lua_msg_free_fn_ref_id; + int lua_msg_free_arg_ref_id; }; -/* 保存Lua插件信息 */ -struct lua_plugin +struct lua_on_message_fn { - /* 注册完成后得到的插件ID */ + int on_use; + int topic_id; int plugin_id; - /* context_new函数在状态机中的引用值 */ - int ctx_new_ref; - /* context_free函数在状态机中的引用值 */ - int ctx_free_ref; - /* 该插件中订阅的topic */ - UT_array *sub_topic_array; + int lua_on_msg_fn_ref_id; }; -void lua_plugin_destory(void *elt); -/* 根据ID号在整个schema中进行遍历 */ -struct lua_plugin *search_plugin_by_id(int plugin_id); -#define MODEL_MARK_INIT_DONE 0x0001 -#define MODEL_MARK_LOAD_DONE 0x0002 +#define HASH_MAX_NUM 1024 +int calc_on_message_func_hash_key(int topic_id, int plugin_id); +struct lua_on_message_fn * hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id); +struct lua_on_message_fn * hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id); -#define LUA_PLUGIN_ENV_DEFAULT_KEY "__penv_pointer" -/* 加载的lua模块, 一个lua模块一般来说对应一个lua文件, 与C插件管理中的so相同 */ -struct lua_model -{ - /* 该模块注册后的插件列表 */ - UT_array *plugin_array; - /* 该模块load函数在状态机中的引用值 */ - int load_ref; - /* 该模块unload函数在状态机中的引用值 */ - int unload_ref; - /* 该模块创建出的plugin_env数据在状态机中的引用值 */ - int private_env_ref; - /* 初始化过程中的标记 */ - unsigned short model_mark; - /* 加载的插件数量 */ - unsigned short plugin_count; -}; -/* 在一个状态机中初始化一个模块 */ -int thread_state_load_specific(lua_State *state, struct lua_model *model, struct lua_config_specific *specific); +#define LUA_GLOBAL_THREAD_ID_KEY "__global_thread_id" +#define LUA_GLOBAL_STELLAR_POINTER "__global_stellar_pointer" +#define LUA_GLOBAL_PLUGIN_MANGE_POINTER "__global_plugin_managee_pointer" -/* 由lua创建的topic结构, 该结构保存在schema中 */ -struct lua_message_mq -{ - /* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */ - int topic_id; - /* 如果是新创建的topic, 必须包含释放函数 */ - int freemessage_ref; - /* 创建一个消息处理私有数据, 对应session_mq中的msg_free_arg */ - int mq_private_ref; - // char * topic_name; -}; -/* 根据topic_id在schema中查找一个message对应的函数 */ -struct lua_message_mq *search_message_mq_by_id(int topic_id); +// int lua_state_get_thread_id(struct lua_state * state); +// struct stellar * lua_state_get_stellar(struct lua_state * state); +struct lua_plugin_manage * lua_state_get_plugin_manage(struct lua_state * state); -#define LUA_STATE_THREAD_ID_KEY "__thread_id" -struct lua_plugin_manage_schema +struct lua_plugin_manage { struct stellar *st; - /* 创建的状态机数量, 状态机数量与线程的个数相同 */ - int state_count; - /* 插入模块的数量, 模块的数量与specific的数量相同 */ - int model_count; - /* 注册的消息队列的数量 */ - int mq_count; - /* 所有模块中注册的插件总数量 */ - int plugin_count; + size_t state_num; + size_t load_script_num; + struct lua_state **state; + struct lua_load_script *load_script; - /* 线程状态机 */ - lua_State **thread_state; - /* 所有插入的模块 */ - struct lua_model **model; - /* TODO: 创建的所有message topic id理论上应该是连续的, 可以考虑用hash数组, 寻址能更快 */ - UT_array *message_mq_array; + // UT_array *session_plugin_env; + // UT_array *packet_plugin_env; + // UT_array *message_free_arg; + struct lua_session_plugin_env *session_plugin_env_list; + struct lua_packet_plugin_env *packet_plugin_env_list; + struct lua_message_free_arg *message_free_arg_list; + + struct lua_on_message_fn on_session_message_hashlist[HASH_MAX_NUM]; + struct lua_on_message_fn on_packet_message_hashlist[HASH_MAX_NUM]; }; -#ifdef LUAPLUGIN_BASIC_UNITTEST -void debug_lua_state_stack(lua_State *state, int mod, const char *message); -void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema); -#endif +struct lua_plugin_manage *lua_plugin_manage_init(struct stellar *st, struct lua_config_spec specifics[], size_t specific_count); +void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr); + + #endif \ No newline at end of file