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
a1f6ce01
Commit
a1f6ce01
authored
Dec 28, 2014
by
Ryan Jacobs
Committed by
Matt Stancliff
Jan 05, 2015
Browse files
Add syntax highlighting to README.md
Closes #293
parent
8f60ee65
Changes
1
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
a1f6ce01
...
@@ -31,9 +31,11 @@ the stateless 0.0.1 that only has a file descriptor to work with.
...
@@ -31,9 +31,11 @@ the stateless 0.0.1 that only has a file descriptor to work with.
To consume the synchronous API, there are only a few function calls that need to be introduced:
To consume the synchronous API, there are only a few function calls that need to be introduced:
redisContext *redisConnect(const char *ip, int port);
```
c
void *redisCommand(redisContext *c, const char *format, ...);
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
);
void freeReplyObject(void *reply);
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...);
void
freeReplyObject
(
void
*
reply
);
```
### Connecting
### Connecting
...
@@ -44,38 +46,41 @@ an error state. The field `errstr` will contain a string with a description of
...
@@ -44,38 +46,41 @@ an error state. The field `errstr` will contain a string with a description of
the error. More information on errors can be found in the
**Errors**
section.
the error. More information on errors can be found in the
**Errors**
section.
After trying to connect to Redis using
`redisConnect`
you should
After trying to connect to Redis using
`redisConnect`
you should
check the
`err`
field to see if establishing the connection was successful:
check the
`err`
field to see if establishing the connection was successful:
```
c
redisContext *c = redisConnect("127.0.0.1", 6379);
redisContext
*
c
=
redisConnect
(
"127.0.0.1"
,
6379
);
if (c != NULL && c->err) {
if
(
c
!=
NULL
&&
c
->
err
)
{
printf("Error: %s\n", c->errstr);
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
// handle error
// handle error
}
}
```
### Sending commands
### Sending commands
There are several ways to issue commands to Redis. The first that will be introduced is
There are several ways to issue commands to Redis. The first that will be introduced is
`redisCommand`
. This function takes a format similar to printf. In the simplest form,
`redisCommand`
. This function takes a format similar to printf. In the simplest form,
it is used like this:
it is used like this:
```
c
reply = redisCommand(context, "SET foo bar");
reply
=
redisCommand
(
context
,
"SET foo bar"
);
```
The specifier
`%s`
interpolates a string in the command, and uses
`strlen`
to
The specifier
`%s`
interpolates a string in the command, and uses
`strlen`
to
determine the length of the string:
determine the length of the string:
```
c
reply = redisCommand(context, "SET foo %s", value);
reply
=
redisCommand
(
context
,
"SET foo %s"
,
value
);
```
When you need to pass binary safe strings in a command, the
`%b`
specifier can be
When you need to pass binary safe strings in a command, the
`%b`
specifier can be
used. Together with a pointer to the string, it requires a
`size_t`
length argument
used. Together with a pointer to the string, it requires a
`size_t`
length argument
of the string:
of the string:
```
c
reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);
reply
=
redisCommand
(
context
,
"SET foo %b"
,
value
,
(
size_t
)
valuelen
);
```
Internally, Hiredis splits the command in different arguments and will
Internally, Hiredis splits the command in different arguments and will
convert it to the protocol used to communicate with Redis.
convert it to the protocol used to communicate with Redis.
One or more spaces separates arguments, so you can use the specifiers
One or more spaces separates arguments, so you can use the specifiers
anywhere in an argument:
anywhere in an argument:
```
c
reply = redisCommand(context, "SET key:%s %s", myid, value);
reply
=
redisCommand
(
context
,
"SET key:%s %s"
,
myid
,
value
);
```
### Using replies
### Using replies
...
@@ -127,9 +132,9 @@ keep an eye on the changelog when upgrading (see issue #39).
...
@@ -127,9 +132,9 @@ keep an eye on the changelog when upgrading (see issue #39).
### Cleaning up
### Cleaning up
To disconnect and free the context the following function can be used:
To disconnect and free the context the following function can be used:
```
c
void redisFree(redisContext *c);
void
redisFree
(
redisContext
*
c
);
```
This function immediately closes the socket and then free's the allocations done in
This function immediately closes the socket and then free's the allocations done in
creating the context.
creating the context.
...
@@ -137,9 +142,9 @@ creating the context.
...
@@ -137,9 +142,9 @@ creating the context.
Together with
`redisCommand`
, the function
`redisCommandArgv`
can be used to issue commands.
Together with
`redisCommand`
, the function
`redisCommandArgv`
can be used to issue commands.
It has the following prototype:
It has the following prototype:
```
c
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
void
*
redisCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
```
It takes the number of arguments
`argc`
, an array of strings
`argv`
and the lengths of the
It takes the number of arguments
`argc`
, an array of strings
`argv`
and the lengths of the
arguments
`argvlen`
. For convenience,
`argvlen`
may be set to
`NULL`
and the function will
arguments
`argvlen`
. For convenience,
`argvlen`
may be set to
`NULL`
and the function will
use
`strlen(3)`
on every argument to determine its length. Obviously, when any of the arguments
use
`strlen(3)`
on every argument to determine its length. Obviously, when any of the arguments
...
@@ -169,10 +174,10 @@ The function `redisGetReply` is exported as part of the Hiredis API and can be u
...
@@ -169,10 +174,10 @@ The function `redisGetReply` is exported as part of the Hiredis API and can be u
is expected on the socket. To pipeline commands, the only things that needs to be done is
is expected on the socket. To pipeline commands, the only things that needs to be done is
filling up the output buffer. For this cause, two commands can be used that are identical
filling up the output buffer. For this cause, two commands can be used that are identical
to the
`redisCommand`
family, apart from not returning a reply:
to the
`redisCommand`
family, apart from not returning a reply:
```
c
void redisAppendCommand(redisContext *c, const char *format, ...);
void
redisAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
void
redisAppendCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
```
After calling either function one or more times,
`redisGetReply`
can be used to receive the
After calling either function one or more times,
`redisGetReply`
can be used to receive the
subsequent replies. The return value for this function is either
`REDIS_OK`
or
`REDIS_ERR`
, where
subsequent replies. The return value for this function is either
`REDIS_OK`
or
`REDIS_ERR`
, where
the latter means an error occurred while reading a reply. Just as with the other commands,
the latter means an error occurred while reading a reply. Just as with the other commands,
...
@@ -180,24 +185,24 @@ the `err` field in the context can be used to find out what the cause of this er
...
@@ -180,24 +185,24 @@ the `err` field in the context can be used to find out what the cause of this er
The following examples shows a simple pipeline (resulting in only a single call to
`write(2)`
and
The following examples shows a simple pipeline (resulting in only a single call to
`write(2)`
and
a single call to
`read(2)`
):
a single call to
`read(2)`
):
```
c
redisReply *reply;
redisReply
*
reply
;
redisAppendCommand(context,"SET foo bar");
redisAppendCommand
(
context
,
"SET foo bar"
);
redisAppendCommand(context,"GET foo");
redisAppendCommand
(
context
,
"GET foo"
);
redisGetReply(context,&reply); // reply for SET
redisGetReply
(
context
,
&
reply
);
// reply for SET
freeReplyObject(reply);
freeReplyObject
(
reply
);
redisGetReply(context,&reply); // reply for GET
redisGetReply
(
context
,
&
reply
);
// reply for GET
freeReplyObject(reply);
freeReplyObject
(
reply
);
```
This API can also be used to implement a blocking subscriber:
This API can also be used to implement a blocking subscriber:
```
c
reply = redisCommand(context,"SUBSCRIBE foo");
reply
=
redisCommand
(
context
,
"SUBSCRIBE foo"
);
freeReplyObject
(
reply
);
while
(
redisGetReply
(
context
,
&
reply
)
==
REDIS_OK
)
{
// consume message
freeReplyObject
(
reply
);
freeReplyObject
(
reply
);
while(redisGetReply(context,&reply) == REDIS_OK) {
}
// consume message
```
freeReplyObject(reply);
}
### Errors
### Errors
When a function call is not successful, depending on the function either
`NULL`
or
`REDIS_ERR`
is
When a function call is not successful, depending on the function either
`NULL`
or
`REDIS_ERR`
is
...
@@ -236,19 +241,20 @@ Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The
...
@@ -236,19 +241,20 @@ Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The
should be checked after creation to see if there were errors creating the connection.
should be checked after creation to see if there were errors creating the connection.
Because the connection that will be created is non-blocking, the kernel is not able to
Because the connection that will be created is non-blocking, the kernel is not able to
instantly return if the specified host and port is able to accept a connection.
instantly return if the specified host and port is able to accept a connection.
```
c
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
redisAsyncContext
*
c
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
if (c->err) {
if
(
c
->
err
)
{
printf("Error: %s\n", c->errstr);
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
// handle error
// handle error
}
}
```
The asynchronous context can hold a disconnect callback function that is called when the
The asynchronous context can hold a disconnect callback function that is called when the
connection is disconnected (either because of an error or per user request). This function should
connection is disconnected (either because of an error or per user request). This function should
have the following prototype:
have the following prototype:
```
c
void(const redisAsyncContext *c, int status);
void
(
const
redisAsyncContext
*
c
,
int
status
);
```
On a disconnect, the
`status`
argument is set to
`REDIS_OK`
when disconnection was initiated by the
On a disconnect, the
`status`
argument is set to
`REDIS_OK`
when disconnection was initiated by the
user, or
`REDIS_ERR`
when the disconnection was caused by an error. When it is
`REDIS_ERR`
, the
`err`
user, or
`REDIS_ERR`
when the disconnection was caused by an error. When it is
`REDIS_ERR`
, the
`err`
field in the context can be accessed to find out the cause of the error.
field in the context can be accessed to find out the cause of the error.
...
@@ -258,30 +264,30 @@ the disconnect callback is a good point to do so.
...
@@ -258,30 +264,30 @@ the disconnect callback is a good point to do so.
Setting the disconnect callback can only be done once per context. For subsequent calls it will
Setting the disconnect callback can only be done once per context. For subsequent calls it will
return
`REDIS_ERR`
. The function to set the disconnect callback has the following prototype:
return
`REDIS_ERR`
. The function to set the disconnect callback has the following prototype:
```
c
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
int
redisAsyncSetDisconnectCallback
(
redisAsyncContext
*
ac
,
redisDisconnectCallback
*
fn
);
```
### Sending commands and their callbacks
### Sending commands and their callbacks
In an asynchronous context, commands are automatically pipelined due to the nature of an event loop.
In an asynchronous context, commands are automatically pipelined due to the nature of an event loop.
Therefore, unlike the synchronous API, there is only a single way to send commands.
Therefore, unlike the synchronous API, there is only a single way to send commands.
Because commands are sent to Redis asynchronously, issuing a command requires a callback function
Because commands are sent to Redis asynchronously, issuing a command requires a callback function
that is called when the reply is received. Reply callbacks should have the following prototype:
that is called when the reply is received. Reply callbacks should have the following prototype:
```
c
void(redisAsyncContext *c, void *reply, void *privdata);
void
(
redisAsyncContext
*
c
,
void
*
reply
,
void
*
privdata
);
```
The
`privdata`
argument can be used to curry arbitrary data to the callback from the point where
The
`privdata`
argument can be used to curry arbitrary data to the callback from the point where
the command is initially queued for execution.
the command is initially queued for execution.
The functions that can be used to issue commands in an asynchronous context are:
The functions that can be used to issue commands in an asynchronous context are:
```
c
int redisAsyncCommand(
int
redisAsyncCommand
(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
redisAsyncContext
*
ac
,
redisCallbackFn
*
fn
,
void
*
privdata
,
const char *format, ...);
const
char
*
format
,
...);
int redisAsyncCommandArgv(
int
redisAsyncCommandArgv
(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
redisAsyncContext
*
ac
,
redisCallbackFn
*
fn
,
void
*
privdata
,
int argc, const char **argv, const size_t *argvlen);
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
```
Both functions work like their blocking counterparts. The return value is
`REDIS_OK`
when the command
Both functions work like their blocking counterparts. The return value is
`REDIS_OK`
when the command
was successfully added to the output buffer and
`REDIS_ERR`
otherwise. Example: when the connection
was successfully added to the output buffer and
`REDIS_ERR`
otherwise. Example: when the connection
is being disconnected per user-request, no new commands may be added to the output buffer and
`REDIS_ERR`
is
is being disconnected per user-request, no new commands may be added to the output buffer and
`REDIS_ERR`
is
...
@@ -296,9 +302,9 @@ All pending callbacks are called with a `NULL` reply when the context encountere
...
@@ -296,9 +302,9 @@ All pending callbacks are called with a `NULL` reply when the context encountere
### Disconnecting
### Disconnecting
An asynchronous connection can be terminated using:
An asynchronous connection can be terminated using:
```
c
void redisAsyncDisconnect(redisAsyncContext *ac);
void
redisAsyncDisconnect
(
redisAsyncContext
*
ac
);
```
When this function is called, the connection is
**not**
immediately terminated. Instead, new
When this function is called, the connection is
**not**
immediately terminated. Instead, new
commands are no longer accepted and the connection is only terminated when all pending commands
commands are no longer accepted and the connection is only terminated when all pending commands
have been written to the socket, their respective replies have been read and their respective
have been written to the socket, their respective replies have been read and their respective
...
@@ -316,12 +322,12 @@ Hiredis comes with a reply parsing API that makes it easy for writing higher
...
@@ -316,12 +322,12 @@ Hiredis comes with a reply parsing API that makes it easy for writing higher
level language bindings.
level language bindings.
The reply parsing API consists of the following functions:
The reply parsing API consists of the following functions:
```
c
redisReader *redisReaderCreate(void);
redisReader
*
redisReaderCreate
(
void
);
void redisReaderFree(redisReader *reader);
void
redisReaderFree
(
redisReader
*
reader
);
int redisReaderFeed(redisReader *reader, const char *buf, size_t len);
int
redisReaderFeed
(
redisReader
*
reader
,
const
char
*
buf
,
size_t
len
);
int redisReaderGetReply(redisReader *reader, void **reply);
int
redisReaderGetReply
(
redisReader
*
reader
,
void
**
reply
);
```
The same set of functions are used internally by hiredis when creating a
The same set of functions are used internally by hiredis when creating a
normal Redis context, the above API just exposes it to the user for a direct
normal Redis context, the above API just exposes it to the user for a direct
usage.
usage.
...
@@ -371,9 +377,9 @@ value for an idle buffer, so the buffer will never get freed.
...
@@ -371,9 +377,9 @@ value for an idle buffer, so the buffer will never get freed.
For instance if you have a normal Redis context you can set the maximum idle
For instance if you have a normal Redis context you can set the maximum idle
buffer to zero (unlimited) just with:
buffer to zero (unlimited) just with:
```
c
context->reader->maxbuf = 0;
context
->
reader
->
maxbuf
=
0
;
```
This should be done only in order to maximize performances when working with
This should be done only in order to maximize performances when working with
large payloads. The context should be set back to
`REDIS_READER_MAX_BUF`
again
large payloads. The context should be set back to
`REDIS_READER_MAX_BUF`
again
as soon as possible in order to prevent allocation of useless memory.
as soon as possible in order to prevent allocation of useless memory.
...
...
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