Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xindoo
redis
提交
36c19d03
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,发现更多精彩内容 >>
提交
36c19d03
编写于
9月 02, 2010
作者:
P
Pieter Noordhuis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Changed reply buildup internals
上级
4a7893ca
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
97 addition
and
62 deletion
+97
-62
src/networking.c
src/networking.c
+96
-51
src/object.c
src/object.c
+0
-1
src/redis.h
src/redis.h
+1
-10
未找到文件。
src/networking.c
浏览文件 @
36c19d03
...
@@ -13,13 +13,9 @@ int listMatchObjects(void *a, void *b) {
...
@@ -13,13 +13,9 @@ int listMatchObjects(void *a, void *b) {
redisClient
*
createClient
(
int
fd
)
{
redisClient
*
createClient
(
int
fd
)
{
redisClient
*
c
;
redisClient
*
c
;
/* Make sure to allocate a multiple of the page size to prevent wasting
/* Allocate more space to hold a static write buffer. */
* memory. A page size of 4096 is assumed here. We need to compensate
c
=
zmalloc
(
sizeof
(
redisClient
)
+
REDIS_REPLY_CHUNK_BYTES
);
* for the zmalloc overhead of sizeof(size_t) bytes. */
c
->
buflen
=
REDIS_REPLY_CHUNK_BYTES
;
size_t
size
=
8192
-
sizeof
(
size_t
);
redisAssert
(
size
>
sizeof
(
redisClient
));
c
=
zmalloc
(
size
);
c
->
buflen
=
size
-
sizeof
(
redisClient
);
c
->
bufpos
=
0
;
c
->
bufpos
=
0
;
anetNonBlock
(
NULL
,
fd
);
anetNonBlock
(
NULL
,
fd
);
...
@@ -71,40 +67,95 @@ int _ensureFileEvent(redisClient *c) {
...
@@ -71,40 +67,95 @@ int _ensureFileEvent(redisClient *c) {
return
REDIS_OK
;
return
REDIS_OK
;
}
}
void
_addReplyObjectToList
(
redisClient
*
c
,
robj
*
obj
)
{
/* Create a duplicate of the last object in the reply list when
redisAssert
(
obj
->
type
==
REDIS_STRING
&&
* it is not exclusively owned by the reply list. */
obj
->
encoding
==
REDIS_ENCODING_RAW
);
robj
*
dupLastObjectIfNeeded
(
list
*
reply
)
{
listAddNodeTail
(
c
->
reply
,
obj
);
robj
*
new
,
*
cur
;
listNode
*
ln
;
redisAssert
(
listLength
(
reply
)
>
0
);
ln
=
listLast
(
reply
);
cur
=
listNodeValue
(
ln
);
if
(
cur
->
refcount
>
1
)
{
new
=
dupStringObject
(
cur
);
decrRefCount
(
cur
);
listNodeValue
(
ln
)
=
new
;
}
return
listNodeValue
(
ln
);
}
}
void
_ensureBufferInReplyList
(
redisClient
*
c
)
{
int
_addReplyToBuffer
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
sds
buffer
=
sdsnewlen
(
NULL
,
REDIS_REPLY_CHUNK_SIZE
);
size_t
available
=
c
->
buflen
-
c
->
bufpos
;
sdsupdatelen
(
buffer
);
/* sdsnewlen expects non-empty string */
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_REPLY_NODE
,
buffer
));
/* If there already are entries in the reply list, we cannot
* add anything more to the static buffer. */
if
(
listLength
(
c
->
reply
)
>
0
)
return
REDIS_ERR
;
/* Check that the buffer has enough space available for this string. */
if
(
len
>
available
)
return
REDIS_ERR
;
memcpy
(
c
->
buf
+
c
->
bufpos
,
s
,
len
);
c
->
bufpos
+=
len
;
return
REDIS_OK
;
}
}
void
_addReplyStringToBuffer
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
void
_addReplyObjectToList
(
redisClient
*
c
,
robj
*
o
)
{
size_t
available
=
0
;
robj
*
tail
;
redisAssert
(
len
<
REDIS_REPLY_CHUNK_THRESHOLD
);
if
(
listLength
(
c
->
reply
)
==
0
)
{
if
(
listLength
(
c
->
reply
)
>
0
)
{
incrRefCount
(
o
);
robj
*
o
=
listNodeValue
(
listLast
(
c
->
reply
));
listAddNodeTail
(
c
->
reply
,
o
);
}
else
{
/* Make sure to append to a reply node with enough bytes available. */
tail
=
listNodeValue
(
listLast
(
c
->
reply
));
if
(
o
->
type
==
REDIS_REPLY_NODE
)
available
=
sdsavail
(
o
->
ptr
);
if
(
o
->
type
!=
REDIS_REPLY_NODE
||
len
>
available
)
{
/* Append to this object when possible. */
_ensureBufferInReplyList
(
c
);
if
(
tail
->
ptr
!=
NULL
&&
_addReplyStringToBuffer
(
c
,
s
,
len
);
sdslen
(
tail
->
ptr
)
+
sdslen
(
o
->
ptr
)
<=
REDIS_REPLY_CHUNK_BYTES
)
{
tail
=
dupLastObjectIfNeeded
(
c
->
reply
);
tail
->
ptr
=
sdscatlen
(
tail
->
ptr
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
}
else
{
}
else
{
o
->
ptr
=
sdscatlen
(
o
->
ptr
,
s
,
len
);
incrRefCount
(
o
);
listAddNodeTail
(
c
->
reply
,
o
);
}
}
}
}
/* This method takes responsibility over the sds. When it is no longer
* needed it will be free'd, otherwise it ends up in a robj. */
void
_addReplySdsToList
(
redisClient
*
c
,
sds
s
)
{
robj
*
tail
;
if
(
listLength
(
c
->
reply
)
==
0
)
{
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_STRING
,
s
));
}
else
{
}
else
{
available
=
c
->
buflen
-
c
->
bufpos
;
tail
=
listNodeValue
(
listLast
(
c
->
reply
));
if
(
len
>
available
)
{
_ensureBufferInReplyList
(
c
);
/* Append to this object when possible. */
_addReplyStringToBuffer
(
c
,
s
,
len
);
if
(
tail
->
ptr
!=
NULL
&&
sdslen
(
tail
->
ptr
)
+
sdslen
(
s
)
<=
REDIS_REPLY_CHUNK_BYTES
)
{
tail
=
dupLastObjectIfNeeded
(
c
->
reply
);
tail
->
ptr
=
sdscatlen
(
tail
->
ptr
,
s
,
sdslen
(
s
));
sdsfree
(
s
);
}
else
{
}
else
{
memcpy
(
c
->
buf
+
c
->
bufpos
,
s
,
len
);
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_STRING
,
s
));
c
->
bufpos
+=
len
;
}
}
}
void
_addReplyStringToList
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
robj
*
tail
;
if
(
listLength
(
c
->
reply
)
==
0
)
{
listAddNodeTail
(
c
->
reply
,
createStringObject
(
s
,
len
));
}
else
{
tail
=
listNodeValue
(
listLast
(
c
->
reply
));
/* Append to this object when possible. */
if
(
tail
->
ptr
!=
NULL
&&
sdslen
(
tail
->
ptr
)
+
len
<=
REDIS_REPLY_CHUNK_BYTES
)
{
tail
=
dupLastObjectIfNeeded
(
c
->
reply
);
tail
->
ptr
=
sdscatlen
(
tail
->
ptr
,
s
,
len
);
}
else
{
listAddNodeTail
(
c
->
reply
,
createStringObject
(
s
,
len
));
}
}
}
}
}
}
...
@@ -118,13 +169,9 @@ void addReply(redisClient *c, robj *obj) {
...
@@ -118,13 +169,9 @@ void addReply(redisClient *c, robj *obj) {
/* This increments the refcount. */
/* This increments the refcount. */
obj
=
getDecodedObject
(
obj
);
obj
=
getDecodedObject
(
obj
);
}
}
if
(
_addReplyToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
))
!=
REDIS_OK
)
if
(
sdslen
(
obj
->
ptr
)
<
REDIS_REPLY_CHUNK_THRESHOLD
)
{
_addReplyStringToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
));
decrRefCount
(
obj
);
}
else
{
_addReplyObjectToList
(
c
,
obj
);
_addReplyObjectToList
(
c
,
obj
);
}
decrRefCount
(
obj
);
}
}
void
addReplySds
(
redisClient
*
c
,
sds
s
)
{
void
addReplySds
(
redisClient
*
c
,
sds
s
)
{
...
@@ -133,28 +180,25 @@ void addReplySds(redisClient *c, sds s) {
...
@@ -133,28 +180,25 @@ void addReplySds(redisClient *c, sds s) {
sdsfree
(
s
);
sdsfree
(
s
);
return
;
return
;
}
}
if
(
sdslen
(
s
)
<
REDIS_REPLY_CHUNK_THRESHOLD
)
{
if
(
_addReplyToBuffer
(
c
,
s
,
sdslen
(
s
))
==
REDIS_OK
)
{
_addReplyStringToBuffer
(
c
,
s
,
sdslen
(
s
));
sdsfree
(
s
);
sdsfree
(
s
);
}
else
{
}
else
{
_addReplyObjectToList
(
c
,
createObject
(
REDIS_STRING
,
s
));
/* This method free's the sds when it is no longer needed. */
_addReplySdsToList
(
c
,
s
);
}
}
}
}
void
addReplyString
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
void
addReplyString
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
if
(
_ensureFileEvent
(
c
)
!=
REDIS_OK
)
return
;
if
(
_ensureFileEvent
(
c
)
!=
REDIS_OK
)
return
;
if
(
len
<
REDIS_REPLY_CHUNK_THRESHOLD
)
{
if
(
_addReplyToBuffer
(
c
,
s
,
len
)
!=
REDIS_OK
)
_addReplyStringToBuffer
(
c
,
s
,
len
);
_addReplyStringToList
(
c
,
s
,
len
);
}
else
{
_addReplyObjectToList
(
c
,
createStringObject
(
s
,
len
));
}
}
}
/* Adds an empty object to the reply list that will contain the multi bulk
/* Adds an empty object to the reply list that will contain the multi bulk
* length, which is not known when this function is called. */
* length, which is not known when this function is called. */
void
*
addDeferredMultiBulkLength
(
redisClient
*
c
)
{
void
*
addDeferredMultiBulkLength
(
redisClient
*
c
)
{
if
(
_ensureFileEvent
(
c
)
!=
REDIS_OK
)
return
NULL
;
if
(
_ensureFileEvent
(
c
)
!=
REDIS_OK
)
return
NULL
;
_addReplyObjectToList
(
c
,
createObject
(
REDIS_STRING
,
NULL
));
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_STRING
,
NULL
));
return
listLast
(
c
->
reply
);
return
listLast
(
c
->
reply
);
}
}
...
@@ -170,9 +214,10 @@ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) {
...
@@ -170,9 +214,10 @@ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) {
len
->
ptr
=
sdscatprintf
(
sdsempty
(),
"*%ld
\r\n
"
,
length
);
len
->
ptr
=
sdscatprintf
(
sdsempty
(),
"*%ld
\r\n
"
,
length
);
if
(
ln
->
next
!=
NULL
)
{
if
(
ln
->
next
!=
NULL
)
{
next
=
listNodeValue
(
ln
->
next
);
next
=
listNodeValue
(
ln
->
next
);
/* Only glue when the next node is a reply chunk. */
if
(
next
->
type
==
REDIS_REPLY_NODE
)
{
/* Only glue when the next node is an sds */
len
->
ptr
=
sdscatlen
(
len
->
ptr
,
next
->
ptr
,
sdslen
(
next
->
ptr
));
if
(
next
->
ptr
!=
NULL
)
{
len
->
ptr
=
sdscat
(
len
->
ptr
,
next
->
ptr
);
listDelNode
(
c
->
reply
,
ln
->
next
);
listDelNode
(
c
->
reply
,
ln
->
next
);
}
}
}
}
...
...
src/object.c
浏览文件 @
36c19d03
...
@@ -196,7 +196,6 @@ void decrRefCount(void *obj) {
...
@@ -196,7 +196,6 @@ void decrRefCount(void *obj) {
case
REDIS_SET
:
freeSetObject
(
o
);
break
;
case
REDIS_SET
:
freeSetObject
(
o
);
break
;
case
REDIS_ZSET
:
freeZsetObject
(
o
);
break
;
case
REDIS_ZSET
:
freeZsetObject
(
o
);
break
;
case
REDIS_HASH
:
freeHashObject
(
o
);
break
;
case
REDIS_HASH
:
freeHashObject
(
o
);
break
;
case
REDIS_REPLY_NODE
:
freeStringObject
(
o
);
break
;
default:
redisPanic
(
"Unknown object type"
);
break
;
default:
redisPanic
(
"Unknown object type"
);
break
;
}
}
o
->
ptr
=
NULL
;
/* defensive programming. We'll see NULL in traces. */
o
->
ptr
=
NULL
;
/* defensive programming. We'll see NULL in traces. */
...
...
src/redis.h
浏览文件 @
36c19d03
...
@@ -47,15 +47,7 @@
...
@@ -47,15 +47,7 @@
#define REDIS_MAX_WRITE_PER_EVENT (1024*64)
#define REDIS_MAX_WRITE_PER_EVENT (1024*64)
#define REDIS_REQUEST_MAX_SIZE (1024*1024*256)
/* max bytes in inline command */
#define REDIS_REQUEST_MAX_SIZE (1024*1024*256)
/* max bytes in inline command */
#define REDIS_SHARED_INTEGERS 10000
#define REDIS_SHARED_INTEGERS 10000
#define REDIS_REPLY_CHUNK_BYTES (5*1500)
/* 5 TCP packets with default MTU */
/* Size of a reply chunk, configured to exactly allocate 4k bytes */
#define REDIS_REPLY_CHUNK_BYTES (4*1024)
#define REDIS_REPLY_CHUNK_SIZE (REDIS_REPLY_CHUNK_BYTES-sizeof(struct sdshdr)-1-sizeof(size_t))
/* It doesn't make sense to memcpy objects to a chunk when the net result is
* not being able to glue other objects. We want to make sure it can be glued
* to at least a bulk length or \r\n, so set the threshold to be a couple
* of bytes less than the size of the buffer. */
#define REDIS_REPLY_CHUNK_THRESHOLD (REDIS_REPLY_CHUNK_SIZE-16)
/* If more then REDIS_WRITEV_THRESHOLD write packets are pending use writev */
/* If more then REDIS_WRITEV_THRESHOLD write packets are pending use writev */
#define REDIS_WRITEV_THRESHOLD 3
#define REDIS_WRITEV_THRESHOLD 3
...
@@ -81,7 +73,6 @@
...
@@ -81,7 +73,6 @@
#define REDIS_SET 2
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_ZSET 3
#define REDIS_HASH 4
#define REDIS_HASH 4
#define REDIS_REPLY_NODE 5
#define REDIS_VMPOINTER 8
#define REDIS_VMPOINTER 8
/* Objects encoding. Some kind of objects like Strings and Hashes can be
/* Objects encoding. Some kind of objects like Strings and Hashes can be
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录