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
hiredis
Commits
47e1f771
Commit
47e1f771
authored
Oct 31, 2010
by
Pieter Noordhuis
Browse files
Refactor internal function flow and add redisAppendCommand* family
parent
298e9325
Changes
2
Hide whitespace changes
Inline
Side-by-side
hiredis.c
View file @
47e1f771
...
...
@@ -730,15 +730,6 @@ int redisBufferRead(redisContext *c) {
return
REDIS_OK
;
}
int
redisGetReply
(
redisContext
*
c
,
void
**
reply
)
{
if
(
redisReplyReaderGetReply
(
c
->
reader
,
reply
)
==
REDIS_ERR
)
{
/* Copy the (protocol) error from the reader to the context. */
c
->
error
=
sdsnew
(((
redisReader
*
)
c
->
reader
)
->
error
);
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
/* Write the output buffer to the socket.
*
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
...
...
@@ -774,69 +765,137 @@ int redisBufferWrite(redisContext *c, int *done) {
return
REDIS_OK
;
}
static
int
redisCommandWriteBlock
(
redisContext
*
c
,
void
**
reply
,
char
*
str
,
size_t
len
)
{
/* Internal helper function to try and get a reply from the reader,
* or set an error in the context otherwise. */
static
int
__redisGetReply
(
redisContext
*
c
,
void
**
reply
)
{
if
(
redisReplyReaderGetReply
(
c
->
reader
,
reply
)
==
REDIS_ERR
)
{
/* Copy the (protocol) error from the reader to the context. */
c
->
error
=
sdsnew
(((
redisReader
*
)
c
->
reader
)
->
error
);
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
int
redisGetReply
(
redisContext
*
c
,
void
**
reply
)
{
int
wdone
=
0
;
void
*
aux
=
NULL
;
assert
(
c
->
flags
&
REDIS_BLOCK
);
c
->
obuf
=
sdscatlen
(
c
->
obuf
,
str
,
len
);
/* Write until done. */
do
{
if
(
redisBufferWrite
(
c
,
&
wdone
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
!
wdone
);
/* Try to read pending replies */
if
(
__redisGetReply
(
c
,
&
aux
)
==
REDIS_ERR
)
{
return
REDIS_ERR
;
}
else
{
/* Return immediately if there was a pending reply */
if
(
aux
!=
NULL
)
return
REDIS_OK
;
}
/*
Read until there is a
reply
.
*/
do
{
if
(
redisBufferRead
(
c
)
==
REDIS_ERR
)
return
REDIS_ERR
;
if
(
redis
GetReply
(
c
,
&
aux
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
aux
==
NULL
);
/*
For the blocking context, flush output buffer and read
reply */
if
(
c
->
flags
&
REDIS_BLOCK
)
{
/* Write until done */
do
{
if
(
redis
BufferWrite
(
c
,
&
wdone
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
!
wdone
);
/* Set reply object. */
if
(
reply
!=
NULL
)
*
reply
=
aux
;
/* Read until there is a reply */
do
{
if
(
redisBufferRead
(
c
)
==
REDIS_ERR
)
return
REDIS_ERR
;
if
(
__redisGetReply
(
c
,
&
aux
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
aux
==
NULL
);
/* Set reply object */
if
(
reply
!=
NULL
)
*
reply
=
aux
;
}
return
REDIS_OK
;
}
static
int
redisCommandWriteNonBlock
(
redisContext
*
c
,
char
*
str
,
size_t
len
)
{
assert
(
!
(
c
->
flags
&
REDIS_BLOCK
));
c
->
obuf
=
sdscatlen
(
c
->
obuf
,
str
,
len
);
/* Helper function for the redisAppendCommand* family of functions.
*
* Write a formatted command to the output buffer. When this family
* is used, you need to call redisGetReply yourself to retrieve
* the reply (or replies in pub/sub).
*/
void
__redisAppendCommand
(
redisContext
*
c
,
char
*
cmd
,
size_t
len
)
{
c
->
obuf
=
sdscatlen
(
c
->
obuf
,
cmd
,
len
);
/* Fire write callback */
if
(
c
->
cbCommand
.
fn
!=
NULL
)
c
->
cbCommand
.
fn
(
c
,
c
->
cbCommand
.
privdata
);
}
return
REDIS_OK
;
void
redisvAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
)
{
char
*
cmd
;
int
len
;
len
=
redisvFormatCommand
(
&
cmd
,
format
,
ap
);
__redisAppendCommand
(
c
,
cmd
,
len
);
free
(
cmd
);
}
void
redisAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
va_start
(
ap
,
format
);
redisvAppendCommand
(
c
,
format
,
ap
);
va_end
(
ap
);
}
void
redisAppendCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
char
*
cmd
;
int
len
;
len
=
redisFormatCommandArgv
(
&
cmd
,
argc
,
argv
,
argvlen
);
__redisAppendCommand
(
c
,
cmd
,
len
);
free
(
cmd
);
}
/* Write a formatted command to the output buffer. If the given context is
/* Helper function for the redisCommand* family of functions.
*
* Write a formatted command to the output buffer. If the given context is
* blocking, immediately read the reply into the "reply" pointer. When the
* context is non-blocking, the "reply" pointer will not be used and the
* command is simply appended to the write buffer.
*
* Returns the reply when a reply was succesfully retrieved. Returns NULL
* otherwise. When NULL is returned in a blocking context, the error field
* in the context will be set. */
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
* in the context will be set.
*/
static
void
*
__redisCommand
(
redisContext
*
c
,
char
*
cmd
,
size_t
len
)
{
void
*
aux
=
NULL
;
__redisAppendCommand
(
c
,
cmd
,
len
);
if
(
c
->
flags
&
REDIS_BLOCK
)
{
if
(
redisGetReply
(
c
,
&
aux
)
==
REDIS_OK
)
return
aux
;
return
NULL
;
}
return
NULL
;
}
void
*
redisvCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
)
{
char
*
cmd
;
int
len
;
void
*
reply
=
NULL
;
va_start
(
ap
,
format
);
len
=
redisvFormatCommand
(
&
cmd
,
format
,
ap
);
reply
=
__redisCommand
(
c
,
cmd
,
len
);
free
(
cmd
);
return
reply
;
}
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
void
*
reply
=
NULL
;
va_start
(
ap
,
format
);
reply
=
redisvCommand
(
c
,
format
,
ap
);
va_end
(
ap
);
return
reply
;
}
if
(
c
->
flags
&
REDIS_BLOCK
)
{
if
(
redisCommandWriteBlock
(
c
,
&
reply
,
cmd
,
len
)
==
REDIS_OK
)
{
free
(
cmd
);
return
reply
;
}
}
else
{
redisCommandWriteNonBlock
(
c
,
cmd
,
len
);
}
void
*
redisCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
char
*
cmd
;
int
len
;
void
*
reply
=
NULL
;
len
=
redisFormatCommandArgv
(
&
cmd
,
argc
,
argv
,
argvlen
);
reply
=
__redisCommand
(
c
,
cmd
,
len
);
free
(
cmd
);
return
NULL
;
return
reply
;
}
hiredis.h
View file @
47e1f771
...
...
@@ -120,6 +120,11 @@ void redisDisconnect(redisContext *c);
void
redisFree
(
redisContext
*
c
);
int
redisBufferRead
(
redisContext
*
c
);
int
redisBufferWrite
(
redisContext
*
c
,
int
*
done
);
/* In a blocking context, this function first checks if there are unconsumed
* replies to return and returns one if so. Otherwise, it flushes the output
* buffer to the socket and reads until it has a reply. In a non-blocking
* context, it will return unconsumed replies until there are no more. */
int
redisGetReply
(
redisContext
*
c
,
void
**
reply
);
/* The disconnect callback is called *immediately* when redisDisconnect()
...
...
@@ -136,11 +141,19 @@ void redisSetCommandCallback(redisContext *c, redisContextCallbackFn *fn, void *
* release resources that depend/use the redisContext that is being free'd. */
void
redisSetFreeCallback
(
redisContext
*
c
,
redisContextCallbackFn
*
fn
,
void
*
privdata
);
/* Issue a command to Redis. In a blocking context, it returns the reply. When
* an error occurs, it returns NULL and you should read redisContext->error
* to find out what's wrong. In a non-blocking context, it has the same effect
* as calling redisCommandWithCallback() with a NULL callback, and will always
* return NULL. */
/* Write a command to the output buffer. Use these functions in blocking mode
* to get a pipeline of commands. */
void
redisvAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
);
void
redisAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
...);
void
redisAppendCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
/* Issue a command to Redis. In a blocking context, it is identical to calling
* redisAppendCommand, followed by redisGetReply. The function will return
* NULL if there was an error in performing the request, otherwise it will
* return the reply. In a non-blocking context, it is identical to calling
* only redisAppendCommand and will always return NULL. */
void
*
redisvCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
);
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...);
void
*
redisCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
#endif
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