Merge in all updates.
[awesomized/libmemcached] / libmemcached / util / pool.c
index 012d550f245f67f69112d4b4d42a6afd27684940..fd3f6ffea2c64f76c7db46c8efe9ea26703227d0 100644 (file)
@@ -1,3 +1,14 @@
+/* LibMemcached
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: connects to a host, and makes sure it is alive.
+ *
+ */
+
 /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #include "libmemcached/common.h"
 #include "libmemcached/memcached_util.h"
@@ -14,6 +25,7 @@ struct memcached_pool_st
   int firstfree;
   uint32_t size;
   uint32_t current_size;
+  bool _owns_master;
   char *version;
 };
 
@@ -57,31 +69,39 @@ static int grow_pool(memcached_pool_st* pool)
   pool->mmc[++pool->firstfree] = obj;
   pool->current_size++;
 
-  return 0;
+  return EXIT_SUCCESS;
 }
 
-memcached_pool_st *memcached_pool_create(memcached_st* mmc,
-                                         uint32_t initial, uint32_t max)
+static inline memcached_pool_st *_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max)
 {
-  memcached_pool_st* ret = NULL;
-  memcached_pool_st object = { .mutex = PTHREAD_MUTEX_INITIALIZER,
-    .cond = PTHREAD_COND_INITIALIZER,
-    .master = mmc,
-    .mmc = calloc(max, sizeof(memcached_st*)),
-    .firstfree = -1,
-    .size = max,
-    .current_size = 0 };
+  memcached_pool_st* ret= NULL;
+
+  if (! initial || ! max || initial > max)
+  {
+    errno= EINVAL;
+    return NULL;
+  }
+
+  memcached_pool_st object= { .mutex = PTHREAD_MUTEX_INITIALIZER,
+    .cond= PTHREAD_COND_INITIALIZER,
+    .master= mmc,
+    .mmc= calloc(max, sizeof(memcached_st*)),
+    .firstfree= -1,
+    .size= max,
+    .current_size= 0,
+    ._owns_master= false};
 
   if (object.mmc != NULL)
   {
-    ret= calloc(1, sizeof(*ret));
+    ret= (memcached_pool_st*)calloc(1, sizeof(memcached_pool_st));
     if (ret == NULL)
     {
       free(object.mmc);
+      errno= ENOMEM; // Set this for the failed calloc
       return NULL;
     }
 
-    *ret = object;
+    *ret= object;
 
     /*
       Try to create the initial size of the pool. An allocation failure at
@@ -97,9 +117,39 @@ memcached_pool_st *memcached_pool_create(memcached_st* mmc,
   return ret;
 }
 
+memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max)
+{
+  return _pool_create(mmc, initial, max);
+}
+
+memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
+{
+  memcached_pool_st *self;
+  memcached_st *memc= memcached_create_with_options(option_string, option_string_length);
+
+  if (! memc)
+    return NULL;
+
+  self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
+  if (! self)
+  {
+    memcached_free(memc);
+    errno= ENOMEM;
+    return NULL;
+  }
+  errno= 0;
+
+  self->_owns_master= true;
+
+  return self;
+}
+
 memcached_st*  memcached_pool_destroy(memcached_pool_st* pool)
 {
-  memcached_st *ret = pool->master;
+  if (! pool)
+    return NULL;
+
+  memcached_st *ret= pool->master;
 
   for (int xx= 0; xx <= pool->firstfree; ++xx)
   {
@@ -111,6 +161,11 @@ memcached_st*  memcached_pool_destroy(memcached_pool_st* pool)
   pthread_mutex_destroy(&pool->mutex);
   pthread_cond_destroy(&pool->cond);
   free(pool->mmc);
+  if (pool->_owns_master)
+  {
+    memcached_free(pool->master);
+    ret= NULL;
+  }
   free(pool);
 
   return ret;
@@ -120,14 +175,24 @@ memcached_st* memcached_pool_pop(memcached_pool_st* pool,
                                  bool block,
                                  memcached_return_t *rc)
 {
+  if (! pool || ! rc)
+  {
+    errno= EINVAL;
+    return NULL;
+  }
+
   memcached_st *ret= NULL;
   if ((*rc= mutex_enter(&pool->mutex)) != MEMCACHED_SUCCESS)
+  {
     return NULL;
+  }
 
   do
   {
     if (pool->firstfree > -1)
+    {
       ret= pool->mmc[pool->firstfree--];
+    }
     else if (pool->current_size == pool->size)
     {
       if (!block)
@@ -138,9 +203,9 @@ memcached_st* memcached_pool_pop(memcached_pool_st* pool,
 
       if (pthread_cond_wait(&pool->cond, &pool->mutex) == -1)
       {
-        int err = errno;
+        int err= errno;
         mutex_exit(&pool->mutex);
-        errno = err;
+        errno= err;
         *rc= MEMCACHED_ERRNO;
         return NULL;
       }
@@ -161,6 +226,9 @@ memcached_st* memcached_pool_pop(memcached_pool_st* pool,
 memcached_return_t memcached_pool_push(memcached_pool_st* pool,
                                        memcached_st *mmc)
 {
+  if (! pool)
+    return MEMCACHED_INVALID_ARGUMENTS;
+
   memcached_return_t rc= mutex_enter(&pool->mutex);
 
   if (rc != MEMCACHED_SUCCESS)
@@ -198,6 +266,8 @@ memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
                                                memcached_behavior_t flag,
                                                uint64_t data)
 {
+  if (! pool)
+    return MEMCACHED_INVALID_ARGUMENTS;
 
   memcached_return_t rc= mutex_enter(&pool->mutex);
   if (rc != MEMCACHED_SUCCESS)
@@ -218,11 +288,14 @@ memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
   {
     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
@@ -244,8 +317,10 @@ memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
                                                memcached_behavior_t flag,
                                                uint64_t *value)
 {
-  memcached_return_t rc= mutex_enter(&pool->mutex);
+  if (! pool)
+    return MEMCACHED_INVALID_ARGUMENTS;
 
+  memcached_return_t rc= mutex_enter(&pool->mutex);
   if (rc != MEMCACHED_SUCCESS)
   {
     return rc;