Merge in code for C++ compiling of libmemcached.
[awesomized/libmemcached] / libmemcached / dump.cc
1 /*
2 We use this to dump all keys.
3
4 At this point we only support a callback method. This could be optimized by first
5 calling items and finding active slabs. For the moment though we just loop through
6 all slabs on servers and "grab" the keys.
7 */
8
9 #include "common.h"
10 static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
11 {
12 memcached_return_t rc= MEMCACHED_SUCCESS;
13 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
14 uint32_t server_key;
15 uint32_t x;
16
17 unlikely (memcached_server_count(ptr) == 0)
18 return MEMCACHED_NO_SERVERS;
19
20 for (server_key= 0; server_key < memcached_server_count(ptr); server_key++)
21 {
22 memcached_server_write_instance_st instance;
23 instance= memcached_server_instance_fetch(ptr, server_key);
24
25 /* 256 I BELIEVE is the upper limit of slabs */
26 for (x= 0; x < 256; x++)
27 {
28 int send_length;
29 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
30 "stats cachedump %u 0 0\r\n", x);
31
32 if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
33 {
34 return MEMCACHED_FAILURE;
35 }
36
37 rc= memcached_do(instance, buffer, (size_t)send_length, true);
38
39 unlikely (rc != MEMCACHED_SUCCESS)
40 goto error;
41
42 while (1)
43 {
44 uint32_t callback_counter;
45 rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
46
47 if (rc == MEMCACHED_ITEM)
48 {
49 char *string_ptr, *end_ptr;
50 char *key;
51
52 string_ptr= buffer;
53 string_ptr+= 5; /* Move past ITEM */
54 for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
55 key= string_ptr;
56 key[(size_t)(end_ptr-string_ptr)]= 0;
57 for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
58 {
59 rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context);
60 if (rc != MEMCACHED_SUCCESS)
61 break;
62 }
63 }
64 else if (rc == MEMCACHED_END)
65 break;
66 else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR)
67 {
68 /* If we try to request stats cachedump for a slab class that is too big
69 * the server will return an incorrect error message:
70 * "MEMCACHED_SERVER_ERROR failed to allocate memory"
71 * This isn't really a fatal error, so let's just skip it. I want to
72 * fix the return value from the memcached server to a CLIENT_ERROR,
73 * so let's add support for that as well right now.
74 */
75 rc= MEMCACHED_END;
76 break;
77 }
78 else
79 goto error;
80 }
81 }
82 }
83
84 error:
85 if (rc == MEMCACHED_END)
86 return MEMCACHED_SUCCESS;
87 else
88 return rc;
89 }
90
91 memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
92 {
93 memcached_return_t rc;
94 if ((rc= initialize_query(ptr)) != MEMCACHED_SUCCESS)
95 {
96 return rc;
97 }
98
99 /*
100 No support for Binary protocol yet
101 @todo Fix this so that we just flush, switch to ascii, and then go back to binary.
102 */
103 if (ptr->flags.binary_protocol)
104 return MEMCACHED_FAILURE;
105
106 return ascii_dump(ptr, callback, context, number_of_callbacks);
107 }