From 011afc7462a7ee812028840fa22e573f3c97ad0b Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Thu, 11 Mar 2010 13:51:29 -0500 Subject: [PATCH 1/4] Release 1.0.1 Fix build for libmemcached-0.38. --- ChangeLog | 4 ++++ package.xml | 21 +++++++++++++-------- php_memcached.c | 6 ++++++ php_memcached.h | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd8b3dc9..75bb593f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ memcached extension changelog +Version 1.0.1 +------------- + * Fix build for libmemcached-0.38. + Version 1.0.0 ------------- * First stable release. diff --git a/package.xml b/package.xml index 9e549acf..7b713a28 100644 --- a/package.xml +++ b/package.xml @@ -15,10 +15,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2009-07-07 + 2010-03-11 - 1.0.0 - 1.0.0 + 1.0.1 + 1.0.1 stable @@ -26,11 +26,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- First stable release. -- Add getResultMessage() method. -- Fix OPT_RECV_TIMEOUT definition. -- Initialize Session lock wait to max execution time (if max execution - time is unlimited, default to 30 seconds). +- Fix build for libmemcached-0.38. @@ -60,6 +56,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached + + stablestable + 1.0.11.0.1 + 2010-03-11 + +- Fix build for libmemcached-0.38. + + + stablestable 1.0.01.0.0 diff --git a/php_memcached.c b/php_memcached.c index a69b1236..da360b76 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1780,8 +1780,14 @@ static PHP_METHOD(Memcached, setOption) * (non-weighted) case. We have to clean up ourselves. */ if (!Z_LVAL_P(value)) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 + (void)memcached_behavior_set_key_hash(i_obj->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution_hash(i_obj->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution(i_obj->memc, MEMCACHED_DISTRIBUTION_MODULA); +#else i_obj->memc->hash = 0; i_obj->memc->distribution = 0; +#endif } break; diff --git a/php_memcached.h b/php_memcached.h index a8c4cf03..956efeff 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -48,7 +48,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "1.0.0" +#define PHP_MEMCACHED_VERSION "1.0.1" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From 9a481623f09d9b638c018eff79ed5e475ce1dd9b Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 3 May 2010 14:59:25 -0700 Subject: [PATCH 2/4] Fix memcached_server_list() problem. --- php_memcached.c | 193 ++++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 81 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index da360b76..ba5cbfd9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -157,6 +157,16 @@ static int le_memc; static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; + +static struct callbackContext +{ + zval *array; + zval *entry; + memcached_stat_st *stats; /* for use with functions that need stats */ + void *return_value; + unsigned int i; /* for use with structures mapped against servers */ +}; + static zend_class_entry *spl_ce_RuntimeException = NULL; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) @@ -190,6 +200,9 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr); static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC); static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC); +static memcached_return php_memc_do_serverlist_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context); +static memcached_return php_memc_do_stats_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context); +static memcached_return php_memc_do_version_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context); /**************************************** @@ -1447,7 +1460,7 @@ PHP_METHOD(Memcached, addServers) } list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host), - Z_LVAL_PP(z_port), weight, &status); + Z_LVAL_PP(z_port), weight, &status); if (php_memc_handle_error(status TSRMLS_CC) == 0) { continue; @@ -1468,13 +1481,14 @@ PHP_METHOD(Memcached, addServers) } /* }}} */ + /* {{{ Memcached::getServerList() Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) { - memcached_server_st *servers; - unsigned int i, servers_count; zval *array; + struct callbackContext context = {0}; + memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { @@ -1483,21 +1497,11 @@ PHP_METHOD(Memcached, getServerList) MEMC_METHOD_FETCH_OBJECT; + callbacks[0] = php_memc_do_serverlist_callback; array_init(return_value); - servers = memcached_server_list(i_obj->memc); - servers_count = memcached_server_count(i_obj->memc); - if (servers == NULL) { - return; - } - - for (i = 0; i < servers_count; i++) { - MAKE_STD_ZVAL(array); - array_init(array); - add_assoc_string(array, "host", servers[i].hostname, 1); - add_assoc_long(array, "port", servers[i].port); - add_assoc_long(array, "weight", servers[i].weight); - add_next_index_zval(return_value, array); - } + context.array = array; + context.return_value = return_value; + memcached_server_cursor(i_obj->memc, callbacks, &context, 1); } /* }}} */ @@ -1541,13 +1545,12 @@ PHP_METHOD(Memcached, getServerByKey) Returns statistics for the memcache servers */ PHP_METHOD(Memcached, getStats) { - memcached_stat_st *stats; + memcached_stat_st *stats; memcached_server_st *servers; - unsigned int i, servers_count; memcached_return status; - char *hostport = NULL; - int hostport_len; zval *entry; + struct callbackContext context = {0}; + memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { @@ -1562,46 +1565,13 @@ PHP_METHOD(Memcached, getStats) } array_init(return_value); - servers = memcached_server_list(i_obj->memc); - servers_count = memcached_server_count(i_obj->memc); - if (servers == NULL) { - return; - } - for (i = 0; i < servers_count; i++) { - hostport_len = spprintf(&hostport, 0, "%s:%d", servers[i].hostname, servers[i].port); - - MAKE_STD_ZVAL(entry); - array_init(entry); - - add_assoc_long(entry, "pid", stats[i].pid); - add_assoc_long(entry, "uptime", stats[i].uptime); - add_assoc_long(entry, "threads", stats[i].threads); - add_assoc_long(entry, "time", stats[i].time); - add_assoc_long(entry, "pointer_size", stats[i].pointer_size); - add_assoc_long(entry, "rusage_user_seconds", stats[i].rusage_user_seconds); - add_assoc_long(entry, "rusage_user_microseconds", stats[i].rusage_user_microseconds); - add_assoc_long(entry, "rusage_system_seconds", stats[i].rusage_system_seconds); - add_assoc_long(entry, "rusage_system_microseconds", stats[i].rusage_system_microseconds); - add_assoc_long(entry, "curr_items", stats[i].curr_items); - add_assoc_long(entry, "total_items", stats[i].total_items); - add_assoc_long(entry, "limit_maxbytes", stats[i].limit_maxbytes); - add_assoc_long(entry, "curr_connections", stats[i].curr_connections); - add_assoc_long(entry, "total_connections", stats[i].total_connections); - add_assoc_long(entry, "connection_structures", stats[i].connection_structures); - add_assoc_long(entry, "bytes", stats[i].bytes); - add_assoc_long(entry, "cmd_get", stats[i].cmd_get); - add_assoc_long(entry, "cmd_set", stats[i].cmd_set); - add_assoc_long(entry, "get_hits", stats[i].get_hits); - add_assoc_long(entry, "get_misses", stats[i].get_misses); - add_assoc_long(entry, "evictions", stats[i].evictions); - add_assoc_long(entry, "bytes_read", stats[i].bytes_read); - add_assoc_long(entry, "bytes_written", stats[i].bytes_written); - add_assoc_stringl(entry, "version", stats[i].version, strlen(stats[i].version), 1); - - add_assoc_zval_ex(return_value, hostport, hostport_len+1, entry); - efree(hostport); - } + callbacks[0] = php_memc_do_stats_callback; + context.i = 0; + context.entry = entry; + context.stats = stats; + context.return_value = return_value; + memcached_server_cursor(i_obj->memc, callbacks, &context, 1); memcached_stat_free(i_obj->memc, stats); } @@ -1612,11 +1582,9 @@ PHP_METHOD(Memcached, getStats) PHP_METHOD(Memcached, getVersion) { memcached_server_st *servers; - unsigned int i, servers_count; - char *hostport = NULL; - char version[16]; - int hostport_len, version_len; memcached_return status = MEMCACHED_SUCCESS; + struct callbackContext context = {0}; + memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { @@ -1626,11 +1594,6 @@ PHP_METHOD(Memcached, getVersion) MEMC_METHOD_FETCH_OBJECT; array_init(return_value); - servers = memcached_server_list(i_obj->memc); - servers_count = memcached_server_count(i_obj->memc); - if (servers == NULL) { - return; - } status = memcached_version(i_obj->memc); if (php_memc_handle_error(status TSRMLS_CC) < 0) { @@ -1638,15 +1601,10 @@ PHP_METHOD(Memcached, getVersion) RETURN_FALSE; } - for (i = 0; i < servers_count; i++) { - hostport_len = spprintf(&hostport, 0, "%s:%d", servers[i].hostname, servers[i].port); - version_len = snprintf(version, sizeof(version), "%d.%d.%d", - servers[i].major_version, servers[i].minor_version, - servers[i].micro_version); + callbacks[0] = php_memc_do_version_callback; + context.return_value = return_value; - add_assoc_stringl_ex(return_value, hostport, hostport_len+1, version, version_len, 1); - efree(hostport); - } + memcached_server_cursor(i_obj->memc, callbacks, &context, 1); } /* }}} */ @@ -1925,6 +1883,79 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) /* }}} */ /* {{{ internal API functions */ +static memcached_return php_memc_do_serverlist_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +{ + struct callbackContext* context = (struct callbackContext*) in_context; + + MAKE_STD_ZVAL(context->array); + array_init(context->array); + add_assoc_string(context->array, "host", instance->hostname, 1); + add_assoc_long(context->array, "port", instance->port); + add_assoc_long(context->array, "weight", instance->weight); + add_next_index_zval(context->return_value, context->array); + return MEMCACHED_SUCCESS; +} + +static memcached_return php_memc_do_stats_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +{ + char *hostport = NULL; + int hostport_len; + struct callbackContext* context = (struct callbackContext*) in_context; + hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port); + + MAKE_STD_ZVAL(context->entry); + array_init(context->entry); + + add_assoc_long(context->entry, "pid", context->stats[context->i].pid); + add_assoc_long(context->entry, "uptime", context->stats[context->i].uptime); + add_assoc_long(context->entry, "threads", context->stats[context->i].threads); + add_assoc_long(context->entry, "time", context->stats[context->i].time); + add_assoc_long(context->entry, "pointer_size", context->stats[context->i].pointer_size); + add_assoc_long(context->entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); + add_assoc_long(context->entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); + add_assoc_long(context->entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); + add_assoc_long(context->entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); + add_assoc_long(context->entry, "curr_items", context->stats[context->i].curr_items); + add_assoc_long(context->entry, "total_items", context->stats[context->i].total_items); + add_assoc_long(context->entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); + add_assoc_long(context->entry, "curr_connections", context->stats[context->i].curr_connections); + add_assoc_long(context->entry, "total_connections", context->stats[context->i].total_connections); + add_assoc_long(context->entry, "connection_structures", context->stats[context->i].connection_structures); + add_assoc_long(context->entry, "bytes", context->stats[context->i].bytes); + add_assoc_long(context->entry, "cmd_get", context->stats[context->i].cmd_get); + add_assoc_long(context->entry, "cmd_set", context->stats[context->i].cmd_set); + add_assoc_long(context->entry, "get_hits", context->stats[context->i].get_hits); + add_assoc_long(context->entry, "get_misses", context->stats[context->i].get_misses); + add_assoc_long(context->entry, "evictions", context->stats[context->i].evictions); + add_assoc_long(context->entry, "bytes_read", context->stats[context->i].bytes_read); + add_assoc_long(context->entry, "bytes_written", context->stats[context->i].bytes_written); + add_assoc_stringl(context->entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version), 1); + + add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, context->entry); + efree(hostport); + + /* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */ + context->i++; + return MEMCACHED_SUCCESS; +} + +static memcached_return php_memc_do_version_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +{ + char *hostport = NULL; + char version[16]; + int hostport_len, version_len; + struct callbackContext* context = (struct callbackContext*) in_context; + + hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port); + version_len = snprintf(version, sizeof(version), "%d.%d.%d", + instance->major_version, instance->minor_version, + instance->micro_version); + + add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1); + efree(hostport); + return MEMCACHED_SUCCESS; +} + static int php_memc_handle_error(memcached_return status TSRMLS_DC) { int result = 0; @@ -1999,7 +2030,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t #if HAVE_JSON_API case SERIALIZER_JSON: { - php_json_encode(&buf, value TSRMLS_CC); + php_json_encode(&buf, value, 0 TSRMLS_CC); buf.c[buf.len] = 0; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); break; @@ -2164,7 +2195,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_JSON: #if HAVE_JSON_API - php_json_decode(value, payload, payload_len, 0 TSRMLS_CC); + php_json_decode(value, payload, payload_len, 0, 512 TSRMLS_CC); #else php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); return -1; @@ -2777,8 +2808,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getServerList, arginfo_getServerList) MEMC_ME(getServerByKey, arginfo_getServerByKey) - MEMC_ME(getStats, arginfo_getStats) - MEMC_ME(getVersion, arginfo_getVersion) + MEMC_ME(getStats, arginfo_getStats) + MEMC_ME(getVersion, arginfo_getVersion) MEMC_ME(flush, arginfo_flush) From f2718bee43d1a4f9df9bc1a41d0d3ce2b0bba1f6 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 3 May 2010 15:03:52 -0700 Subject: [PATCH 3/4] Release 1.0.2. --- ChangeLog | 4 ++++ package.xml | 17 +++++++++++++---- php_memcached.h | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75bb593f..d7f93656 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ memcached extension changelog +Version 1.0.2 +------------- + * Fix build for libmemcached-0.39 (memcached_server_list() issue) + Version 1.0.1 ------------- * Fix build for libmemcached-0.38. diff --git a/package.xml b/package.xml index 7b713a28..7a06026b 100644 --- a/package.xml +++ b/package.xml @@ -15,10 +15,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2010-03-11 + 2010-05-03 - 1.0.1 - 1.0.1 + 1.0.2 + 1.0.2 stable @@ -26,7 +26,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Fix build for libmemcached-0.38. +- Fix build for libmemcached-0.39 (memcached_server_list() issue) @@ -56,6 +56,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached + + stablestable + 1.0.21.0.2 + 2010-05-03 + +- Fix build for libmemcached-0.39 (memcached_server_list() issue) + + + stablestable 1.0.11.0.1 diff --git a/php_memcached.h b/php_memcached.h index 956efeff..b1e4b50b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -48,7 +48,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "1.0.1" +#define PHP_MEMCACHED_VERSION "1.0.2" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From 8d8c95b94b0349c97c3994138413881a4a8f9ad0 Mon Sep 17 00:00:00 2001 From: Mark Rose Date: Tue, 3 Jan 2012 11:04:14 -0500 Subject: [PATCH 4/4] Fix setting session expiry when using memcached for sessions. This commit fixes a bug where the ini file is incorrectly parsed resulting in the session ttl always being set to 0. This leads to never expiring sessions, bloating memcached usage. This is particularly troublesome when using CouchBase as a memcached replacement as sessions never expire, consuming all CouchBase storage. Markus Berthold found and fixed the bug. For more details, see: http://www.couchbase.org/forums/thread/using-membase-php-session-handler --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index ba5cbfd9..249e3f6b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2522,7 +2522,7 @@ PS_WRITE_FUNC(memcached) memcached_st *memc_sess = PS_GET_MOD_DATA(); sess_key_len = spprintf(&sess_key, 0, "memc.sess.key.%s", key); - sess_lifetime = zend_ini_long(ZEND_STRL("session.gc_maxlifetime"), 0); + sess_lifetime = zend_ini_long("session.gc_maxlifetime", sizeof("session.gc_maxlifetime"), 0); if (sess_lifetime > 0) { expiration = time(NULL) + sess_lifetime; } else {