Cleaning out asserts;
[awesomized/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 /*
129 What happens if no servers exist?
130 */
131 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
132 size_t *value_length,
133 uint16_t *flags,
134 memcached_return *error)
135 {
136 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
137 char *buf_ptr= buffer;
138 unsigned int server_key;
139 char *value= NULL;
140 LIBMEMCACHED_MEMCACHED_GET_START();
141
142 server_key= memcached_generate_hash(ptr, key, key_length);
143
144 *value_length= 0;
145 *error= memcached_connect(ptr, server_key);
146
147 if (*error != MEMCACHED_SUCCESS)
148 goto error;
149
150 memcpy(buf_ptr, "get ", 4);
151 buf_ptr+= 4;
152 memcpy(buf_ptr, key, key_length);
153 buf_ptr+= key_length;
154 memcpy(buf_ptr, "\r\n", 2);
155 buf_ptr+= 2;
156
157 if ((memcached_io_write(ptr, server_key, buffer, (size_t)(buf_ptr - buffer), 1)) == -1)
158 {
159 *error= MEMCACHED_WRITE_FAILURE;
160 goto error;
161 }
162
163 value= memcached_value_fetch(ptr, key, &key_length, value_length, flags,
164 error, 0, server_key);
165 if (*error == MEMCACHED_END && *value_length == 0)
166 {
167 *error= MEMCACHED_NOTFOUND;
168 goto error;
169 }
170 else if (*error == MEMCACHED_END)
171 {
172 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
173 }
174 else if (*error == MEMCACHED_SUCCESS)
175 {
176 memcached_return rc;
177 /* We need to read END */
178 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
179
180 if (rc != MEMCACHED_END)
181 {
182 *error= MEMCACHED_PROTOCOL_ERROR;
183 goto error;
184 }
185 }
186 else
187 goto error;
188
189 LIBMEMCACHED_MEMCACHED_GET_END();
190
191 return value;
192
193 error:
194 free(value);
195 *value_length= 0;
196
197 LIBMEMCACHED_MEMCACHED_GET_END();
198
199 return NULL;
200 }
201
202 memcached_return memcached_mget(memcached_st *ptr,
203 char **keys, size_t *key_length,
204 unsigned int number_of_keys)
205 {
206 unsigned int x;
207 memcached_return rc= MEMCACHED_NOTFOUND;
208 char *cursor_key_exec;
209 LIBMEMCACHED_MEMCACHED_MGET_START();
210 ptr->cursor_server= 0;
211
212 if (number_of_keys == 0)
213 return MEMCACHED_NOTFOUND;
214
215 cursor_key_exec= (char *)malloc(sizeof(char) * ptr->number_of_hosts);
216 memset(cursor_key_exec, 0, sizeof(char) * ptr->number_of_hosts);
217
218 for (x= 0; x < number_of_keys; x++)
219 {
220 unsigned int server_key;
221
222 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
223
224 if (cursor_key_exec[server_key] == 0)
225 {
226 rc= memcached_connect(ptr, server_key);
227
228 if ((memcached_io_write(ptr, server_key, "get ", 4, 0)) == -1)
229 {
230 memcached_quit(ptr);
231 rc= MEMCACHED_SOME_ERRORS;
232 break;
233 }
234 }
235
236 if ((memcached_io_write(ptr, server_key, keys[x], key_length[x], 0)) == -1)
237 {
238 memcached_quit(ptr);
239 rc= MEMCACHED_SOME_ERRORS;
240 break;
241 }
242
243 if ((memcached_io_write(ptr, server_key, " ", 1, 0)) == -1)
244 {
245 memcached_quit(ptr);
246 rc= MEMCACHED_SOME_ERRORS;
247 break;
248 }
249 cursor_key_exec[server_key]= 1;
250 }
251
252
253 /*
254 Should we muddle on if some servers are dead?
255 */
256 for (x= 0; x < ptr->number_of_hosts; x++)
257 {
258 if (cursor_key_exec[x])
259 {
260 /* We need to doo something about non-connnected hosts in the future */
261 if ((memcached_io_write(ptr, x, "\r\n", 2, 1)) == -1)
262 {
263 memcached_quit(ptr);
264 rc= MEMCACHED_SOME_ERRORS;
265 break;
266 }
267
268 ptr->hosts[x].cursor_active= 1;
269 }
270 else
271 ptr->hosts[x].cursor_active= 0;
272 }
273
274 free(cursor_key_exec);
275
276 LIBMEMCACHED_MEMCACHED_MGET_END();
277 return rc;
278 }
279
280 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
281 size_t *value_length,
282 uint16_t *flags,
283 memcached_return *error)
284 {
285 char *value_check;
286
287 while (ptr->cursor_server < ptr->number_of_hosts)
288 {
289 if (!ptr->hosts[ptr->cursor_server].cursor_active)
290 {
291 ptr->cursor_server++;
292 continue;
293 }
294
295 value_check= memcached_value_fetch(ptr, key, key_length, value_length, flags,
296 error, 1, ptr->cursor_server);
297
298 if (*error == MEMCACHED_NOTFOUND)
299 ptr->cursor_server++;
300 else if (*error == MEMCACHED_END && *value_length == 0)
301 return NULL;
302 else if (*error == MEMCACHED_END)
303 {
304 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
305 }
306 else if (*error != MEMCACHED_SUCCESS)
307 return NULL;
308 else
309 return value_check;
310
311 }
312
313 *value_length= 0;
314 return NULL;
315 }