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