support dynamic libs compiling and loading
This commit is contained in:
parent
95b83206fb
commit
cc35b08580
|
@ -103,9 +103,20 @@ static void parseLine(std::ofstream &oSrcFile,std::string& line,const std::strin
|
|||
|
||||
void create_view::handleCommand(std::vector<std::string> ¶meters)
|
||||
{
|
||||
for(auto file:parameters)
|
||||
for(auto iter=parameters.begin();iter!=parameters.end();iter++)
|
||||
{
|
||||
if(file[0]=='-')
|
||||
auto file=*iter;
|
||||
if(file=="-o"||file=="--output")
|
||||
{
|
||||
iter=parameters.erase(iter);
|
||||
if(iter!=parameters.end())
|
||||
{
|
||||
_outputPath=*iter;
|
||||
iter=parameters.erase(iter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(file[0]=='-')
|
||||
{
|
||||
std::cout<<ARGS_ERROR_STR<<std::endl;
|
||||
return;
|
||||
|
@ -137,8 +148,8 @@ int create_view::createViewFile(const std::string &script_filename)
|
|||
className=className.substr(pos+1);
|
||||
}
|
||||
std::cout<<"className="<<className<<std::endl;
|
||||
std::string headFileName=className+".h";
|
||||
std::string sourceFilename=className+".cc";
|
||||
std::string headFileName=_outputPath+"/"+className+".h";
|
||||
std::string sourceFilename=_outputPath+"/"+className+".cc";
|
||||
std::ofstream oHeadFile(headFileName.c_str(),std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(),std::ofstream::out);
|
||||
if(!oHeadFile||!oSourceFile)
|
||||
|
@ -176,7 +187,12 @@ void create_view::newViewSourceFile(std::ofstream &file,const std::string &class
|
|||
file <<"#include <map>\n";
|
||||
file <<"#include <vector>\n";
|
||||
file <<"#include <set>\n";
|
||||
file <<"#include <iostream>\n";
|
||||
file <<"using namespace std;\n";
|
||||
// file <<"void __attribute__((constructor)) startup()\n";
|
||||
// file <<"{std::cout<<\"dynamic lib start to load!\"<<std::endl;}\n";
|
||||
// file <<"void __attribute__((destructor)) shutdown()\n";
|
||||
// file <<"{std::cout<<\"dynamic lib start to unload!\"<<std::endl;}\n";
|
||||
std::string buffer;
|
||||
char line[8192];
|
||||
int import_flag=0;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace drogon_ctl
|
|||
virtual std::string script() override {return "create view class files";}
|
||||
|
||||
protected:
|
||||
|
||||
std::string _outputPath=".";
|
||||
void createViewFiles(std::vector<std::string> &cspFileNames);
|
||||
int createViewFile(const std::string &script_filename);
|
||||
void newViewHeaderFile(std::ofstream &file,const std::string &className);
|
||||
|
|
|
@ -9,7 +9,7 @@ void ApiTest::get(const HttpRequest& req,const std::function<void (HttpResponse
|
|||
para["p1"]=std::to_string(p1);
|
||||
para["p2"]=p2;
|
||||
data.insert("parameters",para);
|
||||
auto res=HttpResponse::newHttpViewResponse("ListParaView",data);
|
||||
auto res=HttpResponse::newHttpViewResponse("DynamicListParaView.csp",data);
|
||||
callback(*res);
|
||||
}
|
||||
void ApiTest::your_method_name(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback,double p1,int p2) const
|
||||
|
|
|
@ -113,7 +113,7 @@ int main()
|
|||
drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle4/{4}/{3}/{1}",func);
|
||||
|
||||
//start app framework
|
||||
//drogon::HttpAppFramework::instance().enableDynamicSharedLibLoading();
|
||||
drogon::HttpAppFramework::instance().enableDynamicSharedLibLoading({"/tmp/views"});
|
||||
drogon::HttpAppFramework::instance().run();
|
||||
|
||||
}
|
||||
|
|
|
@ -79,6 +79,6 @@ namespace drogon
|
|||
virtual const std::string & getDocumentRoot() const =0;
|
||||
virtual void setDocumentRoot(const std::string &rootPath)=0;
|
||||
virtual void setFileTypes(const std::vector<std::string> &types)=0;
|
||||
virtual void enableDynamicSharedLibLoading(const std::string &viewPth="views")=0;
|
||||
virtual void enableDynamicSharedLibLoading(const std::vector<std::string> &libPaths)=0;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace drogon
|
|||
virtual const std::string & getDocumentRoot() const override {return _rootPath;}
|
||||
virtual void setDocumentRoot(const std::string &rootPath) override {_rootPath=rootPath;}
|
||||
virtual void setFileTypes(const std::vector<std::string> &types) override;
|
||||
virtual void enableDynamicSharedLibLoading(const std::string &viewPth="views") override;
|
||||
virtual void enableDynamicSharedLibLoading(const std::vector<std::string> &libPaths) override;
|
||||
~HttpAppFrameworkImpl(){}
|
||||
private:
|
||||
std::vector<std::pair<std::string,uint16_t>> _listeners;
|
||||
|
@ -111,7 +111,7 @@ namespace drogon
|
|||
|
||||
|
||||
size_t _threadNum=1;
|
||||
std::string _viewFilePath;
|
||||
std::vector<std::string> _libFilePaths;
|
||||
|
||||
std::unique_ptr<SharedLibManager>_sharedLibManagerPtr;
|
||||
|
||||
|
@ -121,13 +121,21 @@ namespace drogon
|
|||
|
||||
using namespace drogon;
|
||||
using namespace std::placeholders;
|
||||
void HttpAppFrameworkImpl::enableDynamicSharedLibLoading(const std::string &viewPath)
|
||||
void HttpAppFrameworkImpl::enableDynamicSharedLibLoading(const std::vector<std::string> &libPaths)
|
||||
{
|
||||
assert(!_running);
|
||||
if(_viewFilePath.empty())
|
||||
if(_libFilePaths.empty())
|
||||
{
|
||||
_viewFilePath=_rootPath+"/"+viewPath;
|
||||
_sharedLibManagerPtr=std::unique_ptr<SharedLibManager>(new SharedLibManager(&_loop,_viewFilePath));
|
||||
for(auto libpath:libPaths)
|
||||
{
|
||||
if(libpath[0]!='/')
|
||||
{
|
||||
_libFilePaths.push_back(_rootPath+"/"+libpath);
|
||||
} else
|
||||
_libFilePaths.push_back(libpath);
|
||||
}
|
||||
|
||||
_sharedLibManagerPtr=std::unique_ptr<SharedLibManager>(new SharedLibManager(&_loop,_libFilePaths));
|
||||
}
|
||||
}
|
||||
void HttpAppFrameworkImpl::setFileTypes(const std::vector<std::string> &types)
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
|
||||
#include "SharedLibManager.h"
|
||||
#include <trantor/utils/Logger.h>
|
||||
#include <drogon/config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
void *dlopen(const char *filename, int flag);
|
||||
static void forEachFileIn(const std::string &path,const std::function<void (const std::string &filename)> &cb)
|
||||
#include <fstream>
|
||||
static void forEachFileIn(const std::string &path,const std::function<void (const std::string &,const struct stat &)> &cb)
|
||||
{
|
||||
DIR* dp;
|
||||
struct dirent* dirp;
|
||||
|
@ -55,16 +55,16 @@ static void forEachFileIn(const std::string &path,const std::function<void (cons
|
|||
/* if dirent is a directory, continue */
|
||||
if(S_ISDIR(st.st_mode))
|
||||
continue;
|
||||
cb(fullname);
|
||||
cb(fullname,st);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace drogon;
|
||||
SharedLibManager::SharedLibManager(trantor::EventLoop *loop,const std::string viewPath):
|
||||
SharedLibManager::SharedLibManager(trantor::EventLoop *loop,const std::vector<std::string> & libPaths):
|
||||
_loop(loop),
|
||||
_viewPath(viewPath)
|
||||
_libPaths(libPaths)
|
||||
{
|
||||
_loop->runEvery(5.0,[=](){
|
||||
managerLibs();
|
||||
|
@ -72,30 +72,89 @@ _viewPath(viewPath)
|
|||
}
|
||||
void SharedLibManager::managerLibs()
|
||||
{
|
||||
LOG_DEBUG<<"manager .so libs in path "<<_viewPath;
|
||||
forEachFileIn(_viewPath,[=](const std::string &filename){
|
||||
LOG_DEBUG<<filename;
|
||||
auto pos=filename.rfind(".");
|
||||
if(pos!=std::string::npos)
|
||||
{
|
||||
auto exName=filename.substr(pos+1);
|
||||
if(exName=="so")
|
||||
for(auto libPath:_libPaths)
|
||||
{
|
||||
forEachFileIn(libPath,[=](const std::string &filename,const struct stat &st){
|
||||
//LOG_DEBUG<<filename;
|
||||
auto pos=filename.rfind(".");
|
||||
if(pos!=std::string::npos)
|
||||
{
|
||||
//loading so file;
|
||||
if(_dlMap.find(filename)!=_dlMap.end())
|
||||
return;
|
||||
auto Handle=dlopen(filename.c_str(),RTLD_NOW);
|
||||
if(!Handle)
|
||||
auto exName=filename.substr(pos+1);
|
||||
if(exName=="csp")
|
||||
{
|
||||
LOG_ERROR<<"load "<<filename<<" error!";
|
||||
LOG_ERROR<<dlerror();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG<<"Successfully loaded library file "<<filename;
|
||||
_dlMap[filename]=Handle;
|
||||
//compile
|
||||
auto lockFile=filename+".lock";
|
||||
std::ifstream fin(lockFile);
|
||||
if (fin) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(_dlMap.find(filename)!=_dlMap.end())
|
||||
{
|
||||
if(st.st_mtim.tv_sec>_dlMap[filename].mTime.tv_sec)
|
||||
{
|
||||
LOG_DEBUG<<"new csp file:"<<filename;
|
||||
if(dlclose(_dlMap[filename].handle)==0)
|
||||
{
|
||||
LOG_DEBUG<<"close dynamic lib successfully:"<<_dlMap[filename].handle;
|
||||
}
|
||||
else
|
||||
LOG_DEBUG<<dlerror();
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::ofstream fout(lockFile);
|
||||
}
|
||||
std::string cmd="drogon_ctl create view ";
|
||||
cmd.append(filename).append(" -o ").append(libPath);
|
||||
LOG_DEBUG<<cmd;
|
||||
system(cmd.c_str());
|
||||
auto srcFile=filename.substr(0,pos);
|
||||
srcFile.append(".cc");
|
||||
DLStat dlStat;
|
||||
dlStat.handle=loadLibs(srcFile);
|
||||
dlStat.mTime=st.st_mtim;
|
||||
_dlMap[filename]=dlStat;
|
||||
_loop->runAfter(3.5,[=](){
|
||||
LOG_DEBUG<<"remove file "<<lockFile;
|
||||
if(unlink(lockFile.c_str())==-1)
|
||||
perror("");
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
void* SharedLibManager::loadLibs(const std::string &sourceFile) {
|
||||
LOG_DEBUG<<"src:"<<sourceFile;
|
||||
std::string cmd="g++ ";
|
||||
cmd.append(sourceFile).append(" ").append(definitions)
|
||||
.append(compileFlags).append(includeDirs).append(" -shared -fPIC --no-gnu-unique -o ");
|
||||
auto pos=sourceFile.rfind(".");
|
||||
auto soFile=sourceFile.substr(0,pos);
|
||||
soFile.append(".so");
|
||||
cmd.append(soFile);
|
||||
void *Handle = nullptr;
|
||||
if(system(cmd.c_str())==0)
|
||||
{
|
||||
LOG_DEBUG<<"Compiled successfully";
|
||||
//loading so file;
|
||||
Handle=dlopen(soFile.c_str(),RTLD_LAZY);
|
||||
if(!Handle)
|
||||
{
|
||||
LOG_ERROR<<"load "<<soFile<<" error!";
|
||||
LOG_ERROR<<dlerror();
|
||||
}
|
||||
});
|
||||
else
|
||||
{
|
||||
LOG_DEBUG<<"Successfully loaded library file "<<soFile;
|
||||
}
|
||||
}
|
||||
return Handle;
|
||||
}
|
|
@ -16,16 +16,22 @@
|
|||
#include <trantor/utils/NonCopyable.h>
|
||||
#include <trantor/net/EventLoop.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
namespace drogon{
|
||||
class SharedLibManager:public trantor::NonCopyable
|
||||
{
|
||||
public:
|
||||
SharedLibManager(trantor::EventLoop *loop,const std::string viewPath);
|
||||
SharedLibManager(trantor::EventLoop *loop,const std::vector<std::string> & libPaths);
|
||||
~SharedLibManager(){}
|
||||
private:
|
||||
void managerLibs();
|
||||
trantor::EventLoop *_loop;
|
||||
std::string _viewPath;
|
||||
std::unordered_map<std::string,void *> _dlMap;
|
||||
std::vector<std::string> _libPaths;
|
||||
struct DLStat{
|
||||
void * handle;
|
||||
struct timespec mTime;
|
||||
};
|
||||
std::unordered_map<std::string,DLStat> _dlMap;
|
||||
void* loadLibs(const std::string &sourceFile);
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue