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)