12 February 2018
原文: Redis 编程小技巧拾遗

空数组

对于结构体成员中大小不确定的地方,可以考虑放一个空数组到结构体的末尾,这样通过动态内存分配,就可以合理的设置空间了,当然需要一个成员记录元素的个数。

SDS 是 Redis 封装的一个字符串类型,因为字符串的长度需要动态的控制,所以就用了空数组这个小技巧。

宏定义中使用 do while(0)


调试信息打印

自定义 assert 函数,当条件不通过时打印文件名、行号以及条件信息。

// #_e 将_e 转换为字符串
#define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))

void _redisAssert(char *estr, char *file, int line) {
    bugReportStart();
    redisLog(REDIS_WARNING,"=== ASSERTION FAILED ===");
    redisLog(REDIS_WARNING,"==> %s:%d '%s' is not true",file,line,estr);
#ifdef HAVE_BACKTRACE
    server.assert_failed = estr;
    server.assert_file = file;
    server.assert_line = line;
    redisLog(REDIS_WARNING,"(forcing SIGSEGV to print the bug report.)");
#endif
    *((char*)-1) = 'x';
}

另外 redisLog 打印日志时,可以根据第一个参数进行过滤操作。

#define REDIS_DEBUG 0
#define REDIS_VERBOSE 1
#define REDIS_NOTICE 2
#define REDIS_WARNING 3

void redisLog(int level, const char *fmt, ...) {
    va_list ap;
    char msg[REDIS_MAX_LOGMSG_LEN];
    // server.verbosity 从配置文件读取设定
    if ((level&0xff) < server.verbosity) return;

    va_start(ap, fmt);
    vsnprintf(msg, sizeof(msg), fmt, ap);
    va_end(ap);

    redisLogRaw(level,msg);
}

消除函数未使用参数的警告信息

#define REDIS_NOTUSED(V) ((void) V)

这个 宏存在的原因是,变量在函数中没使用到的时候会报 warning,有这个宏就相当于使用了该变量