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: 85.7 % 286 245
Test Date: 2026-08-12 11:03:52 Functions: 91.3 % 23 21

            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            4 : PackageProcessConfig::PackageProcessConfig()
      29           24 :     : configParaParseFuncMap_(
      30            0 :           {{"install_path", &PackageProcessConfig::ParseInstallPath},
      31            0 :            {"optional", &PackageProcessConfig::ParseOptionalFlag},
      32            0 :            {"package_path", &PackageProcessConfig::ParsePackagePath},
      33            8 :            {"load_as_per_soc", &PackageProcessConfig::ParseLoadAsPerSocFlag}})
      34            8 : {}
      35              : 
      36          358 : PackageProcessConfig* PackageProcessConfig::GetInstance()
      37              : {
      38          358 :     static PackageProcessConfig instance;
      39          358 :     return &instance;
      40              : }
      41              : 
      42           22 : PackConfDetail PackageProcessConfig::GetConfigDetailInfo(const std::string& srcPath)
      43              : {
      44           22 :     const std::lock_guard<std::mutex> lk(configMut_);
      45           22 :     const auto iter = configMap_.find(srcPath);
      46           22 :     if (iter != configMap_.end()) {
      47           21 :         return iter->second;
      48              :     } else {
      49            1 :         return PackConfDetail();
      50              :     }
      51           22 : }
      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           66 : std::string PackageProcessConfig::GetHostFilePath(const std::string& fileDir, const std::string& fileName) const
      97              : {
      98           66 :     std::string configPath;
      99           66 :     GetScheduleEnv("ASCEND_HOME_PATH", configPath);
     100           66 :     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           66 :     configPath = configPath + "/" + fileDir;
     106           66 :     if (access(configPath.c_str(), F_OK) != 0) {
     107           17 :         TSD_RUN_WARN("cannot get package path:%s, reason:%s", configPath.c_str(), SafeStrerror().c_str());
     108           34 :         return "";
     109              :     }
     110           49 :     configPath = configPath + fileName;
     111           49 :     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           49 :     TSD_INFO("get config path:%s", configPath.c_str());
     116           49 :     return configPath;
     117           66 : }
     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            0 :         TSD_INFO("config already set, skip parse");
     130            0 :         return TSD_OK;
     131              :     }
     132              : 
     133            8 :     std::ifstream inFile(conFile);
     134            8 :     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           16 :     const ScopeGuard fileGuard([&inFile]() { inFile.close(); });
     139              : 
     140            8 :     std::string inputLine;
     141            8 :     size_t itCnt = 0;
     142           76 :     while (getline(inFile, inputLine) && itCnt < MAX_CONFIG_NUM) {
     143           70 :         TSD_INFO("read config data current line:%s", inputLine.c_str());
     144           70 :         std::string packageName;
     145           70 :         const size_t pos = inputLine.find(PACKAGE_CONFIG_NAME);
     146           70 :         if (pos != std::string::npos) {
     147           58 :             packageName = inputLine.substr(pos + PACKAGE_CONFIG_NAME.size());
     148           58 :             Trim(packageName);
     149           58 :             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           57 :             if (configMap_.find(packageName) == configMap_.end()) {
     155           54 :                 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           56 :             itCnt++;
     162              :         }
     163           70 :     }
     164            6 :     finishParse_ = true;
     165            6 :     return TSD_OK;
     166            8 : }
     167              : 
     168          227 : bool PackageProcessConfig::ParseSinglePara(
     169              :     std::string& inputLine, PackConfDetail& tempNode, std::unordered_set<std::string>& finishedParseItemSet) const
     170              : {
     171          227 :     const std::size_t pos = inputLine.find(":");
     172          227 :     if (pos == std::string::npos) {
     173            1 :         TSD_ERROR("invalid config line:%s", inputLine.c_str());
     174            1 :         return false;
     175              :     }
     176          226 :     std::string key = inputLine.substr(0, pos);
     177          226 :     Trim(key);
     178          226 :     std::string value = inputLine.substr(pos + 1UL);
     179          226 :     Trim(value);
     180          226 :     const auto iter = configParaParseFuncMap_.find(key);
     181          226 :     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          225 :     if ((this->*(iter->second))(value, tempNode)) {
     186          224 :         finishedParseItemSet.insert(key);
     187          224 :         return true;
     188              :     }
     189            1 :     return false;
     190          226 : }
     191              : 
     192           58 : bool PackageProcessConfig::ParseInstallPath(const std::string& para, PackConfDetail& tempNode) const
     193              : {
     194           58 :     if ((para == "0") || (para == "1") || (para == "2") || (para == "3")) {
     195           57 :         int32_t result = 0;
     196           57 :         (void)TransStrToInt(para, result);
     197           57 :         tempNode.decDstDir = static_cast<DeviceInstallPath>(result);
     198              :     } else {
     199            1 :         TSD_ERROR("invalid installPath:%s", para.c_str());
     200            1 :         return false;
     201              :     }
     202           57 :     return true;
     203              : }
     204              : 
     205           60 : bool PackageProcessConfig::ParseOptionalFlag(const std::string& para, PackConfDetail& tempNode) const
     206              : {
     207           60 :     if ((para == "true") || (para == "false")) {
     208           58 :         tempNode.optionalFlag = para == "true" ? true : false;
     209              :     } else {
     210            2 :         TSD_ERROR("invalid optionalFlag:%s", para.c_str());
     211            2 :         return false;
     212              :     }
     213           58 :     return true;
     214              : }
     215              : 
     216           58 : bool PackageProcessConfig::ParsePackagePath(const std::string& para, PackConfDetail& tempNode) const
     217              : {
     218           58 :     if (!para.empty()) {
     219           57 :         tempNode.findPath = para;
     220              :     } else {
     221            1 :         TSD_ERROR("invalid packagePath:%s", para.c_str());
     222            1 :         return false;
     223              :     }
     224           57 :     return true;
     225              : }
     226              : 
     227           57 : bool PackageProcessConfig::ParseLoadAsPerSocFlag(const std::string& para, PackConfDetail& tempNode) const
     228              : {
     229           57 :     if ((para == "true") || (para == "false")) {
     230           56 :         tempNode.loadAsPerSocFlag = para == "true" ? true : false;
     231              :     } else {
     232            1 :         TSD_ERROR("invalid loadAsPerSocFlag:%s", para.c_str());
     233            1 :         return false;
     234              :     }
     235           56 :     return true;
     236              : }
     237              : 
     238           57 : bool PackageProcessConfig::SetConfigDataOnHost(
     239              :     std::ifstream& inFile, const std::string& fileName, const std::string& pkgTitle)
     240              : {
     241           57 :     std::string inputLine;
     242           57 :     uint32_t itCnt = 0U;
     243           57 :     const uint32_t configItemNum = static_cast<uint32_t>(configParaParseFuncMap_.size());
     244           57 :     PackConfDetail tempNode = {};
     245           57 :     std::unordered_set<std::string> finishedParseItemSet;
     246          280 :     while ((itCnt < configItemNum) && (getline(inFile, inputLine))) {
     247          224 :         if (!ParseSinglePara(inputLine, tempNode, finishedParseItemSet)) {
     248            1 :             TSD_ERROR("parse config line failed:%s", inputLine.c_str());
     249            1 :             return false;
     250              :         }
     251          223 :         itCnt++;
     252              :     }
     253           56 :     if (finishedParseItemSet.size() != configItemNum) {
     254            1 :         TSD_ERROR("not all config items parsed");
     255            1 :         return false;
     256              :     }
     257           55 :     tempNode.validFlag = true;
     258              :     try {
     259           55 :         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           54 :         configMap_[fileName] = tempNode;
     264           54 :         tempNode.PrintfInfo(fileName);
     265           54 :         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           54 :     return true;
     271           57 : }
     272              : 
     273            7 : void PackageProcessConfig::ConstructPkgConfigMsg(HDCMessage& hdcMsg)
     274              : {
     275           64 :     for (auto iter = configMap_.begin(); iter != configMap_.end(); iter++) {
     276           57 :         SinkPackageConfig* curConf = hdcMsg.add_sink_pkg_con_list();
     277           57 :         curConf->set_package_name(iter->first);
     278           57 :         curConf->set_file_dec_dst_dir(static_cast<uint32_t>(iter->second.decDstDir));
     279              :         // 对于 compat plugin 包,附带 host 侧解析得到的 version/timestamp
     280           57 :         if (iter->second.decDstDir != DeviceInstallPath::COMPAT_PLUGIN_PATH) {
     281           56 :             continue;
     282              :         }
     283           11 :         std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     284           11 :         const auto verIt = hostPluginVersions_.find(iter->first);
     285           11 :         if (verIt == hostPluginVersions_.end() || verIt->second.Empty()) {
     286           10 :             continue;
     287              :         }
     288              : 
     289            1 :         PluginPackageVersionInfo* info = hdcMsg.add_host_plugin_versions();
     290            1 :         info->set_package_name(iter->first);
     291            1 :         info->set_version(verIt->second.version);
     292            1 :         info->set_timestamp(verIt->second.timestamp);
     293           11 :     }
     294              :     const std::string hashCode =
     295            7 :         CalFileSha256HashValue(GetHostFilePath(COMMON_SINK_PKG_CONFIG_DIR, COMMON_SINK_PKG_CONFIG_NAME));
     296              :     hdcMsg.set_package_config_hash_code(hashCode);
     297            7 :     TSD_INFO("set config hash code:%s", hashCode.c_str());
     298            7 : }
     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           13 : PluginPkgVersion PackageProcessConfig::GetHostPluginVersion(const std::string& pkgName)
     339              : {
     340           13 :     std::lock_guard<std::mutex> lock(hostPluginVersionMut_);
     341           13 :     const auto it = hostPluginVersions_.find(pkgName);
     342           13 :     if (it == hostPluginVersions_.end()) {
     343            6 :         return PluginPkgVersion{};
     344              :     }
     345            7 :     return it->second;
     346           13 : }
     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           20 : TSD_StatusT PackageProcessConfig::GetPkgHostAndDeviceDstPath(
     380              :     const std::string& pkgName, std::string& orgFile, std::string& dstFile, const pid_t hostPid)
     381              : {
     382           20 :     const PackConfDetail detailInfo = GetConfigDetailInfo(pkgName);
     383           20 :     orgFile = detailInfo.hostTruePath;
     384              : 
     385           20 :     if (orgFile.empty()) {
     386            2 :         if (!detailInfo.optionalFlag) {
     387            1 :             TSD_ERROR("cannot find package:%s", pkgName.c_str());
     388            1 :             return TSD_INTERNAL_ERROR;
     389              :         } else {
     390            1 :             TSD_INFO("cannot find package:%s", pkgName.c_str());
     391            1 :             return TSD_OK;
     392              :         }
     393              :     }
     394              : 
     395           18 :     dstFile = dstFile + "/" + std::to_string(hostPid) + "_" + pkgName;
     396           18 :     TSD_RUN_INFO("get orgFile:%s, dstFile:%s", orgFile.c_str(), dstFile.c_str());
     397           18 :     return TSD_OK;
     398           20 : }
     399              : 
     400           57 : bool PackageProcessConfig::SetPkgHostTruePath(
     401              :     PackConfDetail& tempNode, const std::string& pkgName, const std::string& pkgTitle) const
     402              : {
     403           57 :     const auto pos = pkgTitle.find(';');
     404           57 :     std::string packageTitle;
     405           57 :     std::string shortSocVersion;
     406           57 :     if (pos == std::string::npos) {
     407            3 :         packageTitle = pkgTitle;
     408              :     } else {
     409           54 :         packageTitle = pkgTitle.substr(0, pos);
     410           54 :         shortSocVersion = pkgTitle.substr(pos + 1UL);
     411              :     }
     412           57 :     std::string fileDirWholePath;
     413           57 :     if (pkgName.find("-aicpu_legacy.tar.gz") != std::string::npos) {
     414           17 :         fileDirWholePath = tempNode.findPath + "/" + packageTitle + "/aicpu/";
     415              :     } else {
     416           40 :         fileDirWholePath = tempNode.findPath + "/";
     417              :     }
     418           57 :     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           55 :     tempNode.hostTruePath = GetHostFilePath(fileDirWholePath, pkgName);
     427           55 :     TSD_INFO("get package:%s host real path:%s", pkgName.c_str(), tempNode.hostTruePath.c_str());
     428           55 :     return true;
     429           57 : }
     430              : 
     431            2 : std::string PackageProcessConfig::GetPackageHostTruePath(const std::string& pkgName)
     432              : {
     433            2 :     const std::lock_guard<std::mutex> lk(configMut_);
     434            2 :     auto iter = configMap_.find(pkgName);
     435            2 :     if (iter != configMap_.end()) {
     436            1 :         return iter->second.hostTruePath;
     437              :     } else {
     438            2 :         return "";
     439              :     }
     440            2 : }
     441              : } // namespace tsd
        

Generated by: LCOV version 2.0-1