summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniubinghui <[email protected]>2024-09-06 16:29:07 +0800
committerniubinghui <[email protected]>2024-09-06 16:29:07 +0800
commitf8dcaabfbdd3b00113251d220dce231ef1696205 (patch)
tree826daa67798b13f514cb98e4102182c01ea1529e
parentb6780f7f4a41edb3c1f423c10f72d7e826d20983 (diff)
【修改】重新梳理数据结构并重构部分逻辑
-rwxr-xr-xbuild.sh1
-rw-r--r--include/lua_plugin_manage.h42
-rw-r--r--src/Makefile14
-rw-r--r--src/lpm_log.h22
-rw-r--r--src/lua_binding_function.c576
-rw-r--r--src/lua_binding_function.h50
-rw-r--r--src/lua_binding_functions.c830
-rw-r--r--src/lua_binding_functions.h54
-rw-r--r--src/lua_plugin_binding.c472
-rw-r--r--src/lua_plugin_cfunc.c363
-rw-r--r--src/lua_plugin_chunk.c107
-rw-r--r--src/lua_plugin_data.c214
-rw-r--r--src/lua_plugin_manage.c1307
-rw-r--r--src/lua_plugin_manage_internal.h431
14 files changed, 1721 insertions, 2762 deletions
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_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;
-void lua_plugin_get_statistics(int plugin_id, int thread_id, int *new_success, int *new_fail, int *free_success, int *free_fail);
+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 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 <stdio.h>
-
-/* 简单定义一个日志输出, 可根据实际的日志输出调整定义 */
-/* 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 <stdlib.h>
+#include <string.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <utlist.h>
+
+#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 <stdlib.h>
-#include <string.h>
-
-/* 需要注册至状态机中的函数定义在链表中, 会依次完成注册 */
-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))
- return NULL;
- struct lua_model *env = (struct lua_model *)plugin_env;
-
- /* 获取插件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)
- /* 未找到该插件 */
+ if (!plugin_env)
return NULL;
+ 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并找到该线程对应的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;
-
- if (lua_chunk_execute(state, plugin->ctx_new_ref, 3, param, 0, NULL))
+ 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, 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;
+ 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;
+}
- lua_chunk_execute(state, plugin_mq->freemessage_ref, 3, param, 0, NULL);
- lua_context_free(state, (struct lua_context *)msg);
+void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env)
+{
+ if (!plugin_env)
+ return;
+ 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;
+
+ 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;
}
-/*
- * 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_packet_func(struct packet *pkt, unsigned char ip_protocol, 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_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;
- /* 获取插件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)
- /* 未找到对应的消息处理函数 */
- return;
+ int thread_id = stellar_get_current_thread_id(st);
+ struct lua_state *state = plugin_manage->state[thread_id];
- /* 判断该消息是由C端插件产生的还是由Lua插件产生的 */
- struct lua_message_mq *message_mq = search_message_mq_by_id(topic_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;
+}
- int thread_id = session_get_current_thread_id(sess);
- if (thread_id > global_schema->state_count)
+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, &params[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 <time.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-
-struct lua_plugin_manage_schema *global_schema = NULL;
-
-#if 0
-void lua_message_mq_destory(void * elt)
+#include <utlist.h>
+
+#include <lauxlib.h>
+#include <lualib.h>
+
+#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;
+ if (!state || !function_spec || !function_spec->function || !function_spec->func_name)
+ return PARAM_ERR;
+ lua_State *L = (lua_State *)state;
+
+ if (function_spec->space_name)
+ {
+ lua_getglobal(L, function_spec->space_name);
+ if (lua_type(L, -1) == LUA_TNIL)
+ {
+ lua_newtable(L);
+ lua_setglobal(L, function_spec->space_name);
+ lua_settop(L, 0);
+ lua_getglobal(L, function_spec->space_name);
+ }
+ else
+ {
+ if (lua_type(L, -1) != LUA_TTABLE)
+ {
+ lua_settop(L, 0);
+ return BIND_NAMESPACE_TYPE_ERR;
+ }
+
+ 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
+ {
+ 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);
+ }
+
+ lua_settop(L, 0);
+ return SUCCESS;
}
-static UT_icd lua_plugin_icd = {sizeof(struct lua_plugin), NULL, NULL, lua_plugin_destory};
-/*
- * 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)
+static int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec)
{
- for (int i = 0; i < global_schema->model_count; ++i)
+ 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
{
- struct lua_model *model = global_schema->model[i];
+ 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);
- struct lua_plugin *plugin = NULL;
- while ((plugin = utarray_next(model->plugin_array, plugin)))
+ switch (data_spec->data_type)
{
- if (plugin->plugin_id == plugin_id)
- return plugin;
- else if (plugin->plugin_id > plugin_id)
- return NULL;
+ 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);
}
- return NULL;
+
+ lua_settop(L, 0);
+ return SUCCESS;
}
-/*
- * 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)
+int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num)
{
- struct lua_message_mq *mq = NULL;
- while ((mq = utarray_next(global_schema->message_mq_array, mq)))
+ int failed_count = 0;
+ for (unsigned index = 0; index < bind_func_num; index++)
{
- if (mq->topic_id == topic_id)
- return mq;
+ if (lua_cbinding_single_function(state, &bind_function[index]))
+ failed_count++;
}
- return NULL;
+ return failed_count;
}
-/*
- * Function: thread_state_init
- * Input: | int | thread_id | 创建状态机的线程号
- * Output:
- * Return: 创建完成的状态机实例指针
- * Description: 创建一个lua的状态机实例, 在每个线程中创建一个
- */
-lua_State *thread_state_init(int thread_id)
-{
- lua_State *new_state = luaL_newstate();
- if (__glibc_unlikely(!new_state))
+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;
- luaL_openlibs(new_state);
- /* 绑定所有注册函数 */
- lua_cbinding_functions(new_state);
- /* 绑定所有全局变量 */
- lua_cbinding_datas(new_state);
+ lua_newtable(L);
+ int ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
+ if (ref_id == LUA_REFNIL)
+ return NULL;
- lua_pushinteger(new_state, thread_id);
- lua_setglobal(new_state, LUA_STATE_THREAD_ID_KEY);
+ 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_settop(new_state, 0);
+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;
+}
- return new_state;
+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;
}
-/*
- * 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)
-{
- 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;
+/* ***** ***** ***** ***** ***** ***** */
+/* 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;
+}
- /* 加载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);
+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
- /* 创建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;
- }
+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;
+}
- /* 加载load函数 */
- lua_getglobal(state, specific->config_specific_load_func);
- if (lua_type(state, -1) != LUA_TFUNCTION)
+static void lua_cdata_inner_data_free(struct lua_cdata *cdata)
+{
+ if (!cdata)
+ return;
+ cdata->type = 0;
+ cdata->data_len = 0;
+ switch (cdata->type)
{
- luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
- lua_settop(state, 0);
- return STATE_GET_LOAD_FAIL;
+ 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;
}
- int load_ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
- if (load_ref_id == LUA_REFNIL)
+ 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)
{
- luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
- lua_settop(state, 0);
- return STATE_GET_LOAD_FAIL;
+ 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;
}
- if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->load_ref != load_ref_id))
+ 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))
{
- LOGERROR("load new model, load ref id is not same, %d, %d", model->load_ref, load_ref_id);
- return STATE_GET_LOAD_FAIL;
+ 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;
+}
- /* 加载unload函数 */
- lua_getglobal(state, specific->config_specific_unload_func);
- if (lua_type(state, -1) != LUA_TFUNCTION)
+void lua_ctable_free(struct lua_ctable *ctable)
+{
+ if (!ctable)
+ return;
+ for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
{
- 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;
+ lua_cdata_free(ctable->array_data[array_index]);
}
- int unload_ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
- if (unload_ref_id == LUA_REFNIL)
+ for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
{
- 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;
+ lua_cnode_free(ctable->node_data[node_index]);
}
- if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->unload_ref != unload_ref_id))
+ 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++)
{
- LOGERROR("load new model, unload ref id is not same, %d, %d", model->unload_ref, unload_ref_id);
- return STATE_GET_UNLOAD_FAIL;
+ lua_pushinteger(L, (array_index + 1));
+ lua_cdata_push_stack(state, ctable->array_data[array_index]);
+ lua_settable(L, -3);
}
-
- /* 首次加载时完成model初始化 */
- if (!(model->model_mark & MODEL_MARK_INIT_DONE))
+ for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
{
- 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;
+ 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);
}
- lua_settop(state, 0);
return SUCCESS;
}
-/*
- * 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)
-{
- if (__glibc_unlikely(!state || !model || !specific || !st))
+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;
- if ((!(model->model_mark & MODEL_MARK_LOAD_DONE)) && (!model->plugin_array))
+ /* 获取table长度 */
+ ctable->array_size = (size_t)lua_rawlen(L, -1);
+ lua_pushnil(L);
+ while (lua_next(L, -2))
{
- utarray_new(model->plugin_array, &lua_plugin_icd);
- model->model_mark |= MODEL_MARK_LOAD_DONE;
+ 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);
}
- 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);
+ 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();
+ }
- 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;
+ /* 依次获取数据 */
+ 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 lua_chunk_execute(state, model->load_ref, 2, params, 0, NULL);
+ return SUCCESS;
}
-/*
- * 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, &param, 0, NULL);
+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;
}
-/*
- * Function:
- * Input:
- * Output:
- * Return:
- * Description:
- */
-struct lua_plugin_manage_schema *lua_plugin_manage_init(
- struct stellar *st,
- int specific_count,
- struct lua_config_specific *specific)
+void lua_cnode_free(struct lua_cnode *cnode)
{
- 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 (cnode->node_string_key)
+ free(cnode->node_string_key);
+ if (cnode->node_data)
+ lua_cdata_free(cnode->node_data);
+ free(cnode);
+ return;
+}
- 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;
+/* ***** ***** ***** ***** ***** ***** */
+/* 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;
- new_schema->st = st;
- /* 可能运行过程中创建新的topic, 此处进行初始化 */
- new_schema->mq_count = 0;
- utarray_new(new_schema->message_mq_array, &lua_message_mq_icd);
+ 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 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))
- {
- lua_plugin_manage_exit(new_schema);
- return NULL;
+ int pushret = 0;
+ for (unsigned param_index = 0; param_index < param_num; ++param_index)
+ {
+ if ((pushret = lua_cdata_push_stack(state, &param[param_index])))
+ {
+ lua_settop(L, 0);
+ return pushret;
+ }
}
- 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))
+
+ if (lua_pcall(L, param_num, LUA_MULTRET, 0))
{
- lua_plugin_manage_exit(new_schema);
- return NULL;
+ 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;
}
- memset(new_schema->model, 0, specific_count * sizeof(struct lua_model *));
- /* 依次初始化每个状态机 */
- for (int thread_index = 0; thread_index < thread_count; ++thread_index)
+ if (r_num > 0)
{
- /* 创建状态机 */
- new_schema->thread_state[thread_index] = thread_state_init(thread_index);
- if (__glibc_unlikely(!new_schema->thread_state[thread_index]))
+ int count = lua_gettop(L);
+ /* 如果接收返回值数量不够, 只保留前r_num个返回值 */
+ if (count > (int)r_num)
{
- lua_plugin_manage_exit(new_schema);
- return NULL;
+ lua_pop(L, (count - (int)r_num));
+ count = (int)r_num;
}
-
- for (int spec_index = 0; spec_index < specific_count; ++spec_index)
+ int pop_ret = 0;
+ for (int i = (count - 1); i >= 0; --i)
{
- /* 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]))
+ if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i]))))
{
- 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;
+ lua_settop(L, 0);
+ return pop_ret;
}
}
}
-#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_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)
{
- LOGERROR("create plugin statistics failed");
- lua_plugin_manage_exit(new_schema);
+ 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)
- return new_schema;
+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:
- * Input:
- * Output:
- * Return:
- * Description:
- */
-int lua_plugin_manage_load_one_specific(
- struct lua_plugin_manage_schema *schema,
- struct lua_config_specific *specific)
+int lua_state_get_thread_id(struct lua_state * state)
{
- if (__glibc_unlikely(!schema || !specific))
- return -1;
+ 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;
+}
+
+struct stellar * lua_state_get_stellar(struct lua_state * state)
+{
+ 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 (schema->model)
+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;
+}
+
+static int lua_state_load_one_specific(
+ struct lua_state *state,
+ struct lua_config_spec *spec,
+ struct lua_load_script *script,
+ struct stellar *st,
+ char *errlog,
+ size_t errlog_len)
+{
+ 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))
{
- schema->model = (struct lua_model **)realloc(schema->model, (schema->model_count + 1) * sizeof(struct lua_model *));
- schema->model_count += 1;
+ 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;
}
- /* 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]))
+
+ /* 创建on_load函数及on_unload函数的引用 */
+ lua_getglobal(L, spec->spec_load_func_name);
+ if (lua_type(L, -1) != LUA_TFUNCTION)
{
- LOGERROR("calloc for new model failed\n");
- return -1;
+ 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;
}
-
- for (int thread_index = 0; thread_index < schema->state_count; ++thread_index)
+ script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
+ if (script->lua_load_fn_ref_id <= 0)
{
- /* 在状态机中加载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;
- }
+ 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;
+ }
- /* 调用该模块中的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;
- }
+ /* 创建依赖于该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;
}
- 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)
+ 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)
{
- LOGERROR("create plugin statistics failed");
- return -1;
+ 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;
}
-#ifdef LUAPLUGIN_BASIC_UNITTEST
- debug_lua_plugin_manage_schema(schema);
-#endif
- return 0;
-}
+ return SUCCESS;
+};
-/*
- * Function:
- * Input:
- * Output:
- * Return:
- * Description:
- */
-void lua_plugin_manage_exit(struct lua_plugin_manage_schema *lua_plug_mgr)
-{
- if (__glibc_unlikely(!lua_plug_mgr))
- return;
+// 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));
- /* 释放所有的状态机 */
- for (int state_index = 0; state_index < lua_plug_mgr->state_count; ++state_index)
+ new_plugin_manage->st = st;
+
+ int thread_count = stellar_get_worker_thread_num(st);
+ 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++)
{
- 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]);
+ new_plugin_manage->state[thread_index] = thread_state_init(thread_index, st, new_plugin_manage);
}
- free(lua_plug_mgr->thread_state);
- /* 释放所有加载的模块 */
- for (int model_index = 0; model_index < lua_plug_mgr->model_count; ++model_index)
+ for (unsigned on_message_index = 0; on_message_index < HASH_MAX_NUM; on_message_index++)
{
- utarray_free(lua_plug_mgr->model[model_index]->plugin_array);
- free(lua_plug_mgr->model[model_index]);
+ 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;
}
- free(lua_plug_mgr->model);
- if (lua_plug_mgr->message_mq_array)
- utarray_free(lua_plug_mgr->message_mq_array);
-
- 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)
+ 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++)
{
- printf("schema state[%d]pointer is %p\n", i, schema->thread_state[i]);
+ 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)))
+ {
+ printf("%s\n", errlog);
+ goto err;
+ }
}
- printf("schema model count is %d\n", schema->model_count);
- for (int i = 0; i < schema->model_count; ++i)
+
+ 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++)
{
- 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)))
+ 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++)
{
- printf("%d, %d, %d\n", plugin->plugin_id, plugin->ctx_new_ref, plugin->ctx_free_ref);
+ 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);
}
- printf("schema total plugin count is %d\n", schema->plugin_count);
- printf("***** end of debug one lua schema *****\n\n");
+ return new_plugin_manage;
+
+err:
+ lua_plugin_manage_exit(new_plugin_manage);
+ return NULL;
}
-#ifdef LUAPLUGIN_BASIC_UNITTEST
-void debug_lua_state_stack(lua_State *state, int mod, const char *message)
+void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr)
{
- int stackcount = lua_gettop(state);
- /* nothing in stack */
- if (!stackcount)
- {
- printf("debug stack, but stack is empty");
+ if (!lua_plug_mgr)
return;
+
+ for (unsigned script_index = 0; script_index < lua_plug_mgr->load_script_num; script_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, &param, 1, NULL, 0, NULL, 0);
}
+ free(lua_plug_mgr->load_script);
- 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)
+ for (unsigned state_index = 0; state_index < lua_plug_mgr->state_num; ++state_index)
{
- /* 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;
+ lua_close((lua_State *)lua_plug_mgr->state[state_index]);
}
- printf("***** end of debug one lua stack *****\n\n");
-}
-#endif \ No newline at end of file
+ free(lua_plug_mgr->state);
+
+ 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;
+} \ 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 <stddef.h>
#include "lua_plugin_manage.h"
-#include "lpm_log.h"
-#include <utarray.h>
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
+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);
+struct lua_ctable
+{
+ size_t array_size;
+ size_t node_size;
+ struct lua_cdata **array_data;
+ struct lua_cnode **node_data;
+};
-/* ***** ***** ***** ***** ***** ***** */
-/* 此部分为注册至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);
+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);
/* ***** ***** ***** ***** ***** ***** */
-/* 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);
+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);
/* ***** ***** ***** ***** ***** ***** */
-/* TODO:统计插件的运行情况, 暂时没想好怎么用 */
-/* 记录一个插件的运行状态 */
-struct lua_plugin_statistics
+struct lua_load_script
{
- /* ctx_new函数调用成功的次数 */
- int new_success_count;
- /* ctx_new函数调用失败的次数 */
- int new_failed_count;
- /* ctx_free函数调用成功的次数 */
- int free_success_count;
- /* ctx_free函数调用失败的次数 */
- int free_failed_count;
+ int lua_load_fn_ref_id;
+ int lua_unload_fn_ref_id;
+ int lua_script_env_ref_id;
};
-/* 状态机相关的一些数据结构及操作, 实现在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_session_plugin_env
{
- /* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */
- int topic_id;
- /* 如果是订阅的topic必须包含处理函数 */
- int onmessage_ref;
+ 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;
};
-/* 保存Lua插件信息 */
-struct lua_plugin
+struct lua_packet_plugin_env
{
- /* 注册完成后得到的插件ID */
- int plugin_id;
- /* context_new函数在状态机中的引用值 */
- int ctx_new_ref;
- /* context_free函数在状态机中的引用值 */
- int ctx_free_ref;
- /* 该插件中订阅的topic */
- UT_array *sub_topic_array;
+ 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;
};
-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 LUA_PLUGIN_ENV_DEFAULT_KEY "__penv_pointer"
-/* 加载的lua模块, 一个lua模块一般来说对应一个lua文件, 与C插件管理中的so相同 */
-struct lua_model
+struct lua_message_free_arg
{
- /* 该模块注册后的插件列表 */
- 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;
+ struct lua_message_free_arg *next;
+ struct lua_plugin_manage * plugin_manage;
+ int topic_id;
+ int lua_msg_free_fn_ref_id;
+ int lua_msg_free_arg_ref_id;
};
-/* 在一个状态机中初始化一个模块 */
-int thread_state_load_specific(lua_State *state, struct lua_model *model, struct lua_config_specific *specific);
-/* 由lua创建的topic结构, 该结构保存在schema中 */
-struct lua_message_mq
+struct lua_on_message_fn
{
- /* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */
+ int on_use;
int topic_id;
- /* 如果是新创建的topic, 必须包含释放函数 */
- int freemessage_ref;
- /* 创建一个消息处理私有数据, 对应session_mq中的msg_free_arg */
- int mq_private_ref;
- // char * topic_name;
+ int plugin_id;
+ int lua_on_msg_fn_ref_id;
};
-/* 根据topic_id在schema中查找一个message对应的函数 */
-struct lua_message_mq *search_message_mq_by_id(int topic_id);
-#define LUA_STATE_THREAD_ID_KEY "__thread_id"
-struct lua_plugin_manage_schema
+#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_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"
+
+// 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);
+
+struct lua_plugin_manage
{
struct stellar *st;
- /* 创建的状态机数量, 状态机数量与线程的个数相同 */
- int state_count;
- /* 插入模块的数量, 模块的数量与specific的数量相同 */
- int model_count;
- /* 注册的消息队列的数量 */
- int mq_count;
- /* 所有模块中注册的插件总数量 */
- int plugin_count;
-
- /* 线程状态机 */
- lua_State **thread_state;
- /* 所有插入的模块 */
- struct lua_model **model;
- /* TODO: 创建的所有message topic id理论上应该是连续的, 可以考虑用hash数组, 寻址能更快 */
- UT_array *message_mq_array;
+ size_t state_num;
+ size_t load_script_num;
+ struct lua_state **state;
+ struct lua_load_script *load_script;
+
+ // 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