XNSim/XNCore/XNScenarioManager.cpp

393 lines
13 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;
}
// 运行环境配置文件解析
bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType)
{
T_D();
if (initialType == 0) {
return ParseScenarioXml(XmlPath);
} else {
return ParseConfig(XmlPath);
}
}
// 解析运行环境描述文件
bool XNScenarioManager::ParseScenarioXml(const std::string &XmlPath)
{
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 planeName = envInfo->Attribute("PlaneName");
// 设置工作目录
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 = XNSim::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");
std::string serviceVersion = service->Attribute("Version");
libName = XNSim::getFileNameWithoutExt(libName);
std::string dynamicLibName = servicePath + "lib" + libName + ".so." + serviceVersion;
// 加载动态库
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName,
serviceVersion, 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 = XNSim::safe_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 = XNSim::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");
std::string modelVersion = model->Attribute("Version");
libName = XNSim::getFileNameWithoutExt(libName);
std::string dynamicLibName = modelPath + "lib" + libName + ".so." + modelVersion;
// 加载动态库
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, modelVersion,
planeName, 0, threadID);
model = model->NextSiblingElement("Model");
}
modelGroup = modelGroup->NextSiblingElement("ModelGroup");
}
return true;
}
// 解析构型配置文件
bool XNScenarioManager::ParseConfig(const std::string &ConfigID)
{
T_D();
// 获取数据库路径
std::string dbPath = std::getenv("XNCore");
if (dbPath.empty()) {
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
return false;
}
dbPath += "/database/XNSim.db";
// 打开数据库
sqlite3 *db;
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
return false;
}
// 准备SQL语句
std::string sql = "SELECT * FROM Configuration WHERE ConfID = ?";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
sqlite3_close(db);
return false;
}
// 绑定参数
int configIdInt = XNSim::safe_stoi(ConfigID);
if (sqlite3_bind_int(stmt, 1, configIdInt) != SQLITE_OK) {
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 执行查询
if (sqlite3_step(stmt) != SQLITE_ROW) {
LOG_ERROR("0x1019 未找到配置ID为%1的记录", ConfigID);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
std::string planeName = XNSim::getStringFromSqlite3(stmt, 1);
std::string osName = XNSim::getStringFromSqlite3(stmt, 3);
std::string version = XNSim::getStringFromSqlite3(stmt, 4);
std::string kernel = XNSim::getStringFromSqlite3(stmt, 5);
std::string rootPath = XNSim::getStringFromSqlite3(stmt, 7);
GetFramework()->SetWorkPath(rootPath);
// 设置模型库目录
std::string modelPath = rootPath + XNSim::getStringFromSqlite3(stmt, 8);
GetFramework()->SetModelPath(modelPath);
// 设置服务库目录
std::string servicePath = rootPath + XNSim::getStringFromSqlite3(stmt, 9);
GetFramework()->SetServicePath(servicePath);
// 设置域ID
uint32_t domainID = std::stoul(XNSim::getStringFromSqlite3(stmt, 10));
GetFramework()->GetDDSManager()->SetDomainID(domainID);
// 读取CPU亲和性
std::string cpuAff = XNSim::getStringFromSqlite3(stmt, 6);
std::vector<std::string> cpuAffList = XNSim::split(cpuAff, ",");
//查询LoadServices表读取服务信息
std::string servicesSql = "SELECT * FROM LoadServices WHERE ConfID = ?";
sqlite3_stmt *servicesStmt;
if (sqlite3_prepare_v2(db, servicesSql.c_str(), -1, &servicesStmt, nullptr) != SQLITE_OK) {
LOG_ERROR("0x1020 准备LoadServices查询语句失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 绑定参数
if (sqlite3_bind_int(servicesStmt, 1, configIdInt) != SQLITE_OK) {
LOG_ERROR("0x1021 绑定LoadServices参数失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 执行查询并处理结果
while (sqlite3_step(servicesStmt) == SQLITE_ROW) {
// 获取服务信息
std::string ClassName = XNSim::getStringFromSqlite3(servicesStmt, 1);
std::string ServiceVersion = XNSim::getStringFromSqlite3(servicesStmt, 2);
std::string ServiceName = XNSim::getStringFromSqlite3(servicesStmt, 3);
ClassName = XNSim::getFileNameWithoutExt(ClassName);
std::string dynamicLibName = servicePath + "lib" + ClassName + ".so." + ServiceVersion;
// 加载动态库
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, ClassName, ServiceVersion,
1);
}
// 查询LoadModelGroups表读取模型组信息
std::string modelGroupsSql = "SELECT * FROM LoadModelGroups WHERE ConfID = ?";
sqlite3_stmt *modelGroupsStmt;
if (sqlite3_prepare_v2(db, modelGroupsSql.c_str(), -1, &modelGroupsStmt, nullptr)
!= SQLITE_OK) {
LOG_ERROR("0x1020 准备LoadModelGroups查询语句失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 绑定参数
if (sqlite3_bind_int(modelGroupsStmt, 1, configIdInt) != SQLITE_OK) {
LOG_ERROR("0x1021 绑定LoadModelGroups参数失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(modelGroupsStmt);
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 执行查询并处理结果
while (sqlite3_step(modelGroupsStmt) == SQLITE_ROW) {
// 获取模型组信息
std::string GroupID = XNSim::getStringFromSqlite3(modelGroupsStmt, 1);
std::string GroupName = XNSim::getStringFromSqlite3(modelGroupsStmt, 2);
double GroupFreq = std::stod(XNSim::getStringFromSqlite3(modelGroupsStmt, 3));
uint32_t GroupPriority = XNSim::safe_stoi(XNSim::getStringFromSqlite3(modelGroupsStmt, 4));
std::string GroupCPUAff = XNSim::getStringFromSqlite3(modelGroupsStmt, 5);
std::vector<std::string> GroupCPUAffList = XNSim::split(GroupCPUAff, ",");
// 验证CPU亲和性
for (const auto &cpu : GroupCPUAffList) {
if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) {
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误CPU亲和性值%s,进程CPU亲和性值%s",
cpu.c_str(), cpuAff.c_str());
sqlite3_finalize(modelGroupsStmt);
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
}
int ThreadCpuAffinity = 0;
for (const auto &cpu : GroupCPUAffList) {
auto it = std::find(cpuAffList.begin(), cpuAffList.end(), cpu);
if (it != cpuAffList.end()) {
ThreadCpuAffinity |= 1 << std::distance(cpuAffList.begin(), it);
}
}
LOG_INFO("0x1021 添加线程池: %1", GroupName);
// 添加线程池
uint32_t threadID = GetFramework()->GetThreadManager()->AddThreadPool(
GroupName, GroupFreq, GroupPriority, ThreadCpuAffinity);
// 准备查询LoadModels表的SQL语句
std::string modelsSql = "SELECT * FROM LoadModels WHERE GroupID = ?";
sqlite3_stmt *modelsStmt = nullptr;
if (sqlite3_prepare_v2(db, modelsSql.c_str(), -1, &modelsStmt, nullptr) != SQLITE_OK) {
LOG_ERROR("0x1022 准备LoadModels查询语句失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(modelGroupsStmt);
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 绑定参数
if (sqlite3_bind_int(modelsStmt, 1, XNSim::safe_stoi(GroupID)) != SQLITE_OK) {
LOG_ERROR("0x1023 绑定LoadModels参数失败: %1", sqlite3_errmsg(db));
sqlite3_finalize(modelsStmt);
sqlite3_finalize(modelGroupsStmt);
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return false;
}
// 执行查询并处理结果
while (sqlite3_step(modelsStmt) == SQLITE_ROW) {
// 获取模型信息
std::string ClassName = XNSim::getStringFromSqlite3(modelsStmt, 1);
std::string ModelVersion = XNSim::getStringFromSqlite3(modelsStmt, 2);
std::string ModelName = XNSim::getStringFromSqlite3(modelsStmt, 3);
ClassName = XNSim::getFileNameWithoutExt(ClassName);
std::string dynamicLibName = modelPath + "lib" + ClassName + ".so." + ModelVersion;
// 加载动态库
LOG_INFO("0x1021 加载模型: %1", dynamicLibName);
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, ClassName, ModelVersion,
planeName, 1, threadID);
}
// 清理资源
sqlite3_finalize(modelsStmt);
}
// 清理资源
sqlite3_finalize(modelGroupsStmt);
sqlite3_finalize(servicesStmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
return true;
}