static void print_analysis_report(memcached_st *memc,
memcached_analysis_st *report);
-static int opt_verbose= 0;
-static int opt_displayflag= 0;
-static int opt_analyze= 0;
+static bool opt_binary= false;
+static bool opt_verbose= false;
+static bool opt_server_version= false;
+static bool opt_analyze= false;
static char *opt_servers= NULL;
static char *stat_args= NULL;
static char *analyze_mode= NULL;
{(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
{(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
{(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
- {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
- {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+ {(OPTIONSTRING)"verbose", no_argument, NULL, OPT_VERBOSE},
+ {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+ {(OPTIONSTRING)"debug", no_argument, NULL, OPT_DEBUG},
+ {(OPTIONSTRING)"server-version", no_argument, NULL, OPT_SERVER_VERSION},
{(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
- {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
{(OPTIONSTRING)"analyze", optional_argument, NULL, OPT_ANALYZE},
{0, 0, 0, 0},
};
return MEMCACHED_SUCCESS;
}
+static memcached_return_t server_print_callback(const memcached_st *,
+ const memcached_server_st *instance,
+ void *)
+{
+ std::cerr << memcached_server_name(instance) << ":" << memcached_server_port(instance) <<
+ " " << int(instance->major_version) <<
+ "." << int(instance->minor_version) <<
+ "." << int(instance->micro_version) << std::endl;
+
+ return MEMCACHED_SUCCESS;
+}
+
int main(int argc, char *argv[])
{
options_parse(argc, argv);
}
memcached_st *memc= memcached_create(NULL);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
memcached_server_st *servers= memcached_servers_parse(opt_servers);
free(opt_servers);
memcached_return_t rc= memcached_server_push(memc, servers);
memcached_server_list_free(servers);
- if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS)
+ if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_SOME_ERRORS)
{
printf("Failure to communicate with servers (%s)\n",
memcached_strerror(memc, rc));
- exit(1);
+ exit(EXIT_FAILURE);
}
- if (opt_analyze)
+ if (opt_server_version)
{
- memcached_stat_st *memc_stat;
+ if (memcached_failed(memcached_version(memc)))
+ {
+ std::cerr << "Unable to obtain server version";
+ exit(EXIT_FAILURE);
+ }
- memc_stat= memcached_stat(memc, NULL, &rc);
+ memcached_server_fn callbacks[1];
+ callbacks[0]= server_print_callback;
+ memcached_server_cursor(memc, callbacks, NULL, 1);
+ }
+ else if (opt_analyze)
+ {
+ memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc);
- if (! memc_stat)
- exit(-1);
+ if (memc_stat == NULL)
+ {
+ exit(EXIT_FAILURE);
+ }
run_analyzer(memc, memc_stat);
break;
case OPT_VERBOSE: /* --verbose or -v */
- opt_verbose = OPT_VERBOSE;
+ opt_verbose= true;
break;
case OPT_DEBUG: /* --debug or -d */
- opt_verbose = OPT_DEBUG;
+ opt_verbose= true;
+ break;
+
+ case OPT_BINARY:
+ opt_binary= true;
+ break;
+
+ case OPT_SERVER_VERSION:
+ opt_server_version= true;
break;
case OPT_VERSION: /* --version or -V */
#include <libmemcached/common.h>
#include <libmemcached/string.hpp>
-static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
+static memcached_return_t textual_value_fetch(memcached_server_write_instance_st instance,
char *buffer,
memcached_result_st *result)
{
ssize_t read_length= 0;
size_t value_length;
- WATCHPOINT_ASSERT(ptr->root);
+ WATCHPOINT_ASSERT(instance->root);
char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
memcached_result_reset(result);
/* We load the key */
{
- char *key;
- size_t prefix_length;
-
- key= result->item_key;
+ char *key= result->item_key;
result->key_length= 0;
- for (prefix_length= memcached_array_size(ptr->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+ for (size_t prefix_length= memcached_array_size(instance->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
{
if (prefix_length == 0)
{
/* We add two bytes so that we can walk the \r\n */
if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
{
- return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
}
{
some people lazy about using the return length.
*/
size_t to_read= (value_length) + 2;
- memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, read_length);
+ memcached_return_t rrc= memcached_io_read(instance, value_ptr, to_read, read_length);
if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
{
- memcached_quit_server(ptr, true);
- return memcached_set_error(*ptr, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
+ memcached_quit_server(instance, true);
+ return memcached_set_error(*instance, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
}
else if (memcached_failed(rrc))
{
return MEMCACHED_SUCCESS;
read_error:
- memcached_io_reset(ptr);
+ memcached_io_reset(instance);
return MEMCACHED_PARTIAL_READ;
}
buffer, total_read);
}
-static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
+static memcached_return_t binary_read_one_response(memcached_server_write_instance_st instance,
char *buffer, const size_t buffer_length,
memcached_result_st *result)
{
memcached_return_t rc;
protocol_binary_response_header header;
- if ((rc= memcached_safe_read(ptr, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(rc);
return rc;
if (header.response.magic != PROTOCOL_BINARY_RES)
{
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
/*
* We didn't increment the response counter for the GETKQ packet
* (only the final NOOP), so we need to increment the counter again.
*/
- memcached_server_response_increment(ptr);
+ memcached_server_response_increment(instance);
/* FALLTHROUGH */
case PROTOCOL_BINARY_CMD_GETK:
{
memcached_result_reset(result);
result->item_cas= header.response.cas;
- if ((rc= memcached_safe_read(ptr, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
bodylen -= header.response.extlen;
result->key_length= keylen;
- if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, keylen)))
+ if (memcached_failed(rc= memcached_safe_read(instance, result->item_key, keylen)))
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
// Only bother with doing this if key_length > 0
if (result->key_length)
{
- if (memcached_array_size(ptr->root->_namespace) and memcached_array_size(ptr->root->_namespace) >= result->key_length)
+ if (memcached_array_size(instance->root->_namespace) and memcached_array_size(instance->root->_namespace) >= result->key_length)
{
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
- if (memcached_array_size(ptr->root->_namespace))
+ if (memcached_array_size(instance->root->_namespace))
{
- result->key_length-= memcached_array_size(ptr->root->_namespace);
- memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->_namespace), result->key_length);
+ result->key_length-= memcached_array_size(instance->root->_namespace);
+ memmove(result->item_key, result->item_key +memcached_array_size(instance->root->_namespace), result->key_length);
}
}
}
char *vptr= memcached_string_value_mutable(&result->value);
- if (memcached_failed(rc= memcached_safe_read(ptr, vptr, bodylen)))
+ if (memcached_failed(rc= memcached_safe_read(instance, vptr, bodylen)))
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
if (bodylen != sizeof(uint64_t))
{
result->numeric_value= UINT64_MAX;
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
uint64_t val;
- if ((rc= memcached_safe_read(ptr, &val, sizeof(val))) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, &val, sizeof(val))) != MEMCACHED_SUCCESS)
{
result->numeric_value= UINT64_MAX;
return MEMCACHED_UNKNOWN_READ_FAILURE;
case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
case PROTOCOL_BINARY_CMD_VERSION:
{
- memset(buffer, 0, buffer_length);
- if (bodylen >= buffer_length)
+ char version_buffer[32]; // @todo document this number
+ memset(version_buffer, 0, sizeof(version_buffer));
+
+ if (memcached_safe_read(instance, version_buffer, bodylen) != MEMCACHED_SUCCESS)
{
- /* not enough space in buffer.. should not happen... */
return MEMCACHED_UNKNOWN_READ_FAILURE;
}
- else if ((rc= memcached_safe_read(ptr, buffer, bodylen)) != MEMCACHED_SUCCESS)
+
+ char *p;
+ long int version= strtol(version_buffer, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
{
- WATCHPOINT_ERROR(rc);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
+ }
+ instance->major_version= uint8_t(version);
+
+ version= strtol(p +1, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
+ {
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
+ }
+ instance->minor_version= uint8_t(version);
+
+ version= strtol(p + 1, NULL, 10);
+ if (errno == ERANGE)
+ {
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
}
+ instance->micro_version= uint8_t(version);
}
break;
+
case PROTOCOL_BINARY_CMD_FLUSH:
case PROTOCOL_BINARY_CMD_QUIT:
case PROTOCOL_BINARY_CMD_SET:
{
size_t keylen= header.response.keylen;
memset(buffer, 0, buffer_length);
- if ((rc= memcached_safe_read(ptr, buffer, keylen)) != MEMCACHED_SUCCESS ||
- (rc= memcached_safe_read(ptr, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, buffer, keylen)) != MEMCACHED_SUCCESS ||
+ (rc= memcached_safe_read(instance, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
char *vptr= memcached_string_value_mutable(&result->value);
- if ((rc= memcached_safe_read(ptr, vptr, bodylen)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, vptr, bodylen)) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
default:
{
/* Command not implemented yet! */
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
}
}
while (bodylen > 0)
{
size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
- if ((rc= memcached_safe_read(ptr, hole, nr)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_safe_read(instance, hole, nr)) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(rc);
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
bodylen-= (uint32_t) nr;
}
case PROTOCOL_BINARY_CMD_REPLACEQ:
case PROTOCOL_BINARY_CMD_APPENDQ:
case PROTOCOL_BINARY_CMD_PREPENDQ:
- return binary_read_one_response(ptr, buffer, buffer_length, result);
+ return binary_read_one_response(instance, buffer, buffer_length, result);
default:
break;
case PROTOCOL_BINARY_RESPONSE_EINVAL:
case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
default:
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
break;
}
}
return rc;
}
-static memcached_return_t _read_one_response(memcached_server_write_instance_st ptr,
+static memcached_return_t _read_one_response(memcached_server_write_instance_st instance,
char *buffer, const size_t buffer_length,
memcached_result_st *result)
{
- memcached_server_response_decrement(ptr);
+ memcached_server_response_decrement(instance);
if (result == NULL)
{
- memcached_st *root= (memcached_st *)ptr->root;
+ memcached_st *root= (memcached_st *)instance->root;
result = &root->result;
}
memcached_return_t rc;
- if (memcached_is_binary(ptr->root))
+ if (memcached_is_binary(instance->root))
{
- rc= binary_read_one_response(ptr, buffer, buffer_length, result);
+ rc= binary_read_one_response(instance, buffer, buffer_length, result);
}
else
{
- rc= textual_read_one_response(ptr, buffer, buffer_length, result);
+ rc= textual_read_one_response(instance, buffer, buffer_length, result);
assert(rc != MEMCACHED_PROTOCOL_ERROR);
}
if (memcached_fatal(rc))
{
- memcached_io_reset(ptr);
+ memcached_io_reset(instance);
}
return rc;
}
-memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st instance,
memcached_result_st *result)
{
char buffer[SMALL_STRING_LEN];
- if (memcached_is_udp(ptr->root))
+ if (memcached_is_udp(instance->root))
{
- return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
}
- return _read_one_response(ptr, buffer, sizeof(buffer), result);
+ return _read_one_response(instance, buffer, sizeof(buffer), result);
}
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_response(memcached_server_write_instance_st instance,
memcached_result_st *result)
{
char buffer[1024];
- return memcached_response(ptr, buffer, sizeof(buffer), result);
+ return memcached_response(instance, buffer, sizeof(buffer), result);
}
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_response(memcached_server_write_instance_st instance,
char *buffer, size_t buffer_length,
memcached_result_st *result)
{
- if (memcached_is_udp(ptr->root))
+ if (memcached_is_udp(instance->root))
{
- return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
}
/* We may have old commands in the buffer not set, first purge */
- if ((ptr->root->flags.no_block) and (memcached_is_processing_input(ptr->root) == false))
+ if ((instance->root->flags.no_block) and (memcached_is_processing_input(instance->root) == false))
{
- (void)memcached_io_write(ptr);
+ (void)memcached_io_write(instance);
}
/*
* returned the last one. Purge all pending messages to ensure backwards
* compatibility.
*/
- if (memcached_is_binary(ptr->root) == false and memcached_server_response_count(ptr) > 1)
+ if (memcached_is_binary(instance->root) == false and memcached_server_response_count(instance) > 1)
{
memcached_result_st junked_result;
- memcached_result_st *junked_result_ptr= memcached_result_create(ptr->root, &junked_result);
+ memcached_result_st *junked_result_ptr= memcached_result_create(instance->root, &junked_result);
assert(junked_result_ptr);
- while (memcached_server_response_count(ptr) > 1)
+ while (memcached_server_response_count(instance) > 1)
{
- memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr);
+ memcached_return_t rc= _read_one_response(instance, buffer, buffer_length, junked_result_ptr);
// @TODO should we return an error on another but a bad read case?
if (memcached_fatal(rc))
memcached_result_free(junked_result_ptr);
}
- return _read_one_response(ptr, buffer, buffer_length, result);
+ return _read_one_response(instance, buffer, buffer_length, result);
}