8b85fb9a22f40f1bca340a982c57015f51e9fb3c
[m6w6/libmemcached] / lib / memcached_get.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 static char *memcached_value_fetch(memcached_st *ptr, char *key, size_t *key_length,
5 size_t *value_length,
6 uint16_t *flags,
7 memcached_return *error,
8 char load_key,
9 unsigned int server_key)
10 {
11 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
12 char *string_ptr;
13 char *end_ptr;
14
15 memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
16 end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
17
18 *value_length= 0;
19 *flags= 0;
20
21 *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
22
23 if (*error == MEMCACHED_SUCCESS)
24 {
25 char *next_ptr;
26
27 string_ptr= buffer;
28 string_ptr+= 6; /* "VALUE " */
29
30 /* We load the key */
31 if (load_key)
32 {
33 memset(key, 0, MEMCACHED_MAX_KEY);
34 *key_length= 0;
35
36 for (; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++)
37 {
38 *key= *string_ptr;
39 key++;
40 (*key_length)++;
41 }
42 }
43 else /* Skip characters */
44 for (; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
45
46 if (end_ptr == string_ptr)
47 goto read_error;
48
49 /* Flags fetch move past space */
50 string_ptr++;
51 if (end_ptr == string_ptr)
52 goto read_error;
53 for (next_ptr= string_ptr; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
54 *flags= (uint16_t)strtol(next_ptr, &string_ptr, 10);
55
56 if (end_ptr == string_ptr)
57 goto read_error;
58
59 /* Length fetch move past space*/
60 string_ptr++;
61 if (end_ptr == string_ptr)
62 goto read_error;
63
64 for (next_ptr= string_ptr; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
65 *value_length= (size_t)strtoll(next_ptr, &string_ptr, 10);
66
67 if (end_ptr == string_ptr)
68 goto read_error;
69
70 /* Skip past the \r\n */
71 string_ptr+= 2;
72
73 if (end_ptr < string_ptr)
74 goto read_error;
75
76 if (*value_length)
77 {
78 size_t read_length;
79 size_t to_read;
80 char *value;
81 char *value_ptr;
82
83 /* We add two bytes so that we can walk the \r\n */
84 value= (char *)malloc(((*value_length) +2) * sizeof(char));
85 if (!value)
86 {
87 *value_length= 0;
88 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
89 return NULL;
90 }
91 memset(value, 0, ((*value_length) +2) * sizeof(char));
92
93 value_ptr= value;
94 read_length= 0;
95 /*
96 We read the \r\n into the string since not doing so is more
97 cycles then the waster of memory to do so.
98
99 We are null terminating through, which will most likely make
100 some people lazy about using the return length.
101 */
102 to_read= (*value_length) + 2;
103
104 read_length= memcached_io_read(ptr, server_key,
105 value_ptr, to_read);
106
107 if (read_length != (size_t)(*value_length + 2))
108 {
109 free(value);
110 goto read_error;
111 }
112
113 value[*value_length]= 0;
114 value[(*value_length) + 1]= 0;
115
116 return value;
117 }
118 }
119 else if (*error == MEMCACHED_END)
120 *error= MEMCACHED_NOTFOUND;
121
122 return NULL;
123 read_error:
124 *error= MEMCACHED_PARTIAL_READ;
125 return NULL;
126 }
127
128 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
129 size_t *value_length,
130 uint16_t *flags,
131 memcached_return *error)
132 {
133 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
134 char *buf_ptr= buffer;
135 unsigned int server_key;
136 char *value;
137 LIBMEMCACHED_MEMCACHED_GET_START();
138
139 server_key= memcached_generate_hash(ptr, key, key_length);
140
141 *value_length= 0;
142 *error= memcached_connect(ptr, server_key);
143
144 if (*error != MEMCACHED_SUCCESS)
145 goto error;
146
147 memcpy(buf_ptr, "get ", 4);
148 buf_ptr+= 4;
149 memcpy(buf_ptr, key, key_length);
150 buf_ptr+= key_length;
151 memcpy(buf_ptr, "\r\n", 2);
152 buf_ptr+= 2;
153
154 if ((memcached_io_write(ptr, server_key, buffer, (size_t)(buf_ptr - buffer), 1)) == -1)
155 {
156 *error= MEMCACHED_WRITE_FAILURE;
157 goto error;
158 }
159
160 value= memcached_value_fetch(ptr, key, &key_length, value_length, flags,
161 error, 0, server_key);
162 if (*error == MEMCACHED_END && *value_length == 0)
163 {
164 *error= MEMCACHED_NOTFOUND;
165 goto error;
166 }
167 else if (*error == MEMCACHED_END)
168 assert(0); /* If this happens we have somehow messed up the fetch */
169 else if (*error == MEMCACHED_SUCCESS)
170 {
171 memcached_return rc;
172 /* We need to read END */
173 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
174
175 if (rc != MEMCACHED_END)
176 {
177 *error= MEMCACHED_PROTOCOL_ERROR;
178 goto error;
179 }
180 }
181 else
182 goto error;
183
184 LIBMEMCACHED_MEMCACHED_GET_END();
185
186 return value;
187
188 error:
189 free(value);
190 *value_length= 0;
191
192 LIBMEMCACHED_MEMCACHED_GET_END();
193
194 return NULL;
195 }
196
197 memcached_return memcached_mget(memcached_st *ptr,
198 char **keys, size_t *key_length,
199 unsigned int number_of_keys)
200 {
201 char buffer[HUGE_STRING_LEN];
202 unsigned int x;
203 memcached_return rc;
204 char *cursor_key_exec;
205 LIBMEMCACHED_MEMCACHED_MGET_START();
206
207 ptr->cursor_server= 0;
208 memset(buffer, 0, HUGE_STRING_LEN);
209
210 cursor_key_exec= (char *)malloc(sizeof(char) * ptr->number_of_hosts);
211 memset(cursor_key_exec, 0, sizeof(char) * ptr->number_of_hosts);
212
213
214 for (x= 0; x < number_of_keys; x++)
215 {
216 unsigned int server_key;
217
218 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
219
220 if (cursor_key_exec[server_key] == 0)
221 {
222 rc= memcached_connect(ptr, server_key);
223
224 if ((memcached_io_write(ptr, server_key, "get ", 4, 0)) == -1)
225 {
226 memcached_quit(ptr);
227 rc= MEMCACHED_SOME_ERRORS;
228 break;
229 }
230 }
231
232 if ((memcached_io_write(ptr, server_key, keys[x], key_length[x], 0)) == -1)
233 {
234 memcached_quit(ptr);
235 rc= MEMCACHED_SOME_ERRORS;
236 break;
237 }
238
239 if ((memcached_io_write(ptr, server_key, " ", 1, 0)) == -1)
240 {
241 memcached_quit(ptr);
242 rc= MEMCACHED_SOME_ERRORS;
243 break;
244 }
245 cursor_key_exec[server_key]= 1;
246 }
247
248
249 /*
250 Should we muddle on if some servers are dead?
251 */
252 for (x= 0; x < ptr->number_of_hosts; x++)
253 {
254 if (cursor_key_exec[x])
255 {
256 /* We need to doo something about non-connnected hosts in the future */
257 if ((memcached_io_write(ptr, x, "\r\n", 2, 1)) == -1)
258 {
259 memcached_quit(ptr);
260 rc= MEMCACHED_SOME_ERRORS;
261 break;
262 }
263
264 ptr->hosts[x].cursor_active= 1;
265 }
266 else
267 ptr->hosts[x].cursor_active= 0;
268 }
269
270 free(cursor_key_exec);
271
272 LIBMEMCACHED_MEMCACHED_MGET_END();
273 return rc;
274 }
275
276 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
277 size_t *value_length,
278 uint16_t *flags,
279 memcached_return *error)
280 {
281 char *value_check;
282
283 while (ptr->cursor_server < ptr->number_of_hosts)
284 {
285 if (!ptr->hosts[ptr->cursor_server].cursor_active)
286 {
287 ptr->cursor_server++;
288 continue;
289 }
290
291 value_check= memcached_value_fetch(ptr, key, key_length, value_length, flags,
292 error, 1, ptr->cursor_server);
293
294 if (*error == MEMCACHED_NOTFOUND)
295 ptr->cursor_server++;
296 else if (*error == MEMCACHED_END && *value_length == 0)
297 return NULL;
298 else if (*error == MEMCACHED_END)
299 assert(0); /* If this happens we have somehow messed up the fetch */
300 else if (*error != MEMCACHED_SUCCESS)
301 return NULL;
302 else
303 return value_check;
304
305 }
306
307 *value_length= 0;
308 return NULL;
309 }