From: Trond Norbye Date: Mon, 5 Oct 2009 18:37:05 +0000 (+0200) Subject: Move libmemcachedutil to libmemcached/util where it belongs X-Git-Tag: 0.34~15^2~4 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;ds=inline;h=945be4901bee5aad1c6b62a12b9ac91e852f0405;p=m6w6%2Flibmemcached Move libmemcachedutil to libmemcached/util where it belongs --- diff --git a/Makefile.am b/Makefile.am index affdae19..eeab710a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = docs libmemcached libmemcachedutil support clients tests example +SUBDIRS = docs libmemcached support clients tests example EXTRA_dist = README.FIRST check-local: test-no-outputdiff diff --git a/configure.ac b/configure.ac index 0601a175..951edfbf 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ AC_SUBST(MEMCACHEDPROTOCOL_LIBRARY_VERSION) if test "$lt_cv_prog_gnu_ld" = "yes" then LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/libmemcached.ver" - LD_UTIL_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcachedutil/libmemcachedutil.ver" + LD_UTIL_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/util/libmemcachedutil.ver" LD_PROTOCOL_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/protocol/libmemcachedprotocol.ver" fi AC_SUBST(LD_VERSION_SCRIPT) @@ -94,7 +94,6 @@ AC_CONFIG_FILES([ example/Makefile libmemcached/Makefile libmemcached/memcached_configure.h - libmemcachedutil/Makefile support/Makefile support/libmemcached.pc support/libmemcached.spec diff --git a/libmemcached/Makefile.am b/libmemcached/Makefile.am index ef9d0cd8..ac9aa101 100644 --- a/libmemcached/Makefile.am +++ b/libmemcached/Makefile.am @@ -1,5 +1,9 @@ -EXTRA_DIST = libmemcached_probes.d memcached/README.txt libmemcached.ver \ - memcached_configure.h.in protocol/libmemcachedprotocol.ver +EXTRA_DIST = libmemcached.ver \ + libmemcached_probes.d \ + memcached/README.txt \ + memcached_configure.h.in \ + protocol/libmemcachedprotocol.ver \ + util/libmemcachedutil.ver EXTRA_HEADERS = @@ -33,10 +37,6 @@ nobase_pkginclude_HEADERS=protocol/cache.h \ protocol/callback.h -if BUILD_LIBMEMCACHEDUTIL -pkginclude_HEADERS+= memcached_util.h memcached_pool.h -endif - libmemcachedprotocol_la_SOURCES= protocol/ascii_handler.c \ protocol/binary_handler.c \ protocol/cache.c \ @@ -94,6 +94,16 @@ libmemcached_la_DEPENDENCIES= libmemcachedcallbacks.la libmemcached_la_LIBADD= $(LIBM) libmemcachedcallbacks.la libmemcached_la_LDFLAGS = -version-info $(MEMCACHED_LIBRARY_VERSION) $(LD_VERSION_SCRIPT) $(LIBM) +if BUILD_LIBMEMCACHEDUTIL +pkginclude_HEADERS+= memcached_util.h memcached_pool.h +lib_LTLIBRARIES+= libmemcachedutil.la +endif + +libmemcachedutil_la_SOURCES= util/memcached_pool.c +libmemcachedutil_la_LDFLAGS= -version-info $(MEMCACHEDUTIL_LIBRARY_VERSION) $(LD_UTIL_VERSION_SCRIPT) +libmemcachedutil_la_LIBADD= libmemcached.la +libmemcachedutil_la_DEPENDENCIES=libmemcached.la + if BUILD_BYTEORDER noinst_LTLIBRARIES += libbyteorder.la libbyteorder_la_SOURCES= byteorder.c byteorder.h diff --git a/libmemcached/util/Makefile.am b/libmemcached/util/Makefile.am new file mode 100644 index 00000000..bbb94ddd --- /dev/null +++ b/libmemcached/util/Makefile.am @@ -0,0 +1,11 @@ +EXTRA_DIST= libmemcachedutil.ver + +lib_LTLIBRARIES= + +if BUILD_LIBMEMCACHEDUTIL +lib_LTLIBRARIES+= libmemcachedutil.la +endif + +libmemcachedutil_la_SOURCES= memcached_pool.c +libmemcachedutil_la_LDFLAGS= -version-info $(MEMCACHEDUTIL_LIBRARY_VERSION) $(LD_UTIL_VERSION_SCRIPT) +libmemcachedutil_la_LIBADD= ${top_builddir}/libmemcached/libmemcached.la diff --git a/libmemcached/util/libmemcachedutil.ver b/libmemcached/util/libmemcachedutil.ver new file mode 100644 index 00000000..1a6d5013 --- /dev/null +++ b/libmemcached/util/libmemcachedutil.ver @@ -0,0 +1 @@ +libmemcachedutil_0 { global: *; }; diff --git a/libmemcached/util/memcached_pool.c b/libmemcached/util/memcached_pool.c new file mode 100644 index 00000000..afc2fee3 --- /dev/null +++ b/libmemcached/util/memcached_pool.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +#include "libmemcached/common.h" +#include "libmemcached/memcached_pool.h" + +#include +#include + +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; + char* version; +}; + +static memcached_return 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 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 0; +} + +memcached_pool_st *memcached_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 }; + + if (object.mmc != NULL) + { + ret= calloc(1, sizeof(*ret)); + if (ret == NULL) + { + free(object.mmc); + 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_st* memcached_pool_destroy(memcached_pool_st* pool) +{ + 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); + free(pool); + + return ret; +} + +memcached_st* memcached_pool_pop(memcached_pool_st* pool, + bool block, + memcached_return *rc) +{ + 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 memcached_pool_push(memcached_pool_st* pool, + memcached_st *mmc) +{ + memcached_return 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 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); +} diff --git a/libmemcachedutil/Makefile.am b/libmemcachedutil/Makefile.am deleted file mode 100644 index bbb94ddd..00000000 --- a/libmemcachedutil/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -EXTRA_DIST= libmemcachedutil.ver - -lib_LTLIBRARIES= - -if BUILD_LIBMEMCACHEDUTIL -lib_LTLIBRARIES+= libmemcachedutil.la -endif - -libmemcachedutil_la_SOURCES= memcached_pool.c -libmemcachedutil_la_LDFLAGS= -version-info $(MEMCACHEDUTIL_LIBRARY_VERSION) $(LD_UTIL_VERSION_SCRIPT) -libmemcachedutil_la_LIBADD= ${top_builddir}/libmemcached/libmemcached.la diff --git a/libmemcachedutil/libmemcachedutil.ver b/libmemcachedutil/libmemcachedutil.ver deleted file mode 100644 index 1a6d5013..00000000 --- a/libmemcachedutil/libmemcachedutil.ver +++ /dev/null @@ -1 +0,0 @@ -libmemcachedutil_0 { global: *; }; diff --git a/libmemcachedutil/memcached_pool.c b/libmemcachedutil/memcached_pool.c deleted file mode 100644 index afc2fee3..00000000 --- a/libmemcachedutil/memcached_pool.c +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#include "libmemcached/common.h" -#include "libmemcached/memcached_pool.h" - -#include -#include - -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; - char* version; -}; - -static memcached_return 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 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 0; -} - -memcached_pool_st *memcached_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 }; - - if (object.mmc != NULL) - { - ret= calloc(1, sizeof(*ret)); - if (ret == NULL) - { - free(object.mmc); - 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_st* memcached_pool_destroy(memcached_pool_st* pool) -{ - 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); - free(pool); - - return ret; -} - -memcached_st* memcached_pool_pop(memcached_pool_st* pool, - bool block, - memcached_return *rc) -{ - 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 memcached_pool_push(memcached_pool_st* pool, - memcached_st *mmc) -{ - memcached_return 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 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); -} diff --git a/tests/Makefile.am b/tests/Makefile.am index d9a1f7e6..77ba5dee 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ LDADDS = $(top_builddir)/libmemcached/libmemcached.la if BUILD_LIBMEMCACHEDUTIL -LDADDS+= $(top_builddir)/libmemcachedutil/libmemcachedutil.la +LDADDS+= $(top_builddir)/libmemcached/libmemcachedutil.la endif EXTRA_DIST = output.res output2.res\