int main(int argc, char *argv[])
{
- memcached_return_t rc;
- memcached_st *memc;
- memcached_server_st *servers;
-
options_parse(argc, argv);
initialize_sockets();
}
}
- memc= memcached_create(NULL);
+ memcached_st *memc= memcached_create(NULL);
+
+ memcached_server_st *servers= memcached_servers_parse(opt_servers);
+ free(opt_servers);
- servers= memcached_servers_parse(opt_servers);
- rc= memcached_server_push(memc, servers);
+ memcached_return_t rc= memcached_server_push(memc, servers);
memcached_server_list_free(servers);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS)
rc= memcached_stat_execute(memc, stat_args, stat_printer, NULL);
}
- free(opt_servers);
-
memcached_free(memc);
- return rc == MEMCACHED_SUCCESS ? 0: -1;
+ return rc == MEMCACHED_SUCCESS ? EXIT_SUCCESS: EXIT_FAILURE;
}
static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat)
endif
libmemcached_libmemcachedutil_la_SOURCES= \
- libmemcached/util/ping.c \
- libmemcached/util/pool.c \
- libmemcached/util/version.c
+ libmemcached/util/ping.cc \
+ libmemcached/util/pool.cc \
+ libmemcached/util/version.cc
libmemcached_libmemcachedutil_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} ${PTHREAD_CFLAGS}
libmemcached_libmemcachedutil_la_LIBADD= libmemcached/libmemcached.la
libmemcached_libmemcachedutil_la_LDFLAGS= ${AM_LDFLAGS} ${PTHREAD_LIBS} -version-info ${MEMCACHED_UTIL_LIBRARY_VERSION}
self->prefix_key= NULL;
self->configure.initial_pool_size= 1;
self->configure.max_pool_size= 1;
+ self->configure.version= -1;
self->configure.filename= NULL;
return true;
struct {
uint32_t initial_pool_size;
uint32_t max_pool_size;
+ int32_t version; // This is used by pool and others to determine if the memcached_st is out of date.
struct memcached_array_st *filename;
} configure;
struct {
+++ /dev/null
-/* 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.
- *
- */
-
-#include "libmemcached/common.h"
-#include "libmemcached/memcached_util.h"
-
-
-bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
- memcached_return_t rc;
- memcached_st memc, *memc_ptr;
-
- memc_ptr= memcached_create(&memc);
-
- rc= memcached_server_add(memc_ptr, hostname, port);
-
- if (rc == MEMCACHED_SUCCESS)
- {
- rc= memcached_version(memc_ptr);
- }
-
- memcached_free(memc_ptr);
-
- if (ret)
- {
- *ret= rc;
- }
-
- return rc == MEMCACHED_SUCCESS;
-}
--- /dev/null
+/* 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.
+ *
+ */
+
+#include "libmemcached/common.h"
+#include "libmemcached/memcached_util.h"
+
+
+bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+ memcached_return_t rc;
+ memcached_st memc, *memc_ptr;
+
+ memc_ptr= memcached_create(&memc);
+
+ rc= memcached_server_add(memc_ptr, hostname, port);
+
+ if (rc == MEMCACHED_SUCCESS)
+ {
+ rc= memcached_version(memc_ptr);
+ }
+
+ memcached_free(memc_ptr);
+
+ if (ret)
+ {
+ *ret= rc;
+ }
+
+ return rc == MEMCACHED_SUCCESS;
+}
+++ /dev/null
-/* 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"
-
-#include <errno.h>
-#include <pthread.h>
-
-struct memcached_pool_st
-{
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- memcached_st *master;
- memcached_st **mmc;
- int firstfree;
- uint32_t size;
- uint32_t current_size;
- bool _owns_master;
- char *version;
-};
-
-static memcached_return_t mutex_enter(pthread_mutex_t *mutex)
-{
- int ret;
- do
- ret= pthread_mutex_lock(mutex);
- while (ret == -1 && errno == EINTR);
-
- return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t mutex_exit(pthread_mutex_t *mutex)
-{
- int ret;
- do
- ret= pthread_mutex_unlock(mutex);
- while (ret == -1 && errno == EINTR);
-
- return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
-}
-
-/**
- * Grow the connection pool by creating a connection structure and clone the
- * original memcached handle.
- */
-static int grow_pool(memcached_pool_st* pool)
-{
- memcached_st *obj= calloc(1, sizeof(*obj));
-
- if (obj == NULL)
- return -1;
-
- if (memcached_clone(obj, pool->master) == NULL)
- {
- free(obj);
- return -1;
- }
-
- pool->mmc[++pool->firstfree] = obj;
- pool->current_size++;
-
- return EXIT_SUCCESS;
-}
-
-static inline memcached_pool_st *_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max)
-{
- 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= (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;
-
- /*
- Try to create the initial size of the pool. An allocation failure at
- this time is not fatal..
- */
- for (unsigned int ii= 0; ii < initial; ++ii)
- {
- if (grow_pool(ret) == -1)
- break;
- }
- }
-
- 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(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)
-{
- if (! pool)
- return NULL;
-
- memcached_st *ret= pool->master;
-
- for (int xx= 0; xx <= pool->firstfree; ++xx)
- {
- memcached_free(pool->mmc[xx]);
- free(pool->mmc[xx]);
- pool->mmc[xx] = NULL;
- }
-
- 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;
-}
-
-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)
- {
- *rc= mutex_exit(&pool->mutex);
- return NULL;
- }
-
- if (pthread_cond_wait(&pool->cond, &pool->mutex) == -1)
- {
- int err= errno;
- mutex_exit(&pool->mutex);
- errno= err;
- *rc= MEMCACHED_ERRNO;
- return NULL;
- }
- }
- else if (grow_pool(pool) == -1)
- {
- *rc= mutex_exit(&pool->mutex);
- return NULL;
- }
- }
- while (ret == NULL);
-
- *rc= mutex_exit(&pool->mutex);
-
- return ret;
-}
-
-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)
- 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)
- {
- /* we might have people waiting for a connection.. wake them up :-) */
- pthread_cond_broadcast(&pool->cond);
- }
-
- memcached_return_t rval= mutex_exit(&pool->mutex);
- if (rc == MEMCACHED_SOME_ERRORS)
- return rc;
-
- return rval;
-}
-
-
-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)
- 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_t memcached_pool_behavior_get(memcached_pool_st *pool,
- memcached_behavior_t flag,
- uint64_t *value)
-{
- if (! pool)
- return MEMCACHED_INVALID_ARGUMENTS;
-
- memcached_return_t rc= mutex_enter(&pool->mutex);
- if (rc != MEMCACHED_SUCCESS)
- {
- return rc;
- }
-
- *value= memcached_behavior_get(pool->master, flag);
-
- return mutex_exit(&pool->mutex);
-}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+#include <libmemcached/memcached_util.h>
+
+#include <cassert>
+#include <cerrno>
+#include <pthread.h>
+#include <memory>
+
+static bool grow_pool(memcached_pool_st* pool);
+
+struct memcached_pool_st
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ memcached_st *master;
+ memcached_st **server_pool;
+ int firstfree;
+ const uint32_t size;
+ uint32_t current_size;
+ bool _owns_master;
+
+ memcached_pool_st(memcached_st *master_arg, size_t max_arg) :
+ master(master_arg),
+ server_pool(NULL),
+ firstfree(-1),
+ size(max_arg),
+ current_size(0),
+ _owns_master(false)
+ {
+ pthread_mutex_init(&mutex, NULL);
+ pthread_cond_init(&cond, NULL);
+ }
+
+ bool init(uint32_t initial)
+ {
+ server_pool= new (std::nothrow) memcached_st *[size];
+ if (not server_pool)
+ return false;
+
+ /*
+ Try to create the initial size of the pool. An allocation failure at
+ this time is not fatal..
+ */
+ for (unsigned int x= 0; x < initial; ++x)
+ {
+ if (not grow_pool(this))
+ break;
+ }
+
+ return true;
+ }
+
+ ~memcached_pool_st()
+ {
+ for (int x= 0; x <= firstfree; ++x)
+ {
+ memcached_free(server_pool[x]);
+ server_pool[x] = NULL;
+ }
+
+ pthread_mutex_destroy(&mutex);
+ pthread_cond_destroy(&cond);
+ delete [] server_pool;
+ if (_owns_master)
+ {
+ memcached_free(master);
+ }
+ }
+
+ void increment_version()
+ {
+ ++master->configure.version;
+ }
+
+ bool compare_version(const memcached_st *arg) const
+ {
+ return (arg->configure.version == version());
+ }
+
+ int32_t version() const
+ {
+ return master->configure.version;
+ }
+};
+
+static memcached_return_t mutex_enter(pthread_mutex_t *mutex)
+{
+ int ret;
+ do
+ {
+ ret= pthread_mutex_lock(mutex);
+ } while (ret == -1 && errno == EINTR);
+
+ return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t mutex_exit(pthread_mutex_t *mutex)
+{
+ int ret;
+ do
+ {
+ ret= pthread_mutex_unlock(mutex);
+ } while (ret == -1 && errno == EINTR);
+
+ return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
+}
+
+/**
+ * Grow the connection pool by creating a connection structure and clone the
+ * original memcached handle.
+ */
+static bool grow_pool(memcached_pool_st* pool)
+{
+ memcached_st *obj;
+ if (not (obj= memcached_clone(NULL, pool->master)))
+ {
+ return false;
+ }
+
+ pool->server_pool[++pool->firstfree]= obj;
+ pool->current_size++;
+ obj->configure.version= pool->version();
+
+ return true;
+}
+
+static inline memcached_pool_st *_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+ if (! initial || ! max || initial > max)
+ {
+ errno= EINVAL;
+ return NULL;
+ }
+
+ memcached_pool_st *object= new (std::nothrow) memcached_pool_st(master, max);
+ if (not object)
+ {
+ errno= ENOMEM; // Set this for the failed calloc
+ return NULL;
+ }
+
+ /*
+ Try to create the initial size of the pool. An allocation failure at
+ this time is not fatal..
+ */
+ if (not object->init(initial))
+ {
+ delete object;
+ return NULL;
+ }
+
+ return object;
+}
+
+memcached_pool_st *memcached_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+ return _pool_create(master, initial, max);
+}
+
+memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
+{
+ memcached_st *memc= memcached(option_string, option_string_length);
+
+ if (not memc)
+ return NULL;
+
+ memcached_pool_st *self;
+ self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
+ if (not 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)
+{
+ if (not pool)
+ return NULL;
+
+ // Legacy that we return the original structure
+ memcached_st *ret= NULL;
+ if (pool->_owns_master)
+ { }
+ else
+ {
+ ret= pool->master;
+ }
+
+ delete pool;
+
+ return ret;
+}
+
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+ bool block,
+ memcached_return_t *rc)
+{
+ assert(pool);
+ assert(rc);
+ if (not pool || not rc)
+ {
+ errno= EINVAL;
+ return NULL;
+ }
+
+ if ((*rc= mutex_enter(&pool->mutex)) != MEMCACHED_SUCCESS)
+ {
+ return NULL;
+ }
+
+ memcached_st *ret= NULL;
+ do
+ {
+ if (pool->firstfree > -1)
+ {
+ ret= pool->server_pool[pool->firstfree--];
+ }
+ else if (pool->current_size == pool->size)
+ {
+ if (not block)
+ {
+ *rc= mutex_exit(&pool->mutex); // this should be a different error
+ return NULL;
+ }
+
+ if (pthread_cond_wait(&pool->cond, &pool->mutex) == -1)
+ {
+ int err= errno;
+ mutex_exit(&pool->mutex);
+ errno= err;
+ *rc= MEMCACHED_ERRNO;
+ return NULL;
+ }
+ }
+ else if (not grow_pool(pool))
+ {
+ (void)mutex_exit(&pool->mutex);
+ *rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return NULL;
+ }
+ }
+ while (ret == NULL);
+
+ *rc= mutex_exit(&pool->mutex);
+
+ return ret;
+}
+
+memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *released)
+{
+ if (not pool)
+ return MEMCACHED_INVALID_ARGUMENTS;
+
+ memcached_return_t rc= mutex_enter(&pool->mutex);
+
+ if (rc != MEMCACHED_SUCCESS)
+ return rc;
+
+ /* Someone updated the behavior on the object.. */
+ if (not pool->compare_version(released))
+ {
+ memcached_free(released);
+ if (not (released= memcached_clone(NULL, pool->master)))
+ {
+ rc= MEMCACHED_SOME_ERRORS;
+ }
+ }
+
+ pool->server_pool[++pool->firstfree]= released;
+
+ if (pool->firstfree == 0 && pool->current_size == pool->size)
+ {
+ /* we might have people waiting for a connection.. wake them up :-) */
+ pthread_cond_broadcast(&pool->cond);
+ }
+
+ memcached_return_t rval= mutex_exit(&pool->mutex);
+ if (rc == MEMCACHED_SOME_ERRORS)
+ return rc;
+
+ return rval;
+}
+
+
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
+ memcached_behavior_t flag,
+ uint64_t data)
+{
+ if (not pool)
+ return MEMCACHED_INVALID_ARGUMENTS;
+
+ memcached_return_t 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->increment_version();
+ /* update the clones */
+ for (int xx= 0; xx <= pool->firstfree; ++xx)
+ {
+ rc= memcached_behavior_set(pool->server_pool[xx], flag, data);
+ if (rc == MEMCACHED_SUCCESS)
+ {
+ pool->server_pool[xx]->configure.version= pool->version();
+ }
+ else
+ {
+ memcached_free(pool->server_pool[xx]);
+ if (not (pool->server_pool[xx]= memcached_clone(NULL, pool->master)))
+ {
+ /* 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....
+ */
+ }
+ }
+ }
+
+ return mutex_exit(&pool->mutex);
+}
+
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
+ memcached_behavior_t flag,
+ uint64_t *value)
+{
+ if (! pool)
+ return MEMCACHED_INVALID_ARGUMENTS;
+
+ memcached_return_t rc= mutex_enter(&pool->mutex);
+ if (rc != MEMCACHED_SUCCESS)
+ {
+ return rc;
+ }
+
+ *value= memcached_behavior_get(pool->master, flag);
+
+ return mutex_exit(&pool->mutex);
+}
+++ /dev/null
-/* 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: connect to all hosts, and make sure they meet a minimum version
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include "libmemcached/common.h"
-#include "libmemcached/memcached_util.h"
-
-struct local_context
-{
- uint8_t major_version;
- uint8_t minor_version;
- uint8_t micro_version;
-
- bool truth;
-};
-
-static memcached_return_t check_server_version(const memcached_st *ptr,
- const memcached_server_st *instance,
- void *context)
-{
- /* Do Nothing */
- struct local_context *check= (struct local_context *)context;
- (void)ptr;
-
- if (instance->major_version != UINT8_MAX &&
- instance->major_version >= check->major_version &&
- instance->minor_version >= check->minor_version &&
- instance->micro_version >= check->micro_version )
- {
- return MEMCACHED_SUCCESS;
- }
-
- check->truth= false;
-
- return MEMCACHED_FAILURE;
-}
-
-bool libmemcached_util_version_check(memcached_st *memc,
- uint8_t major_version,
- uint8_t minor_version,
- uint8_t micro_version)
-{
- memcached_server_fn callbacks[1];
- memcached_return_t rc= memcached_version(memc);
-
- if (rc != MEMCACHED_SUCCESS)
- return false;
-
- struct local_context check= { .major_version= major_version, .minor_version= minor_version, .micro_version= micro_version, .truth= true };
-
- callbacks[0]= check_server_version;
- memcached_server_cursor(memc, callbacks, (void *)&check, 1);
-
- return check.truth;
-}
--- /dev/null
+/* 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: connect to all hosts, and make sure they meet a minimum version
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include "libmemcached/common.h"
+#include "libmemcached/memcached_util.h"
+
+struct local_context
+{
+ uint8_t major_version;
+ uint8_t minor_version;
+ uint8_t micro_version;
+
+ bool truth;
+};
+
+static memcached_return_t check_server_version(const memcached_st *ptr,
+ const memcached_server_st *instance,
+ void *context)
+{
+ /* Do Nothing */
+ struct local_context *check= (struct local_context *)context;
+ (void)ptr;
+
+ if (instance->major_version != UINT8_MAX &&
+ instance->major_version >= check->major_version &&
+ instance->minor_version >= check->minor_version &&
+ instance->micro_version >= check->micro_version )
+ {
+ return MEMCACHED_SUCCESS;
+ }
+
+ check->truth= false;
+
+ return MEMCACHED_FAILURE;
+}
+
+bool libmemcached_util_version_check(memcached_st *memc,
+ uint8_t major_version,
+ uint8_t minor_version,
+ uint8_t micro_version)
+{
+ memcached_server_fn callbacks[1];
+ memcached_return_t rc= memcached_version(memc);
+
+ if (rc != MEMCACHED_SUCCESS)
+ return false;
+
+ struct local_context check= { major_version, minor_version, micro_version, true };
+
+ callbacks[0]= check_server_version;
+ memcached_server_cursor(memc, callbacks, (void *)&check, 1);
+
+ return check.truth;
+}
} *resource= arg;
usleep(250);
+ // Release all of the memc we are holding
assert(memcached_pool_push(resource->pool, resource->mmc) == MEMCACHED_SUCCESS);
return arg;
}
memcached_st *mmc[POOL_SIZE];
memcached_return_t rc;
+ // Fill up our array that we will store the memc that are in the pool
for (size_t x= 0; x < POOL_SIZE; ++x)
{
mmc[x]= memcached_pool_pop(pool, false, &rc);
test_true(rc == MEMCACHED_SUCCESS);
}
+ // All memc should be gone
test_true(memcached_pool_pop(pool, false, &rc) == NULL);
test_true(rc == MEMCACHED_SUCCESS);
memcached_pool_st* pool;
memcached_st* mmc;
} item= { .pool = pool, .mmc = mmc[9] };
+
pthread_create(&tid, NULL, connection_release, &item);
mmc[9]= memcached_pool_pop(pool, true, &rc);
test_true(rc == MEMCACHED_SUCCESS);
pthread_join(tid, NULL);
- test_true(mmc[9] == item.mmc);
+ test_true(mmc[9]);
const char *key= "key";
size_t keylen= strlen(key);