summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniubinghui <[email protected]>2024-08-06 10:15:48 +0800
committerniubinghui <[email protected]>2024-08-06 10:15:48 +0800
commitdc63983f77361ba94e5bdb4093019c0afda9961c (patch)
treeb2db40df90ed4f93e40abe37ea922c58ea3c19f5
parent4f7a98d2ddc8f25d04dc89bce080dcb508293688 (diff)
【新增】主流程基本完成,需要修改的部分主要为脚本执行位置
-rw-r--r--src/lpm_log.h22
-rw-r--r--src/lua_plugin_binding.c529
-rw-r--r--src/lua_plugin_manage.c649
-rw-r--r--src/lua_plugin_manage_internal.h272
4 files changed, 1472 insertions, 0 deletions
diff --git a/src/lpm_log.h b/src/lpm_log.h
new file mode 100644
index 0000000..09b8ab4
--- /dev/null
+++ b/src/lpm_log.h
@@ -0,0 +1,22 @@
+#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_plugin_binding.c b/src/lua_plugin_binding.c
new file mode 100644
index 0000000..bcf5039
--- /dev/null
+++ b/src/lua_plugin_binding.c
@@ -0,0 +1,529 @@
+/*************************************************************************
+ > 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_session_regist;
+ * ** 注册函数lua_plugin_manage_session_regist还需要补充
+ ************************************************************************/
+#include "lua_plugin_manage_internal.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* 需要注册至lua中供lua调用的所有函数原型 */
+int lua_plugin_manage_session_regist(lua_State * state);
+
+/* 需要注册至状态机中的函数定义在链表中, 会依次完成注册 */
+struct lua_binding_function lua_bind_functions[] = {
+ {lua_plugin_manage_session_regist, "register", "plugin_manage"},
+ {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},
+};
+
+/*
+ * Function: lua_cbinding_function
+ * Input: | lua_State * | state | 需要注册函数的状态机
+ * | lua_CFunction | bind_function | 需要注册的函数
+ * | const char * | function_name | 注册函数的名称
+ * | const char * | space_name | 注册函数的命名空间
+ * Output:
+ * Return: | 0 | 注册成功
+ * | -1 | 传入的参数有错误
+ * | -2 | 命名空间已经存在, 且命名空间不是table类型, 无法新增成员
+ * | -3 | 命名空间中已经存在函数名称对应成员, 无法完成覆盖
+ * | -4 | 存在全局的函数名称, 无法完成注册
+ * Description: 将一个C函数注册至lua中
+ */
+int lua_cbinding_function(
+ lua_State *state,
+ lua_CFunction bind_function,
+ const char *function_name,
+ const char *space_name)
+{
+ if (__glibc_unlikely(!state || !bind_function || !function_name))
+ return -1;
+
+ if (space_name)
+ {
+ /* 包含space_name, 调用时为 space_name.function_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 -2;
+ }
+
+ lua_getfield(state, -1, function_name);
+ if (lua_type(state, -1) != LUA_TNIL)
+ {
+ /* 在待插入的global table中存在与function_name重名的成员 */
+ lua_settop(state, 0);
+ return -3;
+ }
+ lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */
+ }
+
+ lua_pushcfunction(state, bind_function);
+ lua_setfield(state, -2, function_name);
+ }
+ else
+ {
+ lua_getglobal(state, function_name);
+ if (lua_type(state, -1) != LUA_TNIL)
+ {
+ /* 存在与function_name重名的全局成员 */
+ lua_settop(state, 0);
+ return -4;
+ }
+ lua_pop(state, 1);
+
+ /* 不包含space_name, 调用时直接使用function_name调用 */
+ lua_pushcfunction(state, bind_function);
+ lua_setglobal(state, function_name);
+ }
+
+ lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
+ return 0;
+}
+
+/*
+ * Function: lua_cbinding_function_remove
+ * Input: | lua_State * | state | 需要删除注册函数的状态机
+ * | const char * | function_name | 需要删除的函数名称
+ * | const char * | space_name | 需要删除的命名空间名称
+ * Output:
+ * Return: | 0 | 删除成功
+ * | -1 | 参数错误
+ * | -2 | 命名空间存在但不是一个table
+ * | -3 | 命名空间中存在函数名称对应成员, 但是类型不是函数
+ * | -4 | 函数名称对应的成员不是一个函数
+ * 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 -1;
+
+ if (space_name)
+ {
+ /* 检查该命名空间是否存在 */
+ lua_getglobal(state, space_name);
+ if (lua_type(state, -1) != LUA_TTABLE)
+ {
+ /* 命名空间存在且不是table */
+ lua_settop(state, 0);
+ return -2;
+ }
+ /* 检查该命名空间内是否存在function_name */
+ lua_getfield(state, -1, function_name);
+ if (lua_type(state, -1) != LUA_TFUNCTION)
+ {
+ /* 命名空间存在内部元素名称为function_name, 但是类型不符 */
+ lua_settop(state, 0);
+ return -3;
+ }
+ /* 删除该函数 */
+ 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 -4;
+ }
+ /* 删除该函数 */
+ lua_pop(state, 1);
+ lua_pushnil(state);
+ lua_setglobal(state, function_name);
+ }
+
+ lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
+ return 0;
+}
+
+/*
+ * Function: lua_cbinding_data
+ * Input: | lua_State * | state | 需要注册数据的状态机
+ * | struct lua_binding_data * | data | 需要注册至状态机中的数据
+ * Output:
+ * Return: | 0 | 注册成功
+ * | -1 | 传入的参数有错误
+ * | -2 | 命名空间已经存在, 且命名空间不是table类型, 无法新增成员
+ * | -3 | 命名空间中已经存在函数名称对应成员, 无法完成覆盖
+ * | -4 | 无法识别data的数据类型
+ * | -5 | 全局变量名称已经有成员, 不为空
+ * Description: 将一个变量注册至lua状态机中
+ */
+int lua_cbinding_data(
+ lua_State *state,
+ struct lua_binding_data *data)
+{
+ if (__glibc_unlikely(!state || !data))
+ {
+ return -1;
+ }
+ enum DATATYPE data_type = data->binding_data_type;
+ char *value = data->binding_data_value;
+ char *data_name = data->binding_data_name;
+ char *space_name = data->binding_data_space_name;
+ if (__glibc_unlikely(!value || !data_name))
+ return -1;
+
+ 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 -2;
+ }
+
+ lua_getfield(state, -1, data_name);
+ if (lua_type(state, -1) != LUA_TNIL)
+ {
+ /* 在待插入的global table中存在与function_name重名的成员 */
+ lua_settop(state, 0);
+ return -3;
+ }
+ 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 -4;
+ }
+ 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 -5;
+ }
+ 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 -4;
+ }
+ lua_setglobal(state, data_name);
+ }
+
+ lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
+ return 0;
+}
+
+/*
+ * Function: lua_cbinding_data_remove
+ * Input: | lua_State * | state | 需要删除注册数据的状态机
+ * | const char * | data_name | 需要删除的数据名称
+ * | const char * | space_name | 需要删除的命名空间名称
+ * Output:
+ * Return: | 0 | 删除成功
+ * | -1 | 参数错误
+ * | -2 | 命名空间存在但不是一个table
+ * | -3 | 命名空间中存在数据名称对应成员, 但是类型不符
+ * | -4 | 函数名称对应的成员类型不符
+ * 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 -1;
+
+ if (space_name)
+ {
+ /* 检查该命名空间是否存在 */
+ lua_getglobal(state, space_name);
+ if (lua_type(state, -1) != LUA_TTABLE)
+ {
+ /* 命名空间存在且不是table */
+ lua_settop(state, 0);
+ return -2;
+ }
+ /* 检查该命名空间内是否存在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 -3;
+ }
+ else if (data_type == LUA_TNIL)
+ {
+ /* 没有该名称的元素 */
+ lua_settop(state, 0);
+ return 0;
+ }
+ /* 删除该函数 */
+ 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 -4;
+ }
+ else if (data_type == LUA_TNIL)
+ {
+ /* 没有该名称的元素 */
+ lua_settop(state, 0);
+ return 0;
+ }
+ /* 删除该函数 */
+ lua_pop(state, 1);
+ lua_pushnil(state);
+ lua_setglobal(state, data_name);
+ }
+
+ lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
+ return 0;
+}
+
+/*
+ * 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 -1;
+ 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].binding_function && lua_bind_functions[i].binding_function_name)
+ {
+ bind_ret = lua_cbinding_function(state,
+ lua_bind_functions[i].binding_function,
+ (const char *)lua_bind_functions[i].binding_function_name,
+ (const char *)lua_bind_functions[i].binding_function_space_name);
+ if (bind_ret)
+ {
+ LOGERROR("binding function failed, ret is %d, function name is %s\n", bind_ret, lua_bind_functions[i].binding_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].binding_data_value && lua_bind_datas[i].binding_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].binding_data_name, lua_bind_datas[i].binding_data_value);
+ failed_count += 1;
+ }
+ }
+ }
+ return failed_count;
+}
+
+/*
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Description:
+ */
+int lua_plugin_manage_session_regist(lua_State *state)
+{
+ /* 参数个数检查 */
+ if (lua_gettop(state) != 4)
+ {
+ lua_settop(state, 0);
+ return 0;
+ }
+
+ /* 参数类型检查 */
+ if (lua_type(state, -1) != LUA_TLIGHTUSERDATA || lua_type(state, -2) != LUA_TFUNCTION ||
+ lua_type(state, -3) != LUA_TFUNCTION || lua_type(state, -4) != LUA_TLIGHTUSERDATA)
+ {
+ lua_settop(state, 0);
+ return 0;
+ }
+
+ /* 取出处理第四个参数 */
+ struct lua_plugin_env *plugin_env = (struct lua_plugin_env *)lua_topointer(state, -1);
+ if (!plugin_env)
+ {
+ lua_settop(state, 0);
+ return 0;
+ }
+ lua_pop(state, 1);
+
+ /* 取出处理第三个参数 */
+ int ctx_free_id = luaL_ref(state, LUA_REGISTRYINDEX);
+ if (ctx_free_id == LUA_REFNIL)
+ {
+ lua_settop(state, 0);
+ return 0;
+ }
+ lua_pop(state, 1);
+
+ /* 取出处理第二个参数 */
+ int ctx_new_id = luaL_ref(state, LUA_REGISTRYINDEX);
+ if (ctx_new_id == LUA_REFNIL)
+ {
+ lua_settop(state, 0);
+ return 0;
+ }
+ lua_pop(state, 1);
+#if 0
+ /* 取出处理第一个参数 */
+ struct stellar * st = (struct stellar *)lua_topointer(state, -1);
+ if ( !st ) {
+ 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);
+
+ /* 将注册完成的新插件插入到队列中 */
+ struct lua_session_plugin session_plugin;
+ memset(&session_plugin, 0, sizeof(session_plugin));
+ session_plugin_instance_init(&session_plugin, state, plugin_id, ctx_new_id, ctx_free_id);
+
+ utarray_push_back(plugin_env->lua_plugin_env_plugin_array, &session_plugin);
+ lua_pushinteger(state, plugin_id);
+#endif
+ return 1;
+}
diff --git a/src/lua_plugin_manage.c b/src/lua_plugin_manage.c
new file mode 100644
index 0000000..df155ff
--- /dev/null
+++ b/src/lua_plugin_manage.c
@@ -0,0 +1,649 @@
+/*************************************************************************
+ > 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;
+ ************************************************************************/
+#include "lua_plugin_manage_internal.h"
+#include "lpm_log.h"
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <toml.h>
+
+static UT_icd specific_icd = {sizeof(struct lua_config_specific), NULL, specific_instance_copy, specific_instance_destory};
+static UT_icd session_plugin_icd = {sizeof(struct lua_session_plugin), NULL, NULL, session_plugin_instance_destory};
+static UT_icd plugin_env_icd = {sizeof(struct lua_plugin_env), NULL, NULL, plugin_env_instance_destory};
+static UT_icd thread_state_icd = {sizeof(struct lua_thread_state), NULL, NULL, thread_state_instance_destory};
+
+/*
+ * Function: specific_instance_copy
+ * Input: | void * | dst | 拷贝数据目的地址
+ * | void * | src | 拷贝数据源地址
+ * Output:
+ * Return:
+ * Description: 配置的插件信息拷贝函数, 由于可能存在多线程, 将数据完整拷贝一次
+ */
+void specific_instance_copy(void *dst, const void *src)
+{
+ struct lua_config_specific *dst_spec = (struct lua_config_specific *)dst;
+ struct lua_config_specific *src_spec = (struct lua_config_specific *)src;
+ if (__glibc_unlikely(!dst_spec || !src_spec))
+ return;
+ dst_spec->lua_config_specific_file = strdup(src_spec->lua_config_specific_file);
+ // dst_spec->lua_config_specific_name = strdup(src_spec->lua_config_specific_name);
+ dst_spec->lua_config_specific_load_func = strdup(src_spec->lua_config_specific_load_func);
+ dst_spec->lua_config_specific_unload_func = strdup(src_spec->lua_config_specific_unload_func);
+ return;
+}
+
+/*
+ * Function: specific_instance_destory
+ * Input: | void * | elt | 待销毁的specific实例
+ * Output:
+ * Return:
+ * Description: 销毁一个specific实例, 并释放内部占用的内存
+ */
+void specific_instance_destory(void *elt)
+{
+ struct lua_config_specific *element = (struct lua_config_specific *)elt;
+ if (!element)
+ return;
+ if (element->lua_config_specific_file)
+ free(element->lua_config_specific_file);
+ // if (element->lua_config_specific_name)
+ // free(element->lua_config_specific_name);
+ if (element->lua_config_specific_load_func)
+ free(element->lua_config_specific_load_func);
+ if (element->lua_config_specific_unload_func)
+ free(element->lua_config_specific_unload_func);
+ return;
+}
+
+/*
+ * Function: script_instance_init_byname
+ * Input: | struct lua_script * | script | 需要进行初始化的脚本结构
+ * | lua_State * | state | 脚本注册使用的状态机
+ * | const char * | filepath | 脚本加载的文件路径
+ * | const char * | funcname | 脚本加载的函数名称
+ * Output:
+ * Return: | 0 | 加载成功
+ * | -1 | 参数错误
+ * | -3 | 状态机读取文件失败
+ * | -4 | 状态机加载文件后运行失败
+ * | -5 | 加载函数过程中未找到该函数
+ * | -6 | 创建函数引用ID失败
+ * Description: 将一个lua文件中的函数创建成一个lua_script结构, 方便调用运行
+ */
+int script_instance_init_byname(
+ struct lua_script *script,
+ lua_State *state,
+ const char *filepath,
+ const char *funcname)
+{
+ if (__glibc_unlikely(!script || !state || !filepath || !funcname))
+ return -1;
+
+#if 0
+ /* 在加载配置文件的时候检查过了, 这里不检查 */
+ if (access(filepath, F_OK))
+ /* 文件不存在 */
+ return -2;
+#endif
+ if (luaL_loadfile(state, filepath))
+ /* 加载文件失败 */
+ return -3;
+ /* 仅加载不运行 */
+ // lua_settop(state, 0);
+ /* Bugfix: 这里还是需要运行一次, 否则可能加载不完整 */
+ if (lua_pcall(state, 0, 0, 0))
+ {
+ /* 文件加载完成后检查存在错误 */
+ lua_settop(state, 0);
+ return -4;
+ }
+ lua_settop(state, 0);
+
+ /* 加载全局变量, 找到函数后进行类型判断 */
+ lua_getglobal(state, funcname);
+ if (lua_type(state, -1) != LUA_TFUNCTION)
+ {
+ /* 在已经加载的文件中未找到对应的函数名称 */
+ lua_settop(state, 0);
+ return -5;
+ }
+ /* 创建索引 */
+ int ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
+ if (ref_id == LUA_REFNIL)
+ {
+ /* 索引创建失败 */
+ lua_settop(state, 0);
+ return -6;
+ }
+
+ script_instance_init_byrefid(script, state, ref_id);
+ lua_settop(state, 0);
+ return 0;
+}
+
+/*
+ * Function: script_instance_init_byrefid
+ * Input: | struct lua_script * | script | 需要进行初始化的脚本结构
+ * | lua_State * | state | 脚本注册使用的状态机
+ * | int | ref_id | 代码已经在状态机中生成的refid
+ * Output:
+ * Return: | 0 | 初始化成功
+ * | -1 | 参数错误
+ * Description: 根据已经生成的refid初始化一个脚本结构实例
+ */
+int script_instance_init_byrefid(
+ struct lua_script *script,
+ lua_State *state,
+ int ref_id)
+{
+ if (__glibc_unlikely(!script || !state || ref_id == LUA_REFNIL))
+ return -1;
+ script->script_state = state;
+ script->script_ref_id = ref_id;
+ script->script_run_success = 0;
+ script->script_run_failed = 0;
+ script->script_total_ms = 0;
+ return 0;
+}
+
+/*
+ * Function: script_instance_clean
+ * Input: | struct lua_script * | script | 需要清理的脚本实例
+ * Output:
+ * Return:
+ * Description: 清理一个脚本, 并在状态机中释放该脚本的引用
+ */
+void script_instance_clean(struct lua_script *script)
+{
+ if (__glibc_unlikely(!script))
+ return;
+
+ lua_State *state = script->script_state;
+ luaL_unref(state, LUA_REGISTRYINDEX, script->script_ref_id);
+ lua_settop(state, 0);
+ return;
+}
+
+/*
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Description:
+ */
+int script_execute(struct lua_script *script)
+{
+ if (!script)
+ return -1;
+ return 0;
+}
+
+/*
+ * Function: session_plugin_instance_init
+ * Input: | struct lua_session_plugin * | session_plugin | 需要进行初始化的插件实例
+ * | lua_State * | state | 插件注册使用的状态机
+ * | int | plugin_id | 插件注册完成后得到的插件编号
+ * | int | new_refid | ctx_new函数在状态机中的引用
+ * | int | free_refid | ctx_free函数在状态机中的引用
+ * Output:
+ * Return: | 0 | 初始化成功
+ * | -1 | 参数错误
+ * Description: 初始化一个插件实例
+ */
+int session_plugin_instance_init(
+ struct lua_session_plugin *session_plugin,
+ lua_State *state,
+ int plugin_id,
+ int new_refid,
+ int free_refid)
+{
+ if (__glibc_unlikely(!session_plugin || !state))
+ return -1;
+ session_plugin->plugin_id = plugin_id;
+ script_instance_init_byrefid(&session_plugin->plugin_ctx_new_script, state, new_refid);
+ script_instance_init_byrefid(&session_plugin->plugin_ctx_free_script, state, free_refid);
+ return 0;
+}
+
+/*
+ * Function: session_plugin_instance_destory
+ * Input: | void * | elt | 待销毁的插件实例
+ * Output:
+ * Return:
+ * Description: 销毁一个插件实例, 并将插件中引用的函数在状态机中释放
+ */
+void session_plugin_instance_destory(void *elt)
+{
+ if (__glibc_unlikely(!elt))
+ return;
+ struct lua_session_plugin *session_plugin = (struct lua_session_plugin *)elt;
+ script_instance_clean(&session_plugin->plugin_ctx_new_script);
+ script_instance_clean(&session_plugin->plugin_ctx_free_script);
+ return;
+}
+
+/*
+ * Function: plugin_env_instance_init
+ * Input: | struct lua_plugin_env * | plugin_env | 插件的运行环境实例
+ * | lua_State * | state | 插件注册的状态机
+ * | struct lua_config_specific * | specific | 插件需要加载的配置实例
+ * Output:
+ * Return: | 0 | 初始化成功
+ * | -1 | 参数错误
+ * | -2 | 加载函数加载错误
+ * | -3 | 卸载函数加载错误
+ * | -4 | 创建全局函数变量失败
+ * Description: 初始化一个插件的运行环境变量
+ */
+int plugin_env_instance_init(
+ struct lua_plugin_env *plugin_env,
+ lua_State *state,
+ struct lua_config_specific *specific)
+{
+ if (__glibc_unlikely(!plugin_env || !state || !specific))
+ return -1;
+
+ memset(plugin_env, 0, sizeof(struct lua_plugin_env));
+ plugin_env->lua_plugin_env_state = state;
+ plugin_env->lua_plugin_env_plugin_array = NULL;
+ // plugin_env->lua_plugin_env_name = strdup(specific->lua_config_specific_name);
+ /* 从文件中加载load函数, 但此时不调用 */
+ if (script_instance_init_byname(&plugin_env->lua_plugin_env_load_func,
+ state,
+ specific->lua_config_specific_file,
+ specific->lua_config_specific_load_func))
+ {
+ return -2;
+ }
+ /* 从文件中加载unload函数 */
+ if (script_instance_init_byname(&plugin_env->lua_plugin_env_unload_func,
+ state,
+ specific->lua_config_specific_file,
+ specific->lua_config_specific_unload_func))
+ {
+ script_instance_clean(&plugin_env->lua_plugin_env_load_func);
+ return -3;
+ }
+ /* 创建私有数据空间 */
+ lua_newtable(plugin_env->lua_plugin_env_state);
+ int ref_id = luaL_ref(plugin_env->lua_plugin_env_state, LUA_REGISTRYINDEX);
+ if (ref_id == LUA_REFNIL)
+ return -4;
+ plugin_env->lua_plugin_env_ref_id = ref_id;
+
+ return 0;
+}
+
+/*
+ * Function: plugin_env_instance_destory
+ * Input: | void * | elt | 待销毁的插件运行环境实例
+ * Output:
+ * Return:
+ * Description: 销毁一个插件运行环境实例, 并在状态机中释放其引用
+ */
+void plugin_env_instance_destory(void *elt)
+{
+ if (__glibc_unlikely(!elt))
+ return;
+ struct lua_plugin_env *plugin_env = (struct lua_plugin_env *)elt;
+ /* 释放已经注册的插件 */
+ if (plugin_env->lua_plugin_env_plugin_array)
+ utarray_free(plugin_env->lua_plugin_env_plugin_array);
+ /* 释放插件的加载函数与卸载函数 */
+ script_instance_clean(&plugin_env->lua_plugin_env_load_func);
+ script_instance_clean(&plugin_env->lua_plugin_env_unload_func);
+ /* 将lua中的私有环境数据取消引用 */
+ if (plugin_env->lua_plugin_env_ref_id)
+ luaL_unref(plugin_env->lua_plugin_env_state, LUA_REGISTRYINDEX, plugin_env->lua_plugin_env_ref_id);
+ return;
+}
+
+/*
+ * Function: thread_state_instance_init
+ * Input: | struct lua_thread_state * | thread_state | 待初始化的线程状态机
+ * | int | state_id | 线程的ID号
+ * Output:
+ * Return: | 0 | 初始化成功
+ * | -1 | 参数错误
+ * | -2 | 创建新的状态机失败
+ * Description: 在线程中创建一个状态机, 并进行初始化
+ */
+int thread_state_instance_init(
+ struct lua_thread_state *thread_state,
+ int state_id)
+{
+ if (__glibc_unlikely(!thread_state))
+ return -1;
+
+ lua_State *new_state = luaL_newstate();
+ if (__glibc_unlikely(!new_state))
+ return -2;
+ luaL_openlibs(new_state);
+ /* 绑定所有注册函数 */
+ lua_cbinding_functions(new_state);
+ /* 绑定所有全局变量 */
+ lua_cbinding_datas(new_state);
+ lua_settop(new_state, 0);
+
+ memset(thread_state, 0, sizeof(struct lua_thread_state));
+ thread_state->lua_thread_id = state_id;
+ thread_state->lua_thread_plugin_count = 0;
+ thread_state->lua_thread_state = new_state;
+ thread_state->lua_thread_env_array = NULL;
+ thread_state->lua_thread_begin_time = time(NULL);
+
+ return 0;
+}
+
+/*
+ * Function: thread_state_instance_destory
+ * Input: | void * | elt | 待销毁的状态机
+ * Output:
+ * Return:
+ * Description: 销毁一个线程状态机
+ */
+void thread_state_instance_destory(void *elt)
+{
+ if (__glibc_unlikely(!elt))
+ return;
+ struct lua_thread_state *thread_state = (struct lua_thread_state *)elt;
+ /* 卸载所有已经注册的插件 */
+ if (thread_state->lua_thread_env_array)
+ utarray_free(thread_state->lua_thread_env_array);
+ /* 关闭状态机 */
+ if (thread_state->lua_thread_state)
+ lua_close(thread_state->lua_thread_state);
+ return;
+}
+
+/*
+ * Function: thread_state_instance_load
+ * Input: | struct lua_thread_state * | thread_state | 进行初始化加载的状态机
+ * | struct lua_plugin_manage_schema * | schema | 已经完成配置读取的全局实例
+ * Output:
+ * Return: | 0 | 加载成功
+ * | -1 | 参数错误
+ * | -2 | 根据加载的配置初始化插件失败
+ * Description: 在线程的状态机中依次加载插件
+ */
+int thread_state_instance_load(
+ struct lua_thread_state *thread_state,
+ struct lua_plugin_manage_schema *schema)
+{
+ if (__glibc_unlikely(!thread_state || !schema))
+ return -1;
+
+ lua_State *state = thread_state->lua_thread_state;
+ utarray_new(thread_state->lua_thread_env_array, &plugin_env_icd);
+ utarray_reserve(thread_state->lua_thread_env_array, schema->lua_config_specific_count);
+ struct lua_config_specific *specific = NULL;
+
+ /* 读取所有插件并加入插件列表中 */
+ struct lua_plugin_env new_plugin_env;
+ while ((specific = utarray_next(schema->lua_config_specific_array, specific)))
+ {
+ memset(&new_plugin_env, 0, sizeof(new_plugin_env));
+ if (plugin_env_instance_init(&new_plugin_env, state, specific))
+ return -2;
+ utarray_push_back(thread_state->lua_thread_env_array, &new_plugin_env);
+ }
+
+ /* 依次执行插件加载函数, 调用lua中load函数 */
+ struct lua_plugin_env *plugin_env = NULL;
+ while ((plugin_env = utarray_next(thread_state->lua_thread_env_array, plugin_env)))
+ {
+ utarray_new(plugin_env->lua_plugin_env_plugin_array, &session_plugin_icd);
+ lua_rawgeti(state, LUA_REGISTRYINDEX, plugin_env->lua_plugin_env_ref_id);
+ /* 在lua中的全局参数中加入plugin_env指针 */
+ lua_pushlightuserdata(state, plugin_env);
+ lua_setfield(state, -2, PLUGIN_ENV_DEFAULT_KEY);
+ lua_settop(state, 0);
+
+ script_execute(&plugin_env->lua_plugin_env_load_func);
+ }
+
+ return 0;
+}
+
+/*
+ * Function: specific_check
+ * Input: | struct lua_config_specific * | specific | 待减产的配置项
+ * Output:
+ * Return: | 0 | 检查无问题
+ * | -1 | 参数错误
+ * | -2 | 配置中的插件文件不存在
+ * Description: 检查配置是否有明显问题
+ * TODO: 目前仅检查文件是否存在, 后续逐步补充, 比如文件内是否有不应该使用的函数等
+ */
+static int specific_check(struct lua_config_specific *specific)
+{
+ if (__glibc_unlikely(!specific))
+ return -1;
+
+ if (access(specific->lua_config_specific_file, F_OK))
+ return -2;
+
+ return 0;
+}
+
+/*
+ * Function: lua_plugin_manage_config_load
+ * Input: | struct lua_plugin_manage_schema * | scheme | 加载插件的全局变量
+ * | const char * | config_file_name | 插件配置文件
+ * Output:
+ * Return: | >=0 | 加载成功, 返回读取的配置插件数量
+ * | -1 | 参数错误
+ * | -2 | 配置文件不存在或打开文件错误
+ * | -3 | toml加载失败
+ * | -4 | 获取插件列表失败
+ * | -5 | 插件配置项错误
+ * | -6 | 插件配置检查出现问题
+ * Description: 从配置文件中读取所有插件配置
+ */
+int lua_plugin_manage_config_load(
+ struct lua_plugin_manage_schema *schema,
+ const char *config_file_name)
+{
+ if (__glibc_unlikely(!schema || !config_file_name))
+ return -1;
+ int specific_num = 0;
+ char errbuff[256] = {0};
+
+ if (access(config_file_name, F_OK))
+ return -2;
+ FILE *fp = fopen(config_file_name, "r");
+ if (!fp)
+ return -2;
+
+ toml_table_t *conf = toml_parse_file(fp, errbuff, sizeof(errbuff));
+ if (fp)
+ fclose(fp);
+ if (!conf)
+ {
+ LOGERROR("parse config file failed, filename %s, err %s\n", config_file_name, errbuff);
+ return -3;
+ }
+
+ toml_array_t *plugin_array = toml_array_in(conf, "plugin");
+ if (!plugin_array)
+ return -4;
+
+ /* 获取配置中配置的插件数量 */
+ specific_num = toml_array_nelem(plugin_array);
+ utarray_new(schema->lua_config_specific_array, &specific_icd);
+ utarray_reserve(schema->lua_config_specific_array, specific_num);
+ struct lua_config_specific *specific = (struct lua_config_specific *)calloc(sizeof(struct lua_config_specific), 1);
+
+ for (int i = 0; i < specific_num; ++i)
+ {
+ toml_table_t *plugin = toml_table_at(plugin_array, i);
+ const char *raw_filepath = toml_raw_in(plugin, "path");
+ // const char *raw_name = toml_raw_in(plugin, "name");
+ const char *raw_load_func_name = toml_raw_in(plugin, "init");
+ const char *raw_unload_func_name = toml_raw_in(plugin, "exit");
+
+ /* 从配置中拷贝字符串到specific实例中 */
+ if (toml_rtos(raw_filepath, &specific->lua_config_specific_file) ||
+ // toml_rtos(raw_name, &specific->lua_config_specific_name) ||
+ toml_rtos(raw_load_func_name, &specific->lua_config_specific_load_func) ||
+ toml_rtos(raw_unload_func_name, &specific->lua_config_specific_unload_func))
+ {
+ toml_free(conf);
+ free(specific);
+ return -5;
+ }
+
+ /* 插件配置检查 */
+ int spec_check_ret = specific_check(specific);
+ if (spec_check_ret)
+ {
+ LOGERROR("check specific failed, ret is %d\n", spec_check_ret);
+ toml_free(conf);
+ free(specific);
+ return -6;
+ }
+
+ /* 插入到队列中 */
+ utarray_push_back(schema->lua_config_specific_array, specific);
+ specific_instance_destory(specific);
+ }
+ free(specific);
+
+ /* 返回加载的插件数量 */
+ return specific_num;
+}
+
+/*
+ * Function: lua_plugin_manage_thread_load
+ * Input: | struct lua_plugin_manage_schema * | schema | 初始化的全局变量
+ * | int | thread_count | 初始化的线程数量
+ * Output:
+ * Return: | >= 0 | 创建完成, 并返回创建成功数量
+ * | -1 | 参数错误
+ * | -2 | 线程状态机初始化失败
+ * | -3 | 线程状态机加载过程失败
+ * Description: 依次创建好每个线程中的状态机
+ */
+int lua_plugin_manage_thread_load(
+ struct lua_plugin_manage_schema *schema,
+ int thread_count)
+{
+ if (__glibc_unlikely(!schema || thread_count <= 0 || thread_count >= LUA_PLUGIN_MANAGE_MAX_THREAD_COUNT))
+ return -1;
+
+ utarray_new(schema->lua_plugin_thread_array, &thread_state_icd);
+ utarray_reserve(schema->lua_plugin_thread_array, thread_count);
+ struct lua_thread_state new_thread_state;
+ for (int i = 1; i <= thread_count; ++i)
+ {
+ memset(&new_thread_state, 0, sizeof(new_thread_state));
+ if (thread_state_instance_init(&new_thread_state, i))
+ return -2;
+ utarray_push_back(schema->lua_plugin_thread_array, &new_thread_state);
+ }
+
+ struct lua_thread_state *thread_state = NULL;
+ while ((thread_state = utarray_next(schema->lua_plugin_thread_array, thread_state)))
+ {
+ if (thread_state_instance_load(thread_state, schema))
+ return -3;
+ }
+
+ return thread_count;
+}
+
+/*
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Description:
+ */
+struct lua_plugin_manage_schema *lua_plugin_manage_init(
+ struct stellar *st,
+ const char *config_file_path)
+{
+ if (__glibc_unlikely(!st || !config_file_path))
+ return NULL;
+
+ 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));
+
+ new_schema->lua_plugin_schema_st = st;
+ /* 从配置文件中加载插件 */
+ new_schema->lua_config_specific_count = lua_plugin_manage_config_load(new_schema, config_file_path);
+ LOGDEBUG("load config finish, load count is %d, file path is %s", new_schema->lua_config_specific_count, config_file_path);
+ if (new_schema->lua_config_specific_count < 0)
+ {
+ /* 可以没有插件配置, 但是不能在加载过程中出错 */
+ free(new_schema);
+ return NULL;
+ }
+#ifdef LUAPLUGIN_BASIC_UNITTEST
+ struct lua_config_specific *specific = NULL;
+ while ((specific = utarray_next(new_schema->lua_config_specific_array, specific)))
+ {
+ printf("path is %s\n", specific->lua_config_specific_file);
+ printf("load is %s\n", specific->lua_config_specific_load_func);
+ printf("unload is %s\n", specific->lua_config_specific_unload_func);
+ }
+#endif
+
+ int thread_count = 1;
+ /* 依次创建线程状态机, 并加入链表 */
+ new_schema->lua_plugin_thread_count = lua_plugin_manage_thread_load(new_schema, thread_count);
+
+ return new_schema;
+}
+
+/*
+ * 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;
+ if (lua_plug_mgr->lua_config_specific_array)
+ utarray_free(lua_plug_mgr->lua_config_specific_array);
+ if (lua_plug_mgr->lua_plugin_thread_array)
+ utarray_free(lua_plug_mgr->lua_plugin_thread_array);
+ return;
+}
+
+
diff --git a/src/lua_plugin_manage_internal.h b/src/lua_plugin_manage_internal.h
new file mode 100644
index 0000000..ea98f08
--- /dev/null
+++ b/src/lua_plugin_manage_internal.h
@@ -0,0 +1,272 @@
+/*************************************************************************
+ > 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;
+ ************************************************************************/
+#ifndef LUA_PLUGIN_MANAGE_INTERNAL_H
+#define LUA_PLUGIN_MANAGE_INTERNAL_H
+
+#include "lua_plugin_manage.h"
+#include "lpm_log.h"
+
+#include <utarray.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#include <time.h>
+
+/* ***** ***** ***** ***** ***** ***** */
+
+/* 需要注册至lua中的函数 */
+struct lua_binding_function
+{
+ /* 注册函数原型 */
+ lua_CFunction binding_function;
+ /* 注册至lua中的函数名称 */
+ char *binding_function_name;
+ /* 注册至lua中的命名空间名称 */
+ char *binding_function_space_name;
+};
+
+/* 定义在lua_plugin_binding.c文件中 */
+/* 所有需要注册至lua状态机中供lua调用的函数 */
+extern struct lua_binding_function lua_bind_functions[];
+
+/* 向lua状态机中注册一个函数 */
+int lua_cbinding_function(lua_State *state, lua_CFunction bind_function, const char *function_name, const char *space_name);
+/* 从lua状态机中移除一个已经注册的函数 */
+int lua_cbinding_function_remove(lua_State *state, const char *function_name, const char *space_name);
+
+/* 暂时支持前四种数据类型提前注册至lua状态机中 */
+/* 其余类型用于运行lua函数等场景 */
+enum DATATYPE
+{
+ DATATYPE_BEGIN = 0,
+ /* bool类型 */
+ DATATYPE_BOOL,
+ /* int类型 */
+ DATATYPE_INT,
+ /* double类型 */
+ DATATYPE_NUM,
+ /* 字符串类型 */
+ DATATYPE_STRING,
+ /* 以下类型不能用于全局变量注册, 仅用于函数等场景 */
+ /* table类型 */
+ DATATYPE_TABLE,
+ /* 指针类型 */
+ DATATYPE_POINTER,
+ DATATYPE_END
+};
+
+/* 需要注册至lua状态机中的数据 */
+struct lua_binding_data
+{
+ /* 注册的数据类型 */
+ enum DATATYPE binding_data_type;
+ /* 注册数数据值 */
+ char *binding_data_value;
+ /* 注册的数据名称 */
+ char *binding_data_name;
+ /* 注册至lua中的命名空间名称 */
+ char *binding_data_space_name;
+};
+
+/* 定义在lua_plugin_binding.c中 */
+/* 所有需要注册至lua状态机中的全局数据 */
+extern struct lua_binding_data lua_bind_datas[];
+
+/* 将一个全局数据注册至状态机中 */
+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);
+
+/* 将lua_bind_functions中提前注册的所有函数注册至state状态机中 */
+int lua_cbinding_functions(lua_State *state);
+/* 将lua_bind_datas中提前注册的所有数据注册至state状态机中 */
+int lua_cbinding_datas(lua_State *state);
+
+/* ***** ***** ***** ***** ***** ***** */
+
+
+
+/* ***** ***** ***** ***** ***** ***** */
+
+struct lua_config_specific;
+struct lua_script;
+struct lua_session_plugin;
+struct lua_plugin_env;
+struct lua_thread_state;
+struct lua_plugin_manage_schema;
+
+/* 根据配置文件加载过程中保存插件信息的临时结构 */
+struct lua_config_specific
+{
+ /* 插件需要使用的文件名 */
+ char *lua_config_specific_file;
+ /* 插件名称 */
+ // char *lua_config_specific_name;
+ /* 加载插件需要调用的函数名称 */
+ char *lua_config_specific_load_func;
+ /* 卸载插件需要调用的函数名称 */
+ char *lua_config_specific_unload_func;
+};
+
+void specific_instance_copy(void *dst, const void *src);
+void specific_instance_destory(void *elt);
+
+/* 一个可以运行的lua函数 */
+/* 加载过程中生成引用, 后续使用过程中使用引用编号进行调用 */
+struct lua_script
+{
+ /* 该函数注册时注册至的状态机, 运行过程中使用该状态机调用函数 */
+ lua_State *script_state;
+ /* 该函数的引用ID */
+ int script_ref_id;
+
+ /* 运行成功次数 */
+ int script_run_success;
+ /* 运行失败次数 */
+ int script_run_failed;
+ /* 最后一次运行开始时间 */
+ clock_t script_last_ms_start;
+ /* 最后一次运行结束时间 */
+ clock_t script_last_ms_end;
+ /* 运行总用时 */
+ clock_t script_total_ms;
+};
+
+int script_instance_init_byname(struct lua_script *script, lua_State *state, const char *filepath, const char *funcname);
+int script_instance_init_byrefid(struct lua_script *script, lua_State *state, int ref_id);
+void script_instance_clean(struct lua_script *script);
+int script_execute(struct lua_script *script);
+
+/* 每一个插件的函数信息 */
+struct lua_session_plugin
+{
+ /* 插件注册完成后得到的插件编号 */
+ int plugin_id;
+
+ /* ctx_new函数 */
+ struct lua_script plugin_ctx_new_script;
+ /* ctx_free函数 */
+ struct lua_script plugin_ctx_free_script;
+ /* on_message函数 */
+ // struct lua_script plugin_on_message_script;
+};
+
+int session_plugin_instance_init(struct lua_session_plugin *session_plugin, lua_State *state, int plugin_id, int new_refid, int free_refid);
+void session_plugin_instance_destory(void *elt);
+
+#define PLUGIN_ENV_DEFAULT_KEY "penv_pointer"
+
+/* 调用插件加载函数时得到的运行环境数据 */
+struct lua_plugin_env
+{
+ /* 插件注册的状态机 */
+ lua_State *lua_plugin_env_state;
+ /* 该环境数据中包含的所有插件列表 */
+ UT_array *lua_plugin_env_plugin_array;
+
+ /* 加载插件的lua函数 */
+ struct lua_script lua_plugin_env_load_func;
+ /* 卸载插件的lua函数 */
+ struct lua_script lua_plugin_env_unload_func;
+
+ /* 该插件运行环境数据的名称, 在创建时同时在状态机中创建该名称的命名空间 */
+ /* 插件申请lua内的全局变量可以保存在该命名空间内, 防止被其他内容覆盖 */
+ // char * lua_plugin_env_name;
+
+ /* 在lua中保存运行数据的引用ID */
+ int lua_plugin_env_ref_id; /* plugin_env */
+};
+
+/* 此时不创建session_array, 在调用load函数过程中创建 */
+int plugin_env_instance_init(struct lua_plugin_env *plugin_env, lua_State *state, struct lua_config_specific *specific);
+void plugin_env_instance_destory(void *elt);
+
+/* 每一个线程中保存一个状态机数据 */
+struct lua_thread_state
+{
+ /* 创建状态机的线程ID */
+ int lua_thread_id;
+ /* 已经插入的插件数量 */
+ int lua_thread_plugin_count;
+ /* 生成的状态机 */
+ lua_State *lua_thread_state;
+ // struct lua_pl_state_private * lua_thread_private;
+ /* 该线程状态机中注册的插件列表 */
+ UT_array *lua_thread_env_array;
+ /* 状态机的启动时间 */
+ time_t lua_thread_begin_time;
+};
+
+int thread_state_instance_init(struct lua_thread_state *thread_state, int state_id);
+void thread_state_instance_destory(void *elt);
+int thread_state_instance_load(struct lua_thread_state *thread_state, struct lua_plugin_manage_schema *schema);
+
+struct lua_plugin_manage_schema
+{
+ struct stellar *lua_plugin_schema_st;
+ int lua_config_specific_count;
+ UT_array *lua_config_specific_array;
+ int lua_plugin_thread_count;
+ UT_array *lua_plugin_thread_array;
+};
+
+/* 防止参数错误, 暂时定一个上限 */
+#define LUA_PLUGIN_MANAGE_MAX_THREAD_COUNT 10
+
+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_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env);
+
+int lua_plugin_manage_config_load(struct lua_plugin_manage_schema *schema, const char *config_file_name);
+int lua_plugin_manage_thread_load(struct lua_plugin_manage_schema *schema, int thread_count);
+
+#endif \ No newline at end of file