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