【sylar服务器框架】配置系统:基础配置

定义一个基类ConfigVarBase 主要放置一些公用的属性
添加两个字段: m_name、m_description

class ConfigVarBase (
public : 
	typedef std::shared_ptr<ConfigVarBase> ptr;
	
	ConfigVarBase(const std::string& name , const std::string& decription = ""):m_name(name),m_description(description){
	std::transform(m_name.begin(),m_name.end(),::tolower);
	}
	virtual ~ConfigVarBase() {}
	const std::string& getName() const {return m_name;}
	const std::string& getDescription() const {return m_description;} 

	virtual std::string toString() = 0;
	virtual  bool fromString(const std::string& val) = 0;
	
protected:
	std::string m_name;
	std::string m_description;
)

定义配置项类ConfigVar
需要特别关注的方法是toString(),fromString()
它们都是虚方法,由该基类的具体子类来负责实现。
toString负责将配置信息转换为字符串
fromString负责从字符串中解析出配置

添加m_val的get/set方法

template<class T>
class ConfigVar: public ConfigVarBase{
public:
	typedef std::shared_ptr<ConfigVar> ptr;
	ConfigVar(const std::string& name, 
			  const std::string& description,
			  const T& default_val)
			  :ConfigVarBase(name,description),
			  m_val(default_val)
			  {};
			  
	std::string toString() override { 
		try{
			//利用boost中的lexical_cast<>,将m_val强转为string
			return boost::lexical_cast<std::string>(m_val);
		}catch(std::exception& e){
			//利用宏创建一条级别为ERROR的新日志
			LOG_ERROR(用LoggerMgr获取默认的日志器m_root) << e.what()<<" : "<< typeid(m_val).name() <<std::endl;
		}
		return "";
	}

	bool fromString(const std::string& val) override {
		try{
			//利用boost中的lexical_cast<>,将val强转为T
			m_val =  boost::lexical_cast<T>(val);
			return true;
		}catch(std::exception& e){
			//利用宏创建一条级别为ERROR的新日志
			LOG_ERROR(用LoggerMgr获取默认的日志器m_root) << e.what()<<" : "<< typeid(m_val).name() <<std::endl;
		}
		return false;
	}
private:
	T m_val;
};

给LogManager添加getRoot()方法,获取默认的日志器
并定义宏使得可直接返回LogMgr中的默认日志器 m_root

定义类Config (管理配置)

主要字段是一个Map类型的静态s_datas,其中KstringVConfigVarBase::ptr (需要额外初始化一下)
主要方法是两个静态的 lookUp()
其中一个lookup(配置名) 是根据名字在map中查找配置,找到就取出V,用dynamic_pointer_cast强转为ConfigVar类型的智能指针返回
另外一个lookup(配置名,默认值,描述) 是先根据名称查找,找到则返回;没找到则先利用find_first_not_of判断一下名字中是否含非法字符(只可以含字母数字_),若不含再用传入的默认值和描述字符串来创建一个新的配置加入map中,并返回。

修改ConfigVarBase的构造函数,将m_name转换成小写。 std::transform(s.begin(),s.end(),::tolower)
目的是为了在find_first_not_of() 中只传入小写字母即可,并且统一了配置名在系统内均是小写的

基于yaml的文件配置

安装➕配置:
下载库yaml-cpp,mkdir build && cd build && cmake && make install
后修改CMakeList:
include_directories( 配置为yaml-cpp所在路径 )

使用方式:#include <yaml-cpp/yaml.h>
1、加载yaml文件,返回节点Node对象

	YAML::Node  XX = YAML::LoadFile("yaml文件路径")

2、判断yaml节点类型
Node.IsScalar() 判断是否是简单类型。node.Scalar()
Node.IsMap() 是否是MAP类型 。被每个:分割的都是一个键值对:for(auto it = ...){ it->first /it->second}

KK: ......

Node.IsSequence() 以-开头的为数组的一项 node[i]

- A....
  xxx....
- B....
  yyy...  

MAP是KV对之集合;yaml中相同缩进的K:V对构成一个MAP类型的node
-开头到下一个同缩进-的一整块内容为数组中的一项
在这里插入图片描述

接下来为配置管理类Config添加一个重要方法loadFromYaml(const YAML::Node& root),从yaml文件中读取并形成配置项。

首先创建一个二元组pair<string,node>构成的list<>,称为all_nodes,用来放置yaml文件中的每个配置项。
将整个读取到的yaml文件作为根Node,开始递归重复以下操作:
1、检查节点的名称是否合法。若合法将其名称+NODE二元对放入all_nodes
2、若当前节点为MAP类型,使用迭代器遍历其每个元素,用当前MAP节点名 拼接点.`` key(比如:system.port)+ ->second 作为参数,对重复12过程
直到创建好了all_nodes这个二元组列表

lookupBase()函数从Config中的s_datas中查找出现在all_nodes中的每个配置项名称,只要存在就将其值second转换为字符串后交给ConfigVar中的fromString(),将字符串转换为配置项的值m_val


e.what() 返回const char* ,是产生异常的原因。 typeid(XX).name()
暂且理解为输出标识符XX的类型名

find_first_not_of("字符串")返回第一个不与字符串中的任何字符匹配的字符位置,若全都能匹配上,则返回std::string::nops

智能指针的向下转换,所谓向下就是基类 → \rightarrow 派生类,指向基类的智能指针 → \rightarrow 指向派生类的指针,需要使用:
dynamic_pointer_cast<派生类> (基类智能指针)

vim :sp XX ctrl+WW

临时切换到shell ctrl + z && fg

shell 在某目录的所有头文件中查找名为LoadFile的函数
find 路径 -name “*.h” | xargs grep "LoadFile"

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值