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