* Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Description: The flag used by command line.
*/
#ifndef DATASYSTEM_COMMON_FLAGS_FLAG_MANAGER_H
#define DATASYSTEM_COMMON_FLAGS_FLAG_MANAGER_H
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include "datasystem/common/flags/flags.h"
namespace datasystem {
class EmbeddedConfig;
class KVClientConfig;
* @brief Report error.
* @param[in] format Error message format.
*/
void ReportError(const char *format, ...);
class Flag {
public:
Flag(FlagType type, const std::string &name, const std::string meaning, const std::string &filename, void *curr,
void *def, bool modifiable = false)
: type_(type),
name_(name),
meaning_(meaning),
filename_(filename),
currentVal_(curr),
defaultVal_(def),
modified_(false),
modifiable_(modifiable),
validator_(nullptr)
{
}
~Flag() = default;
* @brief Assign value to flag.
* @param[in] value Value to be parsed and assigned.
* @param[out] errMsg Error message would be fill if error happen.
* @return True if assign success.
*/
bool Assign(const std::string &value, std::string &errMsg);
* @brief Check if flag value is validate via validator function.
* @param[in] vlaue Check value.
* @return True if value is validate.
*/
bool IsValidate(const void *value = nullptr) const;
* @brief Return type name.
* @return Type name.
*/
std::string TypeName() const;
* @brief Update modified flag.
*/
void UpdateModified();
* @brief Check if flag value is modified.
* @return True if flag value is modified.
*/
bool IsModified() const
{
return modified_;
}
* @brief Get value.
* @return Value string.
*/
std::string ValueString() const;
private:
friend class FlagManager;
* @brief Parse and assign value from boolean value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromBoolean(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from uint32 value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromUint32(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from int32 value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromInt32(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from uint64 value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromUint64(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from int64 value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromInt64(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from string value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromString(const std::string &value, std::string &errMsg);
* @brief Parse and assign value from double value.
* @param[in] value Value string.
* @param[out] Error message would be fill if error happen.
* @return True if assign success.
*/
bool ParseAssignFromDouble(const std::string &value, std::string &errMsg);
* @brief Return illegal value message.
* @param[in] value Value string.
* @return Illegal value message.
*/
std::string IllegalValueMessage(const std::string &value) const;
* @brief Return invalid value message.
* @param[in] value Value string.
* @return Invalid value message.
*/
std::string ValidateFailureMessage() const;
FlagType type_;
std::string name_;
std::string meaning_;
std::string filename_;
void *currentVal_;
void *defaultVal_;
bool modified_;
bool modifiable_;
bool wasSpecified_ = false;
void *validator_;
};
class FlagManager {
public:
~FlagManager() = default;
* @brief Get FlagManager single instance.
* @return FlagManager instance.
*/
static FlagManager *GetInstance();
* @brief Looks for flags in argv and parses them.
* @param[in] argc Command line argument counts.
* @param[in] argv Command line argument values.
*/
void ParseCommandLineFlags(int argc, char **argv);
* @brief Parse flags from name-value argument map.
* @param[in] args Flag name-value pairs.
* @param[out] errMsg Error message if parse failed.
* @return True on success; false otherwise.
*/
bool ParseCommandLineFlags(const std::unordered_map<std::string, std::string> &args, std::string &errMsg);
* @brief Parse flags from embedded worker config.
* @param[in] config Embedded worker config.
* @param[in] errMsg errMsg if prase failed.
* @return return true if parse success.
*/
bool ParseCommandLineFlags(const EmbeddedConfig &config, std::string &errMsg);
* @brief Parse flags from KV client config.
* @param[in] config KV client config.
* @param[in] errMsg errMsg if prase failed.
* @return return true if parse success.
*/
bool ParseCommandLineFlags(const KVClientConfig &config, std::string &errMsg);
* @brief Parse a JSON worker config file and apply flags.
* @details Validates path, reads and parses JSON, then calls ParseCommandLineFlags.
* @param[in] path Absolute path to the config file.
* @param[out] errMsg Error message if parse failed.
* @return True on success; false otherwise.
*/
bool ParseConfigFile(const std::string &path, std::string &errMsg);
* @brief Get program invocation short name.
* @return Program invocation short name.
*/
std::string ProgramInvocationShortName();
* @brief Register flag before main() execute.
* @param[in] name Flag name.
* @param[in] type Flag type.
* @param[in] meaning Flag description.
* @param[in] filename Flag defined filename.
* @param[in] currentVal Flag current value memory address.
* @param[in] defaultVal Flag default value memory address.
*/
void RegisterFlag(const std::string &name, FlagType type, const std::string &meaning, const std::string &filename,
void *currentVal, void *defaultVal, bool modifiable = false);
* @brief Register flag validator function before main() execute.
* @param[in] flag Flag current value memory address.
* @param[in] func Validator function.
*/
bool RegisterValidator(void *flag, void *func);
* @brief Find flag from flag map and try to assign value.
* @param[in] name Flag name.
* @param[in] value Need to be assigned value.
* @param[out] errMsg Error message if find or assign failed.
* @return True if find and assign success.
*/
bool FindAndAssignFlagValue(const char *name, const std::string &value, std::string &errMsg);
* @brief Find flag from flag map and get its value.
* @param[in] name Flag name.
* @param[out] output Flag value.
* @return True if flag found.
*/
bool FindAndGetFlagValue(const char *name, std::string &output);
* @brief Get all flags from flag map.
* @param[out] output Flag info list.
*/
void GetAllFlags(std::vector<FlagInfo> &output) const;
* @brief Check whether a flag was explicitly specified.
* @param[in] name Flag name.
* @return True if the flag exists and was explicitly set.
*/
bool WasFlagSpecified(const char *name) const;
* @brief Check whether a flag is marked modifiable at registration time.
* @param[in] name Flag name.
* @return True if the flag exists and is modifiable.
*/
bool IsModifiableFlag(const std::string &name) const;
* @brief Dry-run validation for a proposed flag value change.
* @param[in] name Flag name.
* @param[in] newVal Proposed new value string.
* @param[out] errMsg Error message if validation failed.
* @return True if the change would be accepted.
*/
bool ValidateChange(const std::string &name, const std::string &newVal, std::string &errMsg);
* @brief Collect names of all modifiable flags.
* @param[out] out Modifiable flag names.
*/
void GetModifiableFlagNames(std::vector<std::string> &out) const;
* @brief Set version.
* @param[in] version Version message.
*/
void SetVersionString(const std::string &version);
* @brief Set usage description.
* @param[in] description Usage description.
*/
void SetUsageMessage(const std::string &description);
private:
FlagManager() = default;
* @brief Check if need print helpful message or not.
* @param[in] argv0 Program name.
* @return True if need print helpful message.
*/
bool NeedPrintHelpfulMessage(const char *argv0);
* @brief Validate default flags.
*/
void ValidateDefaultFlagsLocked();
* @brief Parse flags from argument map. Caller must hold mutex_.
* @param[in] args Flag name-value pairs.
* @param[out] errMsg Error message if parse failed.
* @return True on success; false otherwise.
*/
bool ParseCommandLineFlagsFromArgsLocked(const std::unordered_map<std::string, std::string> &args,
std::string &errMsg);
* @brief Parse flag value.
* @param[in] arg Argument get from command line.
* @param[in] flag Flag name.
* @param[out] value Parsed value, null if value is not contained in arg.
*/
void ParseFlagValue(char *arg, std::string &flag, char **value);
* @brief Assign flag value.
* @param[in] flag Flag instance.
* @param[in] value Value need to be assigned.
*/
void AssignFlagValue(Flag &flag, const std::string &value);
* @brief Check if need report error.
* @brief if need to report err, get errmsg.
* @return Ture if need to report error.
*/
bool CheckAndReportErrors(std::string &errMsg) const;
struct FlagValueSnapshot;
bool readCurrentIntoSnapshot(const Flag &flag, FlagValueSnapshot &snapshot, const std::string &name,
std::string &errMsg) const;
void writeSnapshotIntoFlag(Flag &flag, const FlagValueSnapshot &snapshot) const;
bool tryAssignWithRollback(Flag &flag, const std::string &newVal, std::string &errMsg);
std::map<std::string, Flag> flagMap_;
std::map<void *, Flag *> flagPtrMap_;
std::map<std::string, std::string> errorFlags_;
std::map<std::string, std::string> unknownFlags_;
std::string version_;
std::string description_;
std::string argv0_{ "UNKNOWN" };
mutable std::mutex mutex_;
};
}
#endif