2 +--------------------------------------------------------------------+
3 | libmemcached - 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 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
16 #include "libmemcached/common.h"
18 static memcached_return_t
ascii_dump(Memcached
*memc
, memcached_dump_fn
*callback
, void *context
,
19 uint32_t number_of_callbacks
) {
20 memcached_version(memc
);
21 /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */
22 for (uint32_t x
= 0; x
< 200; x
++) {
23 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
24 int buffer_length
= snprintf(buffer
, sizeof(buffer
), "%u", x
);
25 if (size_t(buffer_length
) >= sizeof(buffer
) or buffer_length
< 0) {
26 return memcached_set_error(
27 *memc
, MEMCACHED_MEMORY_ALLOCATION_FAILURE
, MEMCACHED_AT
,
28 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
31 // @NOTE the hard coded zero means "no limit"
32 libmemcached_io_vector_st vector
[] = {{memcached_literal_param("stats cachedump ")},
33 {buffer
, size_t(buffer_length
)},
34 {memcached_literal_param(" 0\r\n")}};
36 // Send message to all servers
37 for (uint32_t server_key
= 0; server_key
< memcached_server_count(memc
); server_key
++) {
38 memcached_instance_st
*instance
= memcached_instance_fetch(memc
, server_key
);
40 // skip slabs >63 for server versions >= 1.4.23
41 if (x
< 64 || memcached_version_instance_cmp(instance
, 1, 4, 23) < 0) {
42 memcached_return_t vdo_rc
;
43 if (memcached_failed((vdo_rc
= memcached_vdo(instance
, vector
, 3, true)))) {
49 // Collect the returned items
50 memcached_instance_st
*instance
;
51 memcached_return_t read_ret
= MEMCACHED_SUCCESS
;
52 while ((instance
= memcached_io_get_readable_server(memc
, read_ret
))) {
53 memcached_return_t response_rc
=
54 memcached_response(instance
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, NULL
);
55 if (response_rc
== MEMCACHED_ITEM
) {
56 char *string_ptr
, *end_ptr
;
59 string_ptr
+= 5; /* Move past ITEM */
61 for (end_ptr
= string_ptr
; isgraph(*end_ptr
); end_ptr
++) {
64 char *key
= string_ptr
;
65 key
[(size_t)(end_ptr
- string_ptr
)] = 0;
67 for (uint32_t callback_counter
= 0; callback_counter
< number_of_callbacks
;
69 memcached_return_t callback_rc
=
70 (*callback
[callback_counter
])(memc
, key
, (size_t)(end_ptr
- string_ptr
), context
);
71 if (callback_rc
!= MEMCACHED_SUCCESS
) {
72 // @todo build up a message for the error from the value
73 memcached_set_error(*instance
, callback_rc
, MEMCACHED_AT
);
77 } else if (response_rc
== MEMCACHED_END
) {
78 // All items have been returned
79 } else if (response_rc
== MEMCACHED_SERVER_ERROR
) {
80 /* If we try to request stats cachedump for a slab class that is too big
81 * the server will return an incorrect error message:
82 * "MEMCACHED_SERVER_ERROR failed to allocate memory"
83 * This isn't really a fatal error, so let's just skip it. I want to
84 * fix the return value from the memcached server to a CLIENT_ERROR,
85 * so let's add support for that as well right now.
87 assert(response_rc
== MEMCACHED_SUCCESS
); // Just fail
89 } else if (response_rc
== MEMCACHED_CLIENT_ERROR
) {
90 /* The maximum number of slabs has changed in the past (currently 1<<6-1),
91 * so ignore any client errors complaining about an illegal slab id.
94 == strncmp(buffer
, "CLIENT_ERROR Illegal slab id",
95 sizeof("CLIENT_ERROR Illegal slab id") - 1))
97 memcached_error_free(*instance
);
98 memcached_error_free(*memc
);
103 // IO error of some sort must have occurred
109 return memcached_has_current_error(*memc
) ? MEMCACHED_SOME_ERRORS
: MEMCACHED_SUCCESS
;
112 memcached_return_t
memcached_dump(memcached_st
*shell
, memcached_dump_fn
*callback
, void *context
,
113 uint32_t number_of_callbacks
) {
114 Memcached
*ptr
= memcached2Memcached(shell
);
115 memcached_return_t rc
;
116 if (memcached_failed(rc
= initialize_query(ptr
, true))) {
121 No support for Binary protocol yet
122 @todo Fix this so that we just flush, switch to ascii, and then go back to binary.
124 if (memcached_is_binary(ptr
)) {
125 return memcached_set_error(
126 *ptr
, MEMCACHED_NOT_SUPPORTED
, MEMCACHED_AT
,
127 memcached_literal_param("Binary protocol is not supported for memcached_dump()"));
130 return ascii_dump(ptr
, callback
, context
, number_of_callbacks
);