diff --git a/ChangeLog b/ChangeLog
index bd8b3dc9..d7f93656 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
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.
+
Version 1.0.0
-------------
* First stable release.
diff --git a/package.xml b/package.xml
index 9e549acf..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
- 2009-07-07
+ 2010-05-03
- 1.0.0
- 1.0.0
+ 1.0.2
+ 1.0.2
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.39 (memcached_server_list() issue)
@@ -60,6 +56,24 @@ 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
+ 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..249e3f6b 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);
}
/* }}} */
@@ -1780,8 +1738,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;
@@ -1919,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;
@@ -1993,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;
@@ -2158,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;
@@ -2485,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 {
@@ -2771,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)
diff --git a/php_memcached.h b/php_memcached.h
index a8c4cf03..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.0"
+#define PHP_MEMCACHED_VERSION "1.0.2"
#ifdef ZTS
#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v)