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 : #ifndef HCOMM_BASE_CONFIG_H
12 : #define HCOMM_BASE_CONFIG_H
13 :
14 : #include <cstdint>
15 : #include <cstdlib>
16 : #include <functional>
17 : #include <mutex>
18 : #include <string>
19 : #include <utility>
20 : #include <exception>
21 : #include <vector>
22 : #include <algorithm>
23 : #include <atomic>
24 : #include <cctype>
25 : #include <limits>
26 : #include <stdexcept>
27 : #include <type_traits>
28 :
29 : #include "log.h"
30 : #include "adapter_error_manager_pub.h"
31 : #include "hccl_types.h"
32 :
33 : namespace hcomm {
34 :
35 : /**
36 : * @brief 获取环境变量并立即拷贝为 std::string,封装 getenv 的不可重入风险。
37 : */
38 59 : inline std::string GetEnv(const char* name)
39 : {
40 59 : if (name == nullptr) {
41 0 : return std::string();
42 : }
43 59 : const char* val = getenv(name);
44 59 : if (val == nullptr) {
45 41 : return std::string();
46 : }
47 36 : return std::string(val);
48 : }
49 :
50 : /*------------------- 通用解析器与校验器 -------------------
51 : * 新增环境变量字段时,直接复用这些模板,无需为每种类型手写 static 方法。
52 : * 例如:
53 : * EnvField<uint32_t> myField{"MY_ENV", 10, StrToNum<uint32_t>, MakeRangeValidator(0U, 31U)};
54 : * EnvField<uint8_t> myField2{"MY_ENV2", 0, StrToNum<uint8_t>};
55 : *------------------------------------------------------------------------------------------------*/
56 :
57 : /// 通用字符串→整数解析器:先检查全数字,再调用 std::stoul。
58 : /// 对 EnvField<uint32_t>::Parser (返回 T, bool& parseOk) 签名适配。
59 : template <typename T>
60 16 : typename std::enable_if<std::is_integral<T>::value, T>::type StrToNum(const std::string& s, bool& parseOk)
61 : {
62 16 : if (s.empty() || !std::all_of(s.begin(), s.end(), [](unsigned char c) {
63 24 : return ::isdigit(c) != 0;
64 : })) {
65 5 : parseOk = false;
66 5 : return T{};
67 : }
68 : try {
69 11 : unsigned long val = std::stoul(s);
70 11 : if (val > std::numeric_limits<T>::max()) {
71 0 : parseOk = false;
72 0 : return T{};
73 : }
74 11 : parseOk = true;
75 11 : return static_cast<T>(val);
76 0 : } catch (const std::exception&) {
77 0 : parseOk = false;
78 0 : return T{};
79 : }
80 : }
81 :
82 : /// 通用闭区间校验器工厂。
83 : /// 返回 EnvField<T>::Validator 签名 (bool(const T&)) 的 lambda。
84 : template <typename T>
85 6 : typename std::function<bool(const T&)> MakeRangeValidator(T min, T max)
86 : {
87 6 : return [min, max](const T& v) -> bool {
88 11 : return v >= min && v <= max;
89 6 : };
90 : }
91 :
92 : /// 环境变量错误上报(输出 HCCL_ERROR + RPT_ENV_ERR),返回错误码。
93 : /// 不抛异常,由调用方逐层返回错误码。
94 : HcclResult ReportEnvError(const char* envName, const std::string& envValue, const std::string& reason);
95 :
96 : /**
97 : * @brief 轻量环境变量字段,独立实现。
98 : *
99 : * 每个字段自包含:环境变量名、默认值、解析器、校验器。
100 : * Parse() 负责 getenv + 解析 + 校验,失败时输出 HCCL_ERROR 日志并返回错误码。
101 : */
102 : template <typename T>
103 : class EnvField {
104 : public:
105 : using Parser = std::function<T(const std::string&, bool&)>;
106 : using Validator = std::function<bool(const T&)>;
107 :
108 7 : EnvField(const char* name, T defaultValue, Parser parser, Validator validator = nullptr)
109 7 : : name_(name),
110 7 : value_(std::move(defaultValue)),
111 7 : defaultValue_(std::move(defaultValue)),
112 7 : parser_(std::move(parser)),
113 14 : validator_(std::move(validator))
114 7 : {}
115 :
116 59 : HcclResult Parse()
117 : {
118 59 : std::string envStr = GetEnv(name_);
119 59 : if (envStr.empty()) {
120 42 : isSetByEnv_ = false;
121 42 : value_ = defaultValue_;
122 42 : return HCCL_SUCCESS;
123 : }
124 17 : if (!parser_) {
125 2 : return ReportEnvError(name_, envStr, "no parser function is assigned.");
126 : }
127 16 : bool parseOk = false;
128 16 : T parsed = parser_(envStr, parseOk);
129 16 : if (!parseOk) {
130 10 : return ReportEnvError(name_, envStr, "is invalid, parse failed.");
131 : }
132 11 : if (validator_ && !validator_(parsed)) {
133 6 : return ReportEnvError(name_, envStr, "is out of range.");
134 : }
135 8 : isSetByEnv_ = true;
136 8 : value_ = std::move(parsed);
137 8 : return HCCL_SUCCESS;
138 59 : }
139 :
140 69 : const T& Get() const { return value_; }
141 : bool IsSetByEnv() const { return isSetByEnv_; }
142 50 : const char* GetSource() const { return isSetByEnv_ ? "environment" : "default"; }
143 :
144 : private:
145 : const char* name_;
146 : T value_;
147 : T defaultValue_;
148 : bool isSetByEnv_{false};
149 : Parser parser_;
150 : Validator validator_;
151 : };
152 :
153 : /**
154 : * @brief RDMA 相关环境变量配置。
155 : *
156 : */
157 : class EnvRdmaConfig {
158 : public:
159 : HcclResult GetTaCtpUbTimeOut(uint32_t& value);
160 : HcclResult GetTaRtpUbTimeOut(uint32_t& value);
161 : HcclResult GetTaRtpUboeTimeOut(uint32_t& value);
162 : void ResetParsed();
163 :
164 : private:
165 : HcclResult EnsureParsed();
166 : // 默认值与范围
167 : static constexpr uint32_t TA_CTP_UB_TIMEOUT_DEFAULT = 8; // CTP UB默认TIMEOUT为8(对应4s)
168 : static constexpr uint32_t TA_RTP_UB_TIMEOUT_DEFAULT = 16; // RTP UB默认TIMEOUT为16(对应8s)
169 : static constexpr uint32_t TA_RTP_UBOE_TIMEOUT_DEFAULT = 16; // RTP UBOE默认TIMEOUT为16(对应8s)
170 : static constexpr uint32_t UB_TIMEOUT_MIN = 0; // UB/UBOE TIMEOUT最小值为0
171 : static constexpr uint32_t UB_TIMEOUT_MAX = 31; // UB/UBOE TIMEOUT最大值为31
172 :
173 : // 环境变量字段(解析器与校验器复用通用模板)
174 : EnvField<uint32_t> taCtpUbTimeOut_{
175 : "HCOMM_TA_CTP_UB_TIMEOUT", TA_CTP_UB_TIMEOUT_DEFAULT, StrToNum<uint32_t>,
176 : MakeRangeValidator(UB_TIMEOUT_MIN, UB_TIMEOUT_MAX)};
177 : EnvField<uint32_t> taRtpUbTimeOut_{
178 : "HCOMM_TA_RTP_UB_TIMEOUT", TA_RTP_UB_TIMEOUT_DEFAULT, StrToNum<uint32_t>,
179 : MakeRangeValidator(UB_TIMEOUT_MIN, UB_TIMEOUT_MAX)};
180 : EnvField<uint32_t> taRtpUboeTimeOut_{
181 : "HCOMM_TA_RTP_UBOE_TIMEOUT", TA_RTP_UBOE_TIMEOUT_DEFAULT, StrToNum<uint32_t>,
182 : MakeRangeValidator(UB_TIMEOUT_MIN, UB_TIMEOUT_MAX)};
183 :
184 : std::atomic<bool> isParsed_{false};
185 : std::mutex parseMutex_;
186 : };
187 :
188 : } // namespace hcomm
189 :
190 : #endif // HCOMM_BASE_CONFIG_H
|