Redis代码阅读之Hacking Strings
Hacking Strings
The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dynamic Strings ).
The C structure sdshdr declared in sds.h represents a Redis string:
struct sdshdr {
long len;
long free;
char buf[];
};
The buf character array stores the actual string.
The len field stores the length of buf. This makes obtaining the length of a Redis string an O(1) operation.
The free field stores the number of additional bytes available for use.
Together the len and free field can be thought of as holding the metadata of the buf character array.
Creating Redis Strings
A new data type named sds
is defined in sds.h to be a synonymn for a character pointer:
typedef char *sds;
sdsnewlen
function defined in sds.c creates a new Redis String:
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
#ifdef SDS_ABORT_ON_OOM
if (sh == NULL) sdsOomAbort();
#else
if (sh == NULL) return NULL;
#endif
sh->len = initlen;
sh->free = 0;
if (initlen) {
if (init) memcpy(sh->buf, init, initlen);
else memset(sh->buf,0,initlen);
}
sh->buf[initlen] = '\0';
return (char*)sh->buf;
}
Remember a Redis string is a variable of type struct sdshdr
. But sdsnewlen
returns a character pointer!!
That's a trick and needs some explanation.
Suppose I create a Redis string using sdsnewlen
like below:
sdsnewlen("redis", 5);
This creates a new variable of type struct sdshdr
allocating memory for len and free fields as well as for the buf character array.
sh = zmalloc(sizeof(struct sdshdr)+initlen+1); // initlen is length of init argument.
After sdsnewlen
succesfully creates a Redis string the result is something like:
-----------
|5|0|redis|
-----------
^ ^
sh sh->buf
sdsnewlen
returns sh->buf to the caller.
What do you do if you need to free the Redis string pointed by sh
?
You want the pointer sh
but you only have the pointer sh->buf
.
Can you get the pointer sh
from sh->buf
?
Yes. Pointer arithmetic. Notice from the above ASCII art that if you subtract the size of two longs from sh->buf
you get the pointer sh
.
The sizeof two longs happens to be the size of struct sdshdr
.
Look at sdslen
function and see this trick at work:
size_t sdslen(const sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
return sh->len;
}
Knowing this trick you could easily go through the rest of the functions in sds.c.
The Redis string implementation is hidden behind an interface that accepts only character pointers. The users of Redis strings need not care about how its implemented and treat Redis strings as a character pointer.
C Struct array member without specific length
Redis代码阅读之Hacking Strings的更多相关文章
- 代码阅读分析工具Understand 2.0试用
Understand 2.0是一款源代码阅读分析软件,功能强大.试用过一段时间后,感觉相当不错,确实可以大大提高代码阅读效率.由于Understand功能十分强大,本文不可能详尽地介绍它的所有功能,所 ...
- Android 上的代码阅读器 CoderBrowserHD 修改支持 go 语言代码
我在Android上的代码阅读器用的是 https://github.com/zerob13/CoderBrowserHD 改造的版本,改造后的版本我放在 https://github.com/ghj ...
- Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- [置顶] Linux协议栈代码阅读笔记(一)
Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...
- Session for Tornado(Redis) - 代码分享
Session for Tornado(Redis) - 代码分享 Session for Tornado(Redis) session id的生成借用了web.py. 使用了 redis 的 h ...
- 图形化代码阅读工具——Scitools Understand
Scitools出品的Understand 2.0.用了很多年了,比Source Insight强大很多.以前的名字叫Understand for C/C++,Understand for Java, ...
- Python - 关于代码阅读的一些建议
初始能力 让阅读思路保持清晰连贯,主力关注在流程架构和逻辑实现上,不被语法.技巧和业务流程等频繁地阻碍和打断. 建议基本满足以下条件,再开始进行代码阅读: 具备一定的语言基础:熟悉基础语法,常用的函数 ...
- MediaInfo代码阅读
MediaInfo是一个用来分析媒体文件的开源工具. 支持的文件非常全面,基本上支持所有的媒体文件. 最近是在做HEVC开发,所以比较关注MediaInfo中关于HEVC的分析与处理. 从Meid ...
- Tools - 一些代码阅读的方法
1 初始能力 让阅读思路清晰连贯,保持在程序的流程架构和逻辑实现上,不被语法.编程技巧和业务流程等频繁地阻碍和打断. 语言基础:熟悉基础语法,常用的函数.库.编程技巧等: 了解设计模式.构建工具.代码 ...
随机推荐
- npm穿墙
GWF 很给力,很多东西都能墙掉,但是把 npm 也纳入黑名单,不知道 GWFer 是怎么想的.FQ翻了好多年了,原理其实也挺简单的,proxy 嘛! » 方法一 A) 国内源,http://cnpm ...
- prerender-SPA程序的SEO优化策略
随着web2.0的兴起,ajax的时代已经成为了事实,更如今Knockout,backbone, angular,ember前端MDV(model driver view)框架强势而来,Single ...
- 技术渣如狗,面试虐成猴——本科楼主UC笔试加处女一面全纪录
背景——楼主为广州某校小本一枚,学习成绩渣(班里排名几乎倒数),技术基础渣(算是会敲代码,但很多计算机网络.操作系统的知识都只有模糊的印象).在舍友的鼓励下,收到广州UC的面试通知后,勇敢来到公司直面 ...
- zk系列-zookeeper概述
接触zk是2年前了,最近工作又比较依赖于zk,所以准备起个系列文章,系统的总结下. zookeeper是一个分布式的用于协调的服务,起源于Hadoop中的一个组件.分布式系统可以用zookeeper实 ...
- Java处理Radius access-challenge
最近使用 RSA Authentication Manager, 并且与其自带的Radius server整合, RSA的Radius server 配置不太透明, 目前只配成功了PAP方式的验证,C ...
- WebApi系列~QQ互联的引入(QConnectSDK)
回到目录 感谢与改进 首先要感谢张善友老兄为大家封装的这个DLL,它将QQ官方的相关API都集成到了这个里面,这对于开发人员来说,是个福音,有人会说,为什么QQ官方没有提供.net版的SDK呢,在这里 ...
- JS之BOM
ECMAScript 是 JavaScript 的核心,但如果要在 Web 中使用 JavaScript,那么 BOM(浏览器对象模型)则无疑才是真正的核心.BOM 提供了很多对象,用于访问浏览器的功 ...
- Ajax技术
1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...
- SQL SERVER 2005/2008 中关于架构的理解(二)
本文上接SQL SERVER 2005/2008 中关于架构的理解(一) 架构的作用与示例 用户与架构(schema)分开,让数据库内各对象不再绑在某个用户账号上,可以解决SQL SERVE ...
- 每天一个linux命令(42):kill命令
Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以使用Ctrl+C键,但是,对于一个后台进程就须 ...