RFE: It should be possible to set behavior flags on a pool
authorTrond Norbye <trond.norbye@sun.com>
Sat, 26 Sep 2009 07:47:01 +0000 (09:47 +0200)
committerTrond Norbye <trond.norbye@sun.com>
Sat, 26 Sep 2009 07:47:01 +0000 (09:47 +0200)
docs/Makefile.am
docs/memcached_pool.pod
libmemcached/memcached_pool.h
libmemcachedutil/memcached_pool.c
tests/function.c

index 7972cc98795b81f4b79c2bc1220c0dd0ebc77db2..772b03443025d8d17650ab7ea7ef297d83407baa 100644 (file)
@@ -107,6 +107,8 @@ man_MANS = libmemcached.3\
 
 if BUILD_LIBMEMCACHEDUTIL
 man_MANS+= libmemcachedutil.3 \
+       memcached_pool_behavior_set.3 \
+       memcached_pool_behavior_get.3 \
        memcached_pool_create.3 \
        memcached_pool_destroy.3 \
        memcached_pool_push.3 \
@@ -327,6 +329,12 @@ memcached_get_user_data.3: memcached_user_data.pod
 memcached_set_user_data.3: memcached_user_data.pod
        ${POD2MAN} -c "libmemcached" -r "" -s 3 ${top_srcdir}/docs/memcached_user_data.pod > memcached_set_user_data.3
 
+memcached_pool_behavior_get.3: memcached_pool.pod
+       ${POD2MAN} -c "libmemcachedutil" -r "" -s 3 ${top_srcdir}/docs/memcached_pool.pod > memcached_pool_behavior_get.3
+
+memcached_pool_behavior_set.3: memcached_pool.pod
+       ${POD2MAN} -c "libmemcachedutil" -r "" -s 3 ${top_srcdir}/docs/memcached_pool.pod > memcached_pool_behavior_set.3
+
 memcached_pool_create.3: memcached_pool.pod
        ${POD2MAN} -c "libmemcachedutil" -r "" -s 3 ${top_srcdir}/docs/memcached_pool.pod > memcached_pool_create.3
 
index 2b464ac226dd8352eae83a2984638728fe2a1a8f..ac85d3b9fdfbd9d30e922aaf082b5fc05f2552b4 100644 (file)
@@ -18,6 +18,12 @@ C Client Library for memcached (libmemcachedutil, -lmemcachedutil)
 
   memcached_st *memcached_create (memcached_st *ptr);
 
+  memcached_return memcached_pool_behavior_set(memcached_pool_st *pool, 
+                                               memcached_behavior flag, 
+                                               uint64_t data)
+  memcached_return memcached_pool_behavior_get(memcached_pool_st *pool, 
+                                               memcached_behavior flag,
+                                               uint64_t *value)
 
 =head1 DESCRIPTION
 
@@ -46,6 +52,10 @@ to exceed the maximum size.
 
 memcached_pool_push() is used to return a connection structure back to the pool.
 
+memcached_pool_behavior_set() and memcached_pool_behagior_get() is
+used to get/set behavior flags on all connections in the pool.
+
+
 =head1 RETURN
 
 memcached_pool_create() returns a pointer to the newly created
@@ -61,6 +71,9 @@ from the pool (or NULL if an allocation cannot be satisfied).
 
 memcached_pool_push() returns MEMCACHED_SUCCESS upon success.
 
+memcached_pool_behavior_get() and memcached_pool_behavior_get()
+returns MEMCACHED_SUCCESS upon success.
+
 =head1 HOME
 
 To find out more information please check:
@@ -72,6 +85,6 @@ Trond Norbye, E<lt>trond.norbye@sun.comE<gt>
 
 =head1 SEE ALSO
 
-memcached(1) libmemcached(3) memcached_create(3) memcached_free(3) libmemcachedutil(3)
+memcached(1) libmemcached(3) memcached_create(3) memcached_free(3) libmemcachedutil(3) memcached_behavior_get(3) memcached_behavior_set(3)
 
 =cut
index 7efe65e9e9674835c0c77db08bbd26bd082146a0..03fc0e3a78d9b82fadcd1b18e74feb7d600a4b49 100644 (file)
@@ -31,6 +31,11 @@ LIBMEMCACHED_API
 memcached_return memcached_pool_push(memcached_pool_st* pool, 
                                      memcached_st* mmc);
 
+LIBMEMCACHED_API
+memcached_return memcached_pool_behavior_set(memcached_pool_st *ptr, memcached_behavior flag, uint64_t data);
+LIBMEMCACHED_API
+memcached_return memcached_pool_behavior_get(memcached_pool_st *ptr, memcached_behavior flag, uint64_t *value);
+
 #ifdef __cplusplus
 }
 #endif
