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