LCOV - code coverage report
Current view: top level - basic_component/package_manager/src - package_process_config.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.8 % 286 234
Test Date: 2026-07-28 10:52:48 Functions: 87.0 % 23 20

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "package_process_config.h"
      12              : 
      13              : #include <fstream>
      14              : #include <array>
      15              : #include <vector>
      16              : #include <unordered_set>
      17              : #include "package_worker.h"
      18              : #include "tsd_util_func.h"
      19              : 
      20              : namespace tsd {
      21              : namespace {
      22              : const std::string PACKAGE_CONFIG_NAME = "name:";
      23              : const std::string COMMON_SINK_PKG_CONFIG_NAME = "ascend_package_load.ini";
      24              : const std::string COMMON_SINK_PKG_CONFIG_DIR = "/conf/";
      25              : const size_t MAX_CONFIG_NUM = 100UL;
      26              : } // namespace
      27              : 
      28            5 : PackageProcessConfig::PackageProcessConfig()
      29           30 :     : configParaParseFuncMap_(
      30            0 :           {{"install_path", &PackageProcessConfig::ParseInstallPath},
      31            0 :            {"optional", &PackageProcessConfig::ParseOptionalFlag},
      32            0 :            {"package_path", &PackageProcessConfig::ParsePackagePath},
      33           10 :            {"load_as_per_soc", &PackageProcessConfig::ParseLoadAsPerSocFlag}})
      34           10 : {}
      35              : 
      36          341 : PackageProcessConfig* PackageProcessConfig::GetInstance()
      37              : {
      38          341 :     static PackageProcessConfig instance;
      39          341 :     return &instance;
      40              : }
      41              : 
      42           32 : PackConfDetail PackageProcessConfig::GetConfigDetailInfo(const std::string& srcPath)
      43              : {
      44           32 :     const std::lock_guard<std::mutex> lk(configMut_);
      45           32 :     const auto iter = configMap_.find(srcPath);
      46           32 :     if (iter != configMap_.end()) {
      47           31 :         return iter->second;
      48              :     } else {
      49            1 :         return PackConfDetail();
      50              :     }
      51           32 : }
      52              : 
      53            1 : bool PackageProcessConfig::SetConfigDataOnServer(const SinkPackageConfig& hdcConfig)
      54              : {
      55            1 :     const std::string pkgName = hdcConfig.package_name();
      56            1 :     auto iter = configMap_.find(pkgName);
      57            1 :     if (iter != configMap_.end()) {
      58            0 :         iter->second.decDstDir = static_cast<DeviceInstallPath>(hdcConfig.file_dec_dst_dir());
      59            0 :         TSD_RUN_INFO(
      60              :             "update package:%s config, dest dir:%u", pkgName.c_str(), static_cast<uint32_t>(iter->second.decDstDir));
      61              :     } else {
      62            1 :         if (configMap_.size() >= MAX_CONFIG_NUM) {
      63            0 :             TSD_RUN_WARN("current config map is full:%zu, threshold is:%zu", configMap_.size(), MAX_CONFIG_NUM);
      64            0 :             return true;
      65              :         }
      66            1 :         PackConfDetail tempNode;
      67            1 :         tempNode.decDstDir = static_cast<DeviceInstallPath>(hdcConfig.file_dec_dst_dir());
      68            1 :         tempNode.validFlag = true;
      69            1 :         tempNode.PrintfInfo(pkgName);
      70              :         try {
      71            1 :             configMap_[pkgName] = tempNode;
      72            1 :             TSD_RUN_INFO("insert package:%s config", pkgName.c_str());
      73            0 :         } catch (...) {
      74            0 :             TSD_ERROR("");
      75            0 :             return false;
      76            0 :         }
      77            1 :     }
      78            1 :     return true;
      79            1 : }
      80              : 
      81            2 : TSD_StatusT PackageProcessConfig::ParseConfigDataFromProtoBuf(const HDCMessage& hdcMsg)
      82              : {
      83            2 :     const std::lock_guard<std::mutex> lk(configMut_);
      84          103 :     for (auto j = 0; j < hdcMsg.sink_pkg_con_list_size(); j++) {
      85          102 :         const SinkPackageConfig& hdcConfig = hdcMsg.sink_pkg_con_list(j);
      86          102 :         if (!SetConfigDataOnServer(hdcConfig)) {
      87            1 :             TSD_RUN_WARN("invalid config data");
      88            1 :             return TSD_START_FAIL;
      89              :         }
      90              :     }
      91            1 :     hashCode_ = hdcMsg.package_config_hash_code();
      92            1 :     TSD_RUN_INFO("package config has stored hash code:%s", hashCode_.c_str());
      93            1 :     return TSD_OK;
      94            2 : }
      95              : 
      96           24 : std::string PackageProcessConfig::GetHostFilePath(const std::string& fileDir, const std::string& fileName) const
      97              : {
      98           24 :     std::string configPath;
      99           24 :     GetScheduleEnv("ASCEND_HOME_PATH", configPath);
     100           24 :     if (configPath.empty()) {
     101            0 :         configPath = "/usr/local/Ascend/latest/";
     102            0 :         TSD_INFO("ASCEND_HOME_PATH is not set, use default value[%s]", configPath.c_str());
     103              :     }
     104              : 
     105           24 :     configPath = configPath + "/" + fileDir;
     106           24 :     if (access(configPath.c_str(), F_OK) != 0) {
     107            5 :         TSD_RUN_WARN("cannot get package path:%s, reason:%s", configPath.c_str(), SafeStrerror().c_str());
     108           10 :         return "";
     109              :     }
     110           19 :     configPath = configPath + fileName;
     111           19 :     if (access(configPath.c_str(), F_OK) != 0) {
     112            0 :         TSD_INFO("cannot get package file:%s, reason:%s", configPath.c_str(), SafeStrerror().c_str());
     113            0 :         return "";
     114              :     }
     115           19 :     TSD_INFO("get config path:%s", configPath.c_str());
     116           19 :     return configPath;
     117           24 : }
     118              : 
     119            8 : TSD_StatusT PackageProcessConfig::ParseConfigDataFromFile(const std::string& pkgTitle)
     120              : {
     121            8 :     const std::string conFile = GetHostFilePath(COMMON_SINK_PKG_CONFIG_DIR, COMMON_SINK_PKG_CONFIG_NAME);
     122            8 :     if (access(conFile.c_str(), R_OK) != 0) {
     123            0 :         TSD_INFO("cannot access file:%s, errno=%d, strerror=%s", conFile.c_str(), errno, strerror(errno));
     124            0 :         return TSD_OK;
     125              :     }
     126              : 
     127            8 :     const std::lock_guard<std::mutex> lk(configMut_);
     128            8 :     if (finishParse_) {
     129            5 :         TSD_INFO("config already set, skip parse");
     130            5 :         return TSD_OK;
     131              :     }
     132              : 
     133            3 :     std::ifstream inFile(conFile);
     134            3 :     if (!inFile) {
     135            0 :         TSD_ERROR("open file:%s nok, errno=%d, strerror=%s", conFile.c_str(), errno, strerror(errno));
     136            0 :         return TSD_START_FAIL;
     137              :     }
     138            6 :     const ScopeGuard fileGuard([&inFile]() { inFile.close(); });
     139              : 
     140            3 :     std::string inputLine;
     141            3 :     size_t itCnt = 0;
     142           14 :     while (getline(inFile, inputLine) && itCnt < MAX_CONFIG_NUM) {
     143           13 :         TSD_INFO("read config data current line:%s", inputLine.c_str());
     144           13 :         std::string packageName;
     145           13 :         const size_t pos = inputLine.find(PACKAGE_CONFIG_NAME);
     146           13 :         if (pos != std::string::npos) {
     147           13 :             packageName = inputLine.substr(pos + PACKAGE_CONFIG_NAME.size());
     148           13 :             Trim(packageName);
     149           13 :             if (packageName.empty()) {
     150            1 :                 TSD_ERROR("valid package name is empty read line:%s", inputLine.c_str());
     151            1 :                 configMap_.clear();
     152            1 :                 return TSD_START_FAIL;
     153              :             }
     154           12 :             if (configMap_.find(packageName) == configMap_.end()) {
     155           12 :                 if (!SetConfigDataOnHost(inFile, packageName, pkgTitle)) {
     156            1 :                     TSD_ERROR("package:%s config read but not store, clear all config", packageName.c_str());
     157            1 :                     configMap_.clear();
     158            1 :                     return TSD_START_FAIL;
     159              :                 }
     160              :             }
     161           11 :             itCnt++;
     162              :         }
     163           13 :     }
     164            1 :     finishParse_ = true;
     165            1 :     return TSD_OK;
     166            8 : }
     167              : 
     168           59 : bool PackageProcessConfig::ParseSinglePara(
     169              :     std::string& inputLine, PackConfDetail& tempNode, std::unordered_set<std::string>& finishedParseItemSet) const
     170              : {
     171           59 :     const std::size_t pos = inputLine.find(":");
     172           59 :     if (pos == std::string::npos) {
     173            1 :         TSD_ERROR("invalid config line:%s", inputLine.c_str());
     174            1 :         return false;
     175              :     }
     176           58 :     std::string key = inputLine.substr(0, pos);
     177           58 :     Trim(key);
     178           58 :     std::string value = inputLine.substr(pos + 1UL);
     179           58 :     Trim(value);
     180           58 :     const auto iter = configParaParseFuncMap_.find(key);
     181           58 :     if (iter == configParaParseFuncMap_.end()) {
     182            1 :         TSD_ERROR("invalid config item:%s, line:%s", key.c_str(), inputLine.c_str());
     183            1 :         return false;
     184              :     }
     185           57 :     if ((this->*(iter->second))(value, tempNode)) {
     186           56 :         finishedParseItemSet.insert(key);
     187           56 :         return true;
     188              :     }
     189            1 :     return false;
     190           58 : }
     191              : 
     192           16 : bool PackageProcessConfig::ParseInstallPath(const std::string& para, PackConfDetail& tempNode) const
     193              : {
     194           16 :     if ((para == "0") || (para == "1") || (para == "2") || (para == "3")) {
     195           15 :         int32_t result = 0;
     196           15 :         (void)TransStrToInt(para, result);
     197           15 :         tempNode.decDstDir = static_cast<DeviceInstallPath>(result);
     198              :     } else {
     199            1 :         TSD_ERROR("invalid installPath:%s", para.c_str());
     200            1 :         return false;
     201              :     }
     202           15 :     return true;
     203              : }
     204              : 
     205           18 : bool PackageProcessConfig::ParseOptionalFlag(const std::string& para, PackConfDetail& tempNode) const
     206              : {
     207           18 :     if ((para == "true") || (para == "false")) {
     208           16 :         tempNode.optionalFlag = para == "true" ? true : false;
     209              :     } else {
     210            2 :         TSD_ERROR("invalid optionalFlag:%s", para.c_str());
     211            2 :         return false;
     212              :     }
     213           16 :     return true;
     214              : }
     215              : 
     216           16 : bool PackageProcessConfig::ParsePackagePath(const std::string& para, PackConfDetail& tempNode) const
     217              : {
     218           16 :     if (!para.empty()) {
     219           15 :         tempNode.findPath = para;
     220              :     } else {
     221            1 :         TSD_ERROR("invalid packagePath:%s", para.c_str());
     222            1 :         return false;
     223              :     }
     224           15 :     return true;
     225              : }
     226              : 
     227           15 : bool PackageProcessConfig::ParseLoadAsPerSocFlag(const std::string& para, PackConfDetail& tempNode) const
     228              : {
     229           15 :     if ((para == "true") || (para == "false")) {
     230           14 :         tempNode.loadAsPerSocFlag = para == "true" ? true : false;
     231              :     } else {
     232            1 :         TSD_ERROR("invalid loadAsPerSocFlag:%s", para.c_str());
     233            1 :         return false;
     234              :     }
     235           14 :     return true;
     236              : }
     237              : 
     238           15 : bool PackageProcessConfig::SetConfigDataOnHost(
     239              :     std::ifstream& inFile, const std::string& fileName, const std::string& pkgTitle)
     240              : {
     241           15 :     std::string inputLine;
     242           15 :     uint32_t itCnt = 0U;
     243           15 :     const uint32_t configItemNum = static_cast<uint32_t>(configParaParseFuncMap_.size());
     244           15 :     PackConfDetail tempNode = {};
     245           15 :     std::unordered_set<std::string> finishedParseItemSet;
     246           70 :     while ((itCnt < configItemNum) && (getline(inFile, inputLine))) {
     247           56 :         if (!ParseSinglePara(inputLine, tempNode, finishedParseItemSet)) {
     248            1 :             TSD_ERROR("parse config line failed:%s", inputLine.c_str());
     249            1 :             return false;
     250              :         }
     251           55 :         itCnt++;
     252              :     }
     253           14 :     if (finishedParseItemSet.size() != configItemNum) {
     254            1 :         TSD_ERROR("not all config items parsed");
     255            1 :         return false;
     256              :     }
     257           13 :     tempNode.validFlag = true;
     258              :     try {
     259           13 :         if (!SetPkgHostTruePath(tempNode, fileName, pkgTitle)) {
     260            1 :             TSD_ERROR("set package:%s host true path failed", fileName.c_str());
     261            1 :             return false;
     262              :         }
     263           12 :         configMap_[fileName] = tempNode;
     264           12 :         tempNode.PrintfInfo(fileName);
     265           12 :         TSD_RUN_INFO("insert package:%s config", fileName.c_str());
     266            0 :     } catch (...) {
     267            0 :         TSD_ERROR("insert package:%s config failed", fileName.c_str());
     268            0 :         return false;
     269            0 :     }
     270           12 :     return true;
     271           15 : }
     272              : 
     273            5 : void PackageProcessConfig::ConstructPkgConfigMsg(HDCMessage& hdcMsg)
     274              : {
     275           60 :     for (auto iter = configMap_.begin(); iter != configMap_.end(); iter++) {
     276           55 :         SinkPackageConfig* curConf = hdcMsg.add_sink_pkg_con_list();
     277           55 :         curConf->set_package_name(iter->first);
     278           55 :         curConf->set_file_dec_dst_dir(static_cast<uint32_t>(iter->second.decDstDir));
     279              :         // 对于 compat plugin 包,附带 host 侧解析得到的 version/timestamp
     280           55 :         if (iter->second.decDstDir != DeviceInstallPath::COMPAT_PLUGIN_PATH) {
     281           55 :             continue;
     282              :         }
     283           10 :         std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     284           10 :         const auto verIt = hostPluginVersions_.find(iter->first);
     285           10 :         if (verIt == hostPluginVersions_.end() || verIt->second.Empty()) {
     286           10 :             continue;
     287              :         }
     288              : 
     289            0 :         PluginPackageVersionInfo* info = hdcMsg.add_host_plugin_versions();
     290            0 :         info->set_package_name(iter->first);
     291            0 :         info->set_version(verIt->second.version);
     292            0 :         info->set_timestamp(verIt->second.timestamp);
     293           10 :     }
     294              :     const std::string hashCode =
     295            5 :         CalFileSha256HashValue(GetHostFilePath(COMMON_SINK_PKG_CONFIG_DIR, COMMON_SINK_PKG_CONFIG_NAME));
     296              :     hdcMsg.set_package_config_hash_code(hashCode);
     297            5 :     TSD_INFO("set config hash code:%s", hashCode.c_str());
     298            5 : }
     299              : 
     300            1 : void PackageProcessConfig::RefreshHostPluginVersions()
     301              : {
     302            3 :     for (auto& kv : configMap_) {
     303            2 :         if (kv.second.decDstDir != DeviceInstallPath::COMPAT_PLUGIN_PATH) {
     304            1 :             continue;
     305              :         }
     306            2 :         const std::string& pkgName = kv.first;
     307            2 :         const std::string& hostFile = kv.second.hostTruePath;
     308            2 :         PluginPkgVersion info;
     309            2 :         if (hostFile.empty()) {
     310            1 :             TSD_RUN_INFO("host plugin pkg:%s has empty host path, skip parse ini", pkgName.c_str());
     311            1 :             std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     312            1 :             hostPluginVersions_[pkgName] = info;
     313            1 :             continue;
     314            1 :         }
     315              :         // .ini 与 .tar.gz 同名同路径
     316            1 :         std::string iniPath = hostFile;
     317            1 :         const std::string suffix = ".tar.gz";
     318            2 :         if ((iniPath.size() > suffix.size()) &&
     319            1 :             (iniPath.compare(iniPath.size() - suffix.size(), suffix.size(), suffix) == 0)) {
     320            1 :             iniPath = iniPath.substr(0U, iniPath.size() - suffix.size()) + ".ini";
     321              :         } else {
     322            0 :             iniPath += ".ini";
     323              :         }
     324            1 :         if (!PluginPkgVersionUtil::ParseIniFile(iniPath, info)) {
     325            1 :             TSD_RUN_WARN(
     326              :                 "parse plugin pkg:%s ini file:%s failed, fallback to checkcode compare", pkgName.c_str(),
     327              :                 iniPath.c_str());
     328              :         } else {
     329            0 :             TSD_RUN_INFO(
     330              :                 "host plugin pkg:%s ini parsed, version:%s timestamp:%s", pkgName.c_str(), info.version.c_str(),
     331              :                 info.timestamp.c_str());
     332              :         }
     333            1 :         std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     334            1 :         hostPluginVersions_[pkgName] = info;
     335            2 :     }
     336            1 : }
     337              : 
     338            9 : PluginPkgVersion PackageProcessConfig::GetHostPluginVersion(const std::string& pkgName)
     339              : {
     340            9 :     std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     341            9 :     const auto it = hostPluginVersions_.find(pkgName);
     342            9 :     if (it == hostPluginVersions_.end()) {
     343            3 :         return PluginPkgVersion{};
     344              :     }
     345            6 :     return it->second;
     346            9 : }
     347              : 
     348            0 : bool PackageProcessConfig::HasCompatPluginPackage() const
     349              : {
     350            0 :     for (const auto& kv : configMap_) {
     351            0 :         if (kv.second.decDstDir == DeviceInstallPath::COMPAT_PLUGIN_PATH) {
     352            0 :             return true;
     353              :         }
     354              :     }
     355            0 :     return false;
     356              : }
     357              : 
     358            0 : bool PackageProcessConfig::IsNeedToUpdateConfig(const HDCMessage& hdcMsg) const
     359              : {
     360            0 :     return (hdcMsg.package_config_hash_code() == hashCode_);
     361              : }
     362              : 
     363            2 : bool PackageProcessConfig::IsConfigPackageInfo(const std::string& oriPkgName)
     364              : {
     365            2 :     const size_t pos = oriPkgName.find("_");
     366            2 :     if ((pos == std::string::npos) || (pos == oriPkgName.size() - 1)) {
     367            2 :         return false;
     368              :     }
     369            0 :     const std::string tempName = oriPkgName.substr(pos + 1);
     370            0 :     const std::lock_guard<std::mutex> lk(configMut_);
     371            0 :     auto iter = configMap_.find(tempName);
     372            0 :     if (iter != configMap_.end()) {
     373            0 :         return true;
     374              :     } else {
     375            0 :         return false;
     376              :     }
     377            0 : }
     378              : 
     379           30 : TSD_StatusT PackageProcessConfig::GetPkgHostAndDeviceDstPath(
     380              :     const std::string& pkgName, std::string& orgFile, std::string& dstFile, const pid_t hostPid)
     381              : {
     382           30 :     const PackConfDetail detailInfo = GetConfigDetailInfo(pkgName);
     383           30 :     orgFile = detailInfo.hostTruePath;
     384              : 
     385           30 :     if (orgFile.empty()) {
     386           15 :         if (!detailInfo.optionalFlag) {
     387            0 :             TSD_ERROR("cannot find package:%s", pkgName.c_str());
     388            0 :             return TSD_INTERNAL_ERROR;
     389              :         } else {
     390           15 :             TSD_INFO("cannot find package:%s", pkgName.c_str());
     391           15 :             return TSD_OK;
     392              :         }
     393              :     }
     394              : 
     395           15 :     dstFile = dstFile + "/" + std::to_string(hostPid) + "_" + pkgName;
     396           15 :     TSD_RUN_INFO("get orgFile:%s, dstFile:%s", orgFile.c_str(), dstFile.c_str());
     397           15 :     return TSD_OK;
     398           30 : }
     399              : 
     400           15 : bool PackageProcessConfig::SetPkgHostTruePath(
     401              :     PackConfDetail& tempNode, const std::string& pkgName, const std::string& pkgTitle) const
     402              : {
     403           15 :     const auto pos = pkgTitle.find(';');
     404           15 :     std::string packageTitle;
     405           15 :     std::string shortSocVersion;
     406           15 :     if (pos == std::string::npos) {
     407            2 :         packageTitle = pkgTitle;
     408              :     } else {
     409           13 :         packageTitle = pkgTitle.substr(0, pos);
     410           13 :         shortSocVersion = pkgTitle.substr(pos + 1UL);
     411              :     }
     412           15 :     std::string fileDirWholePath;
     413           15 :     if (pkgName.find("-aicpu_legacy.tar.gz") != std::string::npos) {
     414            4 :         fileDirWholePath = tempNode.findPath + "/" + packageTitle + "/aicpu/";
     415              :     } else {
     416           11 :         fileDirWholePath = tempNode.findPath + "/";
     417              :     }
     418           15 :     if (tempNode.loadAsPerSocFlag) {
     419            3 :         if (shortSocVersion.empty()) {
     420            2 :             TSD_ERROR("short_soc_version is empty, package:%s", pkgName.c_str());
     421            2 :             return false;
     422              :         } else {
     423            1 :             fileDirWholePath = fileDirWholePath + shortSocVersion + "/";
     424              :         }
     425              :     }
     426           13 :     tempNode.hostTruePath = GetHostFilePath(fileDirWholePath, pkgName);
     427           13 :     TSD_INFO("get package:%s host real path:%s", pkgName.c_str(), tempNode.hostTruePath.c_str());
     428           13 :     return true;
     429           15 : }
     430              : 
     431            0 : std::string PackageProcessConfig::GetPackageHostTruePath(const std::string& pkgName)
     432              : {
     433            0 :     const std::lock_guard<std::mutex> lk(configMut_);
     434            0 :     auto iter = configMap_.find(pkgName);
     435            0 :     if (iter != configMap_.end()) {
     436            0 :         return iter->second.hostTruePath;
     437              :     } else {
     438            0 :         return "";
     439              :     }
     440            0 : }
     441              : } // namespace tsd
        

Generated by: LCOV version 2.0-1