index 708b7ce2a793ffa930336eb7102f119d99846cbb..afc2fee3c26304cd24302d84074ee4009bc57f2e 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #include "libmemcached/common.h"
 #include "libmemcached/memcached_pool.h"
 
@@ -13,6 +14,7 @@ struct memcached_pool_st
   int firstfree;
   uint32_t size;
   uint32_t current_size;
+  char* version;
 };
 
 static memcached_return mutex_enter(pthread_mutex_t *mutex) 
@@ -158,6 +160,18 @@ memcached_return memcached_pool_push(memcached_pool_st* pool,
   if (rc != MEMCACHED_SUCCESS)
     return rc;
 
+  char* version = memcached_get_user_data(mmc);
+  /* Someone updated the behavior on the object.. */
+  if (version != pool->version) 
+  {
+    memcached_free(mmc);
+    memset(mmc, 0, sizeof(*mmc));
+    if (memcached_clone(mmc, pool->master) == NULL)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+    }
+  }
+
   pool->mmc[++pool->firstfree]= mmc;
 
   if (pool->firstfree == 0 && pool->current_size == pool->size) 
@@ -166,5 +180,67 @@ memcached_return memcached_pool_push(memcached_pool_st* pool,
     pthread_cond_broadcast(&pool->cond);
   }
 
+  memcached_return rval= mutex_exit(&pool->mutex);
+  if (rc == MEMCACHED_SOME_ERRORS)
+    return rc;
+
+  return rval;
+}
+
+
+memcached_return memcached_pool_behavior_set(memcached_pool_st *pool, 
+                                             memcached_behavior flag, 
+                                             uint64_t data)
+{
+
+  memcached_return rc= mutex_enter(&pool->mutex);
+  if (rc != MEMCACHED_SUCCESS)
+     return rc;
+
+  /* update the master */
+  rc= memcached_behavior_set(pool->master, flag, data);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    mutex_exit(&pool->mutex);
+    return rc;
+  }
+
+  ++pool->version;
+  memcached_set_user_data(pool->master, pool->version);
+  /* update the clones */
+  for (int xx= 0; xx <= pool->firstfree; ++xx) 
+  {
+    rc= memcached_behavior_set(pool->mmc[xx], flag, data);
+    if (rc == MEMCACHED_SUCCESS)
+      memcached_set_user_data(pool->mmc[xx], pool->version);
+    else
+    {
+      memcached_free(pool->mmc[xx]);
+      memset(pool->mmc[xx], 0, sizeof(*pool->mmc[xx]));
+      if (memcached_clone(pool->mmc[xx], pool->master) == NULL)
+      {
+        /* I'm not sure what to do in this case.. this would happen
+           if we fail to push the server list inside the client..
+           I should add a testcase for this, but I believe the following
+           would work, except that you would add a hole in the pool list..
+           in theory you could end up with an empty pool....
+        */
+        free(pool->mmc[xx]);
+        pool->mmc[xx]= NULL;
+      }
+    }
+  }
+
+  return mutex_exit(&pool->mutex);
+}
+
+memcached_return memcached_pool_behavior_get(memcached_pool_st *pool, 
+                                             memcached_behavior flag,
+                                             uint64_t *value)
+{
+  memcached_return rc= mutex_enter(&pool->mutex);
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+  *value= memcached_behavior_get(pool->master, flag);
   return mutex_exit(&pool->mutex);
 }
index 418077717c8856ae51e397b0b9fdc54ab8f55bcc..1dce9ff89f90fddce49f9f26da2e41b34bec9418 100644 (file)
@@ -3664,6 +3664,29 @@ static test_return connection_pool_test(memcached_st *memc)
   for (int x= 0; x < 10; ++x)
     assert(memcached_pool_push(pool, mmc[x]) == MEMCACHED_SUCCESS);
 
+
+  /* verify that I can set behaviors on the pool when I don't have all 
+   * of the connections in the pool. It should however be enabled
+   * when I push the item into the pool
+   */
+  mmc[0]= memcached_pool_pop(pool, false, &rc);
+  assert(mmc[0] != NULL);
+
+  rc= memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK, 9999);
+  assert(rc == MEMCACHED_SUCCESS);
+
+  mmc[1]= memcached_pool_pop(pool, false, &rc);
+  assert(mmc[1] != NULL);
+
+  assert(memcached_behavior_get(mmc[1], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK) == 9999);
+  assert(memcached_pool_push(pool, mmc[1]) == MEMCACHED_SUCCESS);
+  assert(memcached_pool_push(pool, mmc[0]) == MEMCACHED_SUCCESS);
+
+  mmc[0]= memcached_pool_pop(pool, false, &rc);
+  assert(memcached_behavior_get(mmc[0], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK) == 9999);
+  assert(memcached_pool_push(pool, mmc[0]) == MEMCACHED_SUCCESS);
+
+
   assert(memcached_pool_destroy(pool) == memc);
   return TEST_SUCCESS;
 }