优化;删除预编译字节码

This commit is contained in:
xx
2024-06-01 14:08:44 +08:00
parent 2df927b62e
commit 417f6a4d82
29 changed files with 608 additions and 621 deletions

View File

@@ -1,80 +0,0 @@
#include "bytecodemanager.h"
#if ENABLE_BYTECODE == 1
#include "fastweb.h"
#include "utils/luautils.h"
#include "util/file.h"
#include "util/system.h"
#include "core/config.h"
bytecode_manager::bytecode_manager()
{
::ithread::start();
}
bytecode_manager::~bytecode_manager()
{
::ithread::stop();
::ithread::wait();
}
bool bytecode_manager::create(const std::string& name, const std::string& filepath, bool auto_update)
{
std::shared_ptr<bytecode> bc;
if (m_bytescodes.get(name, bc))
{
m_lastErrorDesc = "The bytecode already exists, name: " + name;
return false;
}
bc = std::make_shared<bytecode>();
if (LuaUtils::make_bytecode(filepath, bc->value) == false)
{
m_lastErrorDesc = "make bytecode failed.";
return false;
}
bc->filepath = filepath;
bc->auto_update = true;
bc->auto_update = auto_update;
bc->pre_modify_msec = ylib::file::last_write_time(filepath);
m_bytescodes.add(name, bc);
return true;
}
const std::string& bytecode_manager::get(const std::string& name)
{
static std::string return_empty;
std::shared_ptr<bytecode> bc;
if (m_bytescodes.get(name, bc) == false)
{
return return_empty;
}
return bc->value;
}
std::map<std::string, std::shared_ptr<bytecode>> bytecode_manager::map()
{
return *m_bytescodes.parent();
}
bool bytecode_manager::run()
{
m_bytescodes.lock();
auto map = m_bytescodes.parent();
for_iter(iter, (*map))
{
if (iter->second->auto_update == false)
continue;
auto last_write_time = ylib::file::last_write_time(iter->second->filepath);
if (last_write_time != iter->second->pre_modify_msec)
{
LuaUtils::make_bytecode(iter->second->filepath, iter->second->value);
iter->second->pre_modify_msec = last_write_time;
}
}
m_bytescodes.unlock();
system::sleep_msec(sConfig->scripts.auto_update_sec);
return true;
}
#endif

View File

@@ -1,45 +0,0 @@
#pragma once
#include "core/define.h"
#if ENABLE_BYTECODE == 1
#include "sol/sol.hpp"
#include "base/error.h"
#include "base/singleton.hpp"
#include "util/thread.h"
#include "util/queue.hpp"
#include "util/map.hpp"
#include "core/structs.h"
/// <summary>
/// 字节码管理器
/// </summary>
class bytecode_manager:public ylib::error_base,private ylib::ithread {
public:
bytecode_manager();
~bytecode_manager();
/// <summary>
/// 创建字节码
/// </summary>
/// <param name="name"></param>
/// <param name="filepath"></param>
/// <param name="auto_update"></param>
/// <returns></returns>
bool create(const std::string& name,const std::string& filepath,bool auto_update);
/// <summary>
/// 取字节码
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
const std::string& get(const std::string& name);
std::map<std::string, std::shared_ptr<bytecode>> map();
private:
// ServiceLUA文件
ylib::map<std::string, std::shared_ptr<bytecode>> m_bytescodes;
// 通过 ithread 继承
bool run() override;
};
#endif

View File

