【修改】更新概要设计文档

This commit is contained in:
niubinghui
2024-08-07 15:05:58 +08:00
parent 0f5cbff974
commit c0577f3055

View File

@@ -1,4 +1,43 @@
# LuaPluginManage
- [LuaPluginManage](#luapluginmanage)
- [总述](#总述)
- [整体功能](#整体功能)
- [状态机](#状态机)
- [函数](#函数)
- [数据](#数据)
- [插件](#插件)
- [数据转换\*](#数据转换)
- [接口](#接口)
- [外部接口](#外部接口)
- [内部接口](#内部接口)
- [C注册函数](#c注册函数)
- [Lua注册函数](#lua注册函数)
- [总体设计](#总体设计)
- [初始化](#初始化)
- [退出](#退出)
- [功能模块](#功能模块)
- [函数及全局变量注册](#函数及全局变量注册)
- [数据结构](#数据结构)
- [函数](#函数-1)
- [Lua与C数据转换](#lua与c数据转换)
- [数据结构](#数据结构-1)
- [状态机管理](#状态机管理)
- [数据结构](#数据结构-2)
- [函数](#函数-2)
- [插件管理](#插件管理)
- [数据结构](#数据结构-3)
- [函数](#函数-3)
- [脚本管理](#脚本管理)
- [数据结构](#数据结构-4)
- [函数](#函数-4)
- [配置管理](#配置管理)
- [数据结构](#数据结构-5)
- [函数](#函数-5)
- [C注册函数](#c注册函数-1)
- [Lua注册函数](#lua注册函数-1)
- [安全性](#安全性)
- [重名的情况](#重名的情况)
## 总述
### 整体功能
实现Lua插件的管理功能功能整体包括如下部分
@@ -34,93 +73,135 @@
注册会话插件此功能仅在lua端暴露不在C接口中。在插件加载过程中可注册会话插件
订阅会话消息此功能仅在lua端暴露不在C接口中。在插件加载过程中可订阅一个会话中特定id的会话消息
处理会话消息:处理会话过程中的数据
### 数据转换
### 数据转换*
将Lua数据翻译为C中可读可写可持久化保存的数据也可以将一个由Lua转换为C数据得到的序列化数据转换为Lua中的数据结构
Lua转换至C将Lua数据序列化成为C中一段内存数据
C转换至Lua将C中数据反序列化为Lua中一段数据
## 接口
### 外部接口
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lua_plugin_manage_init | struct stellar * st<br>const char * config_file_path | 创建的lua插件管理器实例指针 | 根据配置文件创建一个lua插件管理器实例并在函数内完成配置加载及初始化过程
| lua_plugin_manage_exit | struct lua_plugin_manage_schema * lua_plug_mgr | void | 清理一个lua插件管理器实例清除内部所有数据
### 内部接口
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lua_cbinding_functions | lua_State *state | 0表示成功其他表示失败返回值大于0时表示注册失败的元素个数 | 向lua状态机中注册函数函数定义在全局变量lua_bind_functions中
| lua_cbinding_datas | lua_State *state | 0表示成功其他表示失败返回值大于0时表示注册失败的元素个数 | 向lua状态机中注册数据所有注册数据在状态机中作为全局变量存在所有注册数据保存在lua_bind_datas全局变量中
| lua_cdata_push_stack | lua_State *state<br>struct lua_cdata *cdata | 0表示成功其他表示失败 | 将一个data结构入栈
| lua_cdata_pop_stack | lua_State *state<br>struct lua_cdata *cdata | 0表示成功其他表示失败 | 从栈中弹出一个元素并保存在data结构中类型限制见函数实现部分
| lua_cdata_destory | struct lua_cdata *cdata | void | 销毁一个data结构只有string类型需要调用此函数其他的情况直接释放即可
| lua_context_new | lua_State *state | 创建出的context实例 | 在状态机中生成一个context
| lua_context_push_stack | struct lua_context *context | 0表示成功其他表示失败 | 将一个context入栈
| lua_context_free | struct lua_context *context | void | 释放一个context
### C注册函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lpm_ctx_new_func | struct session *sess<br>void *plugin_env | 在该session中创建的context实例 | session创建时调用
| lpm_ctx_free_func | struct session *sess<br>void *sess_ctx<br>void *plugin_env | void | session销毁时调用
### Lua注册函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lua_plugin_manage_session_regist | lua_State * state | 0无需处理返回值1需处理返回值 | lua中调用该函数注册插件注册完成后调用方式为调用plugin_manage.register
## 总体设计
### 初始化
```mermaid
---
title: lua plugin manage init
title: lua_plugin_manage_init
---
flowchart TD;
start(["开始"]);
create["创建状态机"];
bindfunc["绑定函数"];
binddata["绑定数据"];
init["读取配置文件并获取插件"]
load["加载插件"];
createschema["calloc新的schema"];
loadconfig["从配置文件中加载配置"];
configcheck{"检查返回值"};
threadcount["获取线程数量"];
loadthread["每个线程中创建新的状态机"];
freeschema["清理schema"];
finish(["结束"]);
start --> create
create --> bindfunc
bindfunc --> binddata
binddata --> init
init --> load
load --> finish
start --> createschema
createschema --> loadconfig
loadconfig --> configcheck
configcheck --> |<0|freeschema
configcheck --> |>=0|threadcount;
threadcount --> loadthread
loadthread --> finish
freeschema --> finish
```
1. 创建一个状态机实例,后续所有的运行全部依赖于该状态机;
2.自定义的C函数绑定至状态机中功能详见[C函数管理](#函数管理)
3. 将一些自定义的数据注册至状态机中,功能详见[数据管理](#数据管理)
4. 进行初始化,根据一个配置文件,加载文件中声明需要加载的所有插件。此时,插件仅是在将必要的信息暂存在状态机中;
5. 加载插件依次调用每一个插件中的load函数功能详见[插件管理](#插件管理)
### 运行
运行过程中所有调用均通过现在的stellar中的plugin_manage于session_plugin_manage进行调用运行过程中不会主动运行。
1. 创建一个新的schema实例
2.配置文件中配置信息加载至schema实例中暂存
3. 在schema中按照线程数量创建状态机并完成初始化
### 退出
```mermaid
---
title: lua plugin manage exit
title: lua_plugin_manage_exit
---
flowchart TD;
start(["开始"]);
unload["依次卸载插件"];
clean["关闭状态机"];
freespecific["依次清理加载的配置信息"];
freethread["依次关闭线程中的状态机"];
freeschema["清理schema"];
finish(["结束"]);
start --> unload
unload --> clean
clean --> finish
start --> freespecific
freespecific --> freethread
freethread --> freeschema
freeschema --> finish
```
1. 依次调用插件管理中每一个插件的unload函数功能详见[插件管理](#插件管理)
2. 关闭状态机并释放占用的资源;
## 外部接口
C端函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lpm_state_instance_create | void | 创建完成的状态机指针NULL为创建失败 | 创建一个状态机实例。
| lpm_state_instance_init | struct stellar * st<br>struct lpm_state * state<br>const char * filename | 0表示成功其他表示失败 | 根据一个配置文件对一个状态机实例进行初始化
| lpm_state_instance_free | struct lpm_state * | int | 释放一个状态机实实例,释放其占用内存
| lpm_cdata_clean | struct lpm_cdata * | void | 清理一个struct lpm_cdata实例内所有数据删除其内部数据占用的内存
| lpm_cbinding_get_params_count | struct lpm_state * state | 传入的参数数量,负数为获取失败 | 该函数用于C函数获取lua在调用C函数时传入的参数个数
| lpm_cbinding_get_params | struct lpm_state * state<br>int index<br>struct lpm_cdata * data | 0表示成功其他表示失败 | 获取传入C中的具体参数内容index表示参数下标data为具体参数内容
| lpm_cbinding_push_return | struct lpm_state * state<br>int count<br>struct lpm_cdata * data | 0表示成功其他表示失败 | 将C函数运行结果传入Lua中count表示传入的数据数量data为具体数据
| lpm_cbinding_function_register | struct lpm_state * state<br>lpm_cbinding_function function<br>const char * func_name<br>const char * space_name | 0表示成功其他表示失败 | 将一个C函数注册至Lua中在Lua中调用方式为space_name.func_name的形式如果space_name为空时可通过func_name进行调用
| lpm_cbinding_function_remove | struct lpm_state * state<br>const char * func_name<br>const char * space_name | 0表示成功其他表示失败 | 从Lua状态机中删除一个函数
| lpm_cdata_register | struct lpm_state * state<br>struct lpm_cdata * data<br>const char * data_name<br>const char * space_name | 0表示成功其他表示失败 | 将一个C数据传入Lua中并可作为Lua的全局变量使用在Lua中使用方式为space_name.data_name当space_name为空时可直接使用data_name获取该变量的值
| lpm_cdata_remove | struct lpm_state * state<br>const char * data_name<br>const char * space_name | 0表示成功其他表示失败 | 从Lua状态机中删除一个全局变量
| lpm_plugin_load | struct stellar * st | 返回插件的私有运行数据 | 提供至stellar中plugin manage的插件注册函数
| lpm_plugin_unload | void * plugin_env | void | 提供至stellar中plugin manage的插件卸载函数
| lpm_ctx_new_func | struct session * sess<br>void * plugin_env | 在该session上插件的私有数据 | 提供至stellar中session plugin manage的函数在会话创建过程中调用创建该会话中的插件私有数据
| lpm_ctx_free_func | struct session * sess<br>void * sess_ctx<br>void * plugin_env | void | 提供至stellar中session plugin manage的函数在会话结束时调用删除在会话上的插件私有数据
| lpm_on_session_msg_func | struct session * sess<br>int topic_id<br>const void * msg<br>void * sess_ctx<br>void * plugin_env | void | 会话中的消息处理函数
| lpm_trans_data_luatoc | struct lpm_state * state<br>struct lpm_cdata * data | 0表示成功其他表示失败 | 将状态机中当前栈顶的数据转换为一个C中的cdata结构并出栈
| lpm_trans_data_ctolua | struct lpm_state * state<br>struct lpm_cdata * data | 0表示成功其他表示失败 | 将一个cdata结构转为一个Lua中的数据并将该数据置于状态机栈顶
Lua端函数
## 功能模块
### 函数管理
### 函数及全局变量注册
1. 如果传入参数中包含space_name则将函数在Lua中注册为space_name.func_name形式
2. 如果参数中没有space_name则将函数在Lua中注册为func_name形式
3. 删除过程中只是将该函数的指针在Lua中修改为nil并不会真正删除需要等Lua下一次自动垃圾回收完成后才会真正完成删除
4. 数据管理与函数管理流程相同不同之处在于函数删除时会检查Lua中数据类型是否为function但是在全局变量删除时不会做该校验
#### 数据结构
```C
/* 需要注册至lua中的函数 */
struct lua_binding_function
{
/* 注册函数原型 */
lua_CFunction binding_function;
/* 注册至lua中的函数名称 */
char *binding_function_name;
/* 注册至lua中的命名空间名称 */
char *binding_function_space_name;
};
/* 需要注册至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_cbinding_function | lua_State *state<br>lua_CFunction bind_function<br>const char *function_name<br>const char *space_name | 0表示成功其他表示失败 | 向lua状态机中注册一个函数
| lua_cbinding_function_remove | lua_State *state<br>const char *function_name<br>const char *space_name | 0表示成功其他表示失败 | 从状态机中移除一个已经完成注册的函数
| lua_cbinding_data | lua_State *state<br>struct lua_binding_data *data | 0表示成功其他表示失败 | 向lua状态机中注册一段数据该数据在状态机中作为全局变量存在
| lua_cbinding_data_remove | lua_State *state<br>const char *data_name<br>const char *space_name | 0表示成功其他表示失败 | 从状态机中删除一个已经注册的数据,从状态机中删除该全局变量的引用
```mermaid
---
title: function register
title: 函数注册 lua_cbinding_function
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
checkspace{"参数中是否有space_name"};
@@ -152,10 +233,9 @@ flowchart TD;
```mermaid
---
title: function remove
title: 函数卸载 lua_cbinding_function_remove
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
funccheck{"func_name是否在管理列表中"}
@@ -182,14 +262,12 @@ flowchart TD;
functype --> |N|finish
deletefunc --> finish
```
### 数据管理
与函数管理流程相同不同之处在于函数删除时会检查Lua中数据类型是否为function但是在全局变量删除时不会做该校验
```mermaid
---
title: data register
title: 数据注册 lua_cbinding_data
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
checkspace{"参数中是否有space_name"};
@@ -221,10 +299,9 @@ flowchart TD;
```mermaid
---
title: data remove
title: 数据卸载 lua_cbinding_data_remove
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
datacheck{"data_name是否在管理列表中"}
@@ -248,36 +325,525 @@ flowchart TD;
datadelete --> deletedata
deletedata --> finish
```
### 插件管理
整体原则每一个Lua插件在stellar的插件管理器中为一个单独的插件每一个session_plugin在stellar的会话插件管理器中也为一个单独的插件
解决方案:
1. 在状态机整体init过程中将所有插件仅暂时保存在一个链表中但是不加载至stellar的插件管理器中。每一次调用lpm_plugin_load函数时从插件链表中取出一个节点并调用该节点中保存的load函数。之后在使用过程中其plugin_env中已经保存了插件的所有信息可通过plugin_env分辨是哪一个插件并调用该插件中数据
2. 在状态机init过程中为插件分配一个lua_plugin_manage_id在所有函数调用过程中增加一个参数每次传入参数时携带该lua_plugin_manage_id
对于会话插件的管理,由于一个插件中可能注册多个会话插件,在会话插件管理上有两种不同的处理方案:
1. plugin_env中维护一个该插件的会话插件列表在调用Lua会话插件时需要同时传入插件ID在该列表中查找对应的处理函数进行调用
2. 会话插件注册过程中复制一个完整的plugin_env每一个会话插件拥有一个完全独立的plugin_env
### Lua与C数据转换
## 数据结构
1. 根据不同的数据类型调用不同的Lua原生函数进行出入栈操作
2. context本质是一个预分配并完成引用关联的lua-table在lua状态机中可以不受限制的使用
3. 后续可能会根据数据类型进行lua和C的内存转换当前不支持内存共享使用
4. lua元素在出栈过程中table类型的变量只创建引用并返回引用编号
#### 数据结构
```C
struct lpm_cdata {
enum LPM_DATATYPE data_type;
int data_length;
union {
int data_bool;
double data_num;
int data_int;
char * data_string;
struct lpm_ctable * data_table;
void * data_user;
void * data_context;
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;
};
};
struct lua_context
{
lua_State *context_state;
int context_ref_id;
};
```
## 可配置项
### 状态机管理
1. 每个线程中创建一个状态机,将该线程中加载的所有插件全部注册在该状态机中;
## 安全设计
#### 数据结构
```C
struct lua_thread_state
{
/* 创建状态机的线程ID */
int thread_id;
/* 已经插入的插件数量 */
int thread_plugin_count;
/* 生成的状态机 */
lua_State *thread_state;
// struct lua_pl_state_private * lua_thread_private;
/* 该线程状态机中注册的插件列表 */
UT_array *thread_env_array;
/* 状态机的启动时间 */
time_t thread_begin_time;
};
```
#### 函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lua_plugin_manage_state_load | struct lua_plugin_manage_schema *schema<br>int thread_count | >=0状态机创建成功的数量<0加载失败 | 在schema中根据线程数量创建多个状态机并完成状态机的初始化
| thread_state_instance_init | struct lua_thread_state *thread_state<br>int state_id | 0表示成功其他表示失败 | 初始化一个状态机的实例包括创建lua_State、绑定函数、绑定全局变量等
| thread_state_instance_destory | void * elt | void | 销毁一个状态机,清空状态机中所有注册的插件并关闭状态机
| thread_state_instance_load | struct lua_thread_state *thread_state<br>struct lua_plugin_manage_schema *schema | 0表示成功其他表示失败 | 根据配置数量创建plugin_env并依次调用插件加载函数完成插件的初始化
```mermaid
---
title: lua_plugin_manage_state_load
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
initstatearray["初始化schema中状态机队列"];
checkstatecount{"状态机数量与线程数量一致"};
createstate["创建新的状态机"];
insertstate["创建完成的新状态机插入至schema队列中"];
checkstateinit{"状态机全部完成初始化"};
initstate["初始化状态机"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|initstatearray
paramcheck --> |N|finish
initstatearray --> checkstatecount;
checkstatecount --> |Y|checkstateinit;
checkstatecount --> |N|createstate;
createstate --> insertstate;
insertstate --> checkstatecount;
checkstateinit --> |Y|finish
checkstateinit --> |N|initstate;
initstate --> checkstateinit;
```
```mermaid
---
title: thread_state_instance_init
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
newstate["创建状态机"];
bindfunc["绑定函数"];
binddata["绑定全局变量"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|newstate
praamcheck --> |N|finish
newstate --> bindfunc
bindfunc --> binddata
binddata --> finish
```
```mermaid
---
title: thread_state_instance_destory
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
unloadplugin["依次卸载所有插件"];
closestate["关闭状态机"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|unloadplugin
paramcheck --> |N|finish
unloadplugin --> closestate
closestate --> finish
```
```mermaid
---
title: thread_state_instance_load
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
plugincount{"完成所有插件初始化"};
initpluginenv["初始化插件环境变量"];
loadcount{"完成所有插件加载"};
loadpluginenv["调用插件加载函数"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|plugincount
paramcheck --> |N|finish
plugincount --> |N|initpluginenv
plugincount --> |Y|loadcount
initpluginenv --> plugincount
loadcount --> |Y|finish
loadcount --> |N|loadpluginenv
loadpluginenv --> loadcount
```
### 插件管理
整体原则每一个Lua插件在stellar的插件管理器中为一个单独的插件插件在C插件管理器中共用同一个函数在调用lua插件函数时根据插件的编号及注册使用的plugin_env查找插件的实际lua函数并完成调用
#### 数据结构
```C
/* 每一个插件的函数信息 */
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;
};
struct lua_plugin_env
{
/* 插件注册的状态机 */
lua_State *plugin_env_state;
/* 该环境数据中包含的所有插件列表 */
UT_array *plugin_env_plugin_array;
/* 加载插件的lua函数 */
struct lua_script plugin_env_load_func;
/* 卸载插件的lua函数 */
struct lua_script plugin_env_unload_func;
/* 该插件运行环境数据的名称, 在创建时同时在状态机中创建该名称的命名空间 */
/* 插件申请lua内的全局变量可以保存在该命名空间内, 防止被其他内容覆盖 */
// char *plugin_env_name;
/* 在lua中保存运行数据的引用ID */
int plugin_env_ref_id; /* plugin_env */
};
```
#### 函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| session_plugin_instance_init | struct lua_session_plugin *session_plugin<br>lua_State *state<br>int plugin_id<br>int new_refid<br>int free_refid | 0表示成功其他表示失败 | 初始化一个运行在会话中的插件
| session_plugin_instance_destory | void *elt | void | 销毁一个运行在会话中的插件
| plugin_env_instance_init | struct lua_plugin_env *plugin_env<br>lua_State *state<br>struct lua_config_specific *specific | 0表示成功其他表示失败 | 根据specific配置初始化一个plugin_env在此过程中仅将函数加载完成并未进行load函数调用load函数在状态机加载完成所有插件后统一调用
| plugin_env_instance_destory | void *elt | void | 销毁一个插件运行环境变量
```mermaid
---
title: session_plugin_instance_init
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
init["根据引用id分别初始化ctx_new及ctx_free"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|init
paramcheck --> |N|finish
init --> finish
```
```mermaid
---
title: session_plugin_instance_destory
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
delete["分别删除状态机中的引用"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|delete
paramcheck --> |N|finish
delete --> finish
```
```mermaid
---
title: plugin_env_instance_init
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
init["根据名称分别初始化ctx_new及ctx_free"];
createenv["创建该插件pluginenv"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|init
paramcheck --> |N|finish
init --> createenv
createenv --> finish
```
```mermaid
---
title: plugin_env_instance_destory
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
unload["调用unload函数"];
unregist["卸载所有在该env中的插件"];
deletefunc["删除load及unload函数在状态机中的引用"];
deleteenv["删除创建的plugin_env"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|unload
paramcheck --> |N|finish
unload --> unregist
unregist --> deletefunc
deletefunc --> deleteenv
deleteenv --> finish
```
### 脚本管理
#### 数据结构
```C
/* 一个可以运行的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;
};
```
#### 函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| script_instance_init_byname | struct lua_script *script<br>lua_State *state<br>const char *filepath<br>const char *funcname | 0表示成功其他表示失败 | 根据文件名及函数名称从lua脚本中初始化一个脚本
| script_instance_init_byrefid | struct lua_script *script<br>lua_State *state<br>int ref_id | 0表示成功其他表示失败 | 根据一个已经在状态机中生成引用的引用编号初始化一个脚本
| script_instance_clean | struct lua_script *script | void | 清理一个脚本实例
| script_execute | struct lua_script *script<br>int pcount<br>struct lua_cdata *param<br>int rmaxcount<br>struct lua_cdata *rvalue | 0表示成功其他表示失败 | 运行一个脚本
```mermaid
---
title: script_instance_init_byname
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
fileload["加载lua文件"];
findfunc["在文件中寻找对应函数"];
createref["创建引用"];
initscript["初始化脚本实例"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|fileload
paramcheck --> |N|finish
fileload --> findfunc
findfunc --> createref
createref --> initscript
initscript --> finish
```
```mermaid
---
title: script_instance_init_byrefid
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
initscript["初始化脚本实例"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|initscript
paramcheck --> |N|finish
initscript --> finish
```
```mermaid
---
title: script_instance_clean
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
delete["状态机中删除该引用"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|delete
paramcheck --> |N|finish
delete --> finish
```
```mermaid
---
title: script_execute
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
getref["根据refid加载函数"];
pushparam["传入参数"];
logtime["记录时间"];
execute["调用函数"];
popreturn["取出参数"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|getref
paramcheck --> |N|finish
getref --> pushparam
pushparam --> logtime
logtime --> execute
execute --> popreturn
popreturn --> finish
```
### 配置管理
#### 数据结构
```C
/* 根据配置文件加载过程中保存插件信息的临时结构 */
struct lua_config_specific
{
/* 插件需要使用的文件名 */
char *config_specific_file;
/* 插件名称 */
// char *config_specific_name;
/* 加载插件需要调用的函数名称 */
char *config_specific_load_func;
/* 卸载插件需要调用的函数名称 */
char *config_specific_unload_func;
};
```
#### 函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| specific_instance_copy | void *dst<br>const void *src | void | 拷贝一个配置结构实例,拷贝过程为深拷贝
| specific_instance_destory | void *elt | void | 销毁一个配置结构实例,释放内部元素占用的内存
```mermaid
---
title: specific_instance_copy
---
flowchart TD;
start(["开始"]);
copy["依次拷贝内部成员"]
finish(["结束"]);
start --> copy
copy --> finish
```
```mermaid
---
title: specific_instance_destory
---
flowchart TD;
start(["开始"]);
free["释放内部成员"]
finish(["结束"]);
start --> free
free --> finish
```
### C注册函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lpm_ctx_new_func | struct session *sess<br>void *plugin_env | 在该session中创建的context实例 | session创建时调用
| lpm_ctx_free_func | struct session *sess<br>void *sess_ctx<br>void *plugin_env | void | session销毁时调用
```mermaid
---
title: lpm_ctx_new_func
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
getpluginid["获取pluginid"];
searchid["在pluginenv中查找该pluginid"];
idcheck{"找到该id对应的插件"};
newcontext["创建新的context"];
execute["调用该插件实际的lua函数"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|getpluginid
paramcheck --> |N|finish
getpluginid --> searchid
searchid --> idcheck
idcheck --> |Y|newcontext
idcheck --> |N|finish
newcontext --> execute
execute --> finish
```
```mermaid
---
title: lpm_ctx_free_func
---
flowchart TD;
start(["开始"]);
paramcheck{"参数检查"};
getpluginid["获取pluginid"];
searchid["在pluginenv中查找该pluginid"];
idcheck{"找到该id对应的插件"};
execute["调用该插件实际的lua函数"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|getpluginid
paramcheck --> |N|finish
getpluginid --> searchid
searchid --> idcheck
idcheck --> |Y|execute
idcheck --> |N|finish
execute --> finish
```
### Lua注册函数
| 函数名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- |
| lua_plugin_manage_session_regist | lua_State * state | 0无需处理返回值1需处理返回值 | lua中调用该函数注册插件注册完成后调用方式为调用plugin_manage.register
```mermaid
---
title: lua_plugin_manage_session_regist
---
flowchart TD;
start(["开始"]);
paramcheck{"参数数量检查"};
paramtypecheck{"参数类型检查"};
getpluginenv["获取plugin_env"];
getfreeref["将ctx_free函数创建引用"];
getnewref["将ctx_new函数创建引用"];
getstellar["获取stellar"];
regist["调用stellar_session_plugin_register"];
insertplugin["将插件id与函数对应关系插入plugin_env"];
returnid["返回pluginid"];
finish(["结束"]);
start --> paramcheck
paramcheck --> |Y|paramtypecheck
paramcheck --> |N|finish
paramtypecheck --> |Y|getpluginenv
paramtypecheck --> |N|finish
getpluginenv --> getfreeref
getfreeref --> getnewref
getnewref --> getstellar
getstellar --> regist
regist --> insertplugin
insertplugin --> returnid
returnid --> finish
```
## 安全性
### 重名的情况
在Lua中并不会校验是否存在重名变量、重名函数等出现重名的变量或函数会直接将旧的数据覆盖。