#include #include #include #include #include #include #include #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"}, {lua_session_get0_current_payload, "get_payload", "session"}, {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 { lua_State *state; }; /* ***** ***** ***** ***** ***** ***** */ /* cbinding */ /* ***** ***** ***** ***** ***** ***** */ static int lua_cbinding_single_function(struct lua_state *state, struct lua_bind_function_spec *function_spec) { 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 int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec) { if (!state || !data_spec || !data_spec->data_value || !data_spec->data_name) return PARAM_ERR; lua_State *L = (lua_State *)state; if (data_spec->space_name) { lua_getglobal(L, data_spec->space_name); if (lua_gettop(L) == 0 || lua_type(L, -1) == LUA_TNIL) { lua_newtable(L); lua_setglobal(L, data_spec->space_name); lua_settop(L, 0); lua_getglobal(L, data_spec->space_name); } else { if (lua_type(L, -1) != LUA_TTABLE) { lua_settop(L, 0); return BIND_NAMESPACE_TYPE_ERR; } lua_getfield(L, -1, data_spec->data_name); if (lua_type(L, -1) != LUA_TNIL) { lua_settop(L, 0); return BIND_DATA_TYPE_ERR; } lua_pop(L, 1); } switch (data_spec->data_type) { case DATATYPE_BOOL: if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE")) lua_pushboolean(L, 1); else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE")) lua_pushboolean(L, 0); break; case DATATYPE_INT: lua_pushinteger(L, atoi(data_spec->data_value)); break; case DATATYPE_NUM: lua_pushnumber(L, (lua_Number)atof(data_spec->data_value)); break; case DATATYPE_STRING: lua_pushstring(L, (const char *)data_spec->data_value); break; default: /* 其他类型不支持 */ lua_settop(L, 0); return BIND_DATA_TYPE_UNKNOWN; } lua_setfield(L, -2, data_spec->data_name); } else { lua_getglobal(L, data_spec->data_name); if (lua_type(L, -1) != LUA_TNIL) { lua_settop(L, 0); return BIND_DATA_TYPE_ERR; } lua_pop(L, 1); switch (data_spec->data_type) { case DATATYPE_BOOL: if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE")) lua_pushboolean(L, 1); else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE")) lua_pushboolean(L, 0); break; case DATATYPE_INT: lua_pushinteger(L, atoi(data_spec->data_value)); break; case DATATYPE_NUM: lua_pushnumber(L, (lua_Number)atof(data_spec->data_value)); break; case DATATYPE_STRING: lua_pushstring(L, (const char *)data_spec->data_value); break; default: /* 其他类型不支持 */ lua_settop(L, 0); return BIND_DATA_TYPE_UNKNOWN; } lua_setglobal(L, data_spec->data_name); } lua_settop(L, 0); return SUCCESS; } int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num) { int failed_count = 0; for (unsigned index = 0; index < bind_func_num; index++) { if (lua_cbinding_single_function(state, &bind_function[index])) failed_count++; } return failed_count; } int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num) { int failed_count = 0; for (unsigned index = 0; index < bind_data_num; index++) { if (lua_cbinding_single_data(state, &bind_data[index])) failed_count++; } return failed_count; } /* ***** ***** ***** ***** ***** ***** */ /* context */ /* ***** ***** ***** ***** ***** ***** */ const char *context_magic_code = "ctx_code"; struct lua_context *lua_context_new(struct lua_state *state) { if (!state) return NULL; lua_State *L = (lua_State *)state; struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); new_context->magic_code = context_magic_code; new_context->state = state; lua_newtable(L); int ref_id = luaL_ref(L, LUA_REGISTRYINDEX); if (ref_id == LUA_REFNIL) return NULL; new_context->lua_context_ref_id = ref_id; return new_context; } 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; } void lua_context_push_stack(struct lua_context *context) { if (!context) return; if (context->lua_context_ref_id) lua_rawgeti((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id); return; } /* ***** ***** ***** ***** ***** ***** */ /* trans data between lua table and C */ /* ***** ***** ***** ***** ***** ***** */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" static int lua_function_writer(lua_State *state, const void *p, size_t sz, void *ud) { /* TODO: 这个函数在lua中会被大量调用, 频繁的realloc可能会导致内存碎片化, 后续调整一下内存分配机制 */ struct lua_cdata *data = (struct lua_cdata *)ud; data->type = DATATYPE_FUNCTION; if (!data->function) data->function = (void *)calloc(1, sizeof(sz)); else data->function = (void *)realloc(data->function, (data->data_len + sz)); memcpy((data->function + data->data_len), p, sz); data->data_len += sz; return 0; } static const char *lua_function_reader(lua_State *state, void *ud, size_t *sz) { struct lua_cdata *data = (struct lua_cdata *)ud; *sz = data->data_len; return (const char *)data->function; } #pragma GCC diagnostic pop struct lua_cdata *lua_cdata_new(void) { struct lua_cdata *new_data = (struct lua_cdata *)calloc(1, sizeof(struct lua_cdata)); memset(new_data, 0, sizeof(struct lua_cdata)); return new_data; } static void lua_cdata_inner_data_free(struct lua_cdata *cdata) { if (!cdata) return; cdata->type = 0; cdata->data_len = 0; switch (cdata->type) { case DATATYPE_STRING: free(cdata->string); break; case DATATYPE_LUA_TABLE: lua_ctable_free(cdata->ctable); break; case DATATYPE_FUNCTION: free(cdata->function); break; default: break; } return; } void lua_cdata_free(struct lua_cdata *cdata) { lua_cdata_inner_data_free(cdata); if (cdata) free(cdata); return; } int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata) { if (!state || !cdata) return PARAM_ERR; lua_State *L = (lua_State *)state; switch (cdata->type) { case DATATYPE_NIL: lua_pushnil(L); break; case DATATYPE_BOOL: lua_pushboolean(L, cdata->bool); break; case DATATYPE_INT: lua_pushinteger(L, cdata->integer); break; case DATATYPE_NUM: lua_pushnumber(L, cdata->number); break; case DATATYPE_STRING: lua_pushstring(L, cdata->string); break; case DATATYPE_TABLE: if (cdata->table) lua_rawgeti(L, LUA_REGISTRYINDEX, cdata->table); break; case DATATYPE_LUA_TABLE: lua_ctable_push_stack(state, cdata->ctable); break; case DATATYPE_POINTER: lua_pushlightuserdata(L, (void *)cdata->pointer); break; case DATATYPE_CONTEXT: lua_context_push_stack(cdata->context); break; case DATATYPE_FUNCTION: lua_load(L, lua_function_reader, (void *)cdata, NULL, NULL); break; default: return DATA_TYPE_UNKNOWN; } return SUCCESS; } int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata) { if (!state || !cdata) return PARAM_ERR; lua_State *L = (lua_State *)state; lua_cdata_inner_data_free(cdata); switch (lua_type(L, -1)) { case LUA_TNIL: cdata->type = DATATYPE_NIL; break; case LUA_TBOOLEAN: cdata->type = DATATYPE_BOOL; cdata->bool = lua_toboolean(L, -1); break; case LUA_TLIGHTUSERDATA: cdata->type = DATATYPE_POINTER; cdata->pointer = (void *)lua_topointer(L, -1); break; case LUA_TNUMBER: cdata->type = DATATYPE_NUM; cdata->number = lua_tonumber(L, -1); int try_int = (int)cdata->number; if ((double)try_int == cdata->number) { cdata->type = DATATYPE_INT; cdata->integer = lua_tointeger(L, -1); } break; case LUA_TSTRING: cdata->type = DATATYPE_STRING; cdata->string = (char *)strdup(lua_tostring(L, -1)); break; case LUA_TTABLE: cdata->type = DATATYPE_LUA_TABLE; cdata->ctable = lua_ctable_new(); lua_ctable_pop_stack(state, cdata->ctable); break; case LUA_TFUNCTION: cdata->type = DATATYPE_FUNCTION; lua_dump(L, lua_function_writer, cdata, 0); break; case LUA_TUSERDATA: cdata->type = DATATYPE_POINTER; cdata->pointer = (void *)lua_topointer(L, -1); break; default: return DATA_TYPE_UNKNOWN; } lua_pop(L, 1); return SUCCESS; } struct lua_ctable *lua_ctable_new(void) { struct lua_ctable *new_table = (struct lua_ctable *)calloc(1, sizeof(struct lua_ctable)); memset(new_table, 0, sizeof(struct lua_ctable)); return new_table; } void lua_ctable_free(struct lua_ctable *ctable) { if (!ctable) return; for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) { lua_cdata_free(ctable->array_data[array_index]); } for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) { lua_cnode_free(ctable->node_data[node_index]); } if (ctable->array_data) free(ctable->array_data); if (ctable->node_data) free(ctable->node_data); free(ctable); return; } int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable) { if (!state || !ctable) return PARAM_ERR; lua_State *L = (lua_State *)state; lua_newtable(L); for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) { lua_pushinteger(L, (array_index + 1)); lua_cdata_push_stack(state, ctable->array_data[array_index]); lua_settable(L, -3); } for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) { if (ctable->node_data[node_index]->node_string_key) lua_pushstring(L, ctable->node_data[node_index]->node_string_key); else lua_pushinteger(L, ctable->node_data[node_index]->node_integer_key); lua_cdata_push_stack(state, ctable->node_data[node_index]->node_data); lua_settable(L, -3); } return SUCCESS; } int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable) { if (!state || !ctable) return PARAM_ERR; lua_State *L = (lua_State *)state; /* 获取table长度 */ ctable->array_size = (size_t)lua_rawlen(L, -1); lua_pushnil(L); while (lua_next(L, -2)) { ctable->node_size++; if (lua_type(L, -2) == LUA_TNUMBER) { int numkey = lua_tointeger(L, -2); if (numkey > 0 && numkey <= (int)ctable->array_size) ctable->node_size--; } lua_pop(L, 1); } ctable->array_data = (struct lua_cdata **)calloc(ctable->array_size, sizeof(struct lua_cdata *)); for (unsigned array_index = 0; array_index < ctable->array_size; array_index++) { ctable->array_data[array_index] = lua_cdata_new(); } ctable->node_data = (struct lua_cnode **)calloc(ctable->node_size, sizeof(struct lua_cnode *)); for (unsigned node_index = 0; node_index < ctable->node_size; node_index++) { ctable->node_data[node_index] = lua_cnode_new(); } /* 依次获取数据 */ int key_index = 0; lua_pushnil(L); while (lua_next(L, -2)) { if (lua_type(L, -2) == LUA_TNUMBER) { int numkey = lua_tointeger(L, -2); if (numkey > 0 && numkey <= (int)ctable->array_size) lua_cdata_pop_stack(state, ctable->array_data[numkey - 1]); else { lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data); ctable->node_data[key_index]->node_integer_key = lua_tointeger(L, -1); ++key_index; } } else if (lua_type(L, -2) == LUA_TSTRING) { lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data); ctable->node_data[key_index]->node_string_key = strdup((char *)lua_tostring(L, -1)); ++key_index; } } return SUCCESS; } struct lua_cnode *lua_cnode_new(void) { struct lua_cnode *new_node = (struct lua_cnode *)calloc(1, sizeof(struct lua_cnode)); memset(new_node, 0, sizeof(struct lua_cnode)); new_node->node_data = lua_cdata_new(); return new_node; } void lua_cnode_free(struct lua_cnode *cnode) { if (cnode->node_string_key) free(cnode->node_string_key); if (cnode->node_data) lua_cdata_free(cnode->node_data); free(cnode); return; } /* ***** ***** ***** ***** ***** ***** */ /* execute one chunk */ /* ***** ***** ***** ***** ***** ***** */ int lua_chunk_execute( struct lua_state *state, int fn_ref_id, struct lua_cdata param[], size_t param_num, struct lua_cdata returnvalue[], size_t r_num, char *errlog, size_t err_len) { if (!state || fn_ref_id <= 0 || (param_num && !param) || (r_num && !returnvalue)) return PARAM_ERR; lua_State *L = (lua_State *)state; lua_rawgeti(L, LUA_REGISTRYINDEX, fn_ref_id); if (lua_type(L, -1) != LUA_TFUNCTION) { lua_settop(L, 0); return CHUNK_TYPE_NOT_FUNCTION; } int pushret = 0; for (unsigned param_index = 0; param_index < param_num; ++param_index) { if ((pushret = lua_cdata_push_stack(state, ¶m[param_index]))) { lua_settop(L, 0); return pushret; } } if (lua_pcall(L, param_num, LUA_MULTRET, 0)) { if (errlog) snprintf(errlog, (err_len - 1), "run script[%d] err %s\n", fn_ref_id, lua_tostring(L, -1)); lua_settop(L, 0); return CHUNK_RUN_CODE_FAIL; } if (r_num > 0) { int count = lua_gettop(L); /* 如果接收返回值数量不够, 只保留前r_num个返回值 */ if (count > (int)r_num) { lua_pop(L, (count - (int)r_num)); count = (int)r_num; } int pop_ret = 0; for (int i = (count - 1); i >= 0; --i) { if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i])))) { lua_settop(L, 0); return pop_ret; } } } lua_settop(L, 0); return SUCCESS; } /* TODO: 这个hash函数是不是合适 */ int calc_on_message_func_hash_key(int topic_id, int plugin_id) { return (((uint32_t)plugin_id << 3) + (uint32_t)topic_id) % HASH_MAX_NUM; } struct lua_on_message_fn *hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id) { int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id); struct lua_on_message_fn *insert_positon = &msg_fn_hashlist[hash_key]; while ((insert_positon->hash_on_use - HASH_MAX_NUM) > 0) { if (insert_positon->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1)) insert_positon = &msg_fn_hashlist[0]; else insert_positon++; /* 没有空位置了 */ if (insert_positon->hash_on_use % HASH_MAX_NUM == hash_key) return NULL; } insert_positon->hash_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->hash_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->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1)) find_position = &msg_fn_hashlist[0]; else find_position++; if ((find_position->hash_on_use % HASH_MAX_NUM == hash_key) || (find_position->hash_on_use - HASH_MAX_NUM) < 0) break; } return NULL; } #define LUA_GLOBAL_VALUE_REF_ID (LUA_RIDX_LAST + 2) static inline struct lua_state *thread_state_init(int thread_id, struct stellar *st, struct lua_plugin_manage *plugin_manage) { lua_State *new_L = luaL_newstate(); luaL_openlibs(new_L); lua_newtable(new_L); lua_pushinteger(new_L, thread_id); lua_setfield(new_L, -2, LUA_GLOBAL_THREAD_ID_KEY); lua_pushlightuserdata(new_L, st); lua_setfield(new_L, -2, LUA_GLOBAL_STELLAR_POINTER); lua_pushlightuserdata(new_L, plugin_manage); lua_setfield(new_L, -2, LUA_GLOBAL_PLUGIN_MANGE_POINTER); int global_ref_id = luaL_ref(new_L, LUA_REGISTRYINDEX); printf("set global ref id is %d\n", global_ref_id); lua_settop(new_L, 0); struct lua_state *new_state = (struct lua_state *)new_L; lua_cbinding_function(new_state, lua_bind_function, (sizeof(lua_bind_function) / sizeof(struct lua_bind_function_spec))); lua_cbinding_data(new_state, lua_bind_data, (sizeof(lua_bind_data) / sizeof(struct lua_bind_data_spec))); return new_state; } /* int lua_state_get_thread_id(struct lua_state * state) { 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; } */ 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)) { 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; } /* 创建on_load函数及on_unload函数的引用 */ lua_getglobal(L, spec->spec_load_func_name); if (lua_type(L, -1) != LUA_TFUNCTION) { snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_load_func_name); return STATE_REF_TYPE_ERR; } script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); if (script->lua_load_fn_ref_id <= 0) { snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_load_func_name, script->lua_load_fn_ref_id); return STATE_CREATE_REF_FAIL; } lua_getglobal(L, spec->spec_unload_func_name); if (lua_type(L, -1) != LUA_TFUNCTION) { snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_unload_func_name); return STATE_REF_TYPE_ERR; } script->lua_unload_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); if (script->lua_unload_fn_ref_id <= 0) { snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_unload_func_name, script->lua_unload_fn_ref_id); return STATE_CREATE_REF_FAIL; } /* 创建依赖于该script的script_env, 并调用on_load函数 */ lua_newtable(L); script->lua_script_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX); if (script->lua_script_env_ref_id <= 0) { snprintf(errlog, (errlog_len - 1), "spec[%s] create script env failed, ref is %d\n", spec->spec_file_path, script->lua_script_env_ref_id); return STATE_CREATE_REF_FAIL; } struct lua_cdata param[2]; param[0].type = DATATYPE_POINTER; param[0].pointer = (void *)st; param[1].type = DATATYPE_TABLE; param[1].table = script->lua_script_env_ref_id; char exec_err[1024] = {0}; int exec_ret = lua_chunk_execute(state, script->lua_load_fn_ref_id, param, 2, NULL, 0, exec_err, sizeof(exec_err)); if (exec_ret) { snprintf(errlog, (errlog_len - 1), "spec[%s]%s call fail, err num %d, err %s\n", spec->spec_file_path, spec->spec_load_func_name, exec_ret, exec_err); return STATE_CALL_LOAD_FAILED; } return SUCCESS; }; // static UT_icd lua_session_plugin_icd = {sizeof(struct lua_session_plugin_env), NULL, NULL, NULL}; // static UT_icd lua_packet_plugin_icd = {sizeof(struct lua_packet_plugin_env), NULL, NULL, NULL}; // static UT_icd lua_message_free_icd = {sizeof(struct lua_message_free_arg), NULL, NULL, NULL}; struct lua_plugin_manage *lua_plugin_manage_init( struct stellar *st, struct lua_config_spec specific[], size_t specific_num) { if (!st) return NULL; char errlog[1024] = {0}; struct lua_plugin_manage *new_plugin_manage = (struct lua_plugin_manage *)calloc(1, sizeof(struct lua_plugin_manage)); memset(new_plugin_manage, 0, sizeof(struct lua_plugin_manage)); new_plugin_manage->st = st; int thread_count = stellar_get_worker_thread_num(st); if (thread_count <= 0) return new_plugin_manage; new_plugin_manage->state_num = thread_count; new_plugin_manage->state_array = (struct lua_state **)calloc(thread_count, sizeof(struct lua_state *)); memset(new_plugin_manage->state_array, 0, thread_count * sizeof(struct lua_state *)); for (int thread_index = 0; thread_index < thread_count; thread_index++) { new_plugin_manage->state_array[thread_index] = thread_state_init(thread_index, st, new_plugin_manage); } for (unsigned on_message_index = 0; on_message_index < HASH_MAX_NUM; on_message_index++) { new_plugin_manage->on_session_message_hashlist[on_message_index].hash_on_use = on_message_index; new_plugin_manage->on_packet_message_hashlist[on_message_index].hash_on_use = on_message_index; } if (specific_num == 0) return new_plugin_manage; new_plugin_manage->load_script_array = (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++) { if (lua_state_load_one_specific(new_plugin_manage->state_array[0], &specific[spec_index], &new_plugin_manage->load_script_array[spec_index], st, errlog, sizeof(errlog))) { printf("%s\n", errlog); goto err; } } lua_newtable((lua_State *)new_plugin_manage->state_array[0]); int lua_ref_max_id = luaL_ref((lua_State *)new_plugin_manage->state_array[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++) { lua_settop((lua_State *)new_plugin_manage->state_array[0], 0); lua_rawgeti((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, ref_index); lua_cdata_pop_stack(new_plugin_manage->state_array[0], trans_data); for (int thread_index = 1; thread_index < thread_count; thread_index++) { lua_cdata_push_stack(new_plugin_manage->state_array[thread_index], trans_data); int ref_id = luaL_ref((lua_State *)new_plugin_manage->state_array[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); } luaL_unref((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, lua_ref_max_id); return new_plugin_manage; err: lua_plugin_manage_exit(new_plugin_manage); return NULL; } void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr) { 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_array[script_index].lua_script_env_ref_id; lua_chunk_execute(lua_plug_mgr->state_array[0], lua_plug_mgr->load_script_array[script_index].lua_unload_fn_ref_id, ¶m, 1, NULL, 0, NULL, 0); } free(lua_plug_mgr->load_script_array); for (unsigned state_index = 0; state_index < lua_plug_mgr->state_num; ++state_index) { lua_close((lua_State *)lua_plug_mgr->state_array[state_index]); } free(lua_plug_mgr->state_array); struct lua_session_plugin_env *session_env = lua_plug_mgr->session_plugin_env_list; while (session_env) { struct lua_session_plugin_env *next = session_env->next; free(session_env); session_env = next; } struct lua_packet_plugin_env *packet_env = lua_plug_mgr->packet_plugin_env_list; while (packet_env) { struct lua_packet_plugin_env *next = packet_env->next; free(packet_env); packet_env = next; } struct lua_message_free_arg *message_free_arg = lua_plug_mgr->message_free_arg_list; while (message_free_arg) { struct lua_message_free_arg *next = message_free_arg->next; free(message_free_arg); message_free_arg = next; } free(lua_plug_mgr); return; }