9688286450d508392b5cfc9b31b9e7a6ba097833
[awesomized/libmemcached] / libmemcached / memcached_get.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 /*
5 What happens if no servers exist?
6 */
7 char *memcached_get(memcached_st *ptr, const char *key,
8 size_t key_length,
9 size_t *value_length,
10 uint32_t *flags,
11 memcached_return *error)
12 {
13 return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
14 flags, error);
15 }
16
17 char *memcached_get_by_key(memcached_st *ptr,
18 const char *master_key,
19 size_t master_key_length,
20 const char *key, size_t key_length,
21 size_t *value_length,
22 uint32_t *flags,
23 memcached_return *error)
24 {
25 char *value;
26 size_t dummy_length;
27 uint32_t dummy_flags;
28 memcached_return dummy_error;
29
30 if (ptr->flags & MEM_USE_UDP)
31 {
32 *error= MEMCACHED_NOT_SUPPORTED;
33 return NULL;
34 }
35
36 /* Request the key */
37 *error= memcached_mget_by_key(ptr,
38 master_key,
39 master_key_length,
40 (char **)&key, &key_length, 1);
41
42 value= memcached_fetch(ptr, NULL, NULL,
43 value_length, flags, error);
44 /* This is for historical reasons */
45 if (*error == MEMCACHED_END)
46 *error= MEMCACHED_NOTFOUND;
47
48 if (value == NULL)
49 {
50 if (ptr->get_key_failure && *error == MEMCACHED_NOTFOUND)
51 {
52 memcached_return rc;
53
54 memcached_result_reset(&ptr->result);
55 rc= ptr->get_key_failure(ptr, key, key_length, &ptr->result);
56
57 /* On all failure drop to returning NULL */
58 if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
59 {
60 if (rc == MEMCACHED_BUFFERED)
61 {
62 uint8_t latch; /* We use latch to track the state of the original socket */
63 latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
64 if (latch == 0)
65 memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
66
67 rc= memcached_set(ptr, key, key_length,
68 memcached_result_value(&ptr->result),
69 memcached_result_length(&ptr->result),
70 0, memcached_result_flags(&ptr->result));
71
72 if (rc == MEMCACHED_BUFFERED && latch == 0)
73 memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
74 }
75 else
76 {
77 rc= memcached_set(ptr, key, key_length,
78 memcached_result_value(&ptr->result),
79 memcached_result_length(&ptr->result),
80 0, memcached_result_flags(&ptr->result));
81 }
82
83 if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
84 {
85 *error= rc;
86 *value_length= memcached_result_length(&ptr->result);
87 *flags= memcached_result_flags(&ptr->result);
88 return memcached_string_c_copy(&ptr->result.value);
89 }
90 }
91 }
92
93 return NULL;
94 }
95
96 (void)memcached_fetch(ptr, NULL, NULL,
97 &dummy_length, &dummy_flags,
98 &dummy_error);
99 WATCHPOINT_ASSERT(dummy_length == 0);
100
101 return value;
102 }
103
104 memcached_return memcached_mget(memcached_st *ptr,
105 char **keys, size_t *key_length,
106 unsigned int number_of_keys)
107 {
108 return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
109 }
110
111 static memcached_return binary_mget_by_key(memcached_st *ptr,
112 unsigned int master_server_key,
113 char **keys, size_t *key_length,
114 unsigned int number_of_keys);
115
116 memcached_return memcached_mget_by_key(memcached_st *ptr,
117 const char *master_key,
118 size_t master_key_length,
119 char **keys,
120 size_t *key_length,
121 unsigned int number_of_keys)
122 {
123 unsigned int x;
124 memcached_return rc= MEMCACHED_NOTFOUND;
125 char *get_command= "get ";
126 uint8_t get_command_length= 4;
127 unsigned int master_server_key= 0;
128
129 if (ptr->flags & MEM_USE_UDP)
130 return MEMCACHED_NOT_SUPPORTED;
131
132 LIBMEMCACHED_MEMCACHED_MGET_START();
133 ptr->cursor_server= 0;
134
135 if (number_of_keys == 0)
136 return MEMCACHED_NOTFOUND;
137
138 if (ptr->number_of_hosts == 0)
139 return MEMCACHED_NO_SERVERS;
140
141 if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED))
142 return MEMCACHED_BAD_KEY_PROVIDED;
143
144 if (ptr->flags & MEM_SUPPORT_CAS)
145 {
146 get_command= "gets ";
147 get_command_length= 5;
148 }
149
150 if (master_key && master_key_length)
151 {
152 if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test((char **)&master_key, &master_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
153 return MEMCACHED_BAD_KEY_PROVIDED;
154 master_server_key= memcached_generate_hash(ptr, master_key, master_key_length);
155 }
156
157 /*
158 Here is where we pay for the non-block API. We need to remove any data sitting
159 in the queue before we start our get.
160
161 It might be optimum to bounce the connection if count > some number.
162 */
163 for (x= 0; x < ptr->number_of_hosts; x++)
164 {
165 if (memcached_server_response_count(&ptr->hosts[x]))
166 {
167 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
168
169 if (ptr->flags & MEM_NO_BLOCK)
170 (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1);
171
172 while(memcached_server_response_count(&ptr->hosts[x]))
173 (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
174 }
175 }
176
177 if (ptr->flags & MEM_BINARY_PROTOCOL)
178 return binary_mget_by_key(ptr, master_server_key, keys,
179 key_length, number_of_keys);
180
181 /*
182 If a server fails we warn about errors and start all over with sending keys
183 to the server.
184 */
185 for (x= 0; x < number_of_keys; x++)
186 {
187 unsigned int server_key;
188
189 if (master_server_key)
190 server_key= master_server_key;
191 else
192 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
193
194 if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
195 {
196 rc= memcached_connect(&ptr->hosts[server_key]);
197
198 if (rc != MEMCACHED_SUCCESS)
199 continue;
200
201 if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1)
202 {
203 rc= MEMCACHED_SOME_ERRORS;
204 continue;
205 }
206 WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 0);
207 memcached_server_response_increment(&ptr->hosts[server_key]);
208 WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 1);
209 }
210
211 /* Only called when we have a prefix key */
212 if (ptr->prefix_key[0] != 0)
213 {
214 if ((memcached_io_write(&ptr->hosts[server_key], ptr->prefix_key, ptr->prefix_key_length, 0)) == -1)
215 {
216 memcached_server_response_reset(&ptr->hosts[server_key]);
217 rc= MEMCACHED_SOME_ERRORS;
218 continue;
219 }
220 }
221
222 if ((memcached_io_write(&ptr->hosts[server_key], keys[x], key_length[x], 0)) == -1)
223 {
224 memcached_server_response_reset(&ptr->hosts[server_key]);
225 rc= MEMCACHED_SOME_ERRORS;
226 continue;
227 }
228
229 if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1)
230 {
231 memcached_server_response_reset(&ptr->hosts[server_key]);
232 rc= MEMCACHED_SOME_ERRORS;
233 continue;
234 }
235 }
236
237 /*
238 Should we muddle on if some servers are dead?
239 */
240 for (x= 0; x < ptr->number_of_hosts; x++)
241 {
242 if (memcached_server_response_count(&ptr->hosts[x]))
243 {
244 /* We need to do something about non-connnected hosts in the future */
245 if ((memcached_io_write(&ptr->hosts[x], "\r\n", 2, 1)) == -1)
246 {
247 rc= MEMCACHED_SOME_ERRORS;
248 }
249 }
250 }
251
252 LIBMEMCACHED_MEMCACHED_MGET_END();
253 return rc;
254 }
255
256 static memcached_return binary_mget_by_key(memcached_st *ptr,
257 unsigned int master_server_key,
258 char **keys, size_t *key_length,
259 unsigned int number_of_keys)
260 {
261 memcached_return rc= MEMCACHED_NOTFOUND;
262 uint32_t x;
263
264 int flush= number_of_keys == 1;
265
266 /*
267 If a server fails we warn about errors and start all over with sending keys
268 to the server.
269 */
270 for (x= 0; x < number_of_keys; x++)
271 {
272 unsigned int server_key;
273
274 if (master_server_key)
275 server_key= master_server_key;
276 else
277 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
278
279 if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
280 {
281 rc= memcached_connect(&ptr->hosts[server_key]);
282 if (rc != MEMCACHED_SUCCESS)
283 continue;
284 }
285
286 protocol_binary_request_getk request= {.bytes= {0}};
287 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
288 if (number_of_keys == 1)
289 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
290 else
291 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
292
293 memcached_return vk;
294 vk= memcached_validate_key_length(key_length[x],
295 ptr->flags & MEM_BINARY_PROTOCOL);
296 unlikely (vk != MEMCACHED_SUCCESS)
297 {
298 if (x > 0)
299 memcached_io_reset(&ptr->hosts[server_key]);
300 return vk;
301 }
302
303 request.message.header.request.keylen= htons((uint16_t)key_length[x]);
304 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
305 request.message.header.request.bodylen= htonl(key_length[x]);
306
307 if ((memcached_io_write(&ptr->hosts[server_key], request.bytes,
308 sizeof(request.bytes), 0) == -1) ||
309 (memcached_io_write(&ptr->hosts[server_key], keys[x],
310 key_length[x], flush) == -1))
311 {
312 memcached_server_response_reset(&ptr->hosts[server_key]);
313 rc= MEMCACHED_SOME_ERRORS;
314 continue;
315 }
316 memcached_server_response_increment(&ptr->hosts[server_key]);
317 }
318
319 if (number_of_keys > 1)
320 {
321 /*
322 * Send a noop command to flush the buffers
323 */
324 protocol_binary_request_noop request= {.bytes= {0}};
325 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
326 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_NOOP;
327 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
328
329 for (x= 0; x < ptr->number_of_hosts; x++)
330 if (memcached_server_response_count(&ptr->hosts[x]))
331 {
332 if (memcached_io_write(&ptr->hosts[x], NULL, 0, 1) == -1)
333 {
334 memcached_server_response_reset(&ptr->hosts[x]);
335 memcached_io_reset(&ptr->hosts[x]);
336 rc= MEMCACHED_SOME_ERRORS;
337 }
338
339 if (memcached_io_write(&ptr->hosts[x], request.bytes,
340 sizeof(request.bytes), 1) == -1)
341 {
342 memcached_server_response_reset(&ptr->hosts[x]);
343 memcached_io_reset(&ptr->hosts[x]);
344 rc= MEMCACHED_SOME_ERRORS;
345 }
346 memcached_server_response_increment(&ptr->hosts[x]);
347 }
348 }
349
350
351 return rc;
352 }