diff options
| author | niubinghui <[email protected]> | 2024-08-13 17:22:10 +0800 |
|---|---|---|
| committer | niubinghui <[email protected]> | 2024-08-13 17:22:10 +0800 |
| commit | 0649e332db32c63a72eafefb49edc312be0fe41c (patch) | |
| tree | 5a8a39ece7b35aa69c7bd3e4133e22ecadfe51a9 /src/lua_plugin_binding.c | |
| parent | d3810797af6bf463d0ff0a78e8538a9098701280 (diff) | |
【修改】修改schema设计思路,将线程与插件作为数组进行管理,节约运行内存
Diffstat (limited to 'src/lua_plugin_binding.c')
| -rw-r--r-- | src/lua_plugin_binding.c | 252 |
1 files changed, 139 insertions, 113 deletions
diff --git a/src/lua_plugin_binding.c b/src/lua_plugin_binding.c index 2444232..f72cb43 100644 --- a/src/lua_plugin_binding.c +++ b/src/lua_plugin_binding.c @@ -18,6 +18,10 @@ * int lua_cbinding_datas; * int lua_plugin_manage_regist; * ** 注册函数lua_plugin_manage_session_regist还需要补充 + * + * 08-12 + * 1. 修改函数lua_cbinding_function, 参数与lua_cbinding_data保持统一 + * 2. 修改部分函数返回值, 使用枚举代替错误码返回值, 方便统一处理 ************************************************************************/ #include "lua_plugin_manage_internal.h" @@ -25,11 +29,11 @@ #include <string.h> /* 需要注册至lua中供lua调用的所有函数原型 */ -int lua_plugin_manage_regist(lua_State * state); -int lua_session_get_id(lua_State * state); -int lua_session_set_id(lua_State * state); -int lua_session_get_type(lua_State * state); -int lua_session_set_type(lua_State * state); +int lua_plugin_manage_regist(lua_State *state); +int lua_session_get_id(lua_State *state); +int lua_session_set_id(lua_State *state); +int lua_session_get_type(lua_State *state); +int lua_session_set_type(lua_State *state); /* 需要注册至状态机中的函数定义在链表中, 会依次完成注册 */ struct lua_binding_function lua_bind_functions[] = { @@ -52,7 +56,7 @@ struct lua_binding_data lua_bind_datas[] = { }; /* 向lua状态机中注册一个函数 */ -int lua_cbinding_function(lua_State *state, lua_CFunction bind_function, const char *function_name, const char *space_name); +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); /* 将一个全局数据注册至状态机中 */ @@ -62,38 +66,38 @@ int lua_cbinding_data_remove(lua_State *state, const char *data_name, const char /* * Function: lua_cbinding_function - * Input: | lua_State * | state | 需要注册函数的状态机 - * | lua_CFunction | bind_function | 需要注册的函数 - * | const char * | function_name | 注册函数的名称 - * | const char * | space_name | 注册函数的命名空间 + * Input: | lua_State * | state | 需要注册函数的状态机 + * | struct lua_binding_function * | function | 需要绑定的function函数结构 * Output: - * Return: | 0 | 注册成功 - * | -1 | 传入的参数有错误 - * | -2 | 命名空间已经存在, 且命名空间不是table类型, 无法新增成员 - * | -3 | 命名空间中已经存在函数名称对应成员, 无法完成覆盖 - * | -4 | 存在全局的函数名称, 无法完成注册 + * Return: enum LUA_PLUGIN_RETURN * Description: 将一个C函数注册至lua中 */ int lua_cbinding_function( lua_State *state, - lua_CFunction bind_function, - const char *function_name, - const char *space_name) + struct lua_binding_function *bind_function) { - if (__glibc_unlikely(!state || !bind_function || !function_name)) - return -1; + 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 (space_name) + if (bind_function->space_name) { /* 包含space_name, 调用时为 space_name.function_name */ - lua_getglobal(state, space_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, space_name); + lua_setglobal(state, bind_function->space_name); lua_settop(state, 0); - lua_getglobal(state, space_name); + lua_getglobal(state, bind_function->space_name); } else { @@ -102,40 +106,40 @@ int lua_cbinding_function( { /* spacename已经被占用, 并且不是table, 无法插入数据 */ lua_settop(state, 0); - return -2; + return BIND_NAMESPACE_TYPE_ERR; } - lua_getfield(state, -1, function_name); + lua_getfield(state, -1, bind_function->function_name); if (lua_type(state, -1) != LUA_TNIL) { /* 在待插入的global table中存在与function_name重名的成员 */ lua_settop(state, 0); - return -3; + return BIND_FUNCTION_TYPE_ERR; } lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */ } - lua_pushcfunction(state, bind_function); - lua_setfield(state, -2, function_name); + lua_pushcfunction(state, bind_function->function); + lua_setfield(state, -2, bind_function->function_name); } else { - lua_getglobal(state, function_name); + lua_getglobal(state, bind_function->function_name); if (lua_type(state, -1) != LUA_TNIL) { /* 存在与function_name重名的全局成员 */ lua_settop(state, 0); - return -4; + return BIND_FUNCTION_TYPE_ERR; } lua_pop(state, 1); /* 不包含space_name, 调用时直接使用function_name调用 */ - lua_pushcfunction(state, bind_function); - lua_setglobal(state, function_name); + lua_pushcfunction(state, bind_function->function); + lua_setglobal(state, bind_function->function_name); } lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return 0; + return SUCCESS; } /* @@ -144,11 +148,7 @@ int lua_cbinding_function( * | const char * | function_name | 需要删除的函数名称 * | const char * | space_name | 需要删除的命名空间名称 * Output: - * Return: | 0 | 删除成功 - * | -1 | 参数错误 - * | -2 | 命名空间存在但不是一个table - * | -3 | 命名空间中存在函数名称对应成员, 但是类型不是函数 - * | -4 | 函数名称对应的成员不是一个函数 + * Return: enum LUA_PLUGIN_RETURN * Description: 从状态机中删除一个C注册的函数, 删除过程中将该函数在lua状态的引用置为nil */ int lua_cbinding_function_remove( @@ -157,7 +157,7 @@ int lua_cbinding_function_remove( const char *space_name) { if (__glibc_unlikely(!state || !function_name)) - return -1; + return PARAM_ERR; if (space_name) { @@ -167,7 +167,7 @@ int lua_cbinding_function_remove( { /* 命名空间存在且不是table */ lua_settop(state, 0); - return -2; + return BIND_NAMESPACE_TYPE_ERR; } /* 检查该命名空间内是否存在function_name */ lua_getfield(state, -1, function_name); @@ -175,7 +175,7 @@ int lua_cbinding_function_remove( { /* 命名空间存在内部元素名称为function_name, 但是类型不符 */ lua_settop(state, 0); - return -3; + return BIND_FUNCTION_TYPE_ERR; } /* 删除该函数 */ lua_pop(state, 1); @@ -190,7 +190,7 @@ int lua_cbinding_function_remove( { /* 类型不符 */ lua_settop(state, 0); - return -4; + return BIND_FUNCTION_TYPE_ERR; } /* 删除该函数 */ lua_pop(state, 1); @@ -199,20 +199,15 @@ int lua_cbinding_function_remove( } lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return 0; + return SUCCESS; } /* * Function: lua_cbinding_data - * Input: | lua_State * | state | 需要注册数据的状态机 + * Input: | lua_State * | state | 需要注册数据的状态机 * | struct lua_binding_data * | data | 需要注册至状态机中的数据 * Output: - * Return: | 0 | 注册成功 - * | -1 | 传入的参数有错误 - * | -2 | 命名空间已经存在, 且命名空间不是table类型, 无法新增成员 - * | -3 | 命名空间中已经存在函数名称对应成员, 无法完成覆盖 - * | -4 | 无法识别data的数据类型 - * | -5 | 全局变量名称已经有成员, 不为空 + * Return: enum LUA_PLUGIN_RETURN * Description: 将一个变量注册至lua状态机中 */ int lua_cbinding_data( @@ -221,14 +216,18 @@ int lua_cbinding_data( { if (__glibc_unlikely(!state || !data)) { - return -1; + return PARAM_ERR; } - 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; + 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 -1; + 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) { @@ -249,7 +248,7 @@ int lua_cbinding_data( { /* spacename已经被占用, 并且不是table, 无法插入数据 */ lua_settop(state, 0); - return -2; + return BIND_NAMESPACE_TYPE_ERR; } lua_getfield(state, -1, data_name); @@ -257,7 +256,7 @@ int lua_cbinding_data( { /* 在待插入的global table中存在与function_name重名的成员 */ lua_settop(state, 0); - return -3; + return BIND_DATA_TYPE_ERR; } lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */ } @@ -268,7 +267,7 @@ int lua_cbinding_data( case DATATYPE_BOOL: if (strstr(value, "true") || strstr(value, "TRUE")) lua_pushboolean(state, 1); - else if (strstr(value, "false") || strstr(value, "false")) + else if (strstr(value, "false") || strstr(value, "FALSE")) lua_pushboolean(state, 0); break; case DATATYPE_INT: @@ -283,7 +282,7 @@ int lua_cbinding_data( default: /* 未识别的类型 */ lua_settop(state, 0); - return -4; + return BIND_DATA_TYPE_UNKNOWN; } lua_setfield(state, -2, data_name); } @@ -294,7 +293,7 @@ int lua_cbinding_data( { lua_settop(state, 0); /* 存在与data_name重名的全局成员 */ - return -5; + return BIND_DATA_TYPE_ERR; } lua_pop(state, 1); @@ -304,7 +303,7 @@ int lua_cbinding_data( case DATATYPE_BOOL: if (strstr(value, "true") || strstr(value, "TRUE")) lua_pushboolean(state, 1); - else if (strstr(value, "false") || strstr(value, "false")) + else if (strstr(value, "false") || strstr(value, "FALSE")) lua_pushboolean(state, 0); break; case DATATYPE_INT: @@ -319,13 +318,13 @@ int lua_cbinding_data( default: /* 未识别的类型 */ lua_settop(state, 0); - return -4; + return BIND_DATA_TYPE_UNKNOWN; } lua_setglobal(state, data_name); } lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return 0; + return SUCCESS; } /* @@ -334,11 +333,7 @@ int lua_cbinding_data( * | const char * | data_name | 需要删除的数据名称 * | const char * | space_name | 需要删除的命名空间名称 * Output: - * Return: | 0 | 删除成功 - * | -1 | 参数错误 - * | -2 | 命名空间存在但不是一个table - * | -3 | 命名空间中存在数据名称对应成员, 但是类型不符 - * | -4 | 函数名称对应的成员类型不符 + * Return: enum LUA_PLUGIN_RETURN * Description: 从状态机中删除一个C注册的数据, 删除过程中将该名称在lua状态的引用置为nil */ int lua_cbinding_data_remove( @@ -347,7 +342,7 @@ int lua_cbinding_data_remove( const char *space_name) { if (__glibc_unlikely(!state || !data_name)) - return -1; + return PARAM_ERR; if (space_name) { @@ -357,7 +352,7 @@ int lua_cbinding_data_remove( { /* 命名空间存在且不是table */ lua_settop(state, 0); - return -2; + return BIND_NAMESPACE_TYPE_ERR; } /* 检查该命名空间内是否存在data_name */ lua_getfield(state, -1, data_name); @@ -366,13 +361,13 @@ int lua_cbinding_data_remove( { /* 命名空间存在内部元素名称为data_name, 但是类型不符 */ lua_settop(state, 0); - return -3; + return BIND_DATA_TYPE_ERR; } else if (data_type == LUA_TNIL) { /* 没有该名称的元素 */ lua_settop(state, 0); - return 0; + return SUCCESS; } /* 删除该函数 */ lua_pop(state, 1); @@ -388,13 +383,13 @@ int lua_cbinding_data_remove( { /* 类型不符 */ lua_settop(state, 0); - return -4; + return BIND_DATA_TYPE_ERR; } else if (data_type == LUA_TNIL) { /* 没有该名称的元素 */ lua_settop(state, 0); - return 0; + return SUCCESS; } /* 删除该函数 */ lua_pop(state, 1); @@ -403,7 +398,7 @@ int lua_cbinding_data_remove( } lua_settop(state, 0); /* 操作完成, 弹出所有元素 */ - return 0; + return SUCCESS; } /* @@ -412,28 +407,25 @@ int lua_cbinding_data_remove( * Output: * Return: | -1 | 参数错误 * | 0 | 成功 - * | >0 | 绑定有错的函数数量 + * | >0 | 绑定出错的数据数量 * Description: 绑定所有需要在lua中调用的C函数 */ int lua_cbinding_functions(lua_State *state) { if (__glibc_unlikely(!state)) - return -1; + 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].binding_function && lua_bind_functions[i].binding_function_name) + if (lua_bind_functions[i].function && lua_bind_functions[i].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); + 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].binding_function_name); + LOGERROR("binding function failed, ret is %d, function name is %s\n", bind_ret, lua_bind_functions[i].function_name); failed_count += 1; } } @@ -460,12 +452,12 @@ int lua_cbinding_datas(lua_State *state) 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) + 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].binding_data_name, lua_bind_datas[i].binding_data_value); + 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; } } @@ -484,7 +476,7 @@ int lua_plugin_manage_regist(lua_State *state) } /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA || lua_type(state, -2) != LUA_TFUNCTION || + 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); @@ -492,13 +484,16 @@ int lua_plugin_manage_regist(lua_State *state) } /* 取出处理第四个参数 */ - struct lua_plugin_env *plugin_env = (struct lua_plugin_env *)lua_topointer(state, -1); /* stack 4 */ - if (!plugin_env) + 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; } - lua_pop(state, 1); + 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 */ @@ -517,8 +512,9 @@ int lua_plugin_manage_regist(lua_State *state) } /* 取出处理第一个参数 */ - struct stellar * st = (struct stellar *)lua_topointer(state, -1); /* stack 1 */ - if ( !st ) { + struct stellar *st = (struct stellar *)lua_topointer(state, -1); /* stack 1 */ + if (!st) + { lua_settop(state, 0); return 0; } @@ -527,15 +523,43 @@ int lua_plugin_manage_regist(lua_State *state) /* 在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\n", plugin_id); + 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; + } + } + /* 将注册完成的新插件插入到队列中 */ - 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->plugin_env_plugin_array, &session_plugin); + 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; lua_settop(state, 0); lua_pushinteger(state, plugin_id); @@ -543,7 +567,7 @@ int lua_plugin_manage_regist(lua_State *state) return 1; } -int lua_session_get_id(lua_State * state) +int lua_session_get_id(lua_State *state) { /* 参数个数检查 */ if (lua_gettop(state) != 1) @@ -553,14 +577,15 @@ int lua_session_get_id(lua_State * state) } /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA ) + if (lua_type(state, -1) != LUA_TLIGHTUSERDATA) { lua_settop(state, 0); return 0; } - struct session * sess = (struct session *)lua_topointer(state, -1); - if ( !sess ) { + struct session *sess = (struct session *)lua_topointer(state, -1); + if (!sess) + { lua_settop(state, 0); return 0; } @@ -570,7 +595,7 @@ int lua_session_get_id(lua_State * state) return 1; } -int lua_session_set_id(lua_State * state) +int lua_session_set_id(lua_State *state) { /* 参数个数检查 */ if (lua_gettop(state) != 2) @@ -580,7 +605,7 @@ int lua_session_set_id(lua_State * state) } /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA ) + if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA) { lua_settop(state, 0); return 0; @@ -588,14 +613,14 @@ int lua_session_set_id(lua_State * state) int setid = lua_tointeger(state, -1); lua_pop(state, 1); - struct session * sess = (struct session *)lua_topointer(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_get_type(lua_State * state) +int lua_session_get_type(lua_State *state) { /* 参数个数检查 */ if (lua_gettop(state) != 1) @@ -605,14 +630,15 @@ int lua_session_get_type(lua_State * state) } /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TLIGHTUSERDATA ) + if (lua_type(state, -1) != LUA_TLIGHTUSERDATA) { lua_settop(state, 0); return 0; } - struct session * sess = (struct session *)lua_topointer(state, -1); - if ( !sess ) { + struct session *sess = (struct session *)lua_topointer(state, -1); + if (!sess) + { lua_settop(state, 0); return 0; } @@ -622,7 +648,7 @@ int lua_session_get_type(lua_State * state) return 1; } -int lua_session_set_type(lua_State * state) +int lua_session_set_type(lua_State *state) { /* 参数个数检查 */ if (lua_gettop(state) != 2) @@ -632,7 +658,7 @@ int lua_session_set_type(lua_State * state) } /* 参数类型检查 */ - if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA ) + if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA) { lua_settop(state, 0); return 0; @@ -640,7 +666,7 @@ int lua_session_set_type(lua_State * state) int settype = lua_tointeger(state, -1); lua_pop(state, 1); - struct session * sess = (struct session *)lua_topointer(state, -1); + struct session *sess = (struct session *)lua_topointer(state, -1); lua_pop(state, 1); session_set_id(sess, settype); |
