Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
cd8788f2
Commit
cd8788f2
authored
Oct 15, 2010
by
Pieter Noordhuis
Browse files
Refactor request parsing code for efficiency
parent
5a4f9f27
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/networking.c
View file @
cd8788f2
...
@@ -28,13 +28,11 @@ redisClient *createClient(int fd) {
...
@@ -28,13 +28,11 @@ redisClient *createClient(int fd) {
selectDb
(
c
,
0
);
selectDb
(
c
,
0
);
c
->
fd
=
fd
;
c
->
fd
=
fd
;
c
->
querybuf
=
sdsempty
();
c
->
querybuf
=
sdsempty
();
c
->
newline
=
NULL
;
c
->
reqtype
=
0
;
c
->
argc
=
0
;
c
->
argc
=
0
;
c
->
argv
=
NULL
;
c
->
argv
=
NULL
;
c
->
multibulklen
=
0
;
c
->
bulklen
=
-
1
;
c
->
bulklen
=
-
1
;
c
->
multibulk
=
0
;
c
->
mbargc
=
0
;
c
->
mbargv
=
NULL
;
c
->
sentlen
=
0
;
c
->
sentlen
=
0
;
c
->
flags
=
0
;
c
->
flags
=
0
;
c
->
lastinteraction
=
time
(
NULL
);
c
->
lastinteraction
=
time
(
NULL
);
...
@@ -374,13 +372,9 @@ void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -374,13 +372,9 @@ void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
static
void
freeClientArgv
(
redisClient
*
c
)
{
static
void
freeClientArgv
(
redisClient
*
c
)
{
int
j
;
int
j
;
for
(
j
=
0
;
j
<
c
->
argc
;
j
++
)
for
(
j
=
0
;
j
<
c
->
argc
;
j
++
)
decrRefCount
(
c
->
argv
[
j
]);
decrRefCount
(
c
->
argv
[
j
]);
for
(
j
=
0
;
j
<
c
->
mbargc
;
j
++
)
decrRefCount
(
c
->
mbargv
[
j
]);
c
->
argc
=
0
;
c
->
argc
=
0
;
c
->
mbargc
=
0
;
}
}
void
freeClient
(
redisClient
*
c
)
{
void
freeClient
(
redisClient
*
c
)
{
...
@@ -461,7 +455,6 @@ void freeClient(redisClient *c) {
...
@@ -461,7 +455,6 @@ void freeClient(redisClient *c) {
}
}
/* Release memory */
/* Release memory */
zfree
(
c
->
argv
);
zfree
(
c
->
argv
);
zfree
(
c
->
mbargv
);
freeClientMultiState
(
c
);
freeClientMultiState
(
c
);
zfree
(
c
);
zfree
(
c
);
}
}
...
@@ -549,6 +542,7 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -549,6 +542,7 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
/* Close connection after entire reply has been sent. */
/* Close connection after entire reply has been sent. */
if
(
c
->
flags
&
REDIS_QUIT
)
freeClient
(
c
);
if
(
c
->
flags
&
REDIS_QUIT
)
freeClient
(
c
);
if
(
c
->
flags
&
REDIS_CLOSE_AFTER_REPLY
)
freeClient
(
c
);
}
}
}
}
...
@@ -633,9 +627,9 @@ void sendReplyToClientWritev(aeEventLoop *el, int fd, void *privdata, int mask)
...
@@ -633,9 +627,9 @@ void sendReplyToClientWritev(aeEventLoop *el, int fd, void *privdata, int mask)
/* resetClient prepare the client to process the next command */
/* resetClient prepare the client to process the next command */
void
resetClient
(
redisClient
*
c
)
{
void
resetClient
(
redisClient
*
c
)
{
freeClientArgv
(
c
);
freeClientArgv
(
c
);
c
->
reqtype
=
0
;
c
->
multibulklen
=
0
;
c
->
bulklen
=
-
1
;
c
->
bulklen
=
-
1
;
c
->
multibulk
=
0
;
c
->
newline
=
NULL
;
}
}
void
closeTimedoutClients
(
void
)
{
void
closeTimedoutClients
(
void
)
{
...
@@ -666,95 +660,169 @@ void closeTimedoutClients(void) {
...
@@ -666,95 +660,169 @@ void closeTimedoutClients(void) {
}
}
}
}
void
processInputBuffer
(
redisClient
*
c
)
{
int
processInlineBuffer
(
redisClient
*
c
)
{
int
seeknewline
=
0
;
char
*
newline
=
strstr
(
c
->
querybuf
,
"
\r\n
"
);
int
argc
,
j
;
again:
sds
*
argv
;
/* Before to process the input buffer, make sure the client is not
size_t
querylen
;
* waitig for a blocking operation such as BLPOP. Note that the first
* iteration the client is never blocked, otherwise the processInputBuffer
/* Nothing to do without a \r\n */
* would not be called at all, but after the execution of the first commands
if
(
newline
==
NULL
)
* in the input buffer the client may be blocked, and the "goto again"
return
REDIS_ERR
;
* will try to reiterate. The following line will make it return asap. */
if
(
c
->
flags
&
REDIS_BLOCKED
||
c
->
flags
&
REDIS_IO_WAIT
)
return
;
/* Split the input buffer up to the \r\n */
querylen
=
newline
-
(
c
->
querybuf
);
/* Never continue to process the input buffer after QUIT. After the output
argv
=
sdssplitlen
(
c
->
querybuf
,
querylen
,
" "
,
1
,
&
argc
);
* buffer is flushed (with the OK), the connection will be dropped. */
if
(
c
->
flags
&
REDIS_QUIT
)
return
;
/* Leave data after the first line of the query in the buffer */
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
querylen
+
2
,
-
1
);
if
(
seeknewline
&&
c
->
bulklen
==
-
1
)
c
->
newline
=
strchr
(
c
->
querybuf
,
'\n'
);
seeknewline
=
1
;
/* Setup argv array on client structure */
if
(
c
->
bulklen
==
-
1
)
{
if
(
c
->
argv
)
zfree
(
c
->
argv
);
/* Read the first line of the query */
c
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
argc
);
size_t
querylen
;
/* Create redis objects for all arguments. */
if
(
c
->
newline
)
{
for
(
c
->
argc
=
0
,
j
=
0
;
j
<
argc
;
j
++
)
{
char
*
p
=
c
->
newline
;
if
(
sdslen
(
argv
[
j
]))
{
sds
query
,
*
argv
;
c
->
argv
[
c
->
argc
]
=
createObject
(
REDIS_STRING
,
argv
[
j
]);
int
argc
,
j
;
c
->
argc
++
;
}
else
{
c
->
newline
=
NULL
;
sdsfree
(
argv
[
j
]);
query
=
c
->
querybuf
;
}
c
->
querybuf
=
sdsempty
();
}
querylen
=
1
+
(
p
-
(
query
));
zfree
(
argv
);
if
(
sdslen
(
query
)
>
querylen
)
{
return
REDIS_OK
;
/* leave data after the first line of the query in the buffer */
}
c
->
querybuf
=
sdscatlen
(
c
->
querybuf
,
query
+
querylen
,
sdslen
(
query
)
-
querylen
);
}
/* Helper function. Trims query buffer to make the function that processes
*
p
=
'\0'
;
/* remove "\n" */
* multi bulk requests idempotent. */
if
(
*
(
p
-
1
)
==
'\r'
)
*
(
p
-
1
)
=
'\0'
;
/* and "\r" if any */
static
void
setProtocolError
(
redisClient
*
c
,
int
pos
)
{
sdsupdatelen
(
query
);
c
->
flags
|=
REDIS_CLOSE_AFTER_REPLY
;
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
pos
,
-
1
);
/* Now we can split the query in arguments */
}
argv
=
sdssplitlen
(
query
,
sdslen
(
query
),
" "
,
1
,
&
argc
);
sdsfree
(
query
);
int
processMultibulkBuffer
(
redisClient
*
c
)
{
char
*
newline
=
NULL
;
if
(
c
->
argv
)
zfree
(
c
->
argv
);
char
*
eptr
;
c
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
argc
);
int
pos
=
0
,
tolerr
;
long
bulklen
;
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
if
(
sdslen
(
argv
[
j
]))
{
if
(
c
->
multibulklen
==
0
)
{
c
->
argv
[
c
->
argc
]
=
createObject
(
REDIS_STRING
,
argv
[
j
]);
/* The client should have been reset */
c
->
argc
++
;
redisAssert
(
c
->
argc
==
0
);
}
else
{
sdsfree
(
argv
[
j
]);
/* Multi bulk length cannot be read without a \r\n */
newline
=
strstr
(
c
->
querybuf
,
"
\r\n
"
);
if
(
newline
==
NULL
)
return
REDIS_ERR
;
/* We know for sure there is a whole line since newline != NULL,
* so go ahead and find out the multi bulk length. */
redisAssert
(
c
->
querybuf
[
0
]
==
'*'
);
c
->
multibulklen
=
strtol
(
c
->
querybuf
+
1
,
&
eptr
,
10
);
pos
=
(
newline
-
c
->
querybuf
)
+
2
;
if
(
c
->
multibulklen
<=
0
)
{
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
pos
,
-
1
);
return
REDIS_OK
;
}
/* Setup argv array on client structure */
if
(
c
->
argv
)
zfree
(
c
->
argv
);
c
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
c
->
multibulklen
);
/* Search new newline */
newline
=
strstr
(
c
->
querybuf
+
pos
,
"
\r\n
"
);
}
redisAssert
(
c
->
multibulklen
>
0
);
while
(
c
->
multibulklen
)
{
/* Read bulk length if unknown */
if
(
c
->
bulklen
==
-
1
)
{
newline
=
strstr
(
c
->
querybuf
+
pos
,
"
\r\n
"
);
if
(
newline
!=
NULL
)
{
if
(
c
->
querybuf
[
pos
]
!=
'$'
)
{
addReplyErrorFormat
(
c
,
"Protocol error: expected '$', got '%c'"
,
c
->
querybuf
[
pos
]);
setProtocolError
(
c
,
pos
);
return
REDIS_ERR
;
}
}
bulklen
=
strtol
(
c
->
querybuf
+
pos
+
1
,
&
eptr
,
10
);
tolerr
=
(
eptr
[
0
]
!=
'\r'
);
if
(
tolerr
||
bulklen
==
LONG_MIN
||
bulklen
==
LONG_MAX
||
bulklen
<
0
||
bulklen
>
1024
*
1024
*
1024
)
{
addReplyError
(
c
,
"Protocol error: invalid bulk length"
);
setProtocolError
(
c
,
pos
);
return
REDIS_ERR
;
}
pos
+=
eptr
-
(
c
->
querybuf
+
pos
)
+
2
;
c
->
bulklen
=
bulklen
;
}
else
{
/* No newline in current buffer, so wait for more data */
break
;
}
}
zfree
(
argv
);
}
if
(
c
->
argc
)
{
/* Execute the command. If the client is still valid
/* Read bulk argument */
* after processCommand() return and there is something
if
(
sdslen
(
c
->
querybuf
)
-
pos
<
(
unsigned
)(
c
->
bulklen
+
2
))
{
* on the query buffer try to process the next command. */
/* Not enough data (+2 == trailing \r\n) */
if
(
processCommand
(
c
)
&&
sdslen
(
c
->
querybuf
))
goto
again
;
break
;
}
else
{
c
->
argv
[
c
->
argc
++
]
=
createStringObject
(
c
->
querybuf
+
pos
,
c
->
bulklen
);
pos
+=
c
->
bulklen
+
2
;
c
->
bulklen
=
-
1
;
c
->
multibulklen
--
;
}
}
/* Trim to pos */
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
pos
,
-
1
);
/* We're done when c->multibulk == 0 */
if
(
c
->
multibulklen
==
0
)
{
return
REDIS_OK
;
}
return
REDIS_ERR
;
}
void
processInputBuffer
(
redisClient
*
c
)
{
/* Keep processing while there is something in the input buffer */
while
(
sdslen
(
c
->
querybuf
))
{
/* Before to process the input buffer, make sure the client is not
* waitig for a blocking operation such as BLPOP. Note that the first
* iteration the client is never blocked, otherwise the processInputBuffer
* would not be called at all, but after the execution of the first commands
* in the input buffer the client may be blocked, and the "goto again"
* will try to reiterate. The following line will make it return asap. */
if
(
c
->
flags
&
REDIS_BLOCKED
||
c
->
flags
&
REDIS_IO_WAIT
)
return
;
/* Never continue to process the input buffer after QUIT. After the output
* buffer is flushed (with the OK), the connection will be dropped. */
if
(
c
->
flags
&
REDIS_QUIT
)
return
;
/* Determine request type when unknown. */
if
(
!
c
->
reqtype
)
{
if
(
c
->
querybuf
[
0
]
==
'*'
)
{
c
->
reqtype
=
REDIS_REQ_MULTIBULK
;
}
else
{
}
else
{
/* Nothing to process, argc == 0. Just process the query
c
->
reqtype
=
REDIS_REQ_INLINE
;
* buffer if it's not empty or return to the caller */
if
(
sdslen
(
c
->
querybuf
))
goto
again
;
}
}
return
;
}
else
if
(
sdslen
(
c
->
querybuf
)
>=
REDIS_REQUEST_MAX_SIZE
)
{
redisLog
(
REDIS_VERBOSE
,
"Client protocol error"
);
freeClient
(
c
);
return
;
}
}
}
else
{
/* Bulk read handling. Note that if we are at this point
if
(
c
->
reqtype
==
REDIS_REQ_INLINE
)
{
the client already sent a command terminated with a newline,
if
(
processInlineBuffer
(
c
)
!=
REDIS_OK
)
break
;
we are reading the bulk data that is actually the last
}
else
if
(
c
->
reqtype
==
REDIS_REQ_MULTIBULK
)
{
argument of the command. */
if
(
processMultibulkBuffer
(
c
)
!=
REDIS_OK
)
break
;
int
qbl
=
sdslen
(
c
->
querybuf
);
}
else
{
redisPanic
(
"Unknown request type"
);
if
(
c
->
bulklen
<=
qbl
)
{
/* Copy everything but the final CRLF as final argument */
c
->
argv
[
c
->
argc
]
=
createStringObject
(
c
->
querybuf
,
c
->
bulklen
-
2
);
c
->
argc
++
;
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
c
->
bulklen
,
-
1
);
/* Process the command. If the client is still valid after
* the processing and there is more data in the buffer
* try to parse it. */
if
(
processCommand
(
c
)
&&
sdslen
(
c
->
querybuf
))
goto
again
;
return
;
}
}
/* Multibulk processing could see a <= 0 length. */
if
(
c
->
argc
>
0
)
processCommand
(
c
);
resetClient
(
c
);
}
}
}
}
...
@@ -780,14 +848,8 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -780,14 +848,8 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
return
;
return
;
}
}
if
(
nread
)
{
if
(
nread
)
{
size_t
oldlen
=
sdslen
(
c
->
querybuf
);
c
->
querybuf
=
sdscatlen
(
c
->
querybuf
,
buf
,
nread
);
c
->
querybuf
=
sdscatlen
(
c
->
querybuf
,
buf
,
nread
);
c
->
lastinteraction
=
time
(
NULL
);
c
->
lastinteraction
=
time
(
NULL
);
/* Scan this new piece of the query for the newline. We do this
* here in order to make sure we perform this scan just one time
* per piece of buffer, leading to an O(N) scan instead of O(N*N) */
if
(
c
->
bulklen
==
-
1
&&
c
->
newline
==
NULL
)
c
->
newline
=
strchr
(
c
->
querybuf
+
oldlen
,
'\n'
);
}
else
{
}
else
{
return
;
return
;
}
}
...
...
src/redis.c
View file @
cd8788f2
...
@@ -889,79 +889,6 @@ void call(redisClient *c, struct redisCommand *cmd) {
...
@@ -889,79 +889,6 @@ void call(redisClient *c, struct redisCommand *cmd) {
int
processCommand
(
redisClient
*
c
)
{
int
processCommand
(
redisClient
*
c
)
{
struct
redisCommand
*
cmd
;
struct
redisCommand
*
cmd
;
/* Handle the multi bulk command type. This is an alternative protocol
* supported by Redis in order to receive commands that are composed of
* multiple binary-safe "bulk" arguments. The latency of processing is
* a bit higher but this allows things like multi-sets, so if this
* protocol is used only for MSET and similar commands this is a big win. */
if
(
c
->
multibulk
==
0
&&
c
->
argc
==
1
&&
((
char
*
)(
c
->
argv
[
0
]
->
ptr
))[
0
]
==
'*'
)
{
c
->
multibulk
=
atoi
(((
char
*
)
c
->
argv
[
0
]
->
ptr
)
+
1
);
if
(
c
->
multibulk
<=
0
)
{
resetClient
(
c
);
return
1
;
}
else
{
decrRefCount
(
c
->
argv
[
c
->
argc
-
1
]);
c
->
argc
--
;
return
1
;
}
}
else
if
(
c
->
multibulk
)
{
if
(
c
->
bulklen
==
-
1
)
{
if
(((
char
*
)
c
->
argv
[
0
]
->
ptr
)[
0
]
!=
'$'
)
{
addReplyError
(
c
,
"multi bulk protocol error"
);
resetClient
(
c
);
return
1
;
}
else
{
char
*
eptr
;
long
bulklen
=
strtol
(((
char
*
)
c
->
argv
[
0
]
->
ptr
)
+
1
,
&
eptr
,
10
);
int
perr
=
eptr
[
0
]
!=
'\0'
;
decrRefCount
(
c
->
argv
[
0
]);
if
(
perr
||
bulklen
==
LONG_MIN
||
bulklen
==
LONG_MAX
||
bulklen
<
0
||
bulklen
>
1024
*
1024
*
1024
)
{
c
->
argc
--
;
addReplyError
(
c
,
"invalid bulk write count"
);
resetClient
(
c
);
return
1
;
}
c
->
argc
--
;
c
->
bulklen
=
bulklen
+
2
;
/* add two bytes for CR+LF */
return
1
;
}
}
else
{
c
->
mbargv
=
zrealloc
(
c
->
mbargv
,(
sizeof
(
robj
*
))
*
(
c
->
mbargc
+
1
));
c
->
mbargv
[
c
->
mbargc
]
=
c
->
argv
[
0
];
c
->
mbargc
++
;
c
->
argc
--
;
c
->
multibulk
--
;
if
(
c
->
multibulk
==
0
)
{
robj
**
auxargv
;
int
auxargc
;
/* Here we need to swap the multi-bulk argc/argv with the
* normal argc/argv of the client structure. */
auxargv
=
c
->
argv
;
c
->
argv
=
c
->
mbargv
;
c
->
mbargv
=
auxargv
;
auxargc
=
c
->
argc
;
c
->
argc
=
c
->
mbargc
;
c
->
mbargc
=
auxargc
;
/* We need to set bulklen to something different than -1
* in order for the code below to process the command without
* to try to read the last argument of a bulk command as
* a special argument. */
c
->
bulklen
=
0
;
/* continue below and process the command */
}
else
{
c
->
bulklen
=
-
1
;
return
1
;
}
}
}
/* -- end of multi bulk commands processing -- */
/* The QUIT command is handled separately. Normal command procs will
/* The QUIT command is handled separately. Normal command procs will
* go through checking for replication and QUIT will cause trouble
* go through checking for replication and QUIT will cause trouble
* when FORCE_REPLICATION is enabled and would be implemented in
* when FORCE_REPLICATION is enabled and would be implemented in
...
@@ -970,7 +897,7 @@ int processCommand(redisClient *c) {
...
@@ -970,7 +897,7 @@ int processCommand(redisClient *c) {
if
(
!
strcasecmp
(
c
->
argv
[
0
]
->
ptr
,
"quit"
))
{
if
(
!
strcasecmp
(
c
->
argv
[
0
]
->
ptr
,
"quit"
))
{
c
->
flags
|=
REDIS_QUIT
;
c
->
flags
|=
REDIS_QUIT
;
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
return
0
;
return
REDIS_ERR
;
}
}
/* Now lookup the command and check ASAP about trivial error conditions
/* Now lookup the command and check ASAP about trivial error conditions
...
@@ -979,46 +906,14 @@ int processCommand(redisClient *c) {
...
@@ -979,46 +906,14 @@ int processCommand(redisClient *c) {
if
(
!
cmd
)
{
if
(
!
cmd
)
{
addReplyErrorFormat
(
c
,
"unknown command '%s'"
,
addReplyErrorFormat
(
c
,
"unknown command '%s'"
,
(
char
*
)
c
->
argv
[
0
]
->
ptr
);
(
char
*
)
c
->
argv
[
0
]
->
ptr
);
resetClient
(
c
);
return
REDIS_OK
;
return
1
;
}
else
if
((
cmd
->
arity
>
0
&&
cmd
->
arity
!=
c
->
argc
)
||
}
else
if
((
cmd
->
arity
>
0
&&
cmd
->
arity
!=
c
->
argc
)
||
(
c
->
argc
<
-
cmd
->
arity
))
{
(
c
->
argc
<
-
cmd
->
arity
))
{
addReplyErrorFormat
(
c
,
"wrong number of arguments for '%s' command"
,
addReplyErrorFormat
(
c
,
"wrong number of arguments for '%s' command"
,
cmd
->
name
);
cmd
->
name
);
resetClient
(
c
);
return
REDIS_OK
;
return
1
;
}
else
if
(
cmd
->
flags
&
REDIS_CMD_BULK
&&
c
->
bulklen
==
-
1
)
{
/* This is a bulk command, we have to read the last argument yet. */
char
*
eptr
;
long
bulklen
=
strtol
(
c
->
argv
[
c
->
argc
-
1
]
->
ptr
,
&
eptr
,
10
);
int
perr
=
eptr
[
0
]
!=
'\0'
;
decrRefCount
(
c
->
argv
[
c
->
argc
-
1
]);
if
(
perr
||
bulklen
==
LONG_MAX
||
bulklen
==
LONG_MIN
||
bulklen
<
0
||
bulklen
>
1024
*
1024
*
1024
)
{
c
->
argc
--
;
addReplyError
(
c
,
"invalid bulk write count"
);
resetClient
(
c
);
return
1
;
}
c
->
argc
--
;
c
->
bulklen
=
bulklen
+
2
;
/* add two bytes for CR+LF */
/* It is possible that the bulk read is already in the
* buffer. Check this condition and handle it accordingly.
* This is just a fast path, alternative to call processInputBuffer().
* It's a good idea since the code is small and this condition
* happens most of the times. */
if
((
signed
)
sdslen
(
c
->
querybuf
)
>=
c
->
bulklen
)
{
c
->
argv
[
c
->
argc
]
=
createStringObject
(
c
->
querybuf
,
c
->
bulklen
-
2
);
c
->
argc
++
;
c
->
querybuf
=
sdsrange
(
c
->
querybuf
,
c
->
bulklen
,
-
1
);
}
else
{
/* Otherwise return... there is to read the last argument
* from the socket. */
return
1
;
}
}
}
/* Let's try to encode the bulk object to save space. */
/* Let's try to encode the bulk object to save space. */
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
c
->
argv
[
c
->
argc
-
1
]
=
tryObjectEncoding
(
c
->
argv
[
c
->
argc
-
1
]);
c
->
argv
[
c
->
argc
-
1
]
=
tryObjectEncoding
(
c
->
argv
[
c
->
argc
-
1
]);
...
@@ -1026,8 +921,7 @@ int processCommand(redisClient *c) {
...
@@ -1026,8 +921,7 @@ int processCommand(redisClient *c) {
/* Check if the user is authenticated */
/* Check if the user is authenticated */
if
(
server
.
requirepass
&&
!
c
->
authenticated
&&
cmd
->
proc
!=
authCommand
)
{
if
(
server
.
requirepass
&&
!
c
->
authenticated
&&
cmd
->
proc
!=
authCommand
)
{
addReplyError
(
c
,
"operation not permitted"
);
addReplyError
(
c
,
"operation not permitted"
);
resetClient
(
c
);
return
REDIS_OK
;
return
1
;
}
}
/* Handle the maxmemory directive.
/* Handle the maxmemory directive.
...
@@ -1040,8 +934,7 @@ int processCommand(redisClient *c) {
...
@@ -1040,8 +934,7 @@ int processCommand(redisClient *c) {
zmalloc_used_memory
()
>
server
.
maxmemory
)
zmalloc_used_memory
()
>
server
.
maxmemory
)
{
{
addReplyError
(
c
,
"command not allowed when used memory > 'maxmemory'"
);
addReplyError
(
c
,
"command not allowed when used memory > 'maxmemory'"
);
resetClient
(
c
);
return
REDIS_OK
;
return
1
;
}
}
/* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */
/* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */
...
@@ -1050,8 +943,7 @@ int processCommand(redisClient *c) {
...
@@ -1050,8 +943,7 @@ int processCommand(redisClient *c) {
cmd
->
proc
!=
subscribeCommand
&&
cmd
->
proc
!=
unsubscribeCommand
&&
cmd
->
proc
!=
subscribeCommand
&&
cmd
->
proc
!=
unsubscribeCommand
&&
cmd
->
proc
!=
psubscribeCommand
&&
cmd
->
proc
!=
punsubscribeCommand
)
{
cmd
->
proc
!=
psubscribeCommand
&&
cmd
->
proc
!=
punsubscribeCommand
)
{
addReplyError
(
c
,
"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context"
);
addReplyError
(
c
,
"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context"
);
resetClient
(
c
);
return
REDIS_OK
;
return
1
;
}
}
/* Exec the command */
/* Exec the command */
...
@@ -1066,10 +958,7 @@ int processCommand(redisClient *c) {
...
@@ -1066,10 +958,7 @@ int processCommand(redisClient *c) {
blockClientOnSwappedKeys
(
c
,
cmd
))
return
1
;
blockClientOnSwappedKeys
(
c
,
cmd
))
return
1
;
call
(
c
,
cmd
);
call
(
c
,
cmd
);
}
}
return
REDIS_OK
;
/* Prepare the client for the next command */
resetClient
(
c
);
return
1
;
}
}
/*================================== Shutdown =============================== */
/*================================== Shutdown =============================== */
...
...
src/redis.h
View file @
cd8788f2
...
@@ -145,6 +145,12 @@
...
@@ -145,6 +145,12 @@
#define REDIS_IO_WAIT 32
/* The client is waiting for Virtual Memory I/O */
#define REDIS_IO_WAIT 32
/* The client is waiting for Virtual Memory I/O */
#define REDIS_DIRTY_CAS 64
/* Watched keys modified. EXEC will fail. */
#define REDIS_DIRTY_CAS 64
/* Watched keys modified. EXEC will fail. */
#define REDIS_QUIT 128
/* Client will be disconnected after reply is sent */
#define REDIS_QUIT 128
/* Client will be disconnected after reply is sent */
#define REDIS_CLOSE_AFTER_REPLY 256
/* Close connection immediately once the
* reply has been sent. */
/* Client request types */
#define REDIS_REQ_INLINE 1
#define REDIS_REQ_MULTIBULK 2
/* Slave replication state - slave side */
/* Slave replication state - slave side */
#define REDIS_REPL_NONE 0
/* No active replication */
#define REDIS_REPL_NONE 0
/* No active replication */
...
@@ -286,11 +292,11 @@ typedef struct redisClient {
...
@@ -286,11 +292,11 @@ typedef struct redisClient {
redisDb
*
db
;
redisDb
*
db
;
int
dictid
;
int
dictid
;
sds
querybuf
;
sds
querybuf
;
robj
**
argv
,
**
mbargv
;
int
argc
;
char
*
newline
;
/* pointing to the detected newline in querybuf */
robj
**
argv
;
int
argc
,
mbargc
;
int
reqtype
;
long
bulklen
;
/* bulk read len. -1 if not in bulk read mode
*/
int
multi
bulklen
;
/* number of multi bulk arguments left to read
*/
int
multibulk
;
/* multi bulk command format active
*/
long
bulklen
;
/* length of bulk argument in multi bulk request
*/
list
*
reply
;
list
*
reply
;
int
sentlen
;
int
sentlen
;
time_t
lastinteraction
;
/* time of the last interaction, used for timeout */
time_t
lastinteraction
;
/* time of the last interaction, used for timeout */
...
...
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