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
;
31 *error
= memcached_mget_by_key(ptr
,
34 (char **)&key
, &key_length
, 1);
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
;
44 if (ptr
->get_key_failure
&& *error
== MEMCACHED_NOTFOUND
)
48 memcached_result_reset(&ptr
->result
);
49 rc
= ptr
->get_key_failure(ptr
, key
, key_length
, &ptr
->result
);
51 /* On all failure drop to returning NULL */
52 if (rc
== MEMCACHED_SUCCESS
|| rc
== MEMCACHED_BUFFERED
)
54 if (rc
== MEMCACHED_BUFFERED
)
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
);
59 memcached_behavior_set(ptr
, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
, 1);
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
));
66 if (rc
== MEMCACHED_BUFFERED
&& latch
== 0)
67 memcached_behavior_set(ptr
, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
, 0);
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
));
77 if (rc
== MEMCACHED_SUCCESS
|| rc
== MEMCACHED_BUFFERED
)
80 *value_length
= memcached_result_length(&ptr
->result
);
81 *flags
= memcached_result_flags(&ptr
->result
);
82 return memcached_string_c_copy(&ptr
->result
.value
);
90 (void)memcached_fetch(ptr
, NULL
, NULL
,
91 &dummy_length
, &dummy_flags
,
93 WATCHPOINT_ASSERT(dummy_length
== 0);
98 memcached_return
memcached_mget(memcached_st
*ptr
,
99 char **keys
, size_t *key_length
,
100 unsigned int number_of_keys
)
102 return memcached_mget_by_key(ptr
, NULL
, 0, keys
, key_length
, number_of_keys
);
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
);
110 memcached_return
memcached_mget_by_key(memcached_st
*ptr
,
111 const char *master_key
,
112 size_t master_key_length
,
115 unsigned int number_of_keys
)
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;
123 LIBMEMCACHED_MEMCACHED_MGET_START();
124 ptr
->cursor_server
= 0;
126 if (number_of_keys
== 0)
127 return MEMCACHED_NOTFOUND
;
129 if (ptr
->number_of_hosts
== 0)
130 return MEMCACHED_NO_SERVERS
;
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
;
135 if (ptr
->flags
& MEM_SUPPORT_CAS
)
137 get_command
= "gets ";
138 get_command_length
= 5;
141 if (master_key
&& master_key_length
)
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
);
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.
152 It might be optimum to bounce the connection if count > some number.
154 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
156 if (memcached_server_response_count(&ptr
->hosts
[x
]))
158 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
160 if (ptr
->flags
& MEM_NO_BLOCK
)
161 (void)memcached_io_write(&ptr
->hosts
[x
], NULL
, 0, 1);
163 while(memcached_server_response_count(&ptr
->hosts
[x
]))
164 (void)memcached_response(&ptr
->hosts
[x
], buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, &ptr
->result
);
168 if (ptr
->flags
& MEM_BINARY_PROTOCOL
)
169 return binary_mget_by_key(ptr
, master_server_key
, keys
,
170 key_length
, number_of_keys
);
173 If a server fails we warn about errors and start all over with sending keys
176 for (x
= 0; x
< number_of_keys
; x
++)
178 unsigned int server_key
;
180 if (master_server_key
)
181 server_key
= master_server_key
;
183 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
185 if (memcached_server_response_count(&ptr
->hosts
[server_key
]) == 0)
187 rc
= memcached_connect(&ptr
->hosts
[server_key
]);
189 if (rc
!= MEMCACHED_SUCCESS
)
192 if ((memcached_io_write(&ptr
->hosts
[server_key
], get_command
, get_command_length
, 0)) == -1)
194 rc
= MEMCACHED_SOME_ERRORS
;
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);
202 /* Only called when we have a prefix key */
203 if (ptr
->prefix_key
[0] != 0)
205 if ((memcached_io_write(&ptr
->hosts
[server_key
], ptr
->prefix_key
, ptr
->prefix_key_length
, 0)) == -1)
207 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
208 rc
= MEMCACHED_SOME_ERRORS
;
213 if ((memcached_io_write(&ptr
->hosts
[server_key
], keys
[x
], key_length
[x
], 0)) == -1)
215 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
216 rc
= MEMCACHED_SOME_ERRORS
;
220 if ((memcached_io_write(&ptr
->hosts
[server_key
], " ", 1, 0)) == -1)
222 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
223 rc
= MEMCACHED_SOME_ERRORS
;
229 Should we muddle on if some servers are dead?
231 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
233 if (memcached_server_response_count(&ptr
->hosts
[x
]))
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)
238 rc
= MEMCACHED_SOME_ERRORS
;
243 LIBMEMCACHED_MEMCACHED_MGET_END();
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
)
252 memcached_return rc
= MEMCACHED_NOTFOUND
;
255 int flush
= number_of_keys
== 1;
258 If a server fails we warn about errors and start all over with sending keys
261 for (x
= 0; x
< number_of_keys
; x
++)
263 unsigned int server_key
;
265 if (master_server_key
)
266 server_key
= master_server_key
;
268 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
270 if (memcached_server_response_count(&ptr
->hosts
[server_key
]) == 0)
272 rc
= memcached_connect(&ptr
->hosts
[server_key
]);
273 if (rc
!= MEMCACHED_SUCCESS
)
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
;
282 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_GETKQ
;
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
]);
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))
293 memcached_server_response_reset(&ptr
->hosts
[server_key
]);
294 rc
= MEMCACHED_SOME_ERRORS
;
297 memcached_server_response_increment(&ptr
->hosts
[server_key
]);
300 if (number_of_keys
> 1)
303 * Send a noop command to flush the buffers
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
;
310 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
311 if (memcached_server_response_count(&ptr
->hosts
[x
]))
313 if (memcached_io_write(&ptr
->hosts
[x
], NULL
, 0, 1) == -1)
315 memcached_server_response_reset(&ptr
->hosts
[x
]);
316 memcached_io_reset(&ptr
->hosts
[x
]);
317 rc
= MEMCACHED_SOME_ERRORS
;
320 if (memcached_io_write(&ptr
->hosts
[x
], request
.bytes
,
321 sizeof(request
.bytes
), 1) == -1)
323 memcached_server_response_reset(&ptr
->hosts
[x
]);
324 memcached_io_reset(&ptr
->hosts
[x
]);
325 rc
= MEMCACHED_SOME_ERRORS
;
327 memcached_server_response_increment(&ptr
->hosts
[x
]);