Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xindoo
redis
提交
5234952b
R
redis
项目概览
xindoo
/
redis
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5234952b
编写于
3月 05, 2010
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
zipmaps functions to get, iterate, test for existence. Initial works for Hash data type
上级
b1ad58ed
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
136 addition
and
24 deletion
+136
-24
Makefile
Makefile
+3
-2
redis.c
redis.c
+28
-3
zipmap.c
zipmap.c
+59
-19
zipmap.h
zipmap.h
+46
-0
未找到文件。
Makefile
浏览文件 @
5234952b
...
...
@@ -14,7 +14,7 @@ endif
CCOPT
=
$(CFLAGS)
$(CCLINK)
$(ARCH)
$(PROF)
DEBUG
?=
-g
-rdynamic
-ggdb
OBJ
=
adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o
OBJ
=
adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o
zipmap.o
BENCHOBJ
=
ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o
...
...
@@ -39,8 +39,9 @@ redis-benchmark.o: redis-benchmark.c fmacros.h ae.h anet.h sds.h adlist.h \
zmalloc.h
redis-cli.o
:
redis-cli.c fmacros.h anet.h sds.h adlist.h zmalloc.h
redis.o
:
redis.c fmacros.h config.h redis.h ae.h sds.h anet.h dict.h
\
adlist.h zmalloc.h lzf.h pqsort.h staticsymbols.h
adlist.h zmalloc.h lzf.h pqsort.h
zipmap.h
staticsymbols.h
sds.o
:
sds.c sds.h zmalloc.h
zipmap.o
:
zipmap.c zmalloc.h
zmalloc.o
:
zmalloc.c config.h
redis-server
:
$(OBJ)
...
...
redis.c
浏览文件 @
5234952b
...
...
@@ -75,6 +75,7 @@
#include "zmalloc.h"
/* total memory usage aware version of malloc/free */
#include "lzf.h"
/* LZF compression library */
#include "pqsort.h"
/* Partial qsort for SORT+LIMIT */
#include "zipmap.h"
/* Error codes */
#define REDIS_OK 0
...
...
@@ -118,9 +119,13 @@
#define REDIS_ZSET 3
#define REDIS_HASH 4
/* Objects encoding */
/* Objects encoding. Some kind of objects like Strings and Hashes can be
* internally represented in multiple ways. The 'encoding' field of the object
* is set to one of this fields for this object. */
#define REDIS_ENCODING_RAW 0
/* Raw representation */
#define REDIS_ENCODING_INT 1
/* Encoded as integer */
#define REDIS_ENCODING_ZIPMAP 2
/* Encoded as zipmap */
#define REDIS_ENCODING_HT 3
/* Encoded as an hash table */
/* Object types only used for dumping to disk */
#define REDIS_EXPIRETIME 253
...
...
@@ -1011,7 +1016,7 @@ static dictType zsetDictType = {
};
/* Db->dict */
static
dictType
hash
DictType
=
{
static
dictType
db
DictType
=
{
dictObjHash
,
/* hash function */
NULL
,
/* key dup */
NULL
,
/* val dup */
...
...
@@ -1030,6 +1035,16 @@ static dictType keyptrDictType = {
NULL
/* val destructor */
};
/* Hash type hash table (note that small hashes are represented with zimpaps) */
static
dictType
hashDictType
=
{
dictEncObjHash
,
/* hash function */
NULL
,
/* key dup */
NULL
,
/* val dup */
dictEncObjKeyCompare
,
/* key compare */
dictRedisObjectDestructor
,
/* key destructor */
dictRedisObjectDestructor
/* val destructor */
};
/* Keylist hash table type has unencoded redis objects as keys and
* lists as values. It's used for blocking operations (BLPOP) and to
* map swapped keys to a list of clients waiting for this keys to be loaded. */
...
...
@@ -1493,7 +1508,7 @@ static void initServer() {
exit
(
1
);
}
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
server
.
db
[
j
].
dict
=
dictCreate
(
&
hash
DictType
,
NULL
);
server
.
db
[
j
].
dict
=
dictCreate
(
&
db
DictType
,
NULL
);
server
.
db
[
j
].
expires
=
dictCreate
(
&
keyptrDictType
,
NULL
);
server
.
db
[
j
].
blockingkeys
=
dictCreate
(
&
keylistDictType
,
NULL
);
if
(
server
.
vm_enabled
)
...
...
@@ -2543,6 +2558,16 @@ static robj *createSetObject(void) {
return
createObject
(
REDIS_SET
,
d
);
}
static
robj
*
createHashObject
(
void
)
{
/* All the Hashes start as zipmaps. Will be automatically converted
* into hash tables if there are enough elements or big elements
* inside. */
unsigned
char
*
zm
=
zipmapNew
();
robj
*
o
=
createObject
(
REDIS_HASH
,
zm
);
o
->
encoding
=
REDIS_ENCODING_ZIPMAP
;
return
o
;
}
static
robj
*
createZsetObject
(
void
)
{
zset
*
zs
=
zmalloc
(
sizeof
(
*
zs
));
...
...
zipmap.c
浏览文件 @
5234952b
...
...
@@ -97,6 +97,11 @@
* comments above, that is, the max number of trailing bytes in a value. */
#define ZIPMAP_VALUE_MAX_FREE 5
/* The following macro returns the number of bytes needed to encode the length
* for the integer value _l, that is, 1 byte for lengths < ZIPMAP_BIGLEN and
* 5 bytes for all the other lengths. */
#define ZIPMAP_LEN_BYTES(_l) (((_l) < ZIPMAP_BIGLEN) ? 1 : sizeof(unsigned int)+1)
/* Create a new empty zipmap. */
unsigned
char
*
zipmapNew
(
void
)
{
unsigned
char
*
zm
=
zmalloc
(
2
);
...
...
@@ -119,7 +124,7 @@ static unsigned int zipmapDecodeLength(unsigned char *p) {
* the amount of bytes required to encode such a length. */
static
unsigned
int
zipmapEncodeLength
(
unsigned
char
*
p
,
unsigned
int
len
)
{
if
(
p
==
NULL
)
{
return
(
len
<
ZIPMAP_BIGLEN
)
?
1
:
1
+
sizeof
(
unsigned
int
);
return
ZIPMAP_LEN_BYTES
(
len
);
}
else
{
if
(
len
<
ZIPMAP_BIGLEN
)
{
p
[
0
]
=
len
;
...
...
@@ -219,23 +224,24 @@ static unsigned int zipmapRawEntryLength(unsigned char *p) {
return
l
+
zipmapRawValueLength
(
p
+
l
);
}
/* Set key to value, creating the key if it does not already exist. */
unsigned
char
*
zipmapSet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
*
val
,
unsigned
int
vlen
)
{
/* Set key to value, creating the key if it does not already exist.
* If 'update' is not NULL, *update is set to 1 if the key was
* already preset, otherwise to 0. */
unsigned
char
*
zipmapSet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
*
val
,
unsigned
int
vlen
,
int
*
update
)
{
unsigned
int
oldlen
=
0
,
freeoff
=
0
,
freelen
;
unsigned
int
reqlen
=
zipmapRequiredLength
(
klen
,
vlen
);
unsigned
int
empty
,
vempty
;
unsigned
char
*
p
;
freelen
=
reqlen
;
if
(
update
)
*
update
=
0
;
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
&
oldlen
,
&
freeoff
,
&
freelen
);
if
(
p
==
NULL
&&
freelen
==
0
)
{
printf
(
"HERE oldlen:%u required:%u
\n
"
,
oldlen
,
reqlen
);
/* Key not found, and not space for the new key. Enlarge */
zm
=
zrealloc
(
zm
,
oldlen
+
reqlen
);
p
=
zm
+
oldlen
-
1
;
zm
[
oldlen
+
reqlen
-
1
]
=
ZIPMAP_END
;
freelen
=
reqlen
;
printf
(
"New total length is: %u
\n
"
,
oldlen
+
reqlen
);
}
else
if
(
p
==
NULL
)
{
/* Key not found, but there is enough free space. */
p
=
zm
+
freeoff
;
...
...
@@ -245,6 +251,7 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
/* Key found. Is there enough space for the new value? */
/* Compute the total length: */
if
(
update
)
*
update
=
1
;
freelen
=
zipmapRawKeyLength
(
b
);
b
+=
freelen
;
freelen
+=
zipmapRawValueLength
(
b
);
...
...
@@ -253,7 +260,7 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
p
[
0
]
=
ZIPMAP_EMPTY
;
zipmapEncodeLength
(
p
+
1
,
freelen
);
zm
[
0
]
|=
ZIPMAP_STATUS_FRAGMENTED
;
return
zipmapSet
(
zm
,
key
,
klen
,
val
,
vlen
);
return
zipmapSet
(
zm
,
key
,
klen
,
val
,
vlen
,
NULL
);
}
}
...
...
@@ -304,37 +311,58 @@ unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int kle
return
zm
;
}
/* Call it before to iterate trought elements via zipmapNext() */
unsigned
char
*
zipmapRewind
(
unsigned
char
*
zm
)
{
return
zm
+
1
;
}
/* This function is used to iterate through all the zipmap elements.
* In the first call the first argument is the pointer to the zipmap + 1.
* In the next calls what zipmapNext returns is used as first argument.
* Example:
*
* unsigned char *i =
my_zipmap+1
;
* unsigned char *i =
zipmapRewind(my_zipmap)
;
* while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {
* printf("%d bytes key at $p\n", klen, key);
* printf("%d bytes value at $p\n", vlen, value);
* }
*/
unsigned
char
*
zipmapNext
(
unsigned
char
*
zm
,
unsigned
char
**
key
,
unsigned
int
*
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
)
{
unsigned
char
*
zipmapNext
(
unsigned
char
*
zm
,
unsigned
char
**
key
,
unsigned
int
*
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
)
{
while
(
zm
[
0
]
==
ZIPMAP_EMPTY
)
zm
+=
zipmapDecodeLength
(
zm
+
1
);
if
(
zm
[
0
]
==
ZIPMAP_END
)
return
NULL
;
if
(
key
)
{
*
key
=
zm
;
*
klen
=
zipmapDecodeLength
(
zm
);
*
key
+=
(
*
klen
<
ZIPMAP_BIGLEN
)
?
1
:
sizeof
(
unsigned
int
);
*
key
+=
ZIPMAP_LEN_BYTES
(
*
klen
);
}
zm
+=
zipmapRawKeyLength
(
zm
);
if
(
value
)
{
*
value
=
zm
+
1
;
*
vlen
=
zipmapDecodeLength
(
zm
);
*
value
+=
(
*
vlen
<
ZIPMAP_BIGLEN
)
?
1
:
sizeof
(
unsigned
int
);
*
value
+=
ZIPMAP_LEN_BYTES
(
*
vlen
);
}
zm
+=
zipmapRawValueLength
(
zm
);
return
zm
;
}
/* Search a key and retrieve the pointer and len of the associated value.
* If the key is found the function returns 1, otherwise 0. */
int
zipmapGet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
)
{
unsigned
char
*
p
;
if
((
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
,
NULL
,
NULL
))
==
NULL
)
return
0
;
p
+=
zipmapRawKeyLength
(
p
);
*
vlen
=
zipmapDecodeLength
(
p
);
*
value
=
p
+
ZIPMAP_LEN_BYTES
(
*
vlen
)
+
1
;
return
1
;
}
/* Return 1 if the key exists, otherwise 0 is returned. */
int
zipmapExists
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
)
{
return
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
,
NULL
,
NULL
)
!=
NULL
;
}
void
zipmapRepr
(
unsigned
char
*
p
)
{
unsigned
int
l
;
...
...
@@ -372,29 +400,41 @@ void zipmapRepr(unsigned char *p) {
printf
(
"
\n
"
);
}
#ifdef ZIPMAP_TEST_MAIN
int
main
(
void
)
{
unsigned
char
*
zm
;
zm
=
zipmapNew
();
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"hello"
,
5
,
(
unsigned
char
*
)
"world!"
,
6
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"bar"
,
3
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"!"
,
1
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"hello"
,
5
,
(
unsigned
char
*
)
"world!"
,
6
,
NULL
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"bar"
,
3
,
NULL
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"!"
,
1
,
NULL
);
zipmapRepr
(
zm
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"12345"
,
5
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
(
unsigned
char
*
)
"12345"
,
5
,
NULL
);
zipmapRepr
(
zm
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"new"
,
3
,
(
unsigned
char
*
)
"xx"
,
2
);
zm
=
zipmapSet
(
zm
,(
unsigned
char
*
)
"new"
,
3
,
(
unsigned
char
*
)
"xx"
,
2
,
NULL
);
zipmapRepr
(
zm
);
zm
=
zipmapDel
(
zm
,(
unsigned
char
*
)
"new"
,
3
,
NULL
);
zipmapRepr
(
zm
);
printf
(
"Iterate trought elements:
\n
"
);
printf
(
"
\n
Perform a direct lookup:
\n
"
);
{
unsigned
char
*
value
;
unsigned
int
vlen
;
if
(
zipmapGet
(
zm
,(
unsigned
char
*
)
"foo"
,
3
,
&
value
,
&
vlen
))
{
printf
(
" foo is associated to the %d bytes value: %.*s
\n
"
,
vlen
,
vlen
,
value
);
}
}
printf
(
"
\n
Iterate trought elements:
\n
"
);
{
unsigned
char
*
i
=
z
m
+
1
;
unsigned
char
*
i
=
z
ipmapRewind
(
zm
)
;
unsigned
char
*
key
,
*
value
;
unsigned
int
klen
,
vlen
;
while
((
i
=
zipmapNext
(
i
,
&
key
,
&
klen
,
&
value
,
&
vlen
))
!=
NULL
)
{
printf
(
"%d:%.*s => %d:%.*s
\n
"
,
klen
,
klen
,
key
,
vlen
,
vlen
,
value
);
printf
(
"
%d:%.*s => %d:%.*s
\n
"
,
klen
,
klen
,
key
,
vlen
,
vlen
,
value
);
}
}
return
0
;
}
#endif
zipmap.h
0 → 100644
浏览文件 @
5234952b
/* String -> String Map data structure optimized for size.
*
* See zipmap.c for more info.
*
* --------------------------------------------------------------------------
*
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ZIMMAP_H
#define _ZIPMAP_H
unsigned
char
*
zipmapNew
(
void
);
unsigned
char
*
zipmapSet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
*
val
,
unsigned
int
vlen
,
int
*
update
);
unsigned
char
*
zipmapDel
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
int
*
deleted
);
unsigned
char
*
zipmapRewind
(
unsigned
char
*
zm
);
unsigned
char
*
zipmapNext
(
unsigned
char
*
zm
,
unsigned
char
**
key
,
unsigned
int
*
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
);
int
zipmapGet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
);
int
zipmapExists
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
);
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录