sylar高性能服务器-配置(P12-p14)内容记录

文章目录

    • p12:复杂类型解析
      • 一、方法函数
      • 二、结果展示
    • p13:复杂类型解析完善
      • 一、方法函数
      • 二、结果展示
    • p14:自定义类型解析
      • 一、方法函数
      • 二、小结

p12:复杂类型解析

​ 本节内容主要针对完了配置类中对于复杂类型的转换。之前只实现了基础类型之间的转换,而对于容器等复杂类型无法转换,所以本节实现了对于vectorstring之间的转换方式。

一、方法函数

ConfigVar

​ 之前由于只有基础类型转换,代码里面直接调用lexical_cast,这样做无法在传入复杂类型时进行解析。因此把lexical_cast的转化过程函数化,方便在外部针对特定类型的转化。

template<class T, class FromStr = LexicalCast<std::string, T>, class ToStr = LexicalCast<T, std::string>>
class ConfigVar : public ConfigvarBase {
public:
    typedef std::shared_ptr<ConfigVar> ptr;

    ConfigVar(const std::string& name, const T& default_value, const std::string& description = "") // 初始化配置名称、参数值以及参数描述
        :ConfigvarBase(name,description)
        ,m_val(default_value) {

        }
    std::string toString() override {   // 将参数值转换为string类型
        try {
            // return boost::lexical_cast<std::string>(m_val);
            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 "";
    }
    bool fromString(const std::string& val) override {  // 从string转换为参数值
        try {
            // m_val = boost::lexical_cast<T>(val);
            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();
        }
        return false;
    }

    const T getValue() const { return m_val; }
    void setValue(const T& v) { m_val = v; }

private:
    T m_val;
};

LexicalCast

​ 如果是int float等基础类型转化,使用下列函数,

// 基础类型转换 把F转换成T类型
template<class F, class T>
class LexicalCast {
public:
    T operator()(const F& v) {
        return boost::lexical_cast<T>(v);
    }
};

​ [string -> vector]。代码比较清楚,直接看注释就行。

// 复杂类型转换 偏特化[string -> vector]
template<class T>
class LexicalCast<std::string, std::vector<T>> {
public:
    std::vector<T> operator()(const std::string& v) {
        // 调用YAML中的load函数,接收一个string类型输入,将其转换成node结构
        YAML::Node node = YAML::Load(v);
        std::vector<T> vec;     // 定义结果vec
        std::stringstream ss;   // 使用字符串流来获取node中的每个string值
        for(size_t i = 0; i < node.size(); ++ i) {
            ss.str("");
            ss << node[i];
            vec.push_back(LexicalCast<std::string, T>()(ss.str())); // 这里相当于调用基础类型转换,如果传入的vec里面元素是int类型,那么就是string -> int
        }
        return vec;
    }
};

[vector -> string]

// 复杂类型转换 偏特化[vector -> string]
template<class T>
class LexicalCast<std::vector<T>, std::string> {
public:
    std::string operator()(const std::vector<T>& v) {
        // 定义一个node容器
        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();
    }
};

二、结果展示

​ 下面代自定义了一个配置参数项g_vec_value_config,输出后载入log.yml文件,更改了g_vec_value_config里面的元素值。


sylar::ConfigVar<std::vector<int>>::ptr g_vec_value_config = 
    sylar::Config::Lookup("system.vec", std::vector<int>{1,2,3}, "system vec");
void test_config() {
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << g_int_value_config->getValue(); 
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << g_float_value_config->toString();
    auto v = g_vec_value_config->getValue();
    auto res = g_vec_value_config->toString();
    std::cout << res << std::endl;
    for(auto& i : v) {
        SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << i;
    }
    YAML::Node root = YAML::LoadFile("/root/Web-learning/sylar/bin/conf/log.yml");
    sylar::Config::LoadFromYaml(root);
    v = g_vec_value_config->getValue();
    for(auto& i : v) {
        SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << i;
    }
    
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << g_int_value_config->getValue(); 
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << g_float_value_config->toString();
}

int main(int argc, char** argv) {
    // test_yaml();
    test_config();
    return 0;
}

image-20231213123210283

p13:复杂类型解析完善

​ 本节内容是对上一节STL容器的完善,新增了对list、map、set、unordered_map、unordered_set的支持。由于本节的代码内容和上一节比较重复,所以简单记录一下部分内容。

一、方法函数

map

​ 注意循环的迭代方式与vector等容器不同,然后目前对于map里面的类型只支持基本类型的转换,所以后期需要按我们目前做的方式让map里面的内容支持复杂类型。

template<class T>
class LexicalCast<std::string, std::map<std::string, T>> {
public:
    std::map<std::string, T> operator()(const std::string& v) {
        YAML::Node node = YAML::Load(v);
        std::map<std::string,T> vec;     
        for(auto it = node.begin(); it != node.end(); ++ it) {
            ss.str("");
            ss << it->second;
            vec.insert(std::make_pair(it->first.Scalar(), LexicalCast<std::string, T>()(ss.str()))); 
        }
        return vec;
    }
};

宏定义

​ 测试时代码重复比较大,通过下面两个宏函数简化。

#define XX(g_var,name,prefix) \
    { \
        auto v = g_var->getValue(); \
        for(auto& i : v) { \
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << #prefix " " #name ": " << i; \
        } \
    }

#define XX_M(g_var,name,prefix) \
    { \
        auto v = g_var->getValue(); \
        for(auto& i : v) { \
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << #prefix " " #name ": {" << i.first << " : " << i.second << "}"; \
        } \
    }

二、结果展示

image-20231213151855855

p14:自定义类型解析

​ 本节内容主要讲解了Config解析自定义类型,和上面两节一样,处理复杂类型或者自定义类型的关键是片特化函数LexicalCast,下面是一些简单比较记录。

一、方法函数

​ 之前代码在解析yml文件时,如果遇到相同key但是类型不同,会直接忽略。比如下列代码,key:system.port的值存在两种类型,当我们使用Config::Lookup(system.port)`查找时,不知道最后找到的是谁,所以程序应该在这里报错提示。

sylar::ConfigVar<int>::ptr g_int_value_config = 
    sylar::Config::Lookup("system.port", (int)8080, "system port");

sylar::ConfigVar<float>::ptr g_int_valuex_config = 
    sylar::Config::Lookup("system.port", (float)8080, "system port");

Lookup

​ 对该函数进行修改,核心思想就是利用dynamic_pointer_cast,如果相同key的类型不同,则会转换失败返回nullptr

auto it = s_datas.find(name); // 直接从配置容器中查找
        if(it != s_datas.end()) {
            auto tmp = std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
            if(tmp) {
                SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exists"; 
            } else {
                SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exists but type not " << typeid(T).name(); 
                return nullptr;
            }
        }

再次运行可以看到已经有了报错提示

image-20231213155114465

自定义类型

​ 以下我们定义了一个Person类,希望能从log.yml文件中解析出相应的配置项。

class Person {
public:
    std::string m_name;
    int m_age = 0;
    bool m_sex = 0;

    std::string toString() const {
        std::stringstream ss;
        ss << "[Person name = " << m_name
           << " age = " << m_age
           << " sex = " << m_sex
           << "]";
        return ss.str();
    }
};

​ 第一步肯定是去书写对应的片特化函数LexicalCast,函数里面的内容无非就是YAML::NODE类型与自定义类型之间的值传递。

namespace sylar {
// 复杂类型转换 偏特化[string -> Person]
template<>
class LexicalCast<std::string, Person> {
public:
    Person operator()(const std::string& v) {
        // 调用YAML中的load函数,接收一个string类型输入,将其转换成node结构
        YAML::Node node = YAML::Load(v);
        Person p;
        p.m_name = node["name"].as<std::string>();
        p.m_age = node["age"].as<int>();
        p.m_sex = node["sex"].as<bool>();
        return p;
    }
};

// 复杂类型转换 偏特化[Person -> string]
template<>
class LexicalCast<Person, std::string> {
public:
    std::string operator()(const Person& p) {
        // 定义一个node容器
        YAML::Node node;
        node["name"] = p.m_name;
        node["age"] = p.m_age;
        node["sex"] = p.m_sex;
        std::stringstream ss;
        ss << node;
        return ss.str();
    }
};
}

​ 来一个测试用例

// 1.自定义类型
sylar::ConfigVar<Person>::ptr g_person = 
    sylar::Config::Lookup("class.person", Person(), "system person");

// log.yml
class:
  person:
    name: ikun
    age: 25
    sex: true

​ 输出结果:

image-20231213202609316

自定义类型与STL的嵌套

​ 设计一些复杂的用例

// 2.自定义类型与STL嵌套
sylar::ConfigVar<std::map<std::string, Person>>::ptr g_person_map = 
    sylar::Config::Lookup("class.map", std::map<std::string, Person>(), "system map");
// 3.更加复杂的类型map<string,vector<Person>>
sylar::ConfigVar<std::map<std::string, std::vector<Person>>>::ptr g_person_vec_map = 
    sylar::Config::Lookup("class.vec_map", std::map<std::string,  std::vector<Person>>(), "system vec_map");
// log.yml
map:
    person1:
      name: ikun2
      age: 252
      sex: true
    person2:
      name: ikun3
      age: 152
      sex: false
  vec_map:
    vec1:
      - name: ikun
        age: 25
        sex: true
      - name: ikun2
        age: 252
        sex: true
    vec2:
      - name: ikun4
        age: 225
        sex: true
      - name: ikun21
        age: 2152
        sex: true

输出结果:

image-20231213203115964

二、小结

​ 整个配置模块到这基本完成,这几节的内容目的就是尽可能的去解析不同类型的配置内容,所以只要12节视频基本弄懂,后面两节的内容也没什么大问题。建议自己跟着视频写好代码后可以把解析过程每一步的内容打印出来,看和自己想的是否一样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/241869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVAEE-8-线程池

池 我们之前也接触过,比如说常量池,数据库连接池,线程池,进程池,内存池等等, 池的共性: 1.提前把要用的对象准备好 2.把用完的对象也不要立即释放,先留着以备下次使用 来提高效率!!! 最开始,进程能够解决并发编程的问题,因为频繁创建销毁进程的开销成本太大了,所以我们引…

【Jenkins】Centos环境安装Jenkins(通过docker安装)

通过docker环境安装Jenkins 参考官网 https://hub.docker.com/r/jenkins/jenkins/ 1、安装docker环境 # 删除已有安装包 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-…

正确看待鸿蒙不兼容Android,这不是趋势?

华为可能明年推出不兼容安卓的鸿蒙版本。11月20日&#xff0c;据澎湃新闻报道&#xff0c;一华为相关人士表示&#xff0c;推出时间还不确定&#xff0c;未来IOS、鸿蒙、安卓将为三个各自独立的系统。 稍早前据证券时报报道&#xff0c;有业内人士亦表示&#xff1a;“华为内部…

测试面试必备:HTTP请求和响应详解!

一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始&#xff0c;客户端按照指定的格式开始向服务端发送HTTP请求&#xff0c;服务端接收请求后&#xff0c;解析HTTP请求&#xff0c;处理完业务逻辑&#xff0c;最后返回一个HTTP的响应给客户端&#xff0c;HTTP的响应内容同…

Ubuntu与Windows通讯传输文件(FTP服务器版)(没用的方法,无法施行)

本文介绍再Windows主机上建立FTP服务器&#xff0c;并且在Ubuntu虚拟机上面访问Windows上FTP服务器的方法 只要按照上图配置就可以了 第二部&#xff1a;打开IIS管理控制台 右击网站&#xff0c;新建FTP站点。需要注意的一点是在填写IP地址的时候&#xff0c;只需要填写Window…

matlab操作方法(三)——matlab中的数字图像(读取、显示、保存)

数字图像是二维图像用有限数字数值像素的表示。通常像素在计算机中保存为二维整数数组的光栅图像&#xff0c;这些值经常用压缩格式进行传输和存储。 二值图像&#xff1a;图像中每个像素的亮度值仅可以取自0或1的图像&#xff0c;因此也称为1bit图像 灰度图像&#xff1a;图…

【数据结构】贪心算法

一.贪心算法的定义 贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;只做出在某种意义上的局部最优解。 贪心算法的结果是最优解的最好近似。 优点&#xff1a;简单&#xff0c;高效。 缺点&…

《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》阅读笔记

论文标题 《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》 利用选择性状态空间的线性时间序列建模 作者 Albert Gu 和 Tri Dao Albert Gu 来自卡内基梅隆大学机器学习系&#xff0c;Mamba 脱胎于 Albert Gu 的前作 S4 架构。 Tri Dao 来自普林斯顿…

赛氪为第五届全球校园人工智能算法精英大赛决赛提供技术支持

12月10日&#xff0c;以“智青春算未来”为主题的2023年第五届全球校园人工智能算法精英大赛全国总决赛在河海大学江宁校区举行。本次大赛由江苏省人工智能学会主办&#xff0c;自9月份启动以来&#xff0c;共吸引了全国近400所高校的3000多支参赛团队参加。经过校赛、省赛选拔…

C语言:高精度除法(除低精度)

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 由图知&#xff0c;被除数的上一位的余数乘10加这位就是这一位结果的除数。 c[i] (d * 10 a[i]) / b #include<stdio.h> #include<string.h> char x[50005];//存储被除数&#xff0c;转为字符…

二百一十七、Flume——Flume拓扑结构之聚合的开发案例(亲测,附截图)

一、目的 对于Flume的聚合拓扑结构&#xff0c;进行一个开发测试 二、聚合 &#xff08;一&#xff09;结构含义 这种模式是我们最常见的&#xff0c;也非常实用。日常web应用通常分布在上百个服务器&#xff0c;大者甚至上千个、上万个服务器产生的日志&#xff0c;处理起来…

Java基础:如何创建多层文件夹

一、单层多个 代码实现如下&#xff1a; public class Main {public static void main(String[] args) {//在D盘中创建File file new File("D:"File.separator"docum");file.mkdir();//在D盘中的docum目录中创建file new File("D:\\docum" Fi…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

Vue表格自定义合计、小计功能

一、合计 <template> <avue-crud:option"optiondata":table-loading"loading":data"testdata":page.sync"page":span-method"spanMethod"ref"cruddata"current-change"currentChangedata"si…

Unity | Shader基础知识(第四集:Shader结构体)

一、本节介绍 上一集&#xff0c;我们做了一个案例&#xff0c;这一集&#xff0c;我们继续讲一个语法&#xff0c;在shader里写结构体。 二、结构体的需求 1.shader里是不好随便去声明数据的&#xff0c;我们前面传入数据时&#xff0c;用的是括号传入&#xff08;如图&…

Redis怎么测?这篇文章写的太全了

Redis是一个高性能、内存数据库和缓存系统&#xff0c;在开发和生产环境中被广泛应用。本文将介绍如何进行有效的Redis软件测试&#xff0c;以确保其稳定性、高性能和可靠性。 Redis作为一种非关系型数据库和缓存系统&#xff0c;被广泛用于支持高流量、低延迟的应用。为了保证…

iic应用篇

一.iic的优点 1. IIC总线物理链路简单&#xff0c;硬件实现方便&#xff0c;扩展性非常好&#xff08;1个主机控制器可以根据需求增加从机数量&#xff0c;同时删减从机数量也不会影响总线通信&#xff09;&#xff1b;IIC总线只需要SDA和SCL两条信号线&#xff0c;相比于PCI/…

锂电池基础知识及管理方式总结

这两天在排查一个锂电池无法充电的问题&#xff0c;用的是电池管理芯片BQ25713&#xff0c;网上相关的资料也很少&#xff0c;查看数据手册时&#xff0c;里面也有很多术语参数等不是很理解&#xff0c;所以&#xff0c;在此对锂电池的基础知识做个简单的总结&#xff0c;方面后…

详解Django+Vue+Docker搭建接口测试平台实战

一. 开头说两句 正好接口自动化测试平台需要迁移到新的测试服务器上&#xff0c;就想要体验一番Docker的“一次构建&#xff0c;处处运行”。这篇文章简单介绍了下这次部署的过程&#xff0c;其中使用了Dockerfile定制镜像和Docker-Compose多容器编排。 二. 项目介绍 项目采…

Python-乒乓球小游戏【附完整源码】

乒乓球小游戏 乒乓球小游戏是一个简单而有趣的2D页面交互式游戏&#xff0c;玩家可以通过键盘输入来控制球拍上下移动来接球&#xff0c;从而体验乒乓球的乐趣。该游戏有单人和双人两种模式 运行效果&#xff1a; 一&#xff1a;主程序&#xff1a; import sys import cfg …