370 lines
12 KiB
C++
370 lines
12 KiB
C++
/*
|
||
* ModuleManager.cpp
|
||
*
|
||
* Created on: 2011-8-29
|
||
* Author: dev
|
||
*/
|
||
#include <PAIConst.h>
|
||
#include "ModuleManager.h"
|
||
#include "Module.h"
|
||
#include "ParameterItem.h"
|
||
#include "ModuleMetaData.h"
|
||
#include "ModuleParameter.h"
|
||
// #include "json/json.h"
|
||
// #include "Configure.h"
|
||
|
||
#include <algorithm>
|
||
#include <cassert>
|
||
#include <vector>
|
||
#include <string>
|
||
#include <set>
|
||
#include <fstream>
|
||
#include "Turtle.h"
|
||
#include <iostream>
|
||
#include <stddef.h>
|
||
#include <sys/types.h>
|
||
// #include <dirent.h>
|
||
#include <map>
|
||
#include <stdlib.h>
|
||
#include <cstring>
|
||
// #include "Log.h"
|
||
using namespace std;
|
||
using namespace pai::turtle;
|
||
|
||
namespace pai {
|
||
namespace module {
|
||
static const char * MODULE_PATH = "module";
|
||
|
||
//需要使用的字符串常量
|
||
const std::string DERECTORY_SPLIT = "/"; //文件夹分割符
|
||
|
||
const std::string JSON_METADATA_FILE_SUFFIX = "MetaData.json"; //JSON文件后缀名
|
||
|
||
const std::string KEY_JSON_MODULE_NAME = "ModuleName"; //JSON文件里 文件名字段 KEY ModuleName
|
||
const std::string KEY_JSON_META_DATA = "MetaData"; //JSON文件里 MetaData字段 KEY MetaData
|
||
const std::string KEY_JSON_CLASS_NAME = "ClassName"; //JSON文件里 ClassName字段 KEY ClassName
|
||
const std::string KEY_JSON_LIB_NAME = "LibName"; //JSON文件里 LibName字段 KEY LibName
|
||
#if defined(_WINDOWS)
|
||
const std::string LIB_NAME_PREFIX = ""; //动态库前缀名
|
||
const std::string LIB_NAME_SUFFIX = ".dll"; //动态库后缀名
|
||
#else
|
||
const std::string LIB_NAME_PREFIX = "lib"; //动态库前缀名
|
||
const std::string LIB_NAME_SUFFIX = ".so"; //动态库后缀名
|
||
#endif
|
||
CModuleManager::CModuleManager() :
|
||
m_moduleContainer(), m_modulePaths(), m_moduleHandles(), m_isLoadAllModules(false)
|
||
{
|
||
// pai::conf::CConfigure config;
|
||
// string loadLazy = config.GetValueByKey("MODULE_LOAD_LAZY");
|
||
// if(loadLazy == "false")
|
||
{
|
||
// pai::log::Info("using load all module mode");
|
||
LoadAllModules();
|
||
}
|
||
}
|
||
|
||
CModuleManager::~CModuleManager()
|
||
{
|
||
for (std::map<std::string, CModule*>::iterator it = m_moduleContainer.begin(); it != m_moduleContainer.end(); it++)
|
||
{
|
||
if(it->second != NULL)
|
||
{
|
||
delete it->second;
|
||
it->second = NULL;
|
||
}
|
||
}
|
||
for (std::vector<void*>::iterator it = m_moduleHandles.begin(); it != m_moduleHandles.end(); it++)
|
||
{
|
||
if(*it)
|
||
GetTurtleAPI()->CloseLibrary(*it);
|
||
}
|
||
}
|
||
|
||
CModule* CModuleManager::CreateModuleByClassNameInternal(const std::string& strModuleClassName)
|
||
{
|
||
CModule* pModule = CModuleFactory::Instance()->CreateModule(strModuleClassName);
|
||
if (pModule == NULL)
|
||
{
|
||
std::map<std::string, std::string>::const_iterator it = m_modulePaths.find(strModuleClassName);
|
||
if (it != m_modulePaths.end())
|
||
{
|
||
void* handle = GetTurtleAPI()->OpenLibrary(it->second);
|
||
if (handle == 0)
|
||
{
|
||
std::stringstream errorMsg;
|
||
errorMsg << std::string(GetTurtleAPI()->ErrorLibrary()) << std::endl;
|
||
errorMsg <<"Please check " << it->second << " first." << std::endl;
|
||
// pai::log::Error(errorMsg.str());
|
||
return NULL;;
|
||
}
|
||
m_moduleHandles.push_back(handle);
|
||
pModule = CModuleFactory::Instance()->CreateModule(strModuleClassName);
|
||
}
|
||
else
|
||
{
|
||
std::stringstream errorMsg;
|
||
errorMsg << strModuleClassName << " not registered." << std::endl;
|
||
// pai::log::Error(errorMsg.str());
|
||
return NULL;
|
||
}
|
||
}
|
||
if (NULL == pModule)
|
||
{
|
||
std::stringstream errorMsg;
|
||
errorMsg << strModuleClassName << " Cannot load " << std::endl;
|
||
// pai::log::Error(errorMsg.str());
|
||
}
|
||
return pModule;
|
||
}
|
||
|
||
CModule* CModuleManager::CreateModuleByClassName(const std::string& strModuleClassName)
|
||
{
|
||
//如果是特殊的PELibraryModule模块,则从注册的模块中clone一份
|
||
std::string PELibraryModule_="PELibraryModule_";
|
||
int x=strModuleClassName.find(PELibraryModule_);
|
||
if(x>=0) {
|
||
CModule* templateModule=GetModuleManager()->FindModule(strModuleClassName.substr(x+PELibraryModule_.length(),100));
|
||
if(templateModule)
|
||
return templateModule->Clone();
|
||
}
|
||
////////////////////////////////////////////
|
||
|
||
if(!LoadModuleByClassName(strModuleClassName))
|
||
{
|
||
// pai::log::Error("Load "+strModuleClassName + "失败,可能原因如下:1.JSON文件格式错误,2.部署的模块版本与当前系统不兼容,请联系模块的开发人员或管理员");
|
||
return NULL;
|
||
}
|
||
CModule* pModule = CreateModuleByClassNameInternal(strModuleClassName);
|
||
if(pModule==NULL){
|
||
// pai::log::Error("Create "+strModuleClassName + "失败,可能原因如下:1.JSON文件格式错误,2.部署的模块版本与当前系统不兼容,请联系模块的开发人员或管理员");
|
||
return pModule;
|
||
}
|
||
std::map<std::string, CModule*>::const_iterator it = m_moduleContainer.begin();
|
||
for (; it != m_moduleContainer.end(); ++it)
|
||
{
|
||
if (std::string(it->second->GetClassName()) == strModuleClassName)
|
||
{
|
||
//拷贝元数据和参数部分
|
||
|
||
CModuleParameter* pModuleParameter = pModule->GetModuleParameter();
|
||
*pModuleParameter = *(it->second->GetModuleParameter());
|
||
*(pModule->GetMetaData()) = *(it->second->GetMetaData());
|
||
//调用模块需要元数据的初始
|
||
pModule->Initialize();
|
||
break;
|
||
}
|
||
}
|
||
return pModule;
|
||
}
|
||
|
||
void CModuleManager::Initialize(string jsonPath)
|
||
{
|
||
//得到jsonPath目录下所有json文件名
|
||
// DIR* dp;
|
||
// struct dirent* ep;
|
||
// dp = opendir(jsonPath.c_str());
|
||
// if(dp != NULL)
|
||
// {
|
||
// while((ep = readdir(dp)))
|
||
// {
|
||
// string tmpPath = jsonPath +DERECTORY_SPLIT+ ep->d_name;
|
||
// size_t pos = tmpPath.rfind(JSON_METADATA_FILE_SUFFIX, tmpPath.length()-1); //失败返回第二个参数
|
||
// pai::log::Debug("Begin parse "+tmpPath);
|
||
// if(pos == (tmpPath.length() - JSON_METADATA_FILE_SUFFIX.length()))//是.json文件的时候注册模块
|
||
// {
|
||
// Json::Value root;
|
||
// ParseMetaData(tmpPath,root);
|
||
// LoadModule(root);
|
||
// }
|
||
// }//end of while
|
||
// closedir(dp);
|
||
// }
|
||
// else
|
||
// {
|
||
// std::stringstream errorMsg;
|
||
// errorMsg << "打开目录:"<<jsonPath<<"失败!";
|
||
// pai::log::Error(errorMsg.str());
|
||
// }
|
||
}
|
||
|
||
bool CModuleManager::LoadModuleByClassName(const std::string moduleClassName)
|
||
{
|
||
char * paiHome = (char*)PAI_HOME.c_str(); //getenv(PAI_HOME.c_str())获取环境变量PAI_HOME
|
||
std::string metaDataPartFileName;
|
||
// if the class name start with 'C', remove it.
|
||
if ('C' == moduleClassName.at(0))
|
||
metaDataPartFileName = moduleClassName.substr(1,moduleClassName.size());
|
||
else
|
||
metaDataPartFileName = moduleClassName;
|
||
string metaDataFilePath = paiHome;
|
||
metaDataFilePath.append(DERECTORY_SPLIT).append(MODULE_PATH).append(DERECTORY_SPLIT).append(metaDataPartFileName).append(JSON_METADATA_FILE_SUFFIX);
|
||
|
||
if(FindModule(metaDataPartFileName))
|
||
return true;
|
||
// Json::Value root;
|
||
// if(ParseMetaData(metaDataFilePath,root)
|
||
// && LoadModule(root))
|
||
// return true;
|
||
return false;
|
||
}
|
||
|
||
bool CModuleManager::ParseMetaData(const std::string metaDataFilePath,Json::Value& root)
|
||
{
|
||
bool result = true;
|
||
fstream src(metaDataFilePath.c_str());
|
||
if(src)
|
||
{
|
||
// Json::Reader reader;
|
||
// if(!reader.parse(src, root, false))
|
||
// {
|
||
// std::stringstream errorMsg;
|
||
// errorMsg << "json文件解析失败!文件格式不匹配,该模块部署错误,可能被误删除或者部署了错误的版本,请联系系统管理人员和该模块开发人员!请检查:" << metaDataFilePath;
|
||
// pai::log::Error(errorMsg.str());
|
||
// result = false;
|
||
// }
|
||
// src.close();//TODO If you throw exceptions before this line, you should close src before you throw exceptions
|
||
}
|
||
else
|
||
{
|
||
std::stringstream errorMsg;
|
||
errorMsg << "打开文件" << metaDataFilePath << " 失败,请联系该模块开发人员!";
|
||
// pai::log::Error(errorMsg.str());
|
||
result = false;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// bool CModuleManager::LoadModule(const Json::Value& root)
|
||
// {
|
||
// CModule* pModel = NULL;
|
||
// CModuleMetaData* pMetaData = NULL;
|
||
// Json::Value rMeta = root[KEY_JSON_META_DATA];
|
||
// if(rMeta.isNull())
|
||
// {
|
||
// pai::log::Error(" MetaData信息为空!");
|
||
// return false;
|
||
// }
|
||
// std::string moduleClassName = rMeta[KEY_JSON_CLASS_NAME].asString();
|
||
// m_modulePaths.insert(make_pair(moduleClassName,LIB_NAME_PREFIX+rMeta[KEY_JSON_LIB_NAME].asString()+LIB_NAME_SUFFIX));
|
||
// pModel = CreateModuleByClassNameInternal(moduleClassName);
|
||
// if(pModel!=NULL)
|
||
// {
|
||
// pMetaData = const_cast<CModuleMetaData*>(pModel->GetMetaData());
|
||
// pMetaData->LoadFromJsonObject(rMeta);
|
||
// pMetaData->LoadIOFromJsonObject(PORT_INPUT, root);
|
||
// pMetaData->LoadIOFromJsonObject(PORT_OUTPUT, root);
|
||
// CModuleParameter* pModuleParam = pModel->GetModuleParameter();
|
||
// try
|
||
// {
|
||
// pModuleParam->LoadFromJson(root,true);
|
||
// }
|
||
// catch (pai::error::generic_error & e)
|
||
// {
|
||
// std::stringstream errorMsg;
|
||
// errorMsg << "\nAn error occurred when create module " << pMetaData->GetName()
|
||
// << ": Load parameter from json failed!" << e.what();
|
||
// pai::log::Error(errorMsg.str());
|
||
// }
|
||
|
||
// m_moduleContainer.insert(make_pair(pMetaData->GetID(), pModel));
|
||
// return true;
|
||
// }
|
||
// else
|
||
// {
|
||
// std::string errorMsg = " 创建Module失败,该模块部署错误,可能被误删除或者部署了错误的版本,请联系该模块开发人员!cannot create class "+rMeta["ClassName"].asString()+" from "+"lib"+rMeta["LibName"].asString()+".so";
|
||
// pai::log::Error(errorMsg);
|
||
// return false;
|
||
// }
|
||
// }
|
||
|
||
void CModuleManager::ListAllModules(std::vector<CModule*>& vecModules) const
|
||
{
|
||
std::map<std::string, CModule*>::const_iterator it = m_moduleContainer.begin();
|
||
while(it != m_moduleContainer.end())
|
||
{
|
||
vecModules.push_back(it->second);
|
||
it++;
|
||
}
|
||
}
|
||
CModule* CModuleManager::FindModule(const std::string& id) const
|
||
{
|
||
std::map<std::string, CModule*>::const_iterator it = m_moduleContainer.find(id);
|
||
if (it != m_moduleContainer.end())
|
||
{
|
||
return it->second;
|
||
}
|
||
return NULL;
|
||
}
|
||
CModuleMetaData* CModuleManager::FindModuleMetaData(const std::string& id) const
|
||
{
|
||
CModule* module = FindModule(id);
|
||
if(module==NULL)
|
||
return NULL;
|
||
else
|
||
return module->GetMetaData();
|
||
|
||
}
|
||
|
||
void CModuleManager::GetModulesByCategory(const std::string& strCategory, std::vector<CModule*>& vecModules)
|
||
{
|
||
std::map<std::string, CModule*>::const_iterator it = m_moduleContainer.begin();
|
||
for (; it != m_moduleContainer.end(); ++it)
|
||
{
|
||
if (it->second->GetMetaData()->GetCategory() == strCategory)
|
||
{
|
||
vecModules.push_back(it->second);
|
||
}
|
||
}
|
||
}
|
||
|
||
void CModuleManager::GetCategoryNames(std::vector<std::string>& vecCategoryNames)
|
||
{
|
||
vecCategoryNames.clear();
|
||
std::map<std::string, CModule*>::const_iterator it = m_moduleContainer.begin();
|
||
for (; it != m_moduleContainer.end(); ++it)
|
||
{
|
||
vecCategoryNames.push_back(it->second->GetMetaData()->GetCategory());
|
||
}
|
||
sort(vecCategoryNames.begin(), vecCategoryNames.end());
|
||
vecCategoryNames.erase(unique(vecCategoryNames.begin(), vecCategoryNames.end()), vecCategoryNames.end());
|
||
}
|
||
|
||
string CModuleManager::GetLibDeployPath() const
|
||
{
|
||
return MODULE_PATH;
|
||
}
|
||
|
||
void CModuleManager::ReLoadAllModules()
|
||
{
|
||
|
||
char * pVal = (char*)PAI_HOME.c_str(); //getenv(PAI_HOME.c_str())获取环境变量PAI_HOME
|
||
string str = pVal;
|
||
string path = DERECTORY_SPLIT;
|
||
path.append(MODULE_PATH);
|
||
str += path;
|
||
Initialize(str);
|
||
}
|
||
|
||
void CModuleManager::LoadAllModules()
|
||
{
|
||
if(!m_isLoadAllModules){
|
||
ReLoadAllModules();
|
||
m_isLoadAllModules = true;
|
||
}
|
||
}
|
||
|
||
void CModuleManager::AddModule(std::string modulefileFullPathName,CModule* aModule,void* modulehandle)
|
||
{
|
||
m_moduleContainer.insert(make_pair(aModule->GetMetaData()->GetID(), aModule));
|
||
m_modulePaths.insert(make_pair(aModule->GetMetaData()->GetID(), modulefileFullPathName));
|
||
m_moduleHandles.push_back(modulehandle);
|
||
}
|
||
CModuleManager* GetModuleManager()
|
||
{
|
||
static CModuleManager g_moduleManager;
|
||
return &g_moduleManager;
|
||
}
|
||
|
||
}
|
||
}
|