memcached_clone.3\\r
memcached_create.3\\r
memcached_decrement.3\\r
+ memcached_decrement_with_initial.3\\r
memcached_delete.3\\r
memcached_delete_by_key.3\\r
memcached_fetch.3\\r
memcached_get.3\\r
memcached_get_by_key.3\\r
memcached_increment.3\\r
+ memcached_increment_with_initial.3\\r
memcached_mget.3\\r
memcached_mget_by_key.3\\r
memcached_prepend.3\\r
memcached_increment.3:\r
@POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_increment.3\r
\r
+memcached_increment_with_initial.3:\r
+ @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_increment_with_initial.3\r
+\r
memcached_decrement.3:\r
@POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_decrement.3\r
\r
+memcached_decrement_with_initial.3:\r
+ @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_decrement_with_initial.3\r
+\r
memcached_flush.3: memcached_flush.pod\r
@POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_flush.pod > memcached_flush.3\r
\r
=head1 NAME
-memcached_increment, memcached_decrement
+memcached_increment, memcached_decrement,
+memcached_increment_with_initial, memcached_decrement_with_initial
=head1 LIBRARY
unsigned int offset,
uint64_t *value);
+ memcached_return
+ memcached_increment_with_initial (memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
+ memcached_return
+ memcached_decrement_with_initial (memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
=head1 DESCRIPTION
memcached(1) servers have the ability to increment and decrement keys
the offset passed to it. The value is then returned via the unsigned int
value pointer you pass to it.
+memcached_increment_with_initial() takes a key and keylength and increments
+the value by the offset passed to it. If the object specified by key does
+not exist, one of two things may happen: If the expiration value is
+MEMCACHED_EXPIRATION_NOT_ADD, the operation will fail. For all other
+expiration values, the operation will succeed by seeding the value for that
+key with a initial value to expire with the provided expiration time. The
+flags will be set to zero.The value is then returned via the unsigned int
+value pointer you pass to it.
+
+memcached_decrement_with_initial() takes a key and keylength and decrements
+the value by the offset passed to it. If the object specified by key does
+not exist, one of two things may happen: If the expiration value is
+MEMCACHED_EXPIRATION_NOT_ADD, the operation will fail. For all other
+expiration values, the operation will succeed by seeding the value for that
+key with a initial value to expire with the provided expiration time. The
+flags will be set to zero.The value is then returned via the unsigned int
+value pointer you pass to it.
+
=head1 RETURN
A value of type C<memcached_return> is returned.
#define LIBMEMCACHED_MEMCACHED_DECREMENT_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_DECREMENT_START()
#define LIBMEMCACHED_MEMCACHED_DECREMENT_START_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END()
+#define LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START()
+#define LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_DELETE_END()
#define LIBMEMCACHED_MEMCACHED_DELETE_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_DELETE_START()
#define LIBMEMCACHED_MEMCACHED_INCREMENT_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_INCREMENT_START()
#define LIBMEMCACHED_MEMCACHED_INCREMENT_START_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END()
+#define LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START()
+#define LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_MGET_END()
#define LIBMEMCACHED_MEMCACHED_MGET_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_MGET_START()
const char *key, size_t key_length,
uint32_t offset,
uint64_t *value);
+memcached_return memcached_increment_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+memcached_return memcached_decrement_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
void memcached_stat_free(memcached_st *, memcached_stat_st *);
memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return *error);
memcached_return memcached_stat_servername(memcached_stat_st *stat, char *args,
static memcached_return binary_incr_decr(memcached_st *ptr, uint8_t cmd,
const char *key, size_t key_length,
- uint32_t offset, uint64_t *value)
+ uint64_t offset, uint64_t initial,
+ time_t expiration,
+ uint64_t *value)
{
unsigned int server_key;
bool no_reply= (ptr->flags & MEM_NOREPLY);
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
request.message.header.request.bodylen= htonl(key_length + request.message.header.request.extlen);
request.message.body.delta= htonll(offset);
-
- /* TODO: The binary protocol allows you to specify initial and expiry time */
+ request.message.body.initial= htonll(initial);
+ request.message.body.expiration= htonl(expiration);
+
if ((memcached_do(&ptr->hosts[server_key], request.bytes,
sizeof(request.bytes), 0)!=MEMCACHED_SUCCESS) ||
(memcached_io_write(&ptr->hosts[server_key], key, key_length, 1) == -1))
LIBMEMCACHED_MEMCACHED_INCREMENT_START();
if (ptr->flags & MEM_BINARY_PROTOCOL)
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT, key,
- key_length, offset, value);
+ rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT, key, key_length,
+ (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ value);
else
rc= memcached_auto(ptr, "incr", key, key_length, offset, value);
LIBMEMCACHED_MEMCACHED_DECREMENT_START();
if (ptr->flags & MEM_BINARY_PROTOCOL)
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT, key,
- key_length, offset, value);
+ rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT, key, key_length,
+ (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ value);
else
rc= memcached_auto(ptr, "decr", key, key_length, offset, value);
return rc;
}
+
+memcached_return memcached_increment_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value)
+{
+ memcached_return rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL);
+ unlikely (rc != MEMCACHED_SUCCESS)
+ return rc;
+
+ LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
+ if (ptr->flags & MEM_BINARY_PROTOCOL)
+ rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT, key,
+ key_length, offset, initial, expiration, value);
+ else
+ rc= MEMCACHED_PROTOCOL_ERROR;
+
+ LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
+
+ return rc;
+}
+
+memcached_return memcached_decrement_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value)
+{
+ memcached_return rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL);
+ unlikely (rc != MEMCACHED_SUCCESS)
+ return rc;
+
+ LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START();
+ if (ptr->flags & MEM_BINARY_PROTOCOL)
+ rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT, key,
+ key_length, offset, initial, expiration, value);
+ else
+ rc= MEMCACHED_PROTOCOL_ERROR;
+
+ LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END();
+
+ return rc;
+}
#define MEMCACHED_DEFAULT_TIMEOUT 1000
#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
+#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
typedef enum {
MEMCACHED_SUCCESS,
return 0;
}
+static test_return increment_with_initial_test(memcached_st *memc)
+{
+ if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
+ {
+ uint64_t new_number;
+ memcached_return rc;
+ char *key= "number";
+ uint64_t initial= 0;
+
+ rc= memcached_increment_with_initial(memc, key, strlen(key),
+ 1, initial, 0, &new_number);
+ assert(rc == MEMCACHED_SUCCESS);
+ assert(new_number == initial);
+
+ rc= memcached_increment_with_initial(memc, key, strlen(key),
+ 1, initial, 0, &new_number);
+ assert(rc == MEMCACHED_SUCCESS);
+ assert(new_number == (initial + 1));
+ }
+ return 0;
+}
+
static test_return decrement_test(memcached_st *memc)
{
uint64_t new_number;
return 0;
}
+static test_return decrement_with_initial_test(memcached_st *memc)
+{
+ if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
+ {
+ uint64_t new_number;
+ memcached_return rc;
+ char *key= "number";
+ uint64_t initial= 3;
+
+ rc= memcached_decrement_with_initial(memc, key, strlen(key),
+ 1, initial, 0, &new_number);
+ assert(rc == MEMCACHED_SUCCESS);
+ assert(new_number == initial);
+
+ rc= memcached_decrement_with_initial(memc, key, strlen(key),
+ 1, initial, 0, &new_number);
+ assert(rc == MEMCACHED_SUCCESS);
+ assert(new_number == (initial - 1));
+ }
+ return 0;
+}
+
static test_return quit_test(memcached_st *memc)
{
memcached_return rc;
{"partial mget", 0, get_test5 },
{"stats_servername", 0, stats_servername_test },
{"increment", 0, increment_test },
+ {"increment_with_initial", 1, increment_with_initial_test },
{"decrement", 0, decrement_test },
+ {"decrement_with_initial", 1, decrement_with_initial_test },
{"quit", 0, quit_test },
{"mget", 1, mget_test },
{"mget_result", 1, mget_result_test },