From cfcf61110135a3256ab54d6ced50ce5e68580121 Mon Sep 17 00:00:00 2001 From: Tasuku SUENAGA Date: Wed, 29 Apr 2009 01:48:18 +0200 Subject: [PATCH] Add support for incr/decr with initial value --- docs/Makefile.am | 8 ++++ docs/memcached_auto.pod | 39 ++++++++++++++++- libmemcached/libmemcached_probes.h | 8 ++++ libmemcached/memcached.h | 14 +++++++ libmemcached/memcached_auto.c | 67 ++++++++++++++++++++++++++---- libmemcached/memcached_constants.h | 1 + tests/function.c | 46 ++++++++++++++++++++ 7 files changed, 175 insertions(+), 8 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 03278abf..1d48b1c8 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -51,6 +51,7 @@ man_MANS = libmemcached.3\ memcached_clone.3\ memcached_create.3\ memcached_decrement.3\ + memcached_decrement_with_initial.3\ memcached_delete.3\ memcached_delete_by_key.3\ memcached_fetch.3\ @@ -60,6 +61,7 @@ man_MANS = libmemcached.3\ memcached_get.3\ memcached_get_by_key.3\ memcached_increment.3\ + memcached_increment_with_initial.3\ memcached_mget.3\ memcached_mget_by_key.3\ memcached_prepend.3\ @@ -148,9 +150,15 @@ memcached_delete_by_key.3: memcached_delete.pod memcached_increment.3: @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_increment.3 +memcached_increment_with_initial.3: + @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_increment_with_initial.3 + memcached_decrement.3: @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_decrement.3 +memcached_decrement_with_initial.3: + @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_decrement_with_initial.3 + memcached_flush.3: memcached_flush.pod @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_flush.pod > memcached_flush.3 diff --git a/docs/memcached_auto.pod b/docs/memcached_auto.pod index df0a8b58..177bb4c8 100755 --- a/docs/memcached_auto.pod +++ b/docs/memcached_auto.pod @@ -1,6 +1,7 @@ =head1 NAME -memcached_increment, memcached_decrement +memcached_increment, memcached_decrement, +memcached_increment_with_initial, memcached_decrement_with_initial =head1 LIBRARY @@ -22,6 +23,24 @@ C Client Library for memcached (libmemcached, -lmemcached) 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 @@ -36,6 +55,24 @@ memcached_decrement() takes a key and keylength and decrements the value by 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 is returned. diff --git a/libmemcached/libmemcached_probes.h b/libmemcached/libmemcached_probes.h index 7db979ce..b441a047 100644 --- a/libmemcached/libmemcached_probes.h +++ b/libmemcached/libmemcached_probes.h @@ -32,6 +32,10 @@ #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() @@ -48,6 +52,10 @@ #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() diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 91c73d7e..62fa65c0 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -137,6 +137,20 @@ memcached_return memcached_decrement(memcached_st *ptr, 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, diff --git a/libmemcached/memcached_auto.c b/libmemcached/memcached_auto.c index ade0b59b..afb1df3a 100644 --- a/libmemcached/memcached_auto.c +++ b/libmemcached/memcached_auto.c @@ -62,7 +62,9 @@ static memcached_return memcached_auto(memcached_st *ptr, 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); @@ -88,8 +90,9 @@ static memcached_return binary_incr_decr(memcached_st *ptr, uint8_t cmd, 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)) @@ -114,8 +117,9 @@ memcached_return memcached_increment(memcached_st *ptr, 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); @@ -135,8 +139,9 @@ memcached_return memcached_decrement(memcached_st *ptr, 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); @@ -144,3 +149,51 @@ memcached_return memcached_decrement(memcached_st *ptr, 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; +} diff --git a/libmemcached/memcached_constants.h b/libmemcached/memcached_constants.h index 1af6aa4a..03c61871 100644 --- a/libmemcached/memcached_constants.h +++ b/libmemcached/memcached_constants.h @@ -26,6 +26,7 @@ extern "C" { #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, diff --git a/tests/function.c b/tests/function.c index 4473000d..d4239a80 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1043,6 +1043,28 @@ static test_return increment_test(memcached_st *memc) 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; @@ -1068,6 +1090,28 @@ static test_return decrement_test(memcached_st *memc) 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; @@ -3629,7 +3673,9 @@ test_st tests[] ={ {"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 }, -- 2.30.2