summaryrefslogtreecommitdiff
path: root/src/lua_plugin_manage_internal.h
blob: fdb763b946629be97162c48768c1faa16d996098 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*************************************************************************
    > File Name: lua_plugin_manage_internal.h
    > Author:
    > Created Time: 2024-08
    > Encoding : UTF-8
 ************************************************************************/

/*************************************************************************
 * version
 * [ v0.1 ]
 * 08-02
 * 完成函数注册及数据注册功能
 * 1. 声明及定义结构
 *    struct lua_binding_function;
 *    enum BINDING_DATATYPE;
 *    struct lua_binding_data;
 * 2. 声明函数
 *    int lua_cbinding_function;
 *    int lua_cbinding_function_remove;
 *    int lua_cbinding_data;
 *    int lua_cbinding_data_remove;
 *    int lua_cbinding_functions;
 *    int lua_cbinding_datas;
 *
 * 08-05
 * 基本完成lua_plugin_manage中主流程
 * 1. 声明及定义结构
 *    struct lua_config_specific;
 *    struct lua_script;
 *    struct lua_session_plugin;
 *    struct lua_plugin_env;
 *    struct lua_thread_state;
 *    struct lua_plugin_manage_schema;
 * 2. 声明函数
 *    void specific_instance_copy;
 *    void specific_instance_destory;
 *    int script_instance_init_byname;
 *    int script_instance_init_byrefid;
 *    void script_instance_clean;
 *    int script_execute; (暂未实现)
 *    int session_plugin_instance_init;
 *    void session_plugin_instance_destory;
 *    int plugin_env_instance_init;
 *    void plugin_env_instance_destory;
 *    int thread_state_instance_init;
 *    void thread_state_instance_destory;
 *    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;
 *
 * 08-07
 * BugFix:
 * 修改struct lua_plugin_env, 其中增加文件路径
 * 防止在加载过程中由于函数重名导致的加载错误
 *
 * 08-08
 * 整体重构状态机相关结构定义, 拆分高频访问数据与低频访问数据
 * 状态机中数据管理由树形结构修改为数组型结构
 * 经过多次验证, 相同状态机在执行相同操作后返回结果及中间产物一致, 合并一些冗余数据
 ************************************************************************/
#ifndef LUA_PLUGIN_MANAGE_INTERNAL_H
#define LUA_PLUGIN_MANAGE_INTERNAL_H

#include "lua_plugin_manage.h"
#include "lpm_log.h"

#include <utarray.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

enum LUA_PLUGIN_RETURN
{
    /* 状态机相关的错误码 */
    STATE_LOAD_FILE_ERR = -400, /* 状态机加载lua文件时出错, 可能原因是文件不存在或文件无法加载 */
    STATE_CREATE_ENV_FAIL,      /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */
    STATE_GET_LOAD_FAIL,        /* 状态机加载load函数时出现错误, 该函数不存在或引用ID有问题 */
    STATE_GET_UNLOAD_FAIL,      /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */
    /* lua代码块运行错误码 */
    CHUNK_TYPE_NOT_FUNCTION = -300, /* 获取得到的代码块类型并非可执行的lua语句, 无法执行 */
    CHUNK_RUN_CODE_FAIL,            /* 调用代码过程中运行失败, 失败的具体报错信息会保存在栈中, 通过日志输出 */
    CHUNK_RCOUNT_ERR,               /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */
    /* lua与C之间数据转换或操作错误码 */
    DATA_PUSHSTACK_ERR = -200, /* 数据入栈过程中遇到未知的问题 */
    DATA_POPSTACK_ERR,         /* 数据从状态机中出栈过程中遇到未知的问题 */
    DATA_POPSTACK_NODATA,      /* 出栈过程中栈内无数据, 导致出栈失败 */
    DATA_TYPE_UNKNOWN,         /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */
    /* lua函数或数据绑定错误码 */
    BIND_NAMESPACE_TYPE_ERR = -100, /* 绑定或删除过程中使用命名空间, 但命名空间数据类型不符 */
    BIND_FUNCTION_TYPE_ERR,         /* 绑定或删除函数过程中数据类型错误 */
    BIND_DATA_TYPE_ERR,             /* 绑定或删除全局变量过程中数据类型错误 */
    BIND_DATA_TYPE_UNKNOWN,         /* struct lua_binding_data格式中数据类型无法识别, 或在该功能中操作了不支持的数据类型 */
    /* 通用返回值 */
    PARAM_ERR = -1, /* 传入参数错误, 可能是指针为空或类型不符合 */
    SUCCESS = 0,    /* 运行成功 */
};

