2 #include "memcached_io.h"
5 What happens if no servers exist?
7 char *memcached_get(memcached_st
*ptr
, const char *key
,
11 memcached_return
*error
)
13 return memcached_get_by_key(ptr
, NULL
, 0, key
, key_length
, value_length
,
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
,
23 memcached_return
*error
)
28 memcached_return dummy_error
;
30 if (ptr
->flags
& MEM_USE_UDP
)
32 *error
= MEMCACHED_NOT_SUPPORTED
;
37 *error
= memcached_mget_by_key(ptr
,
40 (char **)&key
, &key_length
, 1);
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
;
50 if (ptr
->get_key_failure
&& *error
== MEMCACHED_NOTFOUND
)
54 memcached_result_reset(&ptr
->result
);
55 rc
= ptr
->get_key_failure(ptr
, key
, key_length
, &ptr
->result
);
57 /* On all failure drop to returning NULL */
58 if (rc
== MEMCACHED_SUCCESS
|| rc
== MEMCACHED_BUFFERED
)
60 if (rc
== MEMCACHED_BUFFERED
)
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
);
65 memcached_behavior_set(ptr
, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
, 1);
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
));
72 if (rc
== MEMCACHED_BUFFERED
&& latch
== 0)
73 memcached_behavior_set(ptr
, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
, 0);
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
));
83 if (rc
== MEMCACHED_SUCCESS
|| rc
== MEMCACHED_BUFFERED
)
86 *value_length
= memcached_result_length(&ptr
->result
);
87 *flags
= memcached_result_flags(&ptr
->result
);
88 return memcached_string_c_copy(&ptr
->result
.value
);
96 (void)memcached_fetch(ptr
, NULL
, NULL
,
97 &dummy_length
, &dummy_flags
,
99 WATCHPOINT_ASSERT(dummy_length
== 0);
104 memcached_return
memcached_mget(memcached_st
*ptr
,
105 char **keys
, size_t *key_length
,
106 unsigned int number_of_keys
)
108 return memcached_mget_by_key(ptr
, NULL
, 0, keys
, key_length
, number_of_keys
);
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
);
116 memcached_return
memcached_mget_by_key(memcached_st
*ptr
,
117 const char *master_key
,
118 size_t master_key_length
,
121 unsigned int number_of_keys
)
124 memcached_return rc
= MEMCACHED_NOTFOUND
;
125 char *get_command
= "get ";
126 uint8_t get_command_length
= 4;
127 unsigned int master_server_key
= -1; /* 0 is a valid server id! */
129 if (ptr
->flags
& MEM_USE_UDP
)
130 return MEMCACHED_NOT_SUPPORTED
;
132 LIBMEMCACHED_MEMCACHED_MGET_START();
133 ptr
->cursor_server
= 0;
135 if (number_of_keys
== 0)
136 return MEMCACHED_NOTFOUND
;
138 if (ptr
->number_of_hosts
== 0)
139 return MEMCACHED_NO_SERVERS
;
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
;
144 if (ptr
->flags
& MEM_SUPPORT_CAS
)
146 get_command
= "gets ";
147 get_command_length
= 5;
150 if (master_key
&& master_key_length
)
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
);
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.
161 It might be optimum to bounce the connection if count > some number.
163 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
165 if (memcached_server_response_count(&ptr
->hosts
[x
]))
167 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
169 if (ptr
->flags
& MEM_NO_BLOCK
)
170 (void)memcached_io_write(&ptr
->hosts
[x
], NULL
, 0, 1);
172 while(memcached_server_response_count(&ptr
->hosts
[x
]))
173 (void)memcached_response(&ptr
->hosts
[x
], buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, &ptr
->result
);
177 if (ptr
->flags
& MEM_BINARY_PROTOCOL
)
178 return binary_mget_by_key(ptr
, master_server_key
, keys
,
179 key_length
, number_of_keys
);
182 If a server fails we warn about errors and start all over with sending keys
185 for (x
= 0; x
< number_of_keys
; x
++)
187 unsigned int server_key
;
189 if (master_server_key
!= -1)
190 server_key
= master_server_key
;
192 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
194 if (memcached_server_response_count(&ptr
->hosts
[server_key
]) == 0)
196 rc
= memcached_connect(&ptr
->hosts
[server_key
]);
198 if (rc
!= MEMCACHED_SUCCESS
)
201 if ((memcached_io_write(&ptr
->hosts
[server_key
], get_command
, get_command_length
, 0)) == -1)
203 rc
= MEMCACHED_SOME_ERRORS
;
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);
211 /* Only called when we have a prefix key */
212 if (ptr
->prefix_key
[0] != 0)
214 if ((memcached_io_write(&ptr
->hosts
[server_key
], ptr
->prefix_key
, ptr
->prefix_key_length
, 0)) == -1)
216 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
217 rc
= MEMCACHED_SOME_ERRORS
;
222 if ((memcached_io_write(&ptr
->hosts
[server_key
], keys
[x
], key_length
[x
], 0)) == -1)
224 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
225 rc
= MEMCACHED_SOME_ERRORS
;
229 if ((memcached_io_write(&ptr
->hosts
[server_key
], " ", 1, 0)) == -1)
231 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
232 rc
= MEMCACHED_SOME_ERRORS
;
238 Should we muddle on if some servers are dead?
240 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
242 if (memcached_server_response_count(&ptr
->hosts
[x
]))
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)
247 rc
= MEMCACHED_SOME_ERRORS
;
252 LIBMEMCACHED_MEMCACHED_MGET_END();
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
)
261 memcached_return rc
= MEMCACHED_NOTFOUND
;
264 int flush
= number_of_keys
== 1;
267 If a server fails we warn about errors and start all over with sending keys
270 for (x
= 0; x
< number_of_keys
; x
++)
272 unsigned int server_key
;
274 if (master_server_key
)
275 server_key
= master_server_key
;
277 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
279 if (memcached_server_response_count(&ptr
->hosts
[server_key
]) == 0)
281 rc
= memcached_connect(&ptr
->hosts
[server_key
]);
282 if (rc
!= MEMCACHED_SUCCESS
)
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
;
291 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_GETKQ
;
294 vk
= memcached_validate_key_length(key_length
[x
],
295 ptr
->flags
& MEM_BINARY_PROTOCOL
);
296 unlikely (vk
!= MEMCACHED_SUCCESS
)
299 memcached_io_reset(&ptr
->hosts
[server_key
]);
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
]);
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))
312 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
313 rc
= MEMCACHED_SOME_ERRORS
;
316 memcached_server_response_increment(&ptr
->hosts
[server_key
]);
319 if (number_of_keys
> 1)
322 * Send a noop command to flush the buffers
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
;
329 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
330 if (memcached_server_response_count(&ptr
->hosts
[x
]))
332 if (memcached_io_write(&ptr
->hosts
[x
], NULL
, 0, 1) == -1)
334 memcached_server_response_reset(&ptr
->hosts
[x
]);
335 memcached_io_reset(&ptr
->hosts
[x
]);
336 rc
= MEMCACHED_SOME_ERRORS
;
339 if (memcached_io_write(&ptr
->hosts
[x
], request
.bytes
,
340 sizeof(request
.bytes
), 1) == -1)
342 memcached_server_response_reset(&ptr
->hosts
[x
]);
343 memcached_io_reset(&ptr
->hosts
[x
]);
344 rc
= MEMCACHED_SOME_ERRORS
;
346 memcached_server_response_increment(&ptr
->hosts
[x
]);