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 while ((server
= memcached_io_get_readable_server(ptr
, read_ret
))) {
145 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
146 *error
= memcached_response(server
, buffer
, sizeof(buffer
), result
);
148 if (*error
== MEMCACHED_IN_PROGRESS
) {
150 } else if (*error
== MEMCACHED_CONNECTION_FAILURE
) {
151 connection_failures
= true;
153 } else if (*error
== MEMCACHED_SUCCESS
) {
156 } else if (*error
== MEMCACHED_END
) {
157 memcached_server_response_reset(server
);
158 } else if (*error
!= MEMCACHED_NOTFOUND
) {
163 if (*error
== MEMCACHED_NOTFOUND
and result
->count
) {
164 *error
= MEMCACHED_END
;
165 } else if (*error
== MEMCACHED_MAXIMUM_RETURN
and result
->count
) {
166 *error
= MEMCACHED_END
;
167 } else if (*error
== MEMCACHED_MAXIMUM_RETURN
) // while() loop was never entered
169 *error
= MEMCACHED_NOTFOUND
;
170 } else if (connection_failures
) {
172 If we have a connection failure to some servers, the caller may
173 wish to treat that differently to getting a definitive NOT_FOUND
174 from all servers, so return MEMCACHED_CONNECTION_FAILURE to allow
177 *error
= MEMCACHED_CONNECTION_FAILURE
;
178 } else if (*error
== MEMCACHED_SUCCESS
) {
179 *error
= MEMCACHED_END
;
180 } else if (result
->count
== 0) {
181 *error
= MEMCACHED_NOTFOUND
;
184 /* We have completed reading data */
185 if (memcached_is_allocated(result
)) {
186 memcached_result_free(result
);
189 memcached_string_reset(&result
->value
);
195 memcached_return_t
memcached_fetch_execute(memcached_st
*shell
, memcached_execute_fn
*callback
,
196 void *context
, uint32_t number_of_callbacks
) {
197 Memcached
*ptr
= memcached2Memcached(shell
);
198 memcached_result_st
*result
= &ptr
->result
;
199 memcached_return_t rc
;
200 bool some_errors
= false;
202 while ((result
= memcached_fetch_result(ptr
, result
, &rc
))) {
203 if (memcached_failed(rc
) and rc
== MEMCACHED_NOTFOUND
) {
205 } else if (memcached_failed(rc
)) {
206 memcached_set_error(*ptr
, rc
, MEMCACHED_AT
);
211 for (uint32_t x
= 0; x
< number_of_callbacks
; x
++) {
212 memcached_return_t ret
= (*callback
[x
])(ptr
, result
, context
);
213 if (memcached_failed(ret
)) {
215 memcached_set_error(*ptr
, ret
, MEMCACHED_AT
);
222 return MEMCACHED_SOME_ERRORS
;
225 // If we were able to run all keys without issue we return
227 if (memcached_success(rc
)) {
228 return MEMCACHED_SUCCESS
;