]> git.saurik.com Git - redis.git/blob - client-libraries/cpp/redisclient.h
initial multi-bulk query protocol, this will allow MSET and other interesting features.
[redis.git] / client-libraries / cpp / redisclient.h
1 /* redisclient.h -- a C++ client library for redis.
2 *
3 * Copyright (c) 2009, Brian Hammond <brian at fictorial dot com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef REDISCLIENT_H
32 #define REDISCLIENT_H
33
34 #include <string>
35 #include <vector>
36 #include <set>
37 #include <stdexcept>
38 #include <ctime>
39
40 namespace redis
41 {
42 enum server_role
43 {
44 role_master,
45 role_slave
46 };
47
48 struct server_info
49 {
50 std::string version;
51 bool bgsave_in_progress;
52 unsigned long connected_clients;
53 unsigned long connected_slaves;
54 unsigned long used_memory;
55 unsigned long changes_since_last_save;
56 unsigned long last_save_time;
57 unsigned long total_connections_received;
58 unsigned long total_commands_processed;
59 unsigned long uptime_in_seconds;
60 unsigned long uptime_in_days;
61 server_role role;
62 };
63
64 // Generic error that is thrown when communicating with the redis server.
65
66 class redis_error
67 {
68 public:
69 redis_error(const std::string & err);
70 operator std::string ();
71 operator const std::string () const;
72 private:
73 std::string err_;
74 };
75
76 // Some socket-level I/O or general connection error.
77
78 class connection_error : public redis_error
79 {
80 public:
81 connection_error(const std::string & err);
82 };
83
84 // Redis gave us a reply we were not expecting.
85 // Possibly an internal error (here or in redis, probably here).
86
87 class protocol_error : public redis_error
88 {
89 public:
90 protocol_error(const std::string & err);
91 };
92
93 // A key that you expected to exist does not in fact exist.
94
95 class key_error : public redis_error
96 {
97 public:
98 key_error(const std::string & err);
99 };
100
101 // A value of an expected type or other semantics was found to be invalid.
102
103 class value_error : public redis_error
104 {
105 public:
106 value_error(const std::string & err);
107 };
108
109 // You should construct a 'client' object per connection to a redis-server.
110 //
111 // Please read the online redis command reference:
112 // http://code.google.com/p/redis/wiki/CommandReference
113 //
114 // No provisions for customizing the allocator on the string/bulk value type
115 // (std::string) are provided. If needed, you can always change the
116 // string_type typedef in your local version.
117
118 class client
119 {
120 public:
121 typedef std::string string_type;
122 typedef std::vector<string_type> string_vector;
123 typedef std::set<string_type> string_set;
124
125 typedef long int_type;
126
127 explicit client(const string_type & host = "localhost",
128 unsigned int port = 6379);
129
130 ~client();
131
132 //
133 // Connection handling
134 //
135
136 void auth(const string_type & pass);
137
138 //
139 // Commands operating on string values
140 //
141 // Note that empty string values do not denote nonexistent keys but well,
142 // empty values! If a nonexistent key is queried, the value returned will
143 // be missing_value, including when string_vector objects are returned.
144 //
145
146 static string_type missing_value;
147
148 // set a key to a string value
149
150 void set(const string_type & key, const string_type & value);
151
152 // return the string value of the key
153
154 string_type get(const string_type & key);
155
156 // set a key to a string returning the old value of the key
157
158 string_type getset(const string_type & key, const string_type & value);
159
160 // multi-get, return the strings values of the keys
161
162 void mget(const string_vector & keys, string_vector & out);
163
164 // set a key to a string value if the key does not exist. returns true if
165 // the key was set, else false. This does not throw since you are ok with
166 // this failing if the dst key already exists.
167
168 bool setnx(const string_type & key, const string_type & value);
169
170 // increment the integer value of key
171 // returns new value
172
173 int_type incr(const string_type & key);
174
175 // increment the integer value of key by integer
176 // returns new value
177
178 int_type incrby(const string_type & key, int_type by);
179
180 // decrement the integer value of key
181 // returns new value
182
183 int_type decr(const string_type & key);
184
185 // decrement the integer value of key by integer
186 // returns new value
187
188 int_type decrby(const string_type & key, int_type by);
189
190 // test if a key exists
191
192 bool exists(const string_type & key);
193
194 // delete a key
195 // throws if doesn't exist
196
197 void del(const string_type & key);
198
199 enum datatype
200 {
201 datatype_none, // key doesn't exist
202 datatype_string,
203 datatype_list,
204 datatype_set
205 };
206
207 // return the type of the value stored at key
208
209 datatype type(const string_type & key);
210
211 //
212 // Commands operating on the key space
213 //
214
215 // find all the keys matching a given pattern
216 // returns numbers of keys appended to 'out'
217
218 int_type keys(const string_type & pattern, string_vector & out);
219
220 // return a random key from the key space
221 // returns empty string if db is empty
222
223 string_type randomkey();
224
225 // rename the old key in the new one, destroying the new key if
226 // it already exists
227
228 void rename(const string_type & old_name, const string_type & new_name);
229
230 // rename the old key in the new one, if the new key does not already
231 // exist. This does not throw since you are ok with this failing if the
232 // new_name key already exists.
233
234 bool renamenx(const string_type & old_name, const string_type & new_name);
235
236 // return the number of keys in the current db
237
238 int_type dbsize();
239
240 // set a time to live in seconds on a key.
241 // fails if there's already a timeout on the key.
242
243 // NB: there's currently no generic way to remove a timeout on a key
244
245 void expire(const string_type & key, unsigned int secs);
246
247 //
248 // Commands operating on lists
249 //
250
251 // Append an element to the tail of the list value at key
252
253 void rpush(const string_type & key, const string_type & value);
254
255 // Append an element to the head of the list value at key
256
257 void lpush(const string_type & key, const string_type & value);
258
259 // Return the length of the list value at key
260 // Returns 0 if the list does not exist; see 'exists'
261
262 int_type llen(const string_type & key);
263
264 // Fetch a range of elements from the list at key
265 // end can be negative for reverse offsets
266 // Returns number of elements appended to 'out'
267
268 int_type lrange(const string_type & key,
269 int_type start,
270 int_type end,
271 string_vector & out);
272
273 // Fetches the entire list at key.
274
275 int_type get_list(const string_type & key, string_vector & out)
276 {
277 return lrange(key, 0, -1, out);
278 }
279
280 // Trim the list at key to the specified range of elements
281
282 void ltrim(const string_type & key, int_type start, int_type end);
283
284 // Return the element at index position from the list at key
285
286 string_type lindex(const string_type & key, int_type);
287
288 // set a new value as the element at index position of the list at key
289
290 void lset(const string_type & key,
291 int_type index,
292 const string_type &);
293
294 // If count is zero all the elements are removed. If count is negative
295 // elements are removed from tail to head, instead to go from head to tail
296 // that is the normal behaviour. So for example LREM with count -2 and
297 // hello as value to remove against the list (a,b,c,hello,x,hello,hello)
298 // will lave the list (a,b,c,hello,x). Returns the number of removed
299 // elements if the operation succeeded.
300 //
301 // Note: this will not throw if the number of elements removed != count
302 // since you might want to remove at most count elements by don't care if
303 // < count elements are removed. See lrem_exact().
304
305 int_type lrem(const string_type & key,
306 int_type count,
307 const string_type & value);
308
309 // An extension of 'lrem' that wants to remove exactly 'count' elements.
310 // Throws value_error if 'count' elements are not found & removed from the
311 // list at 'key'.
312
313 void lrem_exact(const string_type & key,
314 int_type count,
315 const string_type & value)
316 {
317 if (lrem(key, count, value) != count)
318 throw value_error("failed to remove exactly N elements from list");
319 }
320
321 // Return and remove (atomically) the first element of the list at key
322
323 string_type lpop(const string_type & key);
324
325 // Return and remove (atomically) the last element of the list at key
326
327 string_type rpop(const string_type & key);
328
329 //
330 // Commands operating on sets
331 //
332
333 // Add the specified member to the set value at key
334 // returns true if added, or false if already a member of the set.
335
336 void sadd(const string_type & key, const string_type & value);
337
338 // Remove the specified member from the set value at key
339 // returns true if removed or false if value is not a member of the set.
340
341 void srem(const string_type & key, const string_type & value);
342
343 // Move the specified member from one set to another atomically
344 // returns true if element was moved, else false (e.g. not found)
345
346 void smove(const string_type & srckey,
347 const string_type & dstkey,
348 const string_type & value);
349
350 // Return the number of elements (the cardinality) of the set at key
351
352 int_type scard(const string_type & key);
353
354 // Test if the specified value is a member of the set at key
355 // Returns false if key doesn't exist or value is not a member of the set at key
356
357 bool sismember(const string_type & key, const string_type & value);
358
359 // Return the intersection between the sets stored at key1, key2, ..., keyN
360
361 int_type sinter(const string_vector & keys, string_set & out);
362
363 // Compute the intersection between the sets stored at key1, key2, ...,
364 // keyN, and store the resulting set at dstkey
365 // Returns the number of items in the intersection
366
367 int_type sinterstore(const string_type & dstkey, const string_vector & keys);
368
369 // Return the union between the sets stored at key1, key2, ..., keyN
370
371 int_type sunion(const string_vector & keys, string_set & out);
372
373 // Compute the union between the sets stored at key1, key2, ..., keyN,
374 // and store the resulting set at dstkey
375 // Returns the number of items in the intersection
376
377 int_type sunionstore(const string_type & dstkey, const string_vector & keys);
378
379 // Return all the members of the set value at key
380
381 int_type smembers(const string_type & key, string_set & out);
382
383 //
384 // Multiple databases handling commands
385 //
386
387 // Select the DB having the specified index
388
389 void select(int_type dbindex);
390
391 // Move the key from the currently selected DB to the DB having as index
392 // dbindex. Throws if key was already in the db at dbindex or not found in
393 // currently selected db.
394
395 void move(const string_type & key, int_type dbindex);
396
397 // Remove all the keys of the currently selected DB
398
399 void flushdb();
400
401 // Remove all the keys from all the databases
402
403 void flushall();
404
405 //
406 // Sorting
407 // Just go read http://code.google.com/p/redis/wiki/SortCommand
408 //
409
410 enum sort_order
411 {
412 sort_order_ascending,
413 sort_order_descending
414 };
415
416 int_type sort(const string_type & key,
417 string_vector & out,
418 sort_order order = sort_order_ascending,
419 bool lexicographically = false);
420
421 int_type sort(const string_type & key,
422 string_vector & out,
423 int_type limit_start,
424 int_type limit_end,
425 sort_order order = sort_order_ascending,
426 bool lexicographically = false);
427
428 int_type sort(const string_type & key,
429 string_vector & out,
430 const string_type & by_pattern,
431 int_type limit_start,
432 int_type limit_end,
433 const string_vector & get_patterns,
434 sort_order order = sort_order_ascending,
435 bool lexicographically = false);
436
437 //
438 // Persistence control commands
439 //
440
441 // Synchronously save the DB on disk
442
443 void save();
444
445 // Asynchronously save the DB on disk
446
447 void bgsave();
448
449 // Return the UNIX time stamp of the last successfully saving of the
450 // dataset on disk
451
452 time_t lastsave();
453
454 // Synchronously save the DB on disk, then shutdown the server. This
455 // object's connection to the server will be lost on success. Otherwise,
456 // redis_error is raised. Thus, on success, you should delete or otherwise
457 // no longer use the object.
458
459 void shutdown();
460
461 //
462 // Remote server control commands
463 //
464
465 // Provide information and statistics about the server
466
467 void info(server_info & out);
468
469 private:
470 client(const client &);
471 client & operator=(const client &);
472
473 void send_(const std::string &);
474 void recv_ok_reply_();
475 void recv_int_ok_reply_();
476 std::string recv_single_line_reply_();
477 int_type recv_bulk_reply_(char prefix);
478 std::string recv_bulk_reply_();
479 int_type recv_multi_bulk_reply_(string_vector & out);
480 int_type recv_multi_bulk_reply_(string_set & out);
481 int_type recv_int_reply_();
482
483 private:
484 int socket_;
485 };
486 }
487
488 #endif