]>
Commit | Line | Data |
---|---|---|
24f753a8 PN |
1 | # HIREDIS |
2 | ||
3 | Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database. | |
4 | ||
5 | It is minimalistic because it just adds minimal support for the protocol, but | |
6 | at the same time it uses an high level printf-alike API in order to make it | |
7 | much higher level than otherwise suggested by its minimal code base and the | |
8 | lack of explicit bindings for every Redis command. | |
9 | ||
10 | Apart from supporting sending commands and receiving replies, it comes with | |
11 | a reply parser that is decoupled from the I/O layer. It | |
12 | is a stream parser designed for easy reusability, which can for instance be used | |
13 | in higher level language bindings for efficient reply parsing. | |
14 | ||
15 | Hiredis only supports the binary-safe Redis protocol, so you can use it with any | |
16 | Redis version >= 1.2.0. | |
17 | ||
18 | The library comes with multiple APIs. There is the | |
19 | *synchronous API*, the *asynchronous API* and the *reply parsing API*. | |
20 | ||
21 | ## UPGRADING | |
22 | ||
23 | Version 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing | |
24 | code using hiredis should not be a big pain. The key thing to keep in mind when | |
25 | upgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to | |
26 | the stateless 0.0.1 that only has a file descriptor to work with. | |
27 | ||
28 | ## Synchronous API | |
29 | ||
30 | To consume the synchronous API, there are only a few function calls that need to be introduced: | |
31 | ||
32 | redisContext *redisConnect(const char *ip, int port); | |
33 | void *redisCommand(redisContext *c, const char *format, ...); | |
34 | void freeReplyObject(void *reply); | |
35 | ||
36 | ### Connecting | |
37 | ||
38 | The function `redisConnect` is used to create a so-called `redisContext`. The context is where | |
39 | Hiredis holds state for a connection. The `redisContext` struct has an `error` field that is | |
40 | non-NULL when the connection is in an error state. It contains a string with a textual | |
41 | representation of the error. After trying to connect to Redis using `redisConnect` you should | |
42 | check the `error` field to see if establishing the connection was successful: | |
43 | ||
44 | redisContext *c = redisConnect("127.0.0.1", 6379); | |
45 | if (c->error != NULL) { | |
46 | printf("Error: %s\n", c->error); | |
47 | // handle error | |
48 | } | |
49 | ||
50 | ### Sending commands | |
51 | ||
52 | There are several ways to issue commands to Redis. The first that will be introduced is | |
53 | `redisCommand`. This function takes a format similar to printf. In the simplest form, | |
54 | it is used like this: | |
55 | ||
56 | reply = redisCommand(context, "SET foo bar"); | |
57 | ||
58 | The specifier `%s` interpolates a string in the command, and uses `strlen` to | |
59 | determine the length of the string: | |
60 | ||
61 | reply = redisCommand(context, "SET foo %s", value); | |
62 | ||
63 | When you need to pass binary safe strings in a command, the `%b` specifier can be | |
64 | used. Together with a pointer to the string, it requires a `size_t` length argument | |
65 | of the string: | |
66 | ||
67 | reply = redisCommand(context, "SET foo %b", value, valuelen); | |
68 | ||
69 | Internally, Hiredis splits the command in different arguments and will | |
70 | convert it to the protocol used to communicate with Redis. | |
71 | One or more spaces separates arguments, so you can use the specifiers | |
72 | anywhere in an argument: | |
73 | ||
74 | reply = redisCommand("SET key:%s %s", myid, value); | |
75 | ||
76 | ### Using replies | |
77 | ||
78 | The return value of `redisCommand` holds a reply when the command was | |
79 | successfully executed. When the return value is `NULL`, the `error` field | |
80 | in the context can be used to find out what was the cause of failure. | |
81 | Once an error is returned the context cannot be reused and you should set up | |
82 | a new connection. | |
83 | ||
84 | The standard replies that `redisCommand` are of the type `redisReply`. The | |
85 | `type` field in the `redisReply` should be used to test what kind of reply | |
86 | was received: | |
87 | ||
88 | * **`REDIS_REPLY_STATUS`**: | |
89 | * The command replied with a status reply. The status string can be accessed using `reply->str`. | |
90 | The length of this string can be accessed using `reply->len`. | |
91 | ||
92 | * **`REDIS_REPLY_ERROR`**: | |
93 | * The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`. | |
94 | ||
95 | * **`REDIS_REPLY_INTEGER`**: | |
96 | * The command replied with an integer. The integer value can be accessed using the | |
97 | `reply->integer` field of type `long long`. | |
98 | ||
99 | * **`REDIS_REPLY_NIL`**: | |
100 | * The command replied with a **nil** object. There is no data to access. | |
101 | ||
102 | * **`REDIS_REPLY_STRING`**: | |
103 | * A bulk (string) reply. The value of the reply can be accessed using `reply->str`. | |
104 | The length of this string can be accessed using `reply->len`. | |
105 | ||
106 | * **`REDIS_REPLY_ARRAY`**: | |
107 | * A multi bulk reply. The number of elements in the multi bulk reply is stored in | |
108 | `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well | |
109 | and can be accessed via `reply->elements[..index..]`. | |
110 | Redis may reply with nested arrays but this is fully supported. | |
111 | ||
112 | Replies should be freed using the `freeReplyObject()` function. | |
113 | Note that this function will take care of freeing sub-replies objects | |
114 | contained in arrays and nested arrays, so there is no need for the user to | |
115 | free the sub replies (it is actually harmful and will corrupt the memory). | |
116 | ||
117 | ### Cleaning up | |
118 | ||
119 | To disconnect and free the context the following function can be used: | |
120 | ||
121 | void redisFree(redisContext *c); | |
122 | ||
123 | This function immediately closes the socket and then free's the allocations done in | |
124 | creating the context. | |
125 | ||
126 | ### Sending commands (cont'd) | |
127 | ||
128 | Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands. | |
129 | It has the following prototype: | |
130 | ||
131 | void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); | |
132 | ||
133 | It takes the number of arguments `argc`, an array of strings `argv` and the lengths of the | |
134 | arguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will | |
135 | use `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments | |
136 | need to be binary safe, the entire array of lengths `argvlen` should be provided. | |
137 | ||
138 | The return value has the same semantic as `redisCommand`. | |
139 | ||
140 | ### Pipelining | |
141 | ||
142 | To explain how Hiredis supports pipelining in a blocking connection, there needs to be | |
143 | understanding of the internal execution flow. | |
144 | ||
145 | When any of the functions in the `redisCommand` family is called, Hiredis first formats the | |
146 | command according to the Redis protocol. The formatted command is then put in the output buffer | |
147 | of the context. This output buffer is dynamic, so it can hold any number of commands. | |
148 | After the command is put in the output buffer, `redisGetReply` is called. This function has the | |
149 | following two execution paths: | |
150 | ||
151 | 1. The input buffer is non-empty: | |
152 | * Try to parse a single reply from the input buffer and return it | |
153 | * If no reply could be parsed, continue at *2* | |
154 | 2. The input buffer is empty: | |
155 | * Write the **entire** output buffer to the socket | |
156 | * Read from the socket until a single reply could be parsed | |
157 | ||
158 | The function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply | |
159 | is expected on the socket. To pipeline commands, the only things that needs to be done is | |
160 | filling up the output buffer. For this cause, two commands can be used that are identical | |
161 | to the `redisCommand` family, apart from not returning a reply: | |
162 | ||
163 | void redisAppendCommand(redisContext *c, const char *format, ...); | |
164 | void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); | |
165 | ||
166 | After calling either function one or more times, `redisGetReply` can be used to receive the | |
167 | subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where | |
168 | the latter means an error occurred while reading a reply. Just as with the other commands, | |
169 | the `error` field in the context can be used to find out what the cause of this error is. | |
170 | ||
171 | The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and | |
172 | a single call to `write(2)`): | |
173 | ||
174 | redisReply *reply; | |
175 | redisAppendCommand(context,"SET foo bar"); | |
176 | redisAppendCommand(context,"GET foo"); | |
177 | redisGetReply(context,&reply); // reply for SET | |
178 | freeReplyObject(reply); | |
179 | redisGetReply(context,&reply); // reply for GET | |
180 | freeReplyObject(reply); | |
181 | ||
182 | This API can also be used to implement a blocking subscriber: | |
183 | ||
184 | reply = redisCommand(context,"SUBSCRIBE foo"); | |
185 | freeReplyObject(reply); | |
186 | while(redisGetReply(context,&reply) == REDIS_OK) { | |
187 | // consume message | |
188 | freeReplyObject(reply); | |
189 | } | |
190 | ||
191 | ## Asynchronous API | |
192 | ||
193 | Hiredis comes with an asynchronous API that works easily with any event library. | |
194 | Examples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html) | |
195 | and [libevent](http://monkey.org/~provos/libevent/). | |
196 | ||
197 | ### Connecting | |
198 | ||
199 | The function `redisAsyncConnect` can be used to establish a non-blocking connection to | |
200 | Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `error` field | |
201 | should be checked after creation to see if there were errors creating the connection. | |
202 | Because the connection that will be created is non-blocking, the kernel is not able to | |
203 | instantly return if the specified host and port is able to accept a connection. | |
204 | ||
205 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); | |
206 | if (c->error != NULL) { | |
207 | printf("Error: %s\n", c->error); | |
208 | // handle error | |
209 | } | |
210 | ||
211 | The asynchronous context can hold a disconnect callback function that is called when the | |
212 | connection is disconnected (either because of an error or per user request). This function should | |
213 | have the following prototype: | |
214 | ||
215 | void(const redisAsyncContext *c, int status); | |
216 | ||
217 | On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the | |
218 | user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `error` | |
219 | field in the context can be accessed to find out the cause of the error. | |
220 | ||
221 | The context object is always free'd after the disconnect callback fired. When a reconnect is needed, | |
222 | the disconnect callback is a good point to do so. | |
223 | ||
224 | Setting the disconnect callback can only be done once per context. For subsequent calls it will | |
225 | return `REDIS_ERR`. The function to set the disconnect callback has the following prototype: | |
226 | ||
227 | int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); | |
228 | ||
229 | ### Sending commands and their callbacks | |
230 | ||
231 | In an asynchronous context, commands are automatically pipelined due to the nature of an event loop. | |
232 | Therefore, unlike the synchronous API, there is only a single way to send commands. | |
233 | Because commands are sent to Redis asynchronously, issuing a command requires a callback function | |
234 | that is called when the reply is received. Reply callbacks should have the following prototype: | |
235 | ||
236 | void(redisAsyncContext *c, void *reply, void *privdata); | |
237 | ||
238 | The `privdata` argument can be used to curry arbitrary data to the callback from the point where | |
239 | the command is initially queued for execution. | |
240 | ||
241 | The functions that can be used to issue commands in an asynchronous context are: | |
242 | ||
243 | int redisAsyncCommand( | |
244 | redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, | |
245 | const char *format, ...); | |
246 | int redisAsyncCommandArgv( | |
247 | redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, | |
248 | int argc, const char **argv, const size_t *argvlen); | |
249 | ||
250 | Both functions work like their blocking counterparts. The return value is `REDIS_OK` when the command | |
251 | was successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection | |
252 | is being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is | |
253 | returned on calls to the `redisAsyncCommand` family. | |
254 | ||
255 | If the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback | |
256 | for a command is non-`NULL`, it is responsible for cleaning up the reply. | |
257 | ||
258 | All pending callbacks are called with a `NULL` reply when the context encountered an error. | |
259 | ||
260 | ### Disconnecting | |
261 | ||
262 | An asynchronous connection can be terminated using: | |
263 | ||
264 | void redisAsyncDisconnect(redisAsyncContext *ac); | |
265 | ||
266 | When this function is called, the connection is **not** immediately terminated. Instead, new | |
267 | commands are no longer accepted and the connection is only terminated when all pending commands | |
268 | have been written to the socket, their respective replies have been read and their respective | |
269 | callbacks have been executed. After this, the disconnection callback is executed with the | |
270 | `REDIS_OK` status and the context object is free'd. | |
271 | ||
272 | ### Hooking it up to event library *X* | |
273 | ||
274 | There are a few hooks that need to be set on the context object after it is created. | |
275 | See the `adapters/` directory for bindings to *libev* and *libevent*. | |
276 | ||
277 | ## Reply parsing API | |
278 | ||
279 | To be done. | |
280 | ||
281 | ## AUTHORS | |
282 | ||
283 | Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and | |
284 | Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. |