Memory leak for failed attempt to use memcached_result_free()
[awesomized/libmemcached] / lib / memcached_get.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 static memcached_return memcached_value_fetch(memcached_st *ptr, char *key, size_t *key_length,
5 memcached_string_st *value,
6 uint16_t *flags,
7 uint64_t *cas,
8 char load_key,
9 unsigned int server_key)
10 {
11 memcached_return rc;
12 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
13 char *string_ptr;
14 char *end_ptr;
15
16 end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
17
18 *flags= 0;
19
20 memcached_string_reset(value);
21
22 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
23
24 if (rc == MEMCACHED_SUCCESS)
25 {
26 char *next_ptr;
27 size_t value_length;
28
29 string_ptr= buffer;
30 string_ptr+= 6; /* "VALUE " */
31
32 /* We load the key */
33 if (load_key)
34 {
35 *key_length= 0;
36
37 for (; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++)
38 {
39 *key= *string_ptr;
40 key++;
41 (*key_length)++;
42 }
43 }
44 else /* Skip characters */
45 for (; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
46
47 if (end_ptr == string_ptr)
48 goto read_error;
49
50 /* Flags fetch move past space */
51 string_ptr++;
52 if (end_ptr == string_ptr)
53 goto read_error;
54 for (next_ptr= string_ptr; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
55 *flags= (uint16_t)strtol(next_ptr, &string_ptr, 10);
56
57 if (end_ptr == string_ptr)
58 goto read_error;
59
60 /* Length fetch move past space*/
61 string_ptr++;
62 if (end_ptr == string_ptr)
63 goto read_error;
64
65 for (next_ptr= string_ptr; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
66 value_length= (size_t)strtoll(next_ptr, &string_ptr, 10);
67
68 if (end_ptr == string_ptr)
69 goto read_error;
70
71 /* Skip spaces */
72 if (*string_ptr == '\r')
73 {
74 /* Skip past the \r\n */
75 string_ptr+= 2;
76 }
77 else
78 {
79 string_ptr++;
80 for (next_ptr= string_ptr; end_ptr > string_ptr && *string_ptr != ' '; string_ptr++);
81 if (cas)
82 *cas= (size_t)strtoll(next_ptr, &string_ptr, 10);
83 }
84
85 if (end_ptr < string_ptr)
86 goto read_error;
87
88 if (value_length)
89 {
90 size_t read_length;
91 size_t to_read;
92 char *value_ptr;
93
94 /* We add two bytes so that we can walk the \r\n */
95 rc= memcached_string_check(value, value_length+2);
96 if (rc != MEMCACHED_SUCCESS)
97 {
98 value_length= 0;
99 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
100 }
101
102 value_ptr= memcached_string_value(value);
103 read_length= 0;
104 /*
105 We read the \r\n into the string since not doing so is more
106 cycles then the waster of memory to do so.
107
108 We are null terminating through, which will most likely make
109 some people lazy about using the return length.
110 */
111 to_read= (value_length) + 2;
112
113 read_length= memcached_io_read(ptr, server_key,
114 value_ptr, to_read);
115
116 if (read_length != (size_t)(value_length + 2))
117 {
118 goto read_error;
119 }
120
121 /* This next bit blows the API, but this is internal....*/
122 {
123 char *char_ptr;
124 char_ptr= memcached_string_value(value);;
125 char_ptr[value_length]= 0;
126 char_ptr[value_length + 1]= 0;
127 memcached_string_set_length(value, value_length);
128 }
129
130 return MEMCACHED_SUCCESS;
131 }
132 }
133 else if (rc == MEMCACHED_END)
134 rc= MEMCACHED_NOTFOUND;
135
136 return rc;
137
138 read_error:
139 return MEMCACHED_PARTIAL_READ;
140 }
141
142 /*
143 What happens if no servers exist?
144 */
145 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
146 size_t *value_length,
147 uint16_t *flags,
148 memcached_return *error)
149 {
150 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
151 char *buf_ptr= buffer;
152 unsigned int server_key;
153 memcached_string_st *result_buffer;
154 LIBMEMCACHED_MEMCACHED_GET_START();
155
156 if (key_length == 0)
157 {
158 *error= MEMCACHED_NO_KEY_PROVIDED;
159 return NULL;
160 }
161
162 if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
163 {
164 *error= MEMCACHED_NO_SERVERS;
165 return NULL;
166 }
167
168 server_key= memcached_generate_hash(ptr, key, key_length);
169 result_buffer= &ptr->result_buffer;
170
171 *value_length= 0;
172 memcpy(buf_ptr, "get ", 4);
173 buf_ptr+= 4;
174 memcpy(buf_ptr, key, key_length);
175 buf_ptr+= key_length;
176 memcpy(buf_ptr, "\r\n", 2);
177 buf_ptr+= 2;
178
179 *error= memcached_do(ptr, server_key, buffer, (size_t)(buf_ptr - buffer), 1);
180 if (*error != MEMCACHED_SUCCESS)
181 goto error;
182
183 *error= memcached_value_fetch(ptr, key, &key_length, result_buffer,
184 flags, NULL, 0, server_key);
185 *value_length= memcached_string_length(result_buffer);
186 if (*error == MEMCACHED_END && *value_length == 0)
187 {
188 *error= MEMCACHED_NOTFOUND;
189 goto error;
190 }
191 else if (*error == MEMCACHED_END)
192 {
193 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
194 }
195 else if (*error == MEMCACHED_SUCCESS)
196 {
197 memcached_return rc;
198 /* We need to read END */
199 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
200
201 if (rc != MEMCACHED_END)
202 {
203 *error= MEMCACHED_PROTOCOL_ERROR;
204 goto error;
205 }
206 }
207 else
208 goto error;
209
210 LIBMEMCACHED_MEMCACHED_GET_END();
211
212
213 return memcached_string_c_copy(result_buffer);
214
215 error:
216 *value_length= 0;
217
218 LIBMEMCACHED_MEMCACHED_GET_END();
219
220 return NULL;
221 }
222
223 memcached_return memcached_mget(memcached_st *ptr,
224 char **keys, size_t *key_length,
225 unsigned int number_of_keys)
226 {
227 unsigned int x;
228 memcached_return rc= MEMCACHED_NOTFOUND;
229 char *get_command= "get ";
230 uint8_t get_command_length= 4
231
232 LIBMEMCACHED_MEMCACHED_MGET_START();
233 ptr->cursor_server= 0;
234
235 if (number_of_keys == 0)
236 return MEMCACHED_NOTFOUND;
237
238 if (ptr->number_of_hosts == 0)
239 return MEMCACHED_NO_SERVERS;
240
241 if (ptr->flags & MEM_SUPPORT_CAS)
242 {
243 get_command= "gets ";
244 get_command_length= 5;
245 }
246
247 for (x= 0; x < number_of_keys; x++)
248 {
249 unsigned int server_key;
250
251 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
252
253 if (ptr->hosts[server_key].cursor_active == 0)
254 {
255 rc= memcached_connect(ptr, server_key);
256
257 if ((memcached_io_write(ptr, server_key, get_command, get_command_length, 0)) == -1)
258 {
259 memcached_quit_server(ptr, server_key);
260 rc= MEMCACHED_SOME_ERRORS;
261 continue;
262 }
263 ptr->hosts[server_key].cursor_active= 1;
264 }
265
266 if ((memcached_io_write(ptr, server_key, keys[x], key_length[x], 0)) == -1)
267 {
268 ptr->hosts[server_key].cursor_active = 0;
269 memcached_quit_server(ptr, server_key);
270 rc= MEMCACHED_SOME_ERRORS;
271 continue;
272 }
273
274 if ((memcached_io_write(ptr, server_key, " ", 1, 0)) == -1)
275 {
276 ptr->hosts[server_key].cursor_active = 0;
277 memcached_quit_server(ptr, server_key);
278 rc= MEMCACHED_SOME_ERRORS;
279 continue;
280 }
281 }
282
283
284 /*
285 Should we muddle on if some servers are dead?
286 */
287 for (x= 0; x < ptr->number_of_hosts; x++)
288 {
289 if (ptr->hosts[x].cursor_active == 1)
290 {
291 /* We need to doo something about non-connnected hosts in the future */
292 if ((memcached_io_write(ptr, x, "\r\n", 2, 1)) == -1)
293 {
294 memcached_quit_server(ptr, x);
295 rc= MEMCACHED_SOME_ERRORS;
296 }
297 }
298 }
299
300 LIBMEMCACHED_MEMCACHED_MGET_END();
301 return rc;
302 }
303
304 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
305 size_t *value_length,
306 uint16_t *flags,
307 memcached_return *error)
308 {
309 memcached_string_st *result_buffer;
310 result_buffer= &ptr->result_buffer;
311
312 while (ptr->cursor_server < ptr->number_of_hosts)
313 {
314 if (!ptr->hosts[ptr->cursor_server].cursor_active)
315 {
316 ptr->cursor_server++;
317 continue;
318 }
319
320 *error = memcached_value_fetch(ptr, key, key_length, result_buffer,
321 flags, NULL, 1, ptr->cursor_server);
322 *value_length= memcached_string_length(result_buffer);
323
324 if (*error == MEMCACHED_NOTFOUND)
325 {
326 ptr->hosts[ptr->cursor_server].cursor_active = 0;
327 ptr->cursor_server++;
328 }
329 else if (*error == MEMCACHED_END && *value_length == 0)
330 {
331 return NULL;
332 }
333 else if (*error == MEMCACHED_END)
334 {
335 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
336 *value_length= 0;
337 return NULL;
338 }
339 else if (*error != MEMCACHED_SUCCESS)
340 {
341 return NULL;
342 }
343 else
344 {
345 return memcached_string_c_copy(result_buffer);
346 }
347
348 }
349
350 *value_length= 0;
351 return NULL;
352 }
353
354 memcached_result_st *memcached_fetch_result(memcached_st *ptr,
355 memcached_result_st *result,
356 memcached_return *error)
357 {
358 if (result == NULL)
359 result= memcached_result_create(ptr, NULL);
360
361 while (ptr->cursor_server < ptr->number_of_hosts)
362 {
363 if (!ptr->hosts[ptr->cursor_server].cursor_active)
364 {
365 ptr->cursor_server++;
366 continue;
367 }
368
369 result->cas= 0; /* We do this so we do not send in any junk */
370 *error= memcached_value_fetch(ptr, result->key, &result->key_length,
371 &result->value,
372 &result->flags,
373 &result->cas,
374 1, ptr->cursor_server);
375
376 if (*error == MEMCACHED_NOTFOUND)
377 {
378 ptr->hosts[ptr->cursor_server].cursor_active = 0;
379 ptr->cursor_server++;
380 }
381 else if (*error == MEMCACHED_END && memcached_string_length((memcached_string_st *)(&result->value)) == 0)
382 {
383 goto error;
384 }
385 else if (*error == MEMCACHED_END)
386 {
387 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
388 goto error;
389 }
390 else if (*error != MEMCACHED_SUCCESS)
391 {
392 goto error;
393 }
394 else
395 {
396 return result;
397 }
398
399 }
400
401 error:
402 memcached_result_free(result);
403
404 return NULL;
405 }