2 +--------------------------------------------------------------------+
3 | libmemcached-awesome - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020-2021 Michael Wallner https://awesome.co/ |
13 +--------------------------------------------------------------------+
16 #include "libmemcached/common.h"
18 char *memcached_fetch(memcached_st
*shell
, char *key
, size_t *key_length
, size_t *value_length
,
19 uint32_t *flags
, memcached_return_t
*error
) {
20 Memcached
*ptr
= memcached2Memcached(shell
);
21 memcached_return_t unused
;
26 if (memcached_is_udp(ptr
)) {
43 *error
= MEMCACHED_NOT_SUPPORTED
;
47 memcached_result_st
*result_buffer
= &ptr
->result
;
48 result_buffer
= memcached_fetch_result(ptr
, result_buffer
, error
);
49 if (result_buffer
== NULL
or memcached_failed(*error
)) {
50 WATCHPOINT_ASSERT(result_buffer
== NULL
);
71 *value_length
= memcached_string_length(&result_buffer
->value
);
75 if (result_buffer
->key_length
> MEMCACHED_MAX_KEY
) {
76 *error
= MEMCACHED_KEY_TOO_BIG
;
96 strncpy(key
, result_buffer
->item_key
,
97 result_buffer
->key_length
); // For the binary protocol we will cut off the key :(
99 *key_length
= result_buffer
->key_length
;
104 *flags
= result_buffer
->item_flags
;
107 return memcached_string_take_value(&result_buffer
->value
);
110 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
, memcached_result_st
*result
,
111 memcached_return_t
*error
) {
112 memcached_return_t unused
;
118 *error
= MEMCACHED_INVALID_ARGUMENTS
;
122 if (memcached_is_udp(ptr
)) {
123 *error
= MEMCACHED_NOT_SUPPORTED
;
127 if (result
== NULL
) {
128 // If we have already initialized (ie it is in use) our internal, we
130 if (memcached_is_initialized(&ptr
->result
)) {
131 if ((result
= memcached_result_create(ptr
, NULL
)) == NULL
) {
132 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
136 result
= memcached_result_create(ptr
, &ptr
->result
);
140 *error
= MEMCACHED_MAXIMUM_RETURN
; // We use this to see if we ever go into the loop
141 memcached_instance_st
*server
;
142 memcached_return_t read_ret
= MEMCACHED_SUCCESS
;
143 bool connection_failures
= false;
144 bool timeouts
= false;
145 while ((server
= memcached_io_get_readable_server(ptr
, read_ret
))) {
146 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
147 *error
= memcached_response(server
, buffer
, sizeof(buffer
), result
);
149 if (*error
== MEMCACHED_IN_PROGRESS
) {
151 } else if (*error
== MEMCACHED_CONNECTION_FAILURE
) {
152 connection_failures
= true;
154 } else if (*error
== MEMCACHED_TIMEOUT
) {
156 } else if (*error
== MEMCACHED_SUCCESS
) {
159 } else if (*error
== MEMCACHED_END
) {
160 memcached_server_response_reset(server
);
161 } else if (*error
!= MEMCACHED_NOTFOUND
) {
166 if (*error
== MEMCACHED_NOTFOUND
and result
->count
) {
167 *error
= MEMCACHED_END
;
168 } else if (*error
== MEMCACHED_MAXIMUM_RETURN
and result
->count
) {
169 *error
= MEMCACHED_END
;
170 } else if (*error
== MEMCACHED_MAXIMUM_RETURN
) // while() loop was never entered
172 *error
= MEMCACHED_NOTFOUND
;
173 } else if (connection_failures
) {
175 If we have a connection failure to some servers, the caller may
176 wish to treat that differently to getting a definitive NOT_FOUND
177 from all servers, so return MEMCACHED_CONNECTION_FAILURE to allow
180 *error
= MEMCACHED_CONNECTION_FAILURE
;
181 } else if (timeouts
) {
182 *error
= MEMCACHED_TIMEOUT
;
183 } else if (*error
== MEMCACHED_SUCCESS
) {
184 *error
= MEMCACHED_END
;
185 } else if (result
->count
== 0) {
186 *error
= MEMCACHED_NOTFOUND
;
189 /* We have completed reading data */
190 if (memcached_is_allocated(result
)) {
191 memcached_result_free(result
);
194 memcached_string_reset(&result
->value
);
200 memcached_return_t
memcached_fetch_execute(memcached_st
*shell
, memcached_execute_fn
*callback
,
201 void *context
, uint32_t number_of_callbacks
) {
202 Memcached
*ptr
= memcached2Memcached(shell
);
203 memcached_result_st
*result
= &ptr
->result
;
204 memcached_return_t rc
;
205 bool some_errors
= false;
207 while ((result
= memcached_fetch_result(ptr
, result
, &rc
))) {
208 if (memcached_failed(rc
) and rc
== MEMCACHED_NOTFOUND
) {
210 } else if (memcached_failed(rc
)) {
211 memcached_set_error(*ptr
, rc
, MEMCACHED_AT
);
216 for (uint32_t x
= 0; x
< number_of_callbacks
; x
++) {
217 memcached_return_t ret
= (*callback
[x
])(ptr
, result
, context
);
218 if (memcached_failed(ret
)) {
220 memcached_set_error(*ptr
, ret
, MEMCACHED_AT
);
227 return MEMCACHED_SOME_ERRORS
;
230 // If we were able to run all keys without issue we return
232 if (memcached_success(rc
)) {
233 return MEMCACHED_SUCCESS
;