设为首页 收藏本站
查看: 1047|回复: 0

[经验分享] Redis源码分析(十)--- testhelp.h小型测试框架和redis-check-aof.c日志检测

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-11-5 09:15:49 | 显示全部楼层 |阅读模式
     分析了一段时间的struct结构体的redis代码,越到最后越发现其实很多代码都是大同小异的。在struct包中还有1,2个文件还没分析,是关于set集合的一些东西,就放在下次分析好了,在选择下个分析的对象时,我考虑了一下,最后决定先把简单的test包下的东西看看一下,毕竟结构体这块有点复杂,所以这次分析个简单点的。test包下的文件并不多,代码量也很少,总共5个文件:

1.memtest.c 内存检测
2.redis_benchmark.c 用于redis性能测试的实现。
3.redis_check_aof.c 用于更新日志检查的实现。
4.redis_check_dump.c 用于本地数据库检查的实现。
5.testhelp.c 一个C风格的小型测试框架。

今天讨论3和5,先看看5,testhelp.c被解释为一个C风格的小型测试框架,看见这标题,一定想到这是一个很大的文件吧,都被称为测试框架了,其实不然,我贴出整个代码:



    /* 预处理 */  
    #ifndef __TESTHELP_H  
    #define __TESTHELP_H  
      
    /* 开始时失败总数为0 */  
    int __failed_tests = 0;  
    /* 开始时测试总的例子数为0 */  
    int __test_num = 0;  
      
    /* 宏定义测试方法,输入参数,输入描述语,判断的式子作为参数 */  
    /* 有完全体现了函数式编程的思想 */  
    #define test_cond(descr,_c) do { \  
        __test_num++; printf("%d - %s: ", __test_num, descr); \  
        //判断式子在此处调用  
        if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \  
    } while(0);  
      
    /* 测试报告在最结尾输出 */  
    #define test_report() do { \  
        printf("%d tests, %d passed, %d failed\n", __test_num, \  
                        __test_num-__failed_tests, __failed_tests); \  
        if (__failed_tests) { \  
            printf("=== WARNING === We have failed tests here...\n"); \  
            exit(1); \  
        } \  
    } while(0);  
      
    #endif  


调用形式也是极其简单:



    * test_cond("Check if 1 == 1", 1==1)  
    * test_cond("Check if 5 > 10", 5 > 10)  
    * test_report()  


其实就是宏定义了一个判别表达式真假的方法,又用到了函数式编程的思想,把_c整个表达式的值传入了另一个函数中,就这么简单。好,下一个文件redis_check_aof.c用于日志检测的,必然和文件的操作相关的,同样列出里面的API:



    /* 方法API */  
    int consumeNewline(char *buf) /* 消除buf前面的换行符,即比较buf字符串中的前2个字符 */  
    int readLong(FILE *fp, char prefix, long *target) /* 从文件中读取long类型值 */  
    int readBytes(FILE *fp, char *target, long length) /* 从文件中读取字节 */  
    int readString(FILE *fp, char** target) /* 文件中读取字符串 */  
    int readArgc(FILE *fp, long *target) /* 文件中读取参数,首字符以“*”开头 */  
    off_t process(FILE *fp) /* 返回fp文件的偏移量 */  


read的很多操作其实都是非常类似的,我就举出其中的一个read方法当做例子,就是纯粹文件的简单操作,熟悉C语言的同学一定很熟悉:



    /* 从文件中读取long类型值 */  
    int readLong(FILE *fp, char prefix, long *target) {  
        char buf[128], *eptr;  
        //定位到文件的读取位置  
        epos = ftello(fp);  
        //将文件中的内容读取到buf中  
        if (fgets(buf,sizeof(buf),fp) == NULL) {  
            //如果为空直接返回  
            return 0;  
        }  
         
        //如果读取到的首字符不等于预期值,则提示报错  
        if (buf[0] != prefix) {  
            ERROR("Expected prefix '%c', got: '%c'",buf[0],prefix);  
            return 0;  
        }  
         
        //将字符串值转成long类型值  
        *target = strtol(buf+1,&eptr,10);  
         
        return consumeNewline(eptr);  
    }  


里面有一个比较特别的方法,consumeNewline()消除换行符的方法:



    /* 消除buf前面的换行符,即比较buf字符串中的前2个字符 */  
    int consumeNewline(char *buf) {  
        if (strncmp(buf,"\r\n",2) != 0) {  
            //如果不是等于"\r\n",则提示出错  
            ERROR("Expected \\r\\n, got: %02x%02x",buf[0],buf[1]);  
            return 0;  
        }  
        return 1;  
    }  


里面比较复杂的方法是off_t process(FILE *fp)获取文件偏移量的操作,这个方法是用来后面截断文件的操作,截断后面的空文件的部分:



    off_t pos = process(fp);  
      
    //截断文件的操作,从问价头部到后面的偏移量,没有用的空间截去  
                if (ftruncate(fileno(fp), pos) == -1) {  
                    printf("Failed to truncate AOF\n");  
                    exit(1);  
                } else {  
                    printf("Successfully truncated AOF\n");  
                }  


以上就是我所分析的内容了,非常简单,比起struct比,简单太多了,可以细细体会其中方法涉及的技巧,比如我们会考虑日志文件分析时会想到用consumeNewline()换行操作的设计吗

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-27089-1-1.html 上篇帖子: Redis源码分析(九)--- t_list,t_string的分析 下篇帖子: Redis源码分析(十一)--- memtest内存检测 检测
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表