/************************************************************************* > 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; * * 08-13 * 1. 由于context结构体修改, 部分函数调用及处理逻辑需要同步修改 * * 08-15 * 1. 实现函数 * void lpm_message_free_func * void lpm_on_session_msg_func ************************************************************************/ #include "lua_plugin_manage_internal.h" #include "stellar/session.h" /* 内存分配过程中可能存在内存浪费的情况, 其他即使不是Lua的插件也分配了内存 */ /* 但是从调用的角度来说能够提高访问速度, 不需要做ID映射, 浪费内存也是以B为单位 */ struct lua_plugin_statistics *global_plugin_statistics = NULL; /* * Function: lpm_ctx_new_func * Input: | struct session * | sess | 会话信息 * | void * | plugin_env | 插件运行环境 * Output: * Return: | NULL | 运行函数错误 * | pointer | 运行插件上的ctx_new函数成功, 返回context * Description: 与C插件管理器保持一致的ctx_new_func */ void *lpm_ctx_new_func( struct session *sess, void *plugin_env) { if (__glibc_unlikely(!sess || !plugin_env)) return NULL; struct lua_model *env = (struct lua_model *)plugin_env; /* 获取插件ID并找到该插件 */ int plugin_id = session_get_current_plugin_id(sess); // int plugin_id = 1; struct lua_plugin *plugin = NULL; while ((plugin = utarray_next(env->plugin_array, plugin))) { if (plugin->plugin_id == plugin_id) break; } // LOGDEBUG("%d call plugin id %d, ref %d\n", plugin_id, plugin->plugin_id, plugin->ctx_new_ref); if (!plugin || plugin->plugin_id != plugin_id) /* 未找到该插件 */ return NULL; /* 获取当前的线程id并找到该线程对应的state */ int thread_id = session_get_current_thread_id(sess); if (thread_id > global_schema->state_count) return NULL; lua_State *state = global_schema->thread_state[thread_id]; struct lua_context *new_context = lua_context_new(state); if (__glibc_unlikely(!new_context)) /* 创建新的context失败 */ return NULL; int statisitc_id = thread_id * global_max_plugin_id + plugin_id; struct lua_cdata param[3] = {0}; param[0].cdata_type = DATATYPE_POINTER; param[0].cdata_pointer = sess; param[1].cdata_type = DATATYPE_TABLE; param[1].cdata_table = env->private_env_ref; param[2].cdata_type = DATATYPE_CONTEXT; param[2].cdata_context = new_context; if (lua_chunk_execute(state, plugin->ctx_new_ref, 3, param, 0, NULL)) { /* 脚本执行失败 */ ++global_plugin_statistics[statisitc_id].new_failed_count; lua_context_free(state, new_context); return NULL; } ++global_plugin_statistics[statisitc_id].new_success_count; return (void *)new_context; } /* * Function: lpm_ctx_free_func * Input: | struct session * | sess | 会话信息 * | void * | sess_ctx | 会话中的私有数据 * | void * | plugin_env | 插件运行环境 * Output: * Return: * Description: 与C插件管理器保持一致的ctx_free_func */ void lpm_ctx_free_func( struct session *sess, void *sess_ctx, void *plugin_env) { if (__glibc_unlikely(!sess || !sess_ctx || !plugin_env)) return; struct lua_model *env = (struct lua_model *)plugin_env; /* 获取插件ID并找到该插件 */ int plugin_id = session_get_current_plugin_id(sess); // int plugin_id = 1; struct lua_plugin *plugin = NULL; while ((plugin = utarray_next(env->plugin_array, plugin))) { if (plugin->plugin_id == plugin_id) break; } if (!plugin || plugin->plugin_id != plugin_id) /* 未找到该插件 */ return; int thread_id = session_get_current_thread_id(sess); if (thread_id > global_schema->state_count) return; lua_State *state = global_schema->thread_state[thread_id]; int statistic_id = thread_id * global_max_plugin_id + plugin_id; struct lua_cdata param[3] = {0}; param[0].cdata_type = DATATYPE_POINTER; param[0].cdata_pointer = sess; param[1].cdata_type = DATATYPE_CONTEXT; param[1].cdata_context = (struct lua_context *)sess_ctx; param[2].cdata_type = DATATYPE_TABLE; param[2].cdata_table = env->private_env_ref; if (lua_chunk_execute(state, plugin->ctx_free_ref, 3, param, 0, NULL)) ++global_plugin_statistics[statistic_id].free_failed_count; else ++global_plugin_statistics[statistic_id].free_success_count; lua_context_free(state, (struct lua_context *)sess_ctx); return; } /* * Function: lpm_message_free_func * Input: | struct session * | sess | 释放message对应的session * | void * | msg | 需要释放的message消息 * | void * | msg_free_arg | 释放函数需要存储的私有数据 * Output: * Return: * Description: 与C插件保持一致的session_msg_free_cb_func, 作为lua插件实现对应功能的通用函数 */ void lpm_message_free_func( struct session *sess, void *msg, void *msg_free_arg) { if (__glibc_unlikely(!sess || !msg || !msg_free_arg)) return; struct lua_message_mq *plugin_mq = (struct lua_message_mq *)msg_free_arg; int thread_id = session_get_current_thread_id(sess); if (thread_id > global_schema->state_count) return; lua_State *state = global_schema->thread_state[thread_id]; struct lua_cdata param[3] = {0}; param[0].cdata_type = DATATYPE_POINTER; param[0].cdata_pointer = sess; param[1].cdata_type = DATATYPE_CONTEXT; param[1].cdata_context = (struct lua_context *)msg; param[2].cdata_type = DATATYPE_TABLE; param[2].cdata_table = plugin_mq->mq_private_ref; lua_chunk_execute(state, plugin_mq->freemessage_ref, 3, param, 0, NULL); lua_context_free(state, (struct lua_context *)msg); return; } /* * Function: lpm_on_session_msg_func * Input: | struct session * | sess | 会话信息 * | int | topic_id | 处理的message topic id * | const void * | msg | 需要处理的消息信息 * | void * | sess_ctx | 会话中的私有数据 * | void * | plugin_env | 插件运行环境 * Output: * Return: * Description: 与C插件管理器保持一致的ctx_free_func */ void lpm_on_session_msg_func( struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env) { if (__glibc_unlikely(!sess || !sess || !plugin_env)) return; struct lua_context *sess_context = (struct lua_context *)sess_ctx; struct lua_model *env = (struct lua_model *)plugin_env; /* 获取插件ID并找到该插件 */ int plugin_id = session_get_current_plugin_id(sess); // int plugin_id = 1; struct lua_plugin *plugin = NULL; while ((plugin = utarray_next(env->plugin_array, plugin))) { if (plugin->plugin_id == plugin_id) break; } if (!plugin || plugin->plugin_id != plugin_id || !plugin->sub_topic_array) /* 未找到该插件, 或者在该插件中未发现注册的topic_id */ return; struct lua_plugin_mq *mq = NULL; while ((mq = utarray_next(plugin->sub_topic_array, mq))) { if (mq->topic_id == topic_id) break; } if (!mq || mq->topic_id != topic_id) /* 未找到对应的消息处理函数 */ return; /* 判断该消息是由C端插件产生的还是由Lua插件产生的 */ struct lua_message_mq *message_mq = search_message_mq_by_id(topic_id); int thread_id = session_get_current_thread_id(sess); if (thread_id > global_schema->state_count) return; lua_State *state = global_schema->thread_state[thread_id]; struct lua_cdata params[5] = {0}; params[0].cdata_type = DATATYPE_POINTER; params[0].cdata_pointer = sess; params[1].cdata_type = DATATYPE_INT; params[1].cdata_int = topic_id; if (!message_mq) { /* C端产生的直接使用指针 */ params[2].cdata_type = DATATYPE_POINTER; params[2].cdata_pointer = (void *)msg; } else { /* lua端产生的为一个context结构 */ params[2].cdata_type = DATATYPE_CONTEXT; params[2].cdata_context = (struct lua_context *)msg; } params[3].cdata_type = DATATYPE_CONTEXT; params[3].cdata_context = sess_context; params[4].cdata_type = DATATYPE_TABLE; params[4].cdata_table = env->private_env_ref; lua_chunk_execute(state, mq->onmessage_ref, 5, params, 0, NULL); return; }