/** * @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 #include #include #include // 默认构造函数 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("D01084001:构型管理器初始化成功!"); d->_status = XNFrameObjectStatus::Initialized; return true; } bool XNScenarioManager::PrepareForExecute() { T_D(); d->_status = XNFrameObjectStatus::Ready; LOG_INFO("D01084002:构型管理器准备就绪!"); 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("C01082003:打开构型配置文件 %1 出错, 错误信息: %2", XmlPath, strerror(errno)); return false; } tinyxml2::XMLDocument doc; if (doc.LoadFile(XmlPath.c_str()) != tinyxml2::XML_SUCCESS) { LOG_ERROR("C01082004:构型配置文件 %1 的XML解析失败!", 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")); if (domainID == 0 || domainID > 225) { LOG_WARNING("A01083005:DDS通信域ID设置错误, 使用默认域ID: 10"); domainID = 10; } GetFramework()->GetDDSManager()->SetDomainID(domainID); // 读取CPU亲和性 std::string cpuAff = envInfo->Attribute("CPUAffinity"); std::vector 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; // 加载动态库 LOG_INFO("D01084006:正在加载服务 %1", dynamicLibName); 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("A01082007:模型组 %1 优先级设置错误(0~99),优先级值:%2", modelGroupName, modelGroupPriority); return false; } // 读取模型分组CPU亲和性 std::string modelGroupCPUAff = modelGroup->Attribute("CPUAff"); std::vector modelGroupCPUAffList = XNSim::split(modelGroupCPUAff, ","); // 验证CPU亲和性 for (const auto &cpu : modelGroupCPUAffList) { if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) { LOG_ERROR( "A01082008:模型组 %1 的CPU亲和性设置错误, CPU亲和性值: %2,进程CPU亲和性值: %3", modelGroupName, 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; // 加载动态库 LOG_INFO("D01084009:正在加载模型 %1", dynamicLibName); 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 XNCorePath = std::getenv("XNCore"); if (XNCorePath.empty()) { LOG_ERROR("A01082010:使用数据库构型配置时必须设置XNCore环境变量!"); return false; } std::string dbPath = XNCorePath + "/database/XNSim.db"; // 打开数据库 sqlite3 *db; if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) { LOG_ERROR("C01082011:打开数据库 %1 失败, 错误信息: %2", dbPath, 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("C01082012:数据库查询时准备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("C01082013:数据库查询时绑定参数失败, 错误信息: %1", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close(db); return false; } // 执行查询 if (sqlite3_step(stmt) != SQLITE_ROW) { LOG_ERROR("A01082014:未在数据库中找到构型ID为 %1 的记录", ConfigID); sqlite3_finalize(stmt); sqlite3_close(db); return false; } std::string planeName = XNSim::getStringFromSqlite3(stmt, 1); std::string confName = XNSim::getStringFromSqlite3(stmt, 2); std::string osName = XNSim::getStringFromSqlite3(stmt, 3); std::string version = XNSim::getStringFromSqlite3(stmt, 4); std::string kernel = XNSim::getStringFromSqlite3(stmt, 5); std::string rootPath = XNCorePath + "/Configuration/" + confName; GetFramework()->SetWorkPath(rootPath); // 设置模型库目录 std::string modelPath = rootPath + "/Models"; GetFramework()->SetModelPath(modelPath); // 设置服务库目录 std::string servicePath = XNCorePath + "/Services"; GetFramework()->SetServicePath(servicePath); // 设置域ID uint32_t domainID = std::stoul(XNSim::getStringFromSqlite3(stmt, 7)); if (domainID == 0 || domainID > 225) { LOG_WARNING("A01083015:DDS通信域ID设置错误, 使用默认域ID: 10"); domainID = 10; } GetFramework()->GetDDSManager()->SetDomainID(domainID); // 读取CPU亲和性 std::string cpuAff = XNSim::getStringFromSqlite3(stmt, 6); std::vector 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("C01082016:数据库查询时准备LoadServices表的SQL查询语句失败, 错误信息: %1", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close(db); return false; } // 绑定参数 if (sqlite3_bind_int(servicesStmt, 1, configIdInt) != SQLITE_OK) { LOG_ERROR("C01082017:数据库查询时绑定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; // 加载动态库 LOG_INFO("D01084018:正在加载服务 %1", dynamicLibName); 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("C01082019:数据库查询时准备LoadModelGroups表的SQL查询语句失败, 错误信息: %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("C01082020:数据库查询时绑定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)); if (GroupPriority > 99 || GroupPriority < 0) { LOG_ERROR("A01082021:模型组 %1 优先级设置错误(0~99),优先级值:%2", GroupName, GroupPriority); sqlite3_finalize(modelGroupsStmt); sqlite3_finalize(servicesStmt); sqlite3_finalize(stmt); sqlite3_close(db); return false; } std::string GroupCPUAff = XNSim::getStringFromSqlite3(modelGroupsStmt, 5); std::vector GroupCPUAffList = XNSim::split(GroupCPUAff, ","); // 验证CPU亲和性 for (const auto &cpu : GroupCPUAffList) { if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) { LOG_ERROR( "A01082022:模型组 %1 的CPU亲和性设置错误, CPU亲和性值: %2,进程CPU亲和性值: %3", GroupName, 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); } } // 添加线程池 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("C01082023:数据库查询时准备LoadModels表的SQL查询语句失败, 错误信息: %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("C01082024:数据库查询时绑定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("D01084025:正在加载模型 %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; }