Add support for incr/decr with initial value
authorTasuku SUENAGA <a@razil.jp>
Tue, 28 Apr 2009 23:48:18 +0000 (01:48 +0200)
committerTasuku SUENAGA <a@razil.jp>
Tue, 28 Apr 2009 23:48:18 +0000 (01:48 +0200)
docs/Makefile.am
docs/memcached_auto.pod
libmemcached/libmemcached_probes.h
libmemcached/memcached.h
libmemcached/memcached_auto.c
libmemcached/memcached_constants.h
tests/function.c

index 03278abfb08ba80671125cc56817ebc5a1da894b..1d48b1c81e1b1a3b28259a3a8af0932e640a6fee 100644 (file)
@@ -51,6 +51,7 @@ man_MANS = libmemcached.3\
        memcached_clone.3\\r
        memcached_create.3\\r
        memcached_decrement.3\\r
        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_delete.3\\r
        memcached_delete_by_key.3\\r
        memcached_fetch.3\\r
@@ -60,6 +61,7 @@ man_MANS = libmemcached.3\
        memcached_get.3\\r
        memcached_get_by_key.3\\r
        memcached_increment.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_mget.3\\r
        memcached_mget_by_key.3\\r
        memcached_prepend.3\\r
@@ -148,9 +150,15 @@ memcached_delete_by_key.3: memcached_delete.pod
 memcached_increment.3:\r
        @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_auto.pod > memcached_increment.3\r
 \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.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
 memcached_flush.3: memcached_flush.pod\r
        @POD2MAN@ -c "libmemcached" -r "" -s 3 memcached_flush.pod > memcached_flush.3\r
 \r
index df0a8b58b4352dc7da9020e96bc2684d95177b40..177bb4c89986558f51b7be7714540ce7ee5b1166 100755 (executable)
@@ -1,6 +1,7 @@
 =head1 NAME
 
 =head1 NAME
 
-memcached_increment, memcached_decrement
+memcached_increment, memcached_decrement,
+memcached_increment_with_initial, memcached_decrement_with_initial
 
 =head1 LIBRARY
 
 
 =head1 LIBRARY
 
@@ -22,6 +23,24 @@ C Client Library for memcached (libmemcached, -lmemcached)
                          unsigned int offset,
                          uint64_t *value);
 
                          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
 =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.
 
 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.
 =head1 RETURN
 
 A value of type C<memcached_return> is returned.
index 7db979ce761dbfb7b6e869920e8830f7b3908e3e..b441a04738000f55fe4d83f81138d1fbc5b07cfd 100644 (file)
 #define        LIBMEMCACHED_MEMCACHED_DECREMENT_END_ENABLED() (0)
 #define        LIBMEMCACHED_MEMCACHED_DECREMENT_START()
 #define        LIBMEMCACHED_MEMCACHED_DECREMENT_START_ENABLED() (0)
 #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_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_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()
 #define        LIBMEMCACHED_MEMCACHED_MGET_END()
 #define        LIBMEMCACHED_MEMCACHED_MGET_END_ENABLED() (0)
 #define        LIBMEMCACHED_MEMCACHED_MGET_START()
index 91c73d7e43c9370b5bef4e1c8709c66d26dd0ac4..62fa65c0af3f6661faf139e8dc00e89a25991a80 100644 (file)
@@ -137,6 +137,20 @@ memcached_return memcached_decrement(memcached_st *ptr,
                                      const char *key, size_t key_length,
                                      uint32_t offset,
                                      uint64_t *value);
                                      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, 
 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, 
index ade0b59b98e6d632ebe6e994361bd1138327dae4..afb1df3a498c6256a4c8dd0e43ea15edcf132a99 100644 (file)
@@ -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,
 
 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);
 {
   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);
   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)) 
   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) 
 
   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);
   
   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) 
 
   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);      
   
   else 
     rc= memcached_auto(ptr, "decr", key, key_length, offset, value);      
   
@@ -144,3 +149,51 @@ memcached_return memcached_decrement(memcached_st *ptr,
 
   return rc;
 }
 
   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;
+}
index 1af6aa4a9595e0a02d417a607b8ec9b14d90a963..03c61871a8dc7cd7a0a57535b619e182add49857 100644 (file)
@@ -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_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,
 
 typedef enum {
   MEMCACHED_SUCCESS,
index 4473000dc2d9e5526442957be6ed2490318fd622..d4239a80c09c43bb54997eef074e2ff0287995a2 100644 (file)
@@ -1043,6 +1043,28 @@ static test_return  increment_test(memcached_st *memc)
   return 0;
 }
 
   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;
 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;
 }
 
   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;
 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 },
   {"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", 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 },
   {"quit", 0, quit_test },
   {"mget", 1, mget_test },
   {"mget_result", 1, mget_result_test },