XNSim/XNCore/XNScenarioManager.cpp

203 lines
6.2 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file XNScenarioManager.cpp
* @author jinchao
* @brief 运行环境描述管理器类源文件
* @version 1.0
* @date 2024-11-07
*
* @copyright Copyright (c) 2024 XN
*
*/
#include "XNScenarioManager.h"
#include "XNScenarioManager_p.h"
#include "XNFramework.h"
#include "XNDDSManager.h"
#include "XNThreadManager.h"
#include "XNModelManager.h"
#include "XNServiceManager.h"
#include <fstream>
#include <streambuf>
#include <cerrno>
#include <tinyxml2.h>
// 默认构造函数
XNScenarioManager::XNScenarioManager() : XNBaseFrameObject(new XNScenarioManagerPrivate())
{
SetUniqueId(5);
SetObjectName("XNScenarioManager");
}
XNScenarioManager::~XNScenarioManager()
{
}
XNScenarioManager::XNScenarioManager(PrivateType *p) : XNBaseFrameObject(p)
{
}
// 获取运行环境名称
const std::string &XNScenarioManager::GetSimName()
{
T_D();
return d->_ScenarioName;
}
// 设置运行环境名称
void XNScenarioManager::SetSimName(const std::string &simName)
{
T_D();
d->_ScenarioName = simName;
}
// 初始化
bool XNScenarioManager::Initialize()
{
T_D();
LOG_INFO("XNScenarioManager Initialize Success!");
d->_status = XNFrameObjectStatus::Initialized;
return true;
}
bool XNScenarioManager::PrepareForExecute()
{
T_D();
d->_status = XNFrameObjectStatus::Ready;
LOG_INFO("XNScenarioManager is prepared!");
return true;
}
// 辅助函数:分割字符串
std::vector<std::string> split(const std::string &str, const std::string &delim)
{
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
do {
pos = str.find(delim, prev);
if (pos == std::string::npos)
pos = str.length();
std::string token = str.substr(prev, pos - prev);
if (!token.empty())
tokens.push_back(token);
prev = pos + delim.length();
} while (pos < str.length() && prev < str.length());
return tokens;
}
// 辅助函数:获取文件名(不含扩展名)
std::string getFileNameWithoutExt(const std::string &path)
{
size_t lastDot = path.find_last_of('.');
if (lastDot != std::string::npos) {
return path.substr(0, lastDot);
}
return path;
}
// 运行环境配置文件解析
bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType)
{
T_D();
std::ifstream file(XmlPath);
if (!file.is_open()) {
LOG_ERROR("0x2100 打开运行环境描述文件: %1出错错误信息 %2", XmlPath, strerror(errno));
return false;
}
tinyxml2::XMLDocument doc;
if (doc.LoadFile(XmlPath.c_str()) != tinyxml2::XML_SUCCESS) {
LOG_ERROR("0x2100 解析XML文件: %1 失败", XmlPath);
file.close();
return false;
}
tinyxml2::XMLElement *root = doc.FirstChildElement("Scenario");
// 读取环境信息
tinyxml2::XMLElement *envInfo = root->FirstChildElement("Environment");
std::string OSName = envInfo->Attribute("OSName");
std::string version = envInfo->Attribute("Version");
std::string kernel = envInfo->Attribute("RTXVersion");
// 设置工作目录
std::string rootPath = envInfo->Attribute("WorkPath");
GetFramework()->SetWorkPath(rootPath);
// 设置模型库目录
std::string modelPath = rootPath + envInfo->Attribute("ModelsPath");
GetFramework()->SetModelPath(modelPath);
// 设置服务库目录
std::string servicePath = rootPath + envInfo->Attribute("ServicesPath");
GetFramework()->SetServicePath(servicePath);
// 设置域ID
uint32_t domainID = std::stoul(envInfo->Attribute("DomainID"));
GetFramework()->GetDDSManager()->SetDomainID(domainID);
// 读取CPU亲和性
std::string cpuAff = envInfo->Attribute("CPUAffinity");
std::vector<std::string> cpuAffList = split(cpuAff, ",");
//读取服务列表
tinyxml2::XMLElement *serviceList = root->FirstChildElement("ServicesList");
if (serviceList) {
tinyxml2::XMLElement *service = serviceList->FirstChildElement("Service");
while (service) {
std::string serviceName = service->Attribute("Name");
std::string libName = service->Attribute("ClassName");
libName = getFileNameWithoutExt(libName);
std::string dynamicLibName = servicePath + "lib" + libName + ".so";
// 加载动态库
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName, 0);
service = service->NextSiblingElement("Service");
}
}
// 读取模型分组
tinyxml2::XMLElement *modelGroup = root->FirstChildElement("ModelGroup");
while (modelGroup) {
// 读取模型分组名称
std::string modelGroupName = modelGroup->Attribute("Name");
// 读取模型分组频率
double modelGroupFreq = std::stod(modelGroup->Attribute("Freq"));
// 读取模型分组优先级
int modelGroupPriority = std::stoi(modelGroup->Attribute("Priority"));
if (modelGroupPriority > 99 || modelGroupPriority < 0) {
LOG_ERROR("0x2100 模型分组优先级设置错误,优先级值:%d", modelGroupPriority);
return false;
}
// 读取模型分组CPU亲和性
std::string modelGroupCPUAff = modelGroup->Attribute("CPUAff");
std::vector<std::string> modelGroupCPUAffList = split(modelGroupCPUAff, ",");
// 验证CPU亲和性
for (const auto &cpu : modelGroupCPUAffList) {
if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) {
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误CPU亲和性值%s,进程CPU亲和性值%s",
cpu.c_str(), cpuAff.c_str());
return false;
}
}
int ThreadCpuAffinity = 0;
for (const auto &cpu : modelGroupCPUAffList) {
auto it = std::find(cpuAffList.begin(), cpuAffList.end(), cpu);
if (it != cpuAffList.end()) {
ThreadCpuAffinity |= 1 << std::distance(cpuAffList.begin(), it);
}
}
// 添加线程池
uint32_t threadID = GetFramework()->GetThreadManager()->AddThreadPool(
modelGroupName, modelGroupFreq, modelGroupPriority, ThreadCpuAffinity);
// 读取模型列表
tinyxml2::XMLElement *model = modelGroup->FirstChildElement("Model");
while (model) {
std::string modelName = model->Attribute("Name");
std::string libName = model->Attribute("ClassName");
libName = getFileNameWithoutExt(libName);
std::string dynamicLibName = modelPath + "lib" + libName + ".so";
// 加载动态库
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, 0, threadID);
model = model->NextSiblingElement("Model");
}
modelGroup = modelGroup->NextSiblingElement("ModelGroup");
}
return true;
}