博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis源代码分析(十)--- testhelp.h小测试框架和redis-check-aof.c日志检测
阅读量:5154 次
发布时间:2019-06-13

本文共 3008 字,大约阅读时间需要 10 分钟。

            周期分析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");            }
以上就是我所分析的内容了,很easy。比起struct比,简单太多了,能够细细体会当中方法涉及的技巧,比方我们会考虑日志文件分析时会想到
consumeNewline()更改设计线运行

版权声明:本文博主原创文章,博客,未经同意不得转载。

转载于:https://www.cnblogs.com/zfyouxi/p/4809145.html

你可能感兴趣的文章
5句话搞定ES5作用域
查看>>
Build tool
查看>>
php 小坑记录
查看>>
2018.7.28 二叉树的遍历规则(前序遍历、后序遍历、中序遍历)
查看>>
通过 poi 导入 Excel代码
查看>>
《CSS基础教程》 读书笔记三
查看>>
洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...
查看>>
PHP安全新闻早8点_1127
查看>>
57.Insert Interval
查看>>
PHP 五大运行模式
查看>>
CSS选项卡
查看>>
HDOJ1203 I NEED A OFFER!
查看>>
ZH奶酪:自然语言处理工具LTP语言云调用方法
查看>>
.NET中将图片文件流转成Base64字符串的实现
查看>>
js如何操作或是更改sass里的变量
查看>>
BZOJ1419: Red is good
查看>>
腾讯云-搭建 JAVA 开发环境
查看>>
POJ 3308 Paratroopers (对数转换+最小点权覆盖)
查看>>
rendering omni shadow in one pass.
查看>>
No repository found containing,eclipse 自动更新erro 解决
查看>>