Null
[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 memset(value, 0, ((*value_length) +2) * sizeof(char));
89
90 if (!value)
91 {
92 *value_length= 0;
93 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
94 return NULL;
95 }
96
97 value_ptr= value;
98 read_length= 0;
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 free(value);
107 goto read_error;
108 }
109
110 return value;
111 }
112 }
113 else if (*error == MEMCACHED_END)
114 *error= MEMCACHED_NOTFOUND;
115
116 return NULL;
117 read_error:
118 *error= MEMCACHED_PARTIAL_READ;
119 return NULL;
120 }
121
122 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
123 size_t *value_length,
124 uint16_t *flags,
125 memcached_return *error)
126 {
127 size_t send_length;
128 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
129 unsigned int server_key;
130 char *value;
131 LIBMEMCACHED_MEMCACHED_GET_START();
132
133 *value_length= 0;
134 *error= memcached_connect(ptr);
135
136 if (*error != MEMCACHED_SUCCESS)
137 goto error;
138
139 server_key= memcached_generate_hash(key, key_length) % ptr->number_of_hosts;
140
141 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n",
142 (int)key_length, key);
143
144 if ((memcached_io_write(ptr, server_key, buffer, send_length, 1)) == -1)
145 {
146 *error= MEMCACHED_WRITE_FAILURE;
147 goto error;
148 }
149
150 value= memcached_value_fetch(ptr, key, &key_length, value_length, flags,
151 error, 0, server_key);
152 if (*error == MEMCACHED_END && *value_length == 0)
153 {
154 *error= MEMCACHED_NOTFOUND;
155 goto error;
156 }
157 else if (*error == MEMCACHED_SUCCESS)
158 {
159 memcached_return rc;
160 /* We need to read END */
161 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
162
163 if (rc != MEMCACHED_END)
164 {
165 *error= MEMCACHED_PROTOCOL_ERROR;
166 goto error;
167 }
168 }
169 else
170 goto error;
171
172 LIBMEMCACHED_MEMCACHED_GET_END();
173
174 return value;
175
176 error:
177 free(value);
178 *value_length= 0;
179
180 LIBMEMCACHED_MEMCACHED_GET_END();
181
182 return NULL;
183 }
184
185 memcached_return memcached_mget(memcached_st *ptr,
186 char **keys, size_t *key_length,
187 unsigned int number_of_keys)
188 {
189 char buffer[HUGE_STRING_LEN];
190 unsigned int x;
191 memcached_return rc;
192 memcached_string_st **cursor_key_exec;
193 LIBMEMCACHED_MEMCACHED_MGET_START();
194
195 ptr->cursor_server= 0;
196 memset(buffer, 0, HUGE_STRING_LEN);
197
198 rc= memcached_connect(ptr);
199
200 if (rc != MEMCACHED_SUCCESS)
201 return rc;
202
203 cursor_key_exec= (memcached_string_st **)malloc(sizeof(memcached_string_st *) * ptr->number_of_hosts);
204 memset(cursor_key_exec, 0, sizeof(memcached_string_st *) * ptr->number_of_hosts);
205
206
207 for (x= 0; x < number_of_keys; x++)
208 {
209 unsigned int server_key;
210
211 server_key= memcached_generate_hash(keys[x], key_length[x]) % ptr->number_of_hosts;
212
213 if (cursor_key_exec[server_key])
214 {
215 memcached_string_st *string= cursor_key_exec[server_key];
216
217 memcached_string_append_character(ptr, string, ' ');
218 memcached_string_append(ptr, string, keys[x], key_length[x]);
219 }
220 else
221 {
222 memcached_string_st *string= memcached_string_create(ptr, SMALL_STRING_LEN);
223
224 /* We need to figure out the correct way to error in case of this failure */
225 if (!string)
226 assert(0);
227
228 memcached_string_append(ptr, string, "get ", 4);
229 memcached_string_append(ptr, string, keys[x], key_length[x]);
230
231 cursor_key_exec[server_key]= string;
232 }
233 }
234
235
236 /*
237 Should we muddle on if some servers are dead?
238 */
239 for (x= 0; x < ptr->number_of_hosts; x++)
240 {
241 if (cursor_key_exec[x])
242 {
243 memcached_string_st *string= cursor_key_exec[x];
244 memcached_string_append(ptr, string, "\r\n", 2);
245
246 if ((memcached_io_write(ptr, x, string->string,
247 memcached_string_length(ptr, string), 1)) == -1)
248 {
249 memcached_quit(ptr);
250 rc= MEMCACHED_SOME_ERRORS;
251 }
252 memcached_string_free(ptr, string);
253 cursor_key_exec[x]= NULL; /* Remove warning */
254 }
255 }
256
257 free(cursor_key_exec);
258
259 LIBMEMCACHED_MEMCACHED_MGET_END();
260 return rc;
261 }
262
263 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
264 size_t *value_length,
265 uint16_t *flags,
266 memcached_return *error)
267 {
268 char *value_check;
269
270 while (ptr->cursor_server < ptr->number_of_hosts)
271 {
272 value_check= memcached_value_fetch(ptr, key, key_length, value_length, flags,
273 error, 1, ptr->cursor_server);
274
275 if (*error == MEMCACHED_NOTFOUND)
276 ptr->cursor_server++;
277 else if (*error != MEMCACHED_SUCCESS)
278 return NULL;
279 else
280 return value_check;
281 }
282
283 return NULL;
284 }