@@ -35,14 +35,33 @@ bool config::open(const std::string& ini_filepath)
cache();
return true;
}
bool config::have_https()
std::vector<std::string> config::lua_app_files()
{
for_iter(iter, domain)
std::vector<std::string> results;
auto luas = ylib::file::traverse(sConfig->scripts.app_dir, "(.*\\.lua)");
for_iter(iter, luas)
{
if (iter->second.https)
return true;
if (iter->second == IS_DIRECTORY)
continue;
std::string path = strutils::replace(iter->first, '\\', '/');
results.push_back(path);
}
return false;
return results;
}
std::vector<std::string> config::lua_lib_files()
{
std::vector<std::string> results;
auto luas = ylib::file::traverse(sConfig->scripts.lib_dir, "(.*\\.lua)");
for_iter(iter, luas)
{
if (iter->second == IS_DIRECTORY)
continue;
std::string path = strutils::replace(iter->first, '\\', '/');
results.push_back(path);
}
return results;
}
std::vector<std::string> config::extractVariableNames(const std::string& text)
{

View File

@@ -37,11 +37,8 @@ public:
config() = default;
bool open(const std::string& ini_filepath);
/// <summary>
/// 是否含有https
/// </summary>
/// <returns></returns>
bool have_https();
std::vector<std::string> lua_app_files();
std::vector<std::string> lua_lib_files();
private:
// INI配置文件
ylib::ini m_ini;

View File

@@ -30,4 +30,3 @@
#define VarType sol::object
#define ENABLE_BYTECODE 0

View File

@@ -8,7 +8,7 @@ extern "C" {
#ifdef _WIN32
DLL_EXPORT
#endif
int fastweb(const char* config_filepath)
int fastweb_start(const char* config_filepath)
{
std::cout << "=========== [fastweb engine] ============" << std::endl;
if (sConfig->open(config_filepath) == false)
@@ -25,4 +25,12 @@ extern "C" {
LOG_SUCC("success");
return 0;
}
}
#ifdef _WIN32
DLL_EXPORT
#endif
void fastweb_close()
{
fastweb::getInstance()->stop();
}
}

View File

@@ -4,6 +4,7 @@
#define DLL_EXPORT __attribute__((visibility("default")))
#endif
extern "C" {
DLL_EXPORT int fastweb(const char* config_filepath);
DLL_EXPORT int fastweb_start(const char* config_filepath);
DLL_EXPORT void fastweb_close();
}

View File

@@ -8,8 +8,10 @@
#include "module/http/response.h"
#include "module/globalfuns.h"
#include "core/config.h"
#include "core/global.h"
#include "core/statemanager.h"
#include "core/subscribemanager.h"
#include "core/interceptormanager.h"
bool fastweb::start()
{
@@ -59,210 +61,34 @@ bool fastweb::start()
// 初始化脚本
if (initialization_script() == false)
return false;
#if ENABLE_BYTECODE == 1
// 加载服务脚本
{
auto luas = ylib::file::traverse(sConfig->scripts.app_dir, "(.*\\.lua)");
for_iter(iter, luas) {
if (iter->second == IS_DIRECTORY)
continue;
std::string path = strutils::replace(iter->first, '\\', '/');
if (service_bytecode.create(path, sConfig->scripts.app_dir + "/" + path, true) == false)
{
m_lastErrorDesc = service_bytecode.last_error();
return false;
}
}
}
// 加载拦截器脚本
for_iter(iter, sConfig->website.interceptor_scripts) {
if (interceptor_bytecode.create(iter->regex_express, iter->filepath, true) == false)
{
m_lastErrorDesc = interceptor_bytecode.last_error();
return false;
}
}
// 加入LUA服务映射
{
auto map = service_bytecode.map();
for_iter(iter, map)
{
auto state = sStateMgr->get_state();
std::string route_pattern;
network::http::method method = network::http::ALL;
try
{
auto result = state->script_file(iter->second->filepath);
if (result.valid()) {
auto router = (*state)["route"];
auto type = router.get_type();
if (router.is<sol::table>())
{
sol::optional<std::string> route_pattern_param = router[1];
sol::optional<int> method_param = router[2];
if (route_pattern_param && route_pattern_param->empty() == false)
route_pattern = *route_pattern_param;
if (method_param)
method = (network::http::method)*method_param;
}
}
}
catch (const std::exception& e)
{
LOG_ERROR(e.what());
}
if (route_pattern.empty())
route_pattern = sConfig->scripts.app_mapping_dir + iter->first;
// OutPutLog
{
std::string log;
log = "[subscribe] lua: " + iter->first + "\t pattern: " + route_pattern + "\t method: ";
switch (method)
{
case ylib::network::http::GET:
log.append("GET");
break;
case ylib::network::http::POST:
log.append("POST");
break;
case ylib::network::http::PUT:
log.append("PUT");
break;
case ylib::network::http::DEL:
log.append("DEL");
break;
case ylib::network::http::HEAD:
log.append("HEAD");
break;
case ylib::network::http::ALL:
log.append("ALL");
break;
default:
break;
}
LOG_INFO(log);
}
router->subscribe(route_pattern, method, &fastweb::subscribe_service,new std::string(iter->first));
}
}
#else
// 加入LUA服务映射
{
auto luas = ylib::file::traverse(sConfig->scripts.app_dir, "(.*\\.lua)");
for_iter(iter, luas)
{
if (iter->second == IS_DIRECTORY)
continue;
std::string path = strutils::replace(iter->first, '\\', '/');
auto state = sStateMgr->get_state();
std::string route_pattern;
network::http::method method = network::http::ALL;
try
{
auto result = state->script_file(sConfig->scripts.app_dir+"/"+ path);
if (result.valid()) {
auto router = (*state)["route"];
auto type = router.get_type();
if (router.is<sol::table>())
{
sol::optional<std::string> route_pattern_param = router[1];
sol::optional<int> method_param = router[2];
if (route_pattern_param && route_pattern_param->empty() == false)
route_pattern = *route_pattern_param;
if (method_param)
method = (network::http::method)*method_param;
}
}
}
catch (const std::exception& e)
{
LOG_ERROR(e.what());
}
if (route_pattern.empty())
route_pattern = sConfig->scripts.app_mapping_dir + path;
// OutPutLog
{
std::string log;
log = "[subscribe] lua: " +path + "\t pattern: " + route_pattern + "\t method: ";
switch (method)
{
case ylib::network::http::GET:
log.append("GET");
break;
case ylib::network::http::POST:
log.append("POST");
break;
case ylib::network::http::PUT:
log.append("PUT");
break;
case ylib::network::http::DEL:
log.append("DEL");
break;
case ylib::network::http::HEAD:
log.append("HEAD");
break;
case ylib::network::http::ALL:
log.append("ALL");
break;
default:
break;
}
LOG_INFO(log);
}
router->subscribe(route_pattern, method, &fastweb::subscribe_service, new std::string(sConfig->scripts.app_dir+"/" +path));
}
}
#endif
// 加入拦截器
for (size_t i = 0; i < sConfig->website.interceptor_scripts.size(); i++)
{
#if ENABLE_BYTECODE == 0
interceptor.emplace(sConfig->website.interceptor_scripts[i].regex_express,sConfig->website.interceptor_scripts[i].filepath);
#endif
router->interceptor()->add(sConfig->website.interceptor_scripts[i].regex_express, &fastweb::subscribe_interceptor);
}
// 加载订阅
m_subscribe.load(router);
// 加载拦截器
m_interceptor.load(router);
router->other([&](network::http::request* request, network::http::response* response) {
if (request->filepath() == "/")
{
bool find = false;
for (size_t i = 0; i < sConfig->website.default_index.size(); i++)
{
std::string filepath = sConfig->website.static_dir + request->filepath() + sConfig->website.default_index[i];
if (ylib::file::exist(filepath))
{
find = true;
response->send_file(filepath);
break;
}
}
if (find == false)
send_404(response);
return;
}
send_file(response,request->filepath());
});
return m_center->start();
}
void fastweb::stop()
{
m_subscribe.clear();
m_interceptor.clear();
if (m_center != nullptr)
{
m_center->close();
delete m_center;
}
m_center = nullptr;
global::getInstance()->clear();
if (m_state_init != nullptr)
delete m_state_init;
m_state_init = nullptr;
sStateMgr->close();
}
bool fastweb::initialization_script()
@@ -275,11 +101,11 @@ bool fastweb::initialization_script()
m_lastErrorDesc = "Initialization script not found, filepath: " + script_filepath;
return false;
}
auto state = sStateMgr->get_state();
auto state = sStateMgr->get();
try
{
state->set_function("global_regist", module::global_regist);
auto result = state->script_file(script_filepath);
state->state->set_function("global_regist", module::global_regist);
auto result = state->state->script_file(script_filepath);
if (!result.valid()) {
sol::error err = result;
throw ylib::exception(err.what());
@@ -295,134 +121,6 @@ bool fastweb::initialization_script()
}
// 不可DELETE否则注册的全局变量会被自动销毁
//delete state;
m_state_init = state;
return m_lastErrorDesc == "";
}
void fastweb::subscribe_service(network::http::request* request, network::http::response* response,void *extra)
{
std::string lua_name = *(std::string*)extra;
// 文件原路径(非绝对路径)
//std::string lua_name = strutils::right(request->filepath(), request->filepath().length() - sConfig->scripts.app_mapping_dir.length());
auto lua = sStateMgr->get_state();
std::string exception_string;
try
{
#if ENABLE_BYTECODE == 1
auto bytecode = sFastWeb->service_bytecode.get(lua_name);
if (bytecode.empty())
throw ylib::exception("Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, "+lua_name);
auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
#else
auto lbResult = lua->load_file(lua_name);
#endif
if (lbResult.valid() == false)
{
sol::error err = lbResult;
throw ylib::exception("Failed to load bytecode, " + std::string(err.what()));
}
module::request m_request(request);
module::response m_response(response);
lbResult();
(*lua)["response"] = &m_response;
(*lua)["request"] = &m_request;
auto result = (*lua)["access"]();
if (!result.valid()) {
sol::error err = result;
throw ylib::exception(err.what());
}
}
catch (const std::exception& e)
{
exception_string = e.what();
if(sConfig->website.debug)
LOG_ERROR("[subscribe_service]["+ request->filepath() + "]: "+e.what());
}
lua->collect_garbage();
sStateMgr->push_state(lua);
if (exception_string.empty() == false)
throw ylib::exception(exception_string);
}
bool fastweb::subscribe_interceptor(network::http::reqpack* reqpack, const std::string& express_string)
{
bool ok_continue = false;
auto lua = sStateMgr->get_state();
std::string exception_string;
try
{
#if ENABLE_BYTECODE == 1
const std::string& bytecode = sFastWeb->interceptor_bytecode.get(express_string);
if (bytecode.empty())
throw ylib::exception("[interceptor] Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, " + express_string);
auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
#else
auto lbResult = lua->load_file(sFastWeb->interceptor[express_string]);
#endif
if (lbResult.valid() == false)
{
sol::error err = lbResult;
throw ylib::exception("[interceptor] Failed to load bytecode, " + std::string(err.what()));
}
module::request m_request(reqpack->request());
module::response m_response(reqpack->response());
lbResult();
(*lua)["response"] = m_response;
(*lua)["request"] = m_request;
auto result = (*lua)["access"]();
if (!result.valid()) {
sol::error err = result;
throw ylib::exception(err.what());
}
ok_continue = result.get<bool>();
}
catch (const std::exception& e)
{
exception_string = e.what();
if (sConfig->website.debug)
LOG_ERROR("[subscribe_interceptor][" + reqpack->request()->filepath() + "]: " + e.what());
}
sStateMgr->push_state(lua);
if (exception_string.empty() == false)
throw ylib::exception(exception_string);
return ok_continue;
}
void fastweb::send_file(network::http::response* response, std::string filepath)
{
filepath = sConfig->website.static_dir + filepath;
if (ylib::file::exist(filepath))
{
response->send_file(filepath);
}
else
{
send_404(response);
}
}
void fastweb::send_404(network::http::response* response)
{
std::string default_404 = sConfig->website.static_dir + "\\" + sConfig->website.default_404;
if (sConfig->website.default_404 == "" || ylib::file::exist(default_404) == false)
{
response->send((std::string)"404 Not Found",404,"Not Found");
}
else
{
response->send_file(default_404,-1, 404, "Not Found");
}
}
}

