logplus/Workflow/WFEngine/Module/src/ModuleManager.cpp

370 lines
12 KiB
C++
Raw Normal View History

2026-01-16 17:18:41 +08:00
/*
* 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;
}
}
}