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