/* ***** ***** ***** ***** ***** ***** */
/* 此部分主要功能为C向lua中注册函数及数据, 实现在lua_plugin_binding.c中 */
/* 需要注册至lua中的函数 */
struct lua_binding_function
{
    /* 注册函数原型 */
    lua_CFunction function;
    /* 注册至lua中的函数名称 */
    char *function_name;
    /* 注册至lua中的命名空间名称 */
    char *space_name;
};

/* 定义在lua_plugin_binding.c文件中 */
/* 所有需要注册至lua状态机中供lua调用的函数 */
extern struct lua_binding_function lua_bind_functions[];

/* 暂时支持前四种数据类型提前注册至lua状态机中 */
/* 其余类型用于运行lua函数等场景 */
enum DATATYPE
{
    DATATYPE_BEGIN = 0,
    /* nil类型 */
    DATATYPE_NIL,
    /* bool类型 */
    DATATYPE_BOOL,
    /* int类型 */
    DATATYPE_INT,
    /* double类型 */
    DATATYPE_NUM,
    /* 字符串类型 */
    DATATYPE_STRING,
    /* 以下类型不能用于全局变量注册, 仅用于函数等场景 */
    /* table类型 */
    DATATYPE_TABLE,
    /* 指针类型 */
    DATATYPE_POINTER,
    /* context上下文类型 */
    DATATYPE_CONTEXT,
    DATATYPE_END
};

/* 需要注册至lua状态机中的数据 */
struct lua_binding_data
{
    /* 注册的数据类型 */
    enum DATATYPE data_type;
    /* 注册数数据值 */
    char *data_value;
    /* 注册的数据名称 */
    char *data_name;
    /* 注册至lua中的命名空间名称 */
    char *space_name;
};

/* 定义在lua_plugin_binding.c中 */
/* 所有需要注册至lua状态机中的全局数据 */
extern struct lua_binding_data lua_bind_datas[];

/* 将lua_bind_functions中提前注册的所有函数注册至state状态机中 */
int lua_cbinding_functions(lua_State *state);
/* 将lua_bind_datas中提前注册的所有数据注册至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(lua_State *state, struct lua_context *context);
/* 释放一个context */
void lua_context_free(lua_State *state, struct lua_context *context);

/* ***** ***** ***** ***** ***** ***** */
/* 此部分为注册至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);

/* ***** ***** ***** ***** ***** ***** */
/* lua代码块相关操作, 实现在lua_plugin_chunk.c中 */
/* 执行一段lua代码块, 执行之前需要先在lua中生成一个引用ID */
int lua_chunk_execute(lua_State *state, int ref_id, int pcount, struct lua_cdata *params, int rcount, struct lua_cdata *returns);

/* ***** ***** ***** ***** ***** ***** */
/* 状态机相关的一些数据结构及操作, 实现在lua_plugin_manage.c中 */

extern struct lua_plugin_manage_schema *global_schema;

/* TODO:统计插件的运行情况, 暂时没想好怎么用 */
/* 记录一个插件的运行状态 */
struct lua_plugin_statistics
{
    /* ctx_new函数调用成功的次数 */
    int new_success_count;
    /* ctx_new函数调用失败的次数 */
    int new_failed_count;
    /* ctx_free函数调用成功的次数 */
    int free_success_count;
    /* ctx_free函数调用失败的次数 */
    int free_failed_count;
};

/* 保存Lua插件信息 */
struct lua_plugin
{
    /* 注册完成后得到的插件ID */
    int plugin_id;
    /* context_new函数在状态机中的引用值 */
    int ctx_new_ref;
    /* context_free函数在状态机中的引用值 */
    int ctx_free_ref;
};

#define MODEL_MARK_INIT_DONE 0x0001
#define MODEL_MARK_LOAD_DONE 0x0002

/* 加载的lua模块, 一个lua模块一般来说对应一个lua文件, 与C插件管理中的so相同 */
struct lua_model
{
    /* 该模块注册后的插件列表 */
    UT_array *plugin_array;
    /* 该模块load函数在状态机中的引用值 */
    int load_ref;
    /* 该模块unload函数在状态机中的引用值 */
    int unload_ref;
    /* 该模块创建出的plugin_env数据在状态机中的引用值 */
    int private_env_ref;
    /* 初始化过程中的标记 */
    unsigned short model_mark;
    /* 加载的插件数量 */
    unsigned short plugin_count;
};

struct lua_plugin_manage_schema
{
    struct stellar *st;

    /* 创建的状态机数量, 状态机数量与线程的个数相同 */
    int state_count;
    lua_State **thread_state;

    /*  */
    int model_count;
    struct lua_model *model;
};

#define LUA_PLUGIN_ENV_DEFAULT_KEY "__penv_pointer"
#define LUA_STATE_THREAD_ID_KEY "__thread_id"

#ifdef LUAPLUGIN_BASIC_UNITTEST
void debug_lua_state_stack(lua_State *state, int mod, const char *message);
void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema);
#endif

#endif