From 0f5cbff9740d2526a0b1e18901b709acdfc360af Mon Sep 17 00:00:00 2001 From: niubinghui Date: Tue, 6 Aug 2024 16:16:34 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=95=B0=E6=8D=AE=E7=AE=A1=E7=90=86=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile | 33 +++++ src/lua_plugin_binding.c | 6 +- src/lua_plugin_cfunc.c | 115 ++++++++++++++++ src/lua_plugin_data.c | 210 +++++++++++++++++++++++++++++ src/lua_plugin_manage.c | 221 ++++++++++++++++++++++--------- src/lua_plugin_manage_internal.h | 103 +++++++++++--- 6 files changed, 601 insertions(+), 87 deletions(-) create mode 100644 src/Makefile create mode 100644 src/lua_plugin_cfunc.c create mode 100644 src/lua_plugin_data.c diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..31aa8b4 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,33 @@ +TOPDIR = ./.. +CC=gcc +MAKE=make +TARGET=libluaplugin.so + +TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST + +SRC := lua_plugin_binding.c \ + lua_plugin_data.c \ + lua_plugin_cfunc.c \ + lua_plugin_manage.c + +OBJECTS := lua_plugin_binding.o \ + lua_plugin_data.o \ + lua_plugin_cfunc.o \ + lua_plugin_manage.o + +INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include +CFLAGS = -g -Wextra -Wall -O0 -fPIC +# CFLAGS += -pedantic -fsanitize=address +LDLIBS = -L$(TOPDIR)/dependence/lib -llua -ltoml -ldl -lm + +all:$(OBJECTS) + $(CC) $(CFLAGS) -shared -o $(TARGET) $(OBJECTS) $(LDLIBS) + mkdir -p $(TOPDIR)/output/libs + cp -f $(TARGET) $(TOPDIR)/output/libs + +$(OBJECTS):$(SRC) + $(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SRC) -c $^ + +clean: + rm -rf $(OBJECTS) $(TARGET) + rm -rf $(TOPDIR)/output/libs/$(TARGET) \ No newline at end of file diff --git a/src/lua_plugin_binding.c b/src/lua_plugin_binding.c index bcf5039..6a439f4 100644 --- a/src/lua_plugin_binding.c +++ b/src/lua_plugin_binding.c @@ -506,7 +506,7 @@ int lua_plugin_manage_session_regist(lua_State *state) return 0; } lua_pop(state, 1); -#if 0 + /* 取出处理第一个参数 */ struct stellar * st = (struct stellar *)lua_topointer(state, -1); if ( !st ) { @@ -522,8 +522,8 @@ int lua_plugin_manage_session_regist(lua_State *state) 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); + utarray_push_back(plugin_env->plugin_env_plugin_array, &session_plugin); lua_pushinteger(state, plugin_id); -#endif + return 1; } diff --git a/src/lua_plugin_cfunc.c b/src/lua_plugin_cfunc.c new file mode 100644 index 0000000..ed64823 --- /dev/null +++ b/src/lua_plugin_cfunc.c @@ -0,0 +1,115 @@ +/************************************************************************* + > File Name: lua_plugin_cfunc.c + > Author: + > Created Time: 2024-08 + > Encoding : UTF-8 + ************************************************************************/ + +/************************************************************************* + * version + * [ v0.1 ] + * 08-06 + * 1. 实现函数 + * void *lpm_ctx_new_func; + * void lpm_ctx_free_func; + ************************************************************************/ +#include "lua_plugin_manage_internal.h" + +/* + * 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) +{ + if (__glibc_unlikely(!sess || !plugin_env)) + return NULL; + struct lua_plugin_env *env = (struct lua_plugin_env *)plugin_env; + + /* 获取插件ID并找到该插件 */ + // int plugin_id = session_get_pluginid(sess); + int plugin_id = 1; + struct lua_session_plugin *plugin = NULL; + while ((plugin = utarray_next(env->plugin_env_plugin_array, plugin))) + { + if (plugin->plugin_id == plugin_id) + break; + } + if (!plugin || plugin->plugin_id != plugin_id) + /* 未找到该插件 */ + return NULL; + + struct lua_context *new_context = lua_context_new(env->plugin_env_state); + if (__glibc_unlikely(!new_context)) + /* 创建新的context失败 */ + return NULL; + + 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->plugin_env_ref_id; + param[2].cdata_type = DATATYPE_CONTEXT; + param[2].cdata_context = new_context; + + if (script_execute(&plugin->plugin_ctx_new_script, 3, param, 0, NULL)) + { + /* 脚本执行失败 */ + free(new_context); + return NULL; + } + + 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) +{ + if (__glibc_unlikely(!sess || !sess_ctx || !plugin_env)) + return; + struct lua_context *context = (struct lua_context *)sess_ctx; + struct lua_plugin_env *env = (struct lua_plugin_env *)plugin_env; + + /* 获取插件ID并找到该插件 */ + // int plugin_id = session_get_pluginid(sess); + int plugin_id = 1; + struct lua_session_plugin *plugin = NULL; + while ((plugin = utarray_next(env->plugin_env_plugin_array, plugin))) + { + if (plugin->plugin_id == plugin_id) + break; + } + if (!plugin || plugin->plugin_id != plugin_id) + /* 未找到该插件 */ + return; + + 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 = context; + param[2].cdata_type = DATATYPE_TABLE; + param[2].cdata_table = env->plugin_env_ref_id; + + script_execute(&plugin->plugin_ctx_free_script, 3, param, 0, NULL); + lua_context_free(context); + + return; +} diff --git a/src/lua_plugin_data.c b/src/lua_plugin_data.c new file mode 100644 index 0000000..fb6d466 --- /dev/null +++ b/src/lua_plugin_data.c @@ -0,0 +1,210 @@ +/************************************************************************* + > 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; + ************************************************************************/ +#include "lua_plugin_manage_internal.h" + +/* + * Function: lua_cdata_push_stack + * Input: | lua_State * | state | 入栈数据使用的状态机 + * | struct lua_cdata * | cdata | 需要入栈的数据 + * Output: + * Return: | -1 | 参数错误 + * | 1 | 入栈数据类型有误 + * | 0 | 入栈成功 + * Description: 将一个数据元素入栈 + */ +int lua_cdata_push_stack( + lua_State *state, + struct lua_cdata *cdata) +{ + if (__glibc_unlikely(!state || !cdata)) + return -1; + + switch (cdata->cdata_type) + { + case DATATYPE_NIL: + lua_pushnil(state); + return 0; + case DATATYPE_BOOL: + lua_pushboolean(state, cdata->cdata_bool); + return 0; + case DATATYPE_INT: + lua_pushinteger(state, cdata->cdata_int); + return 0; + case DATATYPE_NUM: + lua_pushnumber(state, cdata->cdata_num); + return 0; + case DATATYPE_STRING: + lua_pushstring(state, cdata->cdata_string); + return 0; + case DATATYPE_TABLE: + lua_rawgeti(state, LUA_REGISTRYINDEX, cdata->cdata_table); + return 0; + case DATATYPE_POINTER: + lua_pushlightuserdata(state, (void *)cdata->cdata_pointer); + return 0; + case DATATYPE_CONTEXT: + lua_context_push_stack(cdata->cdata_context); + return 0; + default: + LOGERROR("can't recorgnize data type %d", cdata->cdata_type); + } + + return 1; +} + +/* + * Function: lua_cdata_pop_stack + * Input: | lua_State * | state | 出栈数据使用的状态机 + * | struct lua_cdata * | cdata | 保存出栈的元素 + * Output: + * Return: | -1 | 参数错误 + * | -2 | 出栈数据类型有误 + * | 0 | 出栈成功 + * Description: 将一个数据元素出栈, 出栈过程中无法出栈context与table类型 + * TODO: 扩展类型, 支持更多数据类型 + */ +int lua_cdata_pop_stack( + lua_State *state, + struct lua_cdata *cdata) +{ + if (__glibc_unlikely(!state || !cdata)) + return -1; + if (!lua_gettop(state)) + return 0; + + 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: + /* 其他数据类型之后处理 */ + LOGERROR("other lua type can't pop out, %d", lua_type(state, -1)); + return -2; + } + + lua_pop(state, 1); + return 0; +} + +/* + * 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); + 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: | struct lua_context * | context | 待入栈的context结构 + * Output: + * Return: | 0 | 入栈成功 + * | -1 | 参数错误 + * Description: 将一个context入栈, 实际入栈流程与table一致 + */ +int lua_context_push_stack(struct lua_context *context) +{ + if (luai_unlikely(!context)) + return -1; + + lua_rawgeti(context->context_state, LUA_REGISTRYINDEX, context->context_ref_id); + return 0; +} + +/* + * Function: lua_context_free + * Input: | struct lua_context * | context | 释放一个context + * Output: + * Return: + * Description: 释放一个context + */ +void lua_context_free(struct lua_context *context) +{ + if (__glibc_unlikely(!context)) + return; + luaL_unref(context->context_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 df155ff..32d9b8d 100644 --- a/src/lua_plugin_manage.c +++ b/src/lua_plugin_manage.c @@ -25,6 +25,10 @@ * int thread_state_instance_load; * int lua_plugin_manage_config_load; * int lua_plugin_manage_thread_load; + * + * 08-06 + * 1. 实现函数 + * int script_execute; ************************************************************************/ #include "lua_plugin_manage_internal.h" #include "lpm_log.h" @@ -55,10 +59,10 @@ void specific_instance_copy(void *dst, const void *src) 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); + dst_spec->config_specific_file = strdup(src_spec->config_specific_file); + // dst_spec->config_specific_name = strdup(src_spec->config_specific_name); + dst_spec->config_specific_load_func = strdup(src_spec->config_specific_load_func); + dst_spec->config_specific_unload_func = strdup(src_spec->config_specific_unload_func); return; } @@ -74,14 +78,14 @@ 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); + if (element->config_specific_file) + free(element->config_specific_file); + // if (element->config_specific_name) + // free(element->config_specific_name); + if (element->config_specific_load_func) + free(element->config_specific_load_func); + if (element->config_specific_unload_func) + free(element->config_specific_unload_func); return; } @@ -195,16 +199,95 @@ void script_instance_clean(struct lua_script *script) } /* - * Function: - * Input: + * Function: script_execute + * Input: | struct lua_script * | script | 需要执行的lua脚本 + * | int | pcount | 传入的参数个数 + * | struct lua_cdata * | param | 传入的参数值 + * | int | rmaxcount | 最大可接收的返回值个数 + * | struct lua_cdata * | rvalue | 接收返回值的data结构 * Output: - * Return: - * Description: + * Return: | 0 | 脚本执行成功 + * | -1 | 参数错误 + * | -2 | 无法获取脚本调用的lua函数 + * | -3 | 参数无法入栈 + * | -4 | 函数执行过程中出错 + * | -5 | 返回值出栈过程中数量过多 + * | -6 | 返回值出栈失败 + * Description: 调用并执行一个lua脚本 */ -int script_execute(struct lua_script *script) +int script_execute( + struct lua_script *script, + int pcount, + struct lua_cdata * param, + int rmaxcount, + struct lua_cdata * rvalue) { if (!script) return -1; + if ( (pcount && !param) || (pcount < 0) ) + return -1; + if ( (rmaxcount && !rvalue) || (rmaxcount < 0) ) + return -1; + + lua_State * state = script->script_state; + + /* 需要调用的函数入栈, 由于后续在读取参数个数的时候对栈操作较多, 需要先将函数入栈 */ + lua_rawgeti(state, LUA_REGISTRYINDEX, script->script_ref_id); + if (lua_gettop(state) == 0 || lua_type(state, -1) != LUA_TFUNCTION) + { + lua_settop(state, 0); + return -2; + } + + /* 参数入栈 */ + for (int i = 0; i < pcount; ++i) { + if ( lua_cdata_push_stack(state, ¶m[i]) ) { + lua_settop(state, 0); + return -3; + } + } + + /* 执行该脚本并记录执行时间 */ + 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)); + /* 仅函数运行过程中出错记入出错记录, 由于参数错误等原因导致的错误不记录 */ + script->script_last_ms_start = start_time; + script->script_last_ms_end = end_time; + script->script_total_ms += (end_time - start_time); + script->script_run_failed += 1; + lua_settop(state, 0); + return -4; + } + end_time = clock(); + + /* 返回值出栈 */ + if ( rmaxcount > 0 ) { + /* 如果rmaxcount为0, 说明在期望中不准备接收返回值, 也不必处理 */ + int rcount = lua_gettop(state); + if ( rcount > rmaxcount ) { + lua_settop(state, 0); + return -5; + } + for (int i = (rcount - 1); i >= 0; ++i) { + if ( lua_cdata_pop_stack(state, &(rvalue[i])) ) { + lua_settop(state, 0); + return -6; + } + } + } + + /* 记录耗时等数据 */ + lua_settop(state, 0); + script->script_last_ms_start = start_time; + script->script_last_ms_end = end_time; + script->script_total_ms += (end_time - start_time); + script->script_run_success += 1; + return 0; } @@ -274,32 +357,32 @@ int plugin_env_instance_init( 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); + plugin_env->plugin_env_state = state; + plugin_env->plugin_env_plugin_array = NULL; + // plugin_env->plugin_env_name = strdup(specific->config_specific_name); /* 从文件中加载load函数, 但此时不调用 */ - if (script_instance_init_byname(&plugin_env->lua_plugin_env_load_func, + if (script_instance_init_byname(&plugin_env->plugin_env_load_func, state, - specific->lua_config_specific_file, - specific->lua_config_specific_load_func)) + specific->config_specific_file, + specific->config_specific_load_func)) { return -2; } /* 从文件中加载unload函数 */ - if (script_instance_init_byname(&plugin_env->lua_plugin_env_unload_func, + if (script_instance_init_byname(&plugin_env->plugin_env_unload_func, state, - specific->lua_config_specific_file, - specific->lua_config_specific_unload_func)) + specific->config_specific_file, + specific->config_specific_unload_func)) { - script_instance_clean(&plugin_env->lua_plugin_env_load_func); + script_instance_clean(&plugin_env->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); + lua_newtable(plugin_env->plugin_env_state); + int ref_id = luaL_ref(plugin_env->plugin_env_state, LUA_REGISTRYINDEX); if (ref_id == LUA_REFNIL) return -4; - plugin_env->lua_plugin_env_ref_id = ref_id; + plugin_env->plugin_env_ref_id = ref_id; return 0; } @@ -316,15 +399,24 @@ void plugin_env_instance_destory(void *elt) if (__glibc_unlikely(!elt)) return; struct lua_plugin_env *plugin_env = (struct lua_plugin_env *)elt; + + /* 调用自身unload函数 */ + struct lua_cdata param; + param.cdata_type = DATATYPE_TABLE; + param.cdata_table = plugin_env->plugin_env_ref_id; + script_execute(&plugin_env->plugin_env_unload_func, 1, ¶m, 0, NULL); + /* 释放已经注册的插件 */ - if (plugin_env->lua_plugin_env_plugin_array) - utarray_free(plugin_env->lua_plugin_env_plugin_array); + if (plugin_env->plugin_env_plugin_array) + utarray_free(plugin_env->plugin_env_plugin_array); + /* 释放插件的加载函数与卸载函数 */ - script_instance_clean(&plugin_env->lua_plugin_env_load_func); - script_instance_clean(&plugin_env->lua_plugin_env_unload_func); + script_instance_clean(&plugin_env->plugin_env_load_func); + script_instance_clean(&plugin_env->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); + if (plugin_env->plugin_env_ref_id) + luaL_unref(plugin_env->plugin_env_state, LUA_REGISTRYINDEX, plugin_env->plugin_env_ref_id); return; } @@ -356,11 +448,11 @@ int thread_state_instance_init( 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); + thread_state->thread_id = state_id; + thread_state->thread_plugin_count = 0; + thread_state->thread_state = new_state; + thread_state->thread_env_array = NULL; + thread_state->thread_begin_time = time(NULL); return 0; } @@ -378,11 +470,11 @@ void thread_state_instance_destory(void *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->thread_env_array) + utarray_free(thread_state->thread_env_array); /* 关闭状态机 */ - if (thread_state->lua_thread_state) - lua_close(thread_state->lua_thread_state); + if (thread_state->thread_state) + lua_close(thread_state->thread_state); return; } @@ -403,9 +495,9 @@ int thread_state_instance_load( 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); + lua_State *state = thread_state->thread_state; + utarray_new(thread_state->thread_env_array, &plugin_env_icd); + utarray_reserve(thread_state->thread_env_array, schema->lua_config_specific_count); struct lua_config_specific *specific = NULL; /* 读取所有插件并加入插件列表中 */ @@ -415,21 +507,26 @@ int thread_state_instance_load( 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); + utarray_push_back(thread_state->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))) + while ((plugin_env = utarray_next(thread_state->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); + utarray_new(plugin_env->plugin_env_plugin_array, &session_plugin_icd); + lua_rawgeti(state, LUA_REGISTRYINDEX, plugin_env->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); + struct lua_cdata param[2]; + param[0].cdata_type = DATATYPE_POINTER; + param[0].cdata_pointer = schema->lua_plugin_schema_st; + param[1].cdata_type = DATATYPE_TABLE; + param[1].cdata_table = plugin_env->plugin_env_ref_id; + script_execute(&plugin_env->plugin_env_load_func, 2, param, 0, NULL); } return 0; @@ -450,7 +547,7 @@ static int specific_check(struct lua_config_specific *specific) if (__glibc_unlikely(!specific)) return -1; - if (access(specific->lua_config_specific_file, F_OK)) + if (access(specific->config_specific_file, F_OK)) return -2; return 0; @@ -502,7 +599,7 @@ int lua_plugin_manage_config_load( 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); + struct lua_config_specific *specific = (struct lua_config_specific *)calloc(1, sizeof(struct lua_config_specific)); for (int i = 0; i < specific_num; ++i) { @@ -513,10 +610,10 @@ int lua_plugin_manage_config_load( 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)) + if (toml_rtos(raw_filepath, &specific->config_specific_file) || + // toml_rtos(raw_name, &specific->config_specific_name) || + toml_rtos(raw_load_func_name, &specific->config_specific_load_func) || + toml_rtos(raw_unload_func_name, &specific->config_specific_unload_func)) { toml_free(conf); free(specific); @@ -615,9 +712,9 @@ struct lua_plugin_manage_schema *lua_plugin_manage_init( 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); + printf("path is %s\n", specific->config_specific_file); + printf("load is %s\n", specific->config_specific_load_func); + printf("unload is %s\n", specific->config_specific_unload_func); } #endif diff --git a/src/lua_plugin_manage_internal.h b/src/lua_plugin_manage_internal.h index ea98f08..ad10ee2 100644 --- a/src/lua_plugin_manage_internal.h +++ b/src/lua_plugin_manage_internal.h @@ -47,6 +47,23 @@ * 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; ************************************************************************/ #ifndef LUA_PLUGIN_MANAGE_INTERNAL_H #define LUA_PLUGIN_MANAGE_INTERNAL_H @@ -62,7 +79,7 @@ #include /* ***** ***** ***** ***** ***** ***** */ - +/* 此部分主要功能为C向lua中注册函数及数据, 实现在lua_plugin_binding.c中 */ /* 需要注册至lua中的函数 */ struct lua_binding_function { @@ -88,6 +105,8 @@ int lua_cbinding_function_remove(lua_State *state, const char *function_name, co enum DATATYPE { DATATYPE_BEGIN = 0, + /* nil类型 */ + DATATYPE_NIL, /* bool类型 */ DATATYPE_BOOL, /* int类型 */ @@ -101,6 +120,7 @@ enum DATATYPE DATATYPE_TABLE, /* 指针类型 */ DATATYPE_POINTER, + DATATYPE_CONTEXT, DATATYPE_END }; @@ -132,11 +152,48 @@ int lua_cbinding_functions(lua_State *state); int lua_cbinding_datas(lua_State *state); /* ***** ***** ***** ***** ***** ***** */ +/* 此部分主要用于lua与C之间的数据转换与传递, 实现在lua_plugin_data.c中 */ +struct lua_cdata; +// struct lua_ctable; +struct lua_context; +/* 保存lua数据的结构 */ +struct lua_cdata { + enum DATATYPE cdata_type; + 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; + }; +}; +/* 将一个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 { + lua_State * context_state; + int context_ref_id; +}; + +/* 在状态机中生成一个context */ +struct lua_context * lua_context_new(lua_State * state); +/* 将一个context入栈 */ +int lua_context_push_stack(struct lua_context * context); +/* 释放一个context */ +void lua_context_free(struct lua_context * context); /* ***** ***** ***** ***** ***** ***** */ - +/* 此部分主要为插件管理及配置管理相关功能, 实现在lua_plugin_manage.c中 */ struct lua_config_specific; struct lua_script; struct lua_session_plugin; @@ -148,13 +205,13 @@ struct lua_plugin_manage_schema; struct lua_config_specific { /* 插件需要使用的文件名 */ - char *lua_config_specific_file; + char *config_specific_file; /* 插件名称 */ - // char *lua_config_specific_name; + // char *config_specific_name; /* 加载插件需要调用的函数名称 */ - char *lua_config_specific_load_func; + char *config_specific_load_func; /* 卸载插件需要调用的函数名称 */ - char *lua_config_specific_unload_func; + char *config_specific_unload_func; }; void specific_instance_copy(void *dst, const void *src); @@ -184,7 +241,7 @@ struct lua_script 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); +int script_execute(struct lua_script *script, int pcount, struct lua_cdata * param, int rmaxcount, struct lua_cdata * rvalue); /* 每一个插件的函数信息 */ struct lua_session_plugin @@ -209,21 +266,21 @@ void session_plugin_instance_destory(void *elt); struct lua_plugin_env { /* 插件注册的状态机 */ - lua_State *lua_plugin_env_state; + lua_State *plugin_env_state; /* 该环境数据中包含的所有插件列表 */ - UT_array *lua_plugin_env_plugin_array; + UT_array *plugin_env_plugin_array; /* 加载插件的lua函数 */ - struct lua_script lua_plugin_env_load_func; + struct lua_script plugin_env_load_func; /* 卸载插件的lua函数 */ - struct lua_script lua_plugin_env_unload_func; + struct lua_script plugin_env_unload_func; /* 该插件运行环境数据的名称, 在创建时同时在状态机中创建该名称的命名空间 */ /* 插件申请lua内的全局变量可以保存在该命名空间内, 防止被其他内容覆盖 */ - // char * lua_plugin_env_name; + // char *plugin_env_name; /* 在lua中保存运行数据的引用ID */ - int lua_plugin_env_ref_id; /* plugin_env */ + int plugin_env_ref_id; /* plugin_env */ }; /* 此时不创建session_array, 在调用load函数过程中创建 */ @@ -234,16 +291,16 @@ void plugin_env_instance_destory(void *elt); struct lua_thread_state { /* 创建状态机的线程ID */ - int lua_thread_id; + int thread_id; /* 已经插入的插件数量 */ - int lua_thread_plugin_count; + int thread_plugin_count; /* 生成的状态机 */ - lua_State *lua_thread_state; + lua_State *thread_state; // struct lua_pl_state_private * lua_thread_private; /* 该线程状态机中注册的插件列表 */ - UT_array *lua_thread_env_array; + UT_array *thread_env_array; /* 状态机的启动时间 */ - time_t lua_thread_begin_time; + time_t thread_begin_time; }; int thread_state_instance_init(struct lua_thread_state *thread_state, int state_id); @@ -262,11 +319,13 @@ struct lua_plugin_manage_schema /* 防止参数错误, 暂时定一个上限 */ #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); +/* ***** ***** ***** ***** ***** ***** */ +/* 此部分为注册至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_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env); + #endif \ No newline at end of file