#include <libmemcached/common.h>
-static memcached_return_t text_incr_decr(memcached_st *ptr,
- const char *verb,
- const char *group_key, size_t group_key_length,
+static memcached_return_t text_incr_decr(memcached_server_write_instance_st instance,
+ const bool is_incr,
const char *key, size_t key_length,
- uint64_t offset,
- uint64_t *value)
+ const uint64_t offset,
+ const bool reply,
+ uint64_t& numeric_value)
{
- memcached_return_t rc;
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- uint32_t server_key;
- memcached_server_write_instance_st instance;
- bool no_reply= ptr->flags.no_reply;
-
- if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
- return MEMCACHED_BAD_KEY_PROVIDED;
-
- server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
- instance= memcached_server_instance_fetch(ptr, server_key);
-
- int send_length;
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "%s %.*s%.*s %" PRIu64 "%s\r\n", verb,
- memcached_print_array(ptr->prefix_key),
- (int)key_length, key,
- offset, no_reply ? " noreply" : "");
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
- return MEMCACHED_WRITE_FAILURE;
-
- rc= memcached_do(instance, buffer, (size_t)send_length, true);
- if (no_reply || rc != MEMCACHED_SUCCESS)
- return rc;
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
- /*
- So why recheck responce? Because the protocol is brain dead :)
- The number returned might end up equaling one of the string
- values. Less chance of a mistake with strncmp() so we will
- use it. We still called memcached_response() though since it
- worked its magic for non-blocking IO.
- */
- if (! strncmp(buffer, "ERROR\r\n", 7))
+ int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
+ if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
{
- *value= 0;
- rc= MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
- else if (! strncmp(buffer, "CLIENT_ERROR\r\n", 14))
+
+ libmemcached_io_vector_st vector[]=
{
- *value= 0;
- rc= MEMCACHED_PROTOCOL_ERROR;
+ { NULL, 0 },
+ { memcached_literal_param("incr ") },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length },
+ { buffer, send_length },
+ { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+ { memcached_literal_param("\r\n") }
+ };
+
+ if (is_incr == false)
+ {
+ vector[1].buffer= "decr ";
}
- else if (!strncmp(buffer, "NOT_FOUND\r\n", 11))
+
+ memcached_return_t rc= memcached_vdo(instance, vector, 7, true);
+
+ if (reply == false)
{
- *value= 0;
- rc= MEMCACHED_NOTFOUND;
+ return MEMCACHED_SUCCESS;
}
- else
+
+ if (memcached_failed(rc))
{
- *value= strtoull(buffer, (char **)NULL, 10);
- rc= MEMCACHED_SUCCESS;
+ numeric_value= UINT64_MAX;
+ return rc;
}
- return rc;
+ rc= memcached_response(instance, buffer, sizeof(buffer), NULL, numeric_value);
+
+ return memcached_set_error(*instance, rc, MEMCACHED_AT);
}
-static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- uint64_t offset, uint64_t initial,
- uint32_t expiration,
+static memcached_return_t binary_incr_decr(memcached_server_write_instance_st instance,
+ protocol_binary_command cmd,
+ const char *key, const size_t key_length,
+ const uint64_t offset,
+ const uint64_t initial,
+ const uint32_t expiration,
+ const bool reply,
uint64_t *value)
{
- uint32_t server_key;
- memcached_server_write_instance_st instance;
- bool no_reply= ptr->flags.no_reply;
-
- if (memcached_server_count(ptr) == 0)
- return memcached_set_error(ptr, MEMCACHED_NO_SERVERS, NULL);
-
- server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
- instance= memcached_server_instance_fetch(ptr, server_key);
-
- if (no_reply)
+ if (reply == false)
{
if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
+ {
cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
+ }
+
if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
+ {
cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
+ }
}
protocol_binary_request_incr request= {}; // = {.bytes= {0}};
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
request.message.header.request.opcode= cmd;
- request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
+ request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
request.message.header.request.extlen= 20;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->prefix_key) +request.message.header.request.extlen));
- request.message.body.delta= htonll(offset);
- request.message.body.initial= htonll(initial);
+ request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
+ request.message.body.delta= memcached_htonll(offset);
+ request.message.body.initial= memcached_htonll(initial);
request.message.body.expiration= htonl((uint32_t) expiration);
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { memcached_array_size(ptr->prefix_key), ptr->prefix_key },
- { key_length, key }
+ { NULL, 0 },
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length }
};
memcached_return_t rc;
- if ((rc= memcached_vdo(instance, vector, 3, true)) != MEMCACHED_SUCCESS)
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
{
memcached_io_reset(instance);
- return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
+ return MEMCACHED_WRITE_FAILURE;
}
- if (no_reply)
+ if (reply == false)
+ {
return MEMCACHED_SUCCESS;
+ }
return memcached_response(instance, (char*)value, sizeof(*value), NULL);
}
uint32_t offset,
uint64_t *value)
{
- uint64_t local_value;
- if (! value)
- value= &local_value;
-
return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
}
uint32_t offset,
uint64_t *value)
{
- uint64_t local_value;
- if (! value)
- value= &local_value;
-
return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
}
{
memcached_return_t rc;
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
- group_key, group_key_length, key, key_length,
- (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+ key, key_length,
+ uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ reply,
value);
}
else
{
- rc= text_incr_decr(ptr, "incr", group_key, group_key_length, key, key_length, offset, value);
+ rc= text_incr_decr(instance, true, key, key_length, offset, reply, *value);
}
LIBMEMCACHED_MEMCACHED_INCREMENT_END();
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_DECREMENT_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
- group_key, group_key_length, key, key_length,
- (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+ key, key_length,
+ offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ reply,
value);
}
else
{
- rc= text_incr_decr(ptr, "decr", group_key, group_key_length, key, key_length, offset, value);
+ rc= text_incr_decr(instance, false, key, key_length, offset, reply, *value);
}
LIBMEMCACHED_MEMCACHED_DECREMENT_END();
time_t expiration,
uint64_t *value)
{
- uint64_t local_value;
- if (! value)
- value= &local_value;
-
return memcached_increment_with_initial_by_key(ptr, key, key_length,
key, key_length,
offset, initial, expiration, value);
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
- if (ptr->flags.binary_protocol)
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
- group_key, group_key_length, key, key_length,
- offset, initial, (uint32_t)expiration,
+ if (memcached_is_binary(ptr))
+ {
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+ key, key_length,
+ offset, initial, uint32_t(expiration),
+ reply,
value);
+ }
else
- rc= MEMCACHED_PROTOCOL_ERROR;
+ {
+ rc= memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
+ }
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
time_t expiration,
uint64_t *value)
{
- uint64_t local_value;
- if (! value)
- value= &local_value;
-
return memcached_decrement_with_initial_by_key(ptr, key, key_length,
key, key_length,
offset, initial, expiration, value);
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
- group_key, group_key_length, key, key_length,
- offset, initial, (uint32_t)expiration,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+ key, key_length,
+ offset, initial, uint32_t(expiration),
+ reply,
value);
}
else
{
- rc= MEMCACHED_PROTOCOL_ERROR;
+ rc= memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("memcached_decrement_with_initial_by_key() is not supported via the ASCII protocol"));
}
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
return rc;
}
-