<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      配置模塊

      概述

      什么是配置?chatGPT是這么回答的:

      配置項(Configuration Item)是一個廣泛使用的術語,尤其在軟件開發、系統管理和IT服務管理中。它通常指的是系統或應用程序中的一個可配置的元素,可以用來調整系統或應用的行為、性能或其他特性。配置項可以是軟件、硬件、文檔、數據庫、參數設置等。

      配置項的用途

      • 定制化:通過調整配置項,可以讓同一軟件或系統在不同環境中運行時表現出不同的行為和特性。
      • 優化性能:通過修改配置參數,可以優化系統或應用程序的性能。
      • 提高安全性:配置安全參數和策略,增強系統或應用程序的安全性。
      • 簡化管理:通過集中管理和控制配置項,可以簡化系統或應用程序的管理和維護。

      Sylar使用YAML作為配置文件。最簡單的配置文件方式還是 .ini 那種,選擇YAML是因為易讀易寫,同時能支持復雜的數據結構。這里支持 STL 容器(vector, list, set, map 等等),支持自定義類型(但需要實現序列化和反序列化方法,也就是兩個仿函數)。YAML 語法快速簡單入門:https://www.runoob.com/w3cnote/yaml-intro.html

      在配置模塊中主要有以下幾個類:

      • class ConfigVarBase:配置變量的基類
      • class ConfigVar:配置參數模板子類,保存對應類型的參數值,通過仿函數實現string和T類型之間的相互轉化
      • class Config:ConfigVar的管理類

      最后將日志模塊與配置模塊整合起來,當配置文件相應參數做出改變時,能夠通過回調函數改變相應的參數。

      配置模塊實現了以下功能:

      • 支持yaml格式的配置文件解析
      • 使用模板完成基礎類型,復雜類型(vector、map、set等),自定義類型的序列化與反序列化
      • 利用回調機制,在加載配置時,完成配置的更新
      • 使用yaml-cpp庫,實現配置文件讀取
      • 約定大于配置

      詳解

      配置變量的基類 class ConfigVarBase

      虛基類。包含配置名稱和配置描述兩個屬性。提供 toString() 和 fromString() 兩個純虛函數將參數值轉換成 YAML String 和從 YAML String 轉成參數的值。

      // 名字
      std::string m_name;
      // 描述
      std::string m_description;
      
      virtual std::string toString() = 0; //轉化為string
      virtual bool fromString(const std::string& val) = 0;    //從string轉化為相應類型
      virtual std::string getTypeName() const = 0;    //獲得該類型的名稱
      
      ConfigVarBase(構造函數 )

      std::transform被用于將字符串m_name中的字母字符轉換為小寫形式并覆蓋原來的字符串。所以不區分大小寫

      ConfigVarBase(const std::string& name, const std::string &description = "")
              : m_name(name)
              , m_description(description)  {
              std::transform(m_name.begin(), m_name.end(), m_name.begin(), ::tolower);
          }
      

      配置參數 class ConfigVar

      /* 
       *  T 參數的具體類型
       *  FromStr 從std::string轉換成T類型的仿函數
       *  ToStr 從T轉換成std::string的仿函數
       *  std::string 為YAML格式的字符串
       */
      template <class T, class FromStr = LexicalCast<std::string, T>
                      , class ToStr = LexicalCast<T, std::string> >
      class ConfigVar : public ConfigVarBase {};
      
      • 對于每種類型的配置,在對應的 ConfigVar 模板類實例化時都要提供其 FromStr 和 ToStr 兩個仿函數,用于實現該類型和 YAML 字符串的相互轉換。
      • 配置參數模板子類。繼承自 ConfigVarBase。
      • 保存對應類型 T 的參數值。
      • 根據不同的非內置基本類型 T,FromStr 和 ToStr 具有不同的模板偏特化實現。
      • 內含一個 std::map,存放配置變更的回調函數。
        提供 setValue() 和 getValue() 函數,其中在 setValue() 函數中,會調用 std::map 中存放的所有回調函數進行通知配置變更。
      • 關于回調函數,提供 addListener()、delListener()、getListener()、clearListener() 四個函數給外界使用。
        其中,FromStr和ToStr使用仿函數片特化的方式,實現不同類型T與string之間的相互轉化,例如vector與string之間的轉化,在轉化的過程中,字符串格式都是以YAML為標準。
      //F from_type, T to_type
      template<class F, class T>
      class LexicalCast {
      public:
          T operator() (const F &v) {
              return boost::lexical_cast<T>(v);
          }
      };
      ?
      // string To vector
      // "[1, 2, 3]" ——> [1, 2, 3]
      template<class T>
      class LexicalCast<std::string, std::vector<T>> {
      public:
          std::vector<T> operator() (const std::string& v) {
              YAML::Node node = YAML::Load(v);
              typename std::vector<T> vec;
              std::stringstream ss;
              for (size_t i = 0; i < node.size(); ++i) {
                  ss.str("");
                  ss << node[i];
                  vec.push_back(LexicalCast<std::string, T>()(ss.str()));
              }
              return vec;
          }
      };
      ?
      // vector To string
      // [1, 2, 3] ——> - 1
      //               - 2
      //               - 3             
      template<class T>
      class LexicalCast<std::vector<T>, std::string> {
      public:
          std::string operator() (const std::vector<T>& v) {
              YAML::Node node;
              for (auto& i : v) {
                  node.push_back(YAML::Load(LexicalCast<T, std::string>()(i)));
              }
              std::stringstream ss;
              ss << node;
              return ss.str();
          }
      };
      
      

      mumber(成員變量)

          // 參數值
          T m_val;
          // 變更回調函數組, uint64_t key(要求唯一,一般可以用hash)
          // typedef std::function<void(const T &old_value, const T &new_value)> on_change_cb;
          std::map<uint64_t, on_change_cb> m_cbs;
          // 讀寫鎖
          mutable RWMutexType m_mutex;
      

      函數

      // 構造函數
      // 給配置名、描述、參數值賦值
      ConfigVar(const std::string& name
              , const T& defult_val
              , const std::string& description = "")
          : ConfigVarBase(name, description)
          , m_val(defult_val) {
      ?
          }
      
      // toString(從參數轉為string)
      // 若成功,返回轉化后的string,失敗打出日志,異常以及值的類型
      std::string toString() override {
          try{
              RWMutexType::ReadLock lock(m_mutex);
              return ToStr()(m_val);
          }
          catch (std::exception &e)
          {
              SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ConfigVar::toString exception"
                  << e.what() << "convert: " << typeid(m_val).name() << "to String";
          }
          return "";
      }
      
      // fromString(從string轉為值)
      // 從YAML String轉為參數值,失敗打出日志,異常以及值的類型
      bool fromString(const std::string& val) override {
          try {
              setValue(FromStr()(val));
          }
          catch (std::exception &e)
          {
              SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ConfigVar::fromString exception "
                  << e.what() << " convert: String to " << typeid(m_val).name()
                  << " - " << val;
          }
          return false;
      }
      
      // getValue(獲取)和setValue(設置參數)
      // 獲取參數直接返回m_val,設置參數時,判斷v與m_val是否相同,若相同,直接返回,若不相同,則回調變更函數
      // 獲取參數
      const T getValue() const {
          RWMutexType::ReadLock lock(m_mutex);
          return m_val;
      }
      ?
      // 設置參數
      void setValue(const T& v) {
          {
              RWMutexType::ReadLock lock(m_mutex);
              if (v == m_val) {
                  return;
              }
              for (auto& i : m_cbs) {
                  i.second(m_val, v);
              }
          }
          RWMutexType::WriteLock lock(m_mutex);
          m_val = v;
      }
      
      // addListener(添加變化回調函數)
      // 返回該回調函數對應的唯一id,用于刪除回調函數
      uint64_t addListener(on_change_cb cb) {
          static uint64_t s_fun_id = 0;
          RWMutexType::WriteLock lock(m_mutex);
          ++s_fun_id;
          m_cbs[s_fun_id] = cb;
      ?
          return s_fun_id;
      }
      
      // delListener(刪除回調函數)
      void delListener(uint64_t key) {
          RWMutexType::WriteLock lock(m_mutex);
          m_cbs.erase(key);
      }
      
      // getListener(獲取回調函數)
      on_change_cb getListener(uint64_t key) {
          RWMutexType::ReadLock lock(m_mutex);
          auto it = m_cbs.find(key);
          return it == m_cbs.end() ? nullptr : it->second;
      }
      
      // clearListener(清除回調函數)
      void clearListener() {
          RWMutexType::WriteLock lock(m_mutex);
          m_cbs.clear();
      } 
      

      ConfigVar管理類 Config

      Config是ConfigVar的管理類,用來管理全部的ConfigVar全特化后的對象。他通過單例模式進行管理,整個服務進程只有一個對象。

      沒有任何靜態成員變量,通過GetDatas函數內的靜態的map進行管理,以及用GetMutex函數內的靜態的鎖加解鎖。

      Lookup函數用于創建或獲取對應參數名的配置參數。傳入三個參數,字符串形式的配置參數名稱,T類型的參數默認值,字符串形式的參數描述。首先判斷是否存在參數名稱的配置,若存在,則從map中取出這個配置項(ConfigVarBase類型的指針,指向了ConfigVar的某個全特化的類的對象)。并且通過dynamic_pointer_cast,轉換成ConfigVar類型的智能指針。若tmp為nullptr的話,說明map中存在著相同名字的配置項,但是map中配置項的參數類型和傳入的默認值的參數默認值不一樣,返回nullptr,否則就返回正確的配置參數。接著判斷參數名是否包含非法字符,存在就拋出一個異常。然后創建一個ConfigVar類型的指針指向的ConfigVar類型的對象,添加到map中。

      還有一個重載的Lookup函數用于查找配置參數,傳入配置參數名稱,返回對應配置參數名稱的配置參數。若不存在或者類型錯誤的話,都會返回nullptr。

      LoadFromYaml函數用于使用yaml初始化配置模塊,參數傳入一個yaml對象。函數內有名為ListAllMember的函數,采用類似遍歷二叉樹的方式遍歷。

      LoadFromConfDir用于加載path文件夾里面的配置文件。

      LookupBase用于返回配置參數的基類(他跟上面的Lookup的區別是一個返回ConfigVar類型的指針,一個返回基類指針)。

      Visit函數用于遍歷配置模塊里面所有配置項,并且將配置項作為傳入函數的參數進行執行。

      用法如下:

      sylar::ConfigVar<int>::ptr g_int_value_config = sylar::Config::Lookup("system.port", (int)8080, "system port");
        				|
      				|
      			   \|/
      SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before: " << g_int_value_config->getValue();
        				|
      				|
      			   \|/
      YAML::Node root = YAML::LoadFile("/home/sylar/workspace/sylar/bin/conf/test.yml");
      sylar::Config::LoadFromYaml(root);
      				|
      				|
      			   \|/
      SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after: " << g_int_value_config->getValue();
      

      成員變量:

      // typedef std::unordered_map<std::string, ConfigVarBase::ptr> ConfigVarMap;
      // 返回所有的配置項
      static ConfigVarMap& GetDatas() {
          static ConfigVarMap s_datas;
          return s_datas;
      }
      ?
      // 配置項的RWMutex
      static RWMutexType& GetMutex() {
          static RWMutexType s_mutex;
          return s_mutex;
      }
      

      Lookup(獲取/創建對應參數名的配置參數)

      template<class T>
      static typename ConfigVar<T>::ptr Lookup(const std::string& name
              , const T& default_value, const std::string& description = "") {
              RWMutexType::WriteLock lock(GetMutex());
              auto it = GetDatas().find(name);
              // 找到了
              if (it != GetDatas().end()) {
                  // 將ConfigVarBase轉換為ConfigVar
                  auto tmp = std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
                  // 若轉換成功,顯示顯示成功
                  if (tmp) {
                      SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exists";
                      return tmp;
                  }   else {
                      SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exitst but type not "
                                                        << typeid(T).name() << ", real_type = " << it->second->getTypeName()
                                                        << " " << it->second->toString();
                      return nullptr;
                  }
              }
          
              // 用于在當前字符串中查找第一個不屬于指定字符集合的字符,并返回該字符位置的索引。如果沒有找到任何字符,則返回 std::string::npos。
              // name不全在 "abcdefghigklmnopqrstuvwxyz._012345678" 中 
              // name中有非法字符,拋出異常
              if (name.find_first_not_of("abcdefghigklmnopqrstuvwxyz._012345678")
                      != std::string::npos) {
                  SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "Lookup name invalid" << name;
                  throw std::invalid_argument(name);
              }
              
              // 若沒有,則創建一個新的ConfigVar
              // typename:用于告訴編譯器 ConfigVar<T>::ptr 是一個類型而不是成員變量。
              typename ConfigVar<T>::ptr v(new ConfigVar<T>(name, default_value, description));
              GetDatas()[name] = v;
              return v;
      }
      

      Lookup(查找配置參數)

      template<class T>
      static typename ConfigVar<T>::ptr Lookup(const std::string& name) {
              RWMutexType::ReadLock lock(GetMutex());
              auto it = GetDatas().find(name);
              if (it == GetDatas().end()) {
                  return nullptr;
              }
              return std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
      }
      

      LookupBase(查找配置參數,返回配置參數的基類)

      ConfigVarBase::ptr Config::LookupBase(const std::string& name) {
          RWMutexType::ReadLock lock(GetMutex());
          auto it = GetDatas().find(name);
          return it == GetDatas().end() ? nullptr : it->second;
      }
      

      LoadFromYaml(使用YAML::Node初始化配置模塊)

      // 遞歸方式,遍歷YAML格式的配置文件中的所有成員,將每個節點的名稱和值存在list中
      static void ListAllMember(const std::string& prefix,
                                const YAML::Node& node,
                                std::list<std::pair<std::string, const YAML::Node> >& output) {
          // prefix字符不合法
          if (prefix.find_first_not_of("abcdefghigklmnopqrstuvwxyz._012345678") 
                  != std::string::npos) {
              SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "Config invalid name: " << prefix << " ! " << node;
              return;
          }
          output.push_back(std::make_pair(prefix, node));
          // 若解析的是map
          if (node.IsMap()) {
              for (auto it = node.begin();
                       it != node.end(); ++it) {
                  // 若前綴為空,說明為頂層,prefix為key的值,否則為子層,prefix為父層加上當前層。it->second為當前node
                  ListAllMember(prefix.empty() ? it->first.Scalar() : prefix + "." + it->first.Scalar(), it->second, output);
              }
          }
      }
      ?
      void Config::LoadFromYaml(const YAML::Node& root) {
          // 將root中的所有節點信息保存到all_nodes中
          std::list<std::pair<std::string, const YAML::Node> > all_nodes;
          ListAllMember("", root, all_nodes);
          
          // 遍歷list
          for(auto &i : all_nodes) {
              std::string &key = i.first;
              if (key.empty()) {
                  continue;
              }
              
              // 無視大小寫
              std::transform(key.begin(), key.end(), key.begin(), ::tolower);
              // 查找名為key的配置參數
              ConfigVarBase::ptr var = LookupBase(key);
              // 若找到
              if (var) {
                  // 若為純量,則調用fromString(會調用setValue設值)
                  if (i.second.IsScalar()) {
                      var->fromString(i.second.Scalar());
                  // 否則為數組,將其轉換為字符串
                  } else {
                      std::stringstream ss;
                      ss << i.second;
                      var->fromString(ss.str());
                  }
              }
          }
      }
      

      Visit(遍歷配置模塊里面所有配置項)

      void Config::Visit(std::function<void(ConfigVarBase::ptr)> cb) {
          RWMutexType::ReadLock lock(GetMutex());
          ConfigVarMap& m = GetDatas();
          for (auto it = m.begin();
               it != m.end(); ++it) {
              cb(it->second);
          }
      }
      
      posted @ 2024-05-28 15:32  機械心  閱讀(72)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 一区二区三区成人| 国产成人精品久久性色av| 仪征市| 久久一级精品久熟女人妻| 亚洲午夜无码久久久久蜜臀av| 固阳县| 久久国产自拍一区二区三区| 99精品偷自拍| 国产午夜福利精品片久久| 汾阳市| 无码福利写真片视频在线播放| 资源在线观看视频一区二区| 成人无码午夜在线观看| 中国少妇人妻xxxxx| 精品亚洲没码中文字幕| 国产亚洲另类无码专区| 花式道具play高h文调教| 日韩欧美aⅴ综合网站发布| 午夜AAAAA级岛国福利在线| 国产熟女老阿姨毛片看爽爽| 九九热爱视频精品| 老熟妇仑乱换频一区二区| 国产精品午夜福利资源| 一区二区三区在线 | 欧洲| 景东| 国产午夜福利在线观看播放| 亚洲精品日韩中文字幕| 成人午夜av在线播放| 久久精品国产99国产精品严洲 | 亚洲国产一成人久久精品| 欧美性受xxxx黑人猛交| 日韩福利片午夜免费观着| 精品中文人妻中文字幕| 亚洲一区在线成人av| 亚洲精品久久久久国色天香| 在线播放国产女同闺蜜| 搡老女人老妇女老熟妇| 久久香蕉国产线看观看猫咪av| 中文字幕在线无码一区二区三区| 枣强县| 中文字幕有码日韩精品|