Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
51669c5a
Commit
51669c5a
authored
Jan 23, 2012
by
antirez
Browse files
client buffer handling refactoring and optimization
parent
3c0602ff
Changes
1
Show whitespace changes
Inline
Side-by-side
src/networking.c
View file @
51669c5a
...
@@ -67,11 +67,23 @@ redisClient *createClient(int fd) {
...
@@ -67,11 +67,23 @@ redisClient *createClient(int fd) {
return
c
;
return
c
;
}
}
/* Set the event loop to listen for write events on the client's socket.
/* This function is called every time we are going to transmit new data
* Typically gets called every time a reply is built. */
* to the client. The behavior is the following:
int
_installWriteEvent
(
redisClient
*
c
)
{
*
* If the client should receive new data (normal clients will) the function
* returns REDIS_OK, and make sure to install the write handler in our event
* loop so that when the socket is writable new data gets written.
*
* If the client should not receive new data, because it is a fake client
* or a slave, or because the setup of the write handler failed, the function
* returns REDIS_ERR.
*
* Typically gets called every time a reply is built, before adding more
* data to the clients output buffers. If the function returns REDIS_ERR no
* data should be appended to the output buffers. */
int
prepareClientToWrite
(
redisClient
*
c
)
{
if
(
c
->
flags
&
REDIS_LUA_CLIENT
)
return
REDIS_OK
;
if
(
c
->
flags
&
REDIS_LUA_CLIENT
)
return
REDIS_OK
;
if
(
c
->
fd
<=
0
)
return
REDIS_ERR
;
if
(
c
->
fd
<=
0
)
return
REDIS_ERR
;
/* Fake client */
if
(
c
->
bufpos
==
0
&&
listLength
(
c
->
reply
)
==
0
&&
if
(
c
->
bufpos
==
0
&&
listLength
(
c
->
reply
)
==
0
&&
(
c
->
replstate
==
REDIS_REPL_NONE
||
(
c
->
replstate
==
REDIS_REPL_NONE
||
c
->
replstate
==
REDIS_REPL_ONLINE
)
&&
c
->
replstate
==
REDIS_REPL_ONLINE
)
&&
...
@@ -203,7 +215,7 @@ void _addReplyStringToList(redisClient *c, char *s, size_t len) {
...
@@ -203,7 +215,7 @@ void _addReplyStringToList(redisClient *c, char *s, size_t len) {
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
void
addReply
(
redisClient
*
c
,
robj
*
obj
)
{
void
addReply
(
redisClient
*
c
,
robj
*
obj
)
{
if
(
_installWriteEvent
(
c
)
!=
REDIS_OK
)
return
;
if
(
prepareClientToWrite
(
c
)
!=
REDIS_OK
)
return
;
/* This is an important place where we can avoid copy-on-write
/* This is an important place where we can avoid copy-on-write
* when there is a saving child running, avoiding touching the
* when there is a saving child running, avoiding touching the
...
@@ -215,19 +227,31 @@ void addReply(redisClient *c, robj *obj) {
...
@@ -215,19 +227,31 @@ void addReply(redisClient *c, robj *obj) {
if
(
obj
->
encoding
==
REDIS_ENCODING_RAW
)
{
if
(
obj
->
encoding
==
REDIS_ENCODING_RAW
)
{
if
(
_addReplyToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
))
!=
REDIS_OK
)
if
(
_addReplyToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
))
!=
REDIS_OK
)
_addReplyObjectToList
(
c
,
obj
);
_addReplyObjectToList
(
c
,
obj
);
}
else
{
}
else
if
(
obj
->
encoding
==
REDIS_ENCODING_INT
)
{
/* FIXME: convert the long into string and use _addReplyToBuffer()
/* Optimization: if there is room in the static buffer for 32 bytes
* instead of calling getDecodedObject. As this place in the
* (more than the max chars a 64 bit integer can take as string) we
* code is too performance critical. */
* avoid decoding the object and go for the lower level approach. */
if
(
listLength
(
c
->
reply
)
==
0
&&
(
sizeof
(
c
->
buf
)
-
c
->
bufpos
)
>=
32
)
{
char
buf
[
32
];
int
len
;
len
=
ll2string
(
buf
,
sizeof
(
buf
),(
long
)
obj
->
ptr
);
if
(
_addReplyToBuffer
(
c
,
buf
,
len
)
==
REDIS_OK
)
return
;
/* else... continue with the normal code path, but should never
* happen actually since we verified there is room. */
}
obj
=
getDecodedObject
(
obj
);
obj
=
getDecodedObject
(
obj
);
if
(
_addReplyToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
))
!=
REDIS_OK
)
if
(
_addReplyToBuffer
(
c
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
))
!=
REDIS_OK
)
_addReplyObjectToList
(
c
,
obj
);
_addReplyObjectToList
(
c
,
obj
);
decrRefCount
(
obj
);
decrRefCount
(
obj
);
}
else
{
redisPanic
(
"Wrong obj->encoding in addReply()"
);
}
}
}
}
void
addReplySds
(
redisClient
*
c
,
sds
s
)
{
void
addReplySds
(
redisClient
*
c
,
sds
s
)
{
if
(
_installWriteEvent
(
c
)
!=
REDIS_OK
)
{
if
(
prepareClientToWrite
(
c
)
!=
REDIS_OK
)
{
/* The caller expects the sds to be free'd. */
/* The caller expects the sds to be free'd. */
sdsfree
(
s
);
sdsfree
(
s
);
return
;
return
;
...
@@ -241,19 +265,19 @@ void addReplySds(redisClient *c, sds s) {
...
@@ -241,19 +265,19 @@ void addReplySds(redisClient *c, sds s) {
}
}
void
addReplyString
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
void
addReplyString
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
if
(
_installWriteEvent
(
c
)
!=
REDIS_OK
)
return
;
if
(
prepareClientToWrite
(
c
)
!=
REDIS_OK
)
return
;
if
(
_addReplyToBuffer
(
c
,
s
,
len
)
!=
REDIS_OK
)
if
(
_addReplyToBuffer
(
c
,
s
,
len
)
!=
REDIS_OK
)
_addReplyStringToList
(
c
,
s
,
len
);
_addReplyStringToList
(
c
,
s
,
len
);
}
}
void
_
addReplyError
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
void
addReplyError
Length
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
addReplyString
(
c
,
"-ERR "
,
5
);
addReplyString
(
c
,
"-ERR "
,
5
);
addReplyString
(
c
,
s
,
len
);
addReplyString
(
c
,
s
,
len
);
addReplyString
(
c
,
"
\r\n
"
,
2
);
addReplyString
(
c
,
"
\r\n
"
,
2
);
}
}
void
addReplyError
(
redisClient
*
c
,
char
*
err
)
{
void
addReplyError
(
redisClient
*
c
,
char
*
err
)
{
_
addReplyError
(
c
,
err
,
strlen
(
err
));
addReplyError
Length
(
c
,
err
,
strlen
(
err
));
}
}
void
addReplyErrorFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
{
void
addReplyErrorFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
{
...
@@ -268,18 +292,18 @@ void addReplyErrorFormat(redisClient *c, const char *fmt, ...) {
...
@@ -268,18 +292,18 @@ void addReplyErrorFormat(redisClient *c, const char *fmt, ...) {
for
(
j
=
0
;
j
<
l
;
j
++
)
{
for
(
j
=
0
;
j
<
l
;
j
++
)
{
if
(
s
[
j
]
==
'\r'
||
s
[
j
]
==
'\n'
)
s
[
j
]
=
' '
;
if
(
s
[
j
]
==
'\r'
||
s
[
j
]
==
'\n'
)
s
[
j
]
=
' '
;
}
}
_
addReplyError
(
c
,
s
,
sdslen
(
s
));
addReplyError
Length
(
c
,
s
,
sdslen
(
s
));
sdsfree
(
s
);
sdsfree
(
s
);
}
}
void
_
addReplyStatus
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
void
addReplyStatus
Length
(
redisClient
*
c
,
char
*
s
,
size_t
len
)
{
addReplyString
(
c
,
"+"
,
1
);
addReplyString
(
c
,
"+"
,
1
);
addReplyString
(
c
,
s
,
len
);
addReplyString
(
c
,
s
,
len
);
addReplyString
(
c
,
"
\r\n
"
,
2
);
addReplyString
(
c
,
"
\r\n
"
,
2
);
}
}
void
addReplyStatus
(
redisClient
*
c
,
char
*
status
)
{
void
addReplyStatus
(
redisClient
*
c
,
char
*
status
)
{
_
addReplyStatus
(
c
,
status
,
strlen
(
status
));
addReplyStatus
Length
(
c
,
status
,
strlen
(
status
));
}
}
void
addReplyStatusFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
{
void
addReplyStatusFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
{
...
@@ -287,7 +311,7 @@ void addReplyStatusFormat(redisClient *c, const char *fmt, ...) {
...
@@ -287,7 +311,7 @@ void addReplyStatusFormat(redisClient *c, const char *fmt, ...) {
va_start
(
ap
,
fmt
);
va_start
(
ap
,
fmt
);
sds
s
=
sdscatvprintf
(
sdsempty
(),
fmt
,
ap
);
sds
s
=
sdscatvprintf
(
sdsempty
(),
fmt
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
_
addReplyStatus
(
c
,
s
,
sdslen
(
s
));
addReplyStatus
Length
(
c
,
s
,
sdslen
(
s
));
sdsfree
(
s
);
sdsfree
(
s
);
}
}
...
@@ -297,7 +321,7 @@ void *addDeferredMultiBulkLength(redisClient *c) {
...
@@ -297,7 +321,7 @@ void *addDeferredMultiBulkLength(redisClient *c) {
/* Note that we install the write event here even if the object is not
/* Note that we install the write event here even if the object is not
* ready to be sent, since we are sure that before returning to the
* ready to be sent, since we are sure that before returning to the
* event loop setDeferredMultiBulkLength() will be called. */
* event loop setDeferredMultiBulkLength() will be called. */
if
(
_installWriteEvent
(
c
)
!=
REDIS_OK
)
return
NULL
;
if
(
prepareClientToWrite
(
c
)
!=
REDIS_OK
)
return
NULL
;
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_STRING
,
NULL
));
listAddNodeTail
(
c
->
reply
,
createObject
(
REDIS_STRING
,
NULL
));
return
listLast
(
c
->
reply
);
return
listLast
(
c
->
reply
);
}
}
...
@@ -336,7 +360,7 @@ void addReplyDouble(redisClient *c, double d) {
...
@@ -336,7 +360,7 @@ void addReplyDouble(redisClient *c, double d) {
/* Add a long long as integer reply or bulk len / multi bulk count.
/* Add a long long as integer reply or bulk len / multi bulk count.
* Basically this is used to output <prefix><long long><crlf>. */
* Basically this is used to output <prefix><long long><crlf>. */
void
_
addReplyLongLong
(
redisClient
*
c
,
long
long
ll
,
char
prefix
)
{
void
addReplyLongLong
WithPrefix
(
redisClient
*
c
,
long
long
ll
,
char
prefix
)
{
char
buf
[
128
];
char
buf
[
128
];
int
len
;
int
len
;
buf
[
0
]
=
prefix
;
buf
[
0
]
=
prefix
;
...
@@ -352,11 +376,11 @@ void addReplyLongLong(redisClient *c, long long ll) {
...
@@ -352,11 +376,11 @@ void addReplyLongLong(redisClient *c, long long ll) {
else
if
(
ll
==
1
)
else
if
(
ll
==
1
)
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
else
else
_
addReplyLongLong
(
c
,
ll
,
':'
);
addReplyLongLong
WithPrefix
(
c
,
ll
,
':'
);
}
}
void
addReplyMultiBulkLen
(
redisClient
*
c
,
long
length
)
{
void
addReplyMultiBulkLen
(
redisClient
*
c
,
long
length
)
{
_
addReplyLongLong
(
c
,
length
,
'*'
);
addReplyLongLong
WithPrefix
(
c
,
length
,
'*'
);
}
}
/* Create the length prefix of a bulk reply, example: $2234 */
/* Create the length prefix of a bulk reply, example: $2234 */
...
@@ -378,7 +402,7 @@ void addReplyBulkLen(redisClient *c, robj *obj) {
...
@@ -378,7 +402,7 @@ void addReplyBulkLen(redisClient *c, robj *obj) {
len
++
;
len
++
;
}
}
}
}
_
addReplyLongLong
(
c
,
len
,
'$'
);
addReplyLongLong
WithPrefix
(
c
,
len
,
'$'
);
}
}
/* Add a Redis Object as a bulk reply */
/* Add a Redis Object as a bulk reply */
...
@@ -390,7 +414,7 @@ void addReplyBulk(redisClient *c, robj *obj) {
...
@@ -390,7 +414,7 @@ void addReplyBulk(redisClient *c, robj *obj) {
/* Add a C buffer as bulk reply */
/* Add a C buffer as bulk reply */
void
addReplyBulkCBuffer
(
redisClient
*
c
,
void
*
p
,
size_t
len
)
{
void
addReplyBulkCBuffer
(
redisClient
*
c
,
void
*
p
,
size_t
len
)
{
_
addReplyLongLong
(
c
,
len
,
'$'
);
addReplyLongLong
WithPrefix
(
c
,
len
,
'$'
);
addReplyString
(
c
,
p
,
len
);
addReplyString
(
c
,
p
,
len
);
addReply
(
c
,
shared
.
crlf
);
addReply
(
c
,
shared
.
crlf
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment