Redis源代码分析(十)--- testhelp.h小测试框架和redis-check-aof.c 日志检测
周期分析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()更改设计线运行
版权声明:本文博主原创文章,博客,未经同意不得转载。
Redis源代码分析(十)--- testhelp.h小测试框架和redis-check-aof.c 日志检测的更多相关文章
- Redis源代码分析(十一年)--- memtest内存测试
今天,我们继续redis源代码test下测试在封装中的其它文件.今天读数memtest档,翻译了,那是,memory test 存储器测试工具..可是里面的提及了非常多东西,也给我涨了非常多见识,网上 ...
- Redis源代码分析(一)--Redis结构解析
从今天起,本人将会展开对Redis源代码的学习,Redis的代码规模比較小,很适合学习,是一份很不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的.希望终于能把他啃完吧,C语言好久不 ...
- redis 源代码分析(一) 内存管理
一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...
- Redis源代码分析(23)--- CRC循环冗余算法RAND随机数的算法
他今天就开始学习Redis源代码的一些工具来实现,在任何一种语言工具.算法实现的原理应该是相同的,一些比較经典的算法.比方说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循 ...
- redis源代码分析(5)——aof
前面几篇基本介绍了redis的主要功能.流程.接下来是一些相对独立的部分,首先看一下持久化. redis持久化支持两种方式:RDB和AOF,我们首先看一下AOF的实现. AOF(Append only ...
- Redis源代码分析(三十五)--- redis.c服务端的实现分析(2)
在Redis服务端的代码量真的是比較大,假设一个一个API的学习怎么实现,无疑是一种效率非常低的做法,所以我今天对服务端的实现代码的学习,重在他的运行流程上.而对于他的模块设计在上一篇中我已经分析过了 ...
- Redis源代码分析(二十八)--- object创建和释放redisObject物
今天的学习更有效率.该Rio分析过,学习之间的另一种方式RedisObject文件,只想说RedisObject有些生成和转换.都是很类似的.列出里面长长的API列表: /* ------------ ...
- Redis源代码分析(二十四)--- tool工具类(2)
在上篇文章中初步的分析了一下,Redis工具类文件里的一些使用方法,包含2个随机算法和循环冗余校验算法,今天,继续学习Redis中的其它的一些辅助工具类的使用方法.包含里面的大小端转换算法,sha算法 ...
- Redis源代码分析(三十)--- pubsub公布订阅模式
今天学习了Redis中比較高大上的名词,"公布订阅模式".公布订阅模式这个词在我最開始接触听说的时候是在JMS(Java Message Service)java消息服务中听说的. ...
随机推荐
- 在js中做数字字符串加0补位,效率分析
分类: Jquery/YUI/ExtJs 2010-08-30 11:27 2700人阅读 评论(0) 收藏 举报 functiondate算法语言c 通常遇到的一个问题是日期的“1976-02-03 ...
- 数据结构 - trie
#include <cstring> #include <iostream> #include <map> #include <cstdio> usin ...
- state pattern
6 状态模式总结 状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用.在实际开 ...
- [ACM] POJ 3254 Corn Fields(状态压缩)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8062 Accepted: 4295 Descr ...
- 客户端上显示csdn上的各类别下的的文章列表 (制作csdn app 三)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23597229 今天将在Android 使用Fragment,ViewPagerI ...
- MyReport报表引擎2.1.0.0新功能
支持简单的四则运算样例1:算总分,简单连加 样例2:算平均分.除非和加法混合(可以识别先乘除后加减,不支持小括号优先运算) 新增行号函数 直接生成行号 新增多种格式化设置修复数个已发现的Bug.优化代 ...
- Google API快速生成QR二维码
Google API快速生成QR二维码 现在来说生成二维码最简单的方法是使用Google Chart API来实现,再次膜拜Google大神- Google Chart API是一套可以让你在线生成报 ...
- HSQLDB相关信息及用法汇总
运行模式 说明 启动命令 JDBC例 内存(Memory-Only)模式 所有数据都在内存里操作.应用程序退出后则数据被销毁.无需另外启动HSQLDB Server 启动方式1:通过程序中首次调用Co ...
- 怎样用C#代码管理SharePoint解决方式
怎样用C#代码管理SharePoint解决方式 本文我们将了解怎样用代码管理SharePoint解决方式.我们使用server端对象模型抽取解决方式. SharePoi ...
- Snail—ORACLE基础之事务学习(五)
---------------事务---当运行到commit时 事务才算是完毕,不然 会运行rollback操作. declare v_money acount.money%type:=1223; e ...