View File

@@ -3,51 +3,26 @@
#include "base/error.h"
#include "base/singleton.hpp"
#include "net/http_center.h"
#include "net/http_response.h"
#include "net/http_request.h"
#include "core/bytecodemanager.h"
#include "core/subscribemanager.h"
#include "core/interceptormanager.h"
class fastweb:public ylib::error_base,public ylib::singleton<fastweb> {
public:
fastweb() = default;
bool start();
void stop();
/// <summary>
/// 发送文件
/// </summary>
/// <param name="response"></param>
/// <param name="filepath"></param>
void send_file(network::http::response* response, std::string filepath);
/// <summary>
/// 发送404
/// </summary>
/// <param name="response"></param>
void send_404(network::http::response* response);
private:
/// <summary>
/// 初始化执行脚本
/// </summary>
/// <returns></returns>
bool initialization_script();
/// <summary>
/// 服务回调
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
static void subscribe_service(network::http::request* request, network::http::response* response, void* extra);
/// <summary>
/// 拦截器回调
/// </summary>
static bool subscribe_interceptor(network::http::reqpack* reqpack,const std::string& express_string);
private:
// 初始化脚本虚拟机
luastate* m_state_init = nullptr;
// 网站服务核心
network::http::center *m_center = nullptr;
public:
#if ENABLE_BYTECODE == 1
// 服务字节码
bytecode_manager service_bytecode;
// 拦截器字节码
bytecode_manager interceptor_bytecode;
#else
std::map<std::string, std::string> interceptor;
#endif
// 订阅管理器
subscribe_manager m_subscribe;
// 拦截器管理器
interceptor_manager m_interceptor;
};

View File

@@ -43,3 +43,18 @@ void global::set(const std::string& name, VarType value)
{
m_values.set(name, value, true);
}
void global::clear()
{
m_values.clear();
m_value_ptr.clear();
//m_value_ptr.lock();
//for_iter(iter, (*m_value_ptr.parent()))
//{
// auto im = static_cast<module::imodule*>(iter->second);
// im->delete_global();
//}
//m_value_ptr.unlock();
//m_value_ptr.clear();
}

View File

@@ -16,6 +16,7 @@ public:
VarType get(const std::string& name, sol::this_state s);
void set(const std::string& name,VarType value);
void clear();
private:
ylib::map<std::string, void*> m_value_ptr;

View File

@@ -0,0 +1,75 @@
#include "core/interceptormanager.h"
#include "core/config.h"
#include "core/statemanager.h"
#include "module/http/request.h"
#include "module/http/response.h"
#include "net/http_interceptor.h"
std::map<std::string, std::string> interceptor_manager::interceptor = std::map<std::string,std::string>();
interceptor_manager::interceptor_manager()
{
}
interceptor_manager::~interceptor_manager()
{
clear();
}
void interceptor_manager::load(network::http::router* router)
{
clear();
m_router = router;
for (size_t i = 0; i < sConfig->website.interceptor_scripts.size(); i++)
{
interceptor_manager::interceptor.emplace(sConfig->website.interceptor_scripts[i].regex_express, sConfig->website.interceptor_scripts[i].filepath);
router->interceptor()->add(sConfig->website.interceptor_scripts[i].regex_express, &interceptor_manager::callback);
}
}
void interceptor_manager::clear()
{
if(m_router != nullptr)
m_router->interceptor()->clear();
interceptor_manager::interceptor.clear();
m_router = nullptr;
}
bool interceptor_manager::callback(network::http::reqpack* reqpack, const std::string& express_string)
{
bool ok_continue = false;
auto lua = sStateMgr->get();
std::string exception_string;
try
{
auto lbResult = lua->state->load_file(interceptor_manager::interceptor[express_string]);
if (lbResult.valid() == false)
{
sol::error err = lbResult;
throw ylib::exception("[interceptor] Failed to load bytecode, " + std::string(err.what()));
}
module::request m_request(reqpack->request());
module::response m_response(reqpack->response());
lbResult();
(*lua->state)["response"] = m_response;
(*lua->state)["request"] = m_request;
auto result = (*lua->state)["access"]();
if (!result.valid()) {
sol::error err = result;
throw ylib::exception(err.what());
}
ok_continue = result.get<bool>();
}
catch (const std::exception& e)
{
exception_string = e.what();
if (sConfig->website.debug)
LOG_ERROR("[subscribe_interceptor][" + reqpack->request()->filepath() + "]: " + e.what());
}
lua->state->collect_garbage();
sStateMgr->push(lua);
if (exception_string.empty() == false)
throw ylib::exception(exception_string);
return ok_continue;
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include "base/singleton.hpp"
#include "core/structs.h"
#include "net/http_reqpack.h"
#include "net/http_request.h"
#include "net/http_response.h"
#include "net/http_router.h"
/// <summary>
/// 拦截器管理器
/// </summary>
class interceptor_manager{
public:
interceptor_manager();
~interceptor_manager();
void load(network::http::router* router);
void clear();
private:
/// <summary>
/// 服务回调
/// </summary>
/// <param name="reqpack"></param>
/// <param name="express_string"></param>
static bool callback(network::http::reqpack* reqpack, const std::string& express_string);
private:
network::http::router* m_router = nullptr;
public:
static std::map<std::string, std::string> interceptor;
};

View File

@@ -0,0 +1,45 @@
#include "lualibdetecter.h"
#include "core/config.h"
#include "util/file.h"
lualib_detecter::lualib_detecter()
{
}
lualib_detecter::~lualib_detecter()
{
}
bool lualib_detecter::changed()
{
auto lib_files = sConfig->lua_lib_files();
bool changed = false;
if (lib_files.size() == m_files.size())
{
for (size_t i = 0; i < lib_files.size(); i++)
{
auto iter = m_files.find(lib_files[i]);
if (iter == m_files.end())
{
changed = true;
break;
}
if (ylib::file::last_write_time(sConfig->scripts.lib_dir+"/"+ lib_files[i]) != iter->second)
{
changed = true;
break;
}
}
}
else
changed = true;
if (changed == false)
return false;
m_files.clear();
for (size_t i = 0; i < lib_files.size(); i++)
m_files.emplace(lib_files[i], ylib::file::last_write_time(sConfig->scripts.lib_dir + "/" + lib_files[i]));
return true;
}

28
src/core/lualibdetecter.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "sol/sol.hpp"
#include "base/error.h"
#include "base/singleton.hpp"
#include "util/thread.h"
#include "util/queue.hpp"
#include "util/map.hpp"
#include "core/structs.h"
/// <summary>
/// LUALIB库变动检测
/// </summary>
class lualib_detecter {
public:
lualib_detecter();
~lualib_detecter();
/// <summary>
/// 是否变化
/// </summary>
/// <returns></returns>
bool changed();
private:
std::map<std::string, timestamp> m_files;
};

View File

@@ -26,28 +26,24 @@
#define LOOP_STATE_USE 1
bool state_manager::start()
{
#if LOOP_STATE_USE == 0
close();
::ithread::start();
#endif
return true;
}
void state_manager::close()
{
#if LOOP_STATE_USE == 0
::ithread::stop();
::ithread::wait();
#endif
sol::state* state = nullptr;
luastate* state = nullptr;
while (m_states.pop(state))
delete state;
}
sol::state* state_manager::create_state()
luastate* state_manager::create()
{
sol::state* lua = new sol::state();
lua->open_libraries(
luastate* lua = new luastate();
lua->flag = m_flag;
lua->state->open_libraries(
sol::lib::base,
sol::lib::package,
sol::lib::math,
@@ -64,82 +60,62 @@ sol::state* state_manager::create_state()
);
{
// 获取当前的package.path添加新的搜索路径
std::string current_path = (*lua)["package"]["path"]; // 获取当前的路径
std::string current_path = (*lua->state)["package"]["path"]; // 获取当前的路径
current_path += ";"+ sConfig->scripts.lib_dir +"/?.lua"; // 添加新的路径
(*lua)["package"]["path"] = current_path; // 设置修改后的路径
(*lua->state)["package"]["path"] = current_path; // 设置修改后的路径
}
module::request::regist(*lua);
module::response::regist(*lua);
module::session::regist(*lua);
module::httpclient::regist(*lua);
module::mysql_regist(*lua);
module::request::regist(*lua->state);
module::response::regist(*lua->state);
module::session::regist(*lua->state);
module::httpclient::regist(*lua->state);
module::mysql_regist(*lua->state);
#ifdef _WIN32
module::mssql::regist(*lua);
module::mssql::regist(*lua->state);
#endif
module::regist_globalfuns(*lua);
module::local_storage::regist(lua);
module::mutex::regist(lua);
module::auto_lock::regist(lua);
module::codec::regist(lua);
module::time::regist(lua);
module::file::regist(lua);
module::sys::regist(lua);
module::regist_globalfuns(*lua->state);
module::local_storage::regist(lua->state);
module::mutex::regist(lua->state);
module::auto_lock::regist(lua->state);
module::codec::regist(lua->state);
module::time::regist(lua->state);
module::file::regist(lua->state);
module::sys::regist(lua->state);
global::getInstance()->regist_lua(lua);
global::getInstance()->regist_lua(lua->state);
return lua;
}
sol::state* state_manager::get_state()
luastate* state_manager::get()
{
sol::state* result = nullptr;
if (m_states.pop(result))
return result;
return create_state();
luastate* result = nullptr;
while (m_states.pop(result))
{
if (result->flag != m_flag)
delete result;
else
return result;
}
return create();
}
void state_manager::push_state(sol::state* state)
void state_manager::push(luastate* state)
{
if (state == nullptr)
return;
#if LOOP_STATE_USE == 1
if (state->flag != m_flag)
{
delete state;
return;
}
m_states.push(state);
#else
m_delete_states.push(state);
#endif
}
bool state_manager::run()
{
#if LOOP_STATE_USE == 0
auto now_msec = time::now_msec();
// 虚拟机缓冲保证
if(sConfig->scripts.lua_cache_size > m_states.size())
{
std::vector<sol::state*> bhvalues;
auto bhcount = sConfig->scripts.lua_cache_size - m_states.size();
if (bhcount > 0 && bhcount <= sConfig->scripts.lua_cache_size)
{
for (size_t i = 0; i < bhcount; i++)
bhvalues.push_back(create_state());
}
for(size_t i=0;i< bhvalues.size();i++)
m_states.push(bhvalues[i]);
}
// 释放虚拟机
{
sol::state* state = nullptr;
while (m_delete_states.pop(state))
delete state;
}
system::sleep_msec(100);
if (m_lib_detecter.changed())
m_flag++;
system::sleep_msec(3000);
return true;
#else
return false;
#endif
}

View File

@@ -10,6 +10,7 @@
#include "util/map.hpp"
#include "core/structs.h"
#include "core/lualibdetecter.h"
/// <summary>
/// LUA状态管理器
@@ -27,21 +28,29 @@ public:
/// 取虚拟机
/// </summary>
/// <returns></returns>
sol::state* get_state();
luastate* get();
/// <summary>
/// 归还虚拟机
/// </summary>
/// <param name="state"></param>
void push_state(sol::state* state);
void push(luastate* state);
private:
// 虚拟机
ylib::queue<sol::state*> m_states;
ylib::queue<sol::state*> m_delete_states;
ylib::queue<luastate*> m_states;
// 版本FLAT
size_t m_flag = 0;
// LIB变化检测
lualib_detecter m_lib_detecter;
private:
// 通过 ithread 继承
bool run() override;
/// <summary>
/// 创建虚拟机
/// </summary>
/// <returns></returns>
luastate* create();
sol::state* create_state();
};

View File

@@ -1,5 +1,6 @@
#pragma once
#include "base/define.h"
#include "sol/sol.hpp"
/// <summary>
/// LUA字节码
/// </summary>
@@ -12,4 +13,19 @@ struct bytecode {
std::string value;
// 自动更新
bool auto_update = false;
};
/// <summary>
/// 包装虚拟机
/// </summary>
struct luastate {
luastate()
{
state = new sol::state();
}
~luastate()
{
delete state;
}
sol::state* state = nullptr;
size_t flag = 0;
};

View File

@@ -0,0 +1,194 @@
#include "subscribemanager.h"
#include "core/config.h"
#include "core/statemanager.h"
#include "module/http/request.h"
#include "module/http/response.h"
subscribe_manager::subscribe_manager()
{
}
subscribe_manager::~subscribe_manager()
{
clear();
}
void subscribe_manager::load(network::http::router* router)
{
clear();
m_router = router;
// 初始化全部订阅
auto files = sConfig->lua_app_files();
for (size_t i = 0; i < files.size(); i++)
{
init_subscribe(files[i]);
}
// 其它绑定
router->other(&subscribe_manager::other);
}
void subscribe_manager::clear()
{
if (m_router != nullptr)
{
m_router->clear_subscribe();
}
for (size_t i = 0; i < m_subextra.size(); i++)
delete m_subextra[i];
m_subextra.clear();
m_router = nullptr;
}
void subscribe_manager::init_subscribe(const std::string& filepath)
{
auto state = sStateMgr->get();
std::string route_pattern;
network::http::method method = network::http::ALL;
try
{
auto result = state->state->script_file(sConfig->scripts.app_dir + "/" + filepath);
if (result.valid()) {
auto router = (*state->state)["route"];
auto type = router.get_type();
if (router.is<sol::table>())
{
sol::optional<std::string> route_pattern_param = router[1];
sol::optional<int> method_param = router[2];
if (route_pattern_param && route_pattern_param->empty() == false)
route_pattern = *route_pattern_param;
if (method_param)
method = (network::http::method)*method_param;
}
}
}
catch (const std::exception& e)
{
LOG_ERROR(e.what());
}
sStateMgr->push(state);
if (route_pattern.empty())
route_pattern = sConfig->scripts.app_mapping_dir + filepath;
// OutPutLog
{
std::string log;
log = "[subscribe] lua: " + filepath + "\t pattern: " + route_pattern + "\t method: ";
switch (method)
{
case ylib::network::http::GET:
log.append("GET");
break;
case ylib::network::http::POST:
log.append("POST");
break;
case ylib::network::http::PUT:
log.append("PUT");
break;
case ylib::network::http::DEL:
log.append("DEL");
break;
case ylib::network::http::HEAD:
log.append("HEAD");
break;
case ylib::network::http::ALL:
log.append("ALL");
break;
default:
break;
}
LOG_INFO(log);
}
std::string* extra = new std::string(sConfig->scripts.app_dir + "/" + filepath);
m_subextra.push_back(extra);
m_router->subscribe(route_pattern, method, &subscribe_manager::callback, extra);
}
void subscribe_manager::callback(network::http::request* request, network::http::response* response, void* extra)
{
std::string lua_filepath = *(std::string*)extra;
auto lua = sStateMgr->get();
std::string exception_string;
try
{
auto lbResult = lua->state->load_file(lua_filepath);
if (lbResult.valid() == false)
{
sol::error err = lbResult;
throw ylib::exception("Failed to load bytecode, " + std::string(err.what()));
}
module::request m_request(request);
module::response m_response(response);
lbResult();
(*lua->state)["response"] = &m_response;
(*lua->state)["request"] = &m_request;
auto result = (*lua->state)["access"]();
if (!result.valid()) {
sol::error err = result;
throw ylib::exception(err.what());
}
}
catch (const std::exception& e)
{
exception_string = e.what();
if (sConfig->website.debug)
LOG_ERROR("[subscribe_service][" + request->filepath() + "]: " + e.what());
}
// 清理
lua->state->collect_garbage();
sStateMgr->push(lua);
if (exception_string.empty() == false)
throw ylib::exception(exception_string);
}
void subscribe_manager::other(network::http::request* request, network::http::response* response)
{
auto send_404 = [](network::http::response* response) {
std::string default_404 = sConfig->website.static_dir + "\\" + sConfig->website.default_404;
if (sConfig->website.default_404 == "" || ylib::file::exist(default_404) == false)
{
response->send((std::string)"404 Not Found", 404, "Not Found");
}
else
{
response->send_file(default_404, -1, 404, "Not Found");
}
};
auto send_file = [&](network::http::response* response, std::string filepath)
{
filepath = sConfig->website.static_dir + filepath;
if (ylib::file::exist(filepath))
{
response->send_file(filepath);
}
else
{
send_404(response);
}
};
if (request->filepath() == "/")
{
bool find = false;
for (size_t i = 0; i < sConfig->website.default_index.size(); i++)
{
std::string filepath = sConfig->website.static_dir + request->filepath() + sConfig->website.default_index[i];
if (ylib::file::exist(filepath))
{
find = true;
response->send_file(filepath);
break;
}
}
if (find == false)
{
send_404(response);
}
return;
}
send_file(response, request->filepath());
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "sol/sol.hpp"
#include "base/singleton.hpp"
#include "core/structs.h"
#include "net/http_request.h"
#include "net/http_response.h"
#include "net/http_router.h"
/// <summary>
/// 订阅管理器
/// </summary>
class subscribe_manager{
public:
subscribe_manager();
~subscribe_manager();
void load(network::http::router* router);
void clear();
private:
/// <summary>
/// 初始化订阅
/// </summary>
/// <param name="filepath"></param>
/// <returns></returns>
void init_subscribe(const std::string& filepath);
private:
/// <summary>
/// 服务回调
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
static void callback(network::http::request* request, network::http::response* response, void* extra);
/// <summary>
/// 其它
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="extra"></param>
static void other(network::http::request* request, network::http::response* response);
private:
network::http::router* m_router = nullptr;
std::vector<std::string*> m_subextra;
};

View File

@@ -9,12 +9,14 @@ namespace module
/// </summary>
class imodule {
public:
virtual ~imodule() {};
/// <summary>
/// 注册全局变量
/// </summary>
/// <param name="name"></param>
/// <param name="lua"></param>
virtual void regist_global(const std::string& name,sol::state* lua) = 0;
virtual void delete_global() = 0;
/// <summary>
/// 全局变量阶段获取自身指针
/// </summary>

View File

@@ -4,6 +4,11 @@ module::local_storage::local_storage()
{
}
module::local_storage::~local_storage()
{
::ylib::local_storage::close();
}
sol::optional<std::string> module::local_storage::readex(const std::string& name)
{
std::string value;
@@ -23,7 +28,8 @@ void module::local_storage::regist(sol::state* lua)
"open", &module::local_storage::open,
"read", &module::local_storage::readex,
"write", &module::local_storage::write,
"self", &module::local_storage::self
"self", &module::local_storage::self,
"last_error", &module::local_storage::last_error
);
}

View File

@@ -9,6 +9,7 @@ namespace module
class local_storage : public ylib::local_storage,public module::imodule {
public:
local_storage();
~local_storage() override;
/// <summary>
/// 取数据
/// </summary>
@@ -20,6 +21,7 @@ namespace module
private:
// 通过 imodule 继承
virtual void regist_global(const std::string& name, sol::state* lua);
virtual void delete_global() { delete this; }
};
}

View File

@@ -10,7 +10,7 @@ namespace module
class mutex:public module::imodule {
public:
mutex();
~mutex();
~mutex() override;
/// <summary>
/// 加锁
/// </summary>
@@ -28,6 +28,7 @@ namespace module
private:
// 通过 imodule 继承
virtual void regist_global(const std::string& name, sol::state* lua);
virtual void delete_global() { delete this; }
std::mutex m_mutex;
};

View File

@@ -448,12 +448,13 @@ module::mysql::mysql()
module::mysql::~mysql()
{
close();
}
bool module::mysql::start(const std::string& ipaddress, const std::string& username, const std::string& password, const std::string& database, const std::string& charset, ushort port, int32 size)
{
close();
m_pool = new ylib::mysql::pool();
m_pool = std::make_shared<ylib::mysql::pool>();
ylib::mysql::mysql_conn_info info;
info.ipaddress = ipaddress;
info.username = username;
@@ -466,9 +467,7 @@ bool module::mysql::start(const std::string& ipaddress, const std::string& usern
void module::mysql::close()
{
if (m_pool != nullptr)
delete m_pool;
m_pool = nullptr;
}
std::shared_ptr<module::select> module::mysql::select()
@@ -496,7 +495,6 @@ void module::mysql::regist_global(const std::string& name, sol::state* lua)
lua->registry()[name] = this;
(*lua)[name] = this;
}
module::mysql_result::mysql_result(ylib::mysql::result* result):m_result(result)
{

View File

@@ -154,7 +154,7 @@ namespace module
class mysql :public imodule {
public:
mysql();
~mysql();
~mysql() override;
/// <summary>
/// 启动
/// </summary>
@@ -177,10 +177,11 @@ namespace module
std::shared_ptr<module::update> update();
std::shared_ptr<module::delete_> delete_();
private:
ylib::mysql::pool* m_pool = nullptr;
std::shared_ptr<ylib::mysql::pool> m_pool;
// 通过 imodule 继承
virtual void regist_global(const std::string& name, sol::state* lua);
virtual void delete_global() { delete this; }
};
}

View File

@@ -1,38 +1,3 @@
#include "luautils.h"
#include "core/define.h"
#include "core/statemanager.h"
bool LuaUtils::make_bytecode(const std::string& filepath, std::string& bytecode)
{
auto lua = sStateMgr->get_state();
try
{
auto result = lua->load_file(filepath);
if (!result.valid()) {
sol::error err = result;
LOG_ERROR(err.what() + std::string(", filepath: " + filepath));
return false;
}
result();
sol::function func = result;
if (!func.valid()) {
LOG_ERROR("Pre execution script failed before compilation. filepath: " + filepath);
return false;
}
sol::function dump = (*lua)["string"]["dump"];
sol::protected_function_result result2 = dump(func);
if (!result2.valid()) {
sol::error err = result2;
LOG_ERROR("failed to dump. " + std::string(err.what()) + ", filepath: " + filepath);
return false;
}
LOG_INFO("update lua script, filepath: " + filepath);
bytecode = result2;
return true;
}
catch (const std::exception& e)
{
LOG_INFO(std::string(e.what()) + ", filepath: " + filepath);
}
sStateMgr->push_state(lua);
return false;
}
#include "core/statemanager.h"

View File

@@ -2,11 +2,5 @@
#include <string>
namespace LuaUtils {
/// <summary>
/// 创建服务字节码
/// </summary>
/// <param name="filepath"></param>
/// <param name="bytecode"></param>
/// <returns></returns>
bool make_bytecode(const std::string& filepath,std::string& bytecode);
}

View File

@@ -5,10 +5,22 @@
int main()
{
std::string config_filepath = std::filesystem::current_path().string()+"/config.ini";
if (fastweb(config_filepath.c_str()) != 0)
if (fastweb_start(config_filepath.c_str()) != 0)
return -1;
while (true)
std::cin.get();
{
std::string input;
std::cin >> input;
if (input == "quit" || input == "exit")
{
fastweb_close();
std::cout << "closed";
break;
}
else
std::cout << "Enter \"quit\" or \"exit\" to exit the application" << std::endl;
}
return 0;
}