From 9bf006d45f40839fe9a7ced725c7112a1d2f43fd Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 23 Jun 2010 08:51:56 -0400 Subject: [PATCH 001/694] Fixed a possible bug when NULL or empty string is passed to MemCached constructor --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1323d5e0..240c0e52 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -329,7 +329,7 @@ static PHP_METHOD(Memcached, __construct) i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC); i_obj->is_pristine = 0; - if (persistent_id) { + if (persistent_id && *persistent_id) { zend_rsrc_list_entry *le = NULL; is_persistent = 1; From 7b01b5669fd65bbcae15eade98ca5bc5749b464a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 23 Jun 2010 08:54:09 -0400 Subject: [PATCH 002/694] Fixed various compiler warnings --- php_memcached.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 240c0e52..f159a16d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -211,7 +211,9 @@ struct callbackContext unsigned int i; /* for use with structures mapped against servers */ }; +#if HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; +#endif #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; @@ -635,7 +637,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(keys))) { - zval copy, *copy_ptr; if (Z_TYPE_PP(entry) != IS_STRING) { convert_to_string_ex(entry); @@ -1782,7 +1783,6 @@ PHP_METHOD(Memcached, getServerByKey) PHP_METHOD(Memcached, getStats) { memcached_stat_st *stats; - memcached_server_st *servers; memcached_return status; zval *entry; struct callbackContext context = {0}; @@ -1821,7 +1821,6 @@ PHP_METHOD(Memcached, getStats) Returns the version of each memcached server in the pool */ PHP_METHOD(Memcached, getVersion) { - memcached_server_st *servers; memcached_return status = MEMCACHED_SUCCESS; struct callbackContext context = {0}; memcached_server_function callbacks[1]; From 12b5fa6705248d9398d6be544e39227a413d7272 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 13 Jul 2010 14:38:12 -0400 Subject: [PATCH 003/694] make get return false on error --- php_memcached.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f159a16d..9d912907 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -163,7 +163,7 @@ typedef unsigned long int uint32_t; #endif #endif -#define RETURN_FROM_GET RETURN_NULL() +#define RETURN_FROM_GET RETURN_FALSE /**************************************** Structures and definitions @@ -497,7 +497,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* if we have a callback, all processing is done */ if (fci.size != 0) { memcached_result_free(&result); - return; + RETURN_FALSE; } } @@ -517,7 +517,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_result_free(&result); - return; + RETURN_FALSE; } else { int rc; From 75024fc044a44dbb3199c1d254ccf1cf0d9a6fe4 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Thu, 7 Oct 2010 19:46:29 +0100 Subject: [PATCH 004/694] Fix the 5% to actually add five percent --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1323d5e0..767b61f7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2471,7 +2471,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t zend_bool compress_status = 0; /* Additional 5% for the data */ - unsigned long payload_comp_len = (unsigned long)((buf.len + 1.05) + 1); + unsigned long payload_comp_len = (unsigned long)((buf.len * 1.05) + 1); char *payload_comp = emalloc(payload_comp_len + sizeof(uint32_t)); payload = payload_comp; memcpy(payload_comp, &buf.len, sizeof(uint32_t)); From f9b2b48e78b3bf7ce21f15b3de9451c66c63fc05 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Tue, 12 Oct 2010 17:14:50 +0100 Subject: [PATCH 005/694] Make sure that all tests output something --- tests/cas.phpt | 2 ++ tests/cas_multi.phpt | 2 ++ tests/conf_persist.phpt | 3 +++ tests/deleted.phpt | 4 ++++ tests/expire.phpt | 3 +++ tests/session_badconf_locktime.phpt | 3 +++ tests/types.phpt | 5 ++++- tests/types_multi.phpt | 3 +++ 8 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/cas.phpt b/tests/cas.phpt index 7ef0994e..fc14842b 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -30,5 +30,7 @@ if ($v !== 11) { echo "Wanted cas_test to be 11, value is: "; var_dump($v); } +echo "OK\n"; ?> --EXPECT-- +OK \ No newline at end of file diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index 85db2c6b..d180d779 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -45,6 +45,8 @@ foreach ($data as $key => $v) { } } +echo "OK\n"; ?> --EXPECT-- +OK \ No newline at end of file diff --git a/tests/conf_persist.phpt b/tests/conf_persist.phpt index bc46a061..eb4895b4 100644 --- a/tests/conf_persist.phpt +++ b/tests/conf_persist.phpt @@ -26,5 +26,8 @@ for ($i = 1000; $i > 0; $i--) { } } +echo "OK\n"; + ?> --EXPECT-- +OK \ No newline at end of file diff --git a/tests/deleted.phpt b/tests/deleted.phpt index 9baf364d..ec79cd0e 100644 --- a/tests/deleted.phpt +++ b/tests/deleted.phpt @@ -17,5 +17,9 @@ if ($v !== Memcached::GET_ERROR_RETURN_VALUE) { echo "Got: "; var_dump($v); } + +echo "OK\n"; + ?> --EXPECT-- +OK \ No newline at end of file diff --git a/tests/expire.phpt b/tests/expire.phpt index 623eb206..6e406d42 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -21,5 +21,8 @@ if ($v !== Memcached::GET_ERROR_RETURN_VALUE) { echo "from get of expired value. Got:\n"; var_dump($v); } + +echo "OK\n"; ?> --EXPECT-- +OK \ No newline at end of file diff --git a/tests/session_badconf_locktime.phpt b/tests/session_badconf_locktime.phpt index 82f267e5..9bda76b6 100644 --- a/tests/session_badconf_locktime.phpt +++ b/tests/session_badconf_locktime.phpt @@ -23,4 +23,7 @@ set_error_handler('handler', E_ALL); session_start(); session_write_close(); +echo "OK\n"; + --EXPECTF-- +OK \ No newline at end of file diff --git a/tests/types.phpt b/tests/types.phpt index d27cdf10..7ed8edf2 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -64,5 +64,8 @@ if ($m->get("sdfjhw38rwdenfoqu29eiajfroehr8jaiodfhjaoierhjadf") !== NULL) { echo "Actual: " . get_type($actual); } +echo "OK\n"; + ?> ---EXPECT-- \ No newline at end of file +--EXPECT-- +OK \ No newline at end of file diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt index 6f1965df..a5c0299b 100644 --- a/tests/types_multi.phpt +++ b/tests/types_multi.phpt @@ -57,5 +57,8 @@ foreach ($data as $key => $value) { } } +echo "OK\n"; + ?> --EXPECT-- +OK \ No newline at end of file From 73e30fecf922e00f0a379c0040afa1de0b10d59e Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Tue, 12 Oct 2010 17:20:56 +0100 Subject: [PATCH 006/694] Added callback when a new object is created. This eases up adding servers to a persistent object. See tests/invoke_callback.phpt --- memcached-api.php | 2 +- php_memcached.c | 48 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 48fe9485..73347d72 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -181,7 +181,7 @@ class Memcached { const RES_CONNECTION_SOCKET_CREATE_FAILURE; - public function __construct( $persistent_id = '' ) {} + public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} public function get( $key, $cache_cb = null, &$cas_token = null ) {} diff --git a/php_memcached.c b/php_memcached.c index 767b61f7..22466e45 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -306,7 +306,39 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, me Method implementations ****************************************/ -/* {{{ Memcached::__construct([string persisten_id])) +static void php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len) +{ + zval *retval_ptr, *pid_z; + zval **params[2]; + + ALLOC_INIT_ZVAL(pid_z); + + if (persistent_id) { + ZVAL_STRINGL(pid_z, persistent_id, persistent_id_len, 1); + } else { + ZVAL_NULL(pid_z); + } + + /* Call the cb */ + params[0] = &object; + params[1] = &pid_z; + + fci->params = params; + fci->param_count = 2; + fci->retval_ptr_ptr = &retval_ptr; + fci->no_separation = 1; + + if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name)); + } + zval_ptr_dtor(&pid_z); + + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } +} + +/* {{{ Memcached::__construct([string persistent_id[, callback on_new]])) Creates a Memcached object, optionally using persistent memcache connection */ static PHP_METHOD(Memcached, __construct) { @@ -319,9 +351,13 @@ static PHP_METHOD(Memcached, __construct) char *plist_key = NULL; int plist_key_len = 0; + + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; + zend_bool invoke_callback = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &persistent_id, - &persistent_id_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sf", &persistent_id, + &persistent_id_len, &fci, &fci_cache) == FAILURE) { ZVAL_NULL(object); return; } @@ -377,6 +413,7 @@ static PHP_METHOD(Memcached, __construct) /* not reached */ } } + invoke_callback = 1; } i_obj->is_persistent = is_persistent; @@ -385,6 +422,10 @@ static PHP_METHOD(Memcached, __construct) if (plist_key != NULL) { efree(plist_key); } + + if (ZEND_NUM_ARGS() >= 2 && invoke_callback) { + php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len); + } } /* }}} */ @@ -3070,6 +3111,7 @@ PS_GC_FUNC(memcached) /* {{{ methods arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) + ZEND_ARG_INFO(0, callback) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getResultCode, 0) From e0704a29f408f1483c4ebc5560655b0e3a356c5f Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Tue, 12 Oct 2010 22:09:45 +0100 Subject: [PATCH 007/694] Added test for callback invoke --- tests/invoke_callback.phpt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/invoke_callback.phpt diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt new file mode 100644 index 00000000..bb77203d --- /dev/null +++ b/tests/invoke_callback.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test that callback is invoked on new object +--SKIPIF-- + +--FILE-- +addServer("127.0.0.1", 11211); +} + +$m = new Memcached('hi', 'my_func'); + +var_dump($m->getServerList()); + +echo "OK\n"; + +--EXPECT-- +array(1) { + [0]=> + array(3) { + ["host"]=> + string(9) "127.0.0.1" + ["port"]=> + int(11211) + ["weight"]=> + int(0) + } +} +OK From b77b090c4770c54ed9a66af00b79e6ecdd9bd178 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 13 Oct 2010 11:52:13 +0100 Subject: [PATCH 008/694] Make sure that null is not converted to empty persistent_id --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 22466e45..035d759f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -356,7 +356,7 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info_cache fci_cache; zend_bool invoke_callback = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sf", &persistent_id, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f", &persistent_id, &persistent_id_len, &fci, &fci_cache) == FAILURE) { ZVAL_NULL(object); return; From 92bef86a127f4653bd7a2c4c2e330f5f34a7050d Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 13 Oct 2010 11:52:34 +0100 Subject: [PATCH 009/694] Add second test for callback --- tests/invoke_callback_twice.phpt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/invoke_callback_twice.phpt diff --git a/tests/invoke_callback_twice.phpt b/tests/invoke_callback_twice.phpt new file mode 100644 index 00000000..7cf63647 --- /dev/null +++ b/tests/invoke_callback_twice.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test that callback is invoked on new object only once +--SKIPIF-- + +--FILE-- + Date: Sun, 17 Oct 2010 10:48:58 +0100 Subject: [PATCH 010/694] Code cleanups --- php_memcached.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 035d759f..d33242a7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -373,6 +373,7 @@ static PHP_METHOD(Memcached, __construct) plist_key_len += 1; if (plist_key == NULL) { + efree(plist_key); php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate peristent list handler"); /* not reached */ } @@ -387,12 +388,14 @@ static PHP_METHOD(Memcached, __construct) if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); if (m_obj == NULL) { + efree(plist_key); php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle"); /* not reached */ } m_obj->memc = memcached_create(NULL); if (m_obj->memc == NULL) { + efree(plist_key); php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); /* not reached */ } @@ -409,6 +412,7 @@ static PHP_METHOD(Memcached, __construct) le.ptr = m_obj; if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + efree(plist_key); php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); /* not reached */ } @@ -689,7 +693,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (preserve_order) { add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i] + 1); } - i++; } } @@ -1525,12 +1528,12 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &server_key, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|l", &server_key, &server_key_len, &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|l", &entries, &expiration) == FAILURE) { return; } } @@ -1542,24 +1545,12 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(entries))) { - int use_copy = 0; - zval entry_copy, *entry_copy_ptr; - + if (Z_TYPE_PP(entry) != IS_STRING) { - entry_copy = **entry; - zval_copy_ctor(&entry_copy); - INIT_PZVAL(&entry_copy); - convert_to_string(&entry_copy); - entry_copy_ptr = &entry_copy; - entry = &entry_copy_ptr; - use_copy = 1; - } - - if (Z_TYPE_PP(entry) != IS_STRING || Z_STRLEN_PP(entry) <= 0) { - if (use_copy) { - zval_dtor(&entry_copy); - } - + convert_to_string_ex(entry); + } + + if (Z_STRLEN_PP(entry) == 0) { continue; } @@ -1575,10 +1566,6 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } else { add_assoc_bool(return_value, Z_STRVAL_PP(entry), 1); } - - if (use_copy) { - zval_dtor(&entry_copy); - } } return; From a90f66f7822f1647c39a13589fa3feaf36eb8f6d Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Sun, 17 Oct 2010 10:50:21 +0100 Subject: [PATCH 011/694] Make sure that key types are not changed during deleteMulti --- tests/deletemultitypes.phpt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/deletemultitypes.phpt diff --git a/tests/deletemultitypes.phpt b/tests/deletemultitypes.phpt new file mode 100644 index 00000000..a72205b6 --- /dev/null +++ b/tests/deletemultitypes.phpt @@ -0,0 +1,27 @@ +--TEST-- +Delete multi key types +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211, 1); + +$m->flush(); + +function dump_types($v, $k) { + echo gettype($v) . "\n"; +} + +$keys = array(100, 'str'); +array_walk($keys, 'dump_types'); + +$deleted = $m->deleteMulti($keys); +array_walk($keys, 'dump_types'); + +?> +--EXPECT-- +integer +string +integer +string \ No newline at end of file From 7422d8c55d530d00b56c1cbeb2a575aae1de5014 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 3 Nov 2010 18:00:59 +0000 Subject: [PATCH 012/694] Session handler support check --- php_memcached.c | 6 ++++++ tests/session_badconf_emptyprefix.phpt | 5 ++++- tests/session_badconf_prefix.phpt | 5 ++++- tests/session_badconf_servers.phpt | 5 ++++- tests/session_basic.phpt | 5 ++++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d33242a7..a537f451 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3458,6 +3458,12 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); #endif +#ifdef HAVE_MEMCACHED_SESSION + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1); +#else + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 0); +#endif + /* * libmemcached behavior options */ diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index 71c4a095..2c356482 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -1,7 +1,10 @@ --TEST-- Session bad configurations, prefix --SKIPIF-- - + --INI-- memcached.sess_locking = on memcached.sess_lock_wait = 150000 diff --git a/tests/session_badconf_prefix.phpt b/tests/session_badconf_prefix.phpt index cf38a991..ddbc8e66 100644 --- a/tests/session_badconf_prefix.phpt +++ b/tests/session_badconf_prefix.phpt @@ -1,7 +1,10 @@ --TEST-- Session bad configurations, prefix --SKIPIF-- - + --INI-- memcached.sess_locking = on memcached.sess_lock_wait = 150000 diff --git a/tests/session_badconf_servers.phpt b/tests/session_badconf_servers.phpt index aadc296b..0afd3108 100644 --- a/tests/session_badconf_servers.phpt +++ b/tests/session_badconf_servers.phpt @@ -1,7 +1,10 @@ --TEST-- Session bad configurations, invalid save path (server list) --SKIPIF-- - + --INI-- memcached.sess_locking = on memcached.sess_lock_wait = 150000 diff --git a/tests/session_basic.phpt b/tests/session_basic.phpt index c996884d..034b2f08 100644 --- a/tests/session_basic.phpt +++ b/tests/session_basic.phpt @@ -1,7 +1,10 @@ --TEST-- Session basic open, write, destroy --SKIPIF-- - + --INI-- memcached.sess_locking = on memcached.sess_lock_wait = 150000 From 122a4a2a0d8346abadbd699f31f9f3036413f7a5 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 3 Nov 2010 21:07:27 +0000 Subject: [PATCH 013/694] Properly link with zlib --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index aac17422..f0d76496 100644 --- a/config.m4 +++ b/config.m4 @@ -59,7 +59,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_CHECKING([for zlib location]) if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then AC_MSG_RESULT([$PHP_ZLIB_DIR]) - PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHE_SHARED_LIBADD) + PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) else AC_MSG_ERROR([memcached support requires ZLIB. Use --with-zlib-dir= to specify the prefix where ZLIB headers and library are located]) From 5d230a42488a686d2c5ba08628d5e05fcc9d018d Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 3 Nov 2010 22:11:10 +0000 Subject: [PATCH 014/694] session support check --- tests/experimental/session_gc.phpt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/experimental/session_gc.phpt b/tests/experimental/session_gc.phpt index 94d9626d..561901fc 100644 --- a/tests/experimental/session_gc.phpt +++ b/tests/experimental/session_gc.phpt @@ -1,7 +1,10 @@ --TEST-- Session expiration --SKIPIF-- - + --INI-- memcached.sess_prefix = "memc.sess.key." session.save_path="127.0.0.1:11211" From d0d9463e8f47ee33d5720fda90a06de0d17586aa Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 3 Nov 2010 22:11:59 +0000 Subject: [PATCH 015/694] session support check --- tests/experimental/moduleinfo.phpt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 2b453f64..3e790a6f 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -1,7 +1,10 @@ --TEST-- Memcached::phpinfo() --SKIPIF-- - + --FILE-- Date: Wed, 3 Nov 2010 22:12:15 +0000 Subject: [PATCH 016/694] Link zlib --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index f0d76496..235c29fe 100644 --- a/config.m4 +++ b/config.m4 @@ -237,7 +237,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR]) PHP_LIBMEMCACHED_INCDIR="$PHP_LIBMEMCACHED_DIR/include" PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR) - PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/lib, MEMCACHED_SHARED_LIBADD) + PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) PHP_SUBST(MEMCACHED_SHARED_LIBADD) From e1f84344b09047710a5dc9478d5d7f4b2c81b520 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Wed, 3 Nov 2010 22:12:53 +0000 Subject: [PATCH 017/694] Delete the object if exception happens in callback --- php_memcached.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a537f451..9ea77dbe 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -300,13 +300,13 @@ static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zen static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); - +static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); /**************************************** Method implementations ****************************************/ -static void php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len) +static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len) { zval *retval_ptr, *pid_z; zval **params[2]; @@ -330,12 +330,14 @@ static void php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, ze if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name)); + return 0; } zval_ptr_dtor(&pid_z); if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } + return 1; } /* {{{ Memcached::__construct([string persistent_id[, callback on_new]])) @@ -374,7 +376,7 @@ static PHP_METHOD(Memcached, __construct) if (plist_key == NULL) { efree(plist_key); - php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate peristent list handler"); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate persistent list handler"); /* not reached */ } @@ -383,8 +385,11 @@ static PHP_METHOD(Memcached, __construct) m_obj = (struct memc_obj *) le->ptr; } } + i_obj->obj = m_obj; } - + + i_obj->is_persistent = is_persistent; + if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); if (m_obj == NULL) { @@ -403,8 +408,21 @@ static PHP_METHOD(Memcached, __construct) m_obj->serializer = MEMC_G(serializer); m_obj->compression_type = MEMC_G(compression_type_real); m_obj->compression = 1; + + i_obj->obj = m_obj; i_obj->is_pristine = 1; + if (ZEND_NUM_ARGS() >= 2) { + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key != NULL) { + efree(plist_key); + } + php_memc_destroy(m_obj, is_persistent TSRMLS_CC); + return; + } + } + if (is_persistent) { zend_rsrc_list_entry le; @@ -417,19 +435,10 @@ static PHP_METHOD(Memcached, __construct) /* not reached */ } } - invoke_callback = 1; } - - i_obj->is_persistent = is_persistent; - i_obj->obj = m_obj; - if (plist_key != NULL) { efree(plist_key); } - - if (ZEND_NUM_ARGS() >= 2 && invoke_callback) { - php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len); - } } /* }}} */ From ae7545e0b72344376c1b902a3c42d7357d6e8c64 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Thu, 4 Nov 2010 10:37:29 +0000 Subject: [PATCH 018/694] Update license to 3.01. Moved session handler support to separate files. clean up unused variables --- LICENSE | 10 +- config.m4 | 8 +- php_memcached.c | 202 ++------------------------------------- php_memcached.h | 9 -- php_memcached_session.c | 203 ++++++++++++++++++++++++++++++++++++++++ php_memcached_session.h | 38 ++++++++ 6 files changed, 260 insertions(+), 210 deletions(-) create mode 100644 php_memcached_session.c create mode 100644 php_memcached_session.h diff --git a/LICENSE b/LICENSE index d4335c29..3cc8b777 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -------------------------------------------------------------------- - The PHP License, Version 3.0 -Copyright (c) 1999 - 2003 The PHP Group. All rights reserved. + The PHP License, version 3.01 +Copyright (c) 1999 - 2010 The PHP Group. All rights reserved. -------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -38,8 +38,8 @@ are met: 6. Redistributions of any form whatsoever must retain the following acknowledgment: - "This product includes PHP, freely available from - ". + "This product includes PHP software, freely available from + ". THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, @@ -64,5 +64,5 @@ The PHP Group can be contacted via Email at group@php.net. For more information on the PHP Group and the PHP project, please see . -This product includes the Zend Engine, freely available at +PHP includes the Zend Engine, freely available at . diff --git a/config.m4 b/config.m4 index 235c29fe..77f00cc2 100644 --- a/config.m4 +++ b/config.m4 @@ -240,8 +240,14 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) PHP_SUBST(MEMCACHED_SHARED_LIBADD) + + PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c" + + if test "$PHP_MEMCACHED_SESSION" != "no"; then + PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" + fi - PHP_NEW_EXTENSION(memcached, php_memcached.c fastlz/fastlz.c, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) + PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) ifdef([PHP_ADD_EXTENSION_DEP], diff --git a/php_memcached.c b/php_memcached.c index 9ea77dbe..790d49e7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1,11 +1,11 @@ /* +----------------------------------------------------------------------+ - | Copyright (c) 2009 The PHP Group | + | Copyright (c) 2009-2010 The PHP Group | +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | + | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | + | http://www.php.net/license/3_01.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | @@ -46,6 +46,10 @@ #include "php_memcached.h" +#ifdef HAVE_MEMCACHED_SESSION +# include "php_memcached_session.h" +#endif + #include "fastlz/fastlz.h" #include @@ -356,7 +360,6 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info fci; zend_fcall_info_cache fci_cache; - zend_bool invoke_callback = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f", &persistent_id, &persistent_id_len, &fci, &fci_cache) == FAILURE) { @@ -689,7 +692,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(keys))) { - zval copy, *copy_ptr; if (Z_TYPE_PP(entry) != IS_STRING) { convert_to_string_ex(entry); @@ -1819,7 +1821,6 @@ PHP_METHOD(Memcached, getServerByKey) PHP_METHOD(Memcached, getStats) { memcached_stat_st *stats; - memcached_server_st *servers; memcached_return status; zval *entry; struct callbackContext context = {0}; @@ -1858,7 +1859,6 @@ PHP_METHOD(Memcached, getStats) Returns the version of each memcached server in the pool */ PHP_METHOD(Memcached, getVersion) { - memcached_server_st *servers; memcached_return status = MEMCACHED_SUCCESS; struct callbackContext context = {0}; memcached_server_function callbacks[1]; @@ -2916,194 +2916,6 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, /* }}} */ -/* {{{ session support */ -#if HAVE_MEMCACHED_SESSION - -#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 -#define MEMC_SESS_LOCK_EXPIRATION 30 - -ps_module ps_mod_memcached = { - PS_MOD(memcached) -}; - -static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) -{ - char *lock_key = NULL; - int lock_key_len = 0; - long attempts; - long lock_maxwait; - long lock_wait = MEMC_G(sess_lock_wait); - time_t expiration; - memcached_return status; - /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ - - lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); - if (lock_maxwait <= 0) { - lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; - } - if (lock_wait == 0) { - lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; - } - expiration = time(NULL) + lock_maxwait + 1; - attempts = lock_maxwait * 1000000 / lock_wait; - - lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); - do { - status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); - if (status == MEMCACHED_SUCCESS) { - MEMC_G(sess_locked) = 1; - MEMC_G(sess_lock_key) = lock_key; - MEMC_G(sess_lock_key_len) = lock_key_len; - return 0; - } - - if (lock_wait > 0) { - usleep(lock_wait); - } - } while(--attempts > 0); - - efree(lock_key); - return -1; -} - -static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) -{ - if (MEMC_G(sess_locked)) { - memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); - MEMC_G(sess_locked) = 0; - efree(MEMC_G(sess_lock_key)); - MEMC_G(sess_lock_key_len) = 0; - } -} - -PS_OPEN_FUNC(memcached) -{ - memcached_st *memc_sess = PS_GET_MOD_DATA(); - memcached_server_st *servers; - memcached_return status; - - servers = memcached_servers_parse((char *)save_path); - if (servers) { - memc_sess = memcached_create(NULL); - if (memc_sess) { - status = memcached_server_push(memc_sess, servers); - memcached_server_list_free(servers); - - if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != - MEMCACHED_SUCCESS) { - PS_SET_MOD_DATA(NULL); - memcached_free(memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); - return FAILURE; - } - - if (status == MEMCACHED_SUCCESS) { - PS_SET_MOD_DATA(memc_sess); - return SUCCESS; - } - } else { - memcached_server_list_free(servers); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); - } - - PS_SET_MOD_DATA(NULL); - return FAILURE; -} - -PS_CLOSE_FUNC(memcached) -{ - memcached_st *memc_sess = PS_GET_MOD_DATA(); - - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess TSRMLS_CC); - } - if (memc_sess) { - memcached_free(memc_sess); - PS_SET_MOD_DATA(NULL); - } - - return SUCCESS; -} - -PS_READ_FUNC(memcached) -{ - char *payload = NULL; - size_t payload_len = 0; - char *sess_key = NULL; - int sess_key_len = 0; - uint32_t flags = 0; - memcached_return status; - memcached_st *memc_sess = PS_GET_MOD_DATA(); - - if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess, key TSRMLS_CC) < 0) { - return FAILURE; - } - } - - sess_key_len = spprintf(&sess_key, 0, "%s", key); - payload = memcached_get(memc_sess, sess_key, sess_key_len, &payload_len, &flags, &status); - efree(sess_key); - - if (status == MEMCACHED_SUCCESS) { - *val = estrndup(payload, payload_len); - *vallen = payload_len; - free(payload); - return SUCCESS; - } else { - return FAILURE; - } -} - -PS_WRITE_FUNC(memcached) -{ - char *sess_key = NULL; - int sess_key_len = 0; - time_t expiration = 0; - memcached_return status; - memcached_st *memc_sess = PS_GET_MOD_DATA(); - - sess_key_len = spprintf(&sess_key, 0, "%s", key); - if (PS(gc_maxlifetime) > 0) { - expiration = PS(gc_maxlifetime); - } - status = memcached_set(memc_sess, sess_key, sess_key_len, val, vallen, expiration, 0); - efree(sess_key); - - if (status == MEMCACHED_SUCCESS) { - return SUCCESS; - } else { - return FAILURE; - } -} - -PS_DESTROY_FUNC(memcached) -{ - char *sess_key = NULL; - int sess_key_len = 0; - memcached_st *memc_sess = PS_GET_MOD_DATA(); - - sess_key_len = spprintf(&sess_key, 0, "%s", key); - memcached_delete(memc_sess, sess_key, sess_key_len, 0); - efree(sess_key); - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess TSRMLS_CC); - } - - return SUCCESS; -} - -PS_GC_FUNC(memcached) -{ - return SUCCESS; -} - -#endif -/* }}} */ - /* {{{ methods arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) diff --git a/php_memcached.h b/php_memcached.h index 2c9713f7..e5a0c4cb 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -86,15 +86,6 @@ PHP_MINFO_FUNCTION(memcached); #define MEMC_G(v) (php_memcached_globals.v) #endif -/* session handler struct */ -#if HAVE_MEMCACHED_SESSION -#include "ext/session/php_session.h" - -extern ps_module ps_mod_memcached; -#define ps_memcached_ptr &ps_mod_memcached - -PS_FUNCS(memcached); -#endif #endif /* PHP_MEMCACHED_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c new file mode 100644 index 00000000..77b26de1 --- /dev/null +++ b/php_memcached_session.c @@ -0,0 +1,203 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +/* {{{ session support */ +#if HAVE_MEMCACHED_SESSION + +#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 +#define MEMC_SESS_LOCK_EXPIRATION 30 + +ps_module ps_mod_memcached = { + PS_MOD(memcached) +}; + +static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) +{ + char *lock_key = NULL; + int lock_key_len = 0; + long attempts; + long lock_maxwait; + long lock_wait = MEMC_G(sess_lock_wait); + time_t expiration; + memcached_return status; + /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ + + lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + if (lock_maxwait <= 0) { + lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; + } + if (lock_wait == 0) { + lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; + } + expiration = time(NULL) + lock_maxwait + 1; + attempts = lock_maxwait * 1000000 / lock_wait; + + lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); + do { + status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); + if (status == MEMCACHED_SUCCESS) { + MEMC_G(sess_locked) = 1; + MEMC_G(sess_lock_key) = lock_key; + MEMC_G(sess_lock_key_len) = lock_key_len; + return 0; + } + + if (lock_wait > 0) { + usleep(lock_wait); + } + } while(--attempts > 0); + + efree(lock_key); + return -1; +} + +static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) +{ + if (MEMC_G(sess_locked)) { + memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); + MEMC_G(sess_locked) = 0; + efree(MEMC_G(sess_lock_key)); + MEMC_G(sess_lock_key_len) = 0; + } +} + +PS_OPEN_FUNC(memcached) +{ + memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_server_st *servers; + memcached_return status; + + servers = memcached_servers_parse((char *)save_path); + if (servers) { + memc_sess = memcached_create(NULL); + if (memc_sess) { + status = memcached_server_push(memc_sess, servers); + memcached_server_list_free(servers); + + if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != + MEMCACHED_SUCCESS) { + PS_SET_MOD_DATA(NULL); + memcached_free(memc_sess); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); + return FAILURE; + } + + if (status == MEMCACHED_SUCCESS) { + PS_SET_MOD_DATA(memc_sess); + return SUCCESS; + } + } else { + memcached_server_list_free(servers); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); + } + + PS_SET_MOD_DATA(NULL); + return FAILURE; +} + +PS_CLOSE_FUNC(memcached) +{ + memcached_st *memc_sess = PS_GET_MOD_DATA(); + + if (MEMC_G(sess_locking_enabled)) { + php_memc_sess_unlock(memc_sess TSRMLS_CC); + } + if (memc_sess) { + memcached_free(memc_sess); + PS_SET_MOD_DATA(NULL); + } + + return SUCCESS; +} + +PS_READ_FUNC(memcached) +{ + char *payload = NULL; + size_t payload_len = 0; + char *sess_key = NULL; + int sess_key_len = 0; + uint32_t flags = 0; + memcached_return status; + memcached_st *memc_sess = PS_GET_MOD_DATA(); + + if (MEMC_G(sess_locking_enabled)) { + if (php_memc_sess_lock(memc_sess, key TSRMLS_CC) < 0) { + return FAILURE; + } + } + + sess_key_len = spprintf(&sess_key, 0, "%s", key); + payload = memcached_get(memc_sess, sess_key, sess_key_len, &payload_len, &flags, &status); + efree(sess_key); + + if (status == MEMCACHED_SUCCESS) { + *val = estrndup(payload, payload_len); + *vallen = payload_len; + free(payload); + return SUCCESS; + } else { + return FAILURE; + } +} + +PS_WRITE_FUNC(memcached) +{ + char *sess_key = NULL; + int sess_key_len = 0; + time_t expiration = 0; + memcached_return status; + memcached_st *memc_sess = PS_GET_MOD_DATA(); + + sess_key_len = spprintf(&sess_key, 0, "%s", key); + if (PS(gc_maxlifetime) > 0) { + expiration = PS(gc_maxlifetime); + } + status = memcached_set(memc_sess, sess_key, sess_key_len, val, vallen, expiration, 0); + efree(sess_key); + + if (status == MEMCACHED_SUCCESS) { + return SUCCESS; + } else { + return FAILURE; + } +} + +PS_DESTROY_FUNC(memcached) +{ + char *sess_key = NULL; + int sess_key_len = 0; + memcached_st *memc_sess = PS_GET_MOD_DATA(); + + sess_key_len = spprintf(&sess_key, 0, "%s", key); + memcached_delete(memc_sess, sess_key, sess_key_len, 0); + efree(sess_key); + if (MEMC_G(sess_locking_enabled)) { + php_memc_sess_unlock(memc_sess TSRMLS_CC); + } + + return SUCCESS; +} + +PS_GC_FUNC(memcached) +{ + return SUCCESS; +} + +#endif +/* }}} */ \ No newline at end of file diff --git a/php_memcached_session.h b/php_memcached_session.h new file mode 100644 index 00000000..941fe589 --- /dev/null +++ b/php_memcached_session.h @@ -0,0 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_MEMCACHED_SESSION_H +#define PHP_MEMCACHED_SESSION_H + +/* session handler struct */ +#if HAVE_MEMCACHED_SESSION +#include "ext/session/php_session.h" + +extern ps_module ps_mod_memcached; +#define ps_memcached_ptr &ps_mod_memcached + +PS_FUNCS(memcached); + +PS_OPEN_FUNC(memcached); +PS_CLOSE_FUNC(memcached); +PS_READ_FUNC(memcached); +PS_WRITE_FUNC(memcached); +PS_DESTROY_FUNC(memcached); +PS_GC_FUNC(memcached); + +#endif + +#endif /* PHP_MEMCACHED_SESSION_H */ \ No newline at end of file From 660eb88fc16689212f670fcb00b23b5ad65c0853 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Thu, 4 Nov 2010 10:38:23 +0000 Subject: [PATCH 019/694] Update package.xml to include session handler files --- package.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.xml b/package.xml index b94447f7..13c2a26e 100644 --- a/package.xml +++ b/package.xml @@ -45,6 +45,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + From 315b940d382e2219034f4af5d8a9fbe935968d52 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Thu, 4 Nov 2010 10:39:57 +0000 Subject: [PATCH 020/694] Added test for callback exceptions --- tests/callback_exception.phpt | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/callback_exception.phpt diff --git a/tests/callback_exception.phpt b/tests/callback_exception.phpt new file mode 100644 index 00000000..8f71d5f8 --- /dev/null +++ b/tests/callback_exception.phpt @@ -0,0 +1,52 @@ +--TEST-- +make sure that callback exception behaves correctly +--SKIPIF-- + +--FILE-- + +--EXPECT-- +success +success +empty_cb called +OK From 6b0e8ec8c0edba1ce9fa0df956148486ae6d9ee5 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Tue, 9 Nov 2010 13:40:16 +0000 Subject: [PATCH 021/694] Fix includes. Need to clean up these into a shared header later --- php_memcached_session.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 77b26de1..2c96e315 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -14,9 +14,36 @@ +----------------------------------------------------------------------+ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* {{{ session support */ #if HAVE_MEMCACHED_SESSION +#include +#include +#include +#include + +#ifdef ZTS +#include "TSRM.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "php_memcached.h" +#include "php_memcached_session.h" + +ZEND_DECLARE_MODULE_GLOBALS(php_memcached) + #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 #define MEMC_SESS_LOCK_EXPIRATION 30 From 551b5c95f54049814c95e8488815dc82edc6ed3e Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Wed, 29 Dec 2010 14:18:43 +0200 Subject: [PATCH 022/694] Fix double free when exception is thrown in init callback. --- php_memcached.c | 23 +++++---- tests/callback_exception_2.phpt | 54 ++++++++++++++++++++ tests/invoke_callback_2.phpt | 88 +++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 tests/callback_exception_2.phpt create mode 100644 tests/invoke_callback_2.phpt diff --git a/php_memcached.c b/php_memcached.c index 790d49e7..20263cf4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -312,20 +312,18 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len) { - zval *retval_ptr, *pid_z; + zval pid_z; + zval *retval_ptr, *pid_z_ptr = &pid_z; zval **params[2]; - ALLOC_INIT_ZVAL(pid_z); - + INIT_ZVAL(pid_z); if (persistent_id) { - ZVAL_STRINGL(pid_z, persistent_id, persistent_id_len, 1); - } else { - ZVAL_NULL(pid_z); + ZVAL_STRINGL(pid_z_ptr, persistent_id, persistent_id_len, 1); } /* Call the cb */ params[0] = &object; - params[1] = &pid_z; + params[1] = &pid_z_ptr; fci->params = params; fci->param_count = 2; @@ -336,7 +334,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name)); return 0; } - zval_ptr_dtor(&pid_z); + zval_dtor(pid_z_ptr); if (retval_ptr) { zval_ptr_dtor(&retval_ptr); @@ -378,7 +376,6 @@ static PHP_METHOD(Memcached, __construct) plist_key_len += 1; if (plist_key == NULL) { - efree(plist_key); php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate persistent list handler"); /* not reached */ } @@ -421,7 +418,12 @@ static PHP_METHOD(Memcached, __construct) if (plist_key != NULL) { efree(plist_key); } - php_memc_destroy(m_obj, is_persistent TSRMLS_CC); + + i_obj->obj = NULL; + if (is_persistent) { + php_memc_destroy(m_obj, is_persistent TSRMLS_CC); + } + return; } } @@ -439,6 +441,7 @@ static PHP_METHOD(Memcached, __construct) } } } + if (plist_key != NULL) { efree(plist_key); } diff --git a/tests/callback_exception_2.phpt b/tests/callback_exception_2.phpt new file mode 100644 index 00000000..8f945068 --- /dev/null +++ b/tests/callback_exception_2.phpt @@ -0,0 +1,54 @@ +--TEST-- +Callback initializer throws and dies +--SKIPIF-- + +--FILE-- +isPersistent()); + throw new RuntimeException('Cb exception'); +} + +function init_cb_die($m, $id) { + echo "ran quitting cb\n"; + die("quit in cb"); +} + +error_reporting(0); + +echo "cb with exception\n"; +try { + $m1 = new Memcached(null, 'init_cb'); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} + +echo "cb persistent with exception\n"; +try { + $m2 = new Memcached('foo', 'init_cb'); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} + +echo "cb persistent dies\n"; +try { + $m3 = new Memcached('bar', 'init_cb_die'); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} +echo "not run\n"; + +--EXPECT-- +cb with exception +ran throwing cb +bool(false) +Cb exception +cb persistent with exception +ran throwing cb +bool(true) +Cb exception +cb persistent dies +ran quitting cb +quit in cb diff --git a/tests/invoke_callback_2.phpt b/tests/invoke_callback_2.phpt new file mode 100644 index 00000000..276d1c26 --- /dev/null +++ b/tests/invoke_callback_2.phpt @@ -0,0 +1,88 @@ +--TEST-- +Use callback initializer +--SKIPIF-- + +--FILE-- +isPersistent()); + var_dump($id); +} + +function init_cb_fail($m, $id) { + echo "configured, should not be called.\n"; +} + +function init_cb_arg($m, $id, $arg) { + var_dump($id); + var_dump($arg); +} + +function init_nopersist_cb($m, $id) { + var_dump($m->isPersistent()); + var_dump($id); +} + +class Foo extends Memcached { + function __construct($id = null) { + parent::__construct($id, array($this, 'init')); + } + + function init($obj, $id, $options) { + var_dump($this->isPristine()); + var_dump($this->isPersistent()); + var_dump($id); + } +} + +error_reporting(0); + +echo "cb call\n"; +$m1 = new Memcached('foo1', 'init_cb'); + +echo "cb not run\n"; +$m1 = new Memcached('foo1', 'init_cb_fail'); + +echo "cb arg without arg\n"; +$m1 = new Memcached('foo3', 'init_cb_arg'); +echo $php_errormsg, "\n"; + +echo "cb arg not persistent\n"; +$m1 = new Memcached(null, 'init_nopersist_cb'); + +echo "cb in object\n"; +$m1 = new Foo(); + +echo "cb persistent in object\n"; +$m1 = new Foo('baz'); + +echo "cb second persistent in object\n"; +$m1 = new Foo('baz'); + +--EXPECT-- +cb call +string(9) "Memcached" +bool(true) +string(4) "foo1" +cb not run +cb arg without arg +string(4) "foo3" +NULL + +cb arg not persistent +bool(false) +NULL +cb in object +bool(true) +bool(false) +NULL +cb persistent in object +bool(true) +bool(true) +string(3) "baz" +cb second persistent in object From 0399e8b59e5717882fb012fbd0144ce43c016d99 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 17 Jan 2011 05:21:19 -0500 Subject: [PATCH 023/694] Fixed incorrect fastlz directory creation --- config.m4 | 3 --- 1 file changed, 3 deletions(-) diff --git a/config.m4 b/config.m4 index 77f00cc2..b5b0c79d 100644 --- a/config.m4 +++ b/config.m4 @@ -65,9 +65,6 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([memcached support requires ZLIB. Use --with-zlib-dir= to specify the prefix where ZLIB headers and library are located]) fi - dnl add FastLZ - PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) - if test "$PHP_MEMCACHED_SESSION" != "no"; then AC_MSG_CHECKING([for session includes]) session_inc_path="" From f584126d2cecd6333d4b6ad63adef34342b0e30d Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 17 Jan 2011 05:22:26 -0500 Subject: [PATCH 024/694] Normalize HAVE_MEMCACHED_SESSION checks --- php_memcached.c | 8 ++++---- php_memcached.h | 2 +- php_memcached_session.c | 2 +- php_memcached_session.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6092b32b..1b7fcf39 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -272,7 +272,7 @@ static PHP_INI_MH(OnUpdateSerializer) /* {{{ INI entries */ PHP_INI_BEGIN() -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) @@ -2721,7 +2721,7 @@ static int php_memc_list_entry(void) static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) { -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION MEMC_G(sess_locking_enabled) = 1; MEMC_G(sess_prefix) = NULL; MEMC_G(sess_lock_wait) = 0; @@ -3427,7 +3427,7 @@ PHP_MINIT_FUNCTION(memcached) php_memc_init_globals(&php_memcached_globals TSRMLS_CC); #endif -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION php_session_register_module(ps_memcached_ptr); #endif @@ -3459,7 +3459,7 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION php_info_print_table_row(2, "Session support", "yes"); #else php_info_print_table_row(2, "Session support ", "no"); diff --git a/php_memcached.h b/php_memcached.h index e5a0c4cb..040dced2 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -52,7 +52,7 @@ enum memcached_serializer { #endif //HAVE_MEMCACHED_IGBINARY ZEND_BEGIN_MODULE_GLOBALS(php_memcached) -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION zend_bool sess_locking_enabled; long sess_lock_wait; char* sess_prefix; diff --git a/php_memcached_session.c b/php_memcached_session.c index 2c96e315..3a3f09c2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -19,7 +19,7 @@ #endif /* {{{ session support */ -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION #include #include diff --git a/php_memcached_session.h b/php_memcached_session.h index 941fe589..e5110366 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -18,7 +18,7 @@ #define PHP_MEMCACHED_SESSION_H /* session handler struct */ -#if HAVE_MEMCACHED_SESSION +#ifdef HAVE_MEMCACHED_SESSION #include "ext/session/php_session.h" extern ps_module ps_mod_memcached; From 14022a032a42b544720e2faac73b7c2a878a502f Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Tue, 18 Jan 2011 00:05:48 +0000 Subject: [PATCH 025/694] Fix build when building inside PHP source tree --- php_memcached_session.c | 9 --------- php_memcached_session.h | 5 +---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 2c96e315..779c8465 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -14,13 +14,6 @@ +----------------------------------------------------------------------+ */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* {{{ session support */ -#if HAVE_MEMCACHED_SESSION - #include #include #include @@ -225,6 +218,4 @@ PS_GC_FUNC(memcached) { return SUCCESS; } - -#endif /* }}} */ \ No newline at end of file diff --git a/php_memcached_session.h b/php_memcached_session.h index 941fe589..30ea1ef1 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -18,7 +18,6 @@ #define PHP_MEMCACHED_SESSION_H /* session handler struct */ -#if HAVE_MEMCACHED_SESSION #include "ext/session/php_session.h" extern ps_module ps_mod_memcached; @@ -33,6 +32,4 @@ PS_WRITE_FUNC(memcached); PS_DESTROY_FUNC(memcached); PS_GC_FUNC(memcached); -#endif - -#endif /* PHP_MEMCACHED_SESSION_H */ \ No newline at end of file +#endif /* PHP_MEMCACHED_SESSION_H */ From 03f5e260d47098cc2241e67e25d98207cea840c5 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Sun, 13 Feb 2011 12:00:08 +0000 Subject: [PATCH 026/694] Add the callback to list --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index a19417e8..a0179a9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ Version 2.0.0 * Add constants for libmemcached 0.37+: - Memcached::OPT_NUMBER_OF_REPLICAS - Memcached::OPT_RANDOMIZE_REPLICA_READ + * Add 'on_new' callback to constructor Version 1.0.1 ------------- From 29a6def6a7c99e124682c4f5e03269ac6a998f9d Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Sun, 13 Feb 2011 12:04:23 +0000 Subject: [PATCH 027/694] Release prep for 2.0.0b1 --- ChangeLog | 2 +- package.xml | 36 ++++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0179a9d..e953e239 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ memcached extension changelog -Version 2.0.0 +Version 2.0.0b1 ------------- * Change the return value for non-existing keys to be NULL rather than 'false', affects simple get only diff --git a/package.xml b/package.xml index 13c2a26e..7ef16ac1 100644 --- a/package.xml +++ b/package.xml @@ -15,22 +15,38 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2009-07-07 + 2011-02-11 - 2.0.0 - 2.0.0 + 2.0.0b1 + 2.0.0b1 - stable - stable + beta + beta 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). +- Change the return value for non-existing keys to be NULL rather than + 'false', affects simple get only +- Add fastlz library that provides better/faster payload compression +- Add configure switch to enable/disable JSON serialization support +- Add getAllKeys() method +- Add deleteMulti() and deleteMultiByKey() methods +- Add isPristine() and isPersistent() methods +- Add setOptions() method to set multiple options at once +- Add SERIALIZER_JSON_ARRAY type that decodes JSON payloads as arrays + instead of objects +- Add support for Unix domain socket connections +- Add memcached.compression_threshold INI setting +- Add memcached.compression_factor INI setting +- Add memcached.compression_type INI setting +- Implement a few speed optimizations +- Many bug fixes and memory leaks plugged +- Add several more tests +- Add constants for libmemcached 0.37+: + - Memcached::OPT_NUMBER_OF_REPLICAS + - Memcached::OPT_RANDOMIZE_REPLICA_READ +- Add 'on_new' callback to constructor From 2903870012a77612c676ef8a4ae225d22a7605ed Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 14:33:20 +0000 Subject: [PATCH 028/694] Missing #endif --- php_memcached_session.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.h b/php_memcached_session.h index cace188d..97fe2005 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -32,3 +32,5 @@ PS_READ_FUNC(memcached); PS_WRITE_FUNC(memcached); PS_DESTROY_FUNC(memcached); PS_GC_FUNC(memcached); + +#endif /* PHP_MEMCACHED_SESSION_H */ From 4acdf084c5212a3bdd2325f52a6dce8b067ed83e Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 14:33:51 +0000 Subject: [PATCH 029/694] Added SASL support --- config.m4 | 2 ++ php_memcached.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-- php_memcached.h | 12 ++++++++- 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index b5b0c79d..5cabd130 100644 --- a/config.m4 +++ b/config.m4 @@ -226,6 +226,8 @@ if test "$PHP_MEMCACHED" != "no"; then fi done fi + + AC_CHECK_HEADERS([sasl/sasl.h]) AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" = "no"; then diff --git a/php_memcached.c b/php_memcached.c index 1b7fcf39..beb72581 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -185,6 +185,9 @@ typedef struct { zend_bool compression; enum memcached_serializer serializer; enum memcached_compression_type compression_type; +#if HAVE_MEMCACHED_SASL + zend_bool has_sasl_data; +#endif } *obj; zend_bool is_persistent; @@ -282,6 +285,9 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.compression_threshold", "2000", PHP_INI_ALL, OnUpdateLong, compression_threshold, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.serializer", SERIALIZER_DEFAULT_NAME, PHP_INI_ALL, OnUpdateSerializer, serializer_name, zend_php_memcached_globals, php_memcached_globals) +#if HAVE_MEMCACHED_SASL + STD_PHP_INI_ENTRY("memcached.use_sasl", "0", PHP_INI_SYSTEM, OnUpdateBool, use_sasl, zend_php_memcached_globals, php_memcached_globals) +#endif PHP_INI_END() /* }}} */ @@ -2173,6 +2179,31 @@ static PHP_METHOD(Memcached, setOption) } /* }}} */ +#ifdef HAVE_MEMCACHED_SASL +/* {{{ Memcached::setSaslAuthData(string user, string pass) + Sets sasl credentials */ +static PHP_METHOD(Memcached, setSaslAuthData) +{ + MEMC_METHOD_INIT_VARS; + + char *user, *pass; + int user_len, pass_len, rc; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &user, &user_len, &pass, &pass_len) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL is only supported with binary protocol"); + RETURN_FALSE; + } + RETURN_BOOL(memcached_set_sasl_auth_data(m_obj->memc, user, pass)); +} +/* }}} */ +#endif /* HAVE_MEMCACHED_SASL */ + /* {{{ Memcached::getResultCode() Returns the result code from the last operation */ static PHP_METHOD(Memcached, getResultCode) @@ -2264,6 +2295,11 @@ static PHP_METHOD(Memcached, isPristine) /* {{{ constructor/destructor */ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC) { +#if HAVE_MEMCACHED_SASL + if (m_obj->has_sasl_data) { + memcached_destroy_sasl_auth_data(m_obj->memc); + } +#endif if (m_obj->memc) { memcached_free(m_obj->memc); } @@ -2734,6 +2770,9 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(compression_type) = NULL; MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; MEMC_G(compression_factor) = 1.30; +#if HAVE_MEMCACHED_SASL + MEMC_G(use_sasl) = 0; +#endif } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) @@ -3126,6 +3165,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) ZEND_ARG_INFO(0, option) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) + ZEND_ARG_INFO(0, username) + ZEND_ARG_INFO(0, password) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) ZEND_ARG_INFO(0, option) ZEND_ARG_INFO(0, value) @@ -3206,6 +3250,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setOption, arginfo_setOption) MEMC_ME(setOptions, arginfo_setOptions) + MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) + MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) { NULL, NULL, NULL } @@ -3290,6 +3336,12 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 0); #endif +#ifdef HAVE_MEMCACHED_SASL + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 1); +#else + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 0); +#endif + /* * libmemcached behavior options */ @@ -3366,7 +3418,11 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); - +#if HAVE_MEMCACHED_SASL + REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); + REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE); +#endif /* * Our result codes. */ @@ -3432,7 +3488,13 @@ PHP_MINIT_FUNCTION(memcached) #endif REGISTER_INI_ENTRIES(); - +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + if (sasl_client_init(NULL) != SASL_OK) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); + } + } +#endif return SUCCESS; } /* }}} */ @@ -3446,6 +3508,11 @@ PHP_MSHUTDOWN_FUNCTION(memcached) php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); #endif +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + sasl_done(); + } +#endif UNREGISTER_INI_ENTRIES(); return SUCCESS; } diff --git a/php_memcached.h b/php_memcached.h index 040dced2..01f3e8c3 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -49,7 +49,14 @@ enum memcached_serializer { #else #define SERIALIZER_DEFAULT SERIALIZER_PHP #define SERIALIZER_DEFAULT_NAME "php" -#endif //HAVE_MEMCACHED_IGBINARY +#endif /* HAVE_MEMCACHED_IGBINARY */ + +#if LIBMEMCACHED_WITH_SASL_SUPPORT +# if defined(HAVE_SASL_SASL_H) +# include +# define HAVE_MEMCACHED_SASL 1 +# endif +#endif ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #ifdef HAVE_MEMCACHED_SESSION @@ -68,6 +75,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) int compression_threshold; double compression_factor; +#if HAVE_MEMCACHED_SASL + bool use_sasl; +#endif ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); From d51debe2380f4281cfdf505bbd702ed0fb3ad5c5 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 15:05:38 +0000 Subject: [PATCH 030/694] Moved SASL client init to RINIT/RSHUTDOWN. Not sure how this interacts with persistent objects but it seems to work with php-cgi -T. --- php_memcached.c | 38 ++++++++++++++++++++++++-------------- php_memcached.h | 2 ++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index beb72581..9556fa69 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3288,8 +3288,8 @@ zend_module_entry memcached_module_entry = { NULL, PHP_MINIT(memcached), PHP_MSHUTDOWN(memcached), - NULL, - NULL, + PHP_RINIT(memcached), + PHP_RSHUTDOWN(memcached), PHP_MINFO(memcached), PHP_MEMCACHED_VERSION, STANDARD_MODULE_PROPERTIES @@ -3457,6 +3457,28 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) } /* }}} */ +PHP_RINIT_FUNCTION(memcached) +{ +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + if (sasl_client_init(NULL) != SASL_OK) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); + } + } +#endif + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(memcached) +{ +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + sasl_done(); + } +#endif + return SUCCESS; +} + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(memcached) { @@ -3488,13 +3510,6 @@ PHP_MINIT_FUNCTION(memcached) #endif REGISTER_INI_ENTRIES(); -#if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { - if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); - } - } -#endif return SUCCESS; } /* }}} */ @@ -3508,11 +3523,6 @@ PHP_MSHUTDOWN_FUNCTION(memcached) php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); #endif -#if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { - sasl_done(); - } -#endif UNREGISTER_INI_ENTRIES(); return SUCCESS; } diff --git a/php_memcached.h b/php_memcached.h index 01f3e8c3..f0471786 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -84,6 +84,8 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void); PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); +PHP_RINIT_FUNCTION(memcached); +PHP_RSHUTDOWN_FUNCTION(memcached); PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); From 84335d0633d96b241dca53d81bb0abddc02ad2ef Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 15:49:12 +0000 Subject: [PATCH 031/694] Update ChangeLog and package.xml --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 7ef16ac1..d3e6ced1 100644 --- a/package.xml +++ b/package.xml @@ -47,6 +47,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Memcached::OPT_NUMBER_OF_REPLICAS - Memcached::OPT_RANDOMIZE_REPLICA_READ - Add 'on_new' callback to constructor +- Add SASL support From 909f25097d740c2c469e8c8da32bd8a9d2426fe8 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 18:39:04 +0000 Subject: [PATCH 032/694] ChangeLog entry about SASL --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index e953e239..47bc18a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,7 @@ Version 2.0.0b1 - Memcached::OPT_NUMBER_OF_REPLICAS - Memcached::OPT_RANDOMIZE_REPLICA_READ * Add 'on_new' callback to constructor + * Add SASL support Version 1.0.1 ------------- From 7f91288c8de6b1fab5a9e3976b536dcbbeacef5b Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 25 Feb 2011 18:40:21 +0000 Subject: [PATCH 033/694] Trying to use cloned object causes segmentation fault --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 9556fa69..2a85bb21 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2331,6 +2331,7 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); retval.handlers = zend_get_std_object_handlers(); + retval.handlers->clone_obj = NULL; return retval; } From 3dc812e9650d45d25f5d441b9bd5c8a7f249a3f4 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Sat, 26 Feb 2011 22:50:15 +0000 Subject: [PATCH 034/694] Fix compile error if libmemcached is compiled without SASL or sasl/sasl.h is not found --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2a85bb21..ea5eea3f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3250,9 +3250,9 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getOption, arginfo_getOption) MEMC_ME(setOption, arginfo_setOption) MEMC_ME(setOptions, arginfo_setOptions) - +#ifdef HAVE_MEMCACHED_SASL MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) - +#endif MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) { NULL, NULL, NULL } From 3529c4d064f8bb14652b8d90dac493cd08eab7b1 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Sat, 26 Feb 2011 22:53:57 +0000 Subject: [PATCH 035/694] Add better error message when sasl headers are not found --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 5cabd130..b3009e0d 100644 --- a/config.m4 +++ b/config.m4 @@ -227,7 +227,7 @@ if test "$PHP_MEMCACHED" != "no"; then done fi - AC_CHECK_HEADERS([sasl/sasl.h]) + AC_CHECK_HEADERS([sasl/sasl.h], [], [AC_MSG_NOTICE([sasl/sasl.h not found. Not enabling SASL support])]) AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" = "no"; then From c169204931e224b842f1a15426175bc4fb8e27ac Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 4 Mar 2011 11:45:23 +0000 Subject: [PATCH 036/694] Add test for cloning --- tests/clone.phpt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/clone.phpt diff --git a/tests/clone.phpt b/tests/clone.phpt new file mode 100644 index 00000000..a0c49cd7 --- /dev/null +++ b/tests/clone.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test cloning +--SKIPIF-- + +--FILE-- + Date: Fri, 4 Mar 2011 11:46:02 +0000 Subject: [PATCH 037/694] Fix cloning --- php_memcached.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index ea5eea3f..3cadf1b1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -209,6 +209,8 @@ static int le_memc; static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; +static zend_object_handlers memcached_object_handlers; + struct callbackContext { zval *array; @@ -2330,8 +2332,7 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - retval.handlers->clone_obj = NULL; + retval.handlers = &memcached_object_handlers; return retval; } @@ -3485,6 +3486,9 @@ PHP_MINIT_FUNCTION(memcached) { zend_class_entry ce; + memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_object_handlers.clone_obj = NULL; + le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); From db63933d47ea319a57e3cfef922a338ec0ad06de Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 4 Mar 2011 11:46:38 +0000 Subject: [PATCH 038/694] Correct return type constant --- php_memcached.c | 2 +- tests/types.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3cadf1b1..0aee7f99 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3455,7 +3455,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) /* * Return value from simple get errors */ - REGISTER_MEMC_CLASS_CONST_NULL(GET_ERROR_RETURN_VALUE); + REGISTER_MEMC_CLASS_CONST_BOOL(GET_ERROR_RETURN_VALUE, 0); } /* }}} */ diff --git a/tests/types.phpt b/tests/types.phpt index 7ed8edf2..6574fd4d 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -59,9 +59,9 @@ foreach ($data as $types) { $m->flush(); -if ($m->get("sdfjhw38rwdenfoqu29eiajfroehr8jaiodfhjaoierhjadf") !== NULL) { +if (($actual = $m->get("sdfjhw38rwdenfoqu29eiajfroehr8jaiodfhjaoierhjadf")) !== false) { echo "Expected: null"; - echo "Actual: " . get_type($actual); + echo "Actual: " . gettype($actual); } echo "OK\n"; From d4d070b09928add54de4b24f9790630f8d26a4f3 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 6 Mar 2011 11:16:52 -0800 Subject: [PATCH 039/694] Fix whitespace. --- ChangeLog | 2 +- php_memcached.c | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47bc18a3..1d51f930 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ memcached extension changelog Version 2.0.0b1 -------------- +--------------- * Change the return value for non-existing keys to be NULL rather than 'false', affects simple get only * Add fastlz library that provides better/faster payload compression diff --git a/php_memcached.c b/php_memcached.c index 0aee7f99..bf3037c2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -324,28 +324,28 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc { zval pid_z; zval *retval_ptr, *pid_z_ptr = &pid_z; - zval **params[2]; - + zval **params[2]; + INIT_ZVAL(pid_z); if (persistent_id) { ZVAL_STRINGL(pid_z_ptr, persistent_id, persistent_id_len, 1); } - /* Call the cb */ + /* Call the cb */ params[0] = &object; params[1] = &pid_z_ptr; - + fci->params = params; fci->param_count = 2; fci->retval_ptr_ptr = &retval_ptr; fci->no_separation = 1; - + if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name)); return 0; } zval_dtor(pid_z_ptr); - + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } @@ -365,7 +365,7 @@ static PHP_METHOD(Memcached, __construct) char *plist_key = NULL; int plist_key_len = 0; - + zend_fcall_info fci; zend_fcall_info_cache fci_cache; @@ -397,9 +397,9 @@ static PHP_METHOD(Memcached, __construct) } i_obj->obj = m_obj; } - + i_obj->is_persistent = is_persistent; - + if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); if (m_obj == NULL) { @@ -418,7 +418,7 @@ static PHP_METHOD(Memcached, __construct) m_obj->serializer = MEMC_G(serializer); m_obj->compression_type = MEMC_G(compression_type_real); m_obj->compression = 1; - + i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -707,13 +707,13 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_hash_move_forward(Z_ARRVAL_P(keys))) { if (Z_TYPE_PP(entry) != IS_STRING) { - convert_to_string_ex(entry); + convert_to_string_ex(entry); } if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { mkeys[i] = Z_STRVAL_PP(entry); mkeys_len[i] = Z_STRLEN_PP(entry); - + if (preserve_order) { add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i] + 1); } @@ -1569,11 +1569,11 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(entries))) { - + if (Z_TYPE_PP(entry) != IS_STRING) { convert_to_string_ex(entry); } - + if (Z_STRLEN_PP(entry) == 0) { continue; } @@ -2107,7 +2107,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML convert_to_long(value); if (flag < 0 || /* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 flag >= MEMCACHED_BEHAVIOR_MAX || #endif memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { @@ -2297,7 +2297,7 @@ static PHP_METHOD(Memcached, isPristine) /* {{{ constructor/destructor */ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC) { -#if HAVE_MEMCACHED_SASL +#if HAVE_MEMCACHED_SASL if (m_obj->has_sasl_data) { memcached_destroy_sasl_auth_data(m_obj->memc); } From a11099d4b023d251c1d25fe87eb3f91778904fa4 Mon Sep 17 00:00:00 2001 From: Mikko Koppanen Date: Fri, 11 Mar 2011 17:32:35 +0000 Subject: [PATCH 040/694] AC_MSG_NOTICE is causing issues --- config.m4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index b3009e0d..0c999eab 100644 --- a/config.m4 +++ b/config.m4 @@ -227,7 +227,9 @@ if test "$PHP_MEMCACHED" != "no"; then done fi - AC_CHECK_HEADERS([sasl/sasl.h], [], [AC_MSG_NOTICE([sasl/sasl.h not found. Not enabling SASL support])]) + AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) + AC_MSG_CHECKING([whether to enable sasl support]) + AC_MSG_RESULT([$memcached_enable_sasl]) AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" = "no"; then From d4dc15057564387d99933e99e059b9d7fe8b5a8b Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sat, 12 Mar 2011 14:55:39 -0500 Subject: [PATCH 041/694] Fix globals declaration. --- php_memcached_session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 779c8465..9b013529 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -35,7 +35,7 @@ #include "php_memcached.h" #include "php_memcached_session.h" -ZEND_DECLARE_MODULE_GLOBALS(php_memcached) +extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 #define MEMC_SESS_LOCK_EXPIRATION 30 @@ -218,4 +218,4 @@ PS_GC_FUNC(memcached) { return SUCCESS; } -/* }}} */ \ No newline at end of file +/* }}} */ From bd98d12fec8aa78e1691123a7c5e3e171795a99f Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sat, 12 Mar 2011 14:55:53 -0500 Subject: [PATCH 042/694] Release 2.0.0b1. --- ChangeLog | 4 ++-- package.xml | 54 ++++++++++++++++++++++++++++++++++++++++++++++--- php_memcached.h | 2 +- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d51f930..387e7361 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,8 +22,8 @@ Version 2.0.0b1 * Add constants for libmemcached 0.37+: - Memcached::OPT_NUMBER_OF_REPLICAS - Memcached::OPT_RANDOMIZE_REPLICA_READ - * Add 'on_new' callback to constructor - * Add SASL support + * Add 'on_new' callback to constructor + * Add SASL support Version 1.0.1 ------------- diff --git a/package.xml b/package.xml index d3e6ced1..5047c961 100644 --- a/package.xml +++ b/package.xml @@ -15,7 +15,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2011-02-11 + 2011-03-12 2.0.0b1 2.0.0b1 @@ -44,8 +44,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Many bug fixes and memory leaks plugged - Add several more tests - Add constants for libmemcached 0.37+: - - Memcached::OPT_NUMBER_OF_REPLICAS - - Memcached::OPT_RANDOMIZE_REPLICA_READ + * Memcached::OPT_NUMBER_OF_REPLICAS + * Memcached::OPT_RANDOMIZE_REPLICA_READ - Add 'on_new' callback to constructor - Add SASL support @@ -83,6 +83,54 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached + + betabeta + 2.0.0b12.0.0b1 + 2011-03-12 + +- Change the return value for non-existing keys to be NULL rather than + 'false', affects simple get only +- Add fastlz library that provides better/faster payload compression +- Add configure switch to enable/disable JSON serialization support +- Add getAllKeys() method +- Add deleteMulti() and deleteMultiByKey() methods +- Add isPristine() and isPersistent() methods +- Add setOptions() method to set multiple options at once +- Add SERIALIZER_JSON_ARRAY type that decodes JSON payloads as arrays + instead of objects +- Add support for Unix domain socket connections +- Add memcached.compression_threshold INI setting +- Add memcached.compression_factor INI setting +- Add memcached.compression_type INI setting +- Implement a few speed optimizations +- Many bug fixes and memory leaks plugged +- Add several more tests +- Add constants for libmemcached 0.37+: + * Memcached::OPT_NUMBER_OF_REPLICAS + * Memcached::OPT_RANDOMIZE_REPLICA_READ +- Add 'on_new' callback to constructor +- Add SASL support + + + + + 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.h b/php_memcached.h index f0471786..f9fbc486 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -90,7 +90,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0-dev" +#define PHP_MEMCACHED_VERSION "2.0.0b1" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From ee7a6ec76ebf10edeece4c58f0d30203436ec8dc Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 13 Mar 2011 14:40:19 -0400 Subject: [PATCH 043/694] Back to -dev. --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index f9fbc486..f0471786 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -90,7 +90,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0b1" +#define PHP_MEMCACHED_VERSION "2.0.0-dev" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From efbad3bd7f24ca6afe1b7f825f790f4d93bf85b1 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 20 Mar 2011 10:28:38 -0700 Subject: [PATCH 044/694] Loop in locking only if MEMCACHED_NOTSTORED is returned. --- php_memcached_session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 9b013529..91910271 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -73,6 +73,8 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) MEMC_G(sess_lock_key) = lock_key; MEMC_G(sess_lock_key_len) = lock_key_len; return 0; + } else if (status != MEMCACHED_NOTSTORED) { + break; } if (lock_wait > 0) { From f63ae8f713a30dbe116d16766bb5a721ccd35ddd Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 20 Mar 2011 10:29:01 -0700 Subject: [PATCH 045/694] Check for invalid (too long) session IDs. --- php_memcached_session.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 91910271..5ff7a75e 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -44,6 +44,26 @@ ps_module ps_mod_memcached = { PS_MOD(memcached) }; +/* + * Stolen from libmemcached/common.h, because we need it and they don't expose it. + */ +static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) +{ + if (key_length == 0) + return MEMCACHED_BAD_KEY_PROVIDED; + + if (binary) + { + if (key_length > 0xffff) + return MEMCACHED_BAD_KEY_PROVIDED; + } else { + if (key_length >= MEMCACHED_MAX_KEY) + return MEMCACHED_BAD_KEY_PROVIDED; + } + + return MEMCACHED_SUCCESS; +} + static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) { char *lock_key = NULL; @@ -157,6 +177,13 @@ PS_READ_FUNC(memcached) uint32_t flags = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); + size_t key_length = strlen(key); + + if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + PS(invalid_session_id) = 1; + return FAILURE; + } if (MEMC_G(sess_locking_enabled)) { if (php_memc_sess_lock(memc_sess, key TSRMLS_CC) < 0) { @@ -185,6 +212,13 @@ PS_WRITE_FUNC(memcached) time_t expiration = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); + size_t key_length = strlen(key); + + if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + PS(invalid_session_id) = 1; + return FAILURE; + } sess_key_len = spprintf(&sess_key, 0, "%s", key); if (PS(gc_maxlifetime) > 0) { From b743f4c53251627c9a496524ec96cfbe6dd6f608 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 20 Mar 2011 11:02:42 -0700 Subject: [PATCH 046/694] Account for session key prefix when calculating length. --- php_memcached_session.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 5ff7a75e..934c5a95 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -177,8 +177,9 @@ PS_READ_FUNC(memcached) uint32_t flags = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); - size_t key_length = strlen(key); + size_t key_length; + key_length = strlen(MEMC_G(sess_prefix)) + strlen(key) + 5; // prefix + "lock." if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; @@ -212,8 +213,9 @@ PS_WRITE_FUNC(memcached) time_t expiration = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); - size_t key_length = strlen(key); + size_t key_length; + key_length = strlen(MEMC_G(sess_prefix)) + strlen(key) + 5; // prefix + "lock." if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; From d11f8dfa9a687c767fe10d4bf96cd1e1137d3da0 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 20 Mar 2011 11:05:42 -0700 Subject: [PATCH 047/694] Fix a case where invalid session ID could lock the script. --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 387e7361..8c87b44d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ memcached extension changelog +Version ******* +--------------- + * Fix a case where invalid session ID could lock the script. + Version 2.0.0b1 --------------- * Change the return value for non-existing keys to be NULL rather than From 7deb03e79b87d0e174e60d1ae9d11b3d06ad5b14 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 27 Mar 2011 17:41:10 -0700 Subject: [PATCH 048/694] Remove erroneous RETURN_FALSE. --- php_memcached.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index bf3037c2..73b367d9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -565,7 +565,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* if we have a callback, all processing is done */ if (fci.size != 0) { memcached_result_free(&result); - RETURN_FALSE; + return; } } @@ -585,8 +585,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_result_free(&result); - RETURN_FALSE; - } else { int rc; zend_bool return_value_set = 0; From 445d4723a9ce1b8fc3734cc5514cdb0fafa02156 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Wed, 20 Apr 2011 11:14:02 -0400 Subject: [PATCH 049/694] Fix ZTS --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 73b367d9..306299e9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -320,7 +320,7 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS Method implementations ****************************************/ -static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len) +static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len TSRMLS_DC) { zval pid_z; zval *retval_ptr, *pid_z_ptr = &pid_z; @@ -423,7 +423,7 @@ static PHP_METHOD(Memcached, __construct) i_obj->is_pristine = 1; if (ZEND_NUM_ARGS() >= 2) { - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len) || EG(exception)) { + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len TSRMLS_CC) || EG(exception)) { /* error calling or exception thrown from callback */ if (plist_key != NULL) { efree(plist_key); From 5beaeedefe5c1eea6d637e3eeeeaf0957a5660ac Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Fri, 21 May 2010 17:23:45 +0300 Subject: [PATCH 050/694] Fix igbinary ZTS build. --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 306299e9..209a7f34 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2496,7 +2496,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t switch (serializer) { #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf.c, &buf.len, value) != 0) { + if (igbinary_serialize((uint8_t **) &buf.c, &buf.len, value TSRMLS_CC) != 0) { smart_str_free(&buf); return NULL; } @@ -2708,7 +2708,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value)) { + if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); goto my_error; From 51bb53a409a6a8e8c0a90ba4056d7e556231f5ec Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 18 May 2010 21:12:44 +0300 Subject: [PATCH 051/694] Add large float. --- tests/types.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/types.phpt b/tests/types.phpt index 6574fd4d..95c5ceff 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -22,6 +22,7 @@ $data = array( array('integer_zero_integer', 0), array('float_positive1', 3.912131), + array('float_positive2', 1.2131E+501), array('float_positive2', 1.2131E+52), array('float_negative', -42.123312), array('float_zero', 0.0), @@ -68,4 +69,4 @@ echo "OK\n"; ?> --EXPECT-- -OK \ No newline at end of file +OK From 895515a9683d0e2553050bd0aa06bf2cc3abea9b Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 18 May 2010 21:13:19 +0300 Subject: [PATCH 052/694] Fix tests. --- tests/experimental/getmulti_badserver.phpt | 10 ++++++++-- tests/experimental/getmulti_partial_error.phpt | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/experimental/getmulti_badserver.phpt b/tests/experimental/getmulti_badserver.phpt index 5c8f1179..3e6bf402 100644 --- a/tests/experimental/getmulti_badserver.phpt +++ b/tests/experimental/getmulti_badserver.phpt @@ -11,7 +11,14 @@ echo $m->getResultMessage(), "\n"; $m->addServer('localhost', 37712, 1); var_dump($m->getMulti(array('foo', 'bar'))); -echo $m->getResultMessage(), "\n"; +switch ($m->getResultCode()) { + case Memcached::RES_ERRNO: + case Memcached::RES_SOME_ERRORS: + break; + default: + echo $m->getResultCode(), ": "; + echo $m->getResultMessage(), "\n"; +} --EXPECT-- array(0) { @@ -19,4 +26,3 @@ array(0) { NO SERVERS DEFINED array(0) { } -SYSTEM ERROR diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/experimental/getmulti_partial_error.phpt index 97f079a1..dc4daa50 100644 --- a/tests/experimental/getmulti_partial_error.phpt +++ b/tests/experimental/getmulti_partial_error.phpt @@ -1,7 +1,6 @@ --TEST-- Memcached::getMulti() partial error --SKIPIF-- ---XFAIL-- --FILE-- deleteMulti(array("key1", "key2"))) == 2); $v = $m->getMulti(array_keys($data)); var_dump(is_array($v)); var_dump(count($v) < count($data)); -var_dump($m->getResultCode() == Memcached::RES_SUCCESS); +var_dump($m->getResultCode() == Memcached::RES_SUCCESS || + $m->getResultCode() == Memcached::RES_SOME_ERRORS); --EXPECT-- bool(true) bool(true) bool(true) bool(true) -bool(false) +bool(true) From 55628f22b1a44177a45e81c6536014ef1704f4e2 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Wed, 19 May 2010 18:51:14 +0300 Subject: [PATCH 053/694] New float tests: "ignore locale" and large/small. --- tests/experimental/extreme_floats.phpt | 29 ++++++++++++++++++++++++++ tests/experimental/locale_float.phpt | 23 ++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/experimental/extreme_floats.phpt create mode 100644 tests/experimental/locale_float.phpt diff --git a/tests/experimental/extreme_floats.phpt b/tests/experimental/extreme_floats.phpt new file mode 100644 index 00000000..0d530370 --- /dev/null +++ b/tests/experimental/extreme_floats.phpt @@ -0,0 +1,29 @@ +--TEST-- +Extreme floats: max, min, Inf, -Inf, and NaN +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211, 1); + +$m->set('float_inf', INF); +$m->set('float_ninf', -INF); +$m->set('float_nan', NAN); +$m->set('float_big', -1.79769e308); +$m->set('float_small', -2.225e-308); +$m->set('float_subsmall', -4.9406564584125e-324); +var_dump($m->get('float_inf')); +var_dump($m->get('float_ninf')); +var_dump($m->get('float_nan')); +var_dump($m->get('float_big')); +var_dump($m->get('float_small')); +var_dump($m->get('float_subsmall')); + +--EXPECT-- +float(INF) +float(-INF) +float(NAN) +float(-1.79769E+308) +float(-2.225E-308) +float(-4.9406564584125E-324) diff --git a/tests/experimental/locale_float.phpt b/tests/experimental/locale_float.phpt new file mode 100644 index 00000000..e6967bdb --- /dev/null +++ b/tests/experimental/locale_float.phpt @@ -0,0 +1,23 @@ +--TEST-- +Float should not consider locale +--SKIPIF-- +addServer('127.0.0.1', 11211); + +setlocale(LC_NUMERIC, + "fi_FI", 'sv_SV', 'nl_NL'); +var_dump($memcache->set('test', 13882.1332451)); +$n = $memcache->get('test'); +setlocale(LC_NUMERIC, "C"); +var_dump($n); + +--EXPECT-- +bool(true) +float(13882.1332451) From dc47bf7092e9d02930acc11d3ebeb8e0808ca4fd Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 14 Sep 2010 23:34:31 +0300 Subject: [PATCH 054/694] Fix PECL Bug #18639, double free in getServerByKey. Bug report and fix, courtesy of Kevin Bowman. --- php_memcached.c | 7 ++++++- tests/bug_18639.phpt | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/bug_18639.phpt diff --git a/php_memcached.c b/php_memcached.c index 209a7f34..db549814 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1823,7 +1823,12 @@ PHP_METHOD(Memcached, getServerByKey) add_assoc_string(return_value, "host", server->hostname, 1); add_assoc_long(return_value, "port", server->port); add_assoc_long(return_value, "weight", server->weight); - memcached_server_free(server); + + /* memcached_server_add(3) states that the server instance is cloned. */ + /* In actuality it is not, possibly a bug in libmemcached 0.40. */ + /* remove server freeing */ + + /* memcached_server_free(server); */ } /* }}} */ diff --git a/tests/bug_18639.phpt b/tests/bug_18639.phpt new file mode 100644 index 00000000..9deb7492 --- /dev/null +++ b/tests/bug_18639.phpt @@ -0,0 +1,23 @@ +--TEST-- +Memcached::getServerByKey(): Bug pecl#18639 (Segfault in getServerByKet) +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211); +var_dump($m->set('test', 'test1')); +var_dump($m->getServerByKey('1')); + +--EXPECTF-- +bool(true) +array(3) { + ["host"]=> + string(9) "127.0.0.1" + ["port"]=> + int(11211) + ["weight"]=> + int(0) +} From de487fffa808d83c206444de390043ec1a613577 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Fri, 21 May 2010 19:32:07 +0300 Subject: [PATCH 055/694] Tweak test, skip instead of FAIL. --- .../serializer/serializer_php_bad_serialize.phpt | 11 +++++++++-- .../serializer/serializer_php_bad_unserialize.phpt | 6 +++++- tests/experimental/set_badserialize.phpt | 1 - tests/experimental/setmulti_badserialize.phpt | 1 - 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/experimental/serializer/serializer_php_bad_serialize.phpt b/tests/experimental/serializer/serializer_php_bad_serialize.phpt index 0976f980..39ef4745 100644 --- a/tests/experimental/serializer/serializer_php_bad_serialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_serialize.phpt @@ -1,8 +1,15 @@ --TEST-- Serializer: exception while serializing ---XFAIL-- --SKIPIF-- - + + --FILE-- --FILE-- From 3f73789da7a3bc07c17cf2447d9d7be905c736b9 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 2 May 2011 14:35:07 -0700 Subject: [PATCH 056/694] Fix error code reading for libmemcached-0.49. --- php_memcached.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 73b367d9..8e8fb5c4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2441,15 +2441,23 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM case MEMCACHED_SOME_ERRORS: i_obj->rescode = status; - /* Hnngghgh! */ - i_obj->memc_errno = i_obj->obj->memc->cached_errno; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 + i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); +#else + i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ + +#endif result = 0; break; default: i_obj->rescode = status; - /* Hnngghgh! */ - i_obj->memc_errno = i_obj->obj->memc->cached_errno; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 + i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); +#else + i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ + +#endif result = -1; break; } @@ -3383,6 +3391,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ); #endif +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 + REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); +#endif /* * libmemcached result codes From e60e02eaf97bf3261a1a5b298fad70efb8919d3e Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 00:37:09 +0300 Subject: [PATCH 057/694] Test cleanup. --- .gitignore | 3 +++ tests/experimental/append.phpt | 2 +- tests/experimental/cachecallback.phpt | 2 +- tests/experimental/delete_bykey.phpt | 2 +- tests/experimental/get.phpt | 6 +++--- tests/experimental/get_bykey.phpt | 2 +- tests/experimental/get_bykey_cas.phpt | 4 ++-- tests/experimental/incrdecr.phpt | 2 +- tests/experimental/moduleinfo.phpt | 1 + tests/experimental/prepend.phpt | 2 +- tests/experimental/replace.phpt | 2 +- tests/experimental/replace_bykey.phpt | 2 +- tests/experimental/stats_badserver.phpt | 2 +- 13 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 73f67b6f..bc9d558c 100644 --- a/.gitignore +++ b/.gitignore @@ -53,16 +53,19 @@ tests/*.out tests/*.diff tests/*.php tests/*.exp +tests/*.sh tests/*/*.log tests/*/*.mem tests/*/*.out tests/*/*.diff tests/*/*.php tests/*/*.exp +tests/*/*.sh tests/*/*/*.log tests/*/*/*.mem tests/*/*/*.out tests/*/*/*.diff tests/*/*/*.php tests/*/*/*.exp +tests/*/*/*.sh tmp-php.ini diff --git a/tests/experimental/append.phpt b/tests/experimental/append.phpt index f6f8b296..02c30b4f 100644 --- a/tests/experimental/append.phpt +++ b/tests/experimental/append.phpt @@ -25,6 +25,6 @@ var_dump($m->get('foo')); NULL %s: cannot append/prepend with compression turned on bool(false) -NULL +bool(false) bool(true) string(2) "ab" diff --git a/tests/experimental/cachecallback.phpt b/tests/experimental/cachecallback.phpt index f1b6be97..ece92b89 100644 --- a/tests/experimental/cachecallback.phpt +++ b/tests/experimental/cachecallback.phpt @@ -59,7 +59,7 @@ Exception in callback Miss string(3) "foo" NULL -NULL +bool(false) Miss string(3) "foo" NULL diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 1face456..e1b28472 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -29,7 +29,7 @@ bool(true) SUCCESS bool(false) NOT FOUND -NULL +bool(false) bool(false) A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) diff --git a/tests/experimental/get.phpt b/tests/experimental/get.phpt index 1f295619..34537fc4 100644 --- a/tests/experimental/get.phpt +++ b/tests/experimental/get.phpt @@ -23,11 +23,11 @@ $m->delete('foo'); var_dump($m->get(' � foo jkh a s ���')); echo $m->getResultMessage(), "\n"; --EXPECT-- -NULL +bool(false) NOT FOUND -NULL +bool(false) A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE string(4) "asdf" SUCCESS -NULL +bool(false) NOT FOUND diff --git a/tests/experimental/get_bykey.phpt b/tests/experimental/get_bykey.phpt index 63ca26c7..220dd44a 100644 --- a/tests/experimental/get_bykey.phpt +++ b/tests/experimental/get_bykey.phpt @@ -30,5 +30,5 @@ int(1) SUCCESS string(4) "asdf" SUCCESS -NULL +bool(false) NOT FOUND diff --git a/tests/experimental/get_bykey_cas.phpt b/tests/experimental/get_bykey_cas.phpt index df94373c..ad94013e 100644 --- a/tests/experimental/get_bykey_cas.phpt +++ b/tests/experimental/get_bykey_cas.phpt @@ -58,10 +58,10 @@ SUCCESS string(4) "asdf" float(%d) SUCCESS -NULL +bool(false) NULL NOT FOUND -NULL +bool(false) NULL A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE called diff --git a/tests/experimental/incrdecr.phpt b/tests/experimental/incrdecr.phpt index 4611a3e7..b38e3813 100644 --- a/tests/experimental/incrdecr.phpt +++ b/tests/experimental/incrdecr.phpt @@ -38,7 +38,7 @@ var_dump($m->get('foo')); Not there bool(false) bool(false) -NULL +bool(false) Normal int(1) int(2) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 3e790a6f..a7eab08d 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -26,3 +26,4 @@ memcached.serializer => %s => %s memcached.sess_lock_wait => %d => %d memcached.sess_locking => %d => %d memcached.sess_prefix => %s => %s +memcached.use_sasl => %s => %s diff --git a/tests/experimental/prepend.phpt b/tests/experimental/prepend.phpt index 1dd24ec9..141468b1 100644 --- a/tests/experimental/prepend.phpt +++ b/tests/experimental/prepend.phpt @@ -25,6 +25,6 @@ var_dump($m->get('foo')); NULL %s: cannot append/prepend with compression turned on bool(false) -NULL +bool(false) bool(true) string(2) "ba" diff --git a/tests/experimental/replace.phpt b/tests/experimental/replace.phpt index 7c6db455..dcf78a46 100644 --- a/tests/experimental/replace.phpt +++ b/tests/experimental/replace.phpt @@ -20,6 +20,6 @@ var_dump($m->get('foo')); --EXPECTF-- bool(false) -NULL +bool(false) bool(true) string(3) "bar" diff --git a/tests/experimental/replace_bykey.phpt b/tests/experimental/replace_bykey.phpt index 67acfb38..1cd858fb 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/experimental/replace_bykey.phpt @@ -22,6 +22,6 @@ var_dump($m->getByKey('kef', 'foo')); bool(false) %rNOT STORED|NOT FOUND%r -NULL +bool(false) bool(true) string(3) "bar" diff --git a/tests/experimental/stats_badserver.phpt b/tests/experimental/stats_badserver.phpt index d0ed189e..262010c9 100644 --- a/tests/experimental/stats_badserver.phpt +++ b/tests/experimental/stats_badserver.phpt @@ -28,6 +28,6 @@ SUCCESS array(0) { } SOME ERRORS WERE REPORTED -int(1) +int(2) bool(true) int(%d) From 9a3142d3ad6828368e13ce22f94705ebc946fa69 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 2 May 2011 14:38:00 -0700 Subject: [PATCH 058/694] Update Changelog. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8c87b44d..2e338846 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ memcached extension changelog Version ******* --------------- + * Add OPT_REMOVE_FAILED_SERVERS option. + * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. Version 2.0.0b1 From 37e46ecd52e3cae1d9815a25a75883707a6f57c8 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 01:09:59 +0300 Subject: [PATCH 059/694] Skip stats call when configuration lacks servers. --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index db549814..60064afa 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1849,6 +1849,11 @@ PHP_METHOD(Memcached, getStats) MEMC_METHOD_FETCH_OBJECT; + if (memcached_server_count(m_obj->memc) == 0) { + array_init(return_value); + return; + } + stats = memcached_stat(m_obj->memc, NULL, &status); php_memc_handle_error(i_obj, status TSRMLS_CC); if (stats == NULL) { From df20b8a3c8ea1a565657764020b50a6d9bc7805c Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 01:33:15 +0300 Subject: [PATCH 060/694] Convert float to ascii using g_fmt and zend_dtoa. This procudes much smaller textual representations and also ignores locales. --- config.m4 | 2 +- g_fmt.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ g_fmt.h | 34 +++++++++++++++++ php_memcached.c | 46 +++++++++++++---------- 4 files changed, 161 insertions(+), 20 deletions(-) create mode 100644 g_fmt.c create mode 100644 g_fmt.h diff --git a/config.m4 b/config.m4 index 0c999eab..278553a4 100644 --- a/config.m4 +++ b/config.m4 @@ -242,7 +242,7 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_SUBST(MEMCACHED_SHARED_LIBADD) - PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c" + PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" diff --git a/g_fmt.c b/g_fmt.c new file mode 100644 index 00000000..c904e653 --- /dev/null +++ b/g_fmt.c @@ -0,0 +1,99 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 1996 by Lucent Technologies. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* g_fmt(buf,x) stores the closest decimal approximation to x in buf; + * it suffices to declare buf + * char buf[32]; + */ + +/* Modified for use with php in the memcached client extension. + * + * // Teddy Grenman , 2010-05-18. + */ + +#include + +char *php_memcached_g_fmt(register char *b, double x) { + register int i, k; + register char *s; + int decpt, j, sign; + char *b0, *s0, *se; + + b0 = b; +#ifdef IGNORE_ZERO_SIGN + if (!x) { + *b++ = '0'; + *b = 0; + goto done; + } +#endif + + s = s0 = zend_dtoa(x, 0, 0, &decpt, &sign, &se); + if (sign) + *b++ = '-'; + if (decpt == 9999) /* Infinity or Nan */ { + while(*b++ = *s++); + goto done0; + } + if (decpt <= -4 || decpt > se - s + 5) { + *b++ = *s++; + if (*s) { + *b++ = '.'; + while(*b = *s++) + b++; + } + *b++ = 'e'; + /* sprintf(b, "%+.2d", decpt - 1); */ + if (--decpt < 0) { + *b++ = '-'; + decpt = -decpt; + } + else + *b++ = '+'; + for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10); + for(;;) { + i = decpt / k; + *b++ = i + '0'; + if (--j <= 0) + break; + decpt -= i*k; + decpt *= 10; + } + *b = 0; + } else if (decpt <= 0) { + *b++ = '.'; + for(; decpt < 0; decpt++) + *b++ = '0'; + while(*b++ = *s++); + } else { + while(*b = *s++) { + b++; + if (--decpt == 0 && *s) + *b++ = '.'; + } + for(; decpt > 0; decpt--) + *b++ = '0'; + *b = 0; + } + + done0: + zend_freedtoa(s0); + done: + return b0; +} diff --git a/g_fmt.h b/g_fmt.h new file mode 100644 index 00000000..75ad8ce7 --- /dev/null +++ b/g_fmt.h @@ -0,0 +1,34 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 1996 by Lucent Technologies. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* g_fmt(buf,x) stores the closest decimal approximation to x in buf; + * it suffices to declare buf + * char buf[32]; + */ + +/* Modified for use with php in the memcached client + * extension by Teddy Grenman, 2010. + */ + +#ifndef MEMC_G_FMT_H +#define MEMC_G_FMT_H + +char *php_memcached_g_fmt(register char *b, double x); + +#endif diff --git a/php_memcached.c b/php_memcached.c index 60064afa..1bdba72d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -42,9 +42,11 @@ #include #include #include +#include #include #include "php_memcached.h" +#include "g_fmt.h" #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" @@ -2480,27 +2482,28 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t break; case IS_LONG: + smart_str_append_long(&buf, Z_LVAL_P(value)); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + break; + case IS_DOUBLE: - case IS_BOOL: { - zval value_copy; + char dstr[40] = {0}; - value_copy = *value; - zval_copy_ctor(&value_copy); - convert_to_string(&value_copy); - smart_str_appendl(&buf, Z_STRVAL(value_copy), Z_STRLEN(value_copy)); - zval_dtor(&value_copy); + php_memcached_g_fmt(dstr, Z_DVAL_P(value)); + smart_str_appends(&buf, dstr); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + break; + } - *flags &= ~MEMC_VAL_COMPRESSED; - if (Z_TYPE_P(value) == IS_LONG) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); - } else if (Z_TYPE_P(value) == IS_DOUBLE) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); - } else if (Z_TYPE_P(value) == IS_BOOL) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + case IS_BOOL: + if (Z_BVAL_P(value)) { + smart_str_appendc(&buf, '1'); + } else { + smart_str_appendl(&buf, "", 0); } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; - } default: switch (serializer) { @@ -2690,11 +2693,16 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload } case MEMC_VAL_IS_DOUBLE: - { - double dval = zend_strtod(payload, NULL); - ZVAL_DOUBLE(value, dval); + if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) { + ZVAL_DOUBLE(value, php_get_inf()); + } else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) { + ZVAL_DOUBLE(value, -php_get_inf()); + } else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) { + ZVAL_DOUBLE(value, php_get_nan()); + } else { + ZVAL_DOUBLE(value, zend_strtod(payload, NULL)); + } break; - } case MEMC_VAL_IS_BOOL: ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1'); From a531a6a94eb8a59be890b8a1dd934d0e1486a56f Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 10:53:06 +0300 Subject: [PATCH 061/694] Add missing files. --- package.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.xml b/package.xml index 5047c961..80beb9dc 100644 --- a/package.xml +++ b/package.xml @@ -64,6 +64,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + From a7597ac2a0345c780fadc2ccdf2c6641b2ab7c3f Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 12:17:47 +0300 Subject: [PATCH 062/694] Fail serialization to payload on exception. --- php_memcached.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 1bdba72d..2d387f19 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2552,6 +2552,12 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t break; } + /* Check for exceptions caused by serializers */ + if (EG(exception)) { + smart_str_free(&buf); + return NULL; + } + /* turn off compression for values below the threshold */ if ((*flags & MEMC_VAL_COMPRESSED) && buf.len < MEMC_G(compression_threshold)) { *flags &= ~MEMC_VAL_COMPRESSED; From 17853a39e8d8accec77b124a65fdd736682201c7 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Tue, 3 May 2011 15:46:02 +0300 Subject: [PATCH 063/694] Cleanup, add pecl bug #17137 (prefix change) test --- tests/bug_17137.phpt | 35 ++++++++++++++++++++++ tests/bug_18639.phpt | 4 +-- tests/experimental/getmulti_badserver.phpt | 1 + tests/getserverlist.phpt | 4 +-- tests/invoke_callback.phpt | 4 +-- tests/session_badconf_emptyprefix.phpt | 2 +- 6 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 tests/bug_17137.phpt diff --git a/tests/bug_17137.phpt b/tests/bug_17137.phpt new file mode 100644 index 00000000..276d6661 --- /dev/null +++ b/tests/bug_17137.phpt @@ -0,0 +1,35 @@ +--TEST-- +Change prefix, pecl bug #17137 +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211); + +$memcache->setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$memcache->setOption(Memcached::OPT_PREFIX_KEY, 'prefix1'); +var_dump($memcache->getOption(Memcached::OPT_PREFIX_KEY)); + +var_dump($memcache->set('test', "val_prefix1", 120)); +var_dump($memcache->get('test')); + +$memcache2 = new Memcached(); +$memcache2->addServer('127.0.0.1', 11211); +$memcache2->setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$memcache2->setOption(Memcached::OPT_PREFIX_KEY, 'prefix2'); +var_dump($memcache2->getOption(Memcached::OPT_PREFIX_KEY)); + +var_dump($memcache2->set('test', "val_prefix2", 120)); +var_dump($memcache2->get('test')); + + +var_dump($memcache->get('test')); +--EXPECT-- +string(7) "prefix1" +bool(true) +string(11) "val_prefix1" +string(7) "prefix2" +bool(true) +string(11) "val_prefix2" +string(11) "val_prefix1" diff --git a/tests/bug_18639.phpt b/tests/bug_18639.phpt index 9deb7492..da3519b1 100644 --- a/tests/bug_18639.phpt +++ b/tests/bug_18639.phpt @@ -1,5 +1,5 @@ --TEST-- -Memcached::getServerByKey(): Bug pecl#18639 (Segfault in getServerByKet) +Memcached::getServerByKey(): Bug pecl#18639 (Segfault in getServerByKey) --SKIPIF-- --FILE-- @@ -19,5 +19,5 @@ array(3) { ["port"]=> int(11211) ["weight"]=> - int(0) + int(%r[01]%r) } diff --git a/tests/experimental/getmulti_badserver.phpt b/tests/experimental/getmulti_badserver.phpt index 3e6bf402..f1a221de 100644 --- a/tests/experimental/getmulti_badserver.phpt +++ b/tests/experimental/getmulti_badserver.phpt @@ -14,6 +14,7 @@ var_dump($m->getMulti(array('foo', 'bar'))); switch ($m->getResultCode()) { case Memcached::RES_ERRNO: case Memcached::RES_SOME_ERRORS: + case Memcached::RES_FAILURE: break; default: echo $m->getResultCode(), ": "; diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index c9e928af..1761f33c 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -15,7 +15,7 @@ $m = new memcached(); $m->addServer('127.0.0.1', 11211); var_dump($m->getServerList()); ?> ---EXPECT-- +--EXPECTF-- array(0) { } array(1) { @@ -57,6 +57,6 @@ array(1) { ["port"]=> int(11211) ["weight"]=> - int(0) + int(%r[01]%r) } } diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index bb77203d..6fddc0c0 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -16,7 +16,7 @@ var_dump($m->getServerList()); echo "OK\n"; ---EXPECT-- +--EXPECTF-- array(1) { [0]=> array(3) { @@ -25,7 +25,7 @@ array(1) { ["port"]=> int(11211) ["weight"]=> - int(0) + int(%r[01]%r) } } OK diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index 2c356482..8dad7386 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -21,7 +21,7 @@ function handler($errno, $errstr) { set_error_handler('handler', E_ALL); -ini_set('memcached.sess_prefix', ''); +ini_set('memcached.sess_prefix', " \n"); session_start(); session_write_close(); From 383d10446c5da9fce36d8af6734a2964e64cbacc Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Wed, 4 May 2011 10:14:51 +0300 Subject: [PATCH 064/694] Pecl bug #19065, use int instead of size_t. --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 6f08c316..a01147cf 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -480,7 +480,7 @@ PHP_METHOD(Memcached, getByKey) static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { char *key = NULL; - size_t key_len = 0; + int key_len = 0; char *server_key = NULL; int server_key_len = 0; char *payload = NULL; From b0f5bff7534dc25445042b1d9ba988c6f3713429 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Wed, 4 May 2011 15:22:43 +0300 Subject: [PATCH 065/694] Allow use of UDP, highly experimental. Only tested with addServer and only if the UDP behavior is set before adding any servers. Libmemcached 0.49 does not support mixing TCP and UDP per client instance. --- php_memcached.c | 2 ++ tests/experimental/get_udp.phpt | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/experimental/get_udp.phpt diff --git a/php_memcached.c b/php_memcached.c index a01147cf..b06ec3c3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1673,6 +1673,8 @@ PHP_METHOD(Memcached, addServer) if (host[0] == '/') { /* unix domain socket */ status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); + } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { + status = memcached_server_add_udp_with_weight(m_obj->memc, host, port, weight); } else { status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); } diff --git a/tests/experimental/get_udp.phpt b/tests/experimental/get_udp.phpt new file mode 100644 index 00000000..6d196cab --- /dev/null +++ b/tests/experimental/get_udp.phpt @@ -0,0 +1,50 @@ +--TEST-- +Memcached::set()/delete() UDP +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211, 1); + +$m_udp = new Memcached(); +$m_udp->setOption(Memcached::OPT_USE_UDP, true); +$m_udp->addServer('127.0.0.1', 11211, 1); + + +error_reporting(0); + +echo "\n"; +echo "Delete not found\n"; +$m->delete('foo'); +var_dump($m_udp->delete('foo')); +echo $m_udp->getResultMessage(), "\n"; + +echo "\n"; +echo "Set\n"; +var_dump($m_udp->set('foo', "asdf", 10)); +echo $m_udp->getResultMessage(), "\n"; +var_dump($m->get('foo')); + +echo "\n"; +echo "Delete found\n"; +var_dump($m_udp->delete('foo')); +echo $m_udp->getResultMessage(), "\n"; +$m->get('foo'); +echo $m->getResultMessage(), "\n"; + + +--EXPECTF-- +Delete not found +bool(true) +SUCCESS + +Set +bool(true) +SUCCESS +string(4) "asdf" + +Delete found +bool(true) +SUCCESS +NOT FOUND From 468487d5af9a63505d20696aac7ca11332e59150 Mon Sep 17 00:00:00 2001 From: Teddy Grenman Date: Wed, 4 May 2011 16:44:21 +0300 Subject: [PATCH 066/694] Fix build against libmemcached versions before 0.39. memcached_server_instance_st was defined in 0.39. Built and tested against 0.31 and 0.49. --- package.xml | 1 + php_libmemcached_compat.h | 16 ++++++++++++++++ php_memcached.c | 1 + php_memcached_session.c | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 php_libmemcached_compat.h diff --git a/package.xml b/package.xml index 80beb9dc..3436757f 100644 --- a/package.xml +++ b/package.xml @@ -64,6 +64,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h new file mode 100644 index 00000000..8b39da36 --- /dev/null +++ b/php_libmemcached_compat.h @@ -0,0 +1,16 @@ +/* + * Here we define backwards compatibility for older + * libmemcached API:s + * + * // Teddy Grenman + */ + +#ifndef PHP_LIBMEMCACHED_COMPAT +#define PHP_LIBMEMCACHED_COMPAT + +#if !defined(LIBMEMCACHED_VERSION_HEX) || LIBMEMCACHED_VERSION_HEX < 0x00039000 +/* definition from libmemcached/types.h version 0.39+ */ +typedef const struct memcached_server_st *memcached_server_instance_st; +#endif + +#endif diff --git a/php_memcached.c b/php_memcached.c index b06ec3c3..8ec7b9f9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -45,6 +45,7 @@ #include #include +#include "php_libmemcached_compat.h" #include "php_memcached.h" #include "g_fmt.h" diff --git a/php_memcached_session.c b/php_memcached_session.c index 934c5a95..cafa9952 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -47,7 +47,7 @@ ps_module ps_mod_memcached = { /* * Stolen from libmemcached/common.h, because we need it and they don't expose it. */ -static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) +static inline int memcached_validate_key_length(size_t key_length, bool binary) { if (key_length == 0) return MEMCACHED_BAD_KEY_PROVIDED; From ea5eb73a20b565caf13ce84f4ad3c1294419a9b9 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 8 Jun 2011 18:06:59 -0400 Subject: [PATCH 067/694] Parameter parsing fix --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 8ec7b9f9..ae1e61bc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1272,7 +1272,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &server_key, - &server_key_len, &key, &key_len, &s_value, &s_value_len, &expiration) == FAILURE) { + &server_key_len, &key, &key_len, &s_value, &s_value_len) == FAILURE) { return; } INIT_ZVAL(s_zvalue); From 21c8ec1e6500bf736cede22985491a8671bf384b Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 9 Jun 2011 12:57:09 -0400 Subject: [PATCH 068/694] Avoid re-allocating data for scalar data types --- php_memcached.c | 67 +++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index ae1e61bc..cb03d1c8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2483,36 +2483,43 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) { char *payload; + char *p; + int l; + zend_bool buf_used = 0; smart_str buf = {0}; + char tmp[40] = {0}; switch (Z_TYPE_P(value)) { case IS_STRING: - smart_str_appendl(&buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); + p = Z_STRVAL_P(value); + l = Z_STRLEN_P(value); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); break; case IS_LONG: - smart_str_append_long(&buf, Z_LVAL_P(value)); + l = sprintf(tmp, "%ld", Z_LVAL_P(value)); + p = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); break; case IS_DOUBLE: - { - char dstr[40] = {0}; - - php_memcached_g_fmt(dstr, Z_DVAL_P(value)); - smart_str_appends(&buf, dstr); + php_memcached_g_fmt(tmp, Z_DVAL_P(value)); + p = tmp; + l = strlen(tmp); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); break; - } case IS_BOOL: if (Z_BVAL_P(value)) { - smart_str_appendc(&buf, '1'); + l = 1; + tmp[0] = '1'; + tmp[1] = '\0'; } else { - smart_str_appendl(&buf, "", 0); + l = 0; + tmp[0] = '\0'; } + p = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; @@ -2524,6 +2531,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t smart_str_free(&buf); return NULL; } + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); break; #endif @@ -2538,6 +2548,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t php_json_encode(&buf, value, 0 TSRMLS_CC); /* options */ #endif buf.c[buf.len] = 0; + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); break; } @@ -2554,7 +2567,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t smart_str_free(&buf); return NULL; } - + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); break; } @@ -2564,7 +2579,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* Check for exceptions caused by serializers */ - if (EG(exception)) { + if (EG(exception) && buf_used) { smart_str_free(&buf); return NULL; } @@ -2579,44 +2594,48 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t zend_bool compress_status = 0; /* Additional 5% for the data */ - unsigned long payload_comp_len = (unsigned long)((buf.len * 1.05) + 1); + unsigned long payload_comp_len = (unsigned long)((l * 1.05) + 1); char *payload_comp = emalloc(payload_comp_len + sizeof(uint32_t)); payload = payload_comp; - memcpy(payload_comp, &buf.len, sizeof(uint32_t)); + memcpy(payload_comp, &l, sizeof(uint32_t)); payload_comp += sizeof(uint32_t); if (compression_type == COMPRESSION_TYPE_FASTLZ) { - compress_status = ((payload_comp_len = fastlz_compress(buf.c, buf.len, payload_comp)) > 0); + compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0); *flags |= MEMC_VAL_COMPRESSION_FASTLZ; } else if (compression_type == COMPRESSION_TYPE_ZLIB) { - compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)buf.c, buf.len) == Z_OK); + compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK); *flags |= MEMC_VAL_COMPRESSION_ZLIB; } if (!compress_status) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); efree(payload); - smart_str_free(&buf); + if (buf_used) { + smart_str_free(&buf); + } return NULL; } /* Check that we are above ratio */ - if (buf.len > (payload_comp_len * MEMC_G(compression_factor))) { + if (l > (payload_comp_len * MEMC_G(compression_factor))) { *payload_len = payload_comp_len + sizeof(uint32_t); payload[*payload_len] = 0; } else { /* Store plain value */ *flags &= ~MEMC_VAL_COMPRESSED; - *payload_len = buf.len; - memcpy(payload, buf.c, buf.len); - payload[buf.len] = 0; + *payload_len = l; + memcpy(payload, p, l); + payload[l] = 0; } } else { - *payload_len = buf.len; - payload = estrndup(buf.c, buf.len); + *payload_len = l; + payload = estrndup(p, l); } - smart_str_free(&buf); + if (buf_used) { + smart_str_free(&buf); + } return payload; } From 8c36e8471f86b7eb86ab3d352fbb51dd35f8936e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 8 Jun 2011 18:06:59 -0400 Subject: [PATCH 069/694] Parameter parsing fix --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 8e8fb5c4..d842a333 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1269,7 +1269,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &server_key, - &server_key_len, &key, &key_len, &s_value, &s_value_len, &expiration) == FAILURE) { + &server_key_len, &key, &key_len, &s_value, &s_value_len) == FAILURE) { return; } INIT_ZVAL(s_zvalue); From 8ee6495befbb06fc7a33759671a78f6274d0e93d Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 9 Jun 2011 13:16:04 -0400 Subject: [PATCH 070/694] Avoid re-allocating data for scalar data types Conflicts: php_memcached.c --- php_memcached.c | 87 +++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d842a333..1c5c5afb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2468,37 +2468,44 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) { char *payload; + char *p; + int l; + zend_bool buf_used = 0; smart_str buf = {0}; + char tmp[40] = {0}; switch (Z_TYPE_P(value)) { case IS_STRING: - smart_str_appendl(&buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); + p = Z_STRVAL_P(value); + l = Z_STRLEN_P(value); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); break; case IS_LONG: - case IS_DOUBLE: - case IS_BOOL: - { - zval value_copy; + l = sprintf(tmp, "%ld", Z_LVAL_P(value)); + p = tmp; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + break; - value_copy = *value; - zval_copy_ctor(&value_copy); - convert_to_string(&value_copy); - smart_str_appendl(&buf, Z_STRVAL(value_copy), Z_STRLEN(value_copy)); - zval_dtor(&value_copy); + case IS_DOUBLE: + l = sprintf(tmp, "%f", Z_DVAL_P(value)); + p = tmp; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + break; - *flags &= ~MEMC_VAL_COMPRESSED; - if (Z_TYPE_P(value) == IS_LONG) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); - } else if (Z_TYPE_P(value) == IS_DOUBLE) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); - } else if (Z_TYPE_P(value) == IS_BOOL) { - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + case IS_BOOL: + if (Z_BVAL_P(value)) { + l = 1; + tmp[0] = '1'; + tmp[1] = '\0'; + } else { + l = 0; + tmp[0] = '\0'; } + p = tmp; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; - } default: switch (serializer) { @@ -2508,6 +2515,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t smart_str_free(&buf); return NULL; } + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); break; #endif @@ -2522,6 +2532,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t php_json_encode(&buf, value, 0 TSRMLS_CC); /* options */ #endif buf.c[buf.len] = 0; + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); break; } @@ -2538,7 +2551,9 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t smart_str_free(&buf); return NULL; } - + p = buf.c; + l = buf.len; + buf_used = 1; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); break; } @@ -2547,6 +2562,12 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t break; } + /* Check for exceptions caused by serializers */ + if (EG(exception) && buf_used) { + smart_str_free(&buf); + return NULL; + } + /* turn off compression for values below the threshold */ if ((*flags & MEMC_VAL_COMPRESSED) && buf.len < MEMC_G(compression_threshold)) { *flags &= ~MEMC_VAL_COMPRESSED; @@ -2557,44 +2578,48 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t zend_bool compress_status = 0; /* Additional 5% for the data */ - unsigned long payload_comp_len = (unsigned long)((buf.len * 1.05) + 1); + unsigned long payload_comp_len = (unsigned long)((l * 1.05) + 1); char *payload_comp = emalloc(payload_comp_len + sizeof(uint32_t)); payload = payload_comp; - memcpy(payload_comp, &buf.len, sizeof(uint32_t)); + memcpy(payload_comp, &l, sizeof(uint32_t)); payload_comp += sizeof(uint32_t); if (compression_type == COMPRESSION_TYPE_FASTLZ) { - compress_status = ((payload_comp_len = fastlz_compress(buf.c, buf.len, payload_comp)) > 0); + compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0); *flags |= MEMC_VAL_COMPRESSION_FASTLZ; } else if (compression_type == COMPRESSION_TYPE_ZLIB) { - compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)buf.c, buf.len) == Z_OK); + compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK); *flags |= MEMC_VAL_COMPRESSION_ZLIB; } if (!compress_status) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); efree(payload); - smart_str_free(&buf); + if (buf_used) { + smart_str_free(&buf); + } return NULL; } /* Check that we are above ratio */ - if (buf.len > (payload_comp_len * MEMC_G(compression_factor))) { + if (l > (payload_comp_len * MEMC_G(compression_factor))) { *payload_len = payload_comp_len + sizeof(uint32_t); payload[*payload_len] = 0; } else { /* Store plain value */ *flags &= ~MEMC_VAL_COMPRESSED; - *payload_len = buf.len; - memcpy(payload, buf.c, buf.len); - payload[buf.len] = 0; + *payload_len = l; + memcpy(payload, p, l); + payload[l] = 0; } } else { - *payload_len = buf.len; - payload = estrndup(buf.c, buf.len); + *payload_len = l; + payload = estrndup(p, l); } - smart_str_free(&buf); + if (buf_used) { + smart_str_free(&buf); + } return payload; } From 67b7628a724d91a9349156d6f3521e85653d865d Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 08:01:09 -0400 Subject: [PATCH 071/694] Fixed compiler warnings --- php_memcached.c | 76 ++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1c5c5afb..c9f66d04 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1772,7 +1772,6 @@ PHP_METHOD(Memcached, addServers) Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) { - zval *array; struct callbackContext context = {0}; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -1785,7 +1784,6 @@ PHP_METHOD(Memcached, getServerList) callbacks[0] = php_memc_do_serverlist_callback; array_init(return_value); - context.array = array; context.return_value = return_value; memcached_server_cursor(m_obj->memc, callbacks, &context, 1); } @@ -1833,7 +1831,6 @@ PHP_METHOD(Memcached, getStats) { memcached_stat_st *stats; memcached_return status; - zval *entry; struct callbackContext context = {0}; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -1857,7 +1854,6 @@ PHP_METHOD(Memcached, getStats) callbacks[0] = php_memc_do_stats_callback; context.i = 0; - context.entry = entry; context.stats = stats; context.return_value = return_value; memcached_server_cursor(m_obj->memc, callbacks, &context, 1); @@ -2349,13 +2345,14 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; + zval *array; - 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); + MAKE_STD_ZVAL(array); + array_init(array); + add_assoc_string(array, "host", instance->hostname, 1); + add_assoc_long(array, "port", instance->port); + add_assoc_long(array, "weight", instance->weight); + add_next_index_zval(context->return_value, array); return MEMCACHED_SUCCESS; } @@ -2364,37 +2361,38 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memc char *hostport = NULL; int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; + zval *entry; 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); + MAKE_STD_ZVAL(entry); + array_init(entry); + + add_assoc_long(entry, "pid", context->stats[context->i].pid); + add_assoc_long(entry, "uptime", context->stats[context->i].uptime); + add_assoc_long(entry, "threads", context->stats[context->i].threads); + add_assoc_long(entry, "time", context->stats[context->i].time); + add_assoc_long(entry, "pointer_size", context->stats[context->i].pointer_size); + add_assoc_long(entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); + add_assoc_long(entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); + add_assoc_long(entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); + add_assoc_long(entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); + add_assoc_long(entry, "curr_items", context->stats[context->i].curr_items); + add_assoc_long(entry, "total_items", context->stats[context->i].total_items); + add_assoc_long(entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); + add_assoc_long(entry, "curr_connections", context->stats[context->i].curr_connections); + add_assoc_long(entry, "total_connections", context->stats[context->i].total_connections); + add_assoc_long(entry, "connection_structures", context->stats[context->i].connection_structures); + add_assoc_long(entry, "bytes", context->stats[context->i].bytes); + add_assoc_long(entry, "cmd_get", context->stats[context->i].cmd_get); + add_assoc_long(entry, "cmd_set", context->stats[context->i].cmd_set); + add_assoc_long(entry, "get_hits", context->stats[context->i].get_hits); + add_assoc_long(entry, "get_misses", context->stats[context->i].get_misses); + add_assoc_long(entry, "evictions", context->stats[context->i].evictions); + add_assoc_long(entry, "bytes_read", context->stats[context->i].bytes_read); + add_assoc_long(entry, "bytes_written", context->stats[context->i].bytes_written); + add_assoc_stringl(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, 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. */ From 7b4478f49694b5c7bf7ee0327be961065b6742a6 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 08:05:10 -0400 Subject: [PATCH 072/694] Added OPT_TCP_KEEPALIVE & OPT_LIBKETAMA_HASH config options --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index c9f66d04..8fe126bb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3391,6 +3391,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); REGISTER_MEMC_CLASS_CONST_LONG(OPT_BUFFER_WRITES, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_BINARY_PROTOCOL, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL); REGISTER_MEMC_CLASS_CONST_LONG(OPT_NO_BLOCK, MEMCACHED_BEHAVIOR_NO_BLOCK); From 8e3e47be6fcf4aee2295bb878074a240e69e89a7 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 08:18:32 -0400 Subject: [PATCH 073/694] Fixed php_memc_cas_impl() implementation when server_key is not being used --- php_memcached.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index cdc25123..1a4984d3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1453,8 +1453,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } - status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, - payload, payload_len, expiration, flags, cas); + + if (by_key) { + status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, payload, payload_len, expiration, flags, cas); + } else { + status = memcached_cas(m_obj->memc, key, key_len, payload, payload_len, expiration, flags, cas); + } efree(payload); if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { RETURN_FALSE; From c0f01937059588a12ebcc37f617feaf4889ae5be Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 10:52:18 -0400 Subject: [PATCH 074/694] Fixed test --- tests/experimental/serializer_json.phpt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/experimental/serializer_json.phpt b/tests/experimental/serializer_json.phpt index f90997ee..b8f982dd 100644 --- a/tests/experimental/serializer_json.phpt +++ b/tests/experimental/serializer_json.phpt @@ -8,9 +8,7 @@ Serialize JSON ?> --REDIRECTTEST-- -$path = implode(DIRECTORY_SEPARATOR, array('tests', 'experimental', 'serializer')); - return array( - 'TESTS' => $path, + 'TESTS' => sys_get_temp_dir(), 'ENV' => array('TEST_MEMC_SERIALIZER' => 'Memcached::SERIALIZER_JSON'), ); From 897d1cf26b830fff3acf412e14ea122951f5b5e3 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 10:53:16 -0400 Subject: [PATCH 075/694] Added support for incremenet/decrement ByKey Added support for initial value initialization by increment/decrement (requires binary protocol) --- php_memcached.c | 122 ++++++++++++++++++----- tests/experimental/incrdecr_bykey.phpt | 52 ++++++++++ tests/experimental/incrdecr_initial.phpt | 51 ++++++++++ 3 files changed, 199 insertions(+), 26 deletions(-) create mode 100644 tests/experimental/incrdecr_bykey.phpt create mode 100644 tests/experimental/incrdecr_initial.phpt diff --git a/php_memcached.c b/php_memcached.c index 1a4984d3..46277185 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -310,7 +310,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); -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); @@ -1601,34 +1600,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } /* }}} */ -/* {{{ Memcached::increment(string key [, int delta ]) - Increments the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, increment) -{ - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ Memcached::decrement(string key [, int delta ]) - Decrements the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrement) -{ - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - /* {{{ -- php_memc_incdec_impl */ -static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) +static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - char *key = NULL; - int key_len = 0; + char *key, *server_key; + int key_len, server_key_len; long offset = 1; - uint64_t value; + uint64_t value, initial = 0; + time_t expiry = 0; memcached_return status; + int n_args = ZEND_NUM_ARGS(); + MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &offset) == FAILURE) { - return; + if (!by_key) { + if (zend_parse_parameters(n_args TSRMLS_CC, "s|lll", &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(n_args TSRMLS_CC, "ss|lll", &server_key, &server_key_len, &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; @@ -1644,10 +1636,34 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) RETURN_FALSE; } - if (incr) { - status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { + if (by_key) { + if (incr) { + status = memcached_increment_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + } else { + status = memcached_decrement_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + } + } else { + if (incr) { + status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + } else { + status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + } + } } else { - status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + if (by_key) { + if (incr) { + status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + } + } else { + if (incr) { + status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + } + } } if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { @@ -1658,6 +1674,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) } /* }}} */ +/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, increment) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); +} +/* }}} */ + +/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrement) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); +} +/* }}} */ + +/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); +} +/* }}} */ + +/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, incrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); +} +/* }}} */ + /* {{{ Memcached::addServer(string hostname, int port [, int weight ]) Adds the given memcache server to the list */ PHP_METHOD(Memcached, addServer) @@ -3189,11 +3237,31 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_incrementByKey, 0, 0, 2) + ZEND_ARG_INFO(0, server_key) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_decrementByKey, 0, 0, 2) + ZEND_ARG_INFO(0, server_key) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0) @@ -3290,6 +3358,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(increment, arginfo_increment) MEMC_ME(decrement, arginfo_decrement) + MEMC_ME(incrementByKey, arginfo_incrementByKey) + MEMC_ME(decrementByKey, arginfo_decrementByKey) MEMC_ME(addServer, arginfo_addServer) MEMC_ME(addServers, arginfo_addServers) diff --git a/tests/experimental/incrdecr_bykey.phpt b/tests/experimental/incrdecr_bykey.phpt new file mode 100644 index 00000000..ea2bd803 --- /dev/null +++ b/tests/experimental/incrdecr_bykey.phpt @@ -0,0 +1,52 @@ +--TEST-- +Memcached::incrementByKey() Memcached::decrementByKey() +--SKIPIF-- + +--FILE-- +addServer('localhost', 11211, 1); + +echo "Not there\n"; +$m->delete('foo'); +var_dump($m->incrementByKey('foo', 'foo', 1)); +var_dump($m->decrementByKey('foo', 'foo', 1)); +var_dump($m->get('foo')); + +echo "Normal\n"; +$m->set('foo', 1); +var_dump($m->get('foo')); +$m->incrementByKey('foo', 'foo'); +var_dump($m->get('foo')); +$m->incrementByKey('foo', 'foo', 2); +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo'); +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo', 2); +var_dump($m->get('foo')); + +error_reporting(0); +echo "Invalid offset\n"; +$m->incrementByKey('foo', 'foo', -1); +echo $php_errormsg, "\n"; +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo', -1); +echo $php_errormsg, "\n"; +var_dump($m->get('foo')); + +--EXPECT-- +Not there +bool(false) +bool(false) +bool(false) +Normal +int(1) +int(2) +int(4) +int(3) +int(1) +Invalid offset +Memcached::incrementByKey(): offset has to be > 0 +int(1) +Memcached::decrementByKey(): offset has to be > 0 +int(1) diff --git a/tests/experimental/incrdecr_initial.phpt b/tests/experimental/incrdecr_initial.phpt new file mode 100644 index 00000000..63d8d008 --- /dev/null +++ b/tests/experimental/incrdecr_initial.phpt @@ -0,0 +1,51 @@ +--TEST-- +Memcached::increment() Memcached::decrement() with initial support +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, 1); +$m->addServer('localhost', 11211, 1); + +$m->delete('foo'); +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 0)); +$m->delete('foo'); + +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 1, 1)); + +var_dump($m->decrement('foo', 1, 1)); +var_dump($m->decrement('foo', 0)); +$m->delete('foo'); + +$m->deleteByKey('foo', 'foo'); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 0)); +$m->deleteByKey('foo', 'foo'); + +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); + +var_dump($m->decrementByKey('foo', 'foo', 1, 1)); +var_dump($m->decrementByKey('foo', 'foo', 0)); +$m->deleteByKey('foo', 'foo'); + +--EXPECT-- +int(1) +int(1) +int(1) +int(2) +int(3) +int(2) +int(2) +int(1) +int(1) +int(1) +int(2) +int(3) +int(2) +int(2) From bb55df8dae697969e501bd821ecb2053de5e29d0 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 11:14:19 -0400 Subject: [PATCH 076/694] Fixed a bug introduced in prior commit designed to reduce mallocs --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 46277185..662726c9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2635,7 +2635,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* turn off compression for values below the threshold */ - if ((*flags & MEMC_VAL_COMPRESSED) && buf.len < MEMC_G(compression_threshold)) { + if ((*flags & MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { *flags &= ~MEMC_VAL_COMPRESSED; } From f932b94c73036c66cbc40aa4b1202522cdad645a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 11:27:05 -0400 Subject: [PATCH 077/694] Test fixes --- tests/experimental/delete_bykey.phpt | 2 +- tests/rescode.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index e1b28472..87219539 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -37,4 +37,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) NOT FOUND bool(false) -%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE%r +%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE|CLIENT ERROR%r diff --git a/tests/rescode.phpt b/tests/rescode.phpt index 7c279733..1bfd3ec0 100644 --- a/tests/rescode.phpt +++ b/tests/rescode.phpt @@ -77,7 +77,7 @@ NO SERVERS DEFINED %d SUCCESS %d -%rSYSTEM ERROR|WRITE FAILURE%r +%rSYSTEM ERROR|WRITE FAILURE|CONNECTION FAILURE%r bool(true) NOT FOUND NOT FOUND From 6f9167a09b5c61b42cd84e83bc8df3b0d2b0c696 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 12:20:15 -0400 Subject: [PATCH 078/694] Added a work-around for libmemcached bug where last char of the domain prefix is truncated --- php_memcached.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 662726c9..14dc7e1d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2041,7 +2041,11 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 + RETURN_STRINGL(result, strlen(result) - 1, 1); +#else RETURN_STRING(result, 1); +#endif } else { RETURN_EMPTY_STRING(); } @@ -2094,11 +2098,23 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML case MEMC_OPT_PREFIX_KEY: { char *key; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 + char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; +#endif convert_to_string(value); if (Z_STRLEN_P(value) == 0) { key = NULL; } else { + /* + work-around a bug in libmemcached prior to version 0.50 that truncates the trailing + character of the key prefix, to avoid the issue we pad it with a '0' + */ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 + snprintf(tmp, sizeof(tmp), "%s0", Z_STRVAL_P(value)); + key = tmp; +#else key = Z_STRVAL_P(value); +#endif } if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided"); From b46bfbd5e048b1bc594838f4bae96ffaa5559730 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 12:21:32 -0400 Subject: [PATCH 079/694] Implemented a mechanism that allows transparent fail-over to secondary servers when set/increment/decrement/setMulti operations fail on the desired server in a multi-server environment. --- php_memcached.c | 82 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 14dc7e1d..1437f5c4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -307,7 +307,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); -static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); @@ -1109,6 +1108,29 @@ PHP_METHOD(Memcached, setMultiByKey) } /* }}} */ +#define PHP_MEMC_FAILOVER_RETRY \ + if (!server_key && retry < 2) { \ + switch (i_obj->rescode) { \ + case MEMCACHED_HOST_LOOKUP_FAILURE: \ + case MEMCACHED_CONNECTION_FAILURE: \ + case MEMCACHED_CONNECTION_BIND_FAILURE: \ + case MEMCACHED_WRITE_FAILURE: \ + case MEMCACHED_READ_FAILURE: \ + case MEMCACHED_UNKNOWN_READ_FAILURE: \ + case MEMCACHED_PROTOCOL_ERROR: \ + case MEMCACHED_SERVER_ERROR: \ + case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: \ + case MEMCACHED_TIMEOUT: \ + case MEMCACHED_FAIL_UNIX_SOCKET: \ + case MEMCACHED_SERVER_MARKED_DEAD: \ + if (memcached_server_count(m_obj->memc) > 0) { \ + retry++; \ + goto retry; \ + } \ + break; \ + } \ + } \ + /* {{{ -- php_memc_setMulti_impl */ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { @@ -1123,6 +1145,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke char *payload; size_t payload_len; uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; char tmp_key[MEMCACHED_MAX_KEY]; MEMC_METHOD_INIT_VARS; @@ -1173,13 +1196,15 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke server_key = str_key; server_key_len = str_key_len-1; } - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, - str_key_len-1, payload, payload_len, expiration, flags); - efree(payload); +retry: + status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags); if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + PHP_MEMC_FAILOVER_RETRY + efree(payload); RETURN_FALSE; } + efree(payload); } RETURN_TRUE; @@ -1250,6 +1275,7 @@ PHP_METHOD(Memcached, replaceByKey) } /* }}} */ + /* {{{ -- php_memc_store_impl */ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { @@ -1265,6 +1291,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool char *payload; size_t payload_len; uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; MEMC_METHOD_INIT_VARS; @@ -1326,7 +1353,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } - +retry: switch (op) { case MEMC_OP_SET: if (!server_key) { @@ -1379,28 +1406,13 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; } - efree(payload); if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - RETURN_FALSE; + PHP_MEMC_FAILOVER_RETRY + RETVAL_FALSE; + } else { + RETVAL_TRUE; } - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) - Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, cas) -{ - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, casByKey) -{ - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + efree(payload); } /* }}} */ @@ -1467,6 +1479,22 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* }}} */ +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) + Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, cas) +{ + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, casByKey) +{ + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + /* {{{ Memcached::delete(string key [, int time ]) Deletes the given key */ PHP_METHOD(Memcached, delete) @@ -1610,7 +1638,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, time_t expiry = 0; memcached_return status; int n_args = ZEND_NUM_ARGS(); - + uint32_t retry = 0; MEMC_METHOD_INIT_VARS; if (!by_key) { @@ -1636,6 +1664,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, RETURN_FALSE; } +retry: if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { @@ -1667,6 +1696,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + PHP_MEMC_FAILOVER_RETRY RETURN_FALSE; } From 55e13e0166a815cdbbb7fe264a9b81faf23ea208 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 08:18:32 -0400 Subject: [PATCH 080/694] Fixed php_memc_cas_impl() implementation when server_key is not being used --- php_memcached.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 8fe126bb..14ab0a82 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1450,8 +1450,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } - status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, - payload, payload_len, expiration, flags, cas); + + if (by_key) { + status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, payload, payload_len, expiration, flags, cas); + } else { + status = memcached_cas(m_obj->memc, key, key_len, payload, payload_len, expiration, flags, cas); + } efree(payload); if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { RETURN_FALSE; From f526db0486ab615e6fa20288b8b1cb49a29f36a9 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 10:52:18 -0400 Subject: [PATCH 081/694] Fixed test --- tests/experimental/serializer_json.phpt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/experimental/serializer_json.phpt b/tests/experimental/serializer_json.phpt index f90997ee..b8f982dd 100644 --- a/tests/experimental/serializer_json.phpt +++ b/tests/experimental/serializer_json.phpt @@ -8,9 +8,7 @@ Serialize JSON ?> --REDIRECTTEST-- -$path = implode(DIRECTORY_SEPARATOR, array('tests', 'experimental', 'serializer')); - return array( - 'TESTS' => $path, + 'TESTS' => sys_get_temp_dir(), 'ENV' => array('TEST_MEMC_SERIALIZER' => 'Memcached::SERIALIZER_JSON'), ); From d6a43cd191d0551996aed23d0ba45036ef6d7ff0 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 10:53:16 -0400 Subject: [PATCH 082/694] Added support for incremenet/decrement ByKey Added support for initial value initialization by increment/decrement (requires binary protocol) --- php_memcached.c | 122 ++++++++++++++++++----- tests/experimental/incrdecr_bykey.phpt | 52 ++++++++++ tests/experimental/incrdecr_initial.phpt | 51 ++++++++++ 3 files changed, 199 insertions(+), 26 deletions(-) create mode 100644 tests/experimental/incrdecr_bykey.phpt create mode 100644 tests/experimental/incrdecr_initial.phpt diff --git a/php_memcached.c b/php_memcached.c index 14ab0a82..1b328c11 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -307,7 +307,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); -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); @@ -1598,34 +1597,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } /* }}} */ -/* {{{ Memcached::increment(string key [, int delta ]) - Increments the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, increment) -{ - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ Memcached::decrement(string key [, int delta ]) - Decrements the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrement) -{ - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - /* {{{ -- php_memc_incdec_impl */ -static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) +static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - char *key = NULL; - int key_len = 0; + char *key, *server_key; + int key_len, server_key_len; long offset = 1; - uint64_t value; + uint64_t value, initial = 0; + time_t expiry = 0; memcached_return status; + int n_args = ZEND_NUM_ARGS(); + MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &offset) == FAILURE) { - return; + if (!by_key) { + if (zend_parse_parameters(n_args TSRMLS_CC, "s|lll", &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(n_args TSRMLS_CC, "ss|lll", &server_key, &server_key_len, &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; @@ -1641,10 +1633,34 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) RETURN_FALSE; } - if (incr) { - status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { + if (by_key) { + if (incr) { + status = memcached_increment_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + } else { + status = memcached_decrement_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + } + } else { + if (incr) { + status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + } else { + status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + } + } } else { - status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + if (by_key) { + if (incr) { + status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + } + } else { + if (incr) { + status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + } + } } if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { @@ -1655,6 +1671,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr) } /* }}} */ +/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, increment) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); +} +/* }}} */ + +/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrement) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); +} +/* }}} */ + +/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); +} +/* }}} */ + +/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, incrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); +} +/* }}} */ + /* {{{ Memcached::addServer(string hostname, int port [, int weight ]) Adds the given memcache server to the list */ PHP_METHOD(Memcached, addServer) @@ -3168,11 +3216,31 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_incrementByKey, 0, 0, 2) + ZEND_ARG_INFO(0, server_key) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_decrementByKey, 0, 0, 2) + ZEND_ARG_INFO(0, server_key) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, initial_value) + ZEND_ARG_INFO(0, expiry) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0) @@ -3269,6 +3337,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(increment, arginfo_increment) MEMC_ME(decrement, arginfo_decrement) + MEMC_ME(incrementByKey, arginfo_incrementByKey) + MEMC_ME(decrementByKey, arginfo_decrementByKey) MEMC_ME(addServer, arginfo_addServer) MEMC_ME(addServers, arginfo_addServers) diff --git a/tests/experimental/incrdecr_bykey.phpt b/tests/experimental/incrdecr_bykey.phpt new file mode 100644 index 00000000..ea2bd803 --- /dev/null +++ b/tests/experimental/incrdecr_bykey.phpt @@ -0,0 +1,52 @@ +--TEST-- +Memcached::incrementByKey() Memcached::decrementByKey() +--SKIPIF-- + +--FILE-- +addServer('localhost', 11211, 1); + +echo "Not there\n"; +$m->delete('foo'); +var_dump($m->incrementByKey('foo', 'foo', 1)); +var_dump($m->decrementByKey('foo', 'foo', 1)); +var_dump($m->get('foo')); + +echo "Normal\n"; +$m->set('foo', 1); +var_dump($m->get('foo')); +$m->incrementByKey('foo', 'foo'); +var_dump($m->get('foo')); +$m->incrementByKey('foo', 'foo', 2); +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo'); +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo', 2); +var_dump($m->get('foo')); + +error_reporting(0); +echo "Invalid offset\n"; +$m->incrementByKey('foo', 'foo', -1); +echo $php_errormsg, "\n"; +var_dump($m->get('foo')); +$m->decrementByKey('foo', 'foo', -1); +echo $php_errormsg, "\n"; +var_dump($m->get('foo')); + +--EXPECT-- +Not there +bool(false) +bool(false) +bool(false) +Normal +int(1) +int(2) +int(4) +int(3) +int(1) +Invalid offset +Memcached::incrementByKey(): offset has to be > 0 +int(1) +Memcached::decrementByKey(): offset has to be > 0 +int(1) diff --git a/tests/experimental/incrdecr_initial.phpt b/tests/experimental/incrdecr_initial.phpt new file mode 100644 index 00000000..63d8d008 --- /dev/null +++ b/tests/experimental/incrdecr_initial.phpt @@ -0,0 +1,51 @@ +--TEST-- +Memcached::increment() Memcached::decrement() with initial support +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, 1); +$m->addServer('localhost', 11211, 1); + +$m->delete('foo'); +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 0)); +$m->delete('foo'); + +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 1, 1)); +var_dump($m->increment('foo', 1, 1)); + +var_dump($m->decrement('foo', 1, 1)); +var_dump($m->decrement('foo', 0)); +$m->delete('foo'); + +$m->deleteByKey('foo', 'foo'); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 0)); +$m->deleteByKey('foo', 'foo'); + +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); +var_dump($m->incrementByKey('foo', 'foo', 1, 1)); + +var_dump($m->decrementByKey('foo', 'foo', 1, 1)); +var_dump($m->decrementByKey('foo', 'foo', 0)); +$m->deleteByKey('foo', 'foo'); + +--EXPECT-- +int(1) +int(1) +int(1) +int(2) +int(3) +int(2) +int(2) +int(1) +int(1) +int(1) +int(2) +int(3) +int(2) +int(2) From cd16d7576b75d5bc7eb323d837327cc745c914c8 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 11:14:19 -0400 Subject: [PATCH 083/694] Fixed a bug introduced in prior commit designed to reduce mallocs --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1b328c11..b559cf86 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2619,7 +2619,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* turn off compression for values below the threshold */ - if ((*flags & MEMC_VAL_COMPRESSED) && buf.len < MEMC_G(compression_threshold)) { + if ((*flags & MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { *flags &= ~MEMC_VAL_COMPRESSED; } From 4e42d44da378f3209b2df1dc304178a851f77169 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 11:27:05 -0400 Subject: [PATCH 084/694] Test fixes --- tests/experimental/delete_bykey.phpt | 2 +- tests/rescode.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 1face456..6097edb9 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -37,4 +37,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) NOT FOUND bool(false) -%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE%r +%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE|CLIENT ERROR%r diff --git a/tests/rescode.phpt b/tests/rescode.phpt index 7c279733..1bfd3ec0 100644 --- a/tests/rescode.phpt +++ b/tests/rescode.phpt @@ -77,7 +77,7 @@ NO SERVERS DEFINED %d SUCCESS %d -%rSYSTEM ERROR|WRITE FAILURE%r +%rSYSTEM ERROR|WRITE FAILURE|CONNECTION FAILURE%r bool(true) NOT FOUND NOT FOUND From 09d5c51b410c6aaa01f742b6f9dc89cab7c4c728 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Jun 2011 13:10:22 -0400 Subject: [PATCH 085/694] Eliminate un-necessary allocation routines inside session handling --- php_memcached_session.c | 51 ++++++++--------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index cafa9952..921d20ef 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -44,26 +44,6 @@ ps_module ps_mod_memcached = { PS_MOD(memcached) }; -/* - * Stolen from libmemcached/common.h, because we need it and they don't expose it. - */ -static inline int memcached_validate_key_length(size_t key_length, bool binary) -{ - if (key_length == 0) - return MEMCACHED_BAD_KEY_PROVIDED; - - if (binary) - { - if (key_length > 0xffff) - return MEMCACHED_BAD_KEY_PROVIDED; - } else { - if (key_length >= MEMCACHED_MAX_KEY) - return MEMCACHED_BAD_KEY_PROVIDED; - } - - return MEMCACHED_SUCCESS; -} - static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) { char *lock_key = NULL; @@ -129,8 +109,7 @@ PS_OPEN_FUNC(memcached) status = memcached_server_push(memc_sess, servers); memcached_server_list_free(servers); - if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != - MEMCACHED_SUCCESS) { + if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { PS_SET_MOD_DATA(NULL); memcached_free(memc_sess); php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); @@ -172,15 +151,14 @@ PS_READ_FUNC(memcached) { char *payload = NULL; size_t payload_len = 0; - char *sess_key = NULL; - int sess_key_len = 0; + int key_len = strlen(key); uint32_t flags = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); size_t key_length; - key_length = strlen(MEMC_G(sess_prefix)) + strlen(key) + 5; // prefix + "lock." - if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." + if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; @@ -192,9 +170,7 @@ PS_READ_FUNC(memcached) } } - sess_key_len = spprintf(&sess_key, 0, "%s", key); - payload = memcached_get(memc_sess, sess_key, sess_key_len, &payload_len, &flags, &status); - efree(sess_key); + payload = memcached_get(memc_sess, key, key_len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { *val = estrndup(payload, payload_len); @@ -208,26 +184,23 @@ PS_READ_FUNC(memcached) PS_WRITE_FUNC(memcached) { - char *sess_key = NULL; - int sess_key_len = 0; + int key_len = strlen(key); time_t expiration = 0; memcached_return status; memcached_st *memc_sess = PS_GET_MOD_DATA(); size_t key_length; - key_length = strlen(MEMC_G(sess_prefix)) + strlen(key) + 5; // prefix + "lock." - if (memcached_validate_key_length(key_length, false) != MEMCACHED_SUCCESS) { + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." + if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; } - sess_key_len = spprintf(&sess_key, 0, "%s", key); if (PS(gc_maxlifetime) > 0) { expiration = PS(gc_maxlifetime); } - status = memcached_set(memc_sess, sess_key, sess_key_len, val, vallen, expiration, 0); - efree(sess_key); + status = memcached_set(memc_sess, key, key_len, val, vallen, expiration, 0); if (status == MEMCACHED_SUCCESS) { return SUCCESS; @@ -238,13 +211,9 @@ PS_WRITE_FUNC(memcached) PS_DESTROY_FUNC(memcached) { - char *sess_key = NULL; - int sess_key_len = 0; memcached_st *memc_sess = PS_GET_MOD_DATA(); - sess_key_len = spprintf(&sess_key, 0, "%s", key); - memcached_delete(memc_sess, sess_key, sess_key_len, 0); - efree(sess_key); + memcached_delete(memc_sess, key, strlen(key), 0); if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess TSRMLS_CC); } From f733d2d8059f8b3b84ca83766033103a02684648 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 13 Jun 2011 17:47:42 -0400 Subject: [PATCH 086/694] Added support for persistance inside session that can be turned on by starting the session.save_path INI setting with PERSISTENT=[persistent id]. Added support for memcached server config string --- php_memcached.c | 13 ------ php_memcached.h | 7 +++ php_memcached_session.c | 99 +++++++++++++++++++++++++++++++++-------- 3 files changed, 88 insertions(+), 31 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1437f5c4..e45f8e84 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -207,8 +207,6 @@ enum { MEMC_OP_PREPEND }; -static int le_memc; - static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; @@ -299,7 +297,6 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_list_entry(void); static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); @@ -386,11 +383,6 @@ static PHP_METHOD(Memcached, __construct) plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id); plist_key_len += 1; - if (plist_key == NULL) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate persistent list handler"); - /* not reached */ - } - if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; @@ -2900,11 +2892,6 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload return -1; } -static int php_memc_list_entry(void) -{ - return le_memc; -} - static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) { #ifdef HAVE_MEMCACHED_SESSION diff --git a/php_memcached.h b/php_memcached.h index f0471786..607b40b7 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -98,6 +98,13 @@ PHP_MINFO_FUNCTION(memcached); #define MEMC_G(v) (php_memcached_globals.v) #endif +static int le_memc; + +static int php_memc_list_entry(void) +{ + return le_memc; +} + #endif /* PHP_MEMCACHED_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c index 921d20ef..f043d895 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -99,35 +99,98 @@ static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) PS_OPEN_FUNC(memcached) { memcached_st *memc_sess = PS_GET_MOD_DATA(); - memcached_server_st *servers; memcached_return status; + char *p, *plist_key = NULL; + int plist_key_len; - servers = memcached_servers_parse((char *)save_path); - if (servers) { - memc_sess = memcached_create(NULL); - if (memc_sess) { - status = memcached_server_push(memc_sess, servers); - memcached_server_list_free(servers); - - if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { - PS_SET_MOD_DATA(NULL); - memcached_free(memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); - return FAILURE; - } + if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { + zend_rsrc_list_entry *le = NULL; + char *e; - if (status == MEMCACHED_SUCCESS) { + p = (char *)save_path + sizeof("PERSISTENT=") - 1; + if (!*p) { +error: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid persistent id for session storage"); + return FAILURE; + } + if ((e = strchr(p, ' '))) { + plist_key_len = spprintf(&plist_key, 0, "memcached_sessions:id=%.*s", (int)(e - p), p); + } else { + goto error; + } + plist_key_len++; + if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { + if (le->type == php_memc_list_entry()) { + memc_sess = (struct memc_obj *) le->ptr; PS_SET_MOD_DATA(memc_sess); return SUCCESS; } + } + p = e + 1; + } else { + p = (char *)save_path; + } + + if (!strstr(p, "--SERVER")) { + memcached_server_st *servers = memcached_servers_parse(p); + if (servers) { + memc_sess = memcached_create(NULL); + if (memc_sess) { + status = memcached_server_push(memc_sess, servers); + memcached_server_list_free(servers); + + if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { + PS_SET_MOD_DATA(NULL); + if (plist_key) { + efree(plist_key); + } + memcached_free(memc_sess); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); + return FAILURE; + } + + if (status == MEMCACHED_SUCCESS) { + goto success; + } + } else { + memcached_server_list_free(servers); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); + } } else { - memcached_server_list_free(servers); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); } } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); + memc_sess = memcached(p, strlen(p)); + if (!memc_sess) { + char error_buffer[1024]; + if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); + } + } else { +success: + PS_SET_MOD_DATA(memc_sess); + + if (plist_key) { + zend_rsrc_list_entry le; + + le.type = php_memc_list_entry(); + le.ptr = memc_sess; + + if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + efree(plist_key); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); + } + efree(plist_key); + } + return SUCCESS; + } } + if (plist_key) { + efree(plist_key); + } PS_SET_MOD_DATA(NULL); return FAILURE; } From 4c3045fbfe9ef0fd854128fe622d45fa30a4422d Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 13 Jun 2011 19:13:55 -0400 Subject: [PATCH 087/694] Finalize persistent session handling --- php_memcached.c | 35 +++++++++++++++++++++++---- php_memcached.h | 11 ++++----- php_memcached_session.c | 53 +++++++++++++++++++++++------------------ 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e45f8e84..a34eecd3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -350,6 +350,13 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc return 1; } +static int le_memc, le_memc_sess; + +static int php_memc_list_entry(void) +{ + return le_memc; +} + /* {{{ Memcached::__construct([string persistent_id[, callback on_new]])) Creates a Memcached object, optionally using persistent memcache connection */ static PHP_METHOD(Memcached, __construct) @@ -2444,6 +2451,16 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) rsrc->ptr = NULL; } } + +ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) +{ + if (rsrc->ptr) { + memcached_sess *memc_sess = (memcached_sess *)rsrc->ptr; + memcached_free(memc_sess->memc_sess); + pefree(rsrc->ptr, 1); + rsrc->ptr = NULL; + } +} /* }}} */ /* {{{ internal API functions */ @@ -3447,8 +3464,13 @@ zend_module_entry memcached_module_entry = { NULL, PHP_MINIT(memcached), PHP_MSHUTDOWN(memcached), +#if HAVE_MEMCACHED_SASL PHP_RINIT(memcached), PHP_RSHUTDOWN(memcached), +#else + NULL, + NULL, +#endif PHP_MINFO(memcached), PHP_MEMCACHED_VERSION, STANDARD_MODULE_PROPERTIES @@ -3619,27 +3641,31 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) } /* }}} */ +#if HAVE_MEMCACHED_SASL PHP_RINIT_FUNCTION(memcached) { -#if HAVE_MEMCACHED_SASL if (MEMC_G(use_sasl)) { if (sasl_client_init(NULL) != SASL_OK) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); } } -#endif return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(memcached) { -#if HAVE_MEMCACHED_SASL if (MEMC_G(use_sasl)) { sasl_done(); } -#endif + return SUCCESS; } +#endif + +int php_memc_sess_list_entry(void) +{ + return le_memc_sess; +} /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(memcached) @@ -3650,6 +3676,7 @@ PHP_MINIT_FUNCTION(memcached) memcached_object_handlers.clone_obj = NULL; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); + le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); memcached_ce = zend_register_internal_class(&ce TSRMLS_CC); diff --git a/php_memcached.h b/php_memcached.h index 607b40b7..c5e79301 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -98,16 +98,15 @@ PHP_MINFO_FUNCTION(memcached); #define MEMC_G(v) (php_memcached_globals.v) #endif -static int le_memc; +typedef struct { + memcached_st *memc_sess; + zend_bool is_persisent; +} memcached_sess; -static int php_memc_list_entry(void) -{ - return le_memc; -} +int php_memc_sess_list_entry(void); #endif /* PHP_MEMCACHED_H */ - /* * Local variables: * tab-width: 4 diff --git a/php_memcached_session.c b/php_memcached_session.c index f043d895..e76f7088 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -98,7 +98,7 @@ static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) PS_OPEN_FUNC(memcached) { - memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_sess *memc_sess = PS_GET_MOD_DATA(); memcached_return status; char *p, *plist_key = NULL; int plist_key_len; @@ -120,31 +120,35 @@ PS_OPEN_FUNC(memcached) } plist_key_len++; if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { - if (le->type == php_memc_list_entry()) { - memc_sess = (struct memc_obj *) le->ptr; + if (le->type == php_memc_sess_list_entry()) { + memc_sess = (struct memcached_sess *) le->ptr; PS_SET_MOD_DATA(memc_sess); return SUCCESS; } } p = e + 1; + memc_sess = pecalloc(sizeof(*memc_sess), 1, 1); + memc_sess->is_persisent = 1; } else { p = (char *)save_path; + memc_sess = ecalloc(sizeof(*memc_sess), 1); + memc_sess->is_persisent = 0; } if (!strstr(p, "--SERVER")) { memcached_server_st *servers = memcached_servers_parse(p); if (servers) { - memc_sess = memcached_create(NULL); - if (memc_sess) { - status = memcached_server_push(memc_sess, servers); + memc_sess->memc_sess = memcached_create(NULL); + if (memc_sess->memc_sess) { + status = memcached_server_push(memc_sess->memc_sess, servers); memcached_server_list_free(servers); - if (memcached_callback_set(memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { + if (memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { PS_SET_MOD_DATA(NULL); if (plist_key) { efree(plist_key); } - memcached_free(memc_sess); + memcached_free(memc_sess->memc_sess); php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); return FAILURE; } @@ -160,8 +164,8 @@ PS_OPEN_FUNC(memcached) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); } } else { - memc_sess = memcached(p, strlen(p)); - if (!memc_sess) { + memc_sess->memc_sess = memcached(p, strlen(p)); + if (!memc_sess->memc_sess) { char error_buffer[1024]; if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); @@ -175,7 +179,7 @@ PS_OPEN_FUNC(memcached) if (plist_key) { zend_rsrc_list_entry le; - le.type = php_memc_list_entry(); + le.type = php_memc_sess_list_entry(); le.ptr = memc_sess; if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { @@ -197,13 +201,16 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { - memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_sess *memc_sess = PS_GET_MOD_DATA(); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); } - if (memc_sess) { - memcached_free(memc_sess); + if (memc_sess->memc_sess) { + if (!memc_sess->is_persisent) { + memcached_free(memc_sess->memc_sess); + efree(memc_sess); + } PS_SET_MOD_DATA(NULL); } @@ -217,7 +224,7 @@ PS_READ_FUNC(memcached) int key_len = strlen(key); uint32_t flags = 0; memcached_return status; - memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." @@ -228,12 +235,12 @@ PS_READ_FUNC(memcached) } if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess, key TSRMLS_CC) < 0) { + if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) { return FAILURE; } } - payload = memcached_get(memc_sess, key, key_len, &payload_len, &flags, &status); + payload = memcached_get(memc_sess->memc_sess, key, key_len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { *val = estrndup(payload, payload_len); @@ -250,7 +257,7 @@ PS_WRITE_FUNC(memcached) int key_len = strlen(key); time_t expiration = 0; memcached_return status; - memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." @@ -263,7 +270,7 @@ PS_WRITE_FUNC(memcached) if (PS(gc_maxlifetime) > 0) { expiration = PS(gc_maxlifetime); } - status = memcached_set(memc_sess, key, key_len, val, vallen, expiration, 0); + status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0); if (status == MEMCACHED_SUCCESS) { return SUCCESS; @@ -274,11 +281,11 @@ PS_WRITE_FUNC(memcached) PS_DESTROY_FUNC(memcached) { - memcached_st *memc_sess = PS_GET_MOD_DATA(); + memcached_sess *memc_sess = PS_GET_MOD_DATA(); - memcached_delete(memc_sess, key, strlen(key), 0); + memcached_delete(memc_sess->memc_sess, key, strlen(key), 0); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); } return SUCCESS; From db2fc7895f27315b5f3a624dcd241ea155b53116 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Thu, 16 Jun 2011 01:45:45 +0200 Subject: [PATCH 088/694] Make sasl disablable. ./configure --disable-memcached-sasl --- config.m4 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/config.m4 b/config.m4 index 0c999eab..99989062 100644 --- a/config.m4 +++ b/config.m4 @@ -17,6 +17,9 @@ PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support, [ --enable-memcached-json Enable memcached json serializer support], no, no) +PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, +[ --disable-memcached-sasl Disable memcached sasl support], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) @@ -226,10 +229,12 @@ if test "$PHP_MEMCACHED" != "no"; then fi done fi - - AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) - AC_MSG_CHECKING([whether to enable sasl support]) - AC_MSG_RESULT([$memcached_enable_sasl]) + + if test "$PHP_MEMCACHED_SASL" != "no"; then + AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) + AC_MSG_CHECKING([whether to enable sasl support]) + AC_MSG_RESULT([$memcached_enable_sasl]) + fi AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" = "no"; then From 494f2c14be36187b28fb8135274abb58518f59fd Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Thu, 16 Jun 2011 15:33:06 +0200 Subject: [PATCH 089/694] Added support for TOUCH. memcached_touch($key, $expiration = 0); memcached_touch_by_key($key, $server_key, $expiration = 0); $m->touch($key, $expiration = 0); $m->touchByKey($key, $expiration = 0); Throws an E_WARNING if called on connections with the text protocol. --- memcached-api.php | 4 ++++ php_memcached.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ tests/expire.phpt | 26 +++++++++++++++++++-- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 73347d72..75522950 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -201,6 +201,10 @@ public function fetchAll( ) {} public function set( $key, $value, $expiration = 0 ) {} + public function touch( $key, $expiration = 0 ) {} + + public function touchbyKey( $key, $expiration = 0 ) {} + public function setByKey( $server_key, $key, $value, $expiration = 0 ) {} public function setMulti( array $items, $expiration = 0 ) {} diff --git a/php_memcached.c b/php_memcached.c index b559cf86..a07e31fd 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -198,6 +198,7 @@ typedef struct { enum { MEMC_OP_SET, + MEMC_OP_TOUCH, MEMC_OP_ADD, MEMC_OP_REPLACE, MEMC_OP_APPEND, @@ -1090,6 +1091,24 @@ PHP_METHOD(Memcached, setByKey) } /* }}} */ +/* {{{ Memcached::touch(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touch) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); +} +/* }}} */ + +/* {{{ Memcached::touchbyKey(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touchByKey) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); +} +/* }}} */ + + + /* {{{ Memcached::setMulti(array items [, int expiration ]) Sets the keys/values specified in the items array */ PHP_METHOD(Memcached, setMulti) @@ -1274,6 +1293,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool INIT_ZVAL(s_zvalue); value = &s_zvalue; ZVAL_STRINGL(value, s_value, s_value_len, 0); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key, + &server_key_len, &key, &key_len, &expiration) == FAILURE) { + return; + } } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|l", &server_key, &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) { @@ -1289,6 +1313,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool INIT_ZVAL(s_zvalue); value = &s_zvalue; ZVAL_STRINGL(value, s_value, s_value_len, 0); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, + &key_len, &expiration) == FAILURE) { + return; + } } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &key, &key_len, &value, &expiration) == FAILURE) { @@ -1318,6 +1347,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool flags |= MEMC_VAL_COMPRESSED; } + if (op == MEMC_OP_TOUCH && !memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); + RETURN_FALSE; + } + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1334,6 +1368,16 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } break; + case MEMC_OP_TOUCH: + if (!server_key) { + status = memcached_touch(m_obj->memc, key, key_len, expiration); + } else { + status = memcached_touch_by_key(m_obj->memc, server_key, server_key_len, key, + key_len, expiration); + } + break; + + case MEMC_OP_ADD: if (!server_key) { status = memcached_add(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); @@ -3113,6 +3157,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, expiration) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_touchByKey, 0, 0, 3) + ZEND_ARG_INFO(0, server_key) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, expiration) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) @@ -3317,6 +3372,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) + MEMC_ME(touch, arginfo_touch) + MEMC_ME(touchByKey, arginfo_touchByKey) MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) diff --git a/tests/expire.phpt b/tests/expire.phpt index 6e406d42..959b7eff 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -1,10 +1,11 @@ --TEST-- -Memcached store & fetch expired key +Memcached store, fetch & touch expired key --SKIPIF-- --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, true); $m->addServer('127.0.0.1', 11211, 1); $set = $m->set('will_expire', "foo", 2); @@ -12,6 +13,16 @@ $v = $m->get('will_expire'); if (!$set || $v != 'foo') { echo "Error setting will_expire to \"foo\" with 2s expiry.\n"; } +sleep(1); +$res = $m->touch('will_expire', 2); +$v = $m->get('will_expire'); +if(!$res || $v != 'foo') { + echo "Error touching will_expire for another 2s expiry.\n"; + var_dump($res); + var_dump($m->getResultMessage()); + var_dump($v); +} + sleep(3); $v = $m->get('will_expire'); @@ -22,7 +33,18 @@ if ($v !== Memcached::GET_ERROR_RETURN_VALUE) { var_dump($v); } +// test with plaintext proto should throw error +$m = new Memcached(); +$m->addServer('127.0.0.1', 11211, 1); + +$set = $m->set('will_expire', "foo", 2); +$v = $m->touch('will_expire'); +if($v !== false) { + echo "Touch with text protocol should return false.\n"; +} + echo "OK\n"; ?> ---EXPECT-- +--EXPECTF-- +Warning: Memcached::touch(): touch is only supported with binary protocol in %s on line %d OK \ No newline at end of file From 2a47a9d7cee37414893970b3678307108a5670ad Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 21 Jun 2011 08:25:10 -0400 Subject: [PATCH 090/694] Update changelog --- ChangeLog | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2e338846..11d9fa9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,23 @@ Version ******* * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. + * Session Support + - Added support for libmemcached config string + - Added persistence support via PERSISTENT=persistent_id prefix + of the save_path + - Optimized code by removing unnecessary allocation + * Added 3rd parameter to the __construct() that allows specification + of libmemcached configuration string + * Fixed a possible crash in __construct() when using persistent + connections + * Added work-around a bug in libmemcached < 0.5 that causes truncation + of last character of server key prefix + * When using multiple servers implement transparent fail-over + * Fixed php_memc_cas_impl() implementation when server_key is not being used + * Optimize set* operations for scalar values + * Added support for incrementByKey() and decrementByKey() + * When using binary protocol allow increment/decrement to initialize value + when it is not available. Version 2.0.0b1 --------------- From 45aa53ff2dd8d8b5c3f1ad4fda7476b21930d8cc Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 21 Jun 2011 08:33:26 -0400 Subject: [PATCH 091/694] Initialize struct to avoid errors --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index b6caecd2..849a80d7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -371,7 +371,7 @@ static PHP_METHOD(Memcached, __construct) char *plist_key = NULL; int plist_key_len = 0; - zend_fcall_info fci; + zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f!s", &persistent_id, &persistent_id_len, &fci, &fci_cache, &conn_str, &conn_str_len) == FAILURE) { From df9fc6360eaad4c368e04dc720e5d37edb78c771 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 22 Jun 2011 07:04:26 -0400 Subject: [PATCH 092/694] Allow compilation with newer PHP versions (patch by Bob Vincent) --- php_memcached.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 849a80d7..89f411ef 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2457,7 +2457,11 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) i_obj = ecalloc(1, sizeof(*i_obj)); zend_object_std_init( &i_obj->zo, ce TSRMLS_CC ); +#ifdef ZEND_ENGINE_2_4 + object_properties_init( (zend_object *) i_obj, ce); +#else zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); +#endif retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); retval.handlers = &memcached_object_handlers; From a00f7cd6aa2a72cc9d01ac6fef065e20a9a3cb0e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 23 Jun 2011 12:08:36 -0400 Subject: [PATCH 093/694] Fixed a possible un-initialized access --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 849a80d7..3cca344c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1129,7 +1129,7 @@ PHP_METHOD(Memcached, setMultiByKey) /* }}} */ #define PHP_MEMC_FAILOVER_RETRY \ - if (!server_key && retry < 2) { \ + if (by_key && retry < 2) { \ switch (i_obj->rescode) { \ case MEMCACHED_HOST_LOOKUP_FAILURE: \ case MEMCACHED_CONNECTION_FAILURE: \ From 1416a09d1d0e78cea5fec227744c1fe7b352017b Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 24 Jun 2011 12:03:13 -0700 Subject: [PATCH 094/694] Release 2.0.0b2. --- ChangeLog | 24 ++++++++--------- package.xml | 72 ++++++++++++++++++++++++++++++++----------------- php_memcached.h | 2 +- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11d9fa9d..4f4a6788 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,27 +1,25 @@ memcached extension changelog -Version ******* +Version 2.0.0b2 --------------- * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. - * Session Support - - Added support for libmemcached config string - - Added persistence support via PERSISTENT=persistent_id prefix + * Improve session support: + - Add support for libmemcached config string + - Add persistence support via PERSISTENT=persistent_id prefix of the save_path - - Optimized code by removing unnecessary allocation - * Added 3rd parameter to the __construct() that allows specification + * Add 3rd parameter to the __construct() that allows specification of libmemcached configuration string - * Fixed a possible crash in __construct() when using persistent + * Fix a possible crash in __construct() when using persistent connections - * Added work-around a bug in libmemcached < 0.5 that causes truncation + * Add work-around a bug in libmemcached < 0.50 that causes truncation of last character of server key prefix * When using multiple servers implement transparent fail-over - * Fixed php_memc_cas_impl() implementation when server_key is not being used - * Optimize set* operations for scalar values - * Added support for incrementByKey() and decrementByKey() - * When using binary protocol allow increment/decrement to initialize value - when it is not available. + * Fix php_memc_cas_impl() implementation when server_key is not being used + * Add support for incrementByKey() and decrementByKey() + * Make increment/decrement initialize value when it is not available (when + using binary protocol) Version 2.0.0b1 --------------- diff --git a/package.xml b/package.xml index 3436757f..75757321 100644 --- a/package.xml +++ b/package.xml @@ -15,10 +15,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2011-03-12 + 2011-06-24 - 2.0.0b1 - 2.0.0b1 + 2.0.0b2 + 2.0.0b2 beta @@ -26,28 +26,24 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Change the return value for non-existing keys to be NULL rather than - 'false', affects simple get only -- Add fastlz library that provides better/faster payload compression -- Add configure switch to enable/disable JSON serialization support -- Add getAllKeys() method -- Add deleteMulti() and deleteMultiByKey() methods -- Add isPristine() and isPersistent() methods -- Add setOptions() method to set multiple options at once -- Add SERIALIZER_JSON_ARRAY type that decodes JSON payloads as arrays - instead of objects -- Add support for Unix domain socket connections -- Add memcached.compression_threshold INI setting -- Add memcached.compression_factor INI setting -- Add memcached.compression_type INI setting -- Implement a few speed optimizations -- Many bug fixes and memory leaks plugged -- Add several more tests -- Add constants for libmemcached 0.37+: - * Memcached::OPT_NUMBER_OF_REPLICAS - * Memcached::OPT_RANDOMIZE_REPLICA_READ -- Add 'on_new' callback to constructor -- Add SASL support +- Add OPT_REMOVE_FAILED_SERVERS option. +- Make it work with libmemcached up to 0.49. +- Fix a case where invalid session ID could lock the script. +- Improve session support: + * Add support for libmemcached config string + * Add persistence support via PERSISTENT=persistent_id prefix + of the save_path +- Add 3rd parameter to the __construct() that allows specification + of libmemcached configuration string +- Fix a possible crash in __construct() when using persistent + connections +- Add work-around a bug in libmemcached < 0.50 that causes truncation + of last character of server key prefix +- When using multiple servers implement transparent fail-over +- Fix php_memc_cas_impl() implementation when server_key is not being used +- Add support for incrementByKey() and decrementByKey() +- Make increment/decrement initialize value when it is not available (when + using binary protocol) @@ -87,6 +83,32 @@ http://pear.php.net/dtd/package-2.0.xsd"> + betabeta + 2.0.0b22.0.0b2 + 2011-06-24 + +- Add OPT_REMOVE_FAILED_SERVERS option. +- Make it work with libmemcached up to 0.49. +- Fix a case where invalid session ID could lock the script. +- Improve session support: + * Add support for libmemcached config string + * Add persistence support via PERSISTENT=persistent_id prefix + of the save_path +- Add 3rd parameter to the __construct() that allows specification + of libmemcached configuration string +- Fix a possible crash in __construct() when using persistent + connections +- Add work-around a bug in libmemcached < 0.50 that causes truncation + of last character of server key prefix +- When using multiple servers implement transparent fail-over +- Fix php_memc_cas_impl() implementation when server_key is not being used +- Add support for incrementByKey() and decrementByKey() +- Make increment/decrement initialize value when it is not available (when + using binary protocol) + + + + betabeta 2.0.0b12.0.0b1 2011-03-12 diff --git a/php_memcached.h b/php_memcached.h index c5e79301..d5edcee1 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -90,7 +90,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0-dev" +#define PHP_MEMCACHED_VERSION "2.0.0b2" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From 721780236a0488db9b40a54abb823cdeb837a13d Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 24 Jun 2011 12:32:59 -0700 Subject: [PATCH 095/694] Back to -dev. --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index d5edcee1..c5e79301 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -90,7 +90,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0b2" +#define PHP_MEMCACHED_VERSION "2.0.0-dev" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From 1281f77d4d5cd6b0bc5868cb4386730079662207 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 29 Jun 2011 06:08:47 -0400 Subject: [PATCH 096/694] Fixed fail-over condition --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index aecdc4f1..d199b504 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1129,7 +1129,7 @@ PHP_METHOD(Memcached, setMultiByKey) /* }}} */ #define PHP_MEMC_FAILOVER_RETRY \ - if (by_key && retry < 2) { \ + if (!by_key && retry < 2) { \ switch (i_obj->rescode) { \ case MEMCACHED_HOST_LOOKUP_FAILURE: \ case MEMCACHED_CONNECTION_FAILURE: \ From 014df25943cf4330ab3ad894ae7ba0908fab919b Mon Sep 17 00:00:00 2001 From: David Sklar Date: Thu, 7 Jul 2011 12:29:33 -0400 Subject: [PATCH 097/694] Add resetServerList() and quit() --- php_memcached.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index d199b504..039ea453 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1938,6 +1938,40 @@ PHP_METHOD(Memcached, getServerByKey) } /* }}} */ +/* {{{ Memcached::resetServerList() + Reset the server list in use */ +PHP_METHOD(Memcached, resetServerList) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_servers_reset(m_obj->memc); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::quit() + Close any open connections */ +PHP_METHOD(Memcached, quit) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_quit(m_obj->memc); + RETURN_TRUE; +} +/* }}} */ + /* {{{ Memcached::getStats() Returns statistics for the memcache servers */ PHP_METHOD(Memcached, getStats) @@ -3357,6 +3391,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getServerList, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_resetServerList, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_quit, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0) ZEND_ARG_INFO(0, server_key) ZEND_END_ARG_INFO() @@ -3441,6 +3481,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(addServers, arginfo_addServers) MEMC_ME(getServerList, arginfo_getServerList) MEMC_ME(getServerByKey, arginfo_getServerByKey) + MEMC_ME(resetServerList, arginfo_resetServerList) + MEMC_ME(quit, arginfo_quit) MEMC_ME(getStats, arginfo_getStats) MEMC_ME(getVersion, arginfo_getVersion) From 473c63e7e7965ca1c698a6df0540fefed3e1d8f5 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Tue, 26 Jul 2011 17:02:23 -0700 Subject: [PATCH 098/694] Use proper version check. --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index d199b504..a965d6c3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2457,7 +2457,7 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) i_obj = ecalloc(1, sizeof(*i_obj)); zend_object_std_init( &i_obj->zo, ce TSRMLS_CC ); -#ifdef ZEND_ENGINE_2_4 +#if PHP_VERSION_ID >= 50400 object_properties_init( (zend_object *) i_obj, ce); #else zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); From c4b25424c10940da319f7bfc4df2460f7cb20f93 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 27 Sep 2011 20:21:06 -0400 Subject: [PATCH 099/694] Optimize setMulti() --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d199b504..34c2f1f5 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1212,12 +1212,12 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke RETURN_FALSE; } +retry: if (!by_key) { - server_key = str_key; - server_key_len = str_key_len-1; + status = memcached_set(m_obj->memc, str_key, str_key_len-1, payload, payload_len, expiration, flags); + } else { + status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags); } -retry: - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags); if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { PHP_MEMC_FAILOVER_RETRY From 55d57a3ef1bf86d25d9f69077442443694a8dd01 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 17 Oct 2011 16:19:33 -0400 Subject: [PATCH 100/694] Fixed bug #59956 (Additional path to search for igbinary.h) --- config.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.m4 b/config.m4 index 278553a4..32b7eae9 100644 --- a/config.m4 +++ b/config.m4 @@ -168,6 +168,8 @@ if test "$PHP_MEMCACHED" != "no"; then igbinary_inc_path="$abs_srcdir" elif test -f "$phpincludedir/ext/session/igbinary.h"; then igbinary_inc_path="$phpincludedir" + elif test -f "$phpincludedir/ext/igbinary/igbinary.h"; then + igbinary_inc_path="$phpincludedir" else for i in php php4 php5 php6; do if test -f "$prefix/include/$i/ext/igbinary/igbinary.h"; then From 77f0139485587e9f5e8089a043f4c1f867ecea8e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 20 Oct 2011 10:58:47 -0400 Subject: [PATCH 101/694] Cleanup parameter parsing --- php_memcached.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d82bbe43..96d567a6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -991,7 +991,7 @@ PHP_METHOD(Memcached, fetch) memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1048,7 +1048,7 @@ PHP_METHOD(Memcached, fetchAll) memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1884,7 +1884,7 @@ PHP_METHOD(Memcached, getServerList) memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1944,7 +1944,7 @@ PHP_METHOD(Memcached, resetServerList) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1961,7 +1961,7 @@ PHP_METHOD(Memcached, quit) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1982,7 +1982,7 @@ PHP_METHOD(Memcached, getStats) memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2023,7 +2023,7 @@ PHP_METHOD(Memcached, getVersion) memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2374,7 +2374,7 @@ static PHP_METHOD(Memcached, getResultCode) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2390,7 +2390,7 @@ static PHP_METHOD(Memcached, getResultMessage) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2426,7 +2426,7 @@ static PHP_METHOD(Memcached, isPersistent) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2442,7 +2442,7 @@ static PHP_METHOD(Memcached, isPristine) { MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } From 0b3765a7aa73149a1de42a95df290eb833c44b10 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Thu, 29 Dec 2011 13:47:22 -0800 Subject: [PATCH 102/694] Check for MEMCACHED_DATA_EXISTS also when setting lock. --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index e76f7088..4b445e03 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -73,7 +73,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) MEMC_G(sess_lock_key) = lock_key; MEMC_G(sess_lock_key_len) = lock_key_len; return 0; - } else if (status != MEMCACHED_NOTSTORED) { + } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) { break; } From 766a16d4e6678b780c301cb0be10594974720c01 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Thu, 29 Dec 2011 14:02:12 -0800 Subject: [PATCH 103/694] Avoid overflow error. --- php_memcached_session.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 4b445e03..04e6a63f 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -48,7 +48,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) { char *lock_key = NULL; int lock_key_len = 0; - long attempts; + unsigned long attempts; long lock_maxwait; long lock_wait = MEMC_G(sess_lock_wait); time_t expiration; @@ -63,7 +63,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; } expiration = time(NULL) + lock_maxwait + 1; - attempts = lock_maxwait * 1000000 / lock_wait; + attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); do { @@ -121,7 +121,7 @@ PS_OPEN_FUNC(memcached) plist_key_len++; if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { if (le->type == php_memc_sess_list_entry()) { - memc_sess = (struct memcached_sess *) le->ptr; + memc_sess = (memcached_sess *) le->ptr; PS_SET_MOD_DATA(memc_sess); return SUCCESS; } From b73b8100e420d4c7bfee6e8db748f47a6f578dce Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Thu, 29 Dec 2011 14:13:32 -0800 Subject: [PATCH 104/694] Support for binary protocol in sessions. (patch from trevor@blubolt.com) --- memcached.ini | 3 +++ php_memcached.c | 2 ++ php_memcached.h | 1 + php_memcached_session.c | 8 ++++++++ 4 files changed, 14 insertions(+) diff --git a/memcached.ini b/memcached.ini index 9767e184..cc11b25c 100644 --- a/memcached.ini +++ b/memcached.ini @@ -17,6 +17,9 @@ memcached.sess_lock_wait = 150000 ; the default value is "memc.sess.key." memcached.sess_prefix = "memc.sess.key." +; memcached session binary mode +memcached.sess_binary = Off + ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz diff --git a/php_memcached.c b/php_memcached.c index 67e9909b..0397c19f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -281,6 +281,7 @@ static PHP_INI_MH(OnUpdateSerializer) PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) #endif @@ -3017,6 +3018,7 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob { #ifdef HAVE_MEMCACHED_SESSION MEMC_G(sess_locking_enabled) = 1; + MEMC_G(sess_binary_enabled) = 1; MEMC_G(sess_prefix) = NULL; MEMC_G(sess_lock_wait) = 0; MEMC_G(sess_locked) = 0; diff --git a/php_memcached.h b/php_memcached.h index c5e79301..811ceac3 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -78,6 +78,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif + zend_bool sess_binary_enabled; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/php_memcached_session.c b/php_memcached_session.c index 04e6a63f..bbd96b6a 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -188,6 +188,14 @@ PS_OPEN_FUNC(memcached) } efree(plist_key); } + + if (MEMC_G(sess_binary_enabled)) { + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + return FAILURE; + } + } + return SUCCESS; } } From bfe46dee0a8dd2836145f20dfd623874ee5eb896 Mon Sep 17 00:00:00 2001 From: zextra Date: Wed, 15 Feb 2012 01:52:58 +0100 Subject: [PATCH 105/694] Changed non-working igbinary URL --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 7a8041e4..b218c8c9 100644 --- a/README.markdown +++ b/README.markdown @@ -11,4 +11,4 @@ Resources --------- * [libmemcached](http://tangent.org/552/libmemcached.html) * [memcached](http://www.danga.com/memcached/) - * [igbinary](http://opensource.dynamoid.com/) + * [igbinary](https://github.com/phadej/igbinary/) From 41fbaace23b20e9c546246d31256cda8b32a869d Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 2 Mar 2012 14:48:51 -0500 Subject: [PATCH 106/694] Fix some tests. --- tests/experimental/get_udp.phpt | 2 +- tests/experimental/getmulti_badserver.phpt | 1 + tests/experimental/getversion.phpt | 3 +-- tests/experimental/moduleinfo.phpt | 2 +- tests/expire.phpt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/experimental/get_udp.phpt b/tests/experimental/get_udp.phpt index 6d196cab..d59ada41 100644 --- a/tests/experimental/get_udp.phpt +++ b/tests/experimental/get_udp.phpt @@ -8,8 +8,8 @@ $m = new Memcached(); $m->addServer('127.0.0.1', 11211, 1); $m_udp = new Memcached(); -$m_udp->setOption(Memcached::OPT_USE_UDP, true); $m_udp->addServer('127.0.0.1', 11211, 1); +$m_udp->setOption(Memcached::OPT_USE_UDP, true); error_reporting(0); diff --git a/tests/experimental/getmulti_badserver.phpt b/tests/experimental/getmulti_badserver.phpt index f1a221de..7856db0e 100644 --- a/tests/experimental/getmulti_badserver.phpt +++ b/tests/experimental/getmulti_badserver.phpt @@ -27,3 +27,4 @@ array(0) { NO SERVERS DEFINED array(0) { } +3: CONNECTION FAILURE diff --git a/tests/experimental/getversion.phpt b/tests/experimental/getversion.phpt index 0df50cbf..509ff5d5 100644 --- a/tests/experimental/getversion.phpt +++ b/tests/experimental/getversion.phpt @@ -13,8 +13,7 @@ $stats = $m->getVersion(); var_dump($stats); --EXPECTF-- -array(0) { -} +bool(false) array(%d) { ["%s:%d"]=> string(%d) "%s" diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index a7eab08d..bf57aecb 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -23,7 +23,7 @@ memcached.compression_factor => %f => %f memcached.compression_threshold => %d => %d memcached.compression_type => %s => %s memcached.serializer => %s => %s +memcached.sess_binary => %d => %d memcached.sess_lock_wait => %d => %d memcached.sess_locking => %d => %d memcached.sess_prefix => %s => %s -memcached.use_sasl => %s => %s diff --git a/tests/expire.phpt b/tests/expire.phpt index 959b7eff..17ddcc1e 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -47,4 +47,4 @@ echo "OK\n"; ?> --EXPECTF-- Warning: Memcached::touch(): touch is only supported with binary protocol in %s on line %d -OK \ No newline at end of file +OK From f6360fb6b5f3787e856e3308334641472d791196 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 2 Mar 2012 14:49:08 -0500 Subject: [PATCH 107/694] Fix segfault with touch command. --- php_memcached.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 0397c19f..4b75e0e9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1114,6 +1114,7 @@ PHP_METHOD(Memcached, setByKey) } /* }}} */ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 /* {{{ Memcached::touch(string key, [, int expiration ]) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) @@ -1129,7 +1130,7 @@ PHP_METHOD(Memcached, touchByKey) php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ - +#endif /* {{{ Memcached::setMulti(array items [, int expiration ]) @@ -1398,15 +1399,17 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool flags |= MEMC_VAL_COMPRESSED; } - if (op == MEMC_OP_TOUCH && !memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); - RETURN_FALSE; - } - - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); - if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; + if (op == MEMC_OP_TOUCH) { + if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); + RETURN_FALSE; + } + } else { + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + if (payload == NULL) { + i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + RETURN_FALSE; + } } retry: switch (op) { @@ -1477,7 +1480,10 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } else { RETVAL_TRUE; } - efree(payload); + + if (op != MEMC_OP_TOUCH) { + efree(payload); + } } /* }}} */ @@ -2170,7 +2176,7 @@ static PHP_METHOD(Memcached, getOption) char *result; result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); - if (retval == MEMCACHED_SUCCESS) { + if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 RETURN_STRINGL(result, strlen(result) - 1, 1); #else @@ -3511,8 +3517,10 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 MEMC_ME(touch, arginfo_touch) MEMC_ME(touchByKey, arginfo_touchByKey) +#endif MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) From 384ade6cd7e2b0faa210e023ee202abc29332f34 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 2 Mar 2012 15:27:19 -0500 Subject: [PATCH 108/694] Release 2.0.0 --- ChangeLog | 8 ++++++++ package.xml | 46 +++++++++++++++++++++++----------------------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f4a6788..b5d398be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ memcached extension changelog +Version 2.0.0 +------------- + * Add touch() and touchByKey() methods + * Add resetServerList() and quit() methods + * Support binary protocol in sessions + * Make it work with libmemcached up to 1.0.4 + * Test against PHP 5.4.0 + Version 2.0.0b2 --------------- * Add OPT_REMOVE_FAILED_SERVERS option. diff --git a/package.xml b/package.xml index 75757321..3bdb704f 100644 --- a/package.xml +++ b/package.xml @@ -15,35 +15,22 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2011-06-24 + 2012-03-02 - 2.0.0b2 - 2.0.0b2 + 2.0.0 + 2.0.0 - beta - beta + stable + stable PHP -- Add OPT_REMOVE_FAILED_SERVERS option. -- Make it work with libmemcached up to 0.49. -- Fix a case where invalid session ID could lock the script. -- Improve session support: - * Add support for libmemcached config string - * Add persistence support via PERSISTENT=persistent_id prefix - of the save_path -- Add 3rd parameter to the __construct() that allows specification - of libmemcached configuration string -- Fix a possible crash in __construct() when using persistent - connections -- Add work-around a bug in libmemcached < 0.50 that causes truncation - of last character of server key prefix -- When using multiple servers implement transparent fail-over -- Fix php_memc_cas_impl() implementation when server_key is not being used -- Add support for incrementByKey() and decrementByKey() -- Make increment/decrement initialize value when it is not available (when - using binary protocol) +- Add touch() and touchByKey() methods +- Add resetServerList() and quit() methods +- Support binary protocol in sessions +- Make it work with libmemcached up to 1.0.4 +- Test against PHP 5.4.0 @@ -83,6 +70,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> + stablestable + 2.0.02.0.0 + 2012-03-02 + +- Add touch() and touchByKey() methods +- Add resetServerList() and quit() methods +- Support binary protocol in sessions +- Make it work with libmemcached up to 1.0.4 +- Test against PHP 5.4.0 + + + + betabeta 2.0.0b22.0.0b2 2011-06-24 From 1ad9a2b593af1d950b67ca4f774b847eca54820c Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sat, 3 Mar 2012 09:54:27 -0500 Subject: [PATCH 109/694] Fix version number and repackage. --- ChangeLog | 4 ++++ package.xml | 21 +++++++++++++-------- php_memcached.h | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index b5d398be..d356e3c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ memcached extension changelog +Version 2.0.1 +------------- + * Fix embedded version number to be not -dev + Version 2.0.0 ------------- * Add touch() and touchByKey() methods diff --git a/package.xml b/package.xml index 3bdb704f..c89fae2b 100644 --- a/package.xml +++ b/package.xml @@ -15,10 +15,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2012-03-02 + 2012-03-03 - 2.0.0 - 2.0.0 + 2.0.1 + 2.0.1 stable @@ -26,11 +26,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Add touch() and touchByKey() methods -- Add resetServerList() and quit() methods -- Support binary protocol in sessions -- Make it work with libmemcached up to 1.0.4 -- Test against PHP 5.4.0 +- Fix embedded version number to be not -dev @@ -69,6 +65,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached + + stablestable + 2.0.12.0.1 + 2012-03-03 + +- Fix embedded version number to be not -dev + + + stablestable 2.0.02.0.0 diff --git a/php_memcached.h b/php_memcached.h index 811ceac3..18b1898d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -91,7 +91,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0-dev" +#define PHP_MEMCACHED_VERSION "2.0.0" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From aeb14874972836ef2fadb1e7633cd85c3ea25e8e Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sat, 3 Mar 2012 09:55:42 -0500 Subject: [PATCH 110/694] Really update now, to 2.0.1. --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 18b1898d..a7c8cfb0 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -91,7 +91,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.0" +#define PHP_MEMCACHED_VERSION "2.0.1" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From 3943c789f128194a0a1b8607d94b550da8c26678 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Tue, 6 Mar 2012 21:42:06 -0800 Subject: [PATCH 111/694] Define zend_parse_parameters_none() for < 5.3. --- php_memcached.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 4b75e0e9..62e7b095 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -172,6 +172,12 @@ typedef unsigned long int uint32_t; #define RETURN_FROM_GET RETURN_FALSE +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3) +#define zend_parse_parameters_none() \ + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") +#endif + + /**************************************** Structures and definitions ****************************************/ From 0c7b569adc1943b1be4aac6276ac438f0596708d Mon Sep 17 00:00:00 2001 From: bruno Date: Mon, 23 Apr 2012 19:49:57 -0300 Subject: [PATCH 112/694] Added virtual buckets support by implementation of memcached_bucket_set bindings. --- memcached-api.php | 8 +++- php_memcached.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 75522950..5c46d5eb 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -34,6 +34,8 @@ class Memcached { const DISTRIBUTION_MODULA; const DISTRIBUTION_CONSISTENT; + + const DISTRIBUTION_VIRTUAL_BUCKET; const LIBKETAMA_COMPATIBLE; @@ -201,9 +203,9 @@ public function fetchAll( ) {} public function set( $key, $value, $expiration = 0 ) {} - public function touch( $key, $expiration = 0 ) {} + public function touch( $key, $expiration = 0 ) {} - public function touchbyKey( $key, $expiration = 0 ) {} + public function touchbyKey( $key, $expiration = 0 ) {} public function setByKey( $server_key, $key, $value, $expiration = 0 ) {} @@ -249,6 +251,8 @@ public function setOption( $option, $value ) {} public function setOptions( array $options ) {} + public function setBucket( array $host_map, array $forward_map, $buckets, $replicas ) {} + public function addServer( $host, $port, $weight = 0 ) {} public function addServers( array $servers ) {} diff --git a/php_memcached.c b/php_memcached.c index 4b75e0e9..b4927b05 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2333,6 +2333,99 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML return 1; } +/* {{{ Memcached::setBucket(array host_map, array forward_map, long buckets, long replicas) + Sets the memcached virtual buckets */ + +PHP_METHOD(Memcached, setBucket) +{ + zval *host_map; + zval *forward_map; + long buckets; + long replicas; + + uint32_t *hm = NULL,*fm = NULL; + zend_bool ok = 1; + uint key_len; + char *key; + ulong key_index; + zval **value; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!ll", &host_map, &forward_map, &buckets, &replicas) == FAILURE) { + return; + } + + + hm = (uint32_t*)malloc(buckets * sizeof(uint32_t)); + + int i = 0; + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(host_map)); + zend_hash_get_current_data(Z_ARRVAL_P(host_map), (void *) &value) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(host_map))) { + + if (i < buckets) { + if (zend_hash_get_current_key_ex(Z_ARRVAL_P(host_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { + zval copy = **value; + zval_copy_ctor(©); + INIT_PZVAL(©); + convert_to_long(©); + hm[i] = Z_LVAL_P(©); + ++i; + zval_dtor(©); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); + ok = 0; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); + ok = 0; + break; + } + } + + if (i != buckets) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); + ok = 0; + } + + i = 0; + if (ok != 0 && forward_map != NULL) { + fm = (uint32_t*)malloc(buckets * sizeof(uint32_t)); + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(forward_map)); + zend_hash_get_current_data(Z_ARRVAL_P(forward_map), (void *) &value) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(forward_map))) { + + if (i < buckets) { + if (zend_hash_get_current_key_ex(Z_ARRVAL_P(forward_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { + zval copy = **value; + zval_copy_ctor(©); + INIT_PZVAL(©); + + convert_to_long(©); + fm[i] = Z_LVAL_P(©); + ++i; + zval_dtor(©); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); + ok = 0; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); + ok = 0; + } + } + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_bucket_set(m_obj->memc, hm, fm, buckets, replicas); + free(hm); + free(fm); + RETURN_BOOL(ok); + +} +/* }}} */ + /* {{{ Memcached::setOptions(array options) Sets the value for the given option constant */ static PHP_METHOD(Memcached, setOptions) @@ -3482,6 +3575,13 @@ ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0) ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 0) + ZEND_ARG_INFO(0, host_map) + ZEND_ARG_INFO(0, forward_map) + ZEND_ARG_INFO(0, buckets) + ZEND_ARG_INFO(0, replicas) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0) ZEND_END_ARG_INFO() @@ -3560,6 +3660,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getOption, arginfo_getOption) MEMC_ME(setOption, arginfo_setOption) MEMC_ME(setOptions, arginfo_setOptions) + MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) #endif @@ -3675,6 +3776,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); + REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); From e2ab51af7538e4cddebc7a6551dcf3b5116f25eb Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Wed, 2 May 2012 20:39:22 -0700 Subject: [PATCH 113/694] libmemcached docs have been fixed. --- php_memcached.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 62e7b095..67c7302f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1986,12 +1986,6 @@ PHP_METHOD(Memcached, getServerByKey) add_assoc_string(return_value, "host", server->hostname, 1); add_assoc_long(return_value, "port", server->port); add_assoc_long(return_value, "weight", server->weight); - - /* memcached_server_add(3) states that the server instance is cloned. */ - /* In actuality it is not, possibly a bug in libmemcached 0.40. */ - /* remove server freeing */ - - /* memcached_server_free(server); */ } /* }}} */ From 9f86643ac30a578201d7d76b0af8fe5b480c8e91 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Wed, 2 May 2012 20:47:00 -0700 Subject: [PATCH 114/694] Support virtual bucket distribution. --- php_memcached.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 67c7302f..e8ee2935 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3675,6 +3675,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 + REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); +#endif REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); From 672974a42ece6e02af84bbd6af8646ecdbab081c Mon Sep 17 00:00:00 2001 From: Bruno Pospichil Date: Fri, 4 May 2012 20:16:27 +0000 Subject: [PATCH 115/694] Threating return of memcached_bucket_set. --- php_memcached.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index b4927b05..58d1762a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2418,7 +2418,11 @@ PHP_METHOD(Memcached, setBucket) MEMC_METHOD_FETCH_OBJECT; - memcached_bucket_set(m_obj->memc, hm, fm, buckets, replicas); + if (memcached_bucket_set(m_obj->memc, hm, fm, buckets, replicas) != MEMCACHED_SUCCESS) + { + ok = 0; + php_error_docref(NULL TSRMLS_CC, E_WARNING,"memcached_bucket_set don't returned MEMCACHED_SUCCESS"); + } free(hm); free(fm); RETURN_BOOL(ok); From be3253c72f4f600b17ce64ca83f30c53bdaf3f68 Mon Sep 17 00:00:00 2001 From: Damien Claisse Date: Tue, 24 Jul 2012 18:38:44 +0200 Subject: [PATCH 116/694] add consistent hashing option for session handling --- memcached.ini | 8 ++++++++ php_memcached.c | 1 + php_memcached.h | 1 + php_memcached_session.c | 12 ++++++++++++ 4 files changed, 22 insertions(+) diff --git a/memcached.ini b/memcached.ini index cc11b25c..1e1b4351 100644 --- a/memcached.ini +++ b/memcached.ini @@ -17,6 +17,14 @@ memcached.sess_lock_wait = 150000 ; the default value is "memc.sess.key." memcached.sess_prefix = "memc.sess.key." +; memcached session consistent hash mode +; if set to On, consistent hashing (libketama) is used +; for session handling. +; When consistent hashing is used, one can add or remove cache +; node(s) without messing up too much with existing keys +; default is Off +memcached.sess_consistent_hash = Off + ; memcached session binary mode memcached.sess_binary = Off diff --git a/php_memcached.c b/php_memcached.c index e8ee2935..7b60f999 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -287,6 +287,7 @@ static PHP_INI_MH(OnUpdateSerializer) PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_consistent_hash", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hash_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) diff --git a/php_memcached.h b/php_memcached.h index a7c8cfb0..a611b911 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -78,6 +78,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif + zend_bool sess_consistent_hash_enabled; zend_bool sess_binary_enabled; ZEND_END_MODULE_GLOBALS(php_memcached) diff --git a/php_memcached_session.c b/php_memcached_session.c index bbd96b6a..15950a7c 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -140,6 +140,18 @@ PS_OPEN_FUNC(memcached) if (servers) { memc_sess->memc_sess = memcached_create(NULL); if (memc_sess->memc_sess) { + if (MEMC_G(sess_consistent_hash_enabled)) { + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, (uint64_t) 1) == MEMCACHED_FAILURE) { + PS_SET_MOD_DATA(NULL); + if (plist_key) { + efree(plist_key); + } + memcached_free(memc_sess->memc_sess); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to enable memcached consistent hashing"); + return FAILURE; + } + } + status = memcached_server_push(memc_sess->memc_sess, servers); memcached_server_list_free(servers); From 47172e18a19bcfb5b847336a1ec4b42215fcdfc1 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 6 Aug 2012 21:57:39 -0700 Subject: [PATCH 117/694] Drop libmemcached 0.x series support, release 2.1.0. --- ChangeLog | 6 ++++++ config.m4 | 23 +++++++++++------------ php_libmemcached_compat.h | 13 ++----------- php_memcached.c | 18 ++++++++++-------- php_memcached.h | 4 ++-- php_memcached_session.c | 1 - 6 files changed, 31 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index d356e3c0..9a7280d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ memcached extension changelog +Version 2.1.0 +------------- + * Drop support for libmemcached 0.x series, now 1.0.x is required + * Add support for virtual bucket distribution + * Fix compilation against PHP 5.2 + Version 2.0.1 ------------- * Fix embedded version number to be not -dev diff --git a/config.m4 b/config.m4 index ca9c043c..045758aa 100644 --- a/config.m4 +++ b/config.m4 @@ -216,11 +216,16 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi + if test "$PHP_MEMCACHED_SASL" != "no"; then + AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) + AC_MSG_CHECKING([whether to enable sasl support]) + AC_MSG_RESULT([$memcached_enable_sasl]) + fi + + AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then - if test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached/memcached.h"; then - PHP_LIBMEMCACHED_DIR="$PHP_LIBMEMCACHED_DIR" - else - AC_MSG_ERROR([Can't find libmemcached headers under "$PHP_LIBMEMCACHED_DIR"]) + if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached-1.0/memcached.h"; then + AC_MSG_ERROR([Can't find libmemcached 1.0.x headers under "$PHP_LIBMEMCACHED_DIR"]) fi else PHP_LIBMEMCACHED_DIR="no" @@ -232,17 +237,11 @@ if test "$PHP_MEMCACHED" != "no"; then done fi - if test "$PHP_MEMCACHED_SASL" != "no"; then - AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) - AC_MSG_CHECKING([whether to enable sasl support]) - AC_MSG_RESULT([$memcached_enable_sasl]) - fi - - AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" = "no"; then - AC_MSG_ERROR([memcached support requires libmemcached. Use --with-libmemcached-dir= to specify the prefix where libmemcached headers and library are located]) + AC_MSG_ERROR([memcached support requires libmemcached 1.0.x. Use --with-libmemcached-dir= to specify the prefix where libmemcached headers and library are located]) else AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR]) + PHP_LIBMEMCACHED_INCDIR="$PHP_LIBMEMCACHED_DIR/include" PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR) PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 8b39da36..6e5f58b1 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -1,16 +1,7 @@ -/* - * Here we define backwards compatibility for older - * libmemcached API:s - * - * // Teddy Grenman - */ - #ifndef PHP_LIBMEMCACHED_COMPAT #define PHP_LIBMEMCACHED_COMPAT -#if !defined(LIBMEMCACHED_VERSION_HEX) || LIBMEMCACHED_VERSION_HEX < 0x00039000 -/* definition from libmemcached/types.h version 0.39+ */ -typedef const struct memcached_server_st *memcached_server_instance_st; -#endif +/* this is the version(s) we support */ +#include #endif diff --git a/php_memcached.c b/php_memcached.c index e8ee2935..90ea8ab2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -43,9 +43,7 @@ #include #include #include -#include -#include "php_libmemcached_compat.h" #include "php_memcached.h" #include "g_fmt.h" @@ -2582,9 +2580,12 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, MAKE_STD_ZVAL(array); array_init(array); - add_assoc_string(array, "host", instance->hostname, 1); - add_assoc_long(array, "port", instance->port); + add_assoc_string(array, "host", memcached_server_name(instance), 1); + add_assoc_long(array, "port", memcached_server_port(instance)); + /* + * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); + */ add_next_index_zval(context->return_value, array); return MEMCACHED_SUCCESS; } @@ -2595,7 +2596,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memc int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; zval *entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); MAKE_STD_ZVAL(entry); array_init(entry); @@ -2640,10 +2641,11 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, me int hostport_len, version_len; struct callbackContext* context = (struct callbackContext*) in_context; - hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); version_len = snprintf(version, sizeof(version), "%d.%d.%d", - instance->major_version, instance->minor_version, - instance->micro_version); + memcached_server_major_version(instance), + memcached_server_minor_version(instance), + memcached_server_micro_version(instance)); add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1); efree(hostport); diff --git a/php_memcached.h b/php_memcached.h index a7c8cfb0..564b7a53 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -19,7 +19,7 @@ #ifndef PHP_MEMCACHED_H #define PHP_MEMCACHED_H -#include +#include "php_libmemcached_compat.h" #ifdef HAVE_CONFIG_H # include "config.h" @@ -91,7 +91,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.0.1" +#define PHP_MEMCACHED_VERSION "2.1.0" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) diff --git a/php_memcached_session.c b/php_memcached_session.c index bbd96b6a..0dca5151 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "php_memcached.h" #include "php_memcached_session.h" From 09791df73d23fa7d182660e23ffbbf0753f2b2fa Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 6 Aug 2012 21:59:31 -0700 Subject: [PATCH 118/694] Release 2.1.0. --- package.xml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index c89fae2b..11a6518f 100644 --- a/package.xml +++ b/package.xml @@ -15,10 +15,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes - 2012-03-03 + 2012-08-06 - 2.0.1 - 2.0.1 + 2.1.0 + 2.1.0 stable @@ -26,7 +26,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Fix embedded version number to be not -dev +- Drop support for libmemcached 0.x series, now 1.0.x is required +- Add support for virtual bucket distribution +- Fix compilation against PHP 5.2 @@ -65,6 +67,17 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached + + stablestable + 2.1.02.1.0 + 2012-08-06 + +- Drop support for libmemcached 0.x series, now 1.0.x is required +- Add support for virtual bucket distribution +- Fix compilation against PHP 5.2 + + + stablestable 2.0.12.0.1 From d9a01a3d7778810c28292574292b90c6569649fa Mon Sep 17 00:00:00 2001 From: gureedo Date: Wed, 29 Aug 2012 18:16:12 +0600 Subject: [PATCH 119/694] session replica options --- php_memcached.c | 4 ++++ php_memcached.h | 2 ++ php_memcached_session.c | 11 +++++++++++ 3 files changed, 17 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 90ea8ab2..54264aed 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -288,6 +288,8 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) @@ -3032,6 +3034,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(sess_locked) = 0; MEMC_G(sess_lock_key) = NULL; MEMC_G(sess_lock_key_len) = 0; + MEMC_G(sess_number_of_replicas) = 0; + MEMC_G(sess_randomize_replica_read) = 0; #endif MEMC_G(serializer_name) = NULL; MEMC_G(serializer) = SERIALIZER_DEFAULT; diff --git a/php_memcached.h b/php_memcached.h index 564b7a53..e4e5a2e2 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -66,6 +66,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool sess_locked; char* sess_lock_key; int sess_lock_key_len; + int sess_number_of_replicas; + zend_bool sess_randomize_replica_read; #endif char *serializer_name; enum memcached_serializer serializer; diff --git a/php_memcached_session.c b/php_memcached_session.c index 0dca5151..a263a5c5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -195,6 +195,17 @@ PS_OPEN_FUNC(memcached) } } + if (MEMC_G(sess_number_of_replicas) > 0) { + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session number of replicas"); + return FAILURE; + } + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session randomize replica read"); + return FAILURE; + } + } + return SUCCESS; } } From cc7b0decd6ee9fb1d8fa262c7027b7533de9e78e Mon Sep 17 00:00:00 2001 From: gureedo Date: Sun, 2 Sep 2012 21:18:10 +0600 Subject: [PATCH 120/694] added replica options to memcached.ini --- memcached.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/memcached.ini b/memcached.ini index cc11b25c..9c9bc926 100644 --- a/memcached.ini +++ b/memcached.ini @@ -20,6 +20,12 @@ memcached.sess_prefix = "memc.sess.key." ; memcached session binary mode memcached.sess_binary = Off +; memcached session number of replicas +memcached.sess_number_of_replicas = 0 + +; memcached session replica read randomize +memcached.sess_randomize_replica_read = Off + ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz From 74542111f175fe2ec41c8bf722fc2cd3dac93eea Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Sun, 30 Sep 2012 11:09:01 -0700 Subject: [PATCH 121/694] Fix version access for libmemcached older than 1.0.8. --- php_memcached.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 90ea8ab2..7e6041a6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2642,10 +2642,17 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, me struct callbackContext* context = (struct callbackContext*) in_context; hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000008 version_len = snprintf(version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), memcached_server_micro_version(instance)); +#else + version_len = snprintf(version, sizeof(version), "%d.%d.%d", + instance->major_version, + instance->minor_version, + instance->micro_version); +#endif add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1); efree(hostport); From faf84af78919cc5641675aac98c37fbf278d2fe8 Mon Sep 17 00:00:00 2001 From: Mitch Hagstrand Date: Wed, 3 Oct 2012 13:04:45 -0700 Subject: [PATCH 122/694] Added Memcached Session Replicas by changes below 1. Allow for automatic removal of failed server to session handler (MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS) 2. Allow X number of replicas (MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) 3. Added option for consistent hasing (MEMCACHED_BEHAVIOR_KETAMA) 4. Added error msg when session handler couldn't obtain a lock --- memcached.ini | 17 +++++++++++++ php_memcached.c | 6 +++++ php_memcached.h | 3 +++ php_memcached_session.c | 56 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/memcached.ini b/memcached.ini index cc11b25c..c5ff0bf0 100644 --- a/memcached.ini +++ b/memcached.ini @@ -17,7 +17,24 @@ memcached.sess_lock_wait = 150000 ; the default value is "memc.sess.key." memcached.sess_prefix = "memc.sess.key." + +; Allow consistent hasing for the session +memcached.sess_consistent_hashing = 1 + +; Allow failed memcached server to automatically be removed +memcached.sess_remove_failed = 1 + +; Write data to a number of additional memcached servers +; This is "poor man's HA" as libmemcached calls it. +; If this value is positive and sess_remove_failed is enabled +; when a memcached server fails the session will continue to be available +; from a replica. However, if the failed memcache server +; becomes available again it will read the session from there +; which could have old data or no data at all +memcached.sess_num_replicas = 0; + ; memcached session binary mode +; libmemcached replicas only work if binary mode is enabled memcached.sess_binary = Off ; Set the compression type diff --git a/php_memcached.c b/php_memcached.c index 7e6041a6..38f53dad 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -288,6 +288,9 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_consistent_hashing", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hashing_enabled, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_num_replicas", "0", PHP_INI_ALL, OnUpdateLong, sess_num_replicas, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) @@ -3034,6 +3037,9 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #ifdef HAVE_MEMCACHED_SESSION MEMC_G(sess_locking_enabled) = 1; MEMC_G(sess_binary_enabled) = 1; + MEMC_G(sess_consistent_hashing_enabled) = 0; + MEMC_G(sess_num_replicas) = 0; + MEMC_G(sess_remove_failed_enabled) = 0; MEMC_G(sess_prefix) = NULL; MEMC_G(sess_lock_wait) = 0; MEMC_G(sess_locked) = 0; diff --git a/php_memcached.h b/php_memcached.h index 564b7a53..818f7528 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -66,6 +66,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool sess_locked; char* sess_lock_key; int sess_lock_key_len; + long sess_num_replicas; + zend_bool sess_remove_failed_enabled; + zend_bool sess_consistent_hashing_enabled; #endif char *serializer_name; enum memcached_serializer serializer; diff --git a/php_memcached_session.c b/php_memcached_session.c index 0dca5151..8dfc7a0a 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -48,6 +48,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) char *lock_key = NULL; int lock_key_len = 0; unsigned long attempts; + long write_retry_attempts = 0; long lock_maxwait; long lock_wait = MEMC_G(sess_lock_wait); time_t expiration; @@ -64,6 +65,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) expiration = time(NULL) + lock_maxwait + 1; attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); + /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ + if (MEMC_G(sess_remove_failed_enabled)) { + write_retry_attempts = MEMC_G(sess_num_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); + } + lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); do { status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); @@ -73,6 +79,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) MEMC_G(sess_lock_key_len) = lock_key_len; return 0; } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) { + if (write_retry_attempts > 0) { + write_retry_attempts--; + continue; + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Write of lock failed"); break; } @@ -195,6 +206,30 @@ PS_OPEN_FUNC(memcached) } } + if (MEMC_G(sess_consistent_hashing_enabled)) { + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA, (uint64_t) 1) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached consistent hashing"); + return FAILURE; + } + } + + /* Allow libmemcached remove failed servers */ + if (MEMC_G(sess_remove_failed_enabled)) { + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set: remove failed servers"); + return FAILURE; + } + } + + /* Allow replicas section */ + long num_replicas = MEMC_G(sess_num_replicas); + if (num_replicas > 0) { + /* Set the number of replicas libmemcached will use */ + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) num_replicas) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached client replicating"); + return FAILURE; + } + } return SUCCESS; } } @@ -243,6 +278,7 @@ PS_READ_FUNC(memcached) if (MEMC_G(sess_locking_enabled)) { if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to clear session lock record"); return FAILURE; } } @@ -263,6 +299,7 @@ PS_WRITE_FUNC(memcached) { int key_len = strlen(key); time_t expiration = 0; + long write_try_attempts = 1; memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; @@ -277,13 +314,22 @@ PS_WRITE_FUNC(memcached) if (PS(gc_maxlifetime) > 0) { expiration = PS(gc_maxlifetime); } - status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0); - if (status == MEMCACHED_SUCCESS) { - return SUCCESS; - } else { - return FAILURE; + /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ + if (MEMC_G(sess_remove_failed_enabled)) { + write_try_attempts = 1 + MEMC_G(sess_num_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); } + + do { + status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0); + if (status == MEMCACHED_SUCCESS) { + return SUCCESS; + } else { + write_try_attempts--; + } + } while (write_try_attempts > 0); + + return FAILURE; } PS_DESTROY_FUNC(memcached) From 3574b28758cba0d70f27de1acffbfc09e1733f50 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 3 Nov 2012 14:30:05 -0400 Subject: [PATCH 123/694] Fixed bug #36 (Allow memcached.sess_prefix to be blank) --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 0dca5151..131757c0 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -142,7 +142,7 @@ PS_OPEN_FUNC(memcached) status = memcached_server_push(memc_sess->memc_sess, servers); memcached_server_list_free(servers); - if (memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { + if (MEMC_G(sess_prefix) && MEMC_G(sess_prefix)[0] != 0 && memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { PS_SET_MOD_DATA(NULL); if (plist_key) { efree(plist_key); From 817a9d5682e42043e1b5acc612458c791be845b9 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 3 Nov 2012 16:41:54 -0400 Subject: [PATCH 124/694] Reset error code on retry attempt. Fixes issue #15 --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 027e1d90..b0efd8b3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1173,6 +1173,7 @@ PHP_METHOD(Memcached, setMultiByKey) case MEMCACHED_SERVER_MARKED_DEAD: \ if (memcached_server_count(m_obj->memc) > 0) { \ retry++; \ + i_obj->rescode = 0; \ goto retry; \ } \ break; \ From 5ff95162408c77d1d9b27f1f86740b58229e8e02 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 10 Nov 2012 09:50:21 -0500 Subject: [PATCH 125/694] Fixed version check for a libmemcached bug in version 0.49 case #6 --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index b0efd8b3..9c7a5142 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2179,7 +2179,7 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 RETURN_STRINGL(result, strlen(result) - 1, 1); #else RETURN_STRING(result, 1); @@ -2236,7 +2236,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML case MEMC_OPT_PREFIX_KEY: { char *key; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; #endif convert_to_string(value); @@ -2244,10 +2244,10 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML key = NULL; } else { /* - work-around a bug in libmemcached prior to version 0.50 that truncates the trailing + work-around a bug in libmemcached in version 0.49 that truncates the trailing character of the key prefix, to avoid the issue we pad it with a '0' */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 snprintf(tmp, sizeof(tmp), "%s0", Z_STRVAL_P(value)); key = tmp; #else From 5450f45a3ee9ca520c108a043dd10fbe9b5535ac Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Sat, 10 Nov 2012 22:30:29 +0100 Subject: [PATCH 126/694] memcached_server_by_key actually returns a memcached_server_instance_st instead of memcached_server_st. The structures were compatible to eachother, but this recently changed between 1.0.5 and 1.0.13. See https://bugs.launchpad.net/libmemcached/+bug/1076048 for more info. --- php_memcached.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..e7156431 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1965,7 +1965,7 @@ PHP_METHOD(Memcached, getServerByKey) { char *server_key; int server_key_len; - memcached_server_st *server; + memcached_server_instance_st *server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; @@ -1981,16 +1981,16 @@ PHP_METHOD(Memcached, getServerByKey) RETURN_FALSE; } - server = memcached_server_by_key(m_obj->memc, server_key, server_key_len, &error); - if (server == NULL) { + server_instance = memcached_server_by_key(m_obj->memc, server_key, server_key_len, &error); + if (server_instance == NULL) { php_memc_handle_error(i_obj, error TSRMLS_CC); RETURN_FALSE; } array_init(return_value); - add_assoc_string(return_value, "host", server->hostname, 1); - add_assoc_long(return_value, "port", server->port); - add_assoc_long(return_value, "weight", server->weight); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); + add_assoc_long(return_value, "weight", 0); } /* }}} */ @@ -2587,7 +2587,7 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, MAKE_STD_ZVAL(array); array_init(array); - add_assoc_string(array, "host", memcached_server_name(instance), 1); + add_assoc_string(array, "host", (char*) memcached_server_name(instance), 1); add_assoc_long(array, "port", memcached_server_port(instance)); /* * API does not allow to get at this field. From d9a2e8b6c35a3b4ba069a1e1a7ad95988c756736 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Tue, 13 Nov 2012 00:14:20 +0100 Subject: [PATCH 127/694] Added 4 functions to further debug issues and error codes in a multi-server environment: getLastErrorMessage() getLastErrorCode() getLastErrorErrno() getLastDisconnectedServer() --- memcached-api.php | 8 ++++ php_memcached.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 75522950..46b37855 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -257,6 +257,14 @@ public function getServerList( ) {} public function getServerByKey( $server_key ) {} + public function getLastErrorMessage( ) {} + + public function getLastErrorCode( ) {} + + public function getLastErrorErrno( ) {} + + public function getLastDisconnectedServer( ) {} + public function flush( $delay = 0 ) {} public function getStats( ) {} diff --git a/php_memcached.c b/php_memcached.c index e7156431..6cfa1520 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2028,6 +2028,81 @@ PHP_METHOD(Memcached, quit) } /* }}} */ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 +/* {{{ Memcached::getLastErrorMessage() + Returns the last error message that occurred */ +PHP_METHOD(Memcached, getLastErrorMessage) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_STRING(memcached_last_error_message(m_obj->memc), 1); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorCode() + Returns the last error code that occurred */ +PHP_METHOD(Memcached, getLastErrorCode) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error(m_obj->memc)); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorErrno() + Returns the last error errno that occurred */ +PHP_METHOD(Memcached, getLastErrorErrno) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error_errno(m_obj->memc)); +} +/* }}} */ +#endif + +/* {{{ Memcached::getLastDisconnectedServer() + Returns the last disconnected server + Was added in 0.34 according to libmemcached's Changelog */ +PHP_METHOD(Memcached, getLastDisconnectedServer) +{ + memcached_server_instance_st *server_instance; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + server_instance = memcached_server_get_last_disconnect(m_obj->memc); + if (server_instance == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); +} +/* }}} */ + /* {{{ Memcached::getStats() Returns statistics for the memcache servers */ PHP_METHOD(Memcached, getStats) @@ -3486,6 +3561,18 @@ ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0) ZEND_ARG_INFO(0, server_key) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorMessage, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorCode, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorErrno, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_getLastDisconnectedServer, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) ZEND_ARG_INFO(0, option) ZEND_END_ARG_INFO() @@ -3573,6 +3660,13 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(resetServerList, arginfo_resetServerList) MEMC_ME(quit, arginfo_quit) +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 + MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) + MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) + MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) +#endif + MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) + MEMC_ME(getStats, arginfo_getStats) MEMC_ME(getVersion, arginfo_getVersion) MEMC_ME(getAllKeys, arginfo_getAllKeys) From 30d9031620d93c4f7f4f0c436995a16c4d54e0b2 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Wed, 14 Nov 2012 22:13:43 +0100 Subject: [PATCH 128/694] Added MEMCACHED_BEHAVIOR_DEAD_TIMEOUT class constant 'OPT_DEAD_TIMEOUT' (new in 1.0.3) --- memcached-api.php | 2 ++ php_memcached.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 46b37855..69ff659e 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -53,6 +53,8 @@ class Memcached { const OPT_RETRY_TIMEOUT; + const OPT_DEAD_TIMEOUT; + const OPT_SND_TIMEOUT; const OPT_RCV_TIMEOUT; diff --git a/php_memcached.c b/php_memcached.c index 6cfa1520..642cb162 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3805,6 +3805,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_RECV_SIZE, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE); REGISTER_MEMC_CLASS_CONST_LONG(OPT_CONNECT_TIMEOUT, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RETRY_TIMEOUT, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT); +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000003 + REGISTER_MEMC_CLASS_CONST_LONG(OPT_DEAD_TIMEOUT, MEMCACHED_BEHAVIOR_DEAD_TIMEOUT); +#endif REGISTER_MEMC_CLASS_CONST_LONG(OPT_SEND_TIMEOUT, MEMCACHED_BEHAVIOR_SND_TIMEOUT); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RECV_TIMEOUT, MEMCACHED_BEHAVIOR_RCV_TIMEOUT); REGISTER_MEMC_CLASS_CONST_LONG(OPT_POLL_TIMEOUT, MEMCACHED_BEHAVIOR_POLL_TIMEOUT); From f719529636954eae8395f44129b49a0a212ba23a Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 17 Nov 2012 10:03:29 +0100 Subject: [PATCH 129/694] report about SASL support --- php_memcached.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..cc5643e6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3890,6 +3890,12 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); +#if HAVE_MEMCACHED_SASL + php_info_print_table_row(2, "SASL support", "yes"); +#else + php_info_print_table_row(2, "SASL support", "no"); +#endif + #ifdef HAVE_MEMCACHED_SESSION php_info_print_table_row(2, "Session support", "yes"); #else From 1cd51eb531cabd79fbe1ade5e8e5b051b21a4dd0 Mon Sep 17 00:00:00 2001 From: xoJIog Date: Tue, 20 Nov 2012 11:00:32 +0200 Subject: [PATCH 130/694] php_memcached.c added connect timeout variable --- php_memcached.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..064e3b6c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -294,6 +294,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_consistent_hashing", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hashing_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) @@ -3050,8 +3051,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(sess_locked) = 0; MEMC_G(sess_lock_key) = NULL; MEMC_G(sess_lock_key_len) = 0; - MEMC_G(sess_number_of_replicas) = 0; MEMC_G(sess_randomize_replica_read) = 0; + MEMC_G(sess_connect_timeout) = 1000; #endif MEMC_G(serializer_name) = NULL; MEMC_G(serializer) = SERIALIZER_DEFAULT; From 0d1ff239f13deff0ccd5ce88b9e3cc130e392f17 Mon Sep 17 00:00:00 2001 From: xoJIog Date: Tue, 20 Nov 2012 11:02:41 +0200 Subject: [PATCH 131/694] php_memcached.h added connect timeout --- php_memcached.h | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.h b/php_memcached.h index 2bd5c83e..e3fd1bef 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -71,6 +71,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool sess_randomize_replica_read; zend_bool sess_remove_failed_enabled; zend_bool sess_consistent_hashing_enabled; + long sess_connect_timeout; #endif char *serializer_name; enum memcached_serializer serializer; From 07879fb6a99b32d473cbda9122c75e128c2c1a29 Mon Sep 17 00:00:00 2001 From: xoJIog Date: Tue, 20 Nov 2012 11:11:28 +0200 Subject: [PATCH 132/694] php_memcached_session.c added connect timeout --- php_memcached_session.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 2b64581e..68501bb5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -234,6 +234,11 @@ PS_OPEN_FUNC(memcached) return FAILURE; } } + + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached connection timeout"); + return FAILURE; + } /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { From d7ed677ee96bb5d56d42c5c1bcae1fc5409f30cb Mon Sep 17 00:00:00 2001 From: xoJIog Date: Tue, 20 Nov 2012 11:20:06 +0200 Subject: [PATCH 133/694] memcached.ini added connect timeout --- memcached.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/memcached.ini b/memcached.ini index f4bd68c0..de483dcb 100644 --- a/memcached.ini +++ b/memcached.ini @@ -47,6 +47,11 @@ memcached.sess_number_of_replicas = 0 ; memcached session replica read randomize memcached.sess_randomize_replica_read = Off +; memcached connect timeout value +; In non-blocking mode this changes the value of the timeout +; during socket connection in milliseconds. Specifying -1 means an infinite timeout. +memcached.sess_connect_timeout = 1000 + ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz From 8230dc123f0dddfed1e37b4d4d1721f4f6de1542 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Thu, 13 Dec 2012 09:58:04 -0800 Subject: [PATCH 134/694] 2012 holidays note --- README.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.markdown b/README.markdown index b218c8c9..c8695124 100644 --- a/README.markdown +++ b/README.markdown @@ -1,3 +1,8 @@ +2012 Holidays +------------- +Committers' wishlists, if you feel like kicking in towards a gift: + * [Andrei's](http://given.to/profile/andreiz/wishlist/1411) + Description ----------- This extension uses libmemcached library to provide API for communicating with From f75b16b42ccd9eb79185d55afe70711ea2d5d651 Mon Sep 17 00:00:00 2001 From: David Terei Date: Thu, 3 Jan 2013 23:38:51 +1100 Subject: [PATCH 135/694] Add missing memcached.use_sasl ini option to doc. --- memcached.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/memcached.ini b/memcached.ini index f4bd68c0..f890c5ae 100644 --- a/memcached.ini +++ b/memcached.ini @@ -81,3 +81,8 @@ memcached.compression_threshold = 2000 ; ; The default is igbinary if available and php otherwise. memcached.serializer = "igbinary" + +; Use SASL authentication for connections +; valid values: On, Off +; the default is Off +memcached.use_sasl = Off From 9cb3089d4ffba3ef2c02a3b4e887514daff37e46 Mon Sep 17 00:00:00 2001 From: David Terei Date: Thu, 3 Jan 2013 23:39:17 +1100 Subject: [PATCH 136/694] Add in missing setSaslAuthData to api doc. --- memcached-api.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 75522950..557597e8 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -271,6 +271,8 @@ public function isPersistent( ) {} public function isPristine( ) {} + public function setSaslAuthData( $username, $password ) {} + } class MemcachedException extends Exception { From 99919d5feb4ed5e8523b8857d9593c706c2c5d5b Mon Sep 17 00:00:00 2001 From: David Terei Date: Thu, 3 Jan 2013 23:39:31 +1100 Subject: [PATCH 137/694] Add notes on building to README. --- README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.markdown b/README.markdown index c8695124..aaad0961 100644 --- a/README.markdown +++ b/README.markdown @@ -12,6 +12,13 @@ memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. +Building +-------- +$ phpize +$ ./configure +$ make +$ make test + Resources --------- * [libmemcached](http://tangent.org/552/libmemcached.html) From ace57718002ed7d30b620694fbe68e76abc821fd Mon Sep 17 00:00:00 2001 From: David Terei Date: Thu, 3 Jan 2013 23:58:56 +1100 Subject: [PATCH 138/694] Enable SASL support by default if detected. --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 045758aa..b8bbbff5 100644 --- a/config.m4 +++ b/config.m4 @@ -18,7 +18,7 @@ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer suppo [ --enable-memcached-json Enable memcached json serializer support], no, no) PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, -[ --disable-memcached-sasl Disable memcached sasl support], no, no) +[ --disable-memcached-sasl Disable memcached sasl support], yes, no) if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, From 699ac64abafa56560b003079d9ba563d03d7d787 Mon Sep 17 00:00:00 2001 From: David Terei Date: Fri, 4 Jan 2013 00:51:57 +1100 Subject: [PATCH 139/694] Warn if trying to use SASL when memcached.use_sasl is off. Without this, a far less helpful error message from the underlying libmemcached library would be reported. --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..a11d0572 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2413,6 +2413,11 @@ static PHP_METHOD(Memcached, setSaslAuthData) return; } + if (!MEMC_G(use_sasl)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); + RETURN_FALSE; + } + MEMC_METHOD_FETCH_OBJECT; if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { From 2ac3a9c390812458ae891ce232394bc382fce144 Mon Sep 17 00:00:00 2001 From: Don MacAskill Date: Thu, 10 Jan 2013 17:22:07 -0800 Subject: [PATCH 140/694] Add msgpack serializer support for better cross-language binary serialization, fixed broken igbinary support --- config.m4 | 47 +++++++++++++++++++++++++++++++++++++- memcached.ini | 5 +++-- php_memcached.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- php_memcached.h | 6 ++++- 4 files changed, 113 insertions(+), 5 deletions(-) diff --git a/config.m4 b/config.m4 index 045758aa..a6ec61a0 100644 --- a/config.m4 +++ b/config.m4 @@ -17,6 +17,9 @@ PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support, [ --enable-memcached-json Enable memcached json serializer support], no, no) +PHP_ARG_ENABLE(memcached-msgpack, whether to enable memcached msgpack serializer support, +[ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) + PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], no, no) @@ -188,6 +191,33 @@ if test "$PHP_MEMCACHED" != "no"; then fi fi + if test "$PHP_MEMCACHED_MSGPACK" != "no"; then + AC_MSG_CHECKING([for msgpack includes]) + msgpack_inc_path="" + + if test -f "$abs_srcdir/include/php/ext/msgpack/php_msgpack.h"; then + msgpack_inc_path="$abs_srcdir/include/php" + elif test -f "$abs_srcdir/ext/msgpack/php_msgpack.h"; then + msgpack_inc_path="$abs_srcdir" + elif test -f "$phpincludedir/ext/session/php_msgpack.h"; then + msgpack_inc_path="$phpincludedir" + elif test -f "$phpincludedir/ext/msgpack/php_msgpack.h"; then + msgpack_inc_path="$phpincludedir" + else + for i in php php4 php5 php6; do + if test -f "$prefix/include/$i/ext/msgpack/php_msgpack.h"; then + msgpack_inc_path="$prefix/include/$i" + fi + done + fi + + if test "$msgpack_inc_path" = ""; then + AC_MSG_ERROR([Cannot find php_msgpack.h]) + else + AC_MSG_RESULT([$msgpack_inc_path]) + fi + fi + AC_MSG_CHECKING([for memcached session support]) if test "$PHP_MEMCACHED_SESSION" != "no"; then AC_MSG_RESULT([enabled]) @@ -216,6 +246,21 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi + AC_MSG_CHECKING([for memcached msgpack support]) + if test "$PHP_MEMCACHED_MSGPACK" != "no"; then + AC_MSG_RESULT([enabled]) + AC_DEFINE(HAVE_MEMCACHED_MSGPACK,1,[Whether memcache msgpack serializer is enabled]) + MSGPACK_INCLUDES="-I$msgpack_inc_path" + ifdef([PHP_ADD_EXTENSION_DEP], + [ + PHP_ADD_EXTENSION_DEP(memcached, msgpack) + ]) + else + MSGPACK_INCLUDES="" + AC_MSG_RESULT([disabled]) + fi + + if test "$PHP_MEMCACHED_SASL" != "no"; then AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) AC_MSG_CHECKING([whether to enable sasl support]) @@ -254,7 +299,7 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi - PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) + PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $MSGPACK_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) ifdef([PHP_ADD_EXTENSION_DEP], diff --git a/memcached.ini b/memcached.ini index f4bd68c0..17143e14 100644 --- a/memcached.ini +++ b/memcached.ini @@ -69,7 +69,7 @@ memcached.compression_factor = "1.3" memcached.compression_threshold = 2000 ; Set the default serializer for new memcached objects. -; valid values are: php, igbinary, json, json_array +; valid values are: php, igbinary, json, json_array, msgpack ; ; json - standard php JSON encoding. This serializer ; is fast and compact but only works on UTF-8 @@ -78,6 +78,7 @@ memcached.compression_threshold = 2000 ; json_array - as json, but decodes into arrays ; php - the standard php serializer ; igbinary - a binary serializer +; msgpack - a cross-language binary serializer ; -; The default is igbinary if available and php otherwise. +; The default is igbinary if available, then msgpack if available, then php otherwise. memcached.serializer = "igbinary" diff --git a/php_memcached.c b/php_memcached.c index d1d07246..0c7b9491 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -89,6 +89,10 @@ typedef unsigned long int uint32_t; # include "ext/igbinary/igbinary.h" #endif +#ifdef HAVE_MEMCACHED_MSGPACK +# include "ext/msgpack/php_msgpack.h" +#endif + /* * This is needed because PHP 5.3.[01] does not install JSON_parser.h by default. This * constant will move into php_json.h in the future anyway. @@ -124,6 +128,7 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_IS_SERIALIZED 4 #define MEMC_VAL_IS_IGBINARY 5 #define MEMC_VAL_IS_JSON 6 +#define MEMC_VAL_IS_MSGPACK 7 #define MEMC_VAL_COMPRESSED (1<<4) #define MEMC_VAL_COMPRESSION_ZLIB (1<<5) @@ -264,7 +269,7 @@ static PHP_INI_MH(OnUpdateSerializer) MEMC_G(serializer) = SERIALIZER_DEFAULT; } else if (!strcmp(new_value, "php")) { MEMC_G(serializer) = SERIALIZER_PHP; -#ifdef HAVE_MEMCACHE_IGBINARY +#ifdef HAVE_MEMCACHED_IGBINARY } else if (!strcmp(new_value, "igbinary")) { MEMC_G(serializer) = SERIALIZER_IGBINARY; #endif // IGBINARY @@ -274,6 +279,10 @@ static PHP_INI_MH(OnUpdateSerializer) } else if (!strcmp(new_value, "json_array")) { MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; #endif // JSON +#ifdef HAVE_MEMCACHED_MSGPACK + } else if (!strcmp(new_value, "msgpack")) { + MEMC_G(serializer) = SERIALIZER_MSGPACK; +#endif // msgpack } else { return FAILURE; } @@ -2305,6 +2314,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { m_obj->serializer = SERIALIZER_JSON_ARRAY; } else +#endif + /* msgpack serializer */ +#ifdef HAVE_MEMCACHED_MSGPACK + if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { + m_obj->serializer = SERIALIZER_MSGPACK; + } else #endif /* php serializer */ if (Z_LVAL_P(value) == SERIALIZER_PHP) { @@ -2787,6 +2802,20 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); break; } +#endif +#ifdef HAVE_MEMCACHED_MSGPACK + case SERIALIZER_MSGPACK: + php_msgpack_serialize(&buf, value TSRMLS_CC); + if(!buf.c) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); + smart_str_free(&buf); + return NULL; + } + p = buf.c; + l = buf.len; + buf_used = 1; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; #endif default: { @@ -3019,6 +3048,15 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload #endif break; + case MEMC_VAL_IS_MSGPACK: +#ifdef HAVE_MEMCACHED_MSGPACK + php_msgpack_unserialize(value, payload, payload_len TSRMLS_CC); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + goto my_error; +#endif + break; + default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); goto my_error; @@ -3603,6 +3641,9 @@ static const zend_module_dep memcached_deps[] = { #ifdef HAVE_MEMCACHED_IGBINARY ZEND_MOD_REQUIRED("igbinary") #endif +#ifdef HAVE_MEMCACHED_MSGPACK + ZEND_MOD_REQUIRED("msgpack") +#endif #ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") #endif @@ -3668,6 +3709,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); #endif + /* + * Indicate whether msgpack serializer is available + */ +#ifdef HAVE_MEMCACHED_MSGPACK + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); +#else + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); +#endif + #ifdef HAVE_MEMCACHED_SESSION REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1); #else @@ -3782,6 +3832,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON_ARRAY, SERIALIZER_JSON_ARRAY); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types @@ -3907,6 +3958,13 @@ PHP_MINFO_FUNCTION(memcached) #else php_info_print_table_row(2, "json support", "no"); #endif + +#ifdef HAVE_MEMCACHED_MSGPACK + php_info_print_table_row(2, "msgpack support", "yes"); +#else + php_info_print_table_row(2, "msgpack support", "no"); +#endif + php_info_print_table_end(); DISPLAY_INI_ENTRIES(); diff --git a/php_memcached.h b/php_memcached.h index 2bd5c83e..50366e1e 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,14 +42,18 @@ enum memcached_serializer { SERIALIZER_IGBINARY = 2, SERIALIZER_JSON = 3, SERIALIZER_JSON_ARRAY = 4, + SERIALIZER_MSGPACK = 5, }; #ifdef HAVE_MEMCACHED_IGBINARY #define SERIALIZER_DEFAULT SERIALIZER_IGBINARY #define SERIALIZER_DEFAULT_NAME "igbinary" +#elif HAVE_MEMECACHED_MSGPACK +#define SERIALIZER_DEFAULT SERIALIZER_MSGPACK +#define SERIALIZER_DEFAULT_NAME "msgpack" #else #define SERIALIZER_DEFAULT SERIALIZER_PHP #define SERIALIZER_DEFAULT_NAME "php" -#endif /* HAVE_MEMCACHED_IGBINARY */ +#endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ #if LIBMEMCACHED_WITH_SASL_SUPPORT # if defined(HAVE_SASL_SASL_H) From 7e3bc8b0ee78a57970ad86c98d0e2dde20ae0546 Mon Sep 17 00:00:00 2001 From: Mitch Hagstrand Date: Mon, 14 Jan 2013 00:29:07 -0800 Subject: [PATCH 141/694] Removed memcached.sess_consistent_hashing option. 1. Removed memcached.sess_consistent_hashing which is a lesser version of memcached.sess_consistent_hash 2. Added default value for memcached.sess_consistent_hash --- php_memcached.c | 3 +-- php_memcached.h | 5 ++--- php_memcached_session.c | 7 ------- tests/experimental/moduleinfo.phpt | 3 +-- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..687a5149 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -292,7 +292,6 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_consistent_hashing", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hashing_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) @@ -3042,7 +3041,7 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #ifdef HAVE_MEMCACHED_SESSION MEMC_G(sess_locking_enabled) = 1; MEMC_G(sess_binary_enabled) = 1; - MEMC_G(sess_consistent_hashing_enabled) = 0; + MEMC_G(sess_consistent_hash_enabled) = 0; MEMC_G(sess_number_of_replicas) = 0; MEMC_G(sess_remove_failed_enabled) = 0; MEMC_G(sess_prefix) = NULL; diff --git a/php_memcached.h b/php_memcached.h index 2bd5c83e..9ca2a418 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -70,7 +70,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) int sess_number_of_replicas; zend_bool sess_randomize_replica_read; zend_bool sess_remove_failed_enabled; - zend_bool sess_consistent_hashing_enabled; + zend_bool sess_consistent_hash_enabled; + zend_bool sess_binary_enabled; #endif char *serializer_name; enum memcached_serializer serializer; @@ -83,8 +84,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif - zend_bool sess_consistent_hash_enabled; - zend_bool sess_binary_enabled; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/php_memcached_session.c b/php_memcached_session.c index 2b64581e..7c8c3cca 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -228,13 +228,6 @@ PS_OPEN_FUNC(memcached) } } - if (MEMC_G(sess_consistent_hashing_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached consistent hashing"); - return FAILURE; - } - } - /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 85acbca3..fa3cd631 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -25,10 +25,9 @@ memcached.compression_type => %s => %s memcached.serializer => %s => %s memcached.sess_binary => %d => %d memcached.sess_consistent_hash => %d => %d -memcached.sess_consistent_hashing => %d => %d memcached.sess_lock_wait => %d => %d memcached.sess_locking => %d => %d memcached.sess_number_of_replicas => %d => %d memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d -memcached.sess_remove_failed => %d => %d \ No newline at end of file +memcached.sess_remove_failed => %d => %d From ac8d74feb7ea53af6d35b73249cac72ae9797f44 Mon Sep 17 00:00:00 2001 From: ryanp Date: Wed, 23 Jan 2013 09:42:05 -0600 Subject: [PATCH 142/694] throw warning when ascii is used with *_with_initial() funcs --- php_memcached.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index d1d07246..c75f3604 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1763,6 +1763,10 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } } } else { + if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "*_with_initial() only supported with binary protocol"); + RETURN_FALSE; + } if (by_key) { if (incr) { status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); From f176c203a0aacd6c03654e1b49929f66b7fcd225 Mon Sep 17 00:00:00 2001 From: ryanp Date: Wed, 23 Jan 2013 09:51:54 -0600 Subject: [PATCH 143/694] update api --- memcached-api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 75522950..f56ff56e 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -239,9 +239,9 @@ public function deleteMulti( array $keys, $expiration = 0 ) {} public function deleteMultiByKey( $server_key, array $keys, $expiration = 0 ) {} - public function increment( $key, $offset = 1) {} + public function increment( $key, $offset = 1, $initial_value = 0, $expiry = 0) {} - public function decrement( $key, $offset = 1) {} + public function decrement( $key, $offset = 1, $initial_value = 0, $expiry = 0) {} public function getOption( $option ) {} From 897b62ecf31ff081cf257c1fe63d18ce83bf0497 Mon Sep 17 00:00:00 2001 From: ryanp Date: Wed, 23 Jan 2013 15:46:35 -0600 Subject: [PATCH 144/694] retry on temp failure --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index c75f3604..63d3869a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1174,6 +1174,7 @@ PHP_METHOD(Memcached, setMultiByKey) case MEMCACHED_TIMEOUT: \ case MEMCACHED_FAIL_UNIX_SOCKET: \ case MEMCACHED_SERVER_MARKED_DEAD: \ + case MEMCACHED_SERVER_TEMPORARILY_DISABLED: \ if (memcached_server_count(m_obj->memc) > 0) { \ retry++; \ i_obj->rescode = 0; \ From 6fa359df87ae4a59393158ff24603efb296171ef Mon Sep 17 00:00:00 2001 From: Don MacAskill Date: Mon, 28 Jan 2013 13:27:52 -0800 Subject: [PATCH 145/694] Fixed typo. HAVE_MEMECACHED_MSGPACK -> HAVE_MEMCACHED_MSGPACK --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 50366e1e..43f8a501 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -47,7 +47,7 @@ enum memcached_serializer { #ifdef HAVE_MEMCACHED_IGBINARY #define SERIALIZER_DEFAULT SERIALIZER_IGBINARY #define SERIALIZER_DEFAULT_NAME "igbinary" -#elif HAVE_MEMECACHED_MSGPACK +#elif HAVE_MEMCACHED_MSGPACK #define SERIALIZER_DEFAULT SERIALIZER_MSGPACK #define SERIALIZER_DEFAULT_NAME "msgpack" #else From 3313fa157bfc17545fe0d5ab76a8481fd6a27a48 Mon Sep 17 00:00:00 2001 From: Mitch Hagstrand Date: Sat, 17 Nov 2012 12:30:55 -0800 Subject: [PATCH 146/694] Removed unused memcached.ini option After the merge of commits 5ff9516240 and faf84af789 the memcached.sess_num_replicas option is no longer used --- memcached.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/memcached.ini b/memcached.ini index f4bd68c0..ef832efc 100644 --- a/memcached.ini +++ b/memcached.ini @@ -35,15 +35,12 @@ memcached.sess_remove_failed = 1 ; from a replica. However, if the failed memcache server ; becomes available again it will read the session from there ; which could have old data or no data at all -memcached.sess_num_replicas = 0; +memcached.sess_number_of_replicas = 0 ; memcached session binary mode ; libmemcached replicas only work if binary mode is enabled memcached.sess_binary = Off -; memcached session number of replicas -memcached.sess_number_of_replicas = 0 - ; memcached session replica read randomize memcached.sess_randomize_replica_read = Off From 7bff70a3c3135dd14c8d3d8649b88a3a5b467104 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 3 Mar 2013 10:12:19 -0500 Subject: [PATCH 147/694] Fixed typo in define name from case #55 --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1d2fb2d0..52411455 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -264,7 +264,7 @@ static PHP_INI_MH(OnUpdateSerializer) MEMC_G(serializer) = SERIALIZER_DEFAULT; } else if (!strcmp(new_value, "php")) { MEMC_G(serializer) = SERIALIZER_PHP; -#ifdef HAVE_MEMCACHE_IGBINARY +#ifdef HAVE_MEMCACHED_IGBINARY } else if (!strcmp(new_value, "igbinary")) { MEMC_G(serializer) = SERIALIZER_IGBINARY; #endif // IGBINARY From a551d38e34e65a8e7d4dafa64abac2eb58656e46 Mon Sep 17 00:00:00 2001 From: nakyau Date: Wed, 20 Mar 2013 00:16:43 +0900 Subject: [PATCH 148/694] Fix Changelog for 2.0.0b1. Issue 41 --- ChangeLog | 2 -- 1 file changed, 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9a7280d7..3502e197 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,8 +41,6 @@ Version 2.0.0b2 Version 2.0.0b1 --------------- - * Change the return value for non-existing keys to be NULL rather than - 'false', affects simple get only * Add fastlz library that provides better/faster payload compression * Add configure switch to enable/disable JSON serialization support * Add getAllKeys() method From 80cb21467a1db6b7b18725df586f11801c823695 Mon Sep 17 00:00:00 2001 From: giac Date: Tue, 26 Mar 2013 11:43:20 +0000 Subject: [PATCH 149/694] Update php_memcached.c The symbols memcached_server_major_version, memcached_server_minor_version, memcached_server_micro_version have been introduced in libmemcached 1.0.9, not 1.0.9. Reference: I downloaded the libmemcached source from here: https://launchpad.net/libmemcached/+download --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 839b7bcf..6581365d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2730,7 +2730,7 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, me struct callbackContext* context = (struct callbackContext*) in_context; hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000008 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 version_len = snprintf(version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), From 173b49e72803a67a12cef28169f90e3b01981063 Mon Sep 17 00:00:00 2001 From: blat Date: Wed, 1 May 2013 19:29:17 +0200 Subject: [PATCH 150/694] stop returning NOT_FOUND when an error occured --- php_memcached.c | 140 +++++++++++++++++------------------------------- 1 file changed, 48 insertions(+), 92 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6581365d..e29c4b9d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -550,120 +550,76 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) keys[0] = key; key_lens[0] = key_len; - if (cas_token) { - uint64_t orig_cas_flag; - - /* - * Enable CAS support, but only if it is currently disabled. - */ - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); - } - - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); - - if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); - } - - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - RETURN_FROM_GET; - } - - status = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &result); - - if (memcached_fetch_result(m_obj->memc, &result, &status) == NULL) { - /* This is for historical reasons */ - if (status == MEMCACHED_END) - status = MEMCACHED_NOTFOUND; - - /* - * If the result wasn't found, and we have the read-through callback, invoke - * it to get the value. The CAS token will be 0, because we cannot generate it - * ourselves. - */ - if (status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, - return_value TSRMLS_CC); - ZVAL_DOUBLE(cas_token, 0); - } - - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - memcached_result_free(&result); - RETURN_FROM_GET; - } - - /* if we have a callback, all processing is done */ - if (fci.size != 0) { - memcached_result_free(&result); - return; - } - } - - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - cas = memcached_result_cas(&result); + uint64_t orig_cas_flag; + orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { - memcached_result_free(&result); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FROM_GET; - } + /* + * Enable CAS support, but only if it is currently disabled. + */ + if (cas_token && orig_cas_flag == 0) { + memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + } - zval_dtor(cas_token); - ZVAL_DOUBLE(cas_token, (double)cas); + status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); - memcached_result_free(&result); + if (cas_token && orig_cas_flag == 0) { + memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + } - } else { - int rc; - zend_bool return_value_set = 0; + if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + RETURN_FROM_GET; + } - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); - payload = memcached_fetch(m_obj->memc, NULL, NULL, &payload_len, &flags, &status); + status = MEMCACHED_SUCCESS; + memcached_result_create(m_obj->memc, &result); + if (memcached_fetch_result(m_obj->memc, &result, &status) == NULL) { /* This is for historical reasons */ if (status == MEMCACHED_END) status = MEMCACHED_NOTFOUND; /* - * If payload wasn't found and we have a read-through callback, invoke it to get - * the value. The callback will take care of storing the value back into memcache. - * The callback will set the return value. - */ - if (payload == NULL && status == MEMCACHED_NOTFOUND && fci.size != 0) { - size_t dummy_length; - uint32_t dummy_flags; - memcached_return dummy_status; - + * If the result wasn't found, and we have the read-through callback, invoke + * it to get the value. The CAS token will be 0, because we cannot generate it + * ourselves. + */ + if (cas_token && status == MEMCACHED_NOTFOUND && fci.size != 0) { status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, return_value TSRMLS_CC); - return_value_set = 1; - - (void)memcached_fetch(m_obj->memc, NULL, NULL, &dummy_length, &dummy_flags, &dummy_status); + ZVAL_DOUBLE(cas_token, 0); } if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - if (payload) { - free(payload); - } + memcached_result_free(&result); RETURN_FROM_GET; } - /* if memcached gave a value and there was no callback, payload may be NULL */ - if (!return_value_set) { - rc = php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC); - free(payload); - if (rc < 0) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FROM_GET; - } + /* if we have a callback, all processing is done */ + if (fci.size != 0) { + memcached_result_free(&result); + return; } + } + payload = memcached_result_value(&result); + payload_len = memcached_result_length(&result); + flags = memcached_result_flags(&result); + if (cas_token) { + cas = memcached_result_cas(&result); } + + if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + memcached_result_free(&result); + i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + RETURN_FROM_GET; + } + + if (cas_token) { + zval_dtor(cas_token); + ZVAL_DOUBLE(cas_token, (double)cas); + } + + memcached_result_free(&result); } /* }}} */ From 81273a4248318588bb38f2fa98d51f2adf7d91fd Mon Sep 17 00:00:00 2001 From: Trevor North Date: Tue, 7 May 2013 17:06:49 +0100 Subject: [PATCH 151/694] Fetch all results in php_memc_get_impl Previously only the first result was fetched after the memcached_mget_by_key call resulting in a RES_END result being left on the stack. As per the libmemcached documentation memcached_fetch_result should be called until it returns NULL following a multi-get. In some circumstances this is not noticeable as libmemcached takes care of flushing the receive buffers accordingly, however certain subsequent operations will incorrectly return the left-over RES_END result. --- php_memcached.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index e29c4b9d..611cba2f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -600,6 +600,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) return; } } + + /* Fetch all remaining results */ + memcached_result_st dummy_result; + memcached_return dummy_status = MEMCACHED_SUCCESS; + memcached_result_create(m_obj->memc, &dummy_result); + while (memcached_fetch_result(m_obj->memc, &dummy_result, &dummy_status) != NULL) {} + memcached_result_free(&dummy_result); payload = memcached_result_value(&result); payload_len = memcached_result_length(&result); From dec87985d96873bde27df608607518061ed5d370 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 26 Jul 2013 11:31:01 +0800 Subject: [PATCH 152/694] Fixed bug #65334 (Segfault if uncompress value failed) --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 6581365d..77e1be7b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2962,6 +2962,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload char *buffer = NULL; if (payload == NULL && payload_len > 0) { + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return -1; @@ -3013,6 +3014,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload } if (!decompress_status) { + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value"); efree(buffer); return -1; @@ -3081,6 +3083,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload goto my_error; } #else + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support"); goto my_error; #endif @@ -3094,12 +3097,14 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); # endif #else + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); goto my_error; #endif break; default: + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); goto my_error; } From 3c4cca741342d77e28d8f48aa0e6243791b47bd4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 7 Oct 2013 12:41:44 +0800 Subject: [PATCH 153/694] A bit of general maintenance, mainly related to issue #69 --- php_memcached.c | 120 +++++++++++++++++++++---------------- tests/bug_16084.phpt | 4 +- tests/getserverlist.phpt | 16 ++--- tests/invoke_callback.phpt | 4 +- 4 files changed, 75 insertions(+), 69 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6581365d..859c92d7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -311,7 +311,7 @@ PHP_INI_END() ****************************************/ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); -static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); +static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -321,9 +321,14 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by 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(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); + +// Cursor callbacks +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); + + + static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); /**************************************** @@ -514,7 +519,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int key_len = 0; char *server_key = NULL; int server_key_len = 0; - char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; uint64_t cas = 0; @@ -551,6 +555,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) key_lens[0] = key_len; if (cas_token) { + const char *payload = NULL; uint64_t orig_cas_flag; /* @@ -619,6 +624,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_result_free(&result); } else { + char *payload = NULL; int rc; zend_bool return_value_set = 0; @@ -691,11 +697,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke int server_key_len = 0; size_t num_keys = 0; zval **entry = NULL; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; const char **mkeys = NULL; size_t *mkeys_len = NULL; - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; uint32_t flags; uint64_t cas = 0; @@ -806,12 +812,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke res_key = memcached_result_key_value(&result); res_key_len = memcached_result_key_length(&result); - /* - * This may be a bug in libmemcached, the key is not null terminated - * whe using the binary protocol. - */ - res_key[res_key_len] = 0; - MAKE_STD_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { @@ -829,7 +829,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - add_assoc_zval_ex(return_value, res_key, res_key_len+1, value); + if (res_key [res_key_len - 1] != '\0') { + /* Terminate if needed */ + char key_buffer [MEMCACHED_MAX_KEY]; + + if (res_key_len < MEMCACHED_MAX_KEY) { + memcpy (key_buffer, res_key, res_key_len); + key_buffer [res_key_len] = '\0'; + + add_assoc_zval_ex(return_value, key_buffer, res_key_len + 1, value); + } + } + else { + add_assoc_zval_ex(return_value, res_key, res_key_len + 1, value); + } + if (cas_tokens) { cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); @@ -992,9 +1006,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ Returns the next result from a previous delayed request */ PHP_METHOD(Memcached, fetch) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value; uint32_t flags = 0; @@ -1049,9 +1063,9 @@ PHP_METHOD(Memcached, fetch) Returns all the results from a previous delayed request */ PHP_METHOD(Memcached, fetchAll) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value, *entry; uint32_t flags; @@ -1965,7 +1979,7 @@ PHP_METHOD(Memcached, getServerByKey) { char *server_key; int server_key_len; - memcached_server_instance_st *server_instance; + const memcached_instance_st *server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; @@ -2083,7 +2097,7 @@ PHP_METHOD(Memcached, getLastErrorErrno) Was added in 0.34 according to libmemcached's Changelog */ PHP_METHOD(Memcached, getLastDisconnectedServer) { - memcached_server_instance_st *server_instance; + const memcached_instance_st *server_instance; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { @@ -2398,12 +2412,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML */ flag = (memcached_behavior) option; convert_to_long(value); - if (flag < 0 || -/* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 - flag >= MEMCACHED_BEHAVIOR_MAX || -#endif - memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { + if (memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option"); return 0; } @@ -2660,7 +2669,7 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) /* }}} */ /* {{{ internal API functions */ -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; zval *array; @@ -2671,6 +2680,9 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, add_assoc_long(array, "port", memcached_server_port(instance)); /* * API does not allow to get at this field. + * + * If you comment out stuff like this, please fix tests. -- Mikko + * add_assoc_long(array, "weight", instance->weight); */ @@ -2678,7 +2690,7 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) { char *hostport = NULL; int hostport_len; @@ -2722,7 +2734,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memc return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) { char *hostport = NULL; char version[16]; @@ -2953,13 +2965,20 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) +static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) { + char *pl; + size_t pl_len; + /* A NULL payload is completely valid if length is 0, it is simply empty. */ zend_bool payload_emalloc = 0; - char *buffer = NULL; + + // Explicit cast + pl = (char *) payload; + pl_len = payload_len; + if (payload == NULL && payload_len > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, @@ -2976,6 +2995,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload if (flags & MEMC_VAL_COMPRESSED) { uint32_t len; + char *buffer = NULL; unsigned long length; zend_bool decompress_status = 0; @@ -3017,49 +3037,47 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload efree(buffer); return -1; } - payload = buffer; - payload_len = length; + pl = buffer; + pl_len = length; payload_emalloc = 1; } - payload[payload_len] = 0; - switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: if (payload_emalloc) { - ZVAL_STRINGL(value, payload, payload_len, 0); + ZVAL_STRINGL(value, pl, pl_len, 0); payload_emalloc = 0; } else { - ZVAL_STRINGL(value, payload, payload_len, 1); + ZVAL_STRINGL(value, pl, pl_len, 1); } break; case MEMC_VAL_IS_LONG: { - long lval = strtol(payload, NULL, 10); + long lval = strtol(pl, NULL, 10); ZVAL_LONG(value, lval); break; } case MEMC_VAL_IS_DOUBLE: - if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) { + if (pl_len == 8 && memcmp(pl, "Infinity", 8) == 0) { ZVAL_DOUBLE(value, php_get_inf()); - } else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) { + } else if (pl_len == 9 && memcmp(pl, "-Infinity", 9) == 0) { ZVAL_DOUBLE(value, -php_get_inf()); - } else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) { + } else if (pl_len == 3 && memcmp(pl, "NaN", 3) == 0) { ZVAL_DOUBLE(value, php_get_nan()); } else { - ZVAL_DOUBLE(value, zend_strtod(payload, NULL)); + ZVAL_DOUBLE(value, zend_strtod(pl, NULL)); } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1'); + ZVAL_BOOL(value, pl_len > 0 && pl[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: { - const char *payload_tmp = payload; + const char *payload_tmp = pl; php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -3075,7 +3093,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { + if (igbinary_unserialize((uint8_t *)pl, pl_len, &value TSRMLS_CC)) { ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); goto my_error; @@ -3089,9 +3107,9 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API # if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); + php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); # elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); + php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); # endif #else php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); @@ -3105,14 +3123,14 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload } if (payload_emalloc) { - efree(payload); + efree(pl); } return 0; my_error: if (payload_emalloc) { - efree(payload); + efree(pl); } return -1; } @@ -3269,9 +3287,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value, *retval = NULL; uint64_t cas = 0; diff --git a/tests/bug_16084.phpt b/tests/bug_16084.phpt index 2c282bb2..c103b297 100644 --- a/tests/bug_16084.phpt +++ b/tests/bug_16084.phpt @@ -13,12 +13,10 @@ var_dump($m->getServerList()); bool(true) array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index 1761f33c..e4ef5968 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -20,43 +20,35 @@ array(0) { } array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } array(2) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } [1]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) - ["weight"]=> - int(%r[01]%r) } } diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index 6fddc0c0..d5d0cc90 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -19,13 +19,11 @@ echo "OK\n"; --EXPECTF-- array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) - ["weight"]=> - int(%r[01]%r) } } OK From 29e5d83d2a2c9db13d4022bbc7122f777dde87ce Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 7 Oct 2013 12:56:03 +0800 Subject: [PATCH 154/694] Use pl here --- php_memcached.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 859c92d7..3c2b1367 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2980,11 +2980,11 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p pl_len = payload_len; - if (payload == NULL && payload_len > 0) { + if (pl == NULL && pl_len > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Could not handle non-existing value of length %zu", payload_len); + "Could not handle non-existing value of length %zu", pl_len); return -1; - } else if (payload == NULL) { + } else if (pl == NULL) { if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) { ZVAL_FALSE(value); } else { From 70f859f78d814137825a2ef92c970efe7dde91b1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 02:21:37 +0800 Subject: [PATCH 155/694] Revert "Use pl here" This reverts commit 29e5d83d2a2c9db13d4022bbc7122f777dde87ce. --- php_memcached.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3c2b1367..859c92d7 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2980,11 +2980,11 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p pl_len = payload_len; - if (pl == NULL && pl_len > 0) { + if (payload == NULL && payload_len > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Could not handle non-existing value of length %zu", pl_len); + "Could not handle non-existing value of length %zu", payload_len); return -1; - } else if (pl == NULL) { + } else if (payload == NULL) { if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) { ZVAL_FALSE(value); } else { From 71b03db0c8e63ca20c4562201918f37e0ba45bc3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 02:21:47 +0800 Subject: [PATCH 156/694] Revert "A bit of general maintenance, mainly related to issue #69" This reverts commit 3c4cca741342d77e28d8f48aa0e6243791b47bd4. --- php_memcached.c | 120 ++++++++++++++++--------------------- tests/bug_16084.phpt | 4 +- tests/getserverlist.phpt | 16 +++-- tests/invoke_callback.phpt | 4 +- 4 files changed, 69 insertions(+), 75 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 859c92d7..6581365d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -311,7 +311,7 @@ PHP_INI_END() ****************************************/ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); +static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -321,14 +321,9 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by 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); - -// Cursor callbacks -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context); - - - +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); /**************************************** @@ -519,6 +514,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int key_len = 0; char *server_key = NULL; int server_key_len = 0; + char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; uint64_t cas = 0; @@ -555,7 +551,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) key_lens[0] = key_len; if (cas_token) { - const char *payload = NULL; uint64_t orig_cas_flag; /* @@ -624,7 +619,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_result_free(&result); } else { - char *payload = NULL; int rc; zend_bool return_value_set = 0; @@ -697,11 +691,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke int server_key_len = 0; size_t num_keys = 0; zval **entry = NULL; - const char *payload = NULL; + char *payload = NULL; size_t payload_len = 0; const char **mkeys = NULL; size_t *mkeys_len = NULL; - const char *res_key = NULL; + char *res_key = NULL; size_t res_key_len = 0; uint32_t flags; uint64_t cas = 0; @@ -812,6 +806,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke res_key = memcached_result_key_value(&result); res_key_len = memcached_result_key_length(&result); + /* + * This may be a bug in libmemcached, the key is not null terminated + * whe using the binary protocol. + */ + res_key[res_key_len] = 0; + MAKE_STD_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { @@ -829,21 +829,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - if (res_key [res_key_len - 1] != '\0') { - /* Terminate if needed */ - char key_buffer [MEMCACHED_MAX_KEY]; - - if (res_key_len < MEMCACHED_MAX_KEY) { - memcpy (key_buffer, res_key, res_key_len); - key_buffer [res_key_len] = '\0'; - - add_assoc_zval_ex(return_value, key_buffer, res_key_len + 1, value); - } - } - else { - add_assoc_zval_ex(return_value, res_key, res_key_len + 1, value); - } - + add_assoc_zval_ex(return_value, res_key, res_key_len+1, value); if (cas_tokens) { cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); @@ -1006,9 +992,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ Returns the next result from a previous delayed request */ PHP_METHOD(Memcached, fetch) { - const char *res_key = NULL; + char *res_key = NULL; size_t res_key_len = 0; - const char *payload = NULL; + char *payload = NULL; size_t payload_len = 0; zval *value; uint32_t flags = 0; @@ -1063,9 +1049,9 @@ PHP_METHOD(Memcached, fetch) Returns all the results from a previous delayed request */ PHP_METHOD(Memcached, fetchAll) { - const char *res_key = NULL; + char *res_key = NULL; size_t res_key_len = 0; - const char *payload = NULL; + char *payload = NULL; size_t payload_len = 0; zval *value, *entry; uint32_t flags; @@ -1979,7 +1965,7 @@ PHP_METHOD(Memcached, getServerByKey) { char *server_key; int server_key_len; - const memcached_instance_st *server_instance; + memcached_server_instance_st *server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; @@ -2097,7 +2083,7 @@ PHP_METHOD(Memcached, getLastErrorErrno) Was added in 0.34 according to libmemcached's Changelog */ PHP_METHOD(Memcached, getLastDisconnectedServer) { - const memcached_instance_st *server_instance; + memcached_server_instance_st *server_instance; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { @@ -2412,7 +2398,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML */ flag = (memcached_behavior) option; convert_to_long(value); - if (memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { + if (flag < 0 || +/* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 + flag >= MEMCACHED_BEHAVIOR_MAX || +#endif + memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option"); return 0; } @@ -2669,7 +2660,7 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) /* }}} */ /* {{{ internal API functions */ -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; zval *array; @@ -2680,9 +2671,6 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, add_assoc_long(array, "port", memcached_server_port(instance)); /* * API does not allow to get at this field. - * - * If you comment out stuff like this, please fix tests. -- Mikko - * add_assoc_long(array, "weight", instance->weight); */ @@ -2690,7 +2678,7 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) { char *hostport = NULL; int hostport_len; @@ -2734,7 +2722,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, cons return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context) +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) { char *hostport = NULL; char version[16]; @@ -2965,20 +2953,13 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) +static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) { - char *pl; - size_t pl_len; - /* A NULL payload is completely valid if length is 0, it is simply empty. */ zend_bool payload_emalloc = 0; - - // Explicit cast - pl = (char *) payload; - pl_len = payload_len; - + char *buffer = NULL; if (payload == NULL && payload_len > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, @@ -2995,7 +2976,6 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p if (flags & MEMC_VAL_COMPRESSED) { uint32_t len; - char *buffer = NULL; unsigned long length; zend_bool decompress_status = 0; @@ -3037,47 +3017,49 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p efree(buffer); return -1; } - pl = buffer; - pl_len = length; + payload = buffer; + payload_len = length; payload_emalloc = 1; } + payload[payload_len] = 0; + switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: if (payload_emalloc) { - ZVAL_STRINGL(value, pl, pl_len, 0); + ZVAL_STRINGL(value, payload, payload_len, 0); payload_emalloc = 0; } else { - ZVAL_STRINGL(value, pl, pl_len, 1); + ZVAL_STRINGL(value, payload, payload_len, 1); } break; case MEMC_VAL_IS_LONG: { - long lval = strtol(pl, NULL, 10); + long lval = strtol(payload, NULL, 10); ZVAL_LONG(value, lval); break; } case MEMC_VAL_IS_DOUBLE: - if (pl_len == 8 && memcmp(pl, "Infinity", 8) == 0) { + if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) { ZVAL_DOUBLE(value, php_get_inf()); - } else if (pl_len == 9 && memcmp(pl, "-Infinity", 9) == 0) { + } else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) { ZVAL_DOUBLE(value, -php_get_inf()); - } else if (pl_len == 3 && memcmp(pl, "NaN", 3) == 0) { + } else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) { ZVAL_DOUBLE(value, php_get_nan()); } else { - ZVAL_DOUBLE(value, zend_strtod(pl, NULL)); + ZVAL_DOUBLE(value, zend_strtod(payload, NULL)); } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(value, pl_len > 0 && pl[0] == '1'); + ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: { - const char *payload_tmp = pl; + const char *payload_tmp = payload; php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -3093,7 +3075,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)pl, pl_len, &value TSRMLS_CC)) { + if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); goto my_error; @@ -3107,9 +3089,9 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API # if HAVE_JSON_API_5_2 - php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); # elif HAVE_JSON_API_5_3 - php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); # endif #else php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); @@ -3123,14 +3105,14 @@ static int php_memc_zval_from_payload(zval *value, const char *payload, size_t p } if (payload_emalloc) { - efree(pl); + efree(payload); } return 0; my_error: if (payload_emalloc) { - efree(pl); + efree(payload); } return -1; } @@ -3287,9 +3269,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC) { - const char *res_key = NULL; + char *res_key = NULL; size_t res_key_len = 0; - const char *payload = NULL; + char *payload = NULL; size_t payload_len = 0; zval *value, *retval = NULL; uint64_t cas = 0; diff --git a/tests/bug_16084.phpt b/tests/bug_16084.phpt index c103b297..2c282bb2 100644 --- a/tests/bug_16084.phpt +++ b/tests/bug_16084.phpt @@ -13,10 +13,12 @@ var_dump($m->getServerList()); bool(true) array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["weight"]=> + int(3) } } diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index e4ef5968..1761f33c 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -20,35 +20,43 @@ array(0) { } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["weight"]=> + int(3) } } array(2) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["weight"]=> + int(3) } [1]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["weight"]=> + int(3) } } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["weight"]=> + int(%r[01]%r) } } diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index d5d0cc90..6fddc0c0 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -19,11 +19,13 @@ echo "OK\n"; --EXPECTF-- array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["weight"]=> + int(%r[01]%r) } } OK From 9812556e7a3e4900a5d10a898b5593c171d59064 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:10:22 +0800 Subject: [PATCH 157/694] Fixed broken tests, fixed build against different libmemcached versions (hopefully) and misc error fixes --- .travis.yml | 31 +++++++++++ config.m4 | 19 +++++++ php_memcached.c | 36 ++++++++----- tests/bug_16084.phpt | 4 +- tests/experimental/moduleinfo.phpt | 2 + tests/expire.phpt | 83 ++++++++++++++++++------------ tests/getserverlist.phpt | 16 ++---- tests/invoke_callback.phpt | 4 +- 8 files changed, 131 insertions(+), 64 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..f999af7d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +language: php +php: + - 5.5 + - 5.4 + - 5.3 +env: + - LIBMEMCACHED_VERSION=1.0.17 + - LIBMEMCACHED_VERSION=1.0.16 + - LIBMEMCACHED_VERSION=0.53 + - LIBMEMCACHED_VERSION=0.44 + +before_script: + - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" + - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz + - cd libmemcached-${LIBMEMCACHED_VERSION} + - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" LDFLAGS="-lpthread" + - make + - make install + - cd .. + + +script: + - phpize + - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" + - make + - export NO_INTERACTION=1 + - export REPORT_EXIT_STATUS=1 + - export TEST_PHP_EXECUTABLE=`which php` + - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n ./tests/*.phpt + - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo "-- END"; done + diff --git a/config.m4 b/config.m4 index b8bbbff5..fa232f1b 100644 --- a/config.m4 +++ b/config.m4 @@ -246,6 +246,25 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR) PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) + ORIG_CFLAGS="$CFLAGS" + CFLAGS="-I$PHP_LIBMEMCACHED_INCDIR" + + AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ + AC_TRY_COMPILE( + [ #include ], + [ const memcached_instance_st *instance = NULL; ], + [ ac_cv_have_memcached_instance_st="yes" ], + [ ac_cv_have_memcached_instance_st="no" ] + ) + ]) + + CFLAGS="$ORIG_CFLAGS" + + if test "$ac_cv_have_memcached_instance_st" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_INSTANCE_ST, [1], [Whether memcached_instance_st is defined]) + fi + + PHP_SUBST(MEMCACHED_SHARED_LIBADD) PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c g_fmt.c" diff --git a/php_memcached.c b/php_memcached.c index 6581365d..f57b378f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -54,6 +54,13 @@ #include "fastlz/fastlz.h" #include +/* Compatibility with older versions */ +#ifdef HAVE_MEMCACHED_INSTANCE_ST +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif + /* Used to store the size of the block */ #if defined(HAVE_INTTYPES_H) #include @@ -321,9 +328,9 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by 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(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context); +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); /**************************************** @@ -695,7 +702,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke size_t payload_len = 0; const char **mkeys = NULL; size_t *mkeys_len = NULL; - char *res_key = NULL; + const char *tmp_key = NULL; size_t res_key_len = 0; uint32_t flags; uint64_t cas = 0; @@ -794,6 +801,8 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { + char res_key [MEMCACHED_MAX_KEY]; + if (status != MEMCACHED_SUCCESS) { status = MEMCACHED_SOME_ERRORS; php_memc_handle_error(i_obj, status TSRMLS_CC); @@ -803,14 +812,15 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke payload = memcached_result_value(&result); payload_len = memcached_result_length(&result); flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); + tmp_key = memcached_result_key_value(&result); res_key_len = memcached_result_key_length(&result); /* * This may be a bug in libmemcached, the key is not null terminated * whe using the binary protocol. */ - res_key[res_key_len] = 0; + memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); + res_key [res_key_len] = '\0'; MAKE_STD_ZVAL(value); @@ -1339,7 +1349,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool int s_value_len = 0; zval s_zvalue; zval *value; - time_t expiration = 0; + long expiration = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1411,10 +1421,12 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } if (op == MEMC_OP_TOUCH) { +#ifdef mikko_0 if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); RETURN_FALSE; } +#endif } else { payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { @@ -1965,7 +1977,7 @@ PHP_METHOD(Memcached, getServerByKey) { char *server_key; int server_key_len; - memcached_server_instance_st *server_instance; + php_memcached_instance_st server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; @@ -2083,7 +2095,7 @@ PHP_METHOD(Memcached, getLastErrorErrno) Was added in 0.34 according to libmemcached's Changelog */ PHP_METHOD(Memcached, getLastDisconnectedServer) { - memcached_server_instance_st *server_instance; + php_memcached_instance_st server_instance; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { @@ -2660,7 +2672,7 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) /* }}} */ /* {{{ internal API functions */ -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; zval *array; @@ -2678,7 +2690,7 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { char *hostport = NULL; int hostport_len; @@ -2722,7 +2734,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memc return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context) +static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { char *hostport = NULL; char version[16]; diff --git a/tests/bug_16084.phpt b/tests/bug_16084.phpt index 2c282bb2..c103b297 100644 --- a/tests/bug_16084.phpt +++ b/tests/bug_16084.phpt @@ -13,12 +13,10 @@ var_dump($m->getServerList()); bool(true) array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index fa3cd631..941e2f27 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -24,6 +24,7 @@ memcached.compression_threshold => %d => %d memcached.compression_type => %s => %s memcached.serializer => %s => %s memcached.sess_binary => %d => %d +memcached.sess_connect_timeout => %d => %d memcached.sess_consistent_hash => %d => %d memcached.sess_lock_wait => %d => %d memcached.sess_locking => %d => %d @@ -31,3 +32,4 @@ memcached.sess_number_of_replicas => %d => %d memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d memcached.sess_remove_failed => %d => %d +memcached.use_sasl => %d => %d \ No newline at end of file diff --git a/tests/expire.phpt b/tests/expire.phpt index 17ddcc1e..01cd5208 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -4,47 +4,62 @@ Memcached store, fetch & touch expired key --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$m->addServer('127.0.0.1', 11211, 1); -$set = $m->set('will_expire', "foo", 2); -$v = $m->get('will_expire'); -if (!$set || $v != 'foo') { - echo "Error setting will_expire to \"foo\" with 2s expiry.\n"; -} -sleep(1); -$res = $m->touch('will_expire', 2); -$v = $m->get('will_expire'); -if(!$res || $v != 'foo') { - echo "Error touching will_expire for another 2s expiry.\n"; - var_dump($res); - var_dump($m->getResultMessage()); - var_dump($v); -} +function run_expiry_test ($m) { + + $key = uniqid ('will_expire_'); + + $set = $m->set($key, "foo", 2); + $v = $m->get($key); + if (!$set || $v != 'foo') { + echo "Error setting key to \"foo\" with 2s expiry.\n"; + return; + } + + sleep(1); + $res = $m->touch($key, 2); + $v = $m->get($key); + + if(!$res || $v != 'foo') { + echo "Error touching key for another 2s expiry.\n"; + var_dump($res); + var_dump($m->getResultMessage()); + var_dump($v); + return; + } -sleep(3); -$v = $m->get('will_expire'); + sleep(3); + $v = $m->get($key); -if ($v !== Memcached::GET_ERROR_RETURN_VALUE) { - echo "Wanted:\n"; - var_dump(Memcached::GET_ERROR_RETURN_VALUE); - echo "from get of expired value. Got:\n"; - var_dump($v); + if ($v !== Memcached::GET_ERROR_RETURN_VALUE) { + echo "Wanted:\n"; + var_dump(Memcached::GET_ERROR_RETURN_VALUE); + echo "from get of expired value. Got:\n"; + var_dump($v); + return; + } + echo "All OK" . PHP_EOL; } -// test with plaintext proto should throw error + $m = new Memcached(); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $m->addServer('127.0.0.1', 11211, 1); -$set = $m->set('will_expire', "foo", 2); -$v = $m->touch('will_expire'); -if($v !== false) { - echo "Touch with text protocol should return false.\n"; -} +echo '-- binary protocol' . PHP_EOL; +run_expiry_test ($m); + +$m = new Memcached(); +$m->addServer('127.0.0.1', 11211, 1); + +echo '-- text protocol' . PHP_EOL; +run_expiry_test ($m); -echo "OK\n"; +echo "DONE TEST\n"; ?> ---EXPECTF-- -Warning: Memcached::touch(): touch is only supported with binary protocol in %s on line %d -OK +--EXPECT-- +-- binary protocol +All OK +-- text protocol +All OK +DONE TEST diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index 1761f33c..e4ef5968 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -20,43 +20,35 @@ array(0) { } array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } array(2) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } [1]=> - array(3) { + array(2) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) - ["weight"]=> - int(3) } } array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) - ["weight"]=> - int(%r[01]%r) } } diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index 6fddc0c0..d5d0cc90 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -19,13 +19,11 @@ echo "OK\n"; --EXPECTF-- array(1) { [0]=> - array(3) { + array(2) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) - ["weight"]=> - int(%r[01]%r) } } OK From b5daa1da5340d1002b52dc59bf2f44079cdfb1fd Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:12:26 +0800 Subject: [PATCH 158/694] Push to start travis ci --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index fa232f1b..7f8e599b 100644 --- a/config.m4 +++ b/config.m4 @@ -257,7 +257,7 @@ if test "$PHP_MEMCACHED" != "no"; then [ ac_cv_have_memcached_instance_st="no" ] ) ]) - + CFLAGS="$ORIG_CFLAGS" if test "$ac_cv_have_memcached_instance_st" = "yes"; then From 51a3ec8bbb44812c41fe6cf15d46c20f0209f278 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:16:30 +0800 Subject: [PATCH 159/694] I guess holidays 2013 makes more sense, also added travis build status --- README.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index aaad0961..479613fd 100644 --- a/README.markdown +++ b/README.markdown @@ -1,4 +1,6 @@ -2012 Holidays +[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=master)](https://travis-ci.org/php-memcached-dev/php-memcached) + +2013 Holidays ------------- Committers' wishlists, if you feel like kicking in towards a gift: * [Andrei's](http://given.to/profile/andreiz/wishlist/1411) From aa1a0daee92967bda73f2c7cb3dc432aa15ce8e1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:24:06 +0800 Subject: [PATCH 160/694] Added test for #75 --- tests/pr_75.phpt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/pr_75.phpt diff --git a/tests/pr_75.phpt b/tests/pr_75.phpt new file mode 100644 index 00000000..52f41020 --- /dev/null +++ b/tests/pr_75.phpt @@ -0,0 +1,26 @@ +--TEST-- +Memcached multi store & multi fetch type and value correctness +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$client->set('key1', 'value1'); +echo "set result code: ".$client->getResultCode()."\n"; + +$value = $client->get('key1'); +echo "got $value with result code: ".$client->getResultCode()."\n"; + +$client->add('key2', 'value2'); +echo "add result code: ".$client->getResultCode()."\n"; + +echo "OK\n"; + +?> +--EXPECT-- +set result code: 0 +got value1 with result code: 0 +add result code: 0 +OK \ No newline at end of file From de082cc43b2d195d0378f564bf262ba77df35c44 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:31:49 +0800 Subject: [PATCH 161/694] Fix another broken test --- tests/types_multi.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt index a5c0299b..456405f9 100644 --- a/tests/types_multi.phpt +++ b/tests/types_multi.phpt @@ -32,7 +32,7 @@ $data = array( 'array' => array(1,2,3,"foo"), 'object_array_empty' => (object)array(), - 'object_array' => (object)array(1,2,3), + 'object_array' => (object)array('a' => 1, 'b' => 2, 'c' => 3), 'object_dummy' => new testclass(), ); From 46a0dea083e0a010de345bd9cc45dcdbf2c5120c Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:33:42 +0800 Subject: [PATCH 162/694] This test made no sense before --- tests/no-not-found.phpt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/no-not-found.phpt diff --git a/tests/no-not-found.phpt b/tests/no-not-found.phpt new file mode 100644 index 00000000..de96d3e4 --- /dev/null +++ b/tests/no-not-found.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test that correct return value is returned +--SKIPIF-- + +--FILE-- +addServer('localhost', 5555); // Server should not exist + +$result = $memcached->get('foo_not_exists'); +var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); + +$cas = 7; +$result = $memcached->get('foo_not_exists', null, $cas); +var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); + +echo "OK\n"; + +?> +--EXPECT-- +bool(true) +bool(true) +OK From 69b790a3362ddc1d341b184c0fdb3b4e0002ac7a Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:36:15 +0800 Subject: [PATCH 163/694] Add xfail --- tests/expire.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/expire.phpt b/tests/expire.phpt index 01cd5208..f7562390 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -1,5 +1,7 @@ --TEST-- Memcached store, fetch & touch expired key +--XFAIL-- +libmemcached ignores expiration with binary proto --SKIPIF-- --FILE-- From 66a30452ee9be9897ae3884ac057f732d7d53a2c Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:43:49 +0800 Subject: [PATCH 164/694] Test for spaces in keys as per #35 --- php_memcached.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index df8b6086..9084df22 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -549,7 +549,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0) { + if (key_len == 0 || strchr(key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1365,7 +1365,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0) { + if (key_len == 0 || strchr(key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1505,7 +1505,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0) { + if (key_len == 0 || strchr(key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1612,7 +1612,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0) { + if (key_len == 0 || strchr(key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1712,7 +1712,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0) { + if (key_len == 0 || strchr(key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1951,7 +1951,7 @@ PHP_METHOD(Memcached, getServerByKey) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (server_key_len == 0) { + if (server_key_len == 0 || strchr(server_key, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } From feb3d5fff1c8029f70c7dfa7c3a41fa79452f63f Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 03:48:46 +0800 Subject: [PATCH 165/694] Add two libmemcached versions, only test with php 5.5 for now --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f999af7d..476e7fc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ language: php php: - 5.5 - - 5.4 - - 5.3 + #- 5.4 + #- 5.3 env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 + - LIBMEMCACHED_VERSION=1.0.8 + - LIBMEMCACHED_VERSION=1.0.2 - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.44 From 028323610c5c32a0018471b7b089b3e610576550 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 04:24:25 +0800 Subject: [PATCH 166/694] Added support for session sasl --- memcached.ini | 9 +++++++++ php_memcached.c | 45 +++++++++++++++++------------------------ php_memcached.h | 3 +++ php_memcached_session.c | 20 ++++++++++++++++++ 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/memcached.ini b/memcached.ini index 7c16dde1..0f1a82b0 100644 --- a/memcached.ini +++ b/memcached.ini @@ -49,6 +49,14 @@ memcached.sess_randomize_replica_read = Off ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. memcached.sess_connect_timeout = 1000 +; Session SASL username +; Both username and password need to be set for SASL to be enabled +; In addition to this memcached.use_sasl needs to be on +memcached.sess_sasl_username = NULL + +; Session SASL password +memcached.sess_sasl_password = NULL + ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz @@ -88,3 +96,4 @@ memcached.serializer = "igbinary" ; valid values: On, Off ; the default is Off memcached.use_sasl = Off + diff --git a/php_memcached.c b/php_memcached.c index 9084df22..0b2da74a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -301,6 +301,9 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) + + STD_PHP_INI_ENTRY("memcached.sess_sasl_username", NULL, PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_sasl_password", NULL, PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) @@ -3107,6 +3110,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(sess_lock_key_len) = 0; MEMC_G(sess_randomize_replica_read) = 0; MEMC_G(sess_connect_timeout) = 1000; + MEMC_G(sess_sasl_username) = NULL; + MEMC_G(sess_sasl_password) = NULL; #endif MEMC_G(serializer_name) = NULL; MEMC_G(serializer) = SERIALIZER_DEFAULT; @@ -3695,13 +3700,8 @@ zend_module_entry memcached_module_entry = { NULL, PHP_MINIT(memcached), PHP_MSHUTDOWN(memcached), -#if HAVE_MEMCACHED_SASL - PHP_RINIT(memcached), - PHP_RSHUTDOWN(memcached), -#else NULL, NULL, -#endif PHP_MINFO(memcached), PHP_MEMCACHED_VERSION, STANDARD_MODULE_PROPERTIES @@ -3880,27 +3880,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) } /* }}} */ -#if HAVE_MEMCACHED_SASL -PHP_RINIT_FUNCTION(memcached) -{ - if (MEMC_G(use_sasl)) { - if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); - } - } - return SUCCESS; -} - -PHP_RSHUTDOWN_FUNCTION(memcached) -{ - if (MEMC_G(use_sasl)) { - sasl_done(); - } - - return SUCCESS; -} -#endif - int php_memc_sess_list_entry(void) { return le_memc_sess; @@ -3941,6 +3920,14 @@ PHP_MINIT_FUNCTION(memcached) #endif REGISTER_INI_ENTRIES(); +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + if (sasl_client_init(NULL) != SASL_OK) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); + return FAILURE; + } + } +#endif return SUCCESS; } /* }}} */ @@ -3954,6 +3941,12 @@ PHP_MSHUTDOWN_FUNCTION(memcached) php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); #endif +#if HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + sasl_done(); + } +#endif + UNREGISTER_INI_ENTRIES(); return SUCCESS; } diff --git a/php_memcached.h b/php_memcached.h index 61e9c69e..7a4a1d42 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -73,6 +73,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) long sess_connect_timeout; zend_bool sess_consistent_hash_enabled; zend_bool sess_binary_enabled; + + char *sess_sasl_username; + char *sess_sasl_password; #endif char *serializer_name; enum memcached_serializer serializer; diff --git a/php_memcached_session.c b/php_memcached_session.c index 952b744d..2dda209c 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -217,7 +217,27 @@ PS_OPEN_FUNC(memcached) return FAILURE; } } +#ifdef HAVE_MEMCACHED_SASL + if (MEMC_G(use_sasl)) { + /* + * Enable SASL support if username and password are set + * + */ + if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) { + /* Force binary protocol */ + if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + return FAILURE; + } + if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session sasl credentials"); + return FAILURE; + } + } + } + +#endif if (MEMC_G(sess_number_of_replicas) > 0) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session number of replicas"); From 626030a4fce0407ad1e975a9430760e9598f91d3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 04:36:33 +0800 Subject: [PATCH 167/694] Should this be empty string? --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a4e905c6..cc4ade89 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -302,8 +302,8 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_sasl_username", NULL, PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_sasl_password", NULL, PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_sasl_username", "", PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_sasl_password", "", PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) From e68aa8c57cb5577c4756fdd141e63c05e974bda1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:06:58 +0800 Subject: [PATCH 168/694] Removed unsupported versions --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 476e7fc9..8fb4956d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,6 @@ env: - LIBMEMCACHED_VERSION=1.0.16 - LIBMEMCACHED_VERSION=1.0.8 - LIBMEMCACHED_VERSION=1.0.2 - - LIBMEMCACHED_VERSION=0.53 - - LIBMEMCACHED_VERSION=0.44 before_script: - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" From ae24f490dae721bcfa5aaf975f5528e3ff455e85 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:14:28 +0800 Subject: [PATCH 169/694] Added flush buffers and a test case, #78 --- php_memcached.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index cc4ade89..a89395dd 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2006,6 +2006,22 @@ PHP_METHOD(Memcached, quit) } /* }}} */ +/* {{{ Memcached::flushBuffers() + Flush and senf buffered commands */ +PHP_METHOD(Memcached, flushBuffers) +{ + memcached_return rc; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + RETURN_BOOL(memcached_flush_buffers(m_obj->memc) == MEMCACHED_SUCCESS); +} +/* }}} */ + #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 /* {{{ Memcached::getLastErrorMessage() Returns the last error message that occurred */ @@ -3547,6 +3563,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_quit, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_flushBuffers, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0) ZEND_ARG_INFO(0, server_key) ZEND_END_ARG_INFO() @@ -3649,6 +3668,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getServerByKey, arginfo_getServerByKey) MEMC_ME(resetServerList, arginfo_resetServerList) MEMC_ME(quit, arginfo_quit) + MEMC_ME(flushBuffers, arginfo_flushBuffers) + #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) From c3a22f2179118ca5fc1d58b9c6e264a4f4ed11ad Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:15:39 +0800 Subject: [PATCH 170/694] Debug on travis why everything fails --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8fb4956d..708ca904 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,8 @@ env: - LIBMEMCACHED_VERSION=1.0.2 before_script: + - sudo apt-get update + - sudo apt-get install valgrind - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - cd libmemcached-${LIBMEMCACHED_VERSION} @@ -26,6 +28,6 @@ script: - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n ./tests/*.phpt + - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n -m ./tests/001.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo "-- END"; done From 74b4eb3ee89821ee77afe814f1bf263ec3206f8b Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:22:52 +0800 Subject: [PATCH 171/694] Display valgrind traces --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 708ca904..d52b8c3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,5 +29,6 @@ script: - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n -m ./tests/001.phpt - - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo "-- END"; done + - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done + - for i in `ls tests/*.mem 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done From 0564ce091bf3c2d56abbc0b31a046381cbd5d9e5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:33:48 +0800 Subject: [PATCH 172/694] Valgrind rocks --- .travis.yml | 6 ++---- php_memcached.c | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index d52b8c3f..7960fe7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,6 @@ env: - LIBMEMCACHED_VERSION=1.0.2 before_script: - - sudo apt-get update - - sudo apt-get install valgrind - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - cd libmemcached-${LIBMEMCACHED_VERSION} @@ -28,7 +26,7 @@ script: - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n -m ./tests/001.phpt + - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n -m ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done - - for i in `ls tests/*.mem 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done + diff --git a/php_memcached.c b/php_memcached.c index a89395dd..1565c848 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3961,18 +3961,18 @@ PHP_MINIT_FUNCTION(memcached) /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(memcached) { -#ifdef ZTS - ts_free_id(php_memcached_globals_id); -#else - php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); -#endif - #if HAVE_MEMCACHED_SASL if (MEMC_G(use_sasl)) { sasl_done(); } #endif +#ifdef ZTS + ts_free_id(php_memcached_globals_id); +#else + php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); +#endif + UNREGISTER_INI_ENTRIES(); return SUCCESS; } From e0bcc485816ec0bff4f6b8ec873817b41de475f0 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 05:35:39 +0800 Subject: [PATCH 173/694] No m flag in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7960fe7d..1fefcdd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ script: - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n -m ./tests/*.phpt + - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done From 47e43fac5ed5e5607cbf5fb5b521ba18a978dc2a Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 13:03:28 +0800 Subject: [PATCH 174/694] Added test for #77 --- tests/gh_77.phpt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/gh_77.phpt diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt new file mode 100644 index 00000000..49a4a195 --- /dev/null +++ b/tests/gh_77.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test for Github issue #77 +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211, 1); + +$key = uniqid ("this_does_not_exist_"); + +$mc = new \Memcached(); +$mc->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); +$mc->addServer("127.0.0.1", 11211); + +$mc->touch($key, 5); +var_dump ($mc->getResultCode() == Memcached::RES_NOTFOUND); +$mc->set($key, 1, 5); + +$mc->set($key, 1, 5); +var_dump ($mc->getResultCode() == Memcached::RES_SUCCESS); + +echo "OK\n"; + +?> +--EXPECT-- +bool(true) +bool(true) +OK + From 462ed182a8aeb7ae6c7772fdf95b627eaed955c9 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 14:14:49 +0800 Subject: [PATCH 175/694] Fix const correctness issues --- php_memcached.c | 166 +++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 72 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1565c848..f56f266c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -321,7 +321,7 @@ PHP_INI_END() ****************************************/ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); -static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); +static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -524,7 +524,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int key_len = 0; char *server_key = NULL; int server_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; uint64_t cas = 0; @@ -664,7 +664,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke int server_key_len = 0; size_t num_keys = 0; zval **entry = NULL; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; const char **mkeys = NULL; size_t *mkeys_len = NULL; @@ -968,9 +968,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ Returns the next result from a previous delayed request */ PHP_METHOD(Memcached, fetch) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value; uint32_t flags = 0; @@ -1025,9 +1025,9 @@ PHP_METHOD(Memcached, fetch) Returns all the results from a previous delayed request */ PHP_METHOD(Memcached, fetchAll) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value, *entry; uint32_t flags; @@ -2392,7 +2392,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML */ flag = (memcached_behavior) option; convert_to_long(value); - if (flag < 0 || + if ( /* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */ #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 flag >= MEMCACHED_BEHAVIOR_MAX || @@ -2946,21 +2946,72 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t return payload; } +static +char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) +{ + char *buffer; + uint32_t len; + unsigned long length; + zend_bool decompress_status = 0; + + /* Stored with newer memcached extension? */ + if (flags & MEMC_VAL_COMPRESSION_FASTLZ || flags & MEMC_VAL_COMPRESSION_ZLIB) { + /* This is copied from Ilia's patch */ + memcpy(&len, payload, sizeof(uint32_t)); + buffer = emalloc(len + 1); + *payload_len -= sizeof(uint32_t); + payload += sizeof(uint32_t); + length = len; + + if (flags & MEMC_VAL_COMPRESSION_FASTLZ) { + decompress_status = ((length = fastlz_decompress(payload, *payload_len, buffer, len)) > 0); + } else if (flags & MEMC_VAL_COMPRESSION_ZLIB) { + decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, *payload_len) == Z_OK); + } + } + + /* Fall back to 'old style decompression' */ + if (!decompress_status) { + unsigned int factor = 1, maxfactor = 16; + int status; + + do { + length = (unsigned long)*payload_len * (1 << factor++); + buffer = erealloc(buffer, length + 1); + memset(buffer, 0, length + 1); + status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, payload_len); + } while ((status==Z_BUF_ERROR) && (factor < maxfactor)); + + if (status == Z_OK) { + decompress_status = 1; + } + } + + if (!decompress_status) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value"); + efree(buffer); + return NULL; + } + buffer [length] = '\0'; + *payload_len = length; + return buffer; +} + /* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) +static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) { /* A NULL payload is completely valid if length is 0, it is simply empty. */ zend_bool payload_emalloc = 0; - char *buffer = NULL; + char *datas = NULL, *buffer = NULL, *pl = NULL; - if (payload == NULL && payload_len > 0) { + if (payload_in == NULL && payload_len > 0) { ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return -1; - } else if (payload == NULL) { + } else if (payload_in == NULL) { if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) { ZVAL_FALSE(value); } else { @@ -2970,92 +3021,63 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload } if (flags & MEMC_VAL_COMPRESSED) { - uint32_t len; - unsigned long length; - zend_bool decompress_status = 0; - - /* Stored with newer memcached extension? */ - if (flags & MEMC_VAL_COMPRESSION_FASTLZ || flags & MEMC_VAL_COMPRESSION_ZLIB) { - /* This is copied from Ilia's patch */ - memcpy(&len, payload, sizeof(uint32_t)); - buffer = emalloc(len + 1); - payload_len -= sizeof(uint32_t); - payload += sizeof(uint32_t); - length = len; - - if (flags & MEMC_VAL_COMPRESSION_FASTLZ) { - decompress_status = ((length = fastlz_decompress(payload, payload_len, buffer, len)) > 0); - } else if (flags & MEMC_VAL_COMPRESSION_ZLIB) { - decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, payload_len) == Z_OK); - } - } - - /* Fall back to 'old style decompression' */ - if (!decompress_status) { - unsigned int factor = 1, maxfactor = 16; - int status; - - do { - length = (unsigned long)payload_len * (1 << factor++); - buffer = erealloc(buffer, length + 1); - memset(buffer, 0, length + 1); - status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, payload_len); - } while ((status==Z_BUF_ERROR) && (factor < maxfactor)); - - if (status == Z_OK) { - decompress_status = 1; - } - } - - if (!decompress_status) { + char *datas = s_handle_decompressed (payload_in, &payload_len, flags TSRMLS_CC); + if (!datas) { ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value"); - efree(buffer); return -1; } - payload = buffer; - payload_len = length; + pl = datas; payload_emalloc = 1; + } else { + pl = (char *) payload_in; } - payload[payload_len] = 0; - switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: if (payload_emalloc) { - ZVAL_STRINGL(value, payload, payload_len, 0); + ZVAL_STRINGL(value, pl, payload_len, 0); payload_emalloc = 0; } else { - ZVAL_STRINGL(value, payload, payload_len, 1); + ZVAL_STRINGL(value, pl, payload_len, 1); } break; case MEMC_VAL_IS_LONG: { - long lval = strtol(payload, NULL, 10); + char conv_buf [128]; + memcpy (conv_buf, pl, payload_len); + conv_buf [payload_len] = '\0'; + + long lval = strtol(conv_buf, NULL, 10); ZVAL_LONG(value, lval); break; } case MEMC_VAL_IS_DOUBLE: - if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) { + { + char conv_buf [128]; + memcpy (conv_buf, pl, payload_len); + conv_buf [payload_len] = '\0'; + + if (payload_len == 8 && memcmp(conv_buf, "Infinity", 8) == 0) { ZVAL_DOUBLE(value, php_get_inf()); - } else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) { + } else if (payload_len == 9 && memcmp(conv_buf, "-Infinity", 9) == 0) { ZVAL_DOUBLE(value, -php_get_inf()); - } else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) { + } else if (payload_len == 3 && memcmp(conv_buf, "NaN", 3) == 0) { ZVAL_DOUBLE(value, php_get_nan()); } else { - ZVAL_DOUBLE(value, zend_strtod(payload, NULL)); + ZVAL_DOUBLE(value, zend_strtod(conv_buf, NULL)); } + } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1'); + ZVAL_BOOL(value, payload_len > 0 && pl[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: { - const char *payload_tmp = payload; + const char *payload_tmp = pl; php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -3071,7 +3093,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { + if (igbinary_unserialize((uint8_t *)pl, payload_len, &value TSRMLS_CC)) { ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); goto my_error; @@ -3086,9 +3108,9 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API # if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); + php_json_decode(value, pl, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); # elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); + php_json_decode(value, pl, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); # endif #else ZVAL_FALSE(value); @@ -3104,14 +3126,14 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload } if (payload_emalloc) { - efree(payload); + efree(pl); } return 0; my_error: if (payload_emalloc) { - efree(payload); + efree(pl); } return -1; } @@ -3270,9 +3292,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC) { - char *res_key = NULL; + const char *res_key = NULL; size_t res_key_len = 0; - char *payload = NULL; + const char *payload = NULL; size_t payload_len = 0; zval *value, *retval = NULL; uint64_t cas = 0; From aef9135914251e258ed33914b1edfa34d569ee24 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 14:49:49 +0800 Subject: [PATCH 176/694] Fixed UDP server adding with newer libmemcached, closes #54 --- php_memcached.c | 4 ++++ tests/experimental/get_udp.phpt | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f56f266c..63c9c263 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1815,6 +1815,7 @@ PHP_METHOD(Memcached, addServer) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 if (host[0] == '/') { /* unix domain socket */ status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { @@ -1822,6 +1823,9 @@ PHP_METHOD(Memcached, addServer) } else { status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); } +#else + status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); +#endif if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { RETURN_FALSE; diff --git a/tests/experimental/get_udp.phpt b/tests/experimental/get_udp.phpt index d59ada41..3e038e10 100644 --- a/tests/experimental/get_udp.phpt +++ b/tests/experimental/get_udp.phpt @@ -8,8 +8,9 @@ $m = new Memcached(); $m->addServer('127.0.0.1', 11211, 1); $m_udp = new Memcached(); -$m_udp->addServer('127.0.0.1', 11211, 1); $m_udp->setOption(Memcached::OPT_USE_UDP, true); +$m_udp->addServer('127.0.0.1', 11211, 1); + error_reporting(0); @@ -23,18 +24,22 @@ echo $m_udp->getResultMessage(), "\n"; echo "\n"; echo "Set\n"; var_dump($m_udp->set('foo', "asdf", 10)); +sleep (1); + echo $m_udp->getResultMessage(), "\n"; var_dump($m->get('foo')); echo "\n"; echo "Delete found\n"; var_dump($m_udp->delete('foo')); +sleep (1); + echo $m_udp->getResultMessage(), "\n"; $m->get('foo'); echo $m->getResultMessage(), "\n"; ---EXPECTF-- +--EXPECT-- Delete not found bool(true) SUCCESS From f43c440cee2987cb83639a326d05a1c4d2d1ca48 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 14:52:11 +0800 Subject: [PATCH 177/694] Make the warning a bit more php like --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 8c3283bc..28a7134a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1743,7 +1743,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } } else { if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "*_with_initial() only supported with binary protocol"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initial value is only supported with binary protocol"); RETURN_FALSE; } if (by_key) { From a49cc6e6a1f5c3fc6d6c6d9adb8a9e8a7f9c65b3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 16:35:07 +0800 Subject: [PATCH 178/694] The example for code for issue #21 seems to be working as expected. Close #21 --- tests/gh_21.phpt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/gh_21.phpt diff --git a/tests/gh_21.phpt b/tests/gh_21.phpt new file mode 100644 index 00000000..14505d39 --- /dev/null +++ b/tests/gh_21.phpt @@ -0,0 +1,34 @@ +--TEST-- +Test for Github issue 21 +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$m->addServers($newServers); + +$d = $m->get('foo'); + +$m->set('counter', 5); +$n = $m->decrement('counter'); +var_dump($n); + +$n = $m->decrement('counter', 10); +var_dump($n); + +var_dump($m->get('counter')); + +$m->set('counter', 'abc'); +$n = $m->increment('counter'); +var_dump($n); +?> +--EXPECT-- +int(4) +int(0) +int(0) +bool(false) \ No newline at end of file From 068d1180f8c615fca153074a0e8211909bbbca1e Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 16:39:49 +0800 Subject: [PATCH 179/694] Fixed memory leak with SASL credentials --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 28a7134a..c6728266 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2502,6 +2502,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL is only supported with binary protocol"); RETURN_FALSE; } + m_obj->has_sasl_data = 1; RETURN_BOOL(memcached_set_sasl_auth_data(m_obj->memc, user, pass)); } /* }}} */ From 60e6c1c0be3de2ef34091cf0d3ff96bf9ae67c8e Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 17:06:37 +0800 Subject: [PATCH 180/694] Added strerror to error message --- php_memcached.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c6728266..4cf71f45 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2294,6 +2294,7 @@ static PHP_METHOD(Memcached, getOption) static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRMLS_DC) { + memcached_return rc; memcached_behavior flag; struct memc_obj *m_obj = i_obj->obj; @@ -2346,8 +2347,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML flag = (memcached_behavior) option; convert_to_long(value); - if (memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option"); + if ((rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value))) != MEMCACHED_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } @@ -2401,18 +2402,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML */ flag = (memcached_behavior) option; convert_to_long(value); - if ( -/* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 - flag >= MEMCACHED_BEHAVIOR_MAX || -#endif - memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option"); + if (flag >= MEMCACHED_BEHAVIOR_MAX || (rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value))) != MEMCACHED_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } break; } - return 1; } From 15cf784d4c819ee62841fd2712cdce21473c0700 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 18:43:30 +0800 Subject: [PATCH 181/694] Fixed memleak with session sasl credentials. Fixed pointer deref --- php_memcached.c | 5 ++++- php_memcached.h | 3 +++ php_memcached_session.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 4cf71f45..d7bb6cd3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2984,7 +2984,7 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t length = (unsigned long)*payload_len * (1 << factor++); buffer = erealloc(buffer, length + 1); memset(buffer, 0, length + 1); - status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, payload_len); + status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, *payload_len); } while ((status==Z_BUF_ERROR) && (factor < maxfactor)); if (status == Z_OK) { @@ -3160,6 +3160,9 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(sess_connect_timeout) = 1000; MEMC_G(sess_sasl_username) = NULL; MEMC_G(sess_sasl_password) = NULL; +#if HAVE_MEMCACHED_SASL + MEMC_G(sess_sasl_data) = 0; +#endif #endif MEMC_G(serializer_name) = NULL; MEMC_G(serializer) = SERIALIZER_DEFAULT; diff --git a/php_memcached.h b/php_memcached.h index 7a4a1d42..eb81a67b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -76,6 +76,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *sess_sasl_username; char *sess_sasl_password; +#if HAVE_MEMCACHED_SASL + zend_bool sess_sasl_data; +#endif #endif char *serializer_name; enum memcached_serializer serializer; diff --git a/php_memcached_session.c b/php_memcached_session.c index 2dda209c..ab583ad0 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -233,6 +233,7 @@ PS_OPEN_FUNC(memcached) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session sasl credentials"); return FAILURE; } + MEMC_G(sess_sasl_data) = 1; } } @@ -281,6 +282,9 @@ PS_CLOSE_FUNC(memcached) } if (memc_sess->memc_sess) { if (!memc_sess->is_persisent) { + if (MEMC_G(sess_sasl_data)) { + memcached_destroy_sasl_auth_data(memc_sess->memc_sess); + } memcached_free(memc_sess->memc_sess); efree(memc_sess); } From 663ad4976860480454c97f24e3d4f7de1b373c74 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:10:50 +0800 Subject: [PATCH 182/694] Fix test output --- tests/setoptions.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/setoptions.phpt b/tests/setoptions.phpt index 96ed4492..8b5c04db 100644 --- a/tests/setoptions.phpt +++ b/tests/setoptions.phpt @@ -43,4 +43,4 @@ test invalid options bool(false) %s::setOptions(): invalid configuration option bool(false) -%s::setOptions(): error setting memcached option +%s::setOptions(): error setting memcached option: %s From e9bf97d28666f335ed220e30737c1ef1d83f272c Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:17:23 +0800 Subject: [PATCH 183/694] Fix typo and the build --- php_memcached.h | 2 +- php_memcached_session.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/php_memcached.h b/php_memcached.h index eb81a67b..70e12d60 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -113,7 +113,7 @@ PHP_MINFO_FUNCTION(memcached); typedef struct { memcached_st *memc_sess; - zend_bool is_persisent; + zend_bool is_persistent; } memcached_sess; int php_memc_sess_list_entry(void); diff --git a/php_memcached_session.c b/php_memcached_session.c index ab583ad0..e9a36c27 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -138,11 +138,11 @@ PS_OPEN_FUNC(memcached) } p = e + 1; memc_sess = pecalloc(sizeof(*memc_sess), 1, 1); - memc_sess->is_persisent = 1; + memc_sess->is_persistent = 1; } else { p = (char *)save_path; memc_sess = ecalloc(sizeof(*memc_sess), 1); - memc_sess->is_persisent = 0; + memc_sess->is_persistent = 0; } if (!strstr(p, "--SERVER")) { @@ -281,10 +281,12 @@ PS_CLOSE_FUNC(memcached) php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); } if (memc_sess->memc_sess) { - if (!memc_sess->is_persisent) { + if (!memc_sess->is_persistent) { +#ifdef HAVE_MEMCACHED_SASL if (MEMC_G(sess_sasl_data)) { memcached_destroy_sasl_auth_data(memc_sess->memc_sess); } +#endif memcached_free(memc_sess->memc_sess); efree(memc_sess); } From c47812fad5817e6d2e23a28673e45e6141f95214 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:18:46 +0800 Subject: [PATCH 184/694] Fix indentation on the build instructions --- README.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index 479613fd..e32541d4 100644 --- a/README.markdown +++ b/README.markdown @@ -16,10 +16,11 @@ by alleviating database load. Building -------- -$ phpize -$ ./configure -$ make -$ make test + + $ phpize + $ ./configure + $ make + $ make test Resources --------- From 919a25d9aebb2c6dc1c5adf7be3e1b41530c30c8 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:20:06 +0800 Subject: [PATCH 185/694] Some formatting on markdown --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index e32541d4..f4c4ea0f 100644 --- a/README.markdown +++ b/README.markdown @@ -1,3 +1,5 @@ +Build Status +------------ [![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=master)](https://travis-ci.org/php-memcached-dev/php-memcached) 2013 Holidays From 74deabede73f5a3d65321e83c2248ab5076d882e Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:22:31 +0800 Subject: [PATCH 186/694] Update resources links --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index f4c4ea0f..18bd50f6 100644 --- a/README.markdown +++ b/README.markdown @@ -26,6 +26,6 @@ Building Resources --------- - * [libmemcached](http://tangent.org/552/libmemcached.html) + * [libmemcached](http://libmemcached.org/libMemcached.html) * [memcached](http://www.danga.com/memcached/) * [igbinary](https://github.com/phadej/igbinary/) From edeefa49c299da153b7597f42074e756be353483 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:23:57 +0800 Subject: [PATCH 187/694] Andrei doesn't have any wish lists at the moment. --- README.markdown | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.markdown b/README.markdown index 18bd50f6..e827e6fa 100644 --- a/README.markdown +++ b/README.markdown @@ -2,11 +2,6 @@ Build Status ------------ [![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=master)](https://travis-ci.org/php-memcached-dev/php-memcached) -2013 Holidays -------------- -Committers' wishlists, if you feel like kicking in towards a gift: - * [Andrei's](http://given.to/profile/andreiz/wishlist/1411) - Description ----------- This extension uses libmemcached library to provide API for communicating with @@ -27,5 +22,5 @@ Building Resources --------- * [libmemcached](http://libmemcached.org/libMemcached.html) - * [memcached](http://www.danga.com/memcached/) + * [memcached](http://memcached.org/) * [igbinary](https://github.com/phadej/igbinary/) From 0ca5a6e93f55f5caf485952ef6dbfa11e6ddecc4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 18 Oct 2013 19:28:54 +0800 Subject: [PATCH 188/694] Fixed #29 --- package.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 11a6518f..22ebddc9 100644 --- a/package.xml +++ b/package.xml @@ -65,7 +65,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> memcached - + + + stablestable From 47f6ff1060be140e65fcd7f714560bade0fffb7d Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 00:35:46 +0800 Subject: [PATCH 189/694] Added support for libmemcached 0.44 and up. Testing for now --- .travis.yml | 2 + config.m4 | 78 ++++++++++++++++++++++++++++++++++++--- php_libmemcached_compat.c | 50 +++++++++++++++++++++++++ php_libmemcached_compat.h | 28 +++++++++++++- php_memcached.c | 15 +++++--- php_memcached_session.c | 11 ++++-- tests/flush_buffers.phpt | 31 ++++++++++++++++ tests/gh_77.phpt | 5 ++- tests/pr_75.phpt | 5 ++- 9 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 php_libmemcached_compat.c create mode 100644 tests/flush_buffers.phpt diff --git a/.travis.yml b/.travis.yml index 1fefcdd6..6844e83c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ env: - LIBMEMCACHED_VERSION=1.0.16 - LIBMEMCACHED_VERSION=1.0.8 - LIBMEMCACHED_VERSION=1.0.2 + - LIBMEMCACHED_VERSION=0.53 + - LIBMEMCACHED_VERSION=0.44 before_script: - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" diff --git a/config.m4 b/config.m4 index 7f8e599b..442786b0 100644 --- a/config.m4 +++ b/config.m4 @@ -224,8 +224,8 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_CHECKING([for libmemcached location]) if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then - if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached-1.0/memcached.h"; then - AC_MSG_ERROR([Can't find libmemcached 1.0.x headers under "$PHP_LIBMEMCACHED_DIR"]) + if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached/memcached.h"; then + AC_MSG_ERROR([Can't find libmemcached headers under "$PHP_LIBMEMCACHED_DIR"]) fi else PHP_LIBMEMCACHED_DIR="no" @@ -238,7 +238,7 @@ if test "$PHP_MEMCACHED" != "no"; then fi if test "$PHP_LIBMEMCACHED_DIR" = "no"; then - AC_MSG_ERROR([memcached support requires libmemcached 1.0.x. Use --with-libmemcached-dir= to specify the prefix where libmemcached headers and library are located]) + AC_MSG_ERROR([memcached support requires libmemcached. Use --with-libmemcached-dir= to specify the prefix where libmemcached headers and library are located]) else AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR]) @@ -247,7 +247,10 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) ORIG_CFLAGS="$CFLAGS" - CFLAGS="-I$PHP_LIBMEMCACHED_INCDIR" + ORIG_LIBS="$LIBS" + + CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" + LIBS="$LIBS -lmemcached -L$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR" AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ AC_TRY_COMPILE( @@ -258,16 +261,81 @@ if test "$PHP_MEMCACHED" != "no"; then ) ]) + AC_CACHE_CHECK([whether MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS is defined], ac_cv_have_libmemcached_remove_failed_servers, [ + AC_TRY_COMPILE( + [ #include ], + [ MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS; ], + [ ac_cv_have_libmemcached_remove_failed_servers="yes" ], + [ ac_cv_have_libmemcached_remove_failed_servers="no" ] + ) + ]) + + AC_CACHE_CHECK([whether MEMCACHED_SERVER_TEMPORARILY_DISABLED is defined], ac_cv_have_libmemcached_server_temporarily_disabled, [ + AC_TRY_COMPILE( + [ #include ], + [ MEMCACHED_SERVER_TEMPORARILY_DISABLED; ], + [ ac_cv_have_libmemcached_server_temporarily_disabled="yes" ], + [ ac_cv_have_libmemcached_server_temporarily_disabled="no" ] + ) + ]) + + AC_CACHE_CHECK([whether memcached function exists], ac_cv_have_libmemcached_memcached, [ + AC_TRY_LINK( + [ #include ], + [ memcached("t", sizeof ("t")); ], + [ ac_cv_have_libmemcached_memcached="yes" ], + [ ac_cv_have_libmemcached_memcached="no" ] + ) + ]) + + AC_CACHE_CHECK([whether libmemcached_check_configuration function exists], ac_cv_have_libmemcached_check_configuration, [ + AC_TRY_LINK( + [ #include ], + [ libmemcached_check_configuration("", 1, "", 1); ], + [ ac_cv_have_libmemcached_check_configuration="yes" ], + [ ac_cv_have_libmemcached_check_configuration="no" ] + ) + ]) + + AC_CACHE_CHECK([whether memcached_touch function exists], ac_cv_have_libmemcached_touch, [ + AC_TRY_LINK( + [ #include ], + [ memcached_touch (NULL, NULL, 0, 0); ], + [ ac_cv_have_libmemcached_touch="yes" ], + [ ac_cv_have_libmemcached_touch="no" ] + ) + ]) + CFLAGS="$ORIG_CFLAGS" + LIBS="$ORIG_LIBS" if test "$ac_cv_have_memcached_instance_st" = "yes"; then AC_DEFINE(HAVE_MEMCACHED_INSTANCE_ST, [1], [Whether memcached_instance_st is defined]) fi + if test "$ac_cv_have_libmemcached_remove_failed_servers" = "yes"; then + AC_DEFINE(HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS, [1], [Whether MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS is defined]) + fi + + if test "$ac_cv_have_libmemcached_server_temporarily_disabled" = "yes"; then + AC_DEFINE(HAVE_LIBMEMCACHED_SERVER_TEMPORARILY_MARKER_DISABLED, [1], [Whether MEMCACHED_SERVER_TEMPORARILY_DISABLED is defined]) + fi + + if test "$ac_cv_have_libmemcached_memcached" = "yes"; then + AC_DEFINE(HAVE_LIBMEMCACHED_MEMCACHED, [1], [Whether memcached is defined]) + fi + + if test "$ac_cv_have_libmemcached_check_configuration" = "yes"; then + AC_DEFINE(HAVE_LIBMEMCACHED_CHECK_CONFIGURATION, [1], [Whether libmemcached_check_configuration is defined]) + fi + + if test "$ac_cv_have_libmemcached_touch" = "yes"; then + AC_DEFINE(HAVE_LIBMEMCACHED_TOUCH, [1], [Whether memcached_touch is defined]) + fi PHP_SUBST(MEMCACHED_SHARED_LIBADD) - PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c new file mode 100644 index 00000000..6ab853e6 --- /dev/null +++ b/php_libmemcached_compat.c @@ -0,0 +1,50 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#include "php_libmemcached_compat.h" + +memcached_st *php_memc_create_str (const char *str, size_t str_len) +{ +#if HAVE_LIBMEMCACHED_MEMCACHED + return memcached (str, str_len); +#else + memcached_return rc; + memcached_st *memc; + memcached_server_st *servers; + + memc = memcached_create(NULL); + + if (!memc) { + return NULL; + } + + servers = memcached_servers_parse (str); + + if (!servers) { + memcached_free (memc); + return NULL; + } + + rc = memcached_server_push (memc, servers); + memcached_server_free (servers); + + if (rc != MEMCACHED_SUCCESS) { + memcached_free (memc); + return NULL; + } + return memc; +#endif +} \ No newline at end of file diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 6e5f58b1..19b0ac05 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -1,7 +1,33 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + #ifndef PHP_LIBMEMCACHED_COMPAT #define PHP_LIBMEMCACHED_COMPAT /* this is the version(s) we support */ -#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +memcached_st *php_memc_create_str (const char *str, size_t str_len); + +#ifndef HAVE_LIBMEMCACHED_SERVER_TEMPORARILY_MARKER_DISABLED +# define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) +#endif #endif diff --git a/php_memcached.c b/php_memcached.c index d7bb6cd3..fa8e9095 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -432,17 +432,21 @@ static PHP_METHOD(Memcached, __construct) } if (conn_str) { - m_obj->memc = memcached(conn_str, conn_str_len); + m_obj->memc = php_memc_create_str(conn_str, conn_str_len); if (!m_obj->memc) { char error_buffer[1024]; if (plist_key) { efree(plist_key); } +#if HAVE_LIBMEMCACHED_CHECK_CONFIGURATION if (libmemcached_check_configuration(conn_str, conn_str_len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "configuration error %s", error_buffer); } else { php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); } +#else + php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); +#endif /* not reached */ } } else { @@ -1411,7 +1415,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool key_len, payload, payload_len, expiration, flags); } break; - +#ifdef HAVE_LIBMEMCACHED_TOUCH case MEMC_OP_TOUCH: if (!server_key) { status = memcached_touch(m_obj->memc, key, key_len, expiration); @@ -1420,8 +1424,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool key_len, expiration); } break; - - +#endif case MEMC_OP_ADD: if (!server_key) { status = memcached_add(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); @@ -3665,7 +3668,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 +#if HAVE_LIBMEMCACHED_TOUCH MEMC_ME(touch, arginfo_touch) MEMC_ME(touchByKey, arginfo_touchByKey) #endif @@ -3859,7 +3862,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ); #endif -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 +#if defined(HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS) && HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); #endif diff --git a/php_memcached_session.c b/php_memcached_session.c index e9a36c27..e8711d31 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -186,14 +186,19 @@ PS_OPEN_FUNC(memcached) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); } } else { - memc_sess->memc_sess = memcached(p, strlen(p)); + memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); if (!memc_sess->memc_sess) { +#if HAVE_LIBMEMCACHED_CHECK_CONFIGURATION char error_buffer[1024]; if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); } +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); +#endif + } else { success: PS_SET_MOD_DATA(memc_sess); @@ -253,7 +258,7 @@ PS_OPEN_FUNC(memcached) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached connection timeout"); return FAILURE; } - +#if HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { @@ -261,7 +266,7 @@ PS_OPEN_FUNC(memcached) return FAILURE; } } - +#endif return SUCCESS; } } diff --git a/tests/flush_buffers.phpt b/tests/flush_buffers.phpt new file mode 100644 index 00000000..9bff077b --- /dev/null +++ b/tests/flush_buffers.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test flushing buffers +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211); +$m->setOption(Memcached::OPT_NO_BLOCK, 1); +$m->setOption(Memcached::OPT_BUFFER_WRITES, 1); + +$key = uniqid ('flush_key_'); + +var_dump ($m->set($key, 'test_val')); + +$m2 = new Memcached(); +$m2->addServer('127.0.0.1', 11211); + +var_dump ($m2->get ($key)); +var_dump ($m->flushBuffers ()); +sleep (1); +var_dump ($m2->get ($key)); + +echo "OK" . PHP_EOL; +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +string(8) "test_val" +OK \ No newline at end of file diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 49a4a195..427e040d 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -1,7 +1,10 @@ --TEST-- Test for Github issue #77 --SKIPIF-- - + --FILE-- --FILE-- addServer ('127.0.0.1', 11211); $client->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $client->set('key1', 'value1'); From ab30c5f7e196716f13b41eeb3a07f6668b737ac7 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 13:22:38 +0800 Subject: [PATCH 190/694] Add the version available in gentoo --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6844e83c..4258695f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ php: env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 + - LIBMEMCACHED_VERSION=1.0.14 - LIBMEMCACHED_VERSION=1.0.8 - LIBMEMCACHED_VERSION=1.0.2 - LIBMEMCACHED_VERSION=0.53 From 1711b78f92605625a610eeb25b07c73d08871475 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 13:28:49 +0800 Subject: [PATCH 191/694] Added test for issue #16 --- tests/gh_77.phpt | 3 +-- tests/touch_binary.phpt | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/touch_binary.phpt diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 427e040d..2a1e277e 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -2,8 +2,7 @@ Test for Github issue #77 --SKIPIF-- --FILE-- +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL,true); +$mem->addServer('127.0.0.1', 11211) or die ("Could not connect"); + +$key = uniqid ('touch_t_'); + +var_dump ($mem->get($key)); +$mem->set ($key, 1); +var_dump ($mem->getResultcode()); +var_dump ($mem->get($key)); +$mem->touch ($key); +var_dump ($mem->getResultcode()); +var_dump ($mem->get($key)); +var_dump ($mem->getResultcode()); + +echo "OK\n"; + +?> +--EXPECT-- +bool(false) +int(0) +int(1) +int(0) +int(1) +int(0) +OK From d490471a9df171c99e6b4a36c9f9f22e1a8e5eb4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 16:58:36 +0800 Subject: [PATCH 192/694] Add better test output --- tests/touch_binary.phpt | 57 +++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 763a894b..7735218b 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -6,29 +6,60 @@ Touch in binary mode ?> --FILE-- getConstants (); + + foreach ($c as $name => $value) { + if (strpos ($name, 'RES_') === 0 && $value == $code) + return $name; + } +} + +function status_print ($op, $mem, $expected) +{ + $code = $mem->getResultcode(); + + if ($code == $expected) + echo "${op} status code as expected" . PHP_EOL; + else { + $expected = resolve_to_constant ($code); + $code = resolve_to_constant ($code); + + echo "${op} status code mismatch, expected ${expected} but got ${code}" . PHP_EOL; + } +} + $mem = new Memcached(); $mem->setOption(Memcached::OPT_BINARY_PROTOCOL,true); $mem->addServer('127.0.0.1', 11211) or die ("Could not connect"); $key = uniqid ('touch_t_'); -var_dump ($mem->get($key)); +$mem->get($key); +status_print ('get', $mem, Memcached::RES_NOTFOUND); + $mem->set ($key, 1); -var_dump ($mem->getResultcode()); -var_dump ($mem->get($key)); -$mem->touch ($key); -var_dump ($mem->getResultcode()); -var_dump ($mem->get($key)); -var_dump ($mem->getResultcode()); +status_print ('set', $mem, Memcached::RES_SUCCESS); + +$mem->get($key); +status_print ('get', $mem, Memcached::RES_SUCCESS); + +$mem->touch ($key, 10); +status_print ('touch', $mem, Memcached::RES_SUCCESS); + +$mem->get($key); +status_print ('get', $mem, Memcached::RES_SUCCESS); echo "OK\n"; ?> --EXPECT-- -bool(false) -int(0) -int(1) -int(0) -int(1) -int(0) +get status code as expected +set status code as expected +get status code as expected +touch status code as expected +get status code as expected OK From 54ea1a8aad0300415ba667f39662f82465dcd479 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:06:00 +0800 Subject: [PATCH 193/694] Test error message --- tests/touch_binary.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 7735218b..dbdd8014 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -25,7 +25,7 @@ function status_print ($op, $mem, $expected) if ($code == $expected) echo "${op} status code as expected" . PHP_EOL; else { - $expected = resolve_to_constant ($code); + $expected = resolve_to_constant ($expected); $code = resolve_to_constant ($code); echo "${op} status code mismatch, expected ${expected} but got ${code}" . PHP_EOL; From f1e85b5ae67e723986dd897b31ffc743d932fb77 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:21:32 +0800 Subject: [PATCH 194/694] This version comparison was wrong --- php_memcached.c | 2 +- tests/touch_binary.phpt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index fa8e9095..b6bce463 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1823,7 +1823,7 @@ PHP_METHOD(Memcached, addServer) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 if (host[0] == '/') { /* unix domain socket */ status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index dbdd8014..4e020052 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -53,6 +53,9 @@ status_print ('touch', $mem, Memcached::RES_SUCCESS); $mem->get($key); status_print ('get', $mem, Memcached::RES_SUCCESS); +$mem->get($key); +status_print ('get', $mem, Memcached::RES_SUCCESS); + echo "OK\n"; ?> @@ -62,4 +65,5 @@ set status code as expected get status code as expected touch status code as expected get status code as expected +get status code as expected OK From a63c8f08fdae80a6d9c4050eb3b126c1e5b05fe7 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:25:22 +0800 Subject: [PATCH 195/694] Skip for older libmemcached --- php_memcached.c | 1 + tests/touch_binary.phpt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index b6bce463..f83da937 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3777,6 +3777,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) /* * Class options */ + REGISTER_MEMC_CLASS_CONST_LONG(LIBMEMCACHED_VERSION_HEX, LIBMEMCACHED_VERSION_HEX); REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION); REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 4e020052..b28863bd 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -2,7 +2,7 @@ Touch in binary mode --SKIPIF-- --FILE-- Date: Sat, 19 Oct 2013 17:36:53 +0800 Subject: [PATCH 196/694] Link to the relevant issue, fixed in memcached 1.4.14 --- tests/expire.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/expire.phpt b/tests/expire.phpt index f7562390..d6817233 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached store, fetch & touch expired key --XFAIL-- -libmemcached ignores expiration with binary proto +https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- --FILE-- From 79af37192618b81252d235b985f87f33f5e48669 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:41:01 +0800 Subject: [PATCH 197/694] Added a warning regarding binary proto and touch --- php_memcached.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f83da937..8e1673df 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1392,10 +1392,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } if (op == MEMC_OP_TOUCH) { -#ifdef mikko_0 - if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); - RETURN_FALSE; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000015 + if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.15"); } #endif } else { From a88355b21a112f136313b26a0b2600b728d34b9c Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:43:24 +0800 Subject: [PATCH 198/694] Also test libmemcached 1.0.15 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4258695f..9447b568 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ php: env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 + - LIBMEMCACHED_VERSION=1.0.15 - LIBMEMCACHED_VERSION=1.0.14 - LIBMEMCACHED_VERSION=1.0.8 - LIBMEMCACHED_VERSION=1.0.2 From 8d563c3fec5edd0d1f641f7ce1111d5984799edb Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 19 Oct 2013 17:49:05 +0800 Subject: [PATCH 199/694] Actually needs to be 1.0.16 --- php_memcached.c | 4 ++-- tests/touch_binary.phpt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 8e1673df..ada893f5 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1392,9 +1392,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } if (op == MEMC_OP_TOUCH) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000015 +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.15"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif } else { diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index b28863bd..9bbe4a84 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -2,7 +2,7 @@ Touch in binary mode --SKIPIF-- --FILE-- Date: Sat, 19 Oct 2013 17:54:40 +0800 Subject: [PATCH 200/694] Skip gh_77 test for older libmemcached --- tests/gh_77.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 2a1e277e..9aedf296 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -2,7 +2,7 @@ Test for Github issue #77 --SKIPIF-- --FILE-- Date: Mon, 21 Oct 2013 15:54:44 +0800 Subject: [PATCH 201/694] Fixed AC_TRY_COMPILE tests on CentOS --- config.m4 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 442786b0..9382bbd0 100644 --- a/config.m4 +++ b/config.m4 @@ -250,7 +250,11 @@ if test "$PHP_MEMCACHED" != "no"; then ORIG_LIBS="$LIBS" CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" - LIBS="$LIBS -lmemcached -L$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR" + + # + # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once + # + LIBS="$LIBS -lpthread -lmemcached -L$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR" AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ AC_TRY_COMPILE( From b0cdcb34448a6ca3787649fbbe6f5b38573096e6 Mon Sep 17 00:00:00 2001 From: Eric Merrill Date: Tue, 22 Oct 2013 18:30:45 -0400 Subject: [PATCH 202/694] More granular session locking support Adding memcached.sess_lock_max_wait, which sets how long a incoming lock request will wait for the lock before dying. And memcached.sess_lock_expire, which sets how long until the lock expires, independent of the current max_execution_time. --- memcached.ini | 12 ++++++++++++ php_memcached.c | 4 ++++ php_memcached.h | 2 ++ php_memcached_session.c | 15 ++++++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/memcached.ini b/memcached.ini index 0f1a82b0..dd405a05 100644 --- a/memcached.ini +++ b/memcached.ini @@ -12,6 +12,18 @@ memcached.sess_locking = On ; the default is 150000 memcached.sess_lock_wait = 150000 +; The maximum time, in seconds, to wait for a session lock +; before timing out. +; Setting to 0 results in default behavior, which is to +; use max_execution_time. +memcached.sess_lock_max_wait = 0; + +; The time, in seconds, before a lock should release itself. +; Setting to 0 results in the default behaviour, which is to +; use the memcached.sess_lock_max_wait setting. If that is +; also 0, max_execution_time will be used. +memcached.sess_lock_expire = 0; + ; memcached session key prefix ; valid values are strings less than 219 bytes long ; the default value is "memc.sess.key." diff --git a/php_memcached.c b/php_memcached.c index ada893f5..b9d60319 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -295,6 +295,8 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_consistent_hash", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hash_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_lock_max_wait", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_max_wait, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_lock_expire", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_expire, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals) @@ -3155,6 +3157,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob MEMC_G(sess_remove_failed_enabled) = 0; MEMC_G(sess_prefix) = NULL; MEMC_G(sess_lock_wait) = 0; + MEMC_G(sess_lock_max_wait) = 0; + MEMC_G(sess_lock_expire) = 0; MEMC_G(sess_locked) = 0; MEMC_G(sess_lock_key) = NULL; MEMC_G(sess_lock_key_len) = 0; diff --git a/php_memcached.h b/php_memcached.h index 70e12d60..9eeb8a0e 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -62,6 +62,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #ifdef HAVE_MEMCACHED_SESSION zend_bool sess_locking_enabled; long sess_lock_wait; + long sess_lock_max_wait; + long sess_lock_expire; char* sess_prefix; zend_bool sess_locked; char* sess_lock_key; diff --git a/php_memcached_session.c b/php_memcached_session.c index e8711d31..91d431f4 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -49,20 +49,25 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) int lock_key_len = 0; unsigned long attempts; long write_retry_attempts = 0; - long lock_maxwait; + long lock_maxwait = MEMC_G(sess_lock_max_wait); long lock_wait = MEMC_G(sess_lock_wait); + long lock_expire = MEMC_G(sess_lock_expire); time_t expiration; memcached_return status; /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ - - lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); if (lock_maxwait <= 0) { - lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; + lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + if (lock_maxwait <= 0) { + lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; + } } if (lock_wait == 0) { lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; } - expiration = time(NULL) + lock_maxwait + 1; + if (lock_expire <= 0) { + lock_expire = lock_maxwait; + } + expiration = time(NULL) + lock_expire + 1; attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ From 98fed8d48685c16039724a2ef5aa6474091aa302 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 27 Oct 2013 15:13:13 +0800 Subject: [PATCH 203/694] Added test for #90 --- tests/gh_90.phpt | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tests/gh_90.phpt diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt new file mode 100644 index 00000000..4eb9bedb --- /dev/null +++ b/tests/gh_90.phpt @@ -0,0 +1,93 @@ +--TEST-- +Test for GH #90 +--SKIPIF-- + +--FILE-- +setOptions(array(memcached::OPT_BINARY_PROTOCOL => true)); + $memcached->addServers(array(array('127.0.0.1', 11211, 100))); +} + +// Create a key for use as a lock. If this key already exists, wait till it doesn't exist. +{ + $key = 'LockKey'; + $lockToken = mt_rand(0, pow(2, 32)); //Random value betwen 0 and 2^32 for ownership verification + + while (true) + { + $casToken = null; + $data = $memcached->get($key, $casToken); + if ($memcached->getResultCode() == Memcached::RES_NOTFOUND) + { + if ($memcached->add($key, $lockToken, 5)) + { + break; + } + } + elseif ($data === false) + { + if ($memcached->cas($casToken, $key, $lockToken, 5)) + { + break; + } + } + + //Sleep 10 milliseconds + usleep(10 * 1000); + } +} + +//Do something here that requires exclusive access to this key + +//Effectively delete our key lock. +{ + $casToken = null; + if ($lockToken == $memcached->get($key, $casToken)) + { + $memcached->cas($casToken, $key, false, 1); + } +} + +//Create 10 keys and then increment them. The first value returned will be wrong. +{ + $keyList = array(); + for ($i = 0; $i < 10; $i++) + { + $keyList[] = $i . '_' . uniqid ('count_value_'); + } + + $valueList = array(); + foreach ($keyList as $key) + { + $valueList[$key] = $memcached->increment($key, 1, 1); + } + + var_dump ($valueList); +} + +--EXPECTF-- +array(10) { + ["0_%s"]=> + int(1) + ["1_%s"]=> + int(1) + ["2_%s"]=> + int(1) + ["3_%s"]=> + int(1) + ["4_%s"]=> + int(1) + ["5_%s"]=> + int(1) + ["6_%s"]=> + int(1) + ["7_%s"]=> + int(1) + ["8_%s"]=> + int(1) + ["9_%s"]=> + int(1) +} \ No newline at end of file From 5ba1ec3f805d760d3b480a91a0996fc5dc4442bb Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 27 Oct 2013 20:36:50 +0800 Subject: [PATCH 204/694] Added myself to package.xml, probably Ilia as well? --- package.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.xml b/package.xml index 22ebddc9..45bcc9d2 100644 --- a/package.xml +++ b/package.xml @@ -15,6 +15,12 @@ http://pear.php.net/dtd/package-2.0.xsd"> andrei@php.net yes + + Mikko Koppanen + mkoppanen + mkoppanen@php.net + yes + 2012-08-06 2.1.0 From 240b31620b6d7f90dbe5d165b4ffb94515ec26b5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 28 Oct 2013 18:31:28 +0800 Subject: [PATCH 205/694] Start updating changelogs etc for release --- ChangeLog | 10 ++++++++++ package.xml | 32 +++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3502e197..8bcf6ec8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ memcached extension changelog +Version 2.2.0b1 +--------------- + * Reinstate support for libememcached 0.x series + * Added SASL support to session handler + * Added Memcached::flushBuffers as per GH #78 + * Fixes GH #54: Fixed UDP server adding with newer libmemcached + * Fixed PHP bug #65334: (Segfault if uncompress value failed) + * Fixes GH #14: get with cas token fails to fetch all results + * Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 + Version 2.1.0 ------------- * Drop support for libmemcached 0.x series, now 1.0.x is required diff --git a/package.xml b/package.xml index 45bcc9d2..440c24cf 100644 --- a/package.xml +++ b/package.xml @@ -21,20 +21,24 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2012-08-06 + 2013-10-28 - 2.1.0 - 2.1.0 + 2.2.0b1 + 2.2.0 - stable + beta stable PHP -- Drop support for libmemcached 0.x series, now 1.0.x is required -- Add support for virtual bucket distribution -- Fix compilation against PHP 5.2 +- Reinstate support for libememcached 0.x series +- Added SASL support to session handler +- Added Memcached::flushBuffers as per GH #78 +- Fixes GH #54: Fixed UDP server adding with newer libmemcached +- Fixed PHP bug #65334: (Segfault if uncompress value failed) +- Fixes GH #14: get with cas token fails to fetch all results +- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 @@ -75,6 +79,20 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + betastable + 2.2.0b12.2.0 + 2013-10-28 + +- Reinstate support for libememcached 0.x series +- Added SASL support to session handler +- Added Memcached::flushBuffers as per GH #78 +- Fixes GH #54: Fixed UDP server adding with newer libmemcached +- Fixed PHP bug #65334: (Segfault if uncompress value failed) +- Fixes GH #14: get with cas token fails to fetch all results +- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 + + stablestable 2.1.02.1.0 From b9727dfecde9e70560e630eb60e9c021c6fb0d7f Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 28 Oct 2013 18:35:09 +0800 Subject: [PATCH 206/694] Package tests --- package.xml | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 440c24cf..07638fbc 100644 --- a/package.xml +++ b/package.xml @@ -60,7 +60,55 @@ http://pear.php.net/dtd/package-2.0.xsd"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From bddadc5cb5f5b24583f670a16a8f4a16d37ef489 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 29 Oct 2013 02:23:16 +0800 Subject: [PATCH 207/694] Added a note about PR #91 --- ChangeLog | 1 + package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8bcf6ec8..e3b4ed39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ Version 2.2.0b1 * Fixed PHP bug #65334: (Segfault if uncompress value failed) * Fixes GH #14: get with cas token fails to fetch all results * Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 + * Merged PR #91: memcached.sess_lock_wait and memcached.sess_lock_max_wait Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index 07638fbc..7b3926b8 100644 --- a/package.xml +++ b/package.xml @@ -39,6 +39,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Fixed PHP bug #65334: (Segfault if uncompress value failed) - Fixes GH #14: get with cas token fails to fetch all results - Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 +- Merged PR #91: More granular session locking support From 0381e55a537bf4ba435af847651d11cb136da960 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 29 Oct 2013 17:09:38 +0800 Subject: [PATCH 208/694] Update changelogs further --- ChangeLog | 5 +++++ package.xml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index e3b4ed39..7ad01cfb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,11 @@ Version 2.2.0b1 * Fixes GH #14: get with cas token fails to fetch all results * Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 * Merged PR #91: memcached.sess_lock_wait and memcached.sess_lock_max_wait + * Added Session handler settings: + - memcached.sess_number_of_replicas + - memcached.sess_randomize_replica_read + - memcached.sess_remove_failed + - memcached.sess_connect_timeout Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index 7b3926b8..2fa2e2fe 100644 --- a/package.xml +++ b/package.xml @@ -40,6 +40,11 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Fixes GH #14: get with cas token fails to fetch all results - Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - Merged PR #91: More granular session locking support +- Added Session handler settings: + * memcached.sess_number_of_replicas + * memcached.sess_randomize_replica_read + * memcached.sess_remove_failed + * memcached.sess_connect_timeout From 4537039fe296f37c11512e327d0bc35950879bbe Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 29 Oct 2013 18:20:06 +0800 Subject: [PATCH 209/694] Accidentally capitalised S --- ChangeLog | 2 +- package.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ad01cfb..e7d39cee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,7 +10,7 @@ Version 2.2.0b1 * Fixes GH #14: get with cas token fails to fetch all results * Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 * Merged PR #91: memcached.sess_lock_wait and memcached.sess_lock_max_wait - * Added Session handler settings: + * Added session handler settings: - memcached.sess_number_of_replicas - memcached.sess_randomize_replica_read - memcached.sess_remove_failed diff --git a/package.xml b/package.xml index 2fa2e2fe..7a436b23 100644 --- a/package.xml +++ b/package.xml @@ -40,7 +40,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Fixes GH #14: get with cas token fails to fetch all results - Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - Merged PR #91: More granular session locking support -- Added Session handler settings: +- Added session handler settings: * memcached.sess_number_of_replicas * memcached.sess_randomize_replica_read * memcached.sess_remove_failed From 571f0458b21cb140b8310f39ec999cb778eb0472 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 4 Nov 2013 11:48:07 +0800 Subject: [PATCH 210/694] Test packaging and building from package --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9447b568..481a533d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,11 @@ before_script: script: + - export PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') + - pear package + - mkdir /tmp/php-memcached-build + - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build + - cd /tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION} - phpize - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" - make From 1ff165501232bad3ba247e05eac8e42c7539eac2 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 4 Nov 2013 11:53:03 +0800 Subject: [PATCH 211/694] Missing this php_libmemcached_compat.c from package.xml --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 7a436b23..9b2ce46d 100644 --- a/package.xml +++ b/package.xml @@ -62,6 +62,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + From 3f71933f26fbf0ed1fe068626027eddb6397ae3e Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 4 Nov 2013 12:02:03 +0800 Subject: [PATCH 212/694] More package.xml additions --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 9b2ce46d..7ddf9e15 100644 --- a/package.xml +++ b/package.xml @@ -114,6 +114,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + From 9e45d769948edea68e05ccda4ac05e50fb688ca9 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 4 Nov 2013 12:15:15 +0800 Subject: [PATCH 213/694] Make sure that tests are packaged --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 481a533d..ccc13e36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ env: - LIBMEMCACHED_VERSION=0.44 before_script: + - for file in tests/*.phpt; do grep $(basename $file) package.xml >/dev/null || (echo "Missing $file from package.xml" ; exit 1); done - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - cd libmemcached-${LIBMEMCACHED_VERSION} From 767b3cd0c2a4bbbf4d2bbcdc1c3d7f57cf6f305f Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 6 Nov 2013 12:25:03 +0800 Subject: [PATCH 214/694] Added test for issue #25 --- package.xml | 1 + tests/version.phpt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/version.phpt diff --git a/package.xml b/package.xml index 7ddf9e15..3ae6f7af 100644 --- a/package.xml +++ b/package.xml @@ -69,6 +69,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/version.phpt b/tests/version.phpt new file mode 100644 index 00000000..8b980925 --- /dev/null +++ b/tests/version.phpt @@ -0,0 +1,18 @@ +--TEST-- +Get version +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211); +var_dump ($m->getVersion ()); + +echo "OK" . PHP_EOL; +?> +--EXPECTF-- +array(1) { + ["127.0.0.1:11211"]=> + string(6) "%d.%d.%d" +} +OK \ No newline at end of file From 8a22b47087f64f1ed05d7734a3f680479ce11afe Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 6 Nov 2013 12:39:23 +0800 Subject: [PATCH 215/694] Add new version --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ccc13e36..0e814b38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ env: - LIBMEMCACHED_VERSION=1.0.16 - LIBMEMCACHED_VERSION=1.0.15 - LIBMEMCACHED_VERSION=1.0.14 + - LIBMEMCACHED_VERSION=1.0.10 - LIBMEMCACHED_VERSION=1.0.8 - LIBMEMCACHED_VERSION=1.0.2 - LIBMEMCACHED_VERSION=0.53 From 957255fbef708e05471745a5418703e8084d7b6d Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 6 Nov 2013 12:45:07 +0800 Subject: [PATCH 216/694] Added more notes --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 3ae6f7af..2a3dcd36 100644 --- a/package.xml +++ b/package.xml @@ -38,6 +38,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Fixes GH #54: Fixed UDP server adding with newer libmemcached - Fixed PHP bug #65334: (Segfault if uncompress value failed) - Fixes GH #14: get with cas token fails to fetch all results +- Fixes GH #68: memcached 2.1.0 requires libmemcached 1.0.10 - Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - Merged PR #91: More granular session locking support - Added session handler settings: From 3c6e305b2ab890e309d3dfe580da3c37ddfce317 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 6 Nov 2013 12:45:27 +0800 Subject: [PATCH 217/694] Added more notes --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index e7d39cee..bc0d2063 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ Version 2.2.0b1 * Fixes GH #54: Fixed UDP server adding with newer libmemcached * Fixed PHP bug #65334: (Segfault if uncompress value failed) * Fixes GH #14: get with cas token fails to fetch all results + * Fixes GH #68: memcached 2.1.0 requires libmemcached 1.0.10 * Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 * Merged PR #91: memcached.sess_lock_wait and memcached.sess_lock_max_wait * Added session handler settings: From 2cc0e324fd76fd9034d7f6bdb57654920d91fa0c Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:24:58 +0100 Subject: [PATCH 218/694] Initial commit that introduces UDF (user defined flags). Memcached.txt specifies that flags are a 16-bit integer. Since the library uses internally 8 bits to store type, compression and serialization, this leaves us 8 bytes left to store user data. So basically added the udf_flags parameter to all relevant functions to store and retrieve them. --- php_memcached.c | 160 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 128 insertions(+), 32 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 642cb162..925b9b4b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -129,6 +129,13 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_COMPRESSION_ZLIB (1<<5) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<6) +/**************************************** + User-defined flags +****************************************/ +#define MEMC_UDF_MASK 0xf0 +#define MEMC_UDF_GET(flags) ((long)(((flags) & MEMC_UDF_MASK)>>8)) +#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) + /**************************************** "get" operation flags ****************************************/ @@ -491,7 +498,7 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) +/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) Returns a value for the given key or false */ PHP_METHOD(Memcached, get) { @@ -499,7 +506,7 @@ PHP_METHOD(Memcached, get) } /* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) Returns a value for key from the server identified by the server key or false */ PHP_METHOD(Memcached, getByKey) { @@ -521,6 +528,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) const char* keys[1] = { NULL }; size_t key_lens[1] = { 0 }; zval *cas_token = NULL; + zval *udf_flags = NULL; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; @@ -528,13 +536,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|f!z", &server_key, - &server_key_len, &key, &key_len, &fci, &fcc, &cas_token) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|f!zz", &server_key, + &server_key_len, &key, &key_len, &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!z", &key, &key_len, - &fci, &fcc, &cas_token) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!zz", &key, &key_len, + &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } } @@ -616,6 +624,10 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); + if (udf_flags) ( + ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + } + memcached_result_free(&result); } else { @@ -663,11 +675,14 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } } + if (udf_flags) ( + ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + } } } /* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) +/* {{{ Memcached::getMulti(array keys [, array &cas_tokens [, array &udf_flags ] ]) Returns values for the given keys or false */ PHP_METHOD(Memcached, getMulti) { @@ -675,7 +690,7 @@ PHP_METHOD(Memcached, getMulti) } /* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) +/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens [, array &udf_flags ] ]) Returns values for the given keys from the server identified by the server key or false */ PHP_METHOD(Memcached, getMultiByKey) { @@ -700,6 +715,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint32_t flags; uint64_t cas = 0; zval *cas_tokens = NULL; + zval *udf_flags = NULL; uint64_t orig_cas_flag; zval *value; long get_flags = 0; @@ -710,12 +726,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zl", &server_key, - &server_key_len, &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zlz", &server_key, + &server_key_len, &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } @@ -792,6 +808,15 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke array_init(cas_tokens); } + /* + * Iterate through the result set and create the result array. The flags are + * returned as longs. + */ + if (udf_flags) { + zval_dtor(udf_flags); + array_init(udf_flags); + } + memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { if (status != MEMCACHED_SUCCESS) { @@ -834,6 +859,9 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); } + if (udf_flags) { + add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_UDF_GET(flags)); + } } memcached_result_free(&result); @@ -844,6 +872,10 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval_dtor(cas_tokens); ZVAL_NULL(cas_tokens); } + if (udf_flags) { + zval_dtor(udf_flags); + ZVAL_NULL(udf_flags); + } zval_dtor(return_value); RETURN_FALSE; } @@ -1040,6 +1072,9 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } memcached_result_free(&result); } @@ -1096,6 +1131,9 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } add_next_index_zval(return_value, entry); } @@ -1108,7 +1146,7 @@ PHP_METHOD(Memcached, fetchAll) } /* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration ]) +/* {{{ Memcached::set(string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key */ PHP_METHOD(Memcached, set) { @@ -1116,7 +1154,7 @@ PHP_METHOD(Memcached, set) } /* }}} */ -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key on the server identified by the server key */ PHP_METHOD(Memcached, setByKey) { @@ -1143,7 +1181,7 @@ PHP_METHOD(Memcached, touchByKey) #endif -/* {{{ Memcached::setMulti(array items [, int expiration ]) +/* {{{ Memcached::setMulti(array items [, int expiration [, int udf_flags ] ]) Sets the keys/values specified in the items array */ PHP_METHOD(Memcached, setMulti) { @@ -1151,7 +1189,7 @@ PHP_METHOD(Memcached, setMulti) } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration [, int udf_flags ] ]) Sets the keys/values specified in the items array on the server identified by the given server key */ PHP_METHOD(Memcached, setMultiByKey) { @@ -1190,6 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke char *server_key = NULL; int server_key_len = 0; time_t expiration = 0; + uint32_t udf_flags = 0; zval **entry; char *str_key; uint str_key_len; @@ -1203,12 +1242,12 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &server_key, - &server_key_len, &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|ll", &server_key, + &server_key_len, &entries, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1216,6 +1255,16 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; + /* + * php_memcached uses 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + } + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(entries))) { @@ -1238,6 +1287,10 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke flags |= MEMC_VAL_COMPRESSED; } + if (udf_flags > 0) { + MEMC_UDF_SET(flags, udf_flags); + } + payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1263,7 +1316,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration ]) +/* {{{ Memcached::add(string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key, failing if the key already exists */ PHP_METHOD(Memcached, add) { @@ -1271,7 +1324,7 @@ PHP_METHOD(Memcached, add) } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ PHP_METHOD(Memcached, addByKey) { @@ -1311,7 +1364,7 @@ PHP_METHOD(Memcached, prependByKey) } /* }}} */ -/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) +/* {{{ Memcached::replace(string key, mixed value [, int expiration [, int udf_flags ] ]) Replaces the value for the given key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replace) { @@ -1319,7 +1372,7 @@ PHP_METHOD(Memcached, replace) } /* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replaceByKey) { @@ -1340,6 +1393,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; time_t expiration = 0; + uint32_t udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1362,8 +1416,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|l", &server_key, - &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|ll", &server_key, + &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1382,8 +1436,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &key, &key_len, - &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, + &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1410,6 +1464,18 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool flags |= MEMC_VAL_COMPRESSED; } + /* + * php_memcached uses 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + + MEMC_UDF_SET(flags, udf_flags); + } + if (op == MEMC_OP_TOUCH) { if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); @@ -1509,6 +1575,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int server_key_len = 0; zval *value; time_t expiration = 0; + uint32_t udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1516,13 +1583,13 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|l", &cas_d, &server_key, - &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|ll", &cas_d, &server_key, + &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|l", &cas_d, &key, &key_len, - &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|ll", &cas_d, &key, &key_len, + &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1541,6 +1608,18 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) flags |= MEMC_VAL_COMPRESSED; } + /* + * php_memcached uses 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + + MEMC_UDF_SET(flags, udf_flags); + } + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1561,7 +1640,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* }}} */ -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, cas) { @@ -1569,7 +1648,7 @@ PHP_METHOD(Memcached, cas) } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, casByKey) { @@ -3307,6 +3386,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback"); @@ -3339,6 +3421,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(1, cas_token) + ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) @@ -3346,12 +3429,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(1, cas_token) + ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(1, cas_tokens) ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) @@ -3359,6 +3444,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(1, cas_tokens) ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) @@ -3384,6 +3470,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) @@ -3391,6 +3478,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) @@ -3407,18 +3495,21 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) @@ -3426,12 +3517,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) @@ -3439,6 +3532,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) @@ -3472,6 +3566,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) @@ -3480,6 +3575,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) + ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1) From 7f52206bb1af459f1de7516ca3b4d3139edd9632 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:38:40 +0100 Subject: [PATCH 219/694] Was a bit too greedy with all the errors --- php_memcached.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 925b9b4b..3f6377d0 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -133,7 +133,7 @@ typedef unsigned long int uint32_t; User-defined flags ****************************************/ #define MEMC_UDF_MASK 0xf0 -#define MEMC_UDF_GET(flags) ((long)(((flags) & MEMC_UDF_MASK)>>8)) +#define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) #define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) /**************************************** @@ -624,7 +624,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); - if (udf_flags) ( + if (udf_flags) { ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); } @@ -675,7 +675,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } } - if (udf_flags) ( + if (udf_flags) { ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); } } @@ -1072,7 +1072,7 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } @@ -1131,7 +1131,7 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } add_next_index_zval(return_value, entry); @@ -3386,7 +3386,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } From 81971e7abe4796754be17c719a1adc667d138aa8 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:41:37 +0100 Subject: [PATCH 220/694] updated memcached documentation --- memcached-api.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 69ff659e..5eee7020 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -185,13 +185,13 @@ class Memcached { public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - public function get( $key, $cache_cb = null, &$cas_token = null ) {} + public function get( $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} - public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null ) {} + public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} - public function getMulti( array $keys, &$cas_tokens = null, $flags = 0 ) {} + public function getMulti( array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} - public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0 ) {} + public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} @@ -201,25 +201,25 @@ public function fetch( ) {} public function fetchAll( ) {} - public function set( $key, $value, $expiration = 0 ) {} + public function set( $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function touch( $key, $expiration = 0 ) {} public function touchbyKey( $key, $expiration = 0 ) {} - public function setByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function setByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function setMulti( array $items, $expiration = 0 ) {} + public function setMulti( array $items, $expiration = 0, $udf_flags = 0 ) {} - public function setMultiByKey( $server_key, array $items, $expiration = 0 ) {} + public function setMultiByKey( $server_key, array $items, $expiration = 0, $udf_flags = 0 ) {} - public function cas( $token, $key, $value, $expiration = 0 ) {} + public function cas( $token, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function casByKey( $token, $server_key, $key, $value, $expiration = 0 ) {} + public function casByKey( $token, $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function add( $key, $value, $expiration = 0 ) {} + public function add( $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function addByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function addByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function append( $key, $value ) {} @@ -229,9 +229,9 @@ public function prepend( $key, $value ) {} public function prependByKey( $server_key, $key, $value ) {} - public function replace( $key, $value, $expiration = 0 ) {} + public function replace( $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function replaceByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function replaceByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function delete( $key, $time = 0 ) {} From e4ae8fb560eb06dd069368c28612524a386c1ddd Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 17:50:59 +0100 Subject: [PATCH 221/694] Final fixes and tests, cleanup --- php_memcached.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3f6377d0..11f74ff4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -132,9 +132,9 @@ typedef unsigned long int uint32_t; /**************************************** User-defined flags ****************************************/ -#define MEMC_UDF_MASK 0xf0 +#define MEMC_UDF_MASK 0xff00 #define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) -#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) +#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_UDF_MASK)) /**************************************** "get" operation flags @@ -558,7 +558,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) keys[0] = key; key_lens[0] = key_len; - if (cas_token) { + if (cas_token && Z_TYPE_P(cas_token) != IS_NULL) { uint64_t orig_cas_flag; /* @@ -625,7 +625,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) ZVAL_DOUBLE(cas_token, (double)cas); if (udf_flags) { - ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); } memcached_result_free(&result); @@ -676,7 +676,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (udf_flags) { - ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); } } } @@ -1260,8 +1260,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } } @@ -1469,8 +1469,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } MEMC_UDF_SET(flags, udf_flags); @@ -1613,8 +1613,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } MEMC_UDF_SET(flags, udf_flags); From a5e677d9cf20898f20a04dde7c6c527988ddf912 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 02:57:48 +0800 Subject: [PATCH 222/694] Test flags --- php_memcached.c | 88 +++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 41be52df..db3c91d1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -120,9 +120,14 @@ typedef unsigned long int uint32_t; /**************************************** Payload value flags ****************************************/ -#define MEMC_VAL_TYPE_MASK 0xf -#define MEMC_VAL_GET_TYPE(flags) ((flags) & MEMC_VAL_TYPE_MASK) -#define MEMC_VAL_SET_TYPE(flags, type) ((flags) |= ((type) & MEMC_VAL_TYPE_MASK)) +#define MEMC_CREATE_MASK(start, n_bits) (((1 << n_bits) - 1) << start) + +#define MEMC_MASK_TYPE MEMC_CREATE_MASK(0, 4) +#define MEMC_MASK_INTERNAL MEMC_CREATE_MASK(4, 12) +#define MEMC_MASK_USER MEMC_CREATE_MASK(16, 16) + +#define MEMC_VAL_GET_TYPE(flags) ((flags) & MEMC_MASK_TYPE) +#define MEMC_VAL_SET_TYPE(flags, type) ((flags) |= ((type) & MEMC_MASK_TYPE)) #define MEMC_VAL_IS_STRING 0 #define MEMC_VAL_IS_LONG 1 @@ -132,16 +137,21 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_IS_IGBINARY 5 #define MEMC_VAL_IS_JSON 6 -#define MEMC_VAL_COMPRESSED (1<<4) -#define MEMC_VAL_COMPRESSION_ZLIB (1<<5) -#define MEMC_VAL_COMPRESSION_FASTLZ (1<<6) +#define MEMC_VAL_COMPRESSED (1<<0) +#define MEMC_VAL_COMPRESSION_ZLIB (1<<1) +#define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) + +#define MEMC_VAL_GET_FLAGS(internal_flags) ((internal_flags & MEMC_MASK_INTERNAL) >> 4) +#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= ((internal_flag << 4) & MEMC_MASK_INTERNAL)) +#define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & internal_flag) == internal_flag) +#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL); /**************************************** User-defined flags ****************************************/ -#define MEMC_UDF_MASK 0xff00 -#define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) -#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_UDF_MASK)) +#define MEMC_VAL_GET_USER_FLAGS(flags) ((flags & MEMC_MASK_USER) >> 16) +#define MEMC_VAL_SET_USER_FLAGS(flags, udf_flags) ((flags) |= ((udf_flags << 16) & MEMC_MASK_USER)) +#define MEMC_VAL_USER_FLAGS_MAX (MEMC_MASK_USER >> 16) /**************************************** "get" operation flags @@ -652,7 +662,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (udf_flags) { zval_dtor(udf_flags); - ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -840,7 +850,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); } if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_UDF_GET(flags)); + add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_VAL_GET_USER_FLAGS(flags)); } } @@ -1052,8 +1062,8 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -1111,8 +1121,8 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } add_next_index_zval(return_value, entry); } @@ -1241,8 +1251,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } } @@ -1265,11 +1275,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke flags = 0; if (m_obj->compression) { - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } if (udf_flags > 0) { - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -1442,7 +1452,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on"); return; } - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } /* @@ -1450,11 +1460,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } if (op == MEMC_OP_TOUCH) { @@ -1586,7 +1596,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) DVAL_TO_LVAL(cas_d, cas); if (m_obj->compression) { - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } /* @@ -1594,11 +1604,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -2978,11 +2988,11 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* turn off compression for values below the threshold */ - if ((*flags & MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { - *flags &= ~MEMC_VAL_COMPRESSED; + if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); } - if (*flags & MEMC_VAL_COMPRESSED) { + if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ zend_bool compress_status = 0; @@ -2995,10 +3005,10 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t if (compression_type == COMPRESSION_TYPE_FASTLZ) { compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0); - *flags |= MEMC_VAL_COMPRESSION_FASTLZ; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); } else if (compression_type == COMPRESSION_TYPE_ZLIB) { compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK); - *flags |= MEMC_VAL_COMPRESSION_ZLIB; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); } if (!compress_status) { @@ -3016,7 +3026,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t payload[*payload_len] = 0; } else { /* Store plain value */ - *flags &= ~MEMC_VAL_COMPRESSED; + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED) *payload_len = l; memcpy(payload, p, l); payload[l] = 0; @@ -3041,7 +3051,7 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t zend_bool decompress_status = 0; /* Stored with newer memcached extension? */ - if (flags & MEMC_VAL_COMPRESSION_FASTLZ || flags & MEMC_VAL_COMPRESSION_ZLIB) { + if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ) || MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { /* This is copied from Ilia's patch */ memcpy(&len, payload, sizeof(uint32_t)); buffer = emalloc(len + 1); @@ -3049,9 +3059,9 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t payload += sizeof(uint32_t); length = len; - if (flags & MEMC_VAL_COMPRESSION_FASTLZ) { + if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ)) { decompress_status = ((length = fastlz_decompress(payload, *payload_len, buffer, len)) > 0); - } else if (flags & MEMC_VAL_COMPRESSION_ZLIB) { + } else if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, *payload_len) == Z_OK); } } @@ -3106,7 +3116,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ return 0; } - if (flags & MEMC_VAL_COMPRESSED) { + if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { char *datas = s_handle_decompressed (payload_in, &payload_len, flags TSRMLS_CC); if (!datas) { ZVAL_FALSE(value); @@ -3426,8 +3436,8 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { From ddf3f0ca34d6cac1688ac8fe7d1bb1194251eae5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:10:59 +0800 Subject: [PATCH 223/694] Test memcached version when using flags --- php_memcached.c | 58 +++++++++++++++++++++++++++++++++++++++++++ php_memcached.h | 4 ++- tests/user-flags.phpt | 56 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/user-flags.phpt diff --git a/php_memcached.c b/php_memcached.c index db3c91d1..26280eec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -116,6 +116,7 @@ typedef unsigned long int uint32_t; Custom result codes ****************************************/ #define MEMC_RES_PAYLOAD_FAILURE -1001 +#define MEMC_RES_VERSION_FAILURE -1002 /**************************************** Payload value flags @@ -1212,6 +1213,45 @@ PHP_METHOD(Memcached, setMultiByKey) } \ } \ + +static +memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + uint32_t version; + uint8_t major, minor, micro; + + major = memcached_server_major_version (instance); + minor = memcached_server_minor_version (instance); + micro = memcached_server_micro_version (instance); + + if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { + MEMC_G (user_flag_check_result) = 0; + } + return MEMCACHED_SUCCESS; +} + +static +zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) +{ + memcached_server_function callbacks [1]; + + if (MEMC_G (user_flag_check_done)) + return MEMC_G (user_flag_check_result); + + if (memcached_version(memc) != MEMCACHED_SUCCESS) { + MEMC_G (user_flag_check_done) = 1; + MEMC_G (user_flag_check_result) = 0; + return 0; + } + + MEMC_G (user_flag_check_done) = 1; + MEMC_G (user_flag_check_result) = 1; + + callbacks[0] =& s_user_flag_cb; + memcached_server_cursor(memc, callbacks, NULL, 1); +} + + /* {{{ -- php_memc_setMulti_impl */ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { @@ -1251,6 +1291,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1460,6 +1505,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1604,6 +1654,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -3265,6 +3320,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #if HAVE_MEMCACHED_SASL MEMC_G(use_sasl) = 0; #endif + MEMC_G(user_flag_check_done) = 0; + MEMC_G(user_flag_check_result) = 0; } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) @@ -4018,6 +4075,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_VERSION_FAILURE, MEMC_RES_VERSION_FAILURE); /* * Serializer types. diff --git a/php_memcached.h b/php_memcached.h index 9eeb8a0e..99715402 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -91,8 +91,10 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) double compression_factor; #if HAVE_MEMCACHED_SASL - bool use_sasl; + zend_bool use_sasl; #endif + zend_bool user_flag_check_done; + zend_bool user_flag_check_result; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt new file mode 100644 index 00000000..4427ec14 --- /dev/null +++ b/tests/user-flags.phpt @@ -0,0 +1,56 @@ +--TEST-- +Memcached user flags +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$m->addServer('127.0.0.1', 11211, 1); + +$key = uniqid ('udf_test_'); + +echo "stored with flags" . PHP_EOL; + +$m->set ($key, '1', 10, FLAG_1 | FLAG_4); +$udf_flags = 0; +$value = $m->get ($key, null, $x, $udf_flags); + +var_dump (check_flag ($udf_flags, FLAG_1)); +var_dump (check_flag ($udf_flags, FLAG_2)); +var_dump (check_flag ($udf_flags, FLAG_4)); + + +echo "stored without flags" . PHP_EOL; +$m->set ($key, '1'); +$value = $m->get ($key, null, $x, $udf_flags); + +var_dump (check_flag ($udf_flags, FLAG_1)); +var_dump (check_flag ($udf_flags, FLAG_2)); +var_dump (check_flag ($udf_flags, FLAG_4)); + + +echo "DONE TEST\n"; +?> +--EXPECT-- +stored with flags +bool(true) +bool(false) +bool(true) +stored without flags +bool(false) +bool(false) +bool(false) +DONE TEST \ No newline at end of file From 1514dd413f2f855d1c2da536cda41430d56cac83 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:12:44 +0800 Subject: [PATCH 224/694] Dont break old libmemcached --- php_memcached.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 26280eec..77b4bf11 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1220,9 +1220,15 @@ memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_ uint32_t version; uint8_t major, minor, micro; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 major = memcached_server_major_version (instance); minor = memcached_server_minor_version (instance); micro = memcached_server_micro_version (instance); +#else + major = instance->major_version; + minor = instance->minor_version; + micro = instance->micro_version; +#endif if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { MEMC_G (user_flag_check_result) = 0; From 7140a4b33bb778032c6c32406c437eb4fc4f7df4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:17:44 +0800 Subject: [PATCH 225/694] This should return a value --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 77b4bf11..51743d5a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1255,6 +1255,7 @@ zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) callbacks[0] =& s_user_flag_cb; memcached_server_cursor(memc, callbacks, NULL, 1); + return MEMC_G (user_flag_check_result); } From 994e33429fedc476de19b8c1bb51278fe1360806 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Tue, 12 Nov 2013 09:14:44 +0100 Subject: [PATCH 226/694] Protect against stack overflow in php_memc_zval_from_payload when parsing DOUBLE or LONG --- php_memcached.c | 10 ++++++++++ tests/gh_93.phpt | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/gh_93.phpt diff --git a/php_memcached.c b/php_memcached.c index b9d60319..f602e368 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3053,6 +3053,11 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_LONG: { + if (payload_len >= 128) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read long value, too big"); + goto my_error; + } + char conv_buf [128]; memcpy (conv_buf, pl, payload_len); conv_buf [payload_len] = '\0'; @@ -3064,6 +3069,11 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_DOUBLE: { + if (payload_len >= 128) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read double value, too big"); + goto my_error; + } + char conv_buf [128]; memcpy (conv_buf, pl, payload_len); conv_buf [payload_len] = '\0'; diff --git a/tests/gh_93.phpt b/tests/gh_93.phpt new file mode 100644 index 00000000..cf718b9f --- /dev/null +++ b/tests/gh_93.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test for Github issue #93 (double and long overflow) +--SKIPIF-- + +--FILE-- +addServer('127.0.0.1', 11211, 1); +$m->setOption(Memcached::OPT_COMPRESSION, false); + +function testOverflow($m, $value) { + $m->delete('overflow'); + if (true !== $m->set('overflow', $value)) { + echo "Error storing 'overflow' variable\n"; + return false; + } + + if (true !== $m->prepend('overflow', str_repeat('0', 128))) { + echo "Error prepending key\n"; + return false; + } + + $v = @$m->get('overflow'); + if ($v !== $value) { + // At least it doesn't segfault, so we're happy for now + // echo "Error receiving 'overflow' variable\n"; + // return false; + return true; + } + + return true; +} + +if (!testOverflow($m, 10)) { + return; +} + +if (!testOverflow($m, 9.09)) { + return; +} + +echo "OK\n"; +?> +--EXPECT-- +OK \ No newline at end of file From eaa92d48c571a13f2a86b4979732608b8f401107 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 12 Nov 2013 16:36:06 +0800 Subject: [PATCH 227/694] Break was inside braces, remove mixed declarations --- php_memcached.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f602e368..4074e591 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3053,28 +3053,29 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_LONG: { + long lval; + char conv_buf [128]; + if (payload_len >= 128) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read long value, too big"); goto my_error; } - - char conv_buf [128]; memcpy (conv_buf, pl, payload_len); conv_buf [payload_len] = '\0'; - long lval = strtol(conv_buf, NULL, 10); + lval = strtol(conv_buf, NULL, 10); ZVAL_LONG(value, lval); - break; } + break; case MEMC_VAL_IS_DOUBLE: { + char conv_buf [128]; + if (payload_len >= 128) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read double value, too big"); goto my_error; } - - char conv_buf [128]; memcpy (conv_buf, pl, payload_len); conv_buf [payload_len] = '\0'; From 1010295bc69467e13b8db343271fac532cffd768 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 01:10:02 +0800 Subject: [PATCH 228/694] Remove version check //cc #92 --- php_memcached.c | 63 ------------------------------------------------- php_memcached.h | 2 -- 2 files changed, 65 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 51743d5a..6aa65368 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1211,54 +1211,8 @@ PHP_METHOD(Memcached, setMultiByKey) } \ break; \ } \ - } \ - - -static -memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - uint32_t version; - uint8_t major, minor, micro; - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - major = memcached_server_major_version (instance); - minor = memcached_server_minor_version (instance); - micro = memcached_server_micro_version (instance); -#else - major = instance->major_version; - minor = instance->minor_version; - micro = instance->micro_version; -#endif - - if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { - MEMC_G (user_flag_check_result) = 0; - } - return MEMCACHED_SUCCESS; -} - -static -zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) -{ - memcached_server_function callbacks [1]; - - if (MEMC_G (user_flag_check_done)) - return MEMC_G (user_flag_check_result); - - if (memcached_version(memc) != MEMCACHED_SUCCESS) { - MEMC_G (user_flag_check_done) = 1; - MEMC_G (user_flag_check_result) = 0; - return 0; } - MEMC_G (user_flag_check_done) = 1; - MEMC_G (user_flag_check_result) = 1; - - callbacks[0] =& s_user_flag_cb; - memcached_server_cursor(memc, callbacks, NULL, 1); - return MEMC_G (user_flag_check_result); -} - - /* {{{ -- php_memc_setMulti_impl */ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { @@ -1298,11 +1252,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1512,11 +1461,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1661,11 +1605,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -3327,8 +3266,6 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #if HAVE_MEMCACHED_SASL MEMC_G(use_sasl) = 0; #endif - MEMC_G(user_flag_check_done) = 0; - MEMC_G(user_flag_check_result) = 0; } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) diff --git a/php_memcached.h b/php_memcached.h index 99715402..49d5f041 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -93,8 +93,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL zend_bool use_sasl; #endif - zend_bool user_flag_check_done; - zend_bool user_flag_check_result; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); From 79a299591df30853c6238286d816a6e1dad8e01f Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 01:57:25 +0800 Subject: [PATCH 229/694] Merging from poison/feature-udf. Changed flags for parse parameters to long. //cc #92 --- php_memcached.c | 45 ++++++++++++++++++++++++-------------------- tests/cas.phpt | 19 +++++++++++++++++++ tests/cas_multi.phpt | 27 ++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index dee08205..e3d5c44e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -116,7 +116,6 @@ typedef unsigned long int uint32_t; Custom result codes ****************************************/ #define MEMC_RES_PAYLOAD_FAILURE -1001 -#define MEMC_RES_VERSION_FAILURE -1002 /**************************************** Payload value flags @@ -591,13 +590,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_token && Z_TYPE_P(cas_token) != IS_NULL && orig_cas_flag == 0) { + if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); - if (cas_token && Z_TYPE_P(cas_token) != IS_NULL && orig_cas_flag == 0) { + if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -766,7 +765,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_tokens) { + if (cas_tokens && PZVAL_IS_REF(cas_tokens)) { orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); @@ -780,7 +779,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Restore the CAS support flag, but only if we had to turn it on. */ - if (cas_tokens && orig_cas_flag == 0) { + if (cas_tokens && PZVAL_IS_REF(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -792,8 +791,17 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as doubles, because we cannot store potential 64-bit values in longs. */ if (cas_tokens) { - zval_dtor(cas_tokens); - array_init(cas_tokens); + if (PZVAL_IS_REF(cas_tokens)) { + /* cas_tokens was passed by reference, we'll create an array for it. */ + zval_dtor(cas_tokens); + array_init(cas_tokens); + } else { + /* Not passed by reference, we allow this (eg.: if you specify null + to not enable cas but you want to use the udf_flags parameter). + We destruct it and set it to null for the peace of mind. */ + zval_dtor(cas_tokens); + cas_tokens = NULL; + } } /* @@ -1220,7 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke char *server_key = NULL; int server_key_len = 0; time_t expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; zval **entry; char *str_key; uint str_key_len; @@ -1280,7 +1288,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } if (udf_flags > 0) { - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -1385,7 +1393,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; long expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1464,8 +1472,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } if (op == MEMC_OP_TOUCH) { @@ -1567,7 +1574,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int server_key_len = 0; zval *value; time_t expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1608,8 +1615,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -3482,7 +3488,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(1, cas_token) + ZEND_ARG_INFO(2, cas_token) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -3490,13 +3496,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(1, cas_token) + ZEND_ARG_INFO(2, cas_token) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(1, cas_tokens) + ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -3504,7 +3510,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(1, cas_tokens) + ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -4030,7 +4036,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_VERSION_FAILURE, MEMC_RES_VERSION_FAILURE); /* * Serializer types. diff --git a/tests/cas.phpt b/tests/cas.phpt index fc14842b..09b436e0 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -30,6 +30,25 @@ if ($v !== 11) { echo "Wanted cas_test to be 11, value is: "; var_dump($v); } + +$v = $m->get('cas_test', null, 2); +if ($v != 11) { + echo "Failed to get the value with \$cas_token passed by value (2)\n"; + return; +} + +$v = $m->get('cas_test', null, null); +if ($v != 11) { + echo "Failed to get the value with \$cas_token passed by value (null)\n"; + return; +} + +$v = $m->get('cas_test', null, $data = array(2, 4)); +if ($v != 11 || $data !== array(2, 4)) { + echo "Failed to get the value with \$cas_token passed by value (\$data = array(2, 4))\n"; + return; +} + echo "OK\n"; ?> --EXPECT-- diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index d180d779..e4c9e0f3 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -45,6 +45,33 @@ foreach ($data as $key => $v) { } } +if (array_keys($actual) !== array_keys($data)) { + echo "missing value(s)\n"; + echo "data :"; + var_dump($data); + echo "actual data: "; + var_dump($actual); + return; +} + +$actual = $m->getMulti(array_keys($data), 2); +if (array_keys($actual) !== array_keys($data)) { + echo "Failed to getMulti \$cas_token passed by value (2)\n"; + return; +} + +$actual = $m->getMulti(array_keys($data), null); +if (array_keys($actual) !== array_keys($data)) { + echo "Failed to getMulti \$cas_token passed by value (null)\n"; + return; +} + +$actual = $m->getMulti(array_keys($data), $cas_tokens = array(2, 4)); +if (array_keys($actual) !== array_keys($data) || $cas_tokens !== array(2, 4)) { + echo "Failed to getMulti \$cas_token passed by value (\$cas_tokens = array(2, 4))\n"; + return; +} + echo "OK\n"; ?> From 5bde0d1c5eb720b7d6178b7dae15b94470940cc3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 02:10:18 +0800 Subject: [PATCH 230/694] Missing casts --- php_memcached.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e3d5c44e..7285734b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1260,8 +1260,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } } @@ -1469,8 +1469,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } @@ -1612,8 +1612,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } From ccb7e3bbc8f4d95bb7e43ad665fba956a2bceefc Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 02:23:46 +0800 Subject: [PATCH 231/694] More testing of user flags --- php_memcached.c | 14 +++++++------- tests/user-flags.phpt | 25 ++++++++++++++----------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 7285734b..e3610049 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -151,7 +151,7 @@ typedef unsigned long int uint32_t; ****************************************/ #define MEMC_VAL_GET_USER_FLAGS(flags) ((flags & MEMC_MASK_USER) >> 16) #define MEMC_VAL_SET_USER_FLAGS(flags, udf_flags) ((flags) |= ((udf_flags << 16) & MEMC_MASK_USER)) -#define MEMC_VAL_USER_FLAGS_MAX (MEMC_MASK_USER >> 16) +#define MEMC_VAL_USER_FLAGS_MAX ((1 << 16) - 1) /**************************************** "get" operation flags @@ -1256,8 +1256,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke i_obj->rescode = MEMCACHED_SUCCESS; /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * php_memcached uses 16 bits internally to store type, compression and serialization info. + * We use 16 upper bits to store user defined flags. */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { @@ -1465,8 +1465,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * php_memcached uses 16 bits internally to store type, compression and serialization info. + * We use 16 upper bits to store user defined flags. */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { @@ -1608,8 +1608,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * php_memcached uses 16 bits internally to store type, compression and serialization info. + * We use 16 upper bits to store user defined flags. */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 4427ec14..af96e462 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -13,7 +13,9 @@ function check_flag ($flags, $flag) define ('FLAG_1', 1); define ('FLAG_2', 2); define ('FLAG_4', 4); - +define ('FLAG_32', 32); +define ('FLAG_64', 64); +define ('FLAG_TOO_LARGE', pow(2, 16)); $x = 0; $m = new Memcached(); @@ -24,33 +26,34 @@ $key = uniqid ('udf_test_'); echo "stored with flags" . PHP_EOL; -$m->set ($key, '1', 10, FLAG_1 | FLAG_4); +$m->set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); $udf_flags = 0; $value = $m->get ($key, null, $x, $udf_flags); var_dump (check_flag ($udf_flags, FLAG_1)); var_dump (check_flag ($udf_flags, FLAG_2)); var_dump (check_flag ($udf_flags, FLAG_4)); - +var_dump (check_flag ($udf_flags, FLAG_32)); +var_dump (check_flag ($udf_flags, FLAG_64)); echo "stored without flags" . PHP_EOL; $m->set ($key, '1'); $value = $m->get ($key, null, $x, $udf_flags); -var_dump (check_flag ($udf_flags, FLAG_1)); -var_dump (check_flag ($udf_flags, FLAG_2)); -var_dump (check_flag ($udf_flags, FLAG_4)); - +var_dump ($udf_flags == 0); +$m->set ($key, '1', 10, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> ---EXPECT-- +--EXPECTF-- stored with flags bool(true) bool(false) bool(true) -stored without flags -bool(false) -bool(false) bool(false) +bool(true) +stored without flags +bool(true) + +Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d DONE TEST \ No newline at end of file From a4535461cf2730add577bd3f427a708bc636b353 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 14 Nov 2013 01:47:18 +0800 Subject: [PATCH 232/694] Test user flags with compression --- tests/user-flags.phpt | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index af96e462..4891bfd3 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -5,9 +5,15 @@ Memcached user flags --FILE-- set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); $udf_flags = 0; $value = $m->get ($key, null, $x, $udf_flags); -var_dump (check_flag ($udf_flags, FLAG_1)); -var_dump (check_flag ($udf_flags, FLAG_2)); -var_dump (check_flag ($udf_flags, FLAG_4)); -var_dump (check_flag ($udf_flags, FLAG_32)); -var_dump (check_flag ($udf_flags, FLAG_64)); +check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); echo "stored without flags" . PHP_EOL; $m->set ($key, '1'); @@ -43,17 +45,24 @@ $value = $m->get ($key, null, $x, $udf_flags); var_dump ($udf_flags == 0); $m->set ($key, '1', 10, FLAG_TOO_LARGE); +$m->setOption(Memcached::OPT_COMPRESSION, true); +$m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ); + +$m->set ($key, str_repeat ("abcdef1234567890", 200), 10, FLAG_1 | FLAG_4 | FLAG_64); + +$udf_flags = 0; +$value_back = $m->get($key, null, null, $udf_flags); + +check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); + echo "DONE TEST\n"; ?> --EXPECTF-- stored with flags -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) +Flags OK stored without flags bool(true) Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d +Flags OK DONE TEST \ No newline at end of file From 1d5408b76906001683f49a22fd4cae6d84085d4e Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 14 Nov 2013 15:44:19 +0800 Subject: [PATCH 233/694] Starting initial work on server implementation --- config.m4 | 4 +- php_memcached.c | 43 +++++++- php_memcached_server.c | 220 +++++++++++++++++++++++++++++++++++++++++ php_memcached_server.h | 34 +++++++ 4 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 php_memcached_server.c create mode 100644 php_memcached_server.h diff --git a/config.m4 b/config.m4 index 9382bbd0..e14ba10c 100644 --- a/config.m4 +++ b/config.m4 @@ -339,11 +339,13 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_SUBST(MEMCACHED_SHARED_LIBADD) - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c php_memcached_server.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi + + PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) diff --git a/php_memcached.c b/php_memcached.c index 4074e591..10d87114 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -51,6 +51,8 @@ # include "php_memcached_session.h" #endif +#include "php_memcached_server.h" + #include "fastlz/fastlz.h" #include @@ -220,6 +222,7 @@ enum { }; static zend_class_entry *memcached_ce = NULL; +static zend_class_entry *memcached_server_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; static zend_object_handlers memcached_object_handlers; @@ -3373,9 +3376,32 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, return rc; } - /* }}} */ +static +PHP_METHOD(MemcachedServer, run) +{ + php_memc_proto_handler_t *h = php_memc_proto_handler_new (); + my_run (h); +} + +static +PHP_METHOD(MemcachedServer, on) +{ + char *event_name; + int event_name_len; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &event_name, &event_name_len, &fci, &fci_cache) == FAILURE) { + return; + } + + + +} + + /* {{{ methods arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) @@ -3744,6 +3770,17 @@ static zend_function_entry memcached_class_methods[] = { #undef MEMC_ME /* }}} */ +/* {{{ */ +#define MEMC_SE_ME(name, args) PHP_ME(MemcachedServer, name, args, ZEND_ACC_PUBLIC) +static +zend_function_entry memcached_server_class_methods[] = { + MEMC_SE_ME(run, NULL) + MEMC_SE_ME(on, NULL) +} +#undef MEMC_SE_ME +/* }}} */ + + /* {{{ memcached_module_entry */ @@ -3974,6 +4011,10 @@ PHP_MINIT_FUNCTION(memcached) memcached_ce = zend_register_internal_class(&ce TSRMLS_CC); memcached_ce->create_object = php_memc_new; + INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); + memcached_server_ce = zend_register_internal_class(&ce TSRMLS_CC); + memcached_server_ce->create_object = php_memc_server_new; + INIT_CLASS_ENTRY(ce, "MemcachedException", NULL); memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC); /* TODO diff --git a/php_memcached_server.c b/php_memcached_server.c new file mode 100644 index 00000000..9544c551 --- /dev/null +++ b/php_memcached_server.c @@ -0,0 +1,220 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Mikko Koppanen | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "php_libmemcached_compat.h" +#include + +#include "php_memcached.h" +#include "php_memcached_server.h" + +#include + +#undef NDEBUG +#undef _NDEBUG +#include + + +struct _php_memc_proto_handler_t { + memcached_binary_protocol_callback_st callbacks; + struct memcached_protocol_st *protocol_handle; + struct event_base *event_base; +}; + +// memcached protocol callbacks +static +protocol_binary_response_status s_add_handler(const void *cookie, const void *key, uint16_t keylen, const void *data, + uint32_t datalen, uint32_t flags, uint32_t exptime, uint64_t *cas) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_SUCCESS; + + fprintf (stderr, "adding key\n"); + + return retval; +} + +// libevent callbacks +typedef struct _php_memc_client_t { + struct memcached_protocol_client_st *protocol_client; + struct event_base *event_base; +} php_memc_client_t; + +static +void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) +{ + int rc; + short flags = 0; + php_memc_client_t *client = (php_memc_client_t *)arg; + memcached_protocol_event_t events = memcached_protocol_client_work (client->protocol_client); + + if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Client error during communication"); + + memcached_protocol_client_destroy (client->protocol_client); + efree (client); + evutil_closesocket (fd); + return; + } + + if (events & MEMCACHED_PROTOCOL_WRITE_EVENT) { + flags = EV_WRITE; + } + + if (events & MEMCACHED_PROTOCOL_READ_EVENT) { + flags |= EV_READ; + } + + rc = event_base_once (client->event_base, fd, flags, s_handle_memcached_event, client, NULL); + if (rc != 0) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events"); + } +} + +static +void s_accept_cb (evutil_socket_t fd, short what, void *arg) +{ + int rc; + php_memc_client_t *client; + struct sockaddr_storage addr; + socklen_t addr_len; + evutil_socket_t sock; + + php_memc_proto_handler_t *handler = (php_memc_proto_handler_t *) arg; + + /* Accept the connection */ + addr_len = sizeof (addr); + sock = accept (fd, (struct sockaddr *) &addr, &addr_len); + + if (sock == -1) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to accept the client: %s", strerror (errno)); + return; + } + + client = ecalloc (1, sizeof (php_memc_client_t)); + client->protocol_client = memcached_protocol_create_client (handler->protocol_handle, sock); + client->event_base = handler->event_base; + + if (!client->protocol_client) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); + efree (client); + evutil_closesocket (sock); + return; + } + + // TODO: this should timeout + rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL); + + if (rc != 0) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client"); + memcached_protocol_client_destroy (client->protocol_client); + efree (client); + evutil_closesocket (sock); + return; + } +} + +php_memc_proto_handler_t *php_memc_proto_handler_new () +{ + php_memc_proto_handler_t *handler = ecalloc (1, sizeof (php_memc_proto_handler_t)); + + handler->protocol_handle = memcached_protocol_create_instance (); + assert (handler->protocol_handle); + + memset (&handler->callbacks, 0, sizeof (memcached_binary_protocol_callback_st)); + + handler->callbacks.interface_version = MEMCACHED_PROTOCOL_HANDLER_V1; + handler->callbacks.interface.v1.add = s_add_handler; + /*handler->callbacks.interface.v1.append = s_append_handler; + handler->callbacks.interface.v1.decrement = s_decrement_handler; + handler->callbacks.interface.v1.delete_object = s_delete_handler; + handler->callbacks.interface.v1.flush_object = s_flush_handler; + handler->callbacks.interface.v1.get = s_get_handler; + handler->callbacks.interface.v1.increment = s_increment_handler; + handler->callbacks.interface.v1.noop = s_noop_handler; + handler->callbacks.interface.v1.prepend = s_prepend_handler; + handler->callbacks.interface.v1.quit = s_quit_handler; + handler->callbacks.interface.v1.replace = s_replace_handler; + handler->callbacks.interface.v1.set = s_set_handler; + handler->callbacks.interface.v1.stat = s_stat_handler; + handler->callbacks.interface.v1.version = s_version_handler; + */ + + memcached_binary_protocol_set_callbacks(handler->protocol_handle, &handler->callbacks); + return handler; +} + +static +evutil_socket_t s_create_listening_socket (const char *spec) +{ + evutil_socket_t sock; + struct sockaddr_storage addr; + int addr_len; + + int rc; + + addr_len = sizeof (struct sockaddr); + rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); + assert (rc == 0); + + sock = socket (AF_INET, SOCK_STREAM, 0); + assert (sock >= 0); + + rc = bind (sock, (struct sockaddr *) &addr, addr_len); + assert (sock >= 0); + + rc = listen (sock, 1024); + assert (rc >= 0); + + rc = evutil_make_socket_nonblocking (sock); + assert (rc == 0); + + rc = evutil_make_listen_socket_reuseable (sock); + assert (rc == 0); + + rc = evutil_make_socket_closeonexec (sock); + assert (rc == 0); + + return sock; +} + +void my_run (php_memc_proto_handler_t *handler) +{ + struct event *accept_event; + evutil_socket_t sock = s_create_listening_socket ("127.0.0.1:3434"); + + handler->event_base = event_base_new(); + + accept_event = event_new (handler->event_base, sock, EV_READ | EV_PERSIST, s_accept_cb, handler); + event_add (accept_event, NULL); + + int f = event_base_dispatch (handler->event_base); + fprintf (stderr, "Re: %d\n", f); +} + +void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr) +{ + php_memc_proto_handler_t *handler = *ptr; + + if (handler->protocol_handle) + memcached_protocol_destroy_instance (handler->protocol_handle); + + efree (handler); + *ptr = NULL; +} \ No newline at end of file diff --git a/php_memcached_server.h b/php_memcached_server.h new file mode 100644 index 00000000..027e5e0f --- /dev/null +++ b/php_memcached_server.h @@ -0,0 +1,34 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Mikko Koppanen | + +----------------------------------------------------------------------+ +*/ + +#ifndef _PHP_MEMCACHED_SERVER_H_ +# define _PHP_MEMCACHED_SERVER_H_ + +/* + Opaque structure +*/ +typedef struct _php_memc_proto_handler_t php_memc_proto_handler_t; + +/* + Functions +*/ +php_memc_proto_handler_t *php_memc_proto_handler_new (); + +void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); + +void my_run (php_memc_proto_handler_t *h); + +#endif \ No newline at end of file From 6c9ca2535a24deef77afc70ad615e2af2779095d Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 14 Nov 2013 23:28:03 +0800 Subject: [PATCH 234/694] More implementation of the protocool handler --- php_memcached.c | 114 +++++++++++++++-- php_memcached.h | 27 +++++ php_memcached_server.c | 269 ++++++++++++++++++++++++++++++++++++++--- php_memcached_server.h | 5 +- 4 files changed, 388 insertions(+), 27 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 10d87114..a053ac91 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -44,6 +44,7 @@ #include #include +#include "php_memcached_server.h" #include "php_memcached.h" #include "g_fmt.h" @@ -51,7 +52,7 @@ # include "php_memcached_session.h" #endif -#include "php_memcached_server.h" + #include "fastlz/fastlz.h" #include @@ -143,6 +144,7 @@ typedef unsigned long int uint32_t; ****************************************/ #define MEMC_GET_PRESERVE_ORDER (1<<0) + /**************************************** Helper macros ****************************************/ @@ -212,6 +214,11 @@ typedef struct { int memc_errno; } php_memc_t; +typedef struct { + zend_object zo; + php_memc_proto_handler_t *handler; +} php_memc_server_t; + enum { MEMC_OP_SET, MEMC_OP_TOUCH, @@ -226,6 +233,7 @@ static zend_class_entry *memcached_server_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; static zend_object_handlers memcached_object_handlers; +static zend_object_handlers memcached_server_object_handlers; struct callbackContext { @@ -243,8 +251,8 @@ static zend_class_entry *spl_ce_RuntimeException = NULL; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; #undef ZEND_BEGIN_ARG_INFO_EX -#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ - static zend_arg_info name[] = { \ +#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ + static zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, #endif @@ -2645,6 +2653,35 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) return retval; } +static +void php_memc_server_free_storage(php_memc_server_t *intern TSRMLS_DC) +{ + zend_object_std_dtor(&intern->zo TSRMLS_CC); + efree (intern); +} + +zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + php_memc_server_t *intern; + zval *tmp; + + intern = ecalloc(1, sizeof(php_memc_server_t)); + zend_object_std_init (&intern->zo, ce TSRMLS_CC); +#if PHP_VERSION_ID >= 50400 + object_properties_init( (zend_object *) intern, ce); +#else + zend_hash_copy(intern->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); +#endif + + intern->handler = php_memc_proto_handler_new (); + + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL TSRMLS_CC); + retval.handlers = &memcached_server_object_handlers; + + return retval; +} + ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { if (rsrc->ptr) { @@ -3381,24 +3418,43 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, static PHP_METHOD(MemcachedServer, run) { - php_memc_proto_handler_t *h = php_memc_proto_handler_new (); - my_run (h); + php_memc_server_t *intern; + intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); + + php_memc_proto_handler_run (intern->handler); } + static PHP_METHOD(MemcachedServer, on) { - char *event_name; - int event_name_len; + php_memc_server_t *intern; + + long event; zend_fcall_info fci; zend_fcall_info_cache fci_cache; + zend_bool rc = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &event_name, &event_name_len, &fci, &fci_cache) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lf!", &event, &fci, &fci_cache) == FAILURE) { return; } + intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); + + if (event <= MEMC_SERVER_ON_MIN || event >= MEMC_SERVER_ON_MAX) { + RETURN_FALSE; + } + if (fci.size > 0) { + MEMC_G(server_callbacks) [event].fci = fci; + MEMC_G(server_callbacks) [event].fci_cache = fci_cache; + Z_ADDREF_P (fci.function_name); + if (fci.object_ptr) { + Z_ADDREF_P (fci.object_ptr); + } + } + RETURN_BOOL(rc); } @@ -3776,7 +3832,8 @@ static zend_function_entry memcached_server_class_methods[] = { MEMC_SE_ME(run, NULL) MEMC_SE_ME(on, NULL) -} + { NULL, NULL, NULL } +}; #undef MEMC_SE_ME /* }}} */ @@ -3982,6 +4039,42 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(GET_PRESERVE_ORDER, MEMC_GET_PRESERVE_ORDER); + /* + * Server callbacks + */ + REGISTER_MEMC_CLASS_CONST_LONG(ON_ADD, MEMC_SERVER_ON_ADD); + REGISTER_MEMC_CLASS_CONST_LONG(ON_APPEND, MEMC_SERVER_ON_APPEND); + REGISTER_MEMC_CLASS_CONST_LONG(ON_DECREMENT, MEMC_SERVER_ON_DECREMENT); + REGISTER_MEMC_CLASS_CONST_LONG(ON_DELETE, MEMC_SERVER_ON_DELETE); + REGISTER_MEMC_CLASS_CONST_LONG(ON_FLUSH, MEMC_SERVER_ON_FLUSH); + REGISTER_MEMC_CLASS_CONST_LONG(ON_GET, MEMC_SERVER_ON_GET); + REGISTER_MEMC_CLASS_CONST_LONG(ON_INCREMENT, MEMC_SERVER_ON_INCREMENT); + REGISTER_MEMC_CLASS_CONST_LONG(ON_NOOP, MEMC_SERVER_ON_NOOP); + REGISTER_MEMC_CLASS_CONST_LONG(ON_PREPEND, MEMC_SERVER_ON_PREPEND); + REGISTER_MEMC_CLASS_CONST_LONG(ON_QUIT, MEMC_SERVER_ON_QUIT); + REGISTER_MEMC_CLASS_CONST_LONG(ON_REPLACE, MEMC_SERVER_ON_REPLACE); + REGISTER_MEMC_CLASS_CONST_LONG(ON_SET, MEMC_SERVER_ON_SET); + REGISTER_MEMC_CLASS_CONST_LONG(ON_STAT, MEMC_SERVER_ON_STAT); + REGISTER_MEMC_CLASS_CONST_LONG(ON_VERSION, MEMC_SERVER_ON_VERSION); + + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_SUCCESS, PROTOCOL_BINARY_RESPONSE_SUCCESS); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_KEY_ENOENT, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_KEY_EEXISTS, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_E2BIG, PROTOCOL_BINARY_RESPONSE_E2BIG); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_EINVAL, PROTOCOL_BINARY_RESPONSE_EINVAL); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_NOT_STORED, PROTOCOL_BINARY_RESPONSE_NOT_STORED); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_DELTA_BADVAL, PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_NOT_MY_VBUCKET, PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_AUTH_ERROR, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_AUTH_CONTINUE, PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_UNKNOWN_COMMAND, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_ENOMEM, PROTOCOL_BINARY_RESPONSE_ENOMEM); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_NOT_SUPPORTED, PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_EINTERNAL, PROTOCOL_BINARY_RESPONSE_EINTERNAL); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_EBUSY, PROTOCOL_BINARY_RESPONSE_EBUSY); + REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_ETMPFAIL, PROTOCOL_BINARY_RESPONSE_ETMPFAIL); + + #undef REGISTER_MEMC_CLASS_CONST_LONG /* @@ -4004,6 +4097,9 @@ PHP_MINIT_FUNCTION(memcached) memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); memcached_object_handlers.clone_obj = NULL; + memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_server_object_handlers.clone_obj = NULL; + le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); diff --git a/php_memcached.h b/php_memcached.h index 9eeb8a0e..c2fdf1bf 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -58,6 +58,31 @@ enum memcached_serializer { # endif #endif +typedef enum { + MEMC_SERVER_ON_MIN = -1, + MEMC_SERVER_ON_ADD = 0, + MEMC_SERVER_ON_APPEND = 1, + MEMC_SERVER_ON_DECREMENT = 2, + MEMC_SERVER_ON_DELETE = 3, + MEMC_SERVER_ON_FLUSH = 4, + MEMC_SERVER_ON_GET = 5, + MEMC_SERVER_ON_INCREMENT = 6, + MEMC_SERVER_ON_NOOP = 7, + MEMC_SERVER_ON_PREPEND = 8, + MEMC_SERVER_ON_QUIT = 9, + MEMC_SERVER_ON_REPLACE = 10, + MEMC_SERVER_ON_SET = 11, + MEMC_SERVER_ON_STAT = 12, + MEMC_SERVER_ON_VERSION = 13, + MEMC_SERVER_ON_MAX +} php_memc_event_t; + + +typedef struct { + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; +} php_memc_server_cb_t; + ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #ifdef HAVE_MEMCACHED_SESSION zend_bool sess_locking_enabled; @@ -93,6 +118,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif + + php_memc_server_cb_t server_callbacks [14]; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/php_memcached_server.c b/php_memcached_server.c index 9544c551..0320d834 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -19,11 +19,9 @@ #endif #include -#include "php_libmemcached_compat.h" -#include - #include "php_memcached.h" #include "php_memcached_server.h" +#include "php_libmemcached_compat.h" #include @@ -31,6 +29,11 @@ #undef _NDEBUG #include +#define MEMC_GET_CB(cb_type) (MEMC_G(server_callbacks)[cb_type]) +#define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) + + +ZEND_EXTERN_MODULE_GLOBALS(php_memcached) struct _php_memc_proto_handler_t { memcached_binary_protocol_callback_st callbacks; @@ -38,23 +41,254 @@ struct _php_memc_proto_handler_t { struct event_base *event_base; }; +typedef struct { + struct memcached_protocol_client_st *protocol_client; + struct event_base *event_base; +} php_memc_client_t; + +static +long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count TSRMLS_DC) +{ + long retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *retval_ptr = NULL; + + cb->fci.params = params; + cb->fci.param_count = param_count; + + /* Call the cb */ + cb->fci.no_separation = 1; + cb->fci.retval_ptr_ptr = &retval_ptr; + + if (zend_call_function(&(cb->fci), &(cb->fci_cache) TSRMLS_CC) == FAILURE) { + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback %s()", Z_STRVAL_P (cb->fci.function_name)); + } + if (retval_ptr) { + convert_to_long (retval_ptr); + retval = Z_LVAL_P(retval_ptr); + zval_ptr_dtor(&retval_ptr); + } + return retval; +} + // memcached protocol callbacks static -protocol_binary_response_status s_add_handler(const void *cookie, const void *key, uint16_t keylen, const void *data, - uint32_t datalen, uint32_t flags, uint32_t exptime, uint64_t *cas) +protocol_binary_response_status s_add_handler(const void *cookie, const void *key, uint16_t key_len, const void *data, + uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *cas) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zkey, *zvalue, *zflags, *zexptime, *zcas; + zval **params [5]; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { + return retval; + } + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zvalue); + ZVAL_STRINGL(zvalue, data, data_len, 1); + + MAKE_STD_ZVAL(zflags); + ZVAL_LONG(zflags, flags); + + MAKE_STD_ZVAL(zexptime); + ZVAL_LONG(zexptime, exptime); + + MAKE_STD_ZVAL(zcas); + ZVAL_NULL(zcas); + + params [0] = &zkey; + params [1] = &zvalue; + params [2] = &zflags; + params [3] = &zexptime; + params [4] = &zcas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 5); + + if (Z_TYPE_P(zcas) != IS_NULL) { + convert_to_double (zcas); + *cas = (uint64_t) Z_DVAL_P(zcas); + } + + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zvalue); + zval_ptr_dtor (&zflags); + zval_ptr_dtor (&zexptime); + zval_ptr_dtor (&zcas); + + return retval; +} + +static +protocol_binary_response_status s_append_handler(const void *cookie, const void *key, uint16_t key_len, + const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) { - protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_SUCCESS; + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zkey, *zvalue, *zcas, *zresult_cas; + zval **params [4]; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_APPEND)) { + return retval; + } - fprintf (stderr, "adding key\n"); + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zvalue); + ZVAL_STRINGL(zvalue, data, data_len, 1); + + MAKE_STD_ZVAL(zcas); + ZVAL_DOUBLE(zcas, cas); + + MAKE_STD_ZVAL(zresult_cas); + ZVAL_NULL(zresult_cas); + + params [0] = &zkey; + params [1] = &zvalue; + params [2] = &zcas; + params [3] = &zresult_cas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_APPEND), params, 4); + + if (Z_TYPE_P(zresult_cas) != IS_NULL) { + convert_to_double (zresult_cas); + *result_cas = (uint64_t) Z_DVAL_P(zresult_cas); + } + + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zvalue); + zval_ptr_dtor (&zcas); + zval_ptr_dtor (&zresult_cas); return retval; } +static +protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, const void *cookie, const void *key, uint16_t key_len, uint64_t delta, + uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; + zval **params [6]; + + if (!MEMC_HAS_CB(event)) { + return retval; + } + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zdelta); + ZVAL_LONG(zdelta, (long) delta); + + MAKE_STD_ZVAL(zinital); + ZVAL_LONG(zinital, (long) initial); + + MAKE_STD_ZVAL(zexpiration); + ZVAL_LONG(zexpiration, (long) expiration); + + MAKE_STD_ZVAL(zresult); + ZVAL_LONG(zresult, 0); + + MAKE_STD_ZVAL(zresult_cas); + ZVAL_NULL(zresult_cas); + + params [0] = &zkey; + params [1] = &zdelta; + params [2] = &zinital; + params [3] = &zexpiration; + params [4] = &zresult; + params [5] = &zresult_cas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 6); + + if (Z_TYPE_P(zresult) != IS_LONG) { + convert_to_long (zresult); + } + *result = (uint64_t) Z_LVAL_P(zresult); + + if (Z_TYPE_P(zresult_cas) != IS_NULL) { + convert_to_double (zresult_cas); + *result_cas = (uint64_t) Z_DVAL_P(zresult_cas); + } + + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zdelta); + zval_ptr_dtor (&zinital); + zval_ptr_dtor (&zexpiration); + zval_ptr_dtor (&zresult); + zval_ptr_dtor (&zresult_cas); + + return retval; +} + +static +protocol_binary_response_status s_increment_handler (const void *cookie, const void *key, uint16_t key_len, uint64_t delta, + uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) +{ + return + s_incr_decr_handler (MEMC_SERVER_ON_INCREMENT, cookie, key, key_len, delta, initial, expiration, result, result_cas); +} + +static +protocol_binary_response_status s_decrement_handler (const void *cookie, const void *key, uint16_t key_len, uint64_t delta, + uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) +{ + return + s_incr_decr_handler (MEMC_SERVER_ON_DECREMENT, cookie, key, key_len, delta, initial, expiration, result, result_cas); +} + +static +protocol_binary_response_status s_delete_handler (const void *cookie, const void *key, + uint16_t key_len, uint64_t cas) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zkey, *zcas; + zval **params [2]; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) { + return retval; + } + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zcas); + ZVAL_DOUBLE(zcas, (double) cas); + + params [0] = &zkey; + params [1] = &zcas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 2); + + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zcas); + return retval; +} + +static +protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t when) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zwhen; + zval **params [1]; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) { + return retval; + } + + MAKE_STD_ZVAL(zwhen); + ZVAL_LONG(zwhen, (long) when); + + params [0] = &zwhen; + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 1); + + zval_ptr_dtor (&zwhen); + return retval; +} + // libevent callbacks -typedef struct _php_memc_client_t { - struct memcached_protocol_client_st *protocol_client; - struct event_base *event_base; -} php_memc_client_t; static void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) @@ -65,8 +299,6 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) memcached_protocol_event_t events = memcached_protocol_client_work (client->protocol_client); if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Client error during communication"); - memcached_protocol_client_destroy (client->protocol_client); efree (client); evutil_closesocket (fd); @@ -107,9 +339,9 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) return; } - client = ecalloc (1, sizeof (php_memc_client_t)); + client = ecalloc (1, sizeof (php_memc_client_t)); client->protocol_client = memcached_protocol_create_client (handler->protocol_handle, sock); - client->event_base = handler->event_base; + client->event_base = handler->event_base; if (!client->protocol_client) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); @@ -141,12 +373,15 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () handler->callbacks.interface_version = MEMCACHED_PROTOCOL_HANDLER_V1; handler->callbacks.interface.v1.add = s_add_handler; - /*handler->callbacks.interface.v1.append = s_append_handler; + handler->callbacks.interface.v1.append = s_append_handler; handler->callbacks.interface.v1.decrement = s_decrement_handler; handler->callbacks.interface.v1.delete_object = s_delete_handler; handler->callbacks.interface.v1.flush_object = s_flush_handler; + /* handler->callbacks.interface.v1.get = s_get_handler; + */ handler->callbacks.interface.v1.increment = s_increment_handler; + /* handler->callbacks.interface.v1.noop = s_noop_handler; handler->callbacks.interface.v1.prepend = s_prepend_handler; handler->callbacks.interface.v1.quit = s_quit_handler; @@ -194,7 +429,7 @@ evutil_socket_t s_create_listening_socket (const char *spec) return sock; } -void my_run (php_memc_proto_handler_t *handler) +void php_memc_proto_handler_run (php_memc_proto_handler_t *handler) { struct event *accept_event; evutil_socket_t sock = s_create_listening_socket ("127.0.0.1:3434"); diff --git a/php_memcached_server.h b/php_memcached_server.h index 027e5e0f..bf3fae0f 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -17,6 +17,8 @@ #ifndef _PHP_MEMCACHED_SERVER_H_ # define _PHP_MEMCACHED_SERVER_H_ +#include + /* Opaque structure */ @@ -29,6 +31,7 @@ php_memc_proto_handler_t *php_memc_proto_handler_new (); void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); -void my_run (php_memc_proto_handler_t *h); +void php_memc_proto_handler_run (php_memc_proto_handler_t *h); + #endif \ No newline at end of file From 36608f3e0cec3f8bca0248dda148de90c292d688 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 14 Nov 2013 23:50:38 +0800 Subject: [PATCH 235/694] More protocol handling code --- php_memcached_server.c | 107 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index 0320d834..8f7a188e 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -121,14 +121,14 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke } static -protocol_binary_response_status s_append_handler(const void *cookie, const void *key, uint16_t key_len, - const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) +protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event, const void *cookie, const void *key, uint16_t key_len, + const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *zkey, *zvalue, *zcas, *zresult_cas; zval **params [4]; - if (!MEMC_HAS_CB(MEMC_SERVER_ON_APPEND)) { + if (!MEMC_HAS_CB(event)) { return retval; } @@ -149,7 +149,7 @@ protocol_binary_response_status s_append_handler(const void *cookie, const void params [2] = &zcas; params [3] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_APPEND), params, 4); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 4); if (Z_TYPE_P(zresult_cas) != IS_NULL) { convert_to_double (zresult_cas); @@ -164,6 +164,22 @@ protocol_binary_response_status s_append_handler(const void *cookie, const void return retval; } +static +protocol_binary_response_status s_append_handler (const void *cookie, const void *key, uint16_t key_len, + const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) +{ + return + s_append_prepend_handler (MEMC_SERVER_ON_APPEND, cookie, key, key_len, data, data_len, cas, result_cas); +} + +static +protocol_binary_response_status s_prepend_handler (const void *cookie, const void *key, uint16_t key_len, + const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) +{ + return + s_append_prepend_handler (MEMC_SERVER_ON_PREPEND, cookie, key, key_len, data, data_len, cas, result_cas); +} + static protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, const void *cookie, const void *key, uint16_t key_len, uint64_t delta, uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) @@ -288,6 +304,85 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe return retval; } +static +protocol_binary_response_status s_get_handler (const void *cookie, const void *key, uint16_t key_len, + memcached_binary_protocol_get_response_handler response_handler) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zkey, *zvalue, *zflags, *zresult_cas; + zval **params [4]; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_GET)) { + return retval; + } + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zvalue); + ZVAL_NULL(zvalue); + + MAKE_STD_ZVAL(zflags); + ZVAL_NULL(zflags); + + MAKE_STD_ZVAL(zresult_cas); + ZVAL_NULL(zresult_cas); + + params [0] = &zkey; + params [1] = &zvalue; + params [2] = &zflags; + params [3] = &zresult_cas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 4); + + /* Succeeded in getting the key */ + if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { + uint32_t flags = 0; + uint64_t result_cas = 0; + + if (Z_TYPE_P (zvalue) == IS_NULL) { + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zvalue); + zval_ptr_dtor (&zflags); + zval_ptr_dtor (&zresult_cas); + return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT; + } + + if (Z_TYPE_P (zvalue) != IS_STRING) { + convert_to_string (zvalue); + } + + if (Z_TYPE_P (zflags) == IS_LONG) { + flags = Z_LVAL_P (zflags); + } + + if (Z_TYPE_P(zresult_cas) != IS_NULL) { + if (Z_TYPE_P (zresult_cas) != IS_DOUBLE) { + convert_to_double (zresult_cas); + } + result_cas = (uint64_t) Z_DVAL_P (zresult_cas); + } + retval = response_handler(cookie, key, key_len, Z_STRVAL_P(zvalue), Z_STRLEN_P(zvalue), flags, result_cas); + } + + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zvalue); + zval_ptr_dtor (&zflags); + zval_ptr_dtor (&zresult_cas); + return retval; +} + +static +protocol_binary_response_status s_noop_handler(const void *cookie) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) { + return retval; + } + return s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), NULL, 0); +} + // libevent callbacks static @@ -377,13 +472,11 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () handler->callbacks.interface.v1.decrement = s_decrement_handler; handler->callbacks.interface.v1.delete_object = s_delete_handler; handler->callbacks.interface.v1.flush_object = s_flush_handler; - /* handler->callbacks.interface.v1.get = s_get_handler; - */ handler->callbacks.interface.v1.increment = s_increment_handler; - /* handler->callbacks.interface.v1.noop = s_noop_handler; handler->callbacks.interface.v1.prepend = s_prepend_handler; + /* handler->callbacks.interface.v1.quit = s_quit_handler; handler->callbacks.interface.v1.replace = s_replace_handler; handler->callbacks.interface.v1.set = s_set_handler; From 5735f7f60673e863df8776e9a1e738ec1aa8d988 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 04:29:44 +0800 Subject: [PATCH 236/694] Added more server stuff, added examples of server --- config.m4 | 1 + php_memcached.c | 13 +- php_memcached.h | 33 ++-- php_memcached_server.c | 319 ++++++++++++++++++++++++++------- php_memcached_server.h | 2 +- server-example/run-server.php | 85 +++++++++ server-example/test-server.php | 24 +++ 7 files changed, 394 insertions(+), 83 deletions(-) create mode 100644 server-example/run-server.php create mode 100644 server-example/test-server.php diff --git a/config.m4 b/config.m4 index e14ba10c..fc6ced74 100644 --- a/config.m4 +++ b/config.m4 @@ -346,6 +346,7 @@ if test "$PHP_MEMCACHED" != "no"; then fi PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) + PHP_ADD_LIBRARY_WITH_PATH(event, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) diff --git a/php_memcached.c b/php_memcached.c index a053ac91..b9cb277e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3418,10 +3418,16 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, static PHP_METHOD(MemcachedServer, run) { + char *address; + int address_len; + php_memc_server_t *intern; intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); - php_memc_proto_handler_run (intern->handler); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &address, &address_len) == FAILURE) { + return; + } + php_memc_proto_handler_run (intern->handler, address); } @@ -3446,8 +3452,8 @@ PHP_METHOD(MemcachedServer, on) } if (fci.size > 0) { - MEMC_G(server_callbacks) [event].fci = fci; - MEMC_G(server_callbacks) [event].fci_cache = fci_cache; + MEMC_G(server.callbacks) [event].fci = fci; + MEMC_G(server.callbacks) [event].fci_cache = fci_cache; Z_ADDREF_P (fci.function_name); if (fci.object_ptr) { @@ -4042,6 +4048,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) /* * Server callbacks */ + REGISTER_MEMC_CLASS_CONST_LONG(ON_CONNECT, MEMC_SERVER_ON_CONNECT); REGISTER_MEMC_CLASS_CONST_LONG(ON_ADD, MEMC_SERVER_ON_ADD); REGISTER_MEMC_CLASS_CONST_LONG(ON_APPEND, MEMC_SERVER_ON_APPEND); REGISTER_MEMC_CLASS_CONST_LONG(ON_DECREMENT, MEMC_SERVER_ON_DECREMENT); diff --git a/php_memcached.h b/php_memcached.h index c2fdf1bf..d6e5ba73 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -60,20 +60,21 @@ enum memcached_serializer { typedef enum { MEMC_SERVER_ON_MIN = -1, - MEMC_SERVER_ON_ADD = 0, - MEMC_SERVER_ON_APPEND = 1, - MEMC_SERVER_ON_DECREMENT = 2, - MEMC_SERVER_ON_DELETE = 3, - MEMC_SERVER_ON_FLUSH = 4, - MEMC_SERVER_ON_GET = 5, - MEMC_SERVER_ON_INCREMENT = 6, - MEMC_SERVER_ON_NOOP = 7, - MEMC_SERVER_ON_PREPEND = 8, - MEMC_SERVER_ON_QUIT = 9, - MEMC_SERVER_ON_REPLACE = 10, - MEMC_SERVER_ON_SET = 11, - MEMC_SERVER_ON_STAT = 12, - MEMC_SERVER_ON_VERSION = 13, + MEMC_SERVER_ON_CONNECT = 0, + MEMC_SERVER_ON_ADD = 1, + MEMC_SERVER_ON_APPEND = 2, + MEMC_SERVER_ON_DECREMENT = 3, + MEMC_SERVER_ON_DELETE = 4, + MEMC_SERVER_ON_FLUSH = 5, + MEMC_SERVER_ON_GET = 6, + MEMC_SERVER_ON_INCREMENT = 7, + MEMC_SERVER_ON_NOOP = 8, + MEMC_SERVER_ON_PREPEND = 9, + MEMC_SERVER_ON_QUIT = 10, + MEMC_SERVER_ON_REPLACE = 11, + MEMC_SERVER_ON_SET = 12, + MEMC_SERVER_ON_STAT = 13, + MEMC_SERVER_ON_VERSION = 14, MEMC_SERVER_ON_MAX } php_memc_event_t; @@ -119,7 +120,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) bool use_sasl; #endif - php_memc_server_cb_t server_callbacks [14]; + struct { + php_memc_server_cb_t callbacks [14]; + } server; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/php_memcached_server.c b/php_memcached_server.c index 8f7a188e..f04813c0 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -29,9 +29,26 @@ #undef _NDEBUG #include -#define MEMC_GET_CB(cb_type) (MEMC_G(server_callbacks)[cb_type]) +#define MEMC_GET_CB(cb_type) (MEMC_G(server.callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) +#define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ + do { \ + char *cookie_buf; \ + spprintf (&cookie_buf, 0, "%p", my_ptr); \ + MAKE_STD_ZVAL(my_zcookie); \ + ZVAL_STRING(my_zcookie, cookie_buf, 0); \ + } while (0) + +#define MEMC_MAKE_RESULT_CAS(my_zresult_cas, my_result_cas) \ + do { \ + my_result_cas = 0; \ + if (Z_TYPE_P(my_zresult_cas) != IS_NULL) { \ + convert_to_double (my_zresult_cas); \ + my_result_cas = (uint64_t) Z_DVAL_P(my_zresult_cas); \ + } \ + } while (0) + ZEND_EXTERN_MODULE_GLOBALS(php_memcached) @@ -44,6 +61,7 @@ struct _php_memc_proto_handler_t { typedef struct { struct memcached_protocol_client_st *protocol_client; struct event_base *event_base; + zend_bool on_connect_invoked; } php_memc_client_t; static @@ -76,13 +94,15 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zkey, *zvalue, *zflags, *zexptime, *zcas; - zval **params [5]; + zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zcas; + zval **params [6]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zkey); ZVAL_STRINGL(zkey, key, key_len, 1); @@ -98,19 +118,21 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke MAKE_STD_ZVAL(zcas); ZVAL_NULL(zcas); - params [0] = &zkey; - params [1] = &zvalue; - params [2] = &zflags; - params [3] = &zexptime; - params [4] = &zcas; + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zvalue; + params [3] = &zflags; + params [4] = &zexptime; + params [5] = &zcas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 5); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6); if (Z_TYPE_P(zcas) != IS_NULL) { convert_to_double (zcas); *cas = (uint64_t) Z_DVAL_P(zcas); } + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); zval_ptr_dtor (&zflags); @@ -125,13 +147,15 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zkey, *zvalue, *zcas, *zresult_cas; - zval **params [4]; + zval *zcookie, *zkey, *zvalue, *zcas, *zresult_cas; + zval **params [5]; if (!MEMC_HAS_CB(event)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zkey); ZVAL_STRINGL(zkey, key, key_len, 1); @@ -144,18 +168,17 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event MAKE_STD_ZVAL(zresult_cas); ZVAL_NULL(zresult_cas); - params [0] = &zkey; - params [1] = &zvalue; - params [2] = &zcas; - params [3] = &zresult_cas; + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zvalue; + params [3] = &zcas; + params [4] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 4); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5); - if (Z_TYPE_P(zresult_cas) != IS_NULL) { - convert_to_double (zresult_cas); - *result_cas = (uint64_t) Z_DVAL_P(zresult_cas); - } + MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); zval_ptr_dtor (&zcas); @@ -185,13 +208,15 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; - zval **params [6]; + zval *zcookie, *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; + zval **params [7]; if (!MEMC_HAS_CB(event)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zkey); ZVAL_STRINGL(zkey, key, key_len, 1); @@ -210,25 +235,24 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con MAKE_STD_ZVAL(zresult_cas); ZVAL_NULL(zresult_cas); - params [0] = &zkey; - params [1] = &zdelta; - params [2] = &zinital; - params [3] = &zexpiration; - params [4] = &zresult; - params [5] = &zresult_cas; + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zdelta; + params [3] = &zinital; + params [4] = &zexpiration; + params [5] = &zresult; + params [6] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 6); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); if (Z_TYPE_P(zresult) != IS_LONG) { convert_to_long (zresult); } *result = (uint64_t) Z_LVAL_P(zresult); - if (Z_TYPE_P(zresult_cas) != IS_NULL) { - convert_to_double (zresult_cas); - *result_cas = (uint64_t) Z_DVAL_P(zresult_cas); - } + MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zdelta); zval_ptr_dtor (&zinital); @@ -260,24 +284,28 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void uint16_t key_len, uint64_t cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zkey, *zcas; - zval **params [2]; + zval *zcookie, *zkey, *zcas; + zval **params [3]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zkey); ZVAL_STRINGL(zkey, key, key_len, 1); MAKE_STD_ZVAL(zcas); ZVAL_DOUBLE(zcas, (double) cas); - params [0] = &zkey; - params [1] = &zcas; + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zcas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3); + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zcas); return retval; @@ -287,19 +315,24 @@ static protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t when) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zwhen; - zval **params [1]; + zval *zcookie, *zwhen; + zval **params [2]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zwhen); ZVAL_LONG(zwhen, (long) when); - params [0] = &zwhen; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 1); + params [0] = &zcookie; + params [1] = &zwhen; + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); + + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zwhen); return retval; } @@ -309,13 +342,15 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k memcached_binary_protocol_get_response_handler response_handler) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zkey, *zvalue, *zflags, *zresult_cas; - zval **params [4]; + zval *zcookie, *zkey, *zvalue, *zflags, *zresult_cas; + zval **params [5]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_GET)) { return retval; } + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + MAKE_STD_ZVAL(zkey); ZVAL_STRINGL(zkey, key, key_len, 1); @@ -328,12 +363,13 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k MAKE_STD_ZVAL(zresult_cas); ZVAL_NULL(zresult_cas); - params [0] = &zkey; - params [1] = &zvalue; - params [2] = &zflags; - params [3] = &zresult_cas; + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zvalue; + params [3] = &zflags; + params [4] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 4); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5); /* Succeeded in getting the key */ if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { @@ -341,6 +377,7 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k uint64_t result_cas = 0; if (Z_TYPE_P (zvalue) == IS_NULL) { + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); zval_ptr_dtor (&zflags); @@ -356,15 +393,11 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k flags = Z_LVAL_P (zflags); } - if (Z_TYPE_P(zresult_cas) != IS_NULL) { - if (Z_TYPE_P (zresult_cas) != IS_DOUBLE) { - convert_to_double (zresult_cas); - } - result_cas = (uint64_t) Z_DVAL_P (zresult_cas); - } + MEMC_MAKE_RESULT_CAS(zresult_cas, result_cas); retval = response_handler(cookie, key, key_len, Z_STRVAL_P(zvalue), Z_STRLEN_P(zvalue), flags, result_cas); } + zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); zval_ptr_dtor (&zflags); @@ -376,13 +409,118 @@ static protocol_binary_response_status s_noop_handler(const void *cookie) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zcookie; + zval **params [1]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) { return retval; } - return s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), NULL, 0); + + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + + params [0] = &zcookie; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1); + + zval_ptr_dtor (&zcookie); + return retval; +} + +static +protocol_binary_response_status s_quit_handler(const void *cookie) +{ + zval **params [1]; + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zcookie; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_QUIT)) { + return retval; + } + + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + + params [0] = &zcookie; + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1); + + zval_ptr_dtor (&zcookie); + return retval; +} + + + +static +protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, const void *cookie, const void *key, uint16_t key_len, const void *data, + uint32_t data_len, uint32_t flags, uint32_t expiration, uint64_t cas, uint64_t *result_cas) +{ + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zcookie, *zkey, *zdata, *zflags, *zexpiration, *zcas, *zresult_cas; + zval **params [7]; + + if (!MEMC_HAS_CB(event)) { + return retval; + } + + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zdata); + ZVAL_STRINGL(zdata, ((char *) data), (int) data_len, 1); + + MAKE_STD_ZVAL(zflags); + ZVAL_LONG(zflags, (long) flags); + + MAKE_STD_ZVAL(zexpiration); + ZVAL_LONG(zexpiration, (long) expiration); + + MAKE_STD_ZVAL(zcas); + ZVAL_DOUBLE(zcas, (double) cas); + + MAKE_STD_ZVAL(zresult_cas); + ZVAL_NULL(zresult_cas); + + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zdata; + params [3] = &zflags; + params [4] = &zexpiration; + params [5] = &zcas; + params [6] = &zresult_cas; + + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); + + MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + + zval_ptr_dtor (&zcookie); + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zdata); + zval_ptr_dtor (&zflags); + zval_ptr_dtor (&zexpiration); + zval_ptr_dtor (&zcas); + zval_ptr_dtor (&zresult_cas); + + return retval; } +static +protocol_binary_response_status s_replace_handler (const void *cookie, const void *key, uint16_t key_len, const void *data, + uint32_t data_len, uint32_t flags, uint32_t expiration, uint64_t cas, uint64_t *result_cas) +{ + return + s_set_replace_handler (MEMC_SERVER_ON_REPLACE, cookie, key, key_len, data, data_len, flags, expiration, cas, result_cas); +} + +static +protocol_binary_response_status s_set_handler (const void *cookie, const void *key, uint16_t key_len, const void *data, + uint32_t data_len, uint32_t flags, uint32_t expiration, uint64_t cas, uint64_t *result_cas) +{ + return + s_set_replace_handler (MEMC_SERVER_ON_SET, cookie, key, key_len, data, data_len, flags, expiration, cas, result_cas); +} + + + // libevent callbacks static @@ -390,8 +528,53 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) { int rc; short flags = 0; - php_memc_client_t *client = (php_memc_client_t *)arg; - memcached_protocol_event_t events = memcached_protocol_client_work (client->protocol_client); + php_memc_client_t *client = (php_memc_client_t *) arg; + memcached_protocol_event_t events; + + fprintf (stderr, "memcached event\n"); + + if (!client->on_connect_invoked) { + if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { + zval *zremoteip, *zremoteport; + zval **params [2]; + protocol_binary_response_status retval; + + struct sockaddr_in addr_in; + socklen_t addr_in_len = sizeof(addr_in); + + MAKE_STD_ZVAL(zremoteip); + MAKE_STD_ZVAL(zremoteport); + + if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { + ZVAL_STRING(zremoteip, inet_ntoa (addr_in.sin_addr), 1); + ZVAL_LONG(zremoteport, ntohs (addr_in.sin_port)); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "getpeername failed: %s", strerror (errno)); + ZVAL_NULL(zremoteip); + ZVAL_NULL(zremoteport); + } + + params [0] = &zremoteip; + params [1] = &zremoteport; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); + + zval_ptr_dtor (&zremoteip); + zval_ptr_dtor (&zremoteport); + + if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { + memcached_protocol_client_destroy (client->protocol_client); + efree (client); + evutil_closesocket (fd); + return; + } + } + client->on_connect_invoked = 1; + } + + fprintf (stderr, "memcached start work\n"); + events = memcached_protocol_client_work (client->protocol_client); + fprintf (stderr, "memcached done work\n"); if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) { memcached_protocol_client_destroy (client->protocol_client); @@ -412,6 +595,8 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) if (rc != 0) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events"); } + + fprintf (stderr, "memcached event done\n"); } static @@ -434,9 +619,12 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) return; } - client = ecalloc (1, sizeof (php_memc_client_t)); - client->protocol_client = memcached_protocol_create_client (handler->protocol_handle, sock); - client->event_base = handler->event_base; + client = ecalloc (1, sizeof (php_memc_client_t)); + client->protocol_client = memcached_protocol_create_client (handler->protocol_handle, sock); + client->event_base = handler->event_base; + client->on_connect_invoked = 0; + + memcached_protocol_client_set_verbose (client->protocol_client, 1); if (!client->protocol_client) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); @@ -447,6 +635,7 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) // TODO: this should timeout rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL); + fprintf (stderr, "scheduling\n"); if (rc != 0) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client"); @@ -476,10 +665,12 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () handler->callbacks.interface.v1.increment = s_increment_handler; handler->callbacks.interface.v1.noop = s_noop_handler; handler->callbacks.interface.v1.prepend = s_prepend_handler; - /* handler->callbacks.interface.v1.quit = s_quit_handler; + handler->callbacks.interface.v1.replace = s_replace_handler; handler->callbacks.interface.v1.set = s_set_handler; + + /* handler->callbacks.interface.v1.stat = s_stat_handler; handler->callbacks.interface.v1.version = s_version_handler; */ @@ -522,10 +713,10 @@ evutil_socket_t s_create_listening_socket (const char *spec) return sock; } -void php_memc_proto_handler_run (php_memc_proto_handler_t *handler) +void php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const char *address) { struct event *accept_event; - evutil_socket_t sock = s_create_listening_socket ("127.0.0.1:3434"); + evutil_socket_t sock = s_create_listening_socket (address); handler->event_base = event_base_new(); diff --git a/php_memcached_server.h b/php_memcached_server.h index bf3fae0f..f2d5519d 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -31,7 +31,7 @@ php_memc_proto_handler_t *php_memc_proto_handler_new (); void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); -void php_memc_proto_handler_run (php_memc_proto_handler_t *h); +void php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); #endif \ No newline at end of file diff --git a/server-example/run-server.php b/server-example/run-server.php new file mode 100644 index 00000000..b2c4b3d7 --- /dev/null +++ b/server-example/run-server.php @@ -0,0 +1,85 @@ +on (Memcached::ON_CONNECT, + function ($remote_ip, $remote_port) { + echo "Incoming connection from {$remote_ip}:{$remote_port}" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_ADD, + function ($client_id, $key, $value, $flags, $expiration, &$cas) { + echo "client_id=[$client_id]: Add key=[$key], value=[$value], flags=[$flags], expiration=[$expiration]" . PHP_EOL; + $cas = 15; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_APPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Append key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_PREPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Prepend key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_INCREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Incrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DECREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Decrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DELETE, + function ($client_id, $key, $cas) { + echo "client_id=[$client_id]: Delete key=[$key], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_FLUSH, + function ($client_id, $when) { + echo "client_id=[$client_id]: Flush when=[$when]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_GET, + function ($client_id, $key, &$value, &$flags, &$cas) { + echo "client_id=[$client_id]: Get key=[$key]" . PHP_EOL; + $value = "Hello to you client!"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_NOOP, + function ($client_id) { + echo "client_id=[$client_id]: Noop" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_REPLACE, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Replace key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_SET, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Set key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_QUIT, + function ($client_id) { + echo "client_id=[$client_id]: Client quit" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->run ("127.0.0.1:3434"); \ No newline at end of file diff --git a/server-example/test-server.php b/server-example/test-server.php new file mode 100644 index 00000000..6d4c7d42 --- /dev/null +++ b/server-example/test-server.php @@ -0,0 +1,24 @@ +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('localhost', 3434); + +$cache->add("add_key", "hello", 500); +$cache->append("append_key", "world"); +$cache->prepend("prepend_key", "world"); + +$cache->increment("incr", 2, 1, 500); +$cache->decrement("decr", 2, 1, 500); + +$cache->delete("delete_k"); +$cache->flush(1); + +var_dump ($cache->get ('get_this')); + +$cache->set ('set_key', 'value 1', 100); +$cache->replace ('replace_key', 'value 2', 200); + +$cache->quit(); +sleep (1); \ No newline at end of file From f6db3add0fe7df152d4768d886234ad1f66e6546 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 16:30:47 +0800 Subject: [PATCH 237/694] Add rest of the callbacks --- php_memcached.c | 25 ++++- php_memcached_server.c | 174 ++++++++++++++++++++++++++------- php_memcached_server.h | 2 +- server-example/run-server.php | 7 ++ server-example/test-server.php | 2 + 5 files changed, 171 insertions(+), 39 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index b9cb277e..8229c0af 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3415,9 +3415,22 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, } /* }}} */ +static +void s_destroy_cb (zend_fcall_info *fci) +{ + if (fci->size > 0) { + zval_ptr_dtor(&fci->function_name); + if (fci->object_ptr != NULL) { + zval_ptr_dtor(&fci->object_ptr); + } + } +} + static PHP_METHOD(MemcachedServer, run) { + int i; + zend_bool rc; char *address; int address_len; @@ -3427,9 +3440,15 @@ PHP_METHOD(MemcachedServer, run) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &address, &address_len) == FAILURE) { return; } - php_memc_proto_handler_run (intern->handler, address); -} + rc = php_memc_proto_handler_run (intern->handler, address); + + for (i = MEMC_SERVER_ON_MIN + 1; i < MEMC_SERVER_ON_MAX; i++) { + s_destroy_cb (&MEMC_G(server.callbacks) [i].fci); + } + + RETURN_BOOL(rc); +} static PHP_METHOD(MemcachedServer, on) @@ -3452,6 +3471,8 @@ PHP_METHOD(MemcachedServer, on) } if (fci.size > 0) { + s_destroy_cb (&MEMC_G(server.callbacks) [event].fci); + MEMC_G(server.callbacks) [event].fci = fci; MEMC_G(server.callbacks) [event].fci_cache = fci_cache; diff --git a/php_memcached_server.c b/php_memcached_server.c index f04813c0..68d03142 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -78,7 +78,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa cb->fci.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&(cb->fci), &(cb->fci_cache) TSRMLS_CC) == FAILURE) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback %s()", Z_STRVAL_P (cb->fci.function_name)); + php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback"); } if (retval_ptr) { convert_to_long (retval_ptr); @@ -91,10 +91,10 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa // memcached protocol callbacks static protocol_binary_response_status s_add_handler(const void *cookie, const void *key, uint16_t key_len, const void *data, - uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *cas) + uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zcas; + zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zresult_cas; zval **params [6]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { @@ -115,29 +115,26 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke MAKE_STD_ZVAL(zexptime); ZVAL_LONG(zexptime, exptime); - MAKE_STD_ZVAL(zcas); - ZVAL_NULL(zcas); + MAKE_STD_ZVAL(zresult_cas); + ZVAL_NULL(zresult_cas); params [0] = &zcookie; params [1] = &zkey; params [2] = &zvalue; params [3] = &zflags; params [4] = &zexptime; - params [5] = &zcas; + params [5] = &zresult_cas; retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6); - if (Z_TYPE_P(zcas) != IS_NULL) { - convert_to_double (zcas); - *cas = (uint64_t) Z_DVAL_P(zcas); - } + MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); zval_ptr_dtor (&zflags); zval_ptr_dtor (&zexptime); - zval_ptr_dtor (&zcas); + zval_ptr_dtor (&zresult_cas); return retval; } @@ -519,6 +516,82 @@ protocol_binary_response_status s_set_handler (const void *cookie, const void *k s_set_replace_handler (MEMC_SERVER_ON_SET, cookie, key, key_len, data, data_len, flags, expiration, cas, result_cas); } +static +protocol_binary_response_status s_stat_handler (const void *cookie, const void *key, uint16_t key_len, + memcached_binary_protocol_stat_response_handler response_handler) +{ + zval **params [3]; + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zcookie, *zkey, *zbody; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { + return retval; + } + + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + + MAKE_STD_ZVAL(zkey); + ZVAL_STRINGL(zkey, key, key_len, 1); + + MAKE_STD_ZVAL(zbody); + ZVAL_NULL(zbody); + + params [0] = &zcookie; + params [1] = &zkey; + params [2] = &zbody; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); + + if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { + if (Z_TYPE_P (zbody) == IS_NULL) { + retval = response_handler(cookie, NULL, 0, NULL, 0); + } + else { + if (Z_TYPE_P (zbody) != IS_STRING) { + convert_to_string (zbody); + } + retval = response_handler(cookie, key, key_len, Z_STRVAL_P (zbody), (uint32_t) Z_STRLEN_P (zbody)); + } + } + zval_ptr_dtor (&zcookie); + zval_ptr_dtor (&zkey); + zval_ptr_dtor (&zbody); + return retval; +} + +static +protocol_binary_response_status s_version_handler (const void *cookie, + memcached_binary_protocol_version_response_handler response_handler) +{ + zval **params [2]; + protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; + zval *zcookie, *zversion; + + if (!MEMC_HAS_CB(MEMC_SERVER_ON_VERSION)) { + return retval; + } + + MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + + MAKE_STD_ZVAL(zversion); + ZVAL_NULL(zversion); + + params [0] = &zcookie; + params [1] = &zversion; + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); + + if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { + if (Z_TYPE_P (zversion) != IS_STRING) { + convert_to_string (zversion); + } + + retval = response_handler (cookie, Z_STRVAL_P(zversion), (uint32_t) Z_STRLEN_P(zversion)); + } + zval_ptr_dtor (&zcookie); + zval_ptr_dtor (&zversion); + return retval; +} // libevent callbacks @@ -531,8 +604,6 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) php_memc_client_t *client = (php_memc_client_t *) arg; memcached_protocol_event_t events; - fprintf (stderr, "memcached event\n"); - if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { zval *zremoteip, *zremoteport; @@ -572,9 +643,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) client->on_connect_invoked = 1; } - fprintf (stderr, "memcached start work\n"); events = memcached_protocol_client_work (client->protocol_client); - fprintf (stderr, "memcached done work\n"); if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) { memcached_protocol_client_destroy (client->protocol_client); @@ -595,8 +664,6 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) if (rc != 0) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events"); } - - fprintf (stderr, "memcached event done\n"); } static @@ -624,8 +691,6 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) client->event_base = handler->event_base; client->on_connect_invoked = 0; - memcached_protocol_client_set_verbose (client->protocol_client, 1); - if (!client->protocol_client) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); efree (client); @@ -635,7 +700,6 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) // TODO: this should timeout rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL); - fprintf (stderr, "scheduling\n"); if (rc != 0) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client"); @@ -666,14 +730,10 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () handler->callbacks.interface.v1.noop = s_noop_handler; handler->callbacks.interface.v1.prepend = s_prepend_handler; handler->callbacks.interface.v1.quit = s_quit_handler; - handler->callbacks.interface.v1.replace = s_replace_handler; handler->callbacks.interface.v1.set = s_set_handler; - - /* handler->callbacks.interface.v1.stat = s_stat_handler; handler->callbacks.interface.v1.version = s_version_handler; - */ memcached_binary_protocol_set_callbacks(handler->protocol_handle, &handler->callbacks); return handler; @@ -690,41 +750,83 @@ evutil_socket_t s_create_listening_socket (const char *spec) addr_len = sizeof (struct sockaddr); rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); - assert (rc == 0); + if (rc != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse bind address"); + return -1; + } sock = socket (AF_INET, SOCK_STREAM, 0); - assert (sock >= 0); + if (sock < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "socket failed: %s", strerror (errno)); + return -1; + } rc = bind (sock, (struct sockaddr *) &addr, addr_len); - assert (sock >= 0); + if (rc < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "bind failed: %s", strerror (errno)); + return -1; + } rc = listen (sock, 1024); - assert (rc >= 0); + if (rc < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "listen failed: %s", strerror (errno)); + return -1; + } rc = evutil_make_socket_nonblocking (sock); - assert (rc == 0); + if (rc != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket non-blocking: %s", strerror (errno)); + return -1; + } rc = evutil_make_listen_socket_reuseable (sock); - assert (rc == 0); + if (rc != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket reuseable: %s", strerror (errno)); + return -1; + } rc = evutil_make_socket_closeonexec (sock); - assert (rc == 0); - + if (rc != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket closeonexec: %s", strerror (errno)); + return -1; + } return sock; } -void php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const char *address) +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const char *address) { struct event *accept_event; evutil_socket_t sock = s_create_listening_socket (address); - handler->event_base = event_base_new(); + if (sock == -1) { + return 0; + } + handler->event_base = event_base_new(); + if (!handler->event_base) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + } accept_event = event_new (handler->event_base, sock, EV_READ | EV_PERSIST, s_accept_cb, handler); + if (!accept_event) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + } event_add (accept_event, NULL); - int f = event_base_dispatch (handler->event_base); - fprintf (stderr, "Re: %d\n", f); + switch (event_base_dispatch (handler->event_base)) { + case -1: + php_error_docref(NULL TSRMLS_CC, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno)); + return 0; + break; + + case 1: + php_error_docref(NULL TSRMLS_CC, E_ERROR, "no events registered"); + return 0; + break; + + default: + return 1; + break; + } } void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr) diff --git a/php_memcached_server.h b/php_memcached_server.h index f2d5519d..bb66c556 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -31,7 +31,7 @@ php_memc_proto_handler_t *php_memc_proto_handler_new (); void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); -void php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); #endif \ No newline at end of file diff --git a/server-example/run-server.php b/server-example/run-server.php index b2c4b3d7..a02c6a60 100644 --- a/server-example/run-server.php +++ b/server-example/run-server.php @@ -76,6 +76,13 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { return Memcached::RESPONSE_SUCCESS; }); +$server->on (Memcached::ON_STAT, + function ($client_id, $key, &$value) { + echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + $value = "Stat reply"; + return Memcached::RESPONSE_SUCCESS; + }); + $server->on (Memcached::ON_QUIT, function ($client_id) { echo "client_id=[$client_id]: Client quit" . PHP_EOL; diff --git a/server-example/test-server.php b/server-example/test-server.php index 6d4c7d42..3a5079af 100644 --- a/server-example/test-server.php +++ b/server-example/test-server.php @@ -20,5 +20,7 @@ $cache->set ('set_key', 'value 1', 100); $cache->replace ('replace_key', 'value 2', 200); +$cache->getStats (); + $cache->quit(); sleep (1); \ No newline at end of file From 59a4c9551faeab1775f697782160f2eaa8998722 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 16:44:34 +0800 Subject: [PATCH 238/694] proper builds for server --- config.m4 | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/config.m4 b/config.m4 index fc6ced74..afe513ea 100644 --- a/config.m4 +++ b/config.m4 @@ -20,6 +20,9 @@ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer suppo PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], yes, no) +PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, +[ --enable-memcached-protocol Enable memcached protocoll support], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) @@ -337,18 +340,50 @@ if test "$PHP_MEMCACHED" != "no"; then AC_DEFINE(HAVE_LIBMEMCACHED_TOUCH, [1], [Whether memcached_touch is defined]) fi - PHP_SUBST(MEMCACHED_SHARED_LIBADD) - - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c php_memcached_server.c fastlz/fastlz.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi - - PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) - PHP_ADD_LIBRARY_WITH_PATH(event, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) - PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) + LIBEVENT_INCLUDES="" + if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then + + AC_MSG_CHECKING([for libmemcachedprotocol location]) + if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then + if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcachedprotocol-0.0/handler.h"; then + AC_MSG_ERROR([Can't find libmemcachedprotocol headers under "$PHP_LIBMEMCACHED_DIR"]) + fi + fi + AC_MSG_CHECKING([found]) + + PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + if test "x$PKG_CONFIG" = "xno"; then + AC_MSG_RESULT([pkg-config not found]) + AC_MSG_ERROR([Please reinstall the pkg-config distribution]) + fi + + if $PKG_CONFIG --exists libevent; then + PHP_MEMCACHED_LIBEVENT_VERSION=`$PKG_CONFIG libevent --modversion` + PHP_MEMCACHED_LIBEVENT_PREFIX=`$PKG_CONFIG libevent --variable=prefix` + + AC_MSG_RESULT([found version $PHP_MEMCACHED_LIBEVENT_VERSION, under $PHP_MEMCACHED_LIBEVENT_PREFIX]) + LIBEVENT_LIBS=`$PKG_CONFIG libevent --libs` + LIBEVENT_INCLUDES=`$PKG_CONFIG libevent --cflags` + + PHP_EVAL_LIBLINE($LIBEVENT_LIBS, MEMCACHED_SHARED_LIBADD) + PHP_EVAL_INCLINE($LIBEVENT_INCLUDES) + else + AC_MSG_ERROR(Unable to find libevent installation) + fi + PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_server.c" + fi + + PHP_SUBST(MEMCACHED_SHARED_LIBADD) + + PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $LIBEVENT_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) ifdef([PHP_ADD_EXTENSION_DEP], From b5ce538bfcd5c3074408c8d4661d4c71942b4c02 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 17:14:55 +0800 Subject: [PATCH 239/694] Added more examples --- server-example/set-get-server.php | 44 +++++++++++++++++++++++++++++++ server-example/set-get.php | 12 +++++++++ 2 files changed, 56 insertions(+) create mode 100644 server-example/set-get-server.php create mode 100644 server-example/set-get.php diff --git a/server-example/set-get-server.php b/server-example/set-get-server.php new file mode 100644 index 00000000..449f046b --- /dev/null +++ b/server-example/set-get-server.php @@ -0,0 +1,44 @@ +values [$key] = array ('value' => $value, + 'expires' => time () + $expiration); + } + + public function get ($key) { + if (isset ($this->values [$key])) { + if ($this->values [$key] ['expires'] < time ()) { + unset ($this->values [$key]); + return null; + } + return $this->values [$key] ['value']; + } + else + return null; + } +} + +$storage = new Storage (); + +$server->on (Memcached::ON_GET, + function ($client_id, $key, &$value, &$flags, &$cas) use ($storage) { + echo "Getting key=[$key]" . PHP_EOL; + if (($value = $storage->get ($key)) != null) + return Memcached::RESPONSE_SUCCESS; + + return Memcached::RESPONSE_KEY_ENOENT; + }); + +$server->on (Memcached::ON_SET, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) use ($storage) { + echo "Setting key=[$key] value=[$value]" . PHP_EOL; + $storage->set ($key, $value, $expiration); + return Memcached::RESPONSE_SUCCESS; + }); + +$server->run ("127.0.0.1:3434"); \ No newline at end of file diff --git a/server-example/set-get.php b/server-example/set-get.php new file mode 100644 index 00000000..9ff712d0 --- /dev/null +++ b/server-example/set-get.php @@ -0,0 +1,12 @@ +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('localhost', 3434); + +$cache->set ('set_key1', 'This is the first key', 10); +var_dump ($cache->get ('set_key1')); + +$cache->set ('set_key2', 'This is the second key', 2); +var_dump ($cache->get ('set_key2')); From 748566f5afa4430dc94a7b6f24fb36a741fc3ad8 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 17:20:08 +0800 Subject: [PATCH 240/694] Build fixes --- config.m4 | 6 ++++-- php_memcached.c | 29 +++++++++++++++++++++++------ php_memcached.h | 5 ++++- php_memcached_server.h | 3 +++ 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/config.m4 b/config.m4 index afe513ea..eb603c71 100644 --- a/config.m4 +++ b/config.m4 @@ -349,13 +349,13 @@ if test "$PHP_MEMCACHED" != "no"; then LIBEVENT_INCLUDES="" if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then - AC_MSG_CHECKING([for libmemcachedprotocol location]) + AC_MSG_CHECKING([for libmemcachedprotocol]) if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcachedprotocol-0.0/handler.h"; then AC_MSG_ERROR([Can't find libmemcachedprotocol headers under "$PHP_LIBMEMCACHED_DIR"]) fi fi - AC_MSG_CHECKING([found]) + AC_MSG_RESULT([found]) PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) @@ -365,6 +365,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Please reinstall the pkg-config distribution]) fi + AC_MSG_CHECKING([for libevent]) if $PKG_CONFIG --exists libevent; then PHP_MEMCACHED_LIBEVENT_VERSION=`$PKG_CONFIG libevent --modversion` PHP_MEMCACHED_LIBEVENT_PREFIX=`$PKG_CONFIG libevent --variable=prefix` @@ -379,6 +380,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR(Unable to find libevent installation) fi PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_server.c" + AC_DEFINE(HAVE_MEMCACHED_PROTOCOL,1,[Whether memcached protocol is enabled]) fi PHP_SUBST(MEMCACHED_SHARED_LIBADD) diff --git a/php_memcached.c b/php_memcached.c index 8229c0af..3ad0f34d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -214,11 +214,15 @@ typedef struct { int memc_errno; } php_memc_t; +#ifdef HAVE_MEMCACHED_PROTOCOL + typedef struct { zend_object zo; php_memc_proto_handler_t *handler; } php_memc_server_t; +#endif + enum { MEMC_OP_SET, MEMC_OP_TOUCH, @@ -229,11 +233,15 @@ enum { }; static zend_class_entry *memcached_ce = NULL; -static zend_class_entry *memcached_server_ce = NULL; + static zend_class_entry *memcached_exception_ce = NULL; static zend_object_handlers memcached_object_handlers; + +#ifdef HAVE_MEMCACHED_PROTOCOL static zend_object_handlers memcached_server_object_handlers; +static zend_class_entry *memcached_server_ce = NULL; +#endif struct callbackContext { @@ -2653,6 +2661,7 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) return retval; } +#ifdef HAVE_MEMCACHED_PROTOCOL static void php_memc_server_free_storage(php_memc_server_t *intern TSRMLS_DC) { @@ -2681,6 +2690,7 @@ zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) return retval; } +#endif ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { @@ -3415,6 +3425,8 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, } /* }}} */ +#ifdef HAVE_MEMCACHED_PROTOCOL + static void s_destroy_cb (zend_fcall_info *fci) { @@ -3484,6 +3496,7 @@ PHP_METHOD(MemcachedServer, on) RETURN_BOOL(rc); } +#endif /* {{{ methods arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) @@ -3853,6 +3866,7 @@ static zend_function_entry memcached_class_methods[] = { #undef MEMC_ME /* }}} */ +#ifdef HAVE_MEMCACHED_PROTOCOL /* {{{ */ #define MEMC_SE_ME(name, args) PHP_ME(MemcachedServer, name, args, ZEND_ACC_PUBLIC) static @@ -3863,7 +3877,7 @@ zend_function_entry memcached_server_class_methods[] = { }; #undef MEMC_SE_ME /* }}} */ - +#endif /* {{{ memcached_module_entry */ @@ -4066,6 +4080,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(GET_PRESERVE_ORDER, MEMC_GET_PRESERVE_ORDER); +#ifdef HAVE_MEMCACHED_PROTOCOL /* * Server callbacks */ @@ -4101,7 +4116,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_EINTERNAL, PROTOCOL_BINARY_RESPONSE_EINTERNAL); REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_EBUSY, PROTOCOL_BINARY_RESPONSE_EBUSY); REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_ETMPFAIL, PROTOCOL_BINARY_RESPONSE_ETMPFAIL); - +#endif #undef REGISTER_MEMC_CLASS_CONST_LONG @@ -4125,9 +4140,6 @@ PHP_MINIT_FUNCTION(memcached) memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); memcached_object_handlers.clone_obj = NULL; - memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - memcached_server_object_handlers.clone_obj = NULL; - le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); @@ -4135,9 +4147,14 @@ PHP_MINIT_FUNCTION(memcached) memcached_ce = zend_register_internal_class(&ce TSRMLS_CC); memcached_ce->create_object = php_memc_new; +#ifdef HAVE_MEMCACHED_PROTOCOL + memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_server_object_handlers.clone_obj = NULL; + INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); memcached_server_ce = zend_register_internal_class(&ce TSRMLS_CC); memcached_server_ce->create_object = php_memc_server_new; +#endif INIT_CLASS_ENTRY(ce, "MemcachedException", NULL); memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC); diff --git a/php_memcached.h b/php_memcached.h index d6e5ba73..c04c4da0 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -58,6 +58,7 @@ enum memcached_serializer { # endif #endif +#ifdef HAVE_MEMCACHED_PROTOCOL typedef enum { MEMC_SERVER_ON_MIN = -1, MEMC_SERVER_ON_CONNECT = 0, @@ -83,6 +84,7 @@ typedef struct { zend_fcall_info fci; zend_fcall_info_cache fci_cache; } php_memc_server_cb_t; +#endif ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #ifdef HAVE_MEMCACHED_SESSION @@ -119,10 +121,11 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif - +#ifdef HAVE_MEMCACHED_PROTOCOL struct { php_memc_server_cb_t callbacks [14]; } server; +#endif ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/php_memcached_server.h b/php_memcached_server.h index bb66c556..31676c53 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -17,6 +17,8 @@ #ifndef _PHP_MEMCACHED_SERVER_H_ # define _PHP_MEMCACHED_SERVER_H_ +#ifdef HAVE_MEMCACHED_PROTOCOL + #include /* @@ -33,5 +35,6 @@ void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); +#endif #endif \ No newline at end of file From 1cbaeefc83e0c42d8a6295fe8aad28c45c96ca41 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Fri, 15 Nov 2013 12:16:07 +0100 Subject: [PATCH 241/694] Added MEMC_OPT_STORE_RETRY_COUNT --- php_memcached.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 4074e591..cfd96458 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -111,6 +111,7 @@ typedef unsigned long int uint32_t; #define MEMC_OPT_PREFIX_KEY -1002 #define MEMC_OPT_SERIALIZER -1003 #define MEMC_OPT_COMPRESSION_TYPE -1004 +#define MEMC_OPT_STORE_RETRY_COUNT -1005 /**************************************** Custom result codes @@ -202,6 +203,7 @@ typedef struct { #if HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif + int store_retry_count; } *obj; zend_bool is_persistent; @@ -465,6 +467,7 @@ static PHP_METHOD(Memcached, __construct) m_obj->serializer = MEMC_G(serializer); m_obj->compression_type = MEMC_G(compression_type_real); m_obj->compression = 1; + m_obj->store_retry_count = 2; i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -1142,7 +1145,7 @@ PHP_METHOD(Memcached, setMultiByKey) /* }}} */ #define PHP_MEMC_FAILOVER_RETRY \ - if (!by_key && retry < 2) { \ + if (!by_key && retry < m_obj->store_retry_count) { \ switch (i_obj->rescode) { \ case MEMCACHED_HOST_LOOKUP_FAILURE: \ case MEMCACHED_CONNECTION_FAILURE: \ @@ -2278,6 +2281,10 @@ static PHP_METHOD(Memcached, getOption) RETURN_LONG((long)m_obj->serializer); break; + case MEMC_OPT_STORE_RETRY_COUNT: + RETURN_LONG((long)m_obj->store_retry_count); + break; + case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: if (memcached_server_count(m_obj->memc) == 0) { @@ -2400,6 +2407,11 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML break; } + case MEMC_OPT_STORE_RETRY_COUNT: + convert_to_long(value); + m_obj->store_retry_count = Z_LVAL_P(value); + break; + default: /* * Assume that it's a libmemcached behavior option. @@ -3797,6 +3809,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT); /* * Indicate whether igbinary serializer is available From 761fc793815ebc0f2f45c407f1ba3e033307f9c8 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Fri, 15 Nov 2013 15:04:49 +0100 Subject: [PATCH 242/694] Added ini setting for memcached.store_retry_count --- memcached.ini | 6 ++++++ php_memcached.c | 4 +++- php_memcached.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index dd405a05..db37d98b 100644 --- a/memcached.ini +++ b/memcached.ini @@ -109,3 +109,9 @@ memcached.serializer = "igbinary" ; the default is Off memcached.use_sasl = Off +; The amount of retries for failed store commands. +; This mechanism allows transparent fail-over to secondary servers when +; set/increment/decrement/setMulti operations fail on the desired server in a multi-server +; environment. +; the default is 2 +memcached.store_retry_count = 2 diff --git a/php_memcached.c b/php_memcached.c index cfd96458..2d909ac0 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -317,6 +317,7 @@ PHP_INI_BEGIN() #if HAVE_MEMCACHED_SASL STD_PHP_INI_ENTRY("memcached.use_sasl", "0", PHP_INI_SYSTEM, OnUpdateBool, use_sasl, zend_php_memcached_globals, php_memcached_globals) #endif + STD_PHP_INI_ENTRY("memcached.store_retry_count", "2", PHP_INI_ALL, OnUpdateLong, store_retry_count, zend_php_memcached_globals, php_memcached_globals) PHP_INI_END() /* }}} */ @@ -467,7 +468,7 @@ static PHP_METHOD(Memcached, __construct) m_obj->serializer = MEMC_G(serializer); m_obj->compression_type = MEMC_G(compression_type_real); m_obj->compression = 1; - m_obj->store_retry_count = 2; + m_obj->store_retry_count = MEMC_G(store_retry_count); i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -3201,6 +3202,7 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #if HAVE_MEMCACHED_SASL MEMC_G(use_sasl) = 0; #endif + MEMC_G(store_retry_count) = 2; } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) diff --git a/php_memcached.h b/php_memcached.h index 9eeb8a0e..6bcdab7d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -93,6 +93,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif + int store_retry_count; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); From 0280beebb645751d51c86999b85eba9136b39eb5 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Fri, 15 Nov 2013 15:16:31 +0100 Subject: [PATCH 243/694] changed int to long for store_retry_count --- php_memcached.c | 2 +- php_memcached.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2d909ac0..358a667e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -203,7 +203,7 @@ typedef struct { #if HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif - int store_retry_count; + long store_retry_count; } *obj; zend_bool is_persistent; diff --git a/php_memcached.h b/php_memcached.h index 6bcdab7d..496e3e97 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -93,7 +93,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL bool use_sasl; #endif - int store_retry_count; + long store_retry_count; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); From d69bf88461fefc25a3b00730a50b64e3abd3ce5e Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 22:54:31 +0800 Subject: [PATCH 244/694] Fixes comments by @poison --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index e3610049..de1d21d8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -144,7 +144,7 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_GET_FLAGS(internal_flags) ((internal_flags & MEMC_MASK_INTERNAL) >> 4) #define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= ((internal_flag << 4) & MEMC_MASK_INTERNAL)) #define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & internal_flag) == internal_flag) -#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL); +#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL) /**************************************** User-defined flags From c88c4d6bbca32306a7efc0b3c1d20038c3367b47 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 23:32:38 +0800 Subject: [PATCH 245/694] Fixes error with mixing semicolon --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index de1d21d8..5ad6e2b2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3033,7 +3033,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t payload[*payload_len] = 0; } else { /* Store plain value */ - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED) + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); *payload_len = l; memcpy(payload, p, l); payload[l] = 0; From 72246a9f7d2c3f69c045a3f75d216f0443ed4d1f Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Nov 2013 00:58:12 +0800 Subject: [PATCH 246/694] Add server build flags --- .travis.yml | 4 ++-- package.xml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0e814b38..99002750 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ before_script: - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - cd libmemcached-${LIBMEMCACHED_VERSION} - - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" LDFLAGS="-lpthread" + - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-libmemcachedprotocol LDFLAGS="-lpthread" - make - make install - cd .. @@ -32,7 +32,7 @@ script: - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build - cd /tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION} - phpize - - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" + - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-protocol - make - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 diff --git a/package.xml b/package.xml index 2a3dcd36..2dfd34ab 100644 --- a/package.xml +++ b/package.xml @@ -64,6 +64,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + From e69b95b57c0a67df707b5a43d734234084ece8ba Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Nov 2013 01:01:41 +0800 Subject: [PATCH 247/694] ... --- package.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 2dfd34ab..a49c783b 100644 --- a/package.xml +++ b/package.xml @@ -64,8 +64,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - + + From 99f5573635bfb40d499c0f51f67e24aa97485fbf Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Nov 2013 18:15:47 +0800 Subject: [PATCH 248/694] Fixes small memory leak case and print function name properly --- php_memcached.c | 27 ++++++++++++++++++++++++--- php_memcached.h | 2 ++ php_memcached_server.c | 4 +++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 214008b8..1a2e4131 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -364,8 +364,27 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS Method implementations ****************************************/ + +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) +{ + char *buffer = NULL; + + if (fci->object_ptr) { + spprintf (&buffer, 0, "%s::%s", Z_OBJCE_P (fci->object_ptr)->name, fci_cache->function_handler->common.function_name); + } else { + if (Z_TYPE_P (fci->function_name) == IS_OBJECT) { + spprintf (&buffer, 0, "%s", Z_OBJCE_P (fci->function_name)->name); + } + else { + spprintf (&buffer, 0, "%s", Z_STRVAL_P (fci->function_name)); + } + } + return buffer; +} + static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len TSRMLS_DC) { + zend_bool retval = 1; zval pid_z; zval *retval_ptr, *pid_z_ptr = &pid_z; zval **params[2]; @@ -385,15 +404,17 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc fci->no_separation = 1; if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name)); - return 0; + char *buf = php_memc_printable_func (fci, fci_cache TSRMLS_CC); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); + efree (buf); + retval = 0; } zval_dtor(pid_z_ptr); if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } - return 1; + return retval; } static int le_memc, le_memc_sess; diff --git a/php_memcached.h b/php_memcached.h index 367d3908..6abbbc85 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -154,6 +154,8 @@ typedef struct { int php_memc_sess_list_entry(void); +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); + #endif /* PHP_MEMCACHED_H */ /* diff --git a/php_memcached_server.c b/php_memcached_server.c index 68d03142..53f7c5bd 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -78,7 +78,9 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa cb->fci.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&(cb->fci), &(cb->fci_cache) TSRMLS_CC) == FAILURE) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback"); + char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache) TSRMLS_CC); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback %s()", buf); + efree (buf); } if (retval_ptr) { convert_to_long (retval_ptr); From 80253e82c4fa0e471ba2375a9481024156b87505 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 02:14:35 +0800 Subject: [PATCH 249/694] Added Memcached::setBucket --- memcached-api.php | 4 +- package.xml | 1 + php_memcached.c | 184 ++++++++++++++++++++++++--------------------- tests/vbucket.phpt | 46 ++++++++++++ 4 files changed, 148 insertions(+), 87 deletions(-) create mode 100644 tests/vbucket.phpt diff --git a/memcached-api.php b/memcached-api.php index fad92ba2..8319bfc9 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -253,7 +253,7 @@ public function setOption( $option, $value ) {} public function setOptions( array $options ) {} - public function setBucket( array $host_map, array $forward_map, $buckets, $replicas ) {} + public function setBucket( array $host_map, array $forward_map, $replicas ) {} public function addServer( $host, $port, $weight = 0 ) {} @@ -285,7 +285,7 @@ public function isPersistent( ) {} public function isPristine( ) {} - public function setSaslAuthData( $username, $password ) {} + public function setSaslAuthData( $username, $password ) {} } diff --git a/package.xml b/package.xml index 2a3dcd36..5a087e7f 100644 --- a/package.xml +++ b/package.xml @@ -116,6 +116,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/php_memcached.c b/php_memcached.c index 2d25f44f..d3ec6aae 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2522,100 +2522,115 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML return 1; } -/* {{{ Memcached::setBucket(array host_map, array forward_map, long buckets, long replicas) +static +uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) +{ + zval **ppzval; + uint32_t *retval; + size_t i = 0; + + *num_elements = zend_hash_num_elements(Z_ARRVAL_P(input)); + + if (!*num_elements) { + return NULL; + } + + retval = ecalloc(*num_elements, sizeof(uint32_t)); + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(input)); + zend_hash_get_current_data(Z_ARRVAL_P(input), (void **) &ppzval) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(input)), i++) { + + long value = 0; + + if (Z_TYPE_PP(ppzval) == IS_LONG) { + value = Z_LVAL_PP(ppzval); + } + else { + zval tmp_zval, *tmp_pzval; + tmp_zval = **ppzval; + zval_copy_ctor(&tmp_zval); + tmp_pzval = &tmp_zval; + convert_to_long(tmp_pzval); + + value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0; + zval_dtor(tmp_pzval); + } + + if (value < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "the map must contain positive integers"); + efree (retval); + *num_elements = 0; + return NULL; + } + retval [i] = (uint32_t) value; + } + return retval; +} + +/* {{{ Memcached::setBucket(array host_map, array forward_map, integer replicas) Sets the memcached virtual buckets */ PHP_METHOD(Memcached, setBucket) { - zval *host_map; - zval *forward_map; - long buckets; - long replicas; - - uint32_t *hm = NULL,*fm = NULL; - zend_bool ok = 1; - uint key_len; - char *key; - ulong key_index; - zval **value; + zval *zserver_map; + zval *zforward_map = NULL; + long replicas = 0; + zend_bool retval = 1; + + uint32_t *server_map = NULL, *forward_map = NULL; + size_t server_map_len = 0, forward_map_len = 0; + memcached_return rc; MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!ll", &host_map, &forward_map, &buckets, &replicas) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { return; } - - - hm = (uint32_t*)malloc(buckets * sizeof(uint32_t)); - - int i = 0; - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(host_map)); - zend_hash_get_current_data(Z_ARRVAL_P(host_map), (void *) &value) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(host_map))) { - - if (i < buckets) { - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(host_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { - zval copy = **value; - zval_copy_ctor(©); - INIT_PZVAL(©); - convert_to_long(©); - hm[i] = Z_LVAL_P(©); - ++i; - zval_dtor(©); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); - ok = 0; - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); - ok = 0; - break; - } + + MEMC_METHOD_FETCH_OBJECT; + + if (zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "server map cannot be empty"); + RETURN_FALSE; } - if (i != buckets) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); - ok = 0; - } - - i = 0; - if (ok != 0 && forward_map != NULL) { - fm = (uint32_t*)malloc(buckets * sizeof(uint32_t)); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(forward_map)); - zend_hash_get_current_data(Z_ARRVAL_P(forward_map), (void *) &value) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(forward_map))) { - - if (i < buckets) { - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(forward_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { - zval copy = **value; - zval_copy_ctor(©); - INIT_PZVAL(©); - - convert_to_long(©); - fm[i] = Z_LVAL_P(©); - ++i; - zval_dtor(©); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); - ok = 0; - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch"); - ok = 0; - } + if (zforward_map && zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) != zend_hash_num_elements (Z_ARRVAL_P(zforward_map))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "forward_map length must match the server_map length"); + RETURN_FALSE; + } + + if (replicas < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "replicas must be larger than zero"); + RETURN_FALSE; + } + + server_map = s_zval_to_uint32_array (zserver_map, &server_map_len TSRMLS_CC); + + if (!server_map) { + RETURN_FALSE; + } + + if (zforward_map) { + forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len TSRMLS_CC); + + if (!forward_map) { + efree (server_map); + RETURN_FALSE; } } - - MEMC_METHOD_FETCH_OBJECT; - - if (memcached_bucket_set(m_obj->memc, hm, fm, buckets, replicas) != MEMCACHED_SUCCESS) - { - ok = 0; - php_error_docref(NULL TSRMLS_CC, E_WARNING,"memcached_bucket_set don't returned MEMCACHED_SUCCESS"); + + rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); + + if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { + retval = 0;; } - free(hm); - free(fm); - RETURN_BOOL(ok); - + + efree(server_map); + + if (forward_map) { + efree(forward_map); + } + RETURN_BOOL(retval); } /* }}} */ @@ -3869,10 +3884,9 @@ ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0) ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 0) +ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) ZEND_ARG_INFO(0, host_map) ZEND_ARG_INFO(0, forward_map) - ZEND_ARG_INFO(0, buckets) ZEND_ARG_INFO(0, replicas) ZEND_END_ARG_INFO() @@ -3963,7 +3977,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getOption, arginfo_getOption) MEMC_ME(setOption, arginfo_setOption) MEMC_ME(setOptions, arginfo_setOptions) - MEMC_ME(setBucket, arginfo_setBucket) + MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) #endif diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt new file mode 100644 index 00000000..98aca7f8 --- /dev/null +++ b/tests/vbucket.phpt @@ -0,0 +1,46 @@ +--TEST-- +Memcached virtual buckets +--SKIPIF-- + +--FILE-- +setOption (Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_VIRTUAL_BUCKET)); + +$m->addServer('127.0.0.1', 11211, 1); + +var_dump ($m->setBucket (array (1, 2, 3), null, 2)); + +var_dump ($m->setBucket (array (1,2,2), array (1,2,2), 2)); + +var_dump ($m->setBucket (array ('a', 'b', 'c'), null, 2)); + +var_dump ($m->setBucket (array (), null, 2)); + +var_dump ($m->setBucket (array (), array (), -1)); + +var_dump ($m->setBucket (null, array (), -1)); + +var_dump ($m->setBucket (array (-1), array (-1), 1)); + +echo "OK\n"; + +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d +NULL + +Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d +bool(false) +OK \ No newline at end of file From d583378c6a6fbc8610cbae2a2c35f02f10724eed Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 11:20:43 +0800 Subject: [PATCH 250/694] ZTS --- php_memcached_server.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/php_memcached_server.c b/php_memcached_server.c index 53f7c5bd..ca27a0d0 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -99,6 +99,8 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zresult_cas; zval **params [6]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { return retval; } @@ -149,6 +151,8 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event zval *zcookie, *zkey, *zvalue, *zcas, *zresult_cas; zval **params [5]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(event)) { return retval; } @@ -210,6 +214,8 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con zval *zcookie, *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; zval **params [7]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(event)) { return retval; } @@ -286,6 +292,8 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void zval *zcookie, *zkey, *zcas; zval **params [3]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) { return retval; } @@ -317,6 +325,8 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe zval *zcookie, *zwhen; zval **params [2]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) { return retval; } @@ -344,6 +354,8 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k zval *zcookie, *zkey, *zvalue, *zflags, *zresult_cas; zval **params [5]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_GET)) { return retval; } @@ -411,6 +423,8 @@ protocol_binary_response_status s_noop_handler(const void *cookie) zval *zcookie; zval **params [1]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) { return retval; } @@ -432,6 +446,8 @@ protocol_binary_response_status s_quit_handler(const void *cookie) protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *zcookie; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_QUIT)) { return retval; } @@ -455,6 +471,8 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c zval *zcookie, *zkey, *zdata, *zflags, *zexpiration, *zcas, *zresult_cas; zval **params [7]; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(event)) { return retval; } @@ -526,6 +544,8 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *zcookie, *zkey, *zbody; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { return retval; } @@ -569,6 +589,8 @@ protocol_binary_response_status s_version_handler (const void *cookie, protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *zcookie, *zversion; + TSRMLS_FETCH(); + if (!MEMC_HAS_CB(MEMC_SERVER_ON_VERSION)) { return retval; } @@ -606,6 +628,8 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) php_memc_client_t *client = (php_memc_client_t *) arg; memcached_protocol_event_t events; + TSRMLS_FETCH(); + if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { zval *zremoteip, *zremoteport; @@ -679,6 +703,8 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) php_memc_proto_handler_t *handler = (php_memc_proto_handler_t *) arg; + TSRMLS_FETCH(); + /* Accept the connection */ addr_len = sizeof (addr); sock = accept (fd, (struct sockaddr *) &addr, &addr_len); @@ -750,6 +776,8 @@ evutil_socket_t s_create_listening_socket (const char *spec) int rc; + TSRMLS_FETCH(); + addr_len = sizeof (struct sockaddr); rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); if (rc != 0) { @@ -800,6 +828,8 @@ zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const c struct event *accept_event; evutil_socket_t sock = s_create_listening_socket (address); + TSRMLS_FETCH(); + if (sock == -1) { return 0; } From 4b3e6e3f2b7b67492abc85004e59c52a7d8cc5bc Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 11:24:09 +0800 Subject: [PATCH 251/694] more ZTS --- php_memcached_server.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index ca27a0d0..8c5db704 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -129,7 +129,7 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke params [4] = &zexptime; params [5] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6 TSRMLS_CC); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); @@ -177,7 +177,7 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event params [3] = &zcas; params [4] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5 TSRMLS_CC); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); @@ -248,7 +248,7 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con params [5] = &zresult; params [6] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); if (Z_TYPE_P(zresult) != IS_LONG) { convert_to_long (zresult); @@ -310,7 +310,7 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void params [1] = &zkey; params [2] = &zcas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3 TSRMLS_CC); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); @@ -339,7 +339,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe params [0] = &zcookie; params [1] = &zwhen; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2 TSRMLS_CC); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zwhen); @@ -380,7 +380,7 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k params [3] = &zflags; params [4] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5 TSRMLS_CC); /* Succeeded in getting the key */ if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { @@ -433,7 +433,7 @@ protocol_binary_response_status s_noop_handler(const void *cookie) params [0] = &zcookie; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1 TSRMLS_CC); zval_ptr_dtor (&zcookie); return retval; @@ -455,7 +455,7 @@ protocol_binary_response_status s_quit_handler(const void *cookie) MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); params [0] = &zcookie; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1 TSRMLS_CC); zval_ptr_dtor (&zcookie); return retval; @@ -505,7 +505,7 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c params [5] = &zcas; params [6] = &zresult_cas; - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); @@ -562,7 +562,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * params [1] = &zkey; params [2] = &zbody; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3 TSRMLS_CC); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { if (Z_TYPE_P (zbody) == IS_NULL) { @@ -603,7 +603,7 @@ protocol_binary_response_status s_version_handler (const void *cookie, params [0] = &zcookie; params [1] = &zversion; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2 TSRMLS_CC); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { if (Z_TYPE_P (zversion) != IS_STRING) { @@ -654,7 +654,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) params [0] = &zremoteip; params [1] = &zremoteport; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2 TSRMLS_CC); zval_ptr_dtor (&zremoteip); zval_ptr_dtor (&zremoteport); From 853c0f1ba3ef35dda386a9a463a7d66b21e7c5b2 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 11:47:27 +0800 Subject: [PATCH 252/694] Fixes build for older libmemcached --- config.m4 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/config.m4 b/config.m4 index eb603c71..9ea8928a 100644 --- a/config.m4 +++ b/config.m4 @@ -347,7 +347,9 @@ if test "$PHP_MEMCACHED" != "no"; then fi LIBEVENT_INCLUDES="" + AC_MSG_CHECKING([for memcached protocol support]) if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then + AC_MSG_RESULT([enabled]) AC_MSG_CHECKING([for libmemcachedprotocol]) if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then @@ -357,6 +359,21 @@ if test "$PHP_MEMCACHED" != "no"; then fi AC_MSG_RESULT([found]) + ORIG_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" + + AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_working_libmemcachedprotocol, [ + AC_TRY_COMPILE( + [ #include ], + [ memcached_binary_protocol_callback_st s_test_impl; + s_test_impl.interface.v1.delete_object = 0; + ], + [ ac_cv_have_working_libmemcachedprotocol="yes" ], + [ ac_cv_have_working_libmemcachedprotocol="no" ] + ) + ]) + CFLAGS="$ORIG_CFLAGS" + PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) AC_PATH_PROG(PKG_CONFIG, pkg-config, no) @@ -381,6 +398,8 @@ if test "$PHP_MEMCACHED" != "no"; then fi PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_server.c" AC_DEFINE(HAVE_MEMCACHED_PROTOCOL,1,[Whether memcached protocol is enabled]) + else + AC_MSG_RESULT([disabled]) fi PHP_SUBST(MEMCACHED_SHARED_LIBADD) From abe022c8cfbf974d57ec7eaba0ae6d3f391ee559 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 12:05:01 +0800 Subject: [PATCH 253/694] Fail here --- config.m4 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index 9ea8928a..43846e1f 100644 --- a/config.m4 +++ b/config.m4 @@ -362,18 +362,22 @@ if test "$PHP_MEMCACHED" != "no"; then ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" - AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_working_libmemcachedprotocol, [ + AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [ AC_TRY_COMPILE( [ #include ], [ memcached_binary_protocol_callback_st s_test_impl; s_test_impl.interface.v1.delete_object = 0; ], - [ ac_cv_have_working_libmemcachedprotocol="yes" ], - [ ac_cv_have_working_libmemcachedprotocol="no" ] + [ ac_cv_have_libmemcachedprotocol="yes" ], + [ ac_cv_have_libmemcachedprotocol="no" ] ) ]) CFLAGS="$ORIG_CFLAGS" + if test "$ac_cv_have_libmemcachedprotocol" != "yes"; then + AC_MSG_ERROR([Cannot enable libmemcached protocol]) + fi + PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) AC_PATH_PROG(PKG_CONFIG, pkg-config, no) From 9e13cb61396210809b3da8533938197575535708 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 12:07:32 +0800 Subject: [PATCH 254/694] Fix check for test --- tests/vbucket.phpt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt index 98aca7f8..ee3b1c85 100644 --- a/tests/vbucket.phpt +++ b/tests/vbucket.phpt @@ -1,7 +1,10 @@ --TEST-- Memcached virtual buckets --SKIPIF-- - + --FILE-- Date: Mon, 18 Nov 2013 14:10:41 +0800 Subject: [PATCH 255/694] Do types.phpt and types_multi.phpt with all serializers --- .travis.yml | 7 ++- config.m4 | 2 +- package.xml | 1 + tests/types.phpt | 102 +++++++++++++++++++++++------------------ tests/types_multi.phpt | 87 +++++++++++++++++++---------------- tests/vbucket.phpt | 4 +- 6 files changed, 114 insertions(+), 89 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0e814b38..ff518bb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,8 @@ before_script: - make - make install - cd .. + - sudo apt-get install php-pear php5-dev + - pecl install igbinary script: @@ -32,12 +34,13 @@ script: - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build - cd /tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION} - phpize - - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" + - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-json --enable-memcached-igbinary - make + - make install - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so -d extension_dir=modules -n ./tests/*.phpt + - php run-tests.php -d extension=memcached.so --d extension=igbinary.so -n ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done diff --git a/config.m4 b/config.m4 index 9382bbd0..8d7ba5d8 100644 --- a/config.m4 +++ b/config.m4 @@ -338,7 +338,7 @@ if test "$PHP_MEMCACHED" != "no"; then fi PHP_SUBST(MEMCACHED_SHARED_LIBADD) - + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then diff --git a/package.xml b/package.xml index 5a087e7f..42693ac7 100644 --- a/package.xml +++ b/package.xml @@ -118,6 +118,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/types.phpt b/tests/types.phpt index 7ffa67bb..c5b19c0d 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -4,69 +4,81 @@ Memcached store & fetch type and value correctness --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; class testclass { } -$data = array( - array('boolean_true', true), - array('boolean_false', false), +function types_simple_test ($m, $options) +{ + + $data = array( + array('boolean_true', true), + array('boolean_false', false), - array('string', "just a string"), - array('string_empty', ""), + array('string', "just a string"), + array('string_empty', ""), - array('integer_positive_integer', 10), - array('integer_negative_integer', -10), - array('integer_zero_integer', 0), + array('integer_positive_integer', 10), + array('integer_negative_integer', -10), + array('integer_zero_integer', 0), - array('float_positive1', 3.912131), - array('float_positive2', 1.2131E+501), - array('float_positive2', 1.2131E+52), - array('float_negative', -42.123312), - array('float_zero', 0.0), + array('float_positive1', 3.912131), + array('float_positive2', 1.2131E+501), + array('float_positive2', 1.2131E+52), + array('float_negative', -42.123312), + array('float_zero', 0.0), - array('null', null), + array('null', null), - array('array_empty', array()), - array('array', array(1,2,3,"foo")), + array('array_empty', array()), + array('array', array(1,2,3,"foo")), - array('object_array_empty', (object)array()), - array('object_array', (object)array("a" => "1","b" => "2","c" => "3")), - array('object_dummy', new testclass()), -); + array('object_array_empty', (object)array()), + array('object_array', (object)array("a" => "1","b" => "2","c" => "3")), + array('object_dummy', new testclass()), + ); -foreach ($data as $key => $value) { - $m->delete($key); -} + foreach ($data as $key => $value) { + $m->delete($key); + } + + foreach ($data as $types) { + $key = $types [0]; + $value = $types [1]; -foreach ($data as $types) { - $m->set($types[0], $types[1]); - $actual = $m->get($types[0]); - if ($types[1] !== $actual) { - if (is_object($types[1]) - && $types[1] == $actual - && get_class($types[1]) == get_class($actual)) { - continue; + $m->set($key, $value); + + $actual = $m->get($key); + if ($value !== $actual) { + if (is_object($actual)) { + if ($options['ignore_object_type']) { + $value = (object) (array) $value; + if ($value == $actual) + continue; + } + + if ($value == $actual && get_class($value) == get_class($actual)) + continue; + } + echo "=== $types[0] ===\n"; + echo "Expected: "; + var_dump($types[1]); + echo "Actual: "; + var_dump($actual); } - echo "=== $types[0] ===\n"; - echo "Expected: "; - var_dump($types[1]); - echo "Actual: "; - var_dump($actual); } -} -$m->flush(); + $m->flush(); -if (($actual = $m->get("sdfjhw38rwdenfoqu29eiajfroehr8jaiodfhjaoierhjadf")) !== false) { - echo "Expected: null"; - echo "Actual: " . gettype($actual); + if (($actual = $m->get(uniqid ('random_key_'))) !== false) { + echo "Expected: null"; + echo "Actual: " . gettype($actual); + } } -echo "OK\n"; +memc_run_test ('types_simple_test', memc_get_serializer_options ()); ?> --EXPECT-- -OK +TEST DONE diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt index 456405f9..46bc5f76 100644 --- a/tests/types_multi.phpt +++ b/tests/types_multi.phpt @@ -4,61 +4,70 @@ Memcached multi store & multi fetch type and value correctness --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; class testclass { } -$data = array( - 'boolean_true' => true, - 'boolean_false' => false, +function types_test ($m, $options) +{ + $data = array( + 'boolean_true' => true, + 'boolean_false' => false, - 'string' => "just a string", - 'string_empty' => "", + 'string' => "just a string", + 'string_empty' => "", + 'string_large' => str_repeat ('abcdef0123456789', 500), - 'integer_positive_integer' => 10, - 'integer_negative_integer' => -10, - 'integer_zero_integer' => 0, + 'integer_positive_integer' => 10, + 'integer_negative_integer' => -10, + 'integer_zero_integer' => 0, - 'float_positive1' => 3.912131, - 'float_positive2' => 1.2131E+52, - 'float_negative' => -42.123312, - 'float_zero' => 0.0, + 'float_positive1' => 3.912131, + 'float_positive2' => 1.2131E+52, + 'float_negative' => -42.123312, + 'float_zero' => 0.0, - 'null' => null, + 'null' => null, - 'array_empty' => array(), - 'array' => array(1,2,3,"foo"), + 'array_empty' => array(), + 'array' => array(1,2,3,"foo"), - 'object_array_empty' => (object)array(), - 'object_array' => (object)array('a' => 1, 'b' => 2, 'c' => 3), - 'object_dummy' => new testclass(), -); + 'object_array_empty' => (object)array(), + 'object_array' => (object)array('a' => 1, 'b' => 2, 'c' => 3), + 'object_dummy' => new testclass(), + ); -foreach ($data as $key => $value) { - $m->delete($key); -} -$m->setMulti($data); -$actual = $m->getMulti(array_keys($data)); + foreach ($data as $key => $value) { + $m->delete($key); + } + $m->setMulti($data); + $actual = $m->getMulti(array_keys($data)); + + foreach ($data as $key => $value) { + if ($value !== $actual[$key]) { + if (is_object($value)) { + if ($options['ignore_object_type']) { + $value = (object) (array) $value; + if ($value == $actual[$key]) + continue; + } + + if ($value == $actual[$key] && get_class($value) == get_class($actual[$key])) + continue; + } -foreach ($data as $key => $value) { - if ($value !== $actual[$key]) { - if (is_object($value) - && $value == $actual[$key] - && get_class($value) == get_class($actual[$key])) { - continue; + echo "=== $key ===\n"; + echo "Expected: "; + var_dump($value); + echo "Actual: "; + var_dump($actual[$key]); } - echo "=== $key ===\n"; - echo "Expected: "; - var_dump($value); - echo "Actual: "; - var_dump($actual[$key]); } } -echo "OK\n"; +memc_run_test ('types_test', memc_get_serializer_options ()); ?> --EXPECT-- -OK \ No newline at end of file +TEST DONE \ No newline at end of file diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt index ee3b1c85..1b64c0c1 100644 --- a/tests/vbucket.phpt +++ b/tests/vbucket.phpt @@ -2,8 +2,8 @@ Memcached virtual buckets --SKIPIF-- --FILE-- Date: Mon, 18 Nov 2013 14:14:14 +0800 Subject: [PATCH 256/694] Add update for travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ff518bb0..e37a187b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ before_script: - make - make install - cd .. + - sudo apt-get update - sudo apt-get install php-pear php5-dev - pecl install igbinary From 239623e66f6b9b835db334991b1ed430f1e9e557 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 14:17:26 +0800 Subject: [PATCH 257/694] Fix typo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e37a187b..9b9af008 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,7 +41,7 @@ script: - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so --d extension=igbinary.so -n ./tests/*.phpt + - php run-tests.php -d extension=memcached.so -d extension=igbinary.so -n ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done From 4048537a360ca146fefb689dd8935cc9920d8e50 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 14:24:47 +0800 Subject: [PATCH 258/694] Travis travis.. --- .travis.yml | 10 +++++--- tests/config.inc | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 tests/config.inc diff --git a/.travis.yml b/.travis.yml index 9b9af008..6a929cbd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,9 +23,13 @@ before_script: - make - make install - cd .. - - sudo apt-get update - - sudo apt-get install php-pear php5-dev - - pecl install igbinary + - git clone git@github.com:igbinary/igbinary.git + - cd igbinary + - phpize + - ./configure + - make + - make install + - cd .. script: diff --git a/tests/config.inc b/tests/config.inc new file mode 100644 index 00000000..7b68a2c9 --- /dev/null +++ b/tests/config.inc @@ -0,0 +1,62 @@ +addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + $memcached->flush (); + return $memcached; +} + +function memc_run_test ($test_function, $options = array ()) +{ + foreach ($options as $option_set) { + $memc = memc_get_instance (); + + foreach ($option_set ['options'] as $key => $value) { + if ($memc->setOption ($key, $value) == false) { + die ('Failed to set option: ' . $key); + } + } + $test_function ($memc, $option_set); + } + echo "TEST DONE" . PHP_EOL; +} + +function memc_create_combinations ($name, $serializer, $ignore_object_type = false) +{ + return array ( + array ( + 'title' => "$name serializer, ascii protocol", + 'options' => array ( + Memcached::OPT_SERIALIZER => $serializer + ), + 'ignore_object_type' => $ignore_object_type + ), + array ( + 'title' => "$name serializer, binary protocol", + 'options' => array ( + Memcached::OPT_BINARY_PROTOCOL => true, + Memcached::OPT_SERIALIZER => $serializer + ), + 'ignore_object_type' => $ignore_object_type + ), + ); +} + +function memc_get_serializer_options () +{ + $options = memc_create_combinations ('PHP', Memcached::SERIALIZER_PHP); + + if (defined ('Memcached::HAVE_IGBINARY')) { + $options = array_merge ($options, memc_create_combinations ('igbinary', Memcached::SERIALIZER_IGBINARY)); + } + + if (defined ('Memcached::HAVE_JSON')) { + $options = array_merge ($options, memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true)); + } + return $options; +} \ No newline at end of file From 368dd3c8be5e9ef0ba5d75d6787c682081db54cb Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 14:26:40 +0800 Subject: [PATCH 259/694] Clone over https --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6a929cbd..a3f7da76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_script: - make - make install - cd .. - - git clone git@github.com:igbinary/igbinary.git + - git clone https://github.com/igbinary/igbinary.git - cd igbinary - phpize - ./configure From 4258449ee73ba1e80cd5823cc6c0bd918d980ca7 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 14:52:04 +0800 Subject: [PATCH 260/694] Configure with libmemcached protocol if configure succeeds --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d1bd3cb0..de435661 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ script: - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build - cd /tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION} - phpize - - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-protocol --enable-memcached-json --enable-memcached-igbinary + - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-protocol --enable-memcached-json --enable-memcached-igbinary || ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-json --enable-memcached-igbinary - make - make install - export NO_INTERACTION=1 From 16825267df6b7686f38c96fb8acece8fa5756174 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 14:54:33 +0800 Subject: [PATCH 261/694] Lets see if this fixes the build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index de435661..c78042e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ before_script: - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - cd libmemcached-${LIBMEMCACHED_VERSION} - - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-libmemcachedprotocol LDFLAGS="-lpthread" + - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-libmemcachedprotocol CFLAGS='-std=gnu99' LDFLAGS="-lpthread" - make - make install - cd .. From 374922a280c641a7ff53b88402c315bb76994ccf Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:03:00 +0800 Subject: [PATCH 262/694] Moved travis build to shell script --- .travis.yml | 39 ++------------------ package.xml | 2 ++ travis.sh | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 36 deletions(-) create mode 100755 travis.sh diff --git a/.travis.yml b/.travis.yml index c78042e0..d9e974b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: php php: - 5.5 - #- 5.4 - #- 5.3 + - 5.4 + - 5.3 env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 @@ -14,38 +14,5 @@ env: - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.44 -before_script: - - for file in tests/*.phpt; do grep $(basename $file) package.xml >/dev/null || (echo "Missing $file from package.xml" ; exit 1); done - - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" - - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - - cd libmemcached-${LIBMEMCACHED_VERSION} - - ./configure --prefix="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-libmemcachedprotocol CFLAGS='-std=gnu99' LDFLAGS="-lpthread" - - make - - make install - - cd .. - - git clone https://github.com/igbinary/igbinary.git - - cd igbinary - - phpize - - ./configure - - make - - make install - - cd .. - - script: - - export PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') - - pear package - - mkdir /tmp/php-memcached-build - - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build - - cd /tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION} - - phpize - - ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-protocol --enable-memcached-json --enable-memcached-igbinary || ./configure --with-libmemcached-dir="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" --enable-memcached-json --enable-memcached-igbinary - - make - - make install - - export NO_INTERACTION=1 - - export REPORT_EXIT_STATUS=1 - - export TEST_PHP_EXECUTABLE=`which php` - - php run-tests.php -d extension=memcached.so -d extension=igbinary.so -n ./tests/*.phpt - - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done - - + ./travis.sh $LIBMEMCACHED_VERSION diff --git a/package.xml b/package.xml index d98e9a0f..e2c80e34 100644 --- a/package.xml +++ b/package.xml @@ -119,6 +119,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + diff --git a/travis.sh b/travis.sh new file mode 100755 index 00000000..bb82ee4e --- /dev/null +++ b/travis.sh @@ -0,0 +1,101 @@ +#!/bin/bash -e + +function validate_package_xml() { + retval=0 + for file in tests/*.phpt; do + grep $(basename $file) package.xml >/dev/null + if [ $? != 0 ]; then + echo "Missing $file from package.xml" + retval=1; + fi + done + return $retval; +} + +function install_libmemcached() { + local libmemcached_version=$1 + local enable_protocol=$2 + wget "https://launchpad.net/libmemcached/1.0/$%7Blibmemcached_version%7D/+download/libmemcached-$%7Blibmemcached_version%7D.tar.gz" -O libmemcached-${libmemcached_version}.tar.gz + + tar xvfz libmemcached-${libmemcached_version}.tar.gz + pushd "libmemcached-${libmemcached_version}" + + if test "x$enable_protocol" = "xyes"; then + protocol_flag="--enable-libmemcachedprotocol" + fi + + ./configure --prefix="$PHP_LIBMEMCACHED_PREFIX" $protocol_flag LDFLAGS="-lpthread" + make + make install + popd +} + +function install_igbinary() { + git clone https://github.com/igbinary/igbinary.git + pushd igbinary + phpize + ./configure + make + make install + popd +} + +function build_php_memcached() { + pear package + mkdir /tmp/php-memcached-build + tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build + pushd "/tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION}" + phpize + + if test "x$enable_protocol" = "xyes"; then + protocol_flag="--enable-memcached-protocol" + fi + + ./configure --with-libmemcached-dir="$PHP_LIBMEMCACHED_PREFIX" $protocol_flag --enable-memcached-json --enable-memcached-igbinary + make + make install + popd +} + +function run_memcached_tests() { + export NO_INTERACTION=1 + export REPORT_EXIT_STATUS=1 + export TEST_PHP_EXECUTABLE=`which php` + php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt + for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done +} + +# Command line arguments +PHP_LIBMEMCACHED_VERSION=$1 + +# Export the extension version +export PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') + +# Libmemcached install dir +export PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" + +# Check whether to enable building with protoocol support +dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" '>' 1.0.15 +if [ $? = 0 ]; then + enable_protocol=yes +else + enable_protocol=no +fi + +echo "Enable protocol: $enable_protocol" + +# validate the package.xml +validate_package_xml + +# Install libmemcached version +install_libmemcached $PHP_LIBMEMCACHED_VERSION $enable_protocol + +# Install igbinary extension +install_igbinary + +# Build the extension +build_php_memcached $enable_protocol + +# Run tests +run_memcached_tests + From 9d2b27f9ad9ebb2ae2179a5bd88fdcdf3f539617 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:07:12 +0800 Subject: [PATCH 263/694] enter build directory --- travis.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/travis.sh b/travis.sh index bb82ee4e..5b5ae89f 100755 --- a/travis.sh +++ b/travis.sh @@ -61,8 +61,11 @@ function run_memcached_tests() { export NO_INTERACTION=1 export REPORT_EXIT_STATUS=1 export TEST_PHP_EXECUTABLE=`which php` - php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done + + pushd /tmp/php-memcached-build + php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt + for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done + popd } # Command line arguments @@ -77,25 +80,25 @@ export PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION} # Check whether to enable building with protoocol support dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" '>' 1.0.15 if [ $? = 0 ]; then - enable_protocol=yes + ENABLE_PROTOOCOL=yes else - enable_protocol=no + ENABLE_PROTOOCOL=no fi -echo "Enable protocol: $enable_protocol" +echo "Enable protocol: $ENABLE_PROTOOCOL" # validate the package.xml validate_package_xml # Install libmemcached version -install_libmemcached $PHP_LIBMEMCACHED_VERSION $enable_protocol +install_libmemcached $PHP_LIBMEMCACHED_VERSION $ENABLE_PROTOOCOL # Install igbinary extension install_igbinary # Build the extension -build_php_memcached $enable_protocol +build_php_memcached $ENABLE_PROTOOCOL # Run tests -run_memcached_tests +run_memcached_tests $PHP_LIBMEMCACHED_VERSION From dbb68a5c597b8eba367053f172e3c7f7a20f8942 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:12:12 +0800 Subject: [PATCH 264/694] More travis stuff --- travis.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/travis.sh b/travis.sh index 5b5ae89f..b254ce1a 100755 --- a/travis.sh +++ b/travis.sh @@ -14,7 +14,9 @@ function validate_package_xml() { function install_libmemcached() { local libmemcached_version=$1 - local enable_protocol=$2 + local libmemcached_prefix=$2 + local enable_protocol=$3 + wget "https://launchpad.net/libmemcached/1.0/$%7Blibmemcached_version%7D/+download/libmemcached-$%7Blibmemcached_version%7D.tar.gz" -O libmemcached-${libmemcached_version}.tar.gz tar xvfz libmemcached-${libmemcached_version}.tar.gz @@ -41,28 +43,34 @@ function install_igbinary() { } function build_php_memcached() { + local libmemcached_prefix=$1 + local php_memcached_version=$2 + local enable_protocol=$3 + pear package mkdir /tmp/php-memcached-build - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C /tmp/php-memcached-build - pushd "/tmp/php-memcached-build/memcached-${PHP_MEMCACHED_VERSION}" + tar xfz "memcached-${php_memcached_version}.tgz" -C /tmp/php-memcached-build + pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" phpize if test "x$enable_protocol" = "xyes"; then protocol_flag="--enable-memcached-protocol" fi - ./configure --with-libmemcached-dir="$PHP_LIBMEMCACHED_PREFIX" $protocol_flag --enable-memcached-json --enable-memcached-igbinary + ./configure --with-libmemcached-dir="$libmemcached_prefix" $protocol_flag --enable-memcached-json --enable-memcached-igbinary make make install popd } function run_memcached_tests() { + local php_memcached_version=$1 + export NO_INTERACTION=1 export REPORT_EXIT_STATUS=1 export TEST_PHP_EXECUTABLE=`which php` - pushd /tmp/php-memcached-build + pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done popd @@ -71,11 +79,11 @@ function run_memcached_tests() { # Command line arguments PHP_LIBMEMCACHED_VERSION=$1 -# Export the extension version -export PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') +# the extension version +PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') # Libmemcached install dir -export PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" +PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" # Check whether to enable building with protoocol support dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" '>' 1.0.15 @@ -91,14 +99,14 @@ echo "Enable protocol: $ENABLE_PROTOOCOL" validate_package_xml # Install libmemcached version -install_libmemcached $PHP_LIBMEMCACHED_VERSION $ENABLE_PROTOOCOL +install_libmemcached $PHP_LIBMEMCACHED_VERSION $PHP_LIBMEMCACHED_PREFIX $ENABLE_PROTOOCOL # Install igbinary extension install_igbinary # Build the extension -build_php_memcached $ENABLE_PROTOOCOL +build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL # Run tests -run_memcached_tests $PHP_LIBMEMCACHED_VERSION +run_memcached_tests $PHP_MEMCACHED_VERSION From 0c0402ee9d5f58545d9abecb7fa9869e1eb5b132 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:29:18 +0800 Subject: [PATCH 265/694] More travis stuff --- travis.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/travis.sh b/travis.sh index b254ce1a..8ee5af98 100755 --- a/travis.sh +++ b/travis.sh @@ -1,4 +1,4 @@ -#!/bin/bash -e +#!/bin/bash function validate_package_xml() { retval=0 @@ -72,8 +72,16 @@ function run_memcached_tests() { pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo ""; echo "-- END"; done + retval=$? + for i in `ls tests/*.out 2>/dev/null`; do + echo "-- START ${i}"; + cat $i; + echo ""; + echo "-- END"; + done popd + + return $retval; } # Command line arguments @@ -96,7 +104,10 @@ fi echo "Enable protocol: $ENABLE_PROTOOCOL" # validate the package.xml -validate_package_xml +validate_package_xml || exit 1 + +# exit on error +set -e # Install libmemcached version install_libmemcached $PHP_LIBMEMCACHED_VERSION $PHP_LIBMEMCACHED_PREFIX $ENABLE_PROTOOCOL @@ -108,5 +119,6 @@ install_igbinary build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL # Run tests -run_memcached_tests $PHP_MEMCACHED_VERSION +set +e +run_memcached_tests $PHP_MEMCACHED_VERSION || exit 1 From 3626a25619d2ff25acdba2079c4dbb9df3950652 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:38:37 +0800 Subject: [PATCH 266/694] Make this gt --- travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis.sh b/travis.sh index 8ee5af98..8c481c16 100755 --- a/travis.sh +++ b/travis.sh @@ -94,7 +94,7 @@ PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" # Check whether to enable building with protoocol support -dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" '>' 1.0.15 +dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" gt 1.0.15 if [ $? = 0 ]; then ENABLE_PROTOOCOL=yes else From ae795e44355c5b2937f7f3ddfa545148d0c0d9b7 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:53:00 +0800 Subject: [PATCH 267/694] Run expire test separately because XFAIL causes the whole build fail --- .travis.yml | 2 +- travis.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d9e974b5..e86e7ab0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ env: - LIBMEMCACHED_VERSION=0.44 script: - ./travis.sh $LIBMEMCACHED_VERSION + - ./travis.sh $LIBMEMCACHED_VERSION diff --git a/travis.sh b/travis.sh index 8c481c16..a838d3e3 100755 --- a/travis.sh +++ b/travis.sh @@ -70,6 +70,10 @@ function run_memcached_tests() { export REPORT_EXIT_STATUS=1 export TEST_PHP_EXECUTABLE=`which php` + # We have one xfail test, we run it separately + php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt + rm ./tests/expire.phpt + pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt retval=$? From 74648a8e0e070b709caeea379b27c77f7d49cab4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 16:57:19 +0800 Subject: [PATCH 268/694] Doing this in right dir makes more sense --- travis.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/travis.sh b/travis.sh index a838d3e3..7b53dbe8 100755 --- a/travis.sh +++ b/travis.sh @@ -70,11 +70,11 @@ function run_memcached_tests() { export REPORT_EXIT_STATUS=1 export TEST_PHP_EXECUTABLE=`which php` - # We have one xfail test, we run it separately - php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt - rm ./tests/expire.phpt - pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" + # We have one xfail test, we run it separately + php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt + rm ./tests/expire.phpt + php run-tests.php -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt retval=$? for i in `ls tests/*.out 2>/dev/null`; do From e56d2d49808b4f49d579f7914d0a4131f79c70f6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 17:06:35 +0800 Subject: [PATCH 269/694] Add changelog items --- ChangeLog | 2 ++ package.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index bc0d2063..e4d96745 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,8 @@ Version 2.2.0b1 - memcached.sess_randomize_replica_read - memcached.sess_remove_failed - memcached.sess_connect_timeout + * Added support for memcached protocol handlers + * Added Memcached::setBucket for virtual bucket support Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index e2c80e34..08a6c864 100644 --- a/package.xml +++ b/package.xml @@ -46,6 +46,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> * memcached.sess_randomize_replica_read * memcached.sess_remove_failed * memcached.sess_connect_timeout +- Added support for memcached protocol handlers +- Added Memcached::setBucket for virtual bucket support From 71638fe743a4cf520d5460ba0a7209f07d865de7 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 17:18:00 +0800 Subject: [PATCH 270/694] Msgpack --- tests/config.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/config.inc b/tests/config.inc index 7b68a2c9..a750ba79 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -58,5 +58,9 @@ function memc_get_serializer_options () if (defined ('Memcached::HAVE_JSON')) { $options = array_merge ($options, memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true)); } + + if (defined ('Memcached::HAVE_MSGPACK')) { + $options = array_merge ($options, memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK)); + } return $options; } \ No newline at end of file From 081a161b068799f5a1c04d3de94bd9298cfdcc66 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Nov 2013 17:28:23 +0800 Subject: [PATCH 271/694] Fixes indentation on the msgpack parts --- php_memcached.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 60084adb..ead3fe7d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2543,8 +2543,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML /* msgpack serializer */ #ifdef HAVE_MEMCACHED_MSGPACK if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { - m_obj->serializer = SERIALIZER_MSGPACK; - } else + m_obj->serializer = SERIALIZER_MSGPACK; + } else #endif /* php serializer */ if (Z_LVAL_P(value) == SERIALIZER_PHP) { @@ -3177,18 +3177,18 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } #endif #ifdef HAVE_MEMCACHED_MSGPACK - case SERIALIZER_MSGPACK: - php_msgpack_serialize(&buf, value TSRMLS_CC); + case SERIALIZER_MSGPACK: + php_msgpack_serialize(&buf, value TSRMLS_CC); if(!buf.c) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); - smart_str_free(&buf); - return NULL; - } - p = buf.c; - l = buf.len; - buf_used = 1; - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); - break; + smart_str_free(&buf); + return NULL; + } + p = buf.c; + l = buf.len; + buf_used = 1; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; #endif default: { @@ -3462,10 +3462,10 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ #ifdef HAVE_MEMCACHED_MSGPACK php_msgpack_unserialize(value, pl, payload_len TSRMLS_CC); #else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); - goto my_error; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + goto my_error; #endif - break; + break; default: ZVAL_FALSE(value); @@ -4194,7 +4194,7 @@ static const zend_module_dep memcached_deps[] = { ZEND_MOD_REQUIRED("igbinary") #endif #ifdef HAVE_MEMCACHED_MSGPACK - ZEND_MOD_REQUIRED("msgpack") + ZEND_MOD_REQUIRED("msgpack") #endif #ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") @@ -4262,9 +4262,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * Indicate whether msgpack serializer is available */ #ifdef HAVE_MEMCACHED_MSGPACK - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); #endif #ifdef HAVE_MEMCACHED_SESSION @@ -4558,9 +4558,9 @@ PHP_MINFO_FUNCTION(memcached) #endif #ifdef HAVE_MEMCACHED_MSGPACK - php_info_print_table_row(2, "msgpack support", "yes"); + php_info_print_table_row(2, "msgpack support", "yes"); #else - php_info_print_table_row(2, "msgpack support", "no"); + php_info_print_table_row(2, "msgpack support", "no"); #endif php_info_print_table_end(); From deb45d3e1b4026d8a4f11b41a7e7403b740f467f Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 12:06:35 +0800 Subject: [PATCH 272/694] Add latest version of msgpack --- travis.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/travis.sh b/travis.sh index 1bc3bed9..a58c85e1 100755 --- a/travis.sh +++ b/travis.sh @@ -43,7 +43,13 @@ function install_igbinary() { } function install_msgpack() { - pecl install msgpack-beta + git clone https://github.com/msgpack/msgpack-php.git + pushd msgpack-php + phpize + ./configure + make + make install + popd } function build_php_memcached() { @@ -61,7 +67,7 @@ function build_php_memcached() { protocol_flag="--enable-memcached-protocol" fi - ./configure --with-libmemcached-dir="$libmemcached_prefix" $protocol_flag --enable-memcached-json --enable-memcached-igbinary + ./configure --with-libmemcached-dir="$libmemcached_prefix" $protocol_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack make make install popd @@ -76,10 +82,10 @@ function run_memcached_tests() { pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" # We have one xfail test, we run it separately - php run-tests.php -d msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt + php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt rm ./tests/expire.phpt - php run-tests.php -d msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt retval=$? for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; From 03162e42a28333dbd80f8c75fc5e9d62691364ed Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 12:27:00 +0800 Subject: [PATCH 273/694] Changelog entries --- ChangeLog | 1 + package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index e4d96745..2ba3b177 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ Version 2.2.0b1 - memcached.sess_connect_timeout * Added support for memcached protocol handlers * Added Memcached::setBucket for virtual bucket support + * Added support for msgpack serialization Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index 08a6c864..0bb8c66b 100644 --- a/package.xml +++ b/package.xml @@ -48,6 +48,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> * memcached.sess_connect_timeout - Added support for memcached protocol handlers - Added Memcached::setBucket for virtual bucket support +- Added support for msgpack serialization From a036333f653afae493265b39441a6eba9e253d25 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 12:27:28 +0800 Subject: [PATCH 274/694] Update version --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 90dd3b15..4a68eb7e 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -143,7 +143,7 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#define PHP_MEMCACHED_VERSION "2.1.0" +#define PHP_MEMCACHED_VERSION "2.2.0b1" #ifdef ZTS #define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) From bc5309078790d06e40c6f7fab65f55a05e886f6e Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 12:44:22 +0800 Subject: [PATCH 275/694] Remove unused variables --- php_memcached.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index ead3fe7d..173e8618 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2170,8 +2170,7 @@ PHP_METHOD(Memcached, quit) Flush and senf buffered commands */ PHP_METHOD(Memcached, flushBuffers) { - memcached_return rc; - MEMC_METHOD_INIT_VARS; + MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { return; @@ -2449,7 +2448,7 @@ static PHP_METHOD(Memcached, getOption) static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRMLS_DC) { - memcached_return rc; + memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; struct memc_obj *m_obj = i_obj->obj; @@ -2758,7 +2757,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) MEMC_METHOD_INIT_VARS; char *user, *pass; - int user_len, pass_len, rc; + int user_len, pass_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &user, &user_len, &pass, &pass_len) == FAILURE) { return; @@ -2900,14 +2899,16 @@ zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_memc_t *i_obj; - zval *tmp; i_obj = ecalloc(1, sizeof(*i_obj)); zend_object_std_init( &i_obj->zo, ce TSRMLS_CC ); #if PHP_VERSION_ID >= 50400 object_properties_init( (zend_object *) i_obj, ce); #else - zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + { + zval *tmp; + zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + } #endif retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); @@ -3332,7 +3333,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ A NULL payload is completely valid if length is 0, it is simply empty. */ zend_bool payload_emalloc = 0; - char *datas = NULL, *buffer = NULL, *pl = NULL; + char *pl = NULL; if (payload_in == NULL && payload_len > 0) { ZVAL_FALSE(value); From f7aba7745a5a820aee7a767e0936bc31063bf410 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 12:45:45 +0800 Subject: [PATCH 276/694] Package.xml updates --- package.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 0bb8c66b..def047e2 100644 --- a/package.xml +++ b/package.xml @@ -21,14 +21,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-10-28 + 2013-11-19 2.2.0b1 2.2.0 beta - stable + beta PHP From 65a8cf0c6a8bd39a70569bf7a6eb155e50c24a50 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 16:01:32 +0800 Subject: [PATCH 277/694] Improved config.m4, use pkg-config to find libmemcached --- config.m4 | 59 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/config.m4 b/config.m4 index 573993ca..2d7ee2c9 100644 --- a/config.m4 +++ b/config.m4 @@ -41,6 +41,11 @@ fi if test "$PHP_MEMCACHED" != "no"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + if test "x$PKG_CONFIG" = "xno"; then + AC_MSG_RESULT([pkg-config not found]) + AC_MSG_ERROR([Please reinstall the pkg-config distribution]) + fi dnl # zlib if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then @@ -271,38 +276,37 @@ if test "$PHP_MEMCACHED" != "no"; then fi AC_MSG_CHECKING([for libmemcached location]) + export ORIG_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" + if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then - if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached/memcached.h"; then - AC_MSG_ERROR([Can't find libmemcached headers under "$PHP_LIBMEMCACHED_DIR"]) - fi + export PKG_CONFIG_PATH="$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR/pkgconfig" else - PHP_LIBMEMCACHED_DIR="no" - for i in /usr /usr/local; do - if test -r "$i/include/libmemcached/memcached.h"; then - PHP_LIBMEMCACHED_DIR=$i - break - fi - done + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/$PHP_LIBDIR/pkgconfig:/usr/$PHP_LIBDIR/pkgconfig:/opt/$PHP_LIBDIR/pkgconfig" fi - if test "$PHP_LIBMEMCACHED_DIR" = "no"; then + if ! $PKG_CONFIG --exists libmemcached; then AC_MSG_ERROR([memcached support requires libmemcached. Use --with-libmemcached-dir= to specify the prefix where libmemcached headers and library are located]) else - AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR]) + PHP_LIBMEMCACHED_VERSION=`$PKG_CONFIG libmemcached --modversion` + PHP_LIBMEMCACHED_DIR=`$PKG_CONFIG libmemcached --variable=prefix` + + AC_MSG_RESULT([found version $PHP_LIBMEMCACHED_VERSION, under $PHP_LIBMEMCACHED_DIR]) - PHP_LIBMEMCACHED_INCDIR="$PHP_LIBMEMCACHED_DIR/include" - PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR) - PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) + PHP_LIBMEMCACHED_LIBS=`$PKG_CONFIG libmemcached --libs` + PHP_LIBMEMCACHED_INCLUDES=`$PKG_CONFIG libmemcached --cflags` + + PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) + PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) ORIG_CFLAGS="$CFLAGS" ORIG_LIBS="$LIBS" - CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" # # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once # - LIBS="$LIBS -lpthread -lmemcached -L$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR" + LIBS="$LIBS -lpthread $PHP_LIBMEMCACHED_LIBS" AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ AC_TRY_COMPILE( @@ -316,7 +320,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_CACHE_CHECK([whether MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS is defined], ac_cv_have_libmemcached_remove_failed_servers, [ AC_TRY_COMPILE( [ #include ], - [ MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS; ], + [ (void)MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS; ], [ ac_cv_have_libmemcached_remove_failed_servers="yes" ], [ ac_cv_have_libmemcached_remove_failed_servers="no" ] ) @@ -325,7 +329,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_CACHE_CHECK([whether MEMCACHED_SERVER_TEMPORARILY_DISABLED is defined], ac_cv_have_libmemcached_server_temporarily_disabled, [ AC_TRY_COMPILE( [ #include ], - [ MEMCACHED_SERVER_TEMPORARILY_DISABLED; ], + [ (void)MEMCACHED_SERVER_TEMPORARILY_DISABLED; ], [ ac_cv_have_libmemcached_server_temporarily_disabled="yes" ], [ ac_cv_have_libmemcached_server_temporarily_disabled="no" ] ) @@ -396,16 +400,8 @@ if test "$PHP_MEMCACHED" != "no"; then if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then AC_MSG_RESULT([enabled]) - AC_MSG_CHECKING([for libmemcachedprotocol]) - if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then - if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcachedprotocol-0.0/handler.h"; then - AC_MSG_ERROR([Can't find libmemcachedprotocol headers under "$PHP_LIBMEMCACHED_DIR"]) - fi - fi - AC_MSG_RESULT([found]) - ORIG_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR" + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [ AC_TRY_COMPILE( @@ -425,12 +421,6 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD) - AC_PATH_PROG(PKG_CONFIG, pkg-config, no) - if test "x$PKG_CONFIG" = "xno"; then - AC_MSG_RESULT([pkg-config not found]) - AC_MSG_ERROR([Please reinstall the pkg-config distribution]) - fi - AC_MSG_CHECKING([for libevent]) if $PKG_CONFIG --exists libevent; then PHP_MEMCACHED_LIBEVENT_VERSION=`$PKG_CONFIG libevent --modversion` @@ -451,6 +441,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi + export PKG_CONFIG_PATH="$ORIG_PKG_CONFIG_PATH" PHP_SUBST(MEMCACHED_SHARED_LIBADD) PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $LIBEVENT_INCLUDES $MSGPACK_INCLUDES) From 23b4e22c24c533a92cba0a3a12d9a8942d9bcf3f Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 16:18:31 +0800 Subject: [PATCH 278/694] This should look a bit better in travis --- .travis.yml | 5 +++- travis.sh | 70 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index e86e7ab0..4e1d2994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,5 +14,8 @@ env: - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.44 +before_script: + - ./travis.sh before_script $LIBMEMCACHED_VERSION + script: - - ./travis.sh $LIBMEMCACHED_VERSION + - ./travis.sh script $LIBMEMCACHED_VERSION diff --git a/travis.sh b/travis.sh index a58c85e1..210bd626 100755 --- a/travis.sh +++ b/travis.sh @@ -99,7 +99,18 @@ function run_memcached_tests() { } # Command line arguments -PHP_LIBMEMCACHED_VERSION=$1 +ACTION=$1 +PHP_LIBMEMCACHED_VERSION=$2 + +if test "x$ACTION" = "x"; then + echo "Usage: $0 " + exit 1 +fi + +if test "x$PHP_LIBMEMCACHED_VERSION" = "x"; then + echo "Usage: $0 " + exit 1 +fi # the extension version PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') @@ -108,34 +119,55 @@ PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" # Check whether to enable building with protoocol support -dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" gt 1.0.15 -if [ $? = 0 ]; then +DPKG=`which dpkg` + +if [ "x$DPKG" = "x" ]; then + echo "dpkg not found, enabling protocol support" ENABLE_PROTOOCOL=yes else - ENABLE_PROTOOCOL=no + dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" gt 1.0.15 + if [ $? = 0 ]; then + ENABLE_PROTOOCOL=yes + else + ENABLE_PROTOOCOL=no + fi fi echo "Enable protocol: $ENABLE_PROTOOCOL" -# validate the package.xml -validate_package_xml || exit 1 - -# exit on error set -e -# Install libmemcached version -install_libmemcached $PHP_LIBMEMCACHED_VERSION $PHP_LIBMEMCACHED_PREFIX $ENABLE_PROTOOCOL +case $ACTION in + before_script) + # validate the package.xml + validate_package_xml || exit 1 + + # Install libmemcached version + install_libmemcached $PHP_LIBMEMCACHED_VERSION $PHP_LIBMEMCACHED_PREFIX $ENABLE_PROTOOCOL + + # Install igbinary extension + install_igbinary + + # install msgpack + install_msgpack + ;; + + script) + # Build the extension + build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL + + # Run tests + set +e + run_memcached_tests $PHP_MEMCACHED_VERSION || exit 1 + ;; + + *) + echo "Unknown action. Valid actions are: before_script and script" + exit 1 + ;; +esac -# Install igbinary extension -install_igbinary -# install msgpack -install_msgpack -# Build the extension -build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL -# Run tests -set +e -run_memcached_tests $PHP_MEMCACHED_VERSION || exit 1 From b227adecdb407d420648ea4204d917ec53a423c9 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 16:40:42 +0800 Subject: [PATCH 279/694] Test for serializers correctly --- php_memcached.c | 2 +- tests/config.inc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 173e8618..cc7721b3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -687,7 +687,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) return; } } - + /* Fetch all remaining results */ memcached_result_st dummy_result; memcached_return dummy_status = MEMCACHED_SUCCESS; diff --git a/tests/config.inc b/tests/config.inc index a750ba79..1e197dbe 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -51,15 +51,15 @@ function memc_get_serializer_options () { $options = memc_create_combinations ('PHP', Memcached::SERIALIZER_PHP); - if (defined ('Memcached::HAVE_IGBINARY')) { + if (Memcached::HAVE_IGBINARY) { $options = array_merge ($options, memc_create_combinations ('igbinary', Memcached::SERIALIZER_IGBINARY)); } - if (defined ('Memcached::HAVE_JSON')) { + if (Memcached::HAVE_JSON) { $options = array_merge ($options, memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true)); } - if (defined ('Memcached::HAVE_MSGPACK')) { + if (Memcached::HAVE_MSGPACK) { $options = array_merge ($options, memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK)); } return $options; From 5a31bd1623b4354824b7eb998d36ab8ccbe0aed6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 17:39:53 +0800 Subject: [PATCH 280/694] copy some tests from experimental to tests. Fix cache read-through callbacks --- package.xml | 5 ++ php_memcached.c | 10 +-- tests/{experimental => }/add.phpt | 0 tests/{experimental => }/append.phpt | 0 tests/{experimental => }/bad_construct.phpt | 0 tests/cachecallback.phpt | 60 +++++++++++++++++ tests/experimental/cachecallback.phpt | 67 ------------------- .../get_badunserialize.phpt | 10 +-- .../{experimental => }/set_badserialize.phpt | 0 9 files changed, 76 insertions(+), 76 deletions(-) rename tests/{experimental => }/add.phpt (100%) rename tests/{experimental => }/append.phpt (100%) rename tests/{experimental => }/bad_construct.phpt (100%) create mode 100644 tests/cachecallback.phpt delete mode 100644 tests/experimental/cachecallback.phpt rename tests/{experimental => }/get_badunserialize.phpt (90%) rename tests/{experimental => }/set_badserialize.phpt (100%) diff --git a/package.xml b/package.xml index def047e2..2cbf3a1e 100644 --- a/package.xml +++ b/package.xml @@ -124,6 +124,11 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + diff --git a/php_memcached.c b/php_memcached.c index cc7721b3..de85fa61 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -670,10 +670,12 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * it to get the value. The CAS token will be 0, because we cannot generate it * ourselves. */ - if (cas_token && status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, - return_value TSRMLS_CC); - ZVAL_DOUBLE(cas_token, 0); + if (cas_token) { + ZVAL_DOUBLE(cas_token, 0.0); + } + + if (status == MEMCACHED_NOTFOUND && fci.size != 0) { + status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, return_value TSRMLS_CC); } if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { diff --git a/tests/experimental/add.phpt b/tests/add.phpt similarity index 100% rename from tests/experimental/add.phpt rename to tests/add.phpt diff --git a/tests/experimental/append.phpt b/tests/append.phpt similarity index 100% rename from tests/experimental/append.phpt rename to tests/append.phpt diff --git a/tests/experimental/bad_construct.phpt b/tests/bad_construct.phpt similarity index 100% rename from tests/experimental/bad_construct.phpt rename to tests/bad_construct.phpt diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt new file mode 100644 index 00000000..585bcd7a --- /dev/null +++ b/tests/cachecallback.phpt @@ -0,0 +1,60 @@ +--TEST-- +Memcached::get() with cache callback +--SKIPIF-- + +--FILE-- +addServer('localhost', 11211, 1); + +$runs = 0; +$m->flush (); + +$first_key = uniqid ('cache_test_'); +$second_key = uniqid ('cache_test_'); +$third_key = uniqid ('cache_test_'); + +var_dump ( +$m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { + $value = "hello"; + $expiration = 10; + return true; + }) +); + +var_dump ($m->get ($first_key)); + +var_dump ( +$m->get ($second_key, function (Memcached $memc, $key, &$value, &$expiration) { + $value = "hello"; + $expiration = 10; + return false; + }) +); + +var_dump ($m->get ($second_key)); + +try { + $m->get ($third_key, function (Memcached $memc, $key, &$value, &$expiration) { + $value = "hello"; + $expiration = 10; + throw new Exception ('this is a test'); + return true; + }); +} catch (Exception $e) { + echo 'Got exception' . PHP_EOL; +} + +var_dump ($m->get ($third_key)); + + +echo "OK" . PHP_EOL; + +--EXPECT-- +string(5) "hello" +string(5) "hello" +bool(false) +bool(false) +Got exception +bool(false) +OK \ No newline at end of file diff --git a/tests/experimental/cachecallback.phpt b/tests/experimental/cachecallback.phpt deleted file mode 100644 index ece92b89..00000000 --- a/tests/experimental/cachecallback.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -Memcached::get() with cache callback ---SKIPIF-- - ---FILE-- -addServer('localhost', 11211, 1); - -$m->delete('foo'); -error_reporting(0); -try { - $v = $m->get('foo', 'the_callback'); - var_dump($v); -} catch (Exception $e) { - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} -error_reporting(E_ALL); -$v = $m->get('foo', 'the_callback'); -var_dump($v); -$v = $m->get('foo', 'the_callback'); -var_dump($v); -$v = $m->get('foo', 'the_callback'); -var_dump($v); - ---EXPECT-- -Miss -string(3) "foo" -NULL - -Exception in callback -Miss -string(3) "foo" -NULL -bool(false) -Miss -string(3) "foo" -NULL -string(3) "ten" -string(3) "ten" diff --git a/tests/experimental/get_badunserialize.phpt b/tests/get_badunserialize.phpt similarity index 90% rename from tests/experimental/get_badunserialize.phpt rename to tests/get_badunserialize.phpt index 1d2c4256..03981bc9 100644 --- a/tests/experimental/get_badunserialize.phpt +++ b/tests/get_badunserialize.phpt @@ -97,14 +97,14 @@ try { echo $e->getMessage(), "\n"; } ---EXPECTF-- +--EXPECT-- bool(true) -Memcached::get(): could not unserialize value%S +Memcached::get(): could not unserialize value 123456 -Memcached::get(): could not unserialize value%S +Memcached::get(): could not unserialize value 123456 -Memcached::get(): could not unserialize value%S +Memcached::get(): could not unserialize value 123456 -Memcached::get(): could not unserialize value%S +Memcached::get(): could not unserialize value 1234 diff --git a/tests/experimental/set_badserialize.phpt b/tests/set_badserialize.phpt similarity index 100% rename from tests/experimental/set_badserialize.phpt rename to tests/set_badserialize.phpt From d0d7d9089e670d681c321767bfc7fc2c799776ce Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 17:40:50 +0800 Subject: [PATCH 281/694] Add missing tests --- package.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 2cbf3a1e..b04398eb 100644 --- a/package.xml +++ b/package.xml @@ -128,7 +128,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> - + + From 16f866154051d22f56d3f454dc99e166af17d909 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 17:47:11 +0800 Subject: [PATCH 282/694] Fix unserializer test --- php_memcached.c | 1 + tests/get_badunserialize.phpt | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index de85fa61..53903926 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3465,6 +3465,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ #ifdef HAVE_MEMCACHED_MSGPACK php_msgpack_unserialize(value, pl, payload_len TSRMLS_CC); #else + ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); goto my_error; #endif diff --git a/tests/get_badunserialize.phpt b/tests/get_badunserialize.phpt index 03981bc9..1d2c4256 100644 --- a/tests/get_badunserialize.phpt +++ b/tests/get_badunserialize.phpt @@ -97,14 +97,14 @@ try { echo $e->getMessage(), "\n"; } ---EXPECT-- +--EXPECTF-- bool(true) -Memcached::get(): could not unserialize value +Memcached::get(): could not unserialize value%S 123456 -Memcached::get(): could not unserialize value +Memcached::get(): could not unserialize value%S 123456 -Memcached::get(): could not unserialize value +Memcached::get(): could not unserialize value%S 123456 -Memcached::get(): could not unserialize value +Memcached::get(): could not unserialize value%S 1234 From b183f7feafcce8aa7ee7132dfbb66c51c8722e9d Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 17:59:55 +0800 Subject: [PATCH 283/694] Add more serializer tests --- package.xml | 5 +- tests/config.inc | 95 ++++++++++++++++++++ tests/get_bad_unserialize_igbinary.phpt | 35 ++++++++ tests/get_bad_unserialize_json.phpt | 35 ++++++++ tests/get_bad_unserialize_msgpack.phpt | 35 ++++++++ tests/get_bad_unserialize_php.phpt | 32 +++++++ tests/get_badunserialize.phpt | 110 ------------------------ 7 files changed, 236 insertions(+), 111 deletions(-) create mode 100644 tests/get_bad_unserialize_igbinary.phpt create mode 100644 tests/get_bad_unserialize_json.phpt create mode 100644 tests/get_bad_unserialize_msgpack.phpt create mode 100644 tests/get_bad_unserialize_php.phpt delete mode 100644 tests/get_badunserialize.phpt diff --git a/package.xml b/package.xml index b04398eb..5b6db241 100644 --- a/package.xml +++ b/package.xml @@ -127,7 +127,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> - + + + + diff --git a/tests/config.inc b/tests/config.inc index 1e197dbe..6b69b3fd 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -63,4 +63,99 @@ function memc_get_serializer_options () $options = array_merge ($options, memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK)); } return $options; +} + +class Foo implements Serializable { + public $serialize_throws = false; + + public function __sleep() { + if ($this->serialize_throws) { + throw new Exception("12"); + } + return array(); + } + + public function __wakeup() { + throw new Exception("1234567890"); + } + + public function serialize() { + if ($this->serialize_throws) { + throw new Exception("1234"); + } + return "1234"; + } + + public function unserialize($str) { + throw new Exception("123456"); + } +} + + +function mycb(Memcached $memc, $key, &$value) { + $value = new Foo(); + $value->serialize_throws = true; + return 1; +} + +function test_bad_unserialize ($m, $options) +{ + echo "-- NEW TEST" . PHP_EOL; + + var_dump($m->set('foo', new Foo(), 10)); + error_reporting(0); + + try { + var_dump($m->get('foo')); + } catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $php_errormsg, "\n"; + echo $e->getMessage(), "\n"; + } + + try { + $cas = null; + var_dump($m->get('foo', 'mycb', $cas)); + } catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $php_errormsg, "\n"; + echo $e->getMessage(), "\n"; + } + + try { + var_dump($m->get('foo', 'mycb')); + } catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $php_errormsg, "\n"; + echo $e->getMessage(), "\n"; + } + + $m->delete('foo'); + try { + var_dump($m->get('foo', 'mycb')); + } catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $php_errormsg, "\n"; + echo $e->getMessage(), "\n"; + } } \ No newline at end of file diff --git a/tests/get_bad_unserialize_igbinary.phpt b/tests/get_bad_unserialize_igbinary.phpt new file mode 100644 index 00000000..892e98ac --- /dev/null +++ b/tests/get_bad_unserialize_igbinary.phpt @@ -0,0 +1,35 @@ +--TEST-- +Memcached::get() with bad unserialize with igbinary serializer +--SKIPIF-- + +--FILE-- + +--FILE-- + +--FILE-- + +--FILE-- + ---FILE-- -addServer('localhost', 11211, 1); - -class Foo implements Serializable { - public $serialize_throws = false; - - public function __sleep() { - if ($this->serialize_throws) { - throw new Exception("12"); - } - return array(); - } - - public function __wakeup() { - throw new Exception("1234567890"); - } - - public function serialize() { - if ($this->serialize_throws) { - throw new Exception("1234"); - } - return "1234"; - } - - public function unserialize($str) { - throw new Exception("123456"); - } -} - - -function mycb(Memcached $memc, $key, &$value) { - $value = new Foo(); - $value->serialize_throws = true; - return 1; -} - -var_dump($m->set('foo', new Foo(), 10)); -error_reporting(0); - -try { - var_dump($m->get('foo')); -} catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} - -try { - $cas = null; - var_dump($m->get('foo', 'mycb', $cas)); -} catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} - -try { - var_dump($m->get('foo', 'mycb')); -} catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} - -$m->delete('foo'); -try { - var_dump($m->get('foo', 'mycb')); -} catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} - ---EXPECTF-- -bool(true) -Memcached::get(): could not unserialize value%S -123456 -Memcached::get(): could not unserialize value%S -123456 -Memcached::get(): could not unserialize value%S -123456 -Memcached::get(): could not unserialize value%S -1234 - From 494452486b313968446a5f7870a23bd334f28bd4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 18:09:24 +0800 Subject: [PATCH 284/694] The serializers behave too differently for this --- package.xml | 5 -- tests/config.inc | 95 ------------------------- tests/get_bad_unserialize_igbinary.phpt | 35 --------- tests/get_bad_unserialize_json.phpt | 35 --------- tests/get_bad_unserialize_msgpack.phpt | 35 --------- tests/get_bad_unserialize_php.phpt | 32 --------- tests/set_badserialize.phpt | 47 ------------ 7 files changed, 284 deletions(-) delete mode 100644 tests/get_bad_unserialize_igbinary.phpt delete mode 100644 tests/get_bad_unserialize_json.phpt delete mode 100644 tests/get_bad_unserialize_msgpack.phpt delete mode 100644 tests/get_bad_unserialize_php.phpt delete mode 100644 tests/set_badserialize.phpt diff --git a/package.xml b/package.xml index 5b6db241..09264de6 100644 --- a/package.xml +++ b/package.xml @@ -127,11 +127,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - - - - diff --git a/tests/config.inc b/tests/config.inc index 6b69b3fd..41f6b17f 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -64,98 +64,3 @@ function memc_get_serializer_options () } return $options; } - -class Foo implements Serializable { - public $serialize_throws = false; - - public function __sleep() { - if ($this->serialize_throws) { - throw new Exception("12"); - } - return array(); - } - - public function __wakeup() { - throw new Exception("1234567890"); - } - - public function serialize() { - if ($this->serialize_throws) { - throw new Exception("1234"); - } - return "1234"; - } - - public function unserialize($str) { - throw new Exception("123456"); - } -} - - -function mycb(Memcached $memc, $key, &$value) { - $value = new Foo(); - $value->serialize_throws = true; - return 1; -} - -function test_bad_unserialize ($m, $options) -{ - echo "-- NEW TEST" . PHP_EOL; - - var_dump($m->set('foo', new Foo(), 10)); - error_reporting(0); - - try { - var_dump($m->get('foo')); - } catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; - } - - try { - $cas = null; - var_dump($m->get('foo', 'mycb', $cas)); - } catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; - } - - try { - var_dump($m->get('foo', 'mycb')); - } catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; - } - - $m->delete('foo'); - try { - var_dump($m->get('foo', 'mycb')); - } catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; - } -} \ No newline at end of file diff --git a/tests/get_bad_unserialize_igbinary.phpt b/tests/get_bad_unserialize_igbinary.phpt deleted file mode 100644 index 892e98ac..00000000 --- a/tests/get_bad_unserialize_igbinary.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -Memcached::get() with bad unserialize with igbinary serializer ---SKIPIF-- - ---FILE-- - ---FILE-- - ---FILE-- - ---FILE-- - ---FILE-- -addServer('localhost', 11211, 1); - -class Foo implements Serializable { - public function __sleep() { - throw new Exception("12"); - } - - public function __wakeup() { - throw new Exception("1234567890"); - } - - public function serialize() { - throw new Exception("1234"); - } - - public function unserialize($str) { - throw new Exception("123456"); - } -} - -error_reporting(0); -$m->set('foo', 10, 10); -try { - var_dump($m->set('foo', new Foo(), 10)); -} catch (Exception $e) { - if (version_compare(phpversion(), "5.3.0", ">=")) { - if ($e->getPrevious()) { - $e = $e->getPrevious(); - } - } - - echo $php_errormsg, "\n"; - echo $e->getMessage(), "\n"; -} -var_dump($m->get('foo')); - ---EXPECT-- - -1234 -int(10) From c699b3eee311e5a524321c40fc8de18c43654161 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 18:17:02 +0800 Subject: [PATCH 285/694] More tests --- package.xml | 8 ++++++++ tests/{experimental => }/getmulti.phpt | 0 tests/{experimental => }/incrdecr.phpt | 0 tests/{experimental => }/incrdecr_bykey.phpt | 0 tests/{experimental => }/incrdecr_initial.phpt | 0 tests/{experimental => }/incrdecr_invalid_key.phpt | 0 tests/{experimental => }/prepend.phpt | 0 tests/{experimental => }/replace.phpt | 5 +---- tests/{experimental => }/setmulti.phpt | 0 9 files changed, 9 insertions(+), 4 deletions(-) rename tests/{experimental => }/getmulti.phpt (100%) rename tests/{experimental => }/incrdecr.phpt (100%) rename tests/{experimental => }/incrdecr_bykey.phpt (100%) rename tests/{experimental => }/incrdecr_initial.phpt (100%) rename tests/{experimental => }/incrdecr_invalid_key.phpt (100%) rename tests/{experimental => }/prepend.phpt (100%) rename tests/{experimental => }/replace.phpt (87%) rename tests/{experimental => }/setmulti.phpt (100%) diff --git a/package.xml b/package.xml index 09264de6..10947cfe 100644 --- a/package.xml +++ b/package.xml @@ -127,7 +127,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + + + + diff --git a/tests/experimental/getmulti.phpt b/tests/getmulti.phpt similarity index 100% rename from tests/experimental/getmulti.phpt rename to tests/getmulti.phpt diff --git a/tests/experimental/incrdecr.phpt b/tests/incrdecr.phpt similarity index 100% rename from tests/experimental/incrdecr.phpt rename to tests/incrdecr.phpt diff --git a/tests/experimental/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt similarity index 100% rename from tests/experimental/incrdecr_bykey.phpt rename to tests/incrdecr_bykey.phpt diff --git a/tests/experimental/incrdecr_initial.phpt b/tests/incrdecr_initial.phpt similarity index 100% rename from tests/experimental/incrdecr_initial.phpt rename to tests/incrdecr_initial.phpt diff --git a/tests/experimental/incrdecr_invalid_key.phpt b/tests/incrdecr_invalid_key.phpt similarity index 100% rename from tests/experimental/incrdecr_invalid_key.phpt rename to tests/incrdecr_invalid_key.phpt diff --git a/tests/experimental/prepend.phpt b/tests/prepend.phpt similarity index 100% rename from tests/experimental/prepend.phpt rename to tests/prepend.phpt diff --git a/tests/experimental/replace.phpt b/tests/replace.phpt similarity index 87% rename from tests/experimental/replace.phpt rename to tests/replace.phpt index dcf78a46..b0d53f41 100644 --- a/tests/experimental/replace.phpt +++ b/tests/replace.phpt @@ -6,20 +6,17 @@ Memcached::replace() addServer('localhost', 11211, 1); -error_reporting(0); $m->delete('foo'); var_dump($m->replace('foo', 'bar', 60)); -echo $php_errormsg, "\n"; var_dump($m->get('foo')); $m->set('foo', 'kef'); var_dump($m->replace('foo', 'bar', 60)); var_dump($m->get('foo')); ---EXPECTF-- +--EXPECT-- bool(false) - bool(false) bool(true) string(3) "bar" diff --git a/tests/experimental/setmulti.phpt b/tests/setmulti.phpt similarity index 100% rename from tests/experimental/setmulti.phpt rename to tests/setmulti.phpt From 8ded4bd9945f106d1b3a3ac3c8fc54d0902bbea5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 19 Nov 2013 18:23:52 +0800 Subject: [PATCH 286/694] Fix side-effects' --- tests/pr_75.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pr_75.phpt b/tests/pr_75.phpt index 949c3883..37e48d0f 100644 --- a/tests/pr_75.phpt +++ b/tests/pr_75.phpt @@ -7,6 +7,7 @@ Wrong return values for binary protocol $client = new Memcached(); $client->addServer ('127.0.0.1', 11211); $client->setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$client->flush (); $client->set('key1', 'value1'); echo "set result code: ".$client->getResultCode()."\n"; From 3bd98ddc2b3d9cc28323484254ab2af63eadb7e6 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 Nov 2013 11:44:05 +0100 Subject: [PATCH 287/694] don't run this test for msgpack (object type lost on unserialize) --- tests/config.inc | 6 +++--- tests/types.phpt | 2 +- tests/types_multi.phpt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/config.inc b/tests/config.inc index 1e197dbe..7972cb75 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -47,7 +47,7 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ); } -function memc_get_serializer_options () +function memc_get_serializer_options ($skipmsgpack=false) { $options = memc_create_combinations ('PHP', Memcached::SERIALIZER_PHP); @@ -59,8 +59,8 @@ function memc_get_serializer_options () $options = array_merge ($options, memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true)); } - if (Memcached::HAVE_MSGPACK) { + if (Memcached::HAVE_MSGPACK && !$skipmsgpack) { $options = array_merge ($options, memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK)); } return $options; -} \ No newline at end of file +} diff --git a/tests/types.phpt b/tests/types.phpt index c5b19c0d..6c0a5d03 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -77,7 +77,7 @@ function types_simple_test ($m, $options) } } -memc_run_test ('types_simple_test', memc_get_serializer_options ()); +memc_run_test ('types_simple_test', memc_get_serializer_options (true)); ?> --EXPECT-- diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt index 46bc5f76..51f6fd5a 100644 --- a/tests/types_multi.phpt +++ b/tests/types_multi.phpt @@ -66,8 +66,8 @@ function types_test ($m, $options) } } -memc_run_test ('types_test', memc_get_serializer_options ()); +memc_run_test ('types_test', memc_get_serializer_options (true)); ?> --EXPECT-- -TEST DONE \ No newline at end of file +TEST DONE From 64651de0cbc50dec29c14b2be48722e40b3958e5 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 Nov 2013 11:53:44 +0100 Subject: [PATCH 288/694] issue fix in msgpack --- tests/types.phpt | 2 +- tests/types_multi.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/types.phpt b/tests/types.phpt index 6c0a5d03..b91d94f9 100644 --- a/tests/types.phpt +++ b/tests/types.phpt @@ -77,7 +77,7 @@ function types_simple_test ($m, $options) } } -memc_run_test ('types_simple_test', memc_get_serializer_options (true)); +memc_run_test ('types_simple_test', memc_get_serializer_options (version_compare(phpversion("msgpack"), "0.5.5", "<="))); ?> --EXPECT-- diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt index 51f6fd5a..0d49bd1b 100644 --- a/tests/types_multi.phpt +++ b/tests/types_multi.phpt @@ -66,7 +66,7 @@ function types_test ($m, $options) } } -memc_run_test ('types_test', memc_get_serializer_options (true)); +memc_run_test ('types_test', memc_get_serializer_options (version_compare(phpversion("msgpack"), "0.5.5", "<="))); ?> --EXPECT-- From 39f70b909bcc8657529a7d01895b7775e6a05f13 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 Nov 2013 15:13:27 +0100 Subject: [PATCH 289/694] warning: suggest parentheses around assignment used as truth value [-Wparentheses] --- g_fmt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/g_fmt.c b/g_fmt.c index c904e653..f8aacd65 100644 --- a/g_fmt.c +++ b/g_fmt.c @@ -48,14 +48,14 @@ char *php_memcached_g_fmt(register char *b, double x) { if (sign) *b++ = '-'; if (decpt == 9999) /* Infinity or Nan */ { - while(*b++ = *s++); + while((*b++ = *s++)); goto done0; } if (decpt <= -4 || decpt > se - s + 5) { *b++ = *s++; if (*s) { *b++ = '.'; - while(*b = *s++) + while((*b = *s++)) b++; } *b++ = 'e'; @@ -80,9 +80,9 @@ char *php_memcached_g_fmt(register char *b, double x) { *b++ = '.'; for(; decpt < 0; decpt++) *b++ = '0'; - while(*b++ = *s++); + while((*b++ = *s++)); } else { - while(*b = *s++) { + while((*b = *s++)) { b++; if (--decpt == 0 && *s) *b++ = '.'; From ec9fad45365d612285119b1258103869aad923e4 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 Nov 2013 15:13:55 +0100 Subject: [PATCH 290/694] Fix warning: label 'done' defined but not used [-Wunused-label] --- g_fmt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/g_fmt.c b/g_fmt.c index f8aacd65..73f82fd0 100644 --- a/g_fmt.c +++ b/g_fmt.c @@ -94,6 +94,8 @@ char *php_memcached_g_fmt(register char *b, double x) { done0: zend_freedtoa(s0); +#ifdef IGNORE_ZERO_SIGN done: +#endif return b0; } From 61896ac1271412479dbd5d5a0433776d16d425be Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 Nov 2013 15:17:35 +0100 Subject: [PATCH 291/694] Fix: warning: 'plist_key_len' may be used uninitialized in this function [-Wmaybe-uninitialized] (false positive, juste to make gcc happy) --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 91d431f4..9d538cfa 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -116,7 +116,7 @@ PS_OPEN_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); memcached_return status; char *p, *plist_key = NULL; - int plist_key_len; + int plist_key_len = 0; if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { zend_rsrc_list_entry *le = NULL; From d142a68dfeaf0ede909d9e49d78e1f41c6e98716 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 00:34:15 +0800 Subject: [PATCH 292/694] Refactor tests to configure server address in one place. Also flush server every time so that we start from a clean slate --- tests/add.phpt | 4 ++-- tests/append.phpt | 4 ++-- tests/bad_construct.phpt | 15 +++++++++++++++ tests/bug_16959.phpt | 7 ++++--- tests/bug_17137.phpt | 20 ++++++++++++-------- tests/bug_18639.phpt | 5 ++--- tests/cachecallback.phpt | 5 ++--- tests/cas.phpt | 4 ++-- tests/cas_multi.phpt | 4 ++-- tests/compression_types.phpt | 4 ++-- tests/conf_persist.phpt | 8 +++++--- tests/config.inc | 15 ++++++--------- tests/deleted.phpt | 4 ++-- tests/deletemulti.phpt | 7 ++----- tests/deletemultitypes.phpt | 6 ++---- tests/expire.phpt | 12 ++++++------ tests/flush_buffers.phpt | 13 +++++++------ tests/getdelayed.phpt | 4 ++-- tests/getmulti.phpt | 4 ++-- tests/gh_21.phpt | 4 +++- tests/gh_77.phpt | 8 ++------ tests/gh_90.phpt | 10 ++++------ tests/gh_93.phpt | 7 ++++--- tests/incrdecr.phpt | 4 ++-- tests/incrdecr_bykey.phpt | 4 ++-- tests/incrdecr_initial.phpt | 7 ++++--- tests/incrdecr_invalid_key.phpt | 4 ++-- tests/invoke_callback.phpt | 4 +++- tests/localserver.phpt | 4 ++-- tests/multi_order.phpt | 6 +++--- tests/pr_75.phpt | 11 ++++++----- tests/prepend.phpt | 8 +++----- tests/replace.phpt | 4 ++-- tests/rescode.phpt | 8 +++++--- tests/session_badconf_emptyprefix.phpt | 6 ++++-- tests/session_badconf_prefix.phpt | 6 ++++-- tests/session_badconf_servers.phpt | 6 ++++-- tests/session_basic.phpt | 6 ++++-- tests/set_large.phpt | 4 ++-- tests/setmulti.phpt | 5 ++--- tests/touch_binary.phpt | 5 ++--- tests/undefined_set.phpt | 4 ++-- tests/user-flags.phpt | 5 ++--- tests/vbucket.phpt | 9 ++++----- tests/version.phpt | 6 +++--- 45 files changed, 159 insertions(+), 141 deletions(-) diff --git a/tests/add.phpt b/tests/add.phpt index 0a6dd88c..3d8fcff2 100644 --- a/tests/add.phpt +++ b/tests/add.phpt @@ -4,8 +4,8 @@ Memcached::add() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); var_dump($m->add('foo', 1, 60)); diff --git a/tests/append.phpt b/tests/append.phpt index 02c30b4f..b4964357 100644 --- a/tests/append.phpt +++ b/tests/append.phpt @@ -4,8 +4,8 @@ Memcached::append() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); error_reporting(0); $m->delete('foo'); diff --git a/tests/bad_construct.phpt b/tests/bad_construct.phpt index efa40cec..06bc7236 100644 --- a/tests/bad_construct.phpt +++ b/tests/bad_construct.phpt @@ -9,6 +9,21 @@ $m = new Memcached((object)array()); echo $php_errormsg, "\n"; var_dump($m); +class extended extends Memcached { + public function __construct () { + } +} + +error_reporting(E_ALL); +$extended = new extended (); +var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); + +echo "OK" . PHP_EOL; + --EXPECTF-- Memcached::__construct() expects parameter %s NULL + +Warning: Memcached::setOption(): Memcached constructor was not called in %s on line %d +NULL +OK \ No newline at end of file diff --git a/tests/bug_16959.phpt b/tests/bug_16959.phpt index 0c5e47ea..f03a7091 100644 --- a/tests/bug_16959.phpt +++ b/tests/bug_16959.phpt @@ -4,9 +4,10 @@ Memcached: Bug #16959 (getMulti + BINARY_PROTOCOL problem) --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$cache->addServer('localhost', 11211); +include dirname (__FILE__) . '/config.inc'; +$cache = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true + )); $cache->set('key_0', 'value0'); $cache->set('key_0_additional', 'value0_additional'); diff --git a/tests/bug_17137.phpt b/tests/bug_17137.phpt index 276d6661..28f55d00 100644 --- a/tests/bug_17137.phpt +++ b/tests/bug_17137.phpt @@ -4,20 +4,24 @@ Change prefix, pecl bug #17137 --FILE-- addServer('127.0.0.1', 11211); -$memcache->setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$memcache->setOption(Memcached::OPT_PREFIX_KEY, 'prefix1'); +include dirname (__FILE__) . '/config.inc'; +$memcache = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true, + Memcached::OPT_PREFIX_KEY => 'prefix1', + )); + +$memcache2 = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true, + Memcached::OPT_PREFIX_KEY => 'prefix2', + )); + var_dump($memcache->getOption(Memcached::OPT_PREFIX_KEY)); var_dump($memcache->set('test', "val_prefix1", 120)); var_dump($memcache->get('test')); -$memcache2 = new Memcached(); -$memcache2->addServer('127.0.0.1', 11211); -$memcache2->setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$memcache2->setOption(Memcached::OPT_PREFIX_KEY, 'prefix2'); + var_dump($memcache2->getOption(Memcached::OPT_PREFIX_KEY)); var_dump($memcache2->set('test', "val_prefix2", 120)); diff --git a/tests/bug_18639.phpt b/tests/bug_18639.phpt index da3519b1..46801b6c 100644 --- a/tests/bug_18639.phpt +++ b/tests/bug_18639.phpt @@ -4,10 +4,9 @@ Memcached::getServerByKey(): Bug pecl#18639 (Segfault in getServerByKey) --FILE-- addServer('127.0.0.1', 11211); var_dump($m->set('test', 'test1')); var_dump($m->getServerByKey('1')); diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 585bcd7a..9fe8f4f8 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -4,11 +4,10 @@ Memcached::get() with cache callback --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $runs = 0; -$m->flush (); $first_key = uniqid ('cache_test_'); $second_key = uniqid ('cache_test_'); diff --git a/tests/cas.phpt b/tests/cas.phpt index 09b436e0..e9990798 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -4,8 +4,8 @@ Memcached fetch cas & set cas --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $m->delete('cas_test'); $cas_token = null; diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index e4c9e0f3..240ecadd 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -4,8 +4,8 @@ Memcached multi fetch cas & set cas --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'cas_test_1' => 1, diff --git a/tests/compression_types.phpt b/tests/compression_types.phpt index e441db81..a7c8a219 100644 --- a/tests/compression_types.phpt +++ b/tests/compression_types.phpt @@ -4,8 +4,8 @@ Memcached compression test --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $data = file_get_contents(dirname(__FILE__) . '/testdata.res'); diff --git a/tests/conf_persist.phpt b/tests/conf_persist.phpt index eb4895b4..3b896a2b 100644 --- a/tests/conf_persist.phpt +++ b/tests/conf_persist.phpt @@ -4,9 +4,11 @@ Conf settings persist. --FILE-- setOption(Memcached::OPT_PREFIX_KEY, 'php'); -$m1->addServer('localhost', 11211); +include dirname (__FILE__) . '/config.inc'; +$m1 = memc_get_instance (array ( + Memcached::OPT_PREFIX_KEY => 'php' +), 'id1'); + $m1->set('foo', 'bar'); for ($i = 1000; $i > 0; $i--) { diff --git a/tests/config.inc b/tests/config.inc index 41f6b17f..5641e027 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -3,9 +3,12 @@ define ("MEMC_SERVER_HOST", "127.0.0.1"); define ("MEMC_SERVER_PORT", 11211); -function memc_get_instance () +function memc_get_instance (array $opts = array (), $persistent_id = null) { - $memcached = new Memcached(); + $memcached = new Memcached($persistent_id); + if ($memcached->setOptions ($opts) == false) + echo "Failed to set options" . PHP_EOL; + $memcached->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); $memcached->flush (); return $memcached; @@ -14,13 +17,7 @@ function memc_get_instance () function memc_run_test ($test_function, $options = array ()) { foreach ($options as $option_set) { - $memc = memc_get_instance (); - - foreach ($option_set ['options'] as $key => $value) { - if ($memc->setOption ($key, $value) == false) { - die ('Failed to set option: ' . $key); - } - } + $memc = memc_get_instance ($option_set ['options']); $test_function ($memc, $option_set); } echo "TEST DONE" . PHP_EOL; diff --git a/tests/deleted.phpt b/tests/deleted.phpt index ec79cd0e..6b5bae1a 100644 --- a/tests/deleted.phpt +++ b/tests/deleted.phpt @@ -4,8 +4,8 @@ Memcached store & fetch type correctness --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $m->set('eisaleeoo', "foo"); $m->delete('eisaleeoo'); diff --git a/tests/deletemulti.phpt b/tests/deletemulti.phpt index 94c59c6b..7c9f308b 100644 --- a/tests/deletemulti.phpt +++ b/tests/deletemulti.phpt @@ -4,11 +4,8 @@ Delete multi --FILE-- addServer('127.0.0.1', 11211, 1); -$m->addServer('localhost', 11211, 1); - -$m->flush(); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); function has_all_keys($keys, $array, $check_true = false) { diff --git a/tests/deletemultitypes.phpt b/tests/deletemultitypes.phpt index a72205b6..0063e5f8 100644 --- a/tests/deletemultitypes.phpt +++ b/tests/deletemultitypes.phpt @@ -4,10 +4,8 @@ Delete multi key types --FILE-- addServer('127.0.0.1', 11211, 1); - -$m->flush(); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); function dump_types($v, $k) { echo gettype($v) . "\n"; diff --git a/tests/expire.phpt b/tests/expire.phpt index d6817233..92a63bf3 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -7,6 +7,8 @@ https://code.google.com/p/memcached/issues/detail?id=275 --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$m->addServer('127.0.0.1', 11211, 1); +$m = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true + )); echo '-- binary protocol' . PHP_EOL; run_expiry_test ($m); -$m = new Memcached(); -$m->addServer('127.0.0.1', 11211, 1); +$m = memc_get_instance (); echo '-- text protocol' . PHP_EOL; run_expiry_test ($m); diff --git a/tests/flush_buffers.phpt b/tests/flush_buffers.phpt index 9bff077b..989a4b63 100644 --- a/tests/flush_buffers.phpt +++ b/tests/flush_buffers.phpt @@ -4,17 +4,18 @@ Test flushing buffers --FILE-- addServer('127.0.0.1', 11211); -$m->setOption(Memcached::OPT_NO_BLOCK, 1); -$m->setOption(Memcached::OPT_BUFFER_WRITES, 1); + +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (array ( + Memcached::OPT_NO_BLOCK => 1, + Memcached::OPT_BUFFER_WRITES => 1, + )); $key = uniqid ('flush_key_'); var_dump ($m->set($key, 'test_val')); -$m2 = new Memcached(); -$m2->addServer('127.0.0.1', 11211); +$m2 = memc_get_instance (); var_dump ($m2->get ($key)); var_dump ($m->flushBuffers ()); diff --git a/tests/getdelayed.phpt b/tests/getdelayed.phpt index 70973458..7479e97b 100644 --- a/tests/getdelayed.phpt +++ b/tests/getdelayed.phpt @@ -4,8 +4,8 @@ Memcached getDelayed callback --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/getmulti.phpt b/tests/getmulti.phpt index 8d2d7a82..a32583ea 100644 --- a/tests/getmulti.phpt +++ b/tests/getmulti.phpt @@ -4,8 +4,8 @@ Memcached::getMulti() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); class Foo { function __toString() { diff --git a/tests/gh_21.phpt b/tests/gh_21.phpt index 14505d39..7302220e 100644 --- a/tests/gh_21.phpt +++ b/tests/gh_21.phpt @@ -4,9 +4,11 @@ Test for Github issue 21 --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, true); diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 9aedf296..ead8803d 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -6,15 +6,11 @@ Test for Github issue #77 ?> --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$mc = memc_get_instance (); $key = uniqid ("this_does_not_exist_"); -$mc = new \Memcached(); -$mc->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); -$mc->addServer("127.0.0.1", 11211); - $mc->touch($key, 5); var_dump ($mc->getResultCode() == Memcached::RES_NOTFOUND); $mc->set($key, 1, 5); diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt index 4eb9bedb..9434a2d7 100644 --- a/tests/gh_90.phpt +++ b/tests/gh_90.phpt @@ -4,12 +4,10 @@ Test for GH #90 --FILE-- setOptions(array(memcached::OPT_BINARY_PROTOCOL => true)); - $memcached->addServers(array(array('127.0.0.1', 11211, 100))); -} +include dirname (__FILE__) . '/config.inc'; +$memcached = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true + )); // Create a key for use as a lock. If this key already exists, wait till it doesn't exist. { diff --git a/tests/gh_93.phpt b/tests/gh_93.phpt index cf718b9f..fb7e61f9 100644 --- a/tests/gh_93.phpt +++ b/tests/gh_93.phpt @@ -4,9 +4,10 @@ Test for Github issue #93 (double and long overflow) --FILE-- addServer('127.0.0.1', 11211, 1); -$m->setOption(Memcached::OPT_COMPRESSION, false); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (array ( + Memcached::OPT_COMPRESSION => false + )); function testOverflow($m, $value) { $m->delete('overflow'); diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index b38e3813..3addcfd3 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -4,8 +4,8 @@ Memcached::increment() Memcached::decrement() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); echo "Not there\n"; $m->delete('foo'); diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index ea2bd803..9986b7dc 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -4,8 +4,8 @@ Memcached::incrementByKey() Memcached::decrementByKey() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); echo "Not there\n"; $m->delete('foo'); diff --git a/tests/incrdecr_initial.phpt b/tests/incrdecr_initial.phpt index 63d8d008..b5530707 100644 --- a/tests/incrdecr_initial.phpt +++ b/tests/incrdecr_initial.phpt @@ -4,9 +4,10 @@ Memcached::increment() Memcached::decrement() with initial support --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL, 1); -$m->addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true + )); $m->delete('foo'); var_dump($m->increment('foo', 1, 1)); diff --git a/tests/incrdecr_invalid_key.phpt b/tests/incrdecr_invalid_key.phpt index 9191a791..8d4ab671 100644 --- a/tests/incrdecr_invalid_key.phpt +++ b/tests/incrdecr_invalid_key.phpt @@ -4,8 +4,8 @@ Memcached::increment() Memcached::decrement() with invalid key --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); var_dump($m->increment('', 1)); var_dump($m->decrement('', 1)); diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index d5d0cc90..55cbec1e 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -5,9 +5,11 @@ Test that callback is invoked on new object --FILE-- addServer("127.0.0.1", 11211); + $obj->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); } $m = new Memcached('hi', 'my_func'); diff --git a/tests/localserver.phpt b/tests/localserver.phpt index cacf310f..22872070 100644 --- a/tests/localserver.phpt +++ b/tests/localserver.phpt @@ -4,8 +4,8 @@ Memcached local server test --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $m->set($key, array( diff --git a/tests/multi_order.phpt b/tests/multi_order.phpt index ebdb69e8..4fd5f5b4 100644 --- a/tests/multi_order.phpt +++ b/tests/multi_order.phpt @@ -4,9 +4,9 @@ Memcached GET_PRESERVE_ORDER flag in getMulti --FILE-- addServer('127.0.0.1', 11211, 1); -$m->addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); +$m->addServer (MEMC_SERVER_HOST, MEMC_SERVER_PORT); $data = array( 'foo' => 'foo-data', diff --git a/tests/pr_75.phpt b/tests/pr_75.phpt index 37e48d0f..610e2c7e 100644 --- a/tests/pr_75.phpt +++ b/tests/pr_75.phpt @@ -4,10 +4,10 @@ Wrong return values for binary protocol --FILE-- addServer ('127.0.0.1', 11211); -$client->setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$client->flush (); +include dirname (__FILE__) . '/config.inc'; +$client = memc_get_instance (array ( + Memcached::OPT_BINARY_PROTOCOL => true + )); $client->set('key1', 'value1'); echo "set result code: ".$client->getResultCode()."\n"; @@ -15,7 +15,7 @@ echo "set result code: ".$client->getResultCode()."\n"; $value = $client->get('key1'); echo "got $value with result code: ".$client->getResultCode()."\n"; -$client->add('key2', 'value2'); +var_dump ($client->add('key2', 'value2')); echo "add result code: ".$client->getResultCode()."\n"; echo "OK\n"; @@ -24,5 +24,6 @@ echo "OK\n"; --EXPECT-- set result code: 0 got value1 with result code: 0 +bool(true) add result code: 0 OK \ No newline at end of file diff --git a/tests/prepend.phpt b/tests/prepend.phpt index 141468b1..9e77201e 100644 --- a/tests/prepend.phpt +++ b/tests/prepend.phpt @@ -4,14 +4,12 @@ Memcached::prepend() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); -error_reporting(0); $m->delete('foo'); $m->setOption(Memcached::OPT_COMPRESSION, true); var_dump($m->prepend('foo', 'a')); -echo $php_errormsg, "\n"; $m->setOption(Memcached::OPT_COMPRESSION, false); $m->delete('foo'); @@ -22,8 +20,8 @@ var_dump($m->prepend('foo', 'b')); var_dump($m->get('foo')); --EXPECTF-- +Warning: Memcached::prepend(): cannot append/prepend with compression turned on in %s on line %d NULL -%s: cannot append/prepend with compression turned on bool(false) bool(false) bool(true) diff --git a/tests/replace.phpt b/tests/replace.phpt index b0d53f41..3f4f1e92 100644 --- a/tests/replace.phpt +++ b/tests/replace.phpt @@ -4,8 +4,8 @@ Memcached::replace() --FILE-- addServer('localhost', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); var_dump($m->replace('foo', 'bar', 60)); diff --git a/tests/rescode.phpt b/tests/rescode.phpt index 1bfd3ec0..fbda4f78 100644 --- a/tests/rescode.phpt +++ b/tests/rescode.phpt @@ -4,10 +4,12 @@ Memcached result codes. --FILE-- getResultMessage(), "\n"; -$m->addServer('127.0.0.1', 11211, 1); +$m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT, 1); echo $m->getResultCode(), "\n"; echo $m->getResultMessage(), "\n"; @@ -39,8 +41,8 @@ echo $m2->getResultCode(), "\n"; echo $m2->getResultMessage(), "\n"; var_dump($m->getResultCode() == $code); -$m = new Memcached('test1'); -$m->addServer('127.0.0.1', 11211); + +$m = memc_get_instance (array (), 'test1'); $m2 = new Memcached('test1'); $m->delete('moikkamitakuuluu'); diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index 8dad7386..74d681dd 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -9,11 +9,13 @@ if (!Memcached::HAVE_SESSION) print "skip"; memcached.sess_locking = on memcached.sess_lock_wait = 150000 memcached.sess_prefix = "memc.sess.key." -session.save_path="127.0.0.1:11211" session.save_handler = memcached --FILE-- - --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = str_repeat("foo bar", 1024 * 1024); diff --git a/tests/setmulti.phpt b/tests/setmulti.phpt index 3d48f038..02087614 100644 --- a/tests/setmulti.phpt +++ b/tests/setmulti.phpt @@ -5,9 +5,8 @@ Memcached::setMulti() --FILE-- addServer('localhost', 11211, 1); - +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $data['foo'] = 'bar'; diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 9bbe4a84..b7399616 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -32,9 +32,8 @@ function status_print ($op, $mem, $expected) } } -$mem = new Memcached(); -$mem->setOption(Memcached::OPT_BINARY_PROTOCOL,true); -$mem->addServer('127.0.0.1', 11211) or die ("Could not connect"); +include dirname (__FILE__) . '/config.inc'; +$mem = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true)); $key = uniqid ('touch_t_'); diff --git a/tests/undefined_set.phpt b/tests/undefined_set.phpt index f3d350d1..167600cc 100644 --- a/tests/undefined_set.phpt +++ b/tests/undefined_set.phpt @@ -4,8 +4,8 @@ Set with undefined key and value --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = array('foo' => 'bar'); diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 4891bfd3..2ed44c9a 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -24,9 +24,8 @@ define ('FLAG_64', 64); define ('FLAG_TOO_LARGE', pow(2, 16)); $x = 0; -$m = new Memcached(); -$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); -$m->addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true)); $key = uniqid ('udf_test_'); diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt index 1b64c0c1..31fcb7f2 100644 --- a/tests/vbucket.phpt +++ b/tests/vbucket.phpt @@ -7,10 +7,10 @@ if (!defined("Memcached::DISTRIBUTION_VIRTUAL_BUCKET")) die ("skip DISTRIBUTION_ ?> --FILE-- setOption (Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_VIRTUAL_BUCKET)); - -$m->addServer('127.0.0.1', 11211, 1); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (array ( + Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_VIRTUAL_BUCKET + )); var_dump ($m->setBucket (array (1, 2, 3), null, 2)); @@ -33,7 +33,6 @@ echo "OK\n"; bool(true) bool(true) bool(true) -bool(true) Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d bool(false) diff --git a/tests/version.phpt b/tests/version.phpt index 8b980925..f9adcc52 100644 --- a/tests/version.phpt +++ b/tests/version.phpt @@ -4,15 +4,15 @@ Get version --FILE-- addServer('127.0.0.1', 11211); +include dirname (__FILE__) . '/config.inc'; +$m = memc_get_instance (); var_dump ($m->getVersion ()); echo "OK" . PHP_EOL; ?> --EXPECTF-- array(1) { - ["127.0.0.1:11211"]=> + ["%s:%d"]=> string(6) "%d.%d.%d" } OK \ No newline at end of file From f48ff3fcf7d2aed955e90b2201f46bd8117db1f3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 12:31:13 +0800 Subject: [PATCH 293/694] Merge conflict --- php_memcached.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 53903926..1b9bbea3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2496,14 +2496,16 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided"); return 0; } - break; } + break; case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: flag = (memcached_behavior) option; convert_to_long(value); - if ((rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value))) != MEMCACHED_SUCCESS) { + rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + + if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } @@ -2552,6 +2554,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML m_obj->serializer = SERIALIZER_PHP; } else { m_obj->serializer = SERIALIZER_PHP; + i_obj->rescode = MEMCACHED_FAILURE; php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid serializer provided"); return 0; } @@ -2569,7 +2572,10 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML */ flag = (memcached_behavior) option; convert_to_long(value); - if (flag >= MEMCACHED_BEHAVIOR_MAX || (rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value))) != MEMCACHED_SUCCESS) { + + rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + + if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } @@ -3430,8 +3436,8 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ goto my_error; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - break; } + break; case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY From d4f07b522da8797ffec64b037e5079101d364c0b Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 12:31:58 +0800 Subject: [PATCH 294/694] Added test for invalid keys --- tests/keys.phpt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/keys.phpt diff --git a/tests/keys.phpt b/tests/keys.phpt new file mode 100644 index 00000000..ee6be90d --- /dev/null +++ b/tests/keys.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test different kind of keys +--SKIPIF-- + +--FILE-- + true, + )); + +$ascii = memc_get_instance (); + +var_dump ($binary->set ('binary key with spaces', 'this is a test')); +var_dump ($binary->getResultCode ()); + +var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); +var_dump ($ascii->getResultCode ()); + + +echo "OK" . PHP_EOL; + +--EXPECT-- +bool(false) +int(33) +bool(false) +int(33) +OK From b1207f628ecaa040d7c24ab2bde731d7895c56cf Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 13:50:37 +0800 Subject: [PATCH 295/694] Add missing test --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 10947cfe..4c9afa69 100644 --- a/package.xml +++ b/package.xml @@ -136,6 +136,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + From 8cd01d119d2376f2f69abdf436a4afd59cdd1610 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 13:54:23 +0800 Subject: [PATCH 296/694] Added test for invalid options --- package.xml | 1 + tests/invalid_options.phpt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/invalid_options.phpt diff --git a/package.xml b/package.xml index 4c9afa69..5f353139 100644 --- a/package.xml +++ b/package.xml @@ -137,6 +137,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/invalid_options.phpt b/tests/invalid_options.phpt new file mode 100644 index 00000000..af86531b --- /dev/null +++ b/tests/invalid_options.phpt @@ -0,0 +1,18 @@ +--TEST-- +Get version +--SKIPIF-- + +--FILE-- +setOption(500, 23423); +var_dump ($m->getResultCode ()); + +echo "OK" . PHP_EOL; +?> +--EXPECTF-- +Warning: Memcached::setOption(): error setting memcached option: INVALID ARGUMENTS in %s on line %d +int(38) +OK \ No newline at end of file From 0f5550efe0b00e90b00fef80d0de4840244c15f1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 16:13:03 +0800 Subject: [PATCH 297/694] refactor code to be a bit more readable --- php_memcached.c | 476 +++++++++++++++++++++++++++--------------------- 1 file changed, 272 insertions(+), 204 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1b9bbea3..e3d2662a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2467,6 +2467,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML m_obj->compression_type = Z_LVAL_P(value); } else { /* invalid compression type */ + i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; return 0; } break; @@ -2493,6 +2494,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML #endif } if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { + i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided"); return 0; } @@ -2554,7 +2556,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML m_obj->serializer = SERIALIZER_PHP; } else { m_obj->serializer = SERIALIZER_PHP; - i_obj->rescode = MEMCACHED_FAILURE; + i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid serializer provided"); return 0; } @@ -2573,7 +2575,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML flag = (memcached_behavior) option; convert_to_long(value); - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + if (Z_LVAL_P(value) >= 0 && Z_LVAL_P(value) < MEMCACHED_BEHAVIOR_MAX) { + rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + } + else { + rc = MEMCACHED_INVALID_ARGUMENTS; + } if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); @@ -3110,181 +3117,219 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM return result; } -static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) +static +char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags TSRMLS_DC) +{ + /* status */ + zend_bool compress_status = 0; + + /* Additional 5% for the data */ + size_t buffer_size = (size_t) (((double) *payload_len * 1.05) + 1.0); + char *buffer = emalloc(sizeof(uint32_t) + buffer_size); + + /* Store compressed size here */ + size_t compressed_size = 0; + + /* Copy the uin32_t at the beginning */ + memcpy(buffer, payload_len, sizeof(uint32_t)); + buffer += sizeof(uint32_t); + + switch (compression_type) { + + case COMPRESSION_TYPE_FASTLZ: + compress_status = ((compressed_size = fastlz_compress(payload, *payload_len, buffer)) > 0); + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + break; + + case COMPRESSION_TYPE_ZLIB: + /* ZLIB returns the compressed size in this buffer */ + compressed_size = buffer_size; + + compress_status = (compress((Bytef *)buffer, &compressed_size, (Bytef *)payload, *payload_len) == Z_OK); + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + break; + + default: + compress_status = 0; + break; + } + buffer -= sizeof(uint32_t); + *payload_len = compressed_size + sizeof(uint32_t); + + if (!compress_status) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + + efree (buffer); + *payload_len = 0; + return NULL; + } + + else if (*payload_len > (compressed_size * MEMC_G(compression_factor))) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + efree (buffer); + *payload_len = 0; + return NULL; + } + return buffer; +} + +static +zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags TSRMLS_DC) +{ + switch (serializer) { + + /* + Igbinary serialization + */ +#ifdef HAVE_MEMCACHED_IGBINARY + case SERIALIZER_IGBINARY: + if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value TSRMLS_CC) != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with igbinary"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); + break; +#endif + + /* + JSON serialization + */ +#ifdef HAVE_JSON_API + case SERIALIZER_JSON: + case SERIALIZER_JSON_ARRAY: + { +#if HAVE_JSON_API_5_2 + php_json_encode(buf, value TSRMLS_CC); +#elif HAVE_JSON_API_5_3 + php_json_encode(buf, value, 0 TSRMLS_CC); /* options */ +#endif + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); + } + break; +#endif + + /* + msgpack serialization + */ +#ifdef HAVE_MEMCACHED_MSGPACK + case SERIALIZER_MSGPACK: + php_msgpack_serialize(buf, value TSRMLS_CC); + if (!buf.c) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; +#endif + + /* + PHP serialization + */ + default: + { + php_serialize_data_t var_hash; + PHP_VAR_SERIALIZE_INIT(var_hash); + php_var_serialize(buf, &value, &var_hash TSRMLS_CC); + PHP_VAR_SERIALIZE_DESTROY(var_hash); + + if (!buf->c) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); + } + break; + } + + /* Check for exceptions caused by serializers */ + if (EG(exception) && buf->len) { + smart_str_free(buf); + return 0; + } + return 1; +} + +static +char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) { - char *payload; - char *p; - int l; - zend_bool buf_used = 0; + const char *pl; + size_t pl_len = 0; + + char *payload = NULL; smart_str buf = {0}; char tmp[40] = {0}; switch (Z_TYPE_P(value)) { case IS_STRING: - p = Z_STRVAL_P(value); - l = Z_STRLEN_P(value); + pl = Z_STRVAL_P(value); + pl_len = Z_STRLEN_P(value); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); break; case IS_LONG: - l = sprintf(tmp, "%ld", Z_LVAL_P(value)); - p = tmp; + pl_len = sprintf(tmp, "%ld", Z_LVAL_P(value)); + pl = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); break; case IS_DOUBLE: php_memcached_g_fmt(tmp, Z_DVAL_P(value)); - p = tmp; - l = strlen(tmp); + pl = tmp; + pl_len = strlen(tmp); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); break; case IS_BOOL: if (Z_BVAL_P(value)) { - l = 1; + pl_len = 1; tmp[0] = '1'; tmp[1] = '\0'; } else { - l = 0; + pl_len = 0; tmp[0] = '\0'; } - p = tmp; + pl = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; default: - switch (serializer) { -#ifdef HAVE_MEMCACHED_IGBINARY - case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf.c, &buf.len, value TSRMLS_CC) != 0) { - smart_str_free(&buf); - return NULL; - } - p = buf.c; - l = buf.len; - buf_used = 1; - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); - break; -#endif - -#ifdef HAVE_JSON_API - case SERIALIZER_JSON: - case SERIALIZER_JSON_ARRAY: - { -#if HAVE_JSON_API_5_2 - php_json_encode(&buf, value TSRMLS_CC); -#elif HAVE_JSON_API_5_3 - php_json_encode(&buf, value, 0 TSRMLS_CC); /* options */ -#endif - buf.c[buf.len] = 0; - p = buf.c; - l = buf.len; - buf_used = 1; - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); - break; - } -#endif -#ifdef HAVE_MEMCACHED_MSGPACK - case SERIALIZER_MSGPACK: - php_msgpack_serialize(&buf, value TSRMLS_CC); - if(!buf.c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); - smart_str_free(&buf); - return NULL; - } - p = buf.c; - l = buf.len; - buf_used = 1; - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); - break; -#endif - default: - { - php_serialize_data_t var_hash; - PHP_VAR_SERIALIZE_INIT(var_hash); - php_var_serialize(&buf, &value, &var_hash TSRMLS_CC); - PHP_VAR_SERIALIZE_DESTROY(var_hash); - - if (!buf.c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value"); - smart_str_free(&buf); - return NULL; - } - p = buf.c; - l = buf.len; - buf_used = 1; - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); - break; - } + if (!s_serialize_value (serializer, value, &buf, flags TSRMLS_CC)) { + smart_str_free (&buf); + return NULL; } - + pl = buf.c; + pl_len = buf.len; break; } - /* Check for exceptions caused by serializers */ - if (EG(exception) && buf_used) { - smart_str_free(&buf); - return NULL; - } - /* turn off compression for values below the threshold */ - if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { + if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && pl_len < MEMC_G(compression_threshold)) { MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); } + /* If we have compression flag, compress the value */ if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ - zend_bool compress_status = 0; - - /* Additional 5% for the data */ - unsigned long payload_comp_len = (unsigned long)((l * 1.05) + 1); - char *payload_comp = emalloc(payload_comp_len + sizeof(uint32_t)); - payload = payload_comp; - memcpy(payload_comp, &l, sizeof(uint32_t)); - payload_comp += sizeof(uint32_t); - - if (compression_type == COMPRESSION_TYPE_FASTLZ) { - compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); - } else if (compression_type == COMPRESSION_TYPE_ZLIB) { - compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); - } - - if (!compress_status) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); - efree(payload); - if (buf_used) { - smart_str_free(&buf); - } - return NULL; - } + *payload_len = Z_STRLEN_P(value); + payload = s_compress_value (compression_type, pl, payload_len, flags TSRMLS_CC); + } - /* Check that we are above ratio */ - if (l > (payload_comp_len * MEMC_G(compression_factor))) { - *payload_len = payload_comp_len + sizeof(uint32_t); - payload[*payload_len] = 0; - } else { - /* Store plain value */ - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - *payload_len = l; - memcpy(payload, p, l); - payload[l] = 0; - } - } else { - *payload_len = l; - payload = estrndup(p, l); + /* If compression failed or value is below threshold we just use plain value */ + if (!payload || !MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { + *payload_len = (uint32_t) pl_len; + payload = estrndup(pl, pl_len); } - if (buf_used) { + if (buf.len) { smart_str_free(&buf); } return payload; } static -char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) +char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) { char *buffer; uint32_t len; @@ -3334,12 +3379,74 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t return buffer; } +static +zend_bool s_unserialize_value (int val_type, zval *value, const char *payload, size_t payload_len TSRMLS_DC) +{ + switch (val_type) { + case MEMC_VAL_IS_SERIALIZED: + { + const char *payload_tmp = payload; + php_unserialize_data_t var_hash; + + PHP_VAR_UNSERIALIZE_INIT(var_hash); + if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash TSRMLS_CC)) { + ZVAL_FALSE(value); + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value"); + return 0; + } + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + } + break; + + case MEMC_VAL_IS_IGBINARY: +#ifdef HAVE_MEMCACHED_IGBINARY + if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { + ZVAL_FALSE(value); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); + return 0; + } +#else + ZVAL_FALSE(value); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support"); + return 0; +#endif + break; + + case MEMC_VAL_IS_JSON: +#ifdef HAVE_JSON_API +# if HAVE_JSON_API_5_2 + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); +# elif HAVE_JSON_API_5_3 + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); +# endif +#else + ZVAL_FALSE(value); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); + return 0; +#endif + break; + + case MEMC_VAL_IS_MSGPACK: +#ifdef HAVE_MEMCACHED_MSGPACK + php_msgpack_unserialize(value, payload, payload_len TSRMLS_CC); +#else + ZVAL_FALSE(value); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + return 0; +#endif + break; + } + return 1; +} + /* The caller MUST free the payload */ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) { /* A NULL payload is completely valid if length is 0, it is simply empty. */ + int retval = 0; zend_bool payload_emalloc = 0; char *pl = NULL; @@ -3358,7 +3465,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ } if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { - char *datas = s_handle_decompressed (payload_in, &payload_len, flags TSRMLS_CC); + char *datas = s_decompress_value (payload_in, &payload_len, flags TSRMLS_CC); if (!datas) { ZVAL_FALSE(value); return -1; @@ -3386,13 +3493,15 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ if (payload_len >= 128) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read long value, too big"); - goto my_error; + retval = -1; } - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; + else { + memcpy (conv_buf, pl, payload_len); + conv_buf [payload_len] = '\0'; - lval = strtol(conv_buf, NULL, 10); - ZVAL_LONG(value, lval); + lval = strtol(conv_buf, NULL, 10); + ZVAL_LONG(value, lval); + } } break; @@ -3402,19 +3511,21 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ if (payload_len >= 128) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read double value, too big"); - goto my_error; + retval = -1; } - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; - - if (payload_len == 8 && memcmp(conv_buf, "Infinity", 8) == 0) { - ZVAL_DOUBLE(value, php_get_inf()); - } else if (payload_len == 9 && memcmp(conv_buf, "-Infinity", 9) == 0) { - ZVAL_DOUBLE(value, -php_get_inf()); - } else if (payload_len == 3 && memcmp(conv_buf, "NaN", 3) == 0) { - ZVAL_DOUBLE(value, php_get_nan()); - } else { - ZVAL_DOUBLE(value, zend_strtod(conv_buf, NULL)); + else { + memcpy (conv_buf, pl, payload_len); + conv_buf [payload_len] = '\0'; + + if (payload_len == 8 && memcmp(conv_buf, "Infinity", 8) == 0) { + ZVAL_DOUBLE(value, php_get_inf()); + } else if (payload_len == 9 && memcmp(conv_buf, "-Infinity", 9) == 0) { + ZVAL_DOUBLE(value, -php_get_inf()); + } else if (payload_len == 3 && memcmp(conv_buf, "NaN", 3) == 0) { + ZVAL_DOUBLE(value, php_get_nan()); + } else { + ZVAL_DOUBLE(value, zend_strtod(conv_buf, NULL)); + } } } break; @@ -3424,76 +3535,25 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ break; case MEMC_VAL_IS_SERIALIZED: - { - const char *payload_tmp = pl; - php_unserialize_data_t var_hash; - - PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash TSRMLS_CC)) { - ZVAL_FALSE(value); - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value"); - goto my_error; - } - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - } - break; - case MEMC_VAL_IS_IGBINARY: -#ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)pl, payload_len, &value TSRMLS_CC)) { - ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); - goto my_error; - } -#else - ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support"); - goto my_error; -#endif - break; - case MEMC_VAL_IS_JSON: -#ifdef HAVE_JSON_API -# if HAVE_JSON_API_5_2 - php_json_decode(value, pl, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); -# elif HAVE_JSON_API_5_3 - php_json_decode(value, pl, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); -# endif -#else - ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); - goto my_error; -#endif + case MEMC_VAL_IS_MSGPACK: + if (!s_unserialize_value (MEMC_VAL_GET_TYPE(flags), value, pl, payload_len TSRMLS_CC)) { + retval = -1; + } break; - case MEMC_VAL_IS_MSGPACK: -#ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(value, pl, payload_len TSRMLS_CC); -#else - ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); - goto my_error; -#endif - break; - default: ZVAL_FALSE(value); php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); - goto my_error; - } - - if (payload_emalloc) { - efree(pl); + retval = -1; + break; } - return 0; - -my_error: if (payload_emalloc) { efree(pl); } - return -1; + return retval; } static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) @@ -4376,11 +4436,19 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); + + REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_E2BIG, MEMCACHED_E2BIG); + REGISTER_MEMC_CLASS_CONST_LONG(RES_KEY_TOO_BIG, MEMCACHED_KEY_TOO_BIG); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_TEMPORARILY_DISABLED, MEMCACHED_SERVER_TEMPORARILY_DISABLED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MEMORY_ALLOCATION_FAILURE, MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE); + #if HAVE_MEMCACHED_SASL REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE); #endif + /* * Our result codes. */ From f3e8821852047bf527acae75daf60d767d37f285 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 16:18:51 +0800 Subject: [PATCH 298/694] Add test for too large key --- package.xml | 1 + tests/keys.phpt | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index 5f353139..bff3a156 100644 --- a/package.xml +++ b/package.xml @@ -138,6 +138,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/keys.phpt b/tests/keys.phpt index ee6be90d..0ed90896 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -13,17 +13,21 @@ $binary = memc_get_instance (array ( $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); -var_dump ($binary->getResultCode ()); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); -var_dump ($ascii->getResultCode ()); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); echo "OK" . PHP_EOL; --EXPECT-- bool(false) -int(33) +bool(true) bool(false) -int(33) +bool(true) +bool(false) +bool(true) OK From a09dbdd78a537db75b111a87dd50dba7a2ff4b6d Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 16:22:38 +0800 Subject: [PATCH 299/694] Fix this --- package.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/package.xml b/package.xml index bff3a156..ad560ca9 100644 --- a/package.xml +++ b/package.xml @@ -136,7 +136,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - From add9e6a8dcfa1c49798c897a0c8ae4241d36b709 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 16:39:32 +0800 Subject: [PATCH 300/694] Minor fixes --- php_memcached.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e3d2662a..082ca62c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3215,7 +3215,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, #ifdef HAVE_MEMCACHED_MSGPACK case SERIALIZER_MSGPACK: php_msgpack_serialize(buf, value TSRMLS_CC); - if (!buf.c) { + if (!buf->c) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); return 0; } @@ -3380,7 +3380,7 @@ char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t fla } static -zend_bool s_unserialize_value (int val_type, zval *value, const char *payload, size_t payload_len TSRMLS_DC) +zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len TSRMLS_DC) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: @@ -3538,7 +3538,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - if (!s_unserialize_value (MEMC_VAL_GET_TYPE(flags), value, pl, payload_len TSRMLS_CC)) { + if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len TSRMLS_CC)) { retval = -1; } break; From bda8dfae3632404e1701d1f9a2d83da47b3e8590 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 16:47:27 +0800 Subject: [PATCH 301/694] No need to free here --- php_memcached.c | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 082ca62c..18de9b43 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3244,7 +3244,6 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, /* Check for exceptions caused by serializers */ if (EG(exception) && buf->len) { - smart_str_free(buf); return 0; } return 1; From e11ef00f99c203f09c0fffeecddaca56fc8c8959 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 20 Nov 2013 17:17:01 +0800 Subject: [PATCH 302/694] This is only available in later versions --- php_memcached.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 18de9b43..80da7577 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4440,7 +4440,10 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_E2BIG, MEMCACHED_E2BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_KEY_TOO_BIG, MEMCACHED_KEY_TOO_BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_TEMPORARILY_DISABLED, MEMCACHED_SERVER_TEMPORARILY_DISABLED); + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000008 REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MEMORY_ALLOCATION_FAILURE, MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE); +#endif #if HAVE_MEMCACHED_SASL REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); From d54b2d58bc7b884e923abbb6c8ff3fce8567dd0e Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 01:43:00 +0800 Subject: [PATCH 303/694] Separate serializer tests --- package.xml | 11 ++++- tests/{types.phpt => types.inc} | 68 ++++++++++++++++++++++++------ tests/types_igbinary.phpt | 19 +++++++++ tests/types_igbinary_multi.phpt | 19 +++++++++ tests/types_json.phpt | 19 +++++++++ tests/types_json_multi.phpt | 19 +++++++++ tests/types_msgpack.phpt | 19 +++++++++ tests/types_msgpack_multi.phpt | 19 +++++++++ tests/types_multi.phpt | 73 --------------------------------- tests/types_php.phpt | 16 ++++++++ tests/types_php_multi.phpt | 16 ++++++++ 11 files changed, 211 insertions(+), 87 deletions(-) rename tests/{types.phpt => types.inc} (52%) create mode 100644 tests/types_igbinary.phpt create mode 100644 tests/types_igbinary_multi.phpt create mode 100644 tests/types_json.phpt create mode 100644 tests/types_json_multi.phpt create mode 100644 tests/types_msgpack.phpt create mode 100644 tests/types_msgpack_multi.phpt delete mode 100644 tests/types_multi.phpt create mode 100644 tests/types_php.phpt create mode 100644 tests/types_php_multi.phpt diff --git a/package.xml b/package.xml index ad560ca9..f3f06d1a 100644 --- a/package.xml +++ b/package.xml @@ -118,8 +118,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - + + + + + + + + + diff --git a/tests/types.phpt b/tests/types.inc similarity index 52% rename from tests/types.phpt rename to tests/types.inc index b91d94f9..5e0ad5d3 100644 --- a/tests/types.phpt +++ b/tests/types.inc @@ -1,15 +1,8 @@ ---TEST-- -Memcached store & fetch type and value correctness ---SKIPIF-- - ---FILE-- true, + 'boolean_false' => false, + + 'string' => "just a string", + 'string_empty' => "", + 'string_large' => str_repeat ('abcdef0123456789', 500), + + 'integer_positive_integer' => 10, + 'integer_negative_integer' => -10, + 'integer_zero_integer' => 0, + + 'float_positive1' => 3.912131, + 'float_positive2' => 1.2131E+52, + 'float_negative' => -42.123312, + 'float_zero' => 0.0, + + 'null' => null, + + 'array_empty' => array(), + 'array' => array(1,2,3,"foo"), + + 'object_array_empty' => (object)array(), + 'object_array' => (object)array('a' => 1, 'b' => 2, 'c' => 3), + 'object_dummy' => new testclass(), + ); + + foreach ($data as $key => $value) { + $m->delete($key); + } + $m->setMulti($data); + $actual = $m->getMulti(array_keys($data)); + + foreach ($data as $key => $value) { + if ($value !== $actual[$key]) { + if (is_object($value)) { + if ($options['ignore_object_type']) { + $value = (object) (array) $value; + if ($value == $actual[$key]) + continue; + } + + if ($value == $actual[$key] && get_class($value) == get_class($actual[$key])) + continue; + } -?> ---EXPECT-- -TEST DONE + echo "=== $key ===\n"; + echo "Expected: "; + var_dump($value); + echo "Actual: "; + var_dump($actual[$key]); + } + } +} diff --git a/tests/types_igbinary.phpt b/tests/types_igbinary.phpt new file mode 100644 index 00000000..62fcc29b --- /dev/null +++ b/tests/types_igbinary.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached store & fetch type and value correctness using igbinary serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_igbinary_multi.phpt b/tests/types_igbinary_multi.phpt new file mode 100644 index 00000000..33f4df67 --- /dev/null +++ b/tests/types_igbinary_multi.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached multi store & multi fetch type and value correctness using igbinary serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_json.phpt b/tests/types_json.phpt new file mode 100644 index 00000000..f5735f6d --- /dev/null +++ b/tests/types_json.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached store & fetch type and value correctness using JSON serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt new file mode 100644 index 00000000..2efba2be --- /dev/null +++ b/tests/types_json_multi.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached multi store & multi fetch type and value correctness using JSON serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_msgpack.phpt b/tests/types_msgpack.phpt new file mode 100644 index 00000000..9f359602 --- /dev/null +++ b/tests/types_msgpack.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached store & fetch type and value correctness using msgpack serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_msgpack_multi.phpt b/tests/types_msgpack_multi.phpt new file mode 100644 index 00000000..a1437178 --- /dev/null +++ b/tests/types_msgpack_multi.phpt @@ -0,0 +1,19 @@ +--TEST-- +Memcached multi store & fetch type and value correctness using msgpack serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_multi.phpt b/tests/types_multi.phpt deleted file mode 100644 index 0d49bd1b..00000000 --- a/tests/types_multi.phpt +++ /dev/null @@ -1,73 +0,0 @@ ---TEST-- -Memcached multi store & multi fetch type and value correctness ---SKIPIF-- - ---FILE-- - true, - 'boolean_false' => false, - - 'string' => "just a string", - 'string_empty' => "", - 'string_large' => str_repeat ('abcdef0123456789', 500), - - 'integer_positive_integer' => 10, - 'integer_negative_integer' => -10, - 'integer_zero_integer' => 0, - - 'float_positive1' => 3.912131, - 'float_positive2' => 1.2131E+52, - 'float_negative' => -42.123312, - 'float_zero' => 0.0, - - 'null' => null, - - 'array_empty' => array(), - 'array' => array(1,2,3,"foo"), - - 'object_array_empty' => (object)array(), - 'object_array' => (object)array('a' => 1, 'b' => 2, 'c' => 3), - 'object_dummy' => new testclass(), - ); - - foreach ($data as $key => $value) { - $m->delete($key); - } - $m->setMulti($data); - $actual = $m->getMulti(array_keys($data)); - - foreach ($data as $key => $value) { - if ($value !== $actual[$key]) { - if (is_object($value)) { - if ($options['ignore_object_type']) { - $value = (object) (array) $value; - if ($value == $actual[$key]) - continue; - } - - if ($value == $actual[$key] && get_class($value) == get_class($actual[$key])) - continue; - } - - echo "=== $key ===\n"; - echo "Expected: "; - var_dump($value); - echo "Actual: "; - var_dump($actual[$key]); - } - } -} - -memc_run_test ('types_test', memc_get_serializer_options (version_compare(phpversion("msgpack"), "0.5.5", "<="))); - -?> ---EXPECT-- -TEST DONE diff --git a/tests/types_php.phpt b/tests/types_php.phpt new file mode 100644 index 00000000..f6baab5b --- /dev/null +++ b/tests/types_php.phpt @@ -0,0 +1,16 @@ +--TEST-- +Memcached store & fetch type and value correctness using PHP serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE diff --git a/tests/types_php_multi.phpt b/tests/types_php_multi.phpt new file mode 100644 index 00000000..ac7b0476 --- /dev/null +++ b/tests/types_php_multi.phpt @@ -0,0 +1,16 @@ +--TEST-- +Memcached multi store & fetch type and value correctness using PHP serializer +--SKIPIF-- + +--FILE-- + +--EXPECT-- +TEST DONE From 4e38d89817300517f5a407cac396e0961fcb9135 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 01:56:11 +0800 Subject: [PATCH 304/694] Ensure that memcached is running --- travis.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/travis.sh b/travis.sh index 210bd626..478dd36f 100755 --- a/travis.sh +++ b/travis.sh @@ -156,6 +156,10 @@ case $ACTION in # Build the extension build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL + # Make sure that memcached is running + sudo service memcached restart + nc -z localhost 11211 + # Run tests set +e run_memcached_tests $PHP_MEMCACHED_VERSION || exit 1 From 109fa1d57578d9f8d4e3ddbe4e46f21cdebfdd02 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 02:05:20 +0800 Subject: [PATCH 305/694] parse error --- tests/types_msgpack_multi.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/types_msgpack_multi.phpt b/tests/types_msgpack_multi.phpt index a1437178..68f5505e 100644 --- a/tests/types_msgpack_multi.phpt +++ b/tests/types_msgpack_multi.phpt @@ -11,7 +11,7 @@ include dirname (__FILE__) . '/config.inc'; include dirname (__FILE__) . '/types.inc'; memc_run_test ('memc_types_test_multi', - memc_create_combinations ('JSON', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<="))) + memc_create_combinations ('JSON', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<=")) ); ?> From 2e28f5353ad3ab701e502ff2b75b1c04b9e71074 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 02:11:07 +0800 Subject: [PATCH 306/694] Some copy-pasta errors --- tests/types_json_multi.phpt | 2 +- tests/types_msgpack.phpt | 2 +- tests/types_msgpack_multi.phpt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt index 2efba2be..5535abb8 100644 --- a/tests/types_json_multi.phpt +++ b/tests/types_json_multi.phpt @@ -11,7 +11,7 @@ include dirname (__FILE__) . '/config.inc'; include dirname (__FILE__) . '/types.inc'; memc_run_test ('memc_types_test_multi', - memc_create_combinations ('json', Memcached::SERIALIZER_JSON, true) + memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true) ); ?> diff --git a/tests/types_msgpack.phpt b/tests/types_msgpack.phpt index 9f359602..aed43627 100644 --- a/tests/types_msgpack.phpt +++ b/tests/types_msgpack.phpt @@ -11,7 +11,7 @@ include dirname (__FILE__) . '/config.inc'; include dirname (__FILE__) . '/types.inc'; memc_run_test ('memc_types_test', - memc_create_combinations ('JSON', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<="))) + memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<=")) ); ?> diff --git a/tests/types_msgpack_multi.phpt b/tests/types_msgpack_multi.phpt index 68f5505e..dcf251e1 100644 --- a/tests/types_msgpack_multi.phpt +++ b/tests/types_msgpack_multi.phpt @@ -11,7 +11,7 @@ include dirname (__FILE__) . '/config.inc'; include dirname (__FILE__) . '/types.inc'; memc_run_test ('memc_types_test_multi', - memc_create_combinations ('JSON', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<=")) + memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK, version_compare(phpversion("msgpack"), "0.5.5", "<=")) ); ?> From 8f4a68df276fc0d6fb20992235bb5285e300493b Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 03:03:46 +0800 Subject: [PATCH 307/694] Make this a bit more verbose --- travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis.sh b/travis.sh index 478dd36f..aaee2354 100755 --- a/travis.sh +++ b/travis.sh @@ -158,7 +158,7 @@ case $ACTION in # Make sure that memcached is running sudo service memcached restart - nc -z localhost 11211 + nc -vv -z localhost 11211 # Run tests set +e From 6d2fc84d505f7535336030a196246fb05e2b2a56 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 03:09:45 +0800 Subject: [PATCH 308/694] Use ip instead of localhost --- travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis.sh b/travis.sh index aaee2354..a971f925 100755 --- a/travis.sh +++ b/travis.sh @@ -158,7 +158,7 @@ case $ACTION in # Make sure that memcached is running sudo service memcached restart - nc -vv -z localhost 11211 + nc -vv -z 127.0.0.1 11211 # Run tests set +e From d036f8b72b75b76bbd0a4b87659f8a19cce44ffc Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Nov 2013 12:25:54 +0800 Subject: [PATCH 309/694] Check if memcached is there --- travis.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/travis.sh b/travis.sh index a971f925..51afd8df 100755 --- a/travis.sh +++ b/travis.sh @@ -158,6 +158,7 @@ case $ACTION in # Make sure that memcached is running sudo service memcached restart + netstat -an | grep LISTEN nc -vv -z 127.0.0.1 11211 # Run tests From 26ac8bd9cb1f83c6ec5788f12bded16bc5d680ea Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 23 Nov 2013 12:29:30 +0800 Subject: [PATCH 310/694] Refactor SASL support checking, move "unnecessary" things to private header, move travis script to .travis dir --- .travis.yml | 13 +- .travis/travis.sh | 250 ++++++++++++++++++++++++++++++++++++++ config.m4 | 42 +++++-- package.xml | 2 + php_libmemcached_compat.h | 6 + php_memcached.c | 57 +++------ php_memcached.h | 138 +-------------------- php_memcached_private.h | 184 ++++++++++++++++++++++++++++ php_memcached_server.c | 1 + php_memcached_session.c | 1 + tests/config.inc | 47 +++---- tests/sasl_basic.phpt | 32 +++++ travis.sh | 178 --------------------------- 13 files changed, 565 insertions(+), 386 deletions(-) create mode 100755 .travis/travis.sh create mode 100644 php_memcached_private.h create mode 100644 tests/sasl_basic.phpt delete mode 100755 travis.sh diff --git a/.travis.yml b/.travis.yml index 4e1d2994..4c82f64f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: php php: - 5.5 - - 5.4 - - 5.3 + #- 5.4 + #- 5.3 env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 @@ -10,12 +10,17 @@ env: - LIBMEMCACHED_VERSION=1.0.14 - LIBMEMCACHED_VERSION=1.0.10 - LIBMEMCACHED_VERSION=1.0.8 + - LIBMEMCACHED_VERSION=1.0.7 + - LIBMEMCACHED_VERSION=1.0.6 - LIBMEMCACHED_VERSION=1.0.2 - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.44 +services: + - memcached # will start memcached + before_script: - - ./travis.sh before_script $LIBMEMCACHED_VERSION + - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION script: - - ./travis.sh script $LIBMEMCACHED_VERSION + - ./.travis/travis.sh script $LIBMEMCACHED_VERSION diff --git a/.travis/travis.sh b/.travis/travis.sh new file mode 100755 index 00000000..9534c7e0 --- /dev/null +++ b/.travis/travis.sh @@ -0,0 +1,250 @@ +#!/bin/bash + +function version_compare() { + DPKG=`which dpkg` + + if [ "x$DPKG" = "x" ]; then + echo "dpkg not found, cannot compare versions" + exit 1 + fi + + $DPKG --compare-versions "$1" "$2" "$3" + return $? +} + +function check_protocol_support() { + version_compare "$LIBMEMCACHED_VERSION" gt 1.0.15 + if [ $? = 0 ]; then + ENABLE_PROTOOCOL=yes + else + ENABLE_PROTOOCOL=no + fi +} + +function check_sasl_support() { + version_compare "$LIBMEMCACHED_VERSION" gt 1.0.15 + if [ $? = 0 ]; then + ENABLE_SASL=yes + else + ENABLE_SASL=no + fi +} + +function validate_package_xml() { + retval=0 + for file in tests/*.phpt; do + grep $(basename $file) package.xml >/dev/null + if [ $? != 0 ]; then + echo "Missing $file from package.xml" + retval=1; + fi + done + return $retval +} + +function install_libmemcached() { + + wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" -O libmemcached-${LIBMEMCACHED_VERSION}.tar.gz + + tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz + pushd "libmemcached-${LIBMEMCACHED_VERSION}" + + local protocol_flag="" + if test "x$ENABLE_PROTOOCOL" = "xyes"; then + protocol_flag="--enable-libmemcachedprotocol" + fi + + ./configure --prefix="$LIBMEMCACHED_PREFIX" $protocol_flag LDFLAGS="-lpthread" + make + make install + popd +} + +function install_igbinary() { + git clone https://github.com/igbinary/igbinary.git + pushd igbinary + phpize + ./configure + make + make install + popd +} + +function install_msgpack() { + git clone https://github.com/msgpack/msgpack-php.git + pushd msgpack-php + phpize + ./configure + make + make install + popd +} + +function install_sasl() { + + wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz -O memcached-1.4.15.tar.gz + tar xfz memcached-1.4.15.tar.gz + + pushd memcached-1.4.15 + ./configure --enable-sasl --prefix="${HOME}/memcached" + make + make install + popd + + sudo apt-get install sasl2-bin + export SASL_CONF_PATH="${HOME}/sasl2" + + # Create config path + mkdir "${SASL_CONF_PATH}" + + # Create configuration + cat< "${SASL_CONF_PATH}/memcached.conf" +mech_list: PLAIN +plainlog_level: 5 +sasldb_path: ${SASL_CONF_PATH}/sasldb2 +EOF + + # Create password + echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" + + # Run memcached on port 11212 with SASL support + "${HOME}/memcached/bin/memcached" -S -d -p 11212 +} + +function build_php_memcached() { + pear package + mkdir "$PHP_MEMCACHED_BUILD_DIR" + tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C "$PHP_MEMCACHED_BUILD_DIR" + pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" + phpize + + local protocol_flag="" + if test "x$ENABLE_PROTOCOL" = "xyes"; then + protocol_flag="--enable-memcached-protocol" + fi + + local sasl_flag="--disable-memcached-sasl" + if test "x$ENABLE_SASL" = "xyes"; then + protocol_flag="--enable-memcached-sasl" + fi + + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack + make + make install + popd +} + +function create_memcached_test_configuration() { +cat< "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}/tests/config.inc.local" +/dev/null`; do + echo "-- START ${i}"; + cat $i; + echo ""; + echo "-- END"; + done + popd + + return $retval; +} + +# Command line arguments +ACTION=$1 +LIBMEMCACHED_VERSION=$2 + +if test "x$ACTION" = "x"; then + echo "Usage: $0 " + exit 1 +fi + +if test "x$LIBMEMCACHED_VERSION" = "x"; then + echo "Usage: $0 " + exit 1 +fi + +# the extension version +PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') + +# Libmemcached install dir +LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" + +# Where to do the build +PHP_MEMCACHED_BUILD_DIR="/tmp/php-memcached-build" + +# Check whether to enable building with protoocol and sasl support +check_protocol_support +check_sasl_support + +echo "Enable protocol: $ENABLE_PROTOOCOL" +echo "Enable sasl: $ENABLE_SASL" + +set -e + +case $ACTION in + before_script) + # validate the package.xml + validate_package_xml || exit 1 + + # Install libmemcached version + install_libmemcached + + # Install igbinary extension + install_igbinary + + # install msgpack + install_msgpack + + # install SASL + if test "x$ENABLE_SASL" = "xyes"; then + install_sasl + fi + ;; + + script) + # Build the extension + build_php_memcached + + # Create configuration + if test "x$ENABLE_SASL" = "xyes"; then + create_memcached_test_configuration + fi + + # Run tests + set +e + run_memcached_tests || exit 1 + ;; + + *) + echo "Unknown action. Valid actions are: before_script and script" + exit 1 + ;; +esac + + + + + diff --git a/config.m4 b/config.m4 index 2d7ee2c9..8bdc5749 100644 --- a/config.m4 +++ b/config.m4 @@ -268,13 +268,6 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi - - if test "$PHP_MEMCACHED_SASL" != "no"; then - AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) - AC_MSG_CHECKING([whether to enable sasl support]) - AC_MSG_RESULT([$memcached_enable_sasl]) - fi - AC_MSG_CHECKING([for libmemcached location]) export ORIG_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" @@ -362,6 +355,41 @@ if test "$PHP_MEMCACHED" != "no"; then ) ]) + AC_MSG_CHECKING([whether to enable sasl support]) + if test "$PHP_MEMCACHED_SASL" != "no"; then + AC_MSG_RESULT(yes) + + AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) + + if test "$ac_cv_have_memc_sasl_h" = "yes"; then + + AC_CACHE_CHECK([whether libmemcached supports sasl], ac_cv_memc_sasl_support, [ + AC_TRY_COMPILE( + [ #include ], + [ + #if LIBMEMCACHED_WITH_SASL_SUPPORT + /* yes */ + #else + # error "no sasl support" + #endif + ], + [ ac_cv_memc_sasl_support="yes" ], + [ ac_cv_memc_sasl_support="no" ] + ) + ]) + + if test "$ac_cv_memc_sasl_support" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) + else + AC_MSG_ERROR([no, libmemcached sasl support is not enabled. Run configure with --disable-memcached-sasl to disable this check]) + fi + else + AC_MSG_ERROR([no, sasl.h is not available. Run configure with --disable-memcached-sasl to disable this check]) + fi + else + AC_MSG_RESULT([no]) + fi + CFLAGS="$ORIG_CFLAGS" LIBS="$ORIG_LIBS" diff --git a/package.xml b/package.xml index f3f06d1a..bb62d906 100644 --- a/package.xml +++ b/package.xml @@ -63,6 +63,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + @@ -147,6 +148,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 19b0ac05..9162a279 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -30,4 +30,10 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len); # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) #endif +#ifdef HAVE_MEMCACHED_INSTANCE_ST +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif + #endif diff --git a/php_memcached.c b/php_memcached.c index 80da7577..da194412 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -44,53 +44,18 @@ #include #include -#include "php_memcached_server.h" #include "php_memcached.h" +#include "php_memcached_private.h" +#include "php_memcached_server.h" #include "g_fmt.h" #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" #endif - - #include "fastlz/fastlz.h" #include -/* Compatibility with older versions */ -#ifdef HAVE_MEMCACHED_INSTANCE_ST -typedef const memcached_instance_st * php_memcached_instance_st; -#else -typedef memcached_server_instance_st php_memcached_instance_st; -#endif - -/* Used to store the size of the block */ -#if defined(HAVE_INTTYPES_H) -#include -#elif defined(HAVE_STDINT_H) -#include -#endif - -#ifdef PHP_WIN32 -# include "win32/php_stdint.h" -#else -# ifndef HAVE_INT32_T -# if SIZEOF_INT == 4 -typedef int int32_t; -# elif SIZEOF_LONG == 4 -typedef long int int32_t; -# endif -# endif - -# ifndef HAVE_UINT32_T -# if SIZEOF_INT == 4 -typedef unsigned int uint32_t; -# elif SIZEOF_LONG == 4 -typedef unsigned long int uint32_t; -# endif -# endif -#endif - #ifdef HAVE_JSON_API # include "ext/json/php_json.h" #endif @@ -2770,6 +2735,7 @@ static PHP_METHOD(Memcached, setOption) static PHP_METHOD(Memcached, setSaslAuthData) { MEMC_METHOD_INIT_VARS; + memcached_return status; char *user, *pass; int user_len, pass_len; @@ -2790,7 +2756,12 @@ static PHP_METHOD(Memcached, setSaslAuthData) RETURN_FALSE; } m_obj->has_sasl_data = 1; - RETURN_BOOL(memcached_set_sasl_auth_data(m_obj->memc, user, pass)); + status = memcached_set_sasl_auth_data(m_obj->memc, user, pass); + + if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + RETURN_FALSE; + } + RETURN_TRUE; } /* }}} */ #endif /* HAVE_MEMCACHED_SASL */ @@ -3593,19 +3564,19 @@ static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_g { } -PHP_MEMCACHED_API +PHPAPI zend_class_entry *php_memc_get_ce(void) { return memcached_ce; } -PHP_MEMCACHED_API +PHPAPI zend_class_entry *php_memc_get_exception(void) { return memcached_exception_ce; } -PHP_MEMCACHED_API +PHPAPI zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) { #if HAVE_SPL @@ -4446,8 +4417,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) #endif #if HAVE_MEMCACHED_SASL - REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); - REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); + REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE); #endif diff --git a/php_memcached.h b/php_memcached.h index 4a68eb7e..4c3eb4de 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -19,146 +19,20 @@ #ifndef PHP_MEMCACHED_H #define PHP_MEMCACHED_H -#include "php_libmemcached_compat.h" +#include "php.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif -extern zend_module_entry memcached_module_entry; -#define phpext_memcached_ptr &memcached_module_entry - -#ifdef PHP_WIN32 -#define PHP_MEMCACHED_API __declspec(dllexport) -#else -#define PHP_MEMCACHED_API -#endif - -/**************************************** - Structures and definitions -****************************************/ -enum memcached_serializer { - SERIALIZER_PHP = 1, - SERIALIZER_IGBINARY = 2, - SERIALIZER_JSON = 3, - SERIALIZER_JSON_ARRAY = 4, - SERIALIZER_MSGPACK = 5, -}; -#ifdef HAVE_MEMCACHED_IGBINARY -#define SERIALIZER_DEFAULT SERIALIZER_IGBINARY -#define SERIALIZER_DEFAULT_NAME "igbinary" -#elif HAVE_MEMCACHED_MSGPACK -#define SERIALIZER_DEFAULT SERIALIZER_MSGPACK -#define SERIALIZER_DEFAULT_NAME "msgpack" -#else -#define SERIALIZER_DEFAULT SERIALIZER_PHP -#define SERIALIZER_DEFAULT_NAME "php" -#endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ - -#if LIBMEMCACHED_WITH_SASL_SUPPORT -# if defined(HAVE_SASL_SASL_H) -# include -# define HAVE_MEMCACHED_SASL 1 -# endif -#endif - -#ifdef HAVE_MEMCACHED_PROTOCOL -typedef enum { - MEMC_SERVER_ON_MIN = -1, - MEMC_SERVER_ON_CONNECT = 0, - MEMC_SERVER_ON_ADD = 1, - MEMC_SERVER_ON_APPEND = 2, - MEMC_SERVER_ON_DECREMENT = 3, - MEMC_SERVER_ON_DELETE = 4, - MEMC_SERVER_ON_FLUSH = 5, - MEMC_SERVER_ON_GET = 6, - MEMC_SERVER_ON_INCREMENT = 7, - MEMC_SERVER_ON_NOOP = 8, - MEMC_SERVER_ON_PREPEND = 9, - MEMC_SERVER_ON_QUIT = 10, - MEMC_SERVER_ON_REPLACE = 11, - MEMC_SERVER_ON_SET = 12, - MEMC_SERVER_ON_STAT = 13, - MEMC_SERVER_ON_VERSION = 14, - MEMC_SERVER_ON_MAX -} php_memc_event_t; - - -typedef struct { - zend_fcall_info fci; - zend_fcall_info_cache fci_cache; -} php_memc_server_cb_t; -#endif - -ZEND_BEGIN_MODULE_GLOBALS(php_memcached) -#ifdef HAVE_MEMCACHED_SESSION - zend_bool sess_locking_enabled; - long sess_lock_wait; - long sess_lock_max_wait; - long sess_lock_expire; - char* sess_prefix; - zend_bool sess_locked; - char* sess_lock_key; - int sess_lock_key_len; - - int sess_number_of_replicas; - zend_bool sess_randomize_replica_read; - zend_bool sess_remove_failed_enabled; - long sess_connect_timeout; - zend_bool sess_consistent_hash_enabled; - zend_bool sess_binary_enabled; - - char *sess_sasl_username; - char *sess_sasl_password; -#if HAVE_MEMCACHED_SASL - zend_bool sess_sasl_data; -#endif -#endif - char *serializer_name; - enum memcached_serializer serializer; - - char *compression_type; - int compression_type_real; - int compression_threshold; - - double compression_factor; -#if HAVE_MEMCACHED_SASL - zend_bool use_sasl; -#endif -#ifdef HAVE_MEMCACHED_PROTOCOL - struct { - php_memc_server_cb_t callbacks [14]; - } server; -#endif - long store_retry_count; -ZEND_END_MODULE_GLOBALS(php_memcached) - -PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); -PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void); -PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); - -PHP_RINIT_FUNCTION(memcached); -PHP_RSHUTDOWN_FUNCTION(memcached); -PHP_MINIT_FUNCTION(memcached); -PHP_MSHUTDOWN_FUNCTION(memcached); -PHP_MINFO_FUNCTION(memcached); - #define PHP_MEMCACHED_VERSION "2.2.0b1" -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) -#else -#define MEMC_G(v) (php_memcached_globals.v) -#endif - -typedef struct { - memcached_st *memc_sess; - zend_bool is_persistent; -} memcached_sess; +PHPAPI zend_class_entry *php_memc_get_ce(void); +PHPAPI zend_class_entry *php_memc_get_exception(void); +PHPAPI zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); -int php_memc_sess_list_entry(void); - -char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +extern zend_module_entry memcached_module_entry; +#define phpext_memcached_ptr &memcached_module_entry #endif /* PHP_MEMCACHED_H */ diff --git a/php_memcached_private.h b/php_memcached_private.h new file mode 100644 index 00000000..0fabc1f5 --- /dev/null +++ b/php_memcached_private.h @@ -0,0 +1,184 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +/* $ Id: $ */ + +#ifndef PHP_MEMCACHED_PRIVATE_H +#define PHP_MEMCACHED_PRIVATE_H + +#include "php_libmemcached_compat.h" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef PHP_WIN32 +# include "win32/php_stdint.h" +#else +/* Used to store the size of the block */ +# if defined(HAVE_INTTYPES_H) +# include +# elif defined(HAVE_STDINT_H) +# include +# endif +#endif + +#ifndef HAVE_INT32_T +# if SIZEOF_INT == 4 +typedef int int32_t; +# elif SIZEOF_LONG == 4 +typedef long int int32_t; +# endif +#endif + +#ifndef HAVE_UINT32_T +# if SIZEOF_INT == 4 +typedef unsigned int uint32_t; +# elif SIZEOF_LONG == 4 +typedef unsigned long int uint32_t; +# endif +#endif + +/**************************************** + Structures and definitions +****************************************/ +enum memcached_serializer { + SERIALIZER_PHP = 1, + SERIALIZER_IGBINARY = 2, + SERIALIZER_JSON = 3, + SERIALIZER_JSON_ARRAY = 4, + SERIALIZER_MSGPACK = 5, +}; +#ifdef HAVE_MEMCACHED_IGBINARY +#define SERIALIZER_DEFAULT SERIALIZER_IGBINARY +#define SERIALIZER_DEFAULT_NAME "igbinary" +#elif HAVE_MEMCACHED_MSGPACK +#define SERIALIZER_DEFAULT SERIALIZER_MSGPACK +#define SERIALIZER_DEFAULT_NAME "msgpack" +#else +#define SERIALIZER_DEFAULT SERIALIZER_PHP +#define SERIALIZER_DEFAULT_NAME "php" +#endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ + +#if LIBMEMCACHED_WITH_SASL_SUPPORT +# if defined(HAVE_SASL_SASL_H) +# include +# define HAVE_MEMCACHED_SASL 1 +# endif +#endif + +#ifdef HAVE_MEMCACHED_PROTOCOL +typedef enum { + MEMC_SERVER_ON_MIN = -1, + MEMC_SERVER_ON_CONNECT = 0, + MEMC_SERVER_ON_ADD = 1, + MEMC_SERVER_ON_APPEND = 2, + MEMC_SERVER_ON_DECREMENT = 3, + MEMC_SERVER_ON_DELETE = 4, + MEMC_SERVER_ON_FLUSH = 5, + MEMC_SERVER_ON_GET = 6, + MEMC_SERVER_ON_INCREMENT = 7, + MEMC_SERVER_ON_NOOP = 8, + MEMC_SERVER_ON_PREPEND = 9, + MEMC_SERVER_ON_QUIT = 10, + MEMC_SERVER_ON_REPLACE = 11, + MEMC_SERVER_ON_SET = 12, + MEMC_SERVER_ON_STAT = 13, + MEMC_SERVER_ON_VERSION = 14, + MEMC_SERVER_ON_MAX +} php_memc_event_t; + + +typedef struct { + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; +} php_memc_server_cb_t; +#endif + +ZEND_BEGIN_MODULE_GLOBALS(php_memcached) +#ifdef HAVE_MEMCACHED_SESSION + zend_bool sess_locking_enabled; + long sess_lock_wait; + long sess_lock_max_wait; + long sess_lock_expire; + char* sess_prefix; + zend_bool sess_locked; + char* sess_lock_key; + int sess_lock_key_len; + + int sess_number_of_replicas; + zend_bool sess_randomize_replica_read; + zend_bool sess_remove_failed_enabled; + long sess_connect_timeout; + zend_bool sess_consistent_hash_enabled; + zend_bool sess_binary_enabled; + + char *sess_sasl_username; + char *sess_sasl_password; +#if HAVE_MEMCACHED_SASL + zend_bool sess_sasl_data; +#endif +#endif + char *serializer_name; + enum memcached_serializer serializer; + + char *compression_type; + int compression_type_real; + int compression_threshold; + + double compression_factor; +#if HAVE_MEMCACHED_SASL + zend_bool use_sasl; +#endif +#ifdef HAVE_MEMCACHED_PROTOCOL + struct { + php_memc_server_cb_t callbacks [14]; + } server; +#endif + long store_retry_count; +ZEND_END_MODULE_GLOBALS(php_memcached) + +PHP_RINIT_FUNCTION(memcached); +PHP_RSHUTDOWN_FUNCTION(memcached); +PHP_MINIT_FUNCTION(memcached); +PHP_MSHUTDOWN_FUNCTION(memcached); +PHP_MINFO_FUNCTION(memcached); + +#ifdef ZTS +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) +#else +#define MEMC_G(v) (php_memcached_globals.v) +#endif + +typedef struct { + memcached_st *memc_sess; + zend_bool is_persistent; +} memcached_sess; + +int php_memc_sess_list_entry(void); + +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); + +#endif /* PHP_MEMCACHED_PRIVATE_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/php_memcached_server.c b/php_memcached_server.c index 8c5db704..5cead492 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -20,6 +20,7 @@ #include #include "php_memcached.h" +#include "php_memcached_private.h" #include "php_memcached_server.h" #include "php_libmemcached_compat.h" diff --git a/php_memcached_session.c b/php_memcached_session.c index 9d538cfa..8b4b95f7 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -32,6 +32,7 @@ #include #include "php_memcached.h" +#include "php_memcached_private.h" #include "php_memcached_session.h" extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) diff --git a/tests/config.inc b/tests/config.inc index 5edfa2cc..6d298487 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -1,19 +1,40 @@ setOptions ($opts) == false) echo "Failed to set options" . PHP_EOL; - $memcached->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + $memcached->addServer($host, $port); $memcached->flush (); return $memcached; } +function memc_get_instance (array $opts = array (), $persistent_id = null) +{ + return memc_create_instance(MEMC_SERVER_HOST, MEMC_SERVER_PORT, $opts, $persistent_id); +} + +function memc_get_sasl_instance (array $opts = array (), $persistent_id = null) +{ + return memc_create_instance(MEMC_SASL_SERVER_HOST, MEMC_SASL_SERVER_PORT, $opts, $persistent_id); +} + function memc_run_test ($test_function, $options = array ()) { foreach ($options as $option_set) { @@ -43,21 +64,3 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ), ); } - -function memc_get_serializer_options ($skipmsgpack=false) -{ - $options = memc_create_combinations ('PHP', Memcached::SERIALIZER_PHP); - - if (Memcached::HAVE_IGBINARY) { - $options = array_merge ($options, memc_create_combinations ('igbinary', Memcached::SERIALIZER_IGBINARY)); - } - - if (Memcached::HAVE_JSON) { - $options = array_merge ($options, memc_create_combinations ('JSON', Memcached::SERIALIZER_JSON, true)); - } - - if (Memcached::HAVE_MSGPACK && !$skipmsgpack) { - $options = array_merge ($options, memc_create_combinations ('msgpack', Memcached::SERIALIZER_MSGPACK)); - } - return $options; -} diff --git a/tests/sasl_basic.phpt b/tests/sasl_basic.phpt new file mode 100644 index 00000000..03fcb98b --- /dev/null +++ b/tests/sasl_basic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Test SASL authentication +--SKIPIF-- + +--INI-- +memcached.use_sasl = on +--FILE-- + true + )); + +var_dump ($m->setSaslAuthData (MEMC_SASL_USER, MEMC_SASL_PASS)); + +$key = uniqid ('sasl_test_'); +var_dump ($m->set ($key, 'set using sasl')); +var_dump ($m->get ($key)); + + +echo "OK" . PHP_EOL; +?> +--EXPECT-- +bool(true) +bool(true) +string(14) "set using sasl" +OK diff --git a/travis.sh b/travis.sh deleted file mode 100755 index 51afd8df..00000000 --- a/travis.sh +++ /dev/null @@ -1,178 +0,0 @@ -#!/bin/bash - -function validate_package_xml() { - retval=0 - for file in tests/*.phpt; do - grep $(basename $file) package.xml >/dev/null - if [ $? != 0 ]; then - echo "Missing $file from package.xml" - retval=1; - fi - done - return $retval; -} - -function install_libmemcached() { - local libmemcached_version=$1 - local libmemcached_prefix=$2 - local enable_protocol=$3 - - wget "https://launchpad.net/libmemcached/1.0/$%7Blibmemcached_version%7D/+download/libmemcached-$%7Blibmemcached_version%7D.tar.gz" -O libmemcached-${libmemcached_version}.tar.gz - - tar xvfz libmemcached-${libmemcached_version}.tar.gz - pushd "libmemcached-${libmemcached_version}" - - if test "x$enable_protocol" = "xyes"; then - protocol_flag="--enable-libmemcachedprotocol" - fi - - ./configure --prefix="$PHP_LIBMEMCACHED_PREFIX" $protocol_flag LDFLAGS="-lpthread" - make - make install - popd -} - -function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git - pushd igbinary - phpize - ./configure - make - make install - popd -} - -function install_msgpack() { - git clone https://github.com/msgpack/msgpack-php.git - pushd msgpack-php - phpize - ./configure - make - make install - popd -} - -function build_php_memcached() { - local libmemcached_prefix=$1 - local php_memcached_version=$2 - local enable_protocol=$3 - - pear package - mkdir /tmp/php-memcached-build - tar xfz "memcached-${php_memcached_version}.tgz" -C /tmp/php-memcached-build - pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" - phpize - - if test "x$enable_protocol" = "xyes"; then - protocol_flag="--enable-memcached-protocol" - fi - - ./configure --with-libmemcached-dir="$libmemcached_prefix" $protocol_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack - make - make install - popd -} - -function run_memcached_tests() { - local php_memcached_version=$1 - - export NO_INTERACTION=1 - export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` - - pushd "/tmp/php-memcached-build/memcached-${php_memcached_version}" - # We have one xfail test, we run it separately - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt - rm ./tests/expire.phpt - - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt - retval=$? - for i in `ls tests/*.out 2>/dev/null`; do - echo "-- START ${i}"; - cat $i; - echo ""; - echo "-- END"; - done - popd - - return $retval; -} - -# Command line arguments -ACTION=$1 -PHP_LIBMEMCACHED_VERSION=$2 - -if test "x$ACTION" = "x"; then - echo "Usage: $0 " - exit 1 -fi - -if test "x$PHP_LIBMEMCACHED_VERSION" = "x"; then - echo "Usage: $0 " - exit 1 -fi - -# the extension version -PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') - -# Libmemcached install dir -PHP_LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${PHP_LIBMEMCACHED_VERSION}" - -# Check whether to enable building with protoocol support -DPKG=`which dpkg` - -if [ "x$DPKG" = "x" ]; then - echo "dpkg not found, enabling protocol support" - ENABLE_PROTOOCOL=yes -else - dpkg --compare-versions "$PHP_LIBMEMCACHED_VERSION" gt 1.0.15 - if [ $? = 0 ]; then - ENABLE_PROTOOCOL=yes - else - ENABLE_PROTOOCOL=no - fi -fi - -echo "Enable protocol: $ENABLE_PROTOOCOL" - -set -e - -case $ACTION in - before_script) - # validate the package.xml - validate_package_xml || exit 1 - - # Install libmemcached version - install_libmemcached $PHP_LIBMEMCACHED_VERSION $PHP_LIBMEMCACHED_PREFIX $ENABLE_PROTOOCOL - - # Install igbinary extension - install_igbinary - - # install msgpack - install_msgpack - ;; - - script) - # Build the extension - build_php_memcached $PHP_LIBMEMCACHED_PREFIX $PHP_MEMCACHED_VERSION $ENABLE_PROTOOCOL - - # Make sure that memcached is running - sudo service memcached restart - netstat -an | grep LISTEN - nc -vv -z 127.0.0.1 11211 - - # Run tests - set +e - run_memcached_tests $PHP_MEMCACHED_VERSION || exit 1 - ;; - - *) - echo "Unknown action. Valid actions are: before_script and script" - exit 1 - ;; -esac - - - - - From 59189f9486b9fe4e2cfa52019a19ad494bd0d5e2 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 00:03:17 +0800 Subject: [PATCH 311/694] Added a note about fixed sasl return code --- ChangeLog | 1 + package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2ba3b177..7e43c6b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ Version 2.2.0b1 * Added support for memcached protocol handlers * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization + * Memcached::setSaslAuthData returns correct status on success Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index bb62d906..1a5d7e7e 100644 --- a/package.xml +++ b/package.xml @@ -49,6 +49,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Added support for memcached protocol handlers - Added Memcached::setBucket for virtual bucket support - Added support for msgpack serialization +- Memcached::setSaslAuthData returns correct status on success From 797c8bb62364445a700fbaa883e2f01df7150b96 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 00:17:07 +0800 Subject: [PATCH 312/694] Correct variable here --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 9534c7e0..f90cae9f 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -125,7 +125,7 @@ function build_php_memcached() { local sasl_flag="--disable-memcached-sasl" if test "x$ENABLE_SASL" = "xyes"; then - protocol_flag="--enable-memcached-sasl" + sasl_flag="--enable-memcached-sasl" fi ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack From 6def3bbc92b7399f1f56fb56eea4f1aa66a62ac6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 01:12:18 +0800 Subject: [PATCH 313/694] Fix the message --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 8bdc5749..3b01d776 100644 --- a/config.m4 +++ b/config.m4 @@ -20,7 +20,7 @@ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer suppo PHP_ARG_ENABLE(memcached-msgpack, whether to enable memcached msgpack serializer support, [ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) -PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, +PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], yes, no) PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, From d9d5ce86f6f3848a5b113fa0b21cdde3c8fae8d2 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 01:50:24 +0800 Subject: [PATCH 314/694] Fixed a bug with config options and test for it --- php_memcached.c | 2 +- tests/setoptions.phpt | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index da194412..f3d2c53f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2540,7 +2540,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML flag = (memcached_behavior) option; convert_to_long(value); - if (Z_LVAL_P(value) >= 0 && Z_LVAL_P(value) < MEMCACHED_BEHAVIOR_MAX) { + if (flag >= 0 && flag < MEMCACHED_BEHAVIOR_MAX) { rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); } else { diff --git a/tests/setoptions.phpt b/tests/setoptions.phpt index 8b5c04db..97fc37ec 100644 --- a/tests/setoptions.phpt +++ b/tests/setoptions.phpt @@ -3,7 +3,7 @@ Set options using setOptions --SKIPIF-- --FILE-- -setOptions(array( Memcached::OPT_SERIALIZER => Memcached::SERIALIZER_PHP, Memcached::OPT_COMPRESSION => 0, Memcached::OPT_LIBKETAMA_COMPATIBLE => 1, + Memcached::OPT_CONNECT_TIMEOUT => 5000, ))); var_dump($m->getOption(Memcached::OPT_PREFIX_KEY) == 'a_prefix'); @@ -20,18 +21,14 @@ var_dump($m->getOption(Memcached::OPT_COMPRESSION) == 0); var_dump($m->getOption(Memcached::OPT_LIBKETAMA_COMPATIBLE) == 1); echo "test invalid options\n"; -error_reporting(0); var_dump($m->setOptions(array( "asdf" => 123 ))); -echo $php_errormsg, "\n"; -$php_errormsg = ''; var_dump($m->setOptions(array( -1 => 123 ))); -echo $php_errormsg, "\n"; --EXPECTF-- bool(true) @@ -40,7 +37,9 @@ bool(true) bool(true) bool(true) test invalid options + +Warning: Memcached::setOptions(): invalid configuration option in %s on line %d bool(false) -%s::setOptions(): invalid configuration option + +Warning: Memcached::setOptions(): error setting memcached option: %s in %s on line %d bool(false) -%s::setOptions(): error setting memcached option: %s From a437602912b7ed252341430251ba99d7ff9da247 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 13:48:52 +0800 Subject: [PATCH 315/694] Reorganise headers a bit, include everything in the private header --- config.m4 | 2 -- php_libmemcached_compat.c | 2 ++ php_libmemcached_compat.h | 4 ---- php_memcached.c | 22 ---------------------- php_memcached.h | 1 + php_memcached_private.h | 22 +++++++++++++++++++++- php_memcached_server.c | 6 ------ php_memcached_session.c | 17 ----------------- 8 files changed, 24 insertions(+), 52 deletions(-) diff --git a/config.m4 b/config.m4 index 3b01d776..7b134a15 100644 --- a/config.m4 +++ b/config.m4 @@ -479,8 +479,6 @@ if test "$PHP_MEMCACHED" != "no"; then [ PHP_ADD_EXTENSION_DEP(memcached, spl, true) ]) - fi - fi diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index 6ab853e6..dee5f5b5 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -14,6 +14,8 @@ +----------------------------------------------------------------------+ */ +#include "php_memcached.h" +#include "php_memcached_private.h" #include "php_libmemcached_compat.h" memcached_st *php_memc_create_str (const char *str, size_t str_len) diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 9162a279..7642f402 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -20,10 +20,6 @@ /* this is the version(s) we support */ #include -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - memcached_st *php_memc_create_str (const char *str, size_t str_len); #ifndef HAVE_LIBMEMCACHED_SERVER_TEMPORARILY_MARKER_DISABLED diff --git a/php_memcached.c b/php_memcached.c index f3d2c53f..f9434c32 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -22,28 +22,6 @@ * - ability to set binary protocol for sessions */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#ifdef ZTS -#include "TSRM.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - #include "php_memcached.h" #include "php_memcached_private.h" #include "php_memcached_server.h" diff --git a/php_memcached.h b/php_memcached.h index 4c3eb4de..33306cf6 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -20,6 +20,7 @@ #define PHP_MEMCACHED_H #include "php.h" +#include "main/php_config.h" #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/php_memcached_private.h b/php_memcached_private.h index 0fabc1f5..1a521349 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -19,12 +19,32 @@ #ifndef PHP_MEMCACHED_PRIVATE_H #define PHP_MEMCACHED_PRIVATE_H -#include "php_libmemcached_compat.h" +#include "main/php_config.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include "php_libmemcached_compat.h" + +#include +#include +#include +#include + +#ifdef ZTS +# include "TSRM.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + #ifdef PHP_WIN32 # include "win32/php_stdint.h" #else diff --git a/php_memcached_server.c b/php_memcached_server.c index 5cead492..42ccc8ee 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -14,15 +14,9 @@ +----------------------------------------------------------------------+ */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include #include "php_memcached.h" #include "php_memcached_private.h" #include "php_memcached_server.h" -#include "php_libmemcached_compat.h" #include diff --git a/php_memcached_session.c b/php_memcached_session.c index 8b4b95f7..91529e0b 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -14,23 +14,6 @@ +----------------------------------------------------------------------+ */ -#include -#include -#include -#include - -#ifdef ZTS -#include "TSRM.h" -#endif - -#include -#include -#include -#include -#include -#include -#include - #include "php_memcached.h" #include "php_memcached_private.h" #include "php_memcached_session.h" From 411a64fdcb49a049d02c848cbc519f3aa7613b10 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 15:21:11 +0800 Subject: [PATCH 316/694] Make config.m4 play nice when building inside the source tree --- config.m4 | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/config.m4 b/config.m4 index 7b134a15..2ea30d58 100644 --- a/config.m4 +++ b/config.m4 @@ -291,15 +291,12 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) - ORIG_CFLAGS="$CFLAGS" - ORIG_LIBS="$LIBS" - - CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" - # # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once # - LIBS="$LIBS -lpthread $PHP_LIBMEMCACHED_LIBS" + LIBS="$LIBS -lpthread" + ORIG_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $INCLUDES" AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ AC_TRY_COMPILE( @@ -358,7 +355,6 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_CHECKING([whether to enable sasl support]) if test "$PHP_MEMCACHED_SASL" != "no"; then AC_MSG_RESULT(yes) - AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) if test "$ac_cv_have_memc_sasl_h" = "yes"; then @@ -379,6 +375,7 @@ if test "$PHP_MEMCACHED" != "no"; then ]) if test "$ac_cv_memc_sasl_support" = "yes"; then + PHP_CHECK_LIBRARY(sasl2, sasl_client_init, [PHP_ADD_LIBRARY(sasl2, 1, MEMCACHED_SHARED_LIBADD)]) AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) else AC_MSG_ERROR([no, libmemcached sasl support is not enabled. Run configure with --disable-memcached-sasl to disable this check]) @@ -390,9 +387,6 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi - CFLAGS="$ORIG_CFLAGS" - LIBS="$ORIG_LIBS" - if test "$ac_cv_have_memcached_instance_st" = "yes"; then AC_DEFINE(HAVE_MEMCACHED_INSTANCE_ST, [1], [Whether memcached_instance_st is defined]) fi @@ -428,9 +422,6 @@ if test "$PHP_MEMCACHED" != "no"; then if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then AC_MSG_RESULT([enabled]) - ORIG_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" - AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [ AC_TRY_COMPILE( [ #include ], @@ -441,7 +432,6 @@ if test "$PHP_MEMCACHED" != "no"; then [ ac_cv_have_libmemcachedprotocol="no" ] ) ]) - CFLAGS="$ORIG_CFLAGS" if test "$ac_cv_have_libmemcachedprotocol" != "yes"; then AC_MSG_ERROR([Cannot enable libmemcached protocol]) @@ -469,6 +459,8 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi + CFLAGS="$ORIG_CFLAGS" + export PKG_CONFIG_PATH="$ORIG_PKG_CONFIG_PATH" PHP_SUBST(MEMCACHED_SHARED_LIBADD) From feed35e22040b874ba6fc8659dc16b498e6e4150 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 24 Nov 2013 16:26:47 +0800 Subject: [PATCH 317/694] Version based tests: Do version checks in one place, fix check when setting options --- config.m4 | 83 ++------------------------------------- php_libmemcached_compat.c | 2 +- php_libmemcached_compat.h | 23 ++++++++++- php_memcached.c | 36 +++++++++-------- php_memcached_session.c | 4 +- 5 files changed, 49 insertions(+), 99 deletions(-) diff --git a/config.m4 b/config.m4 index 2ea30d58..b484f29f 100644 --- a/config.m4 +++ b/config.m4 @@ -273,6 +273,10 @@ if test "$PHP_MEMCACHED" != "no"; then if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then export PKG_CONFIG_PATH="$PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR/pkgconfig" + + if test ! -f "$PHP_LIBMEMCACHED_DIR/include/libmemcached/memcached.h"; then + AC_MSG_ERROR(Unable to find memcached.h under $PHP_LIBMEMCACHED_DIR) + fi else export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/$PHP_LIBDIR/pkgconfig:/usr/$PHP_LIBDIR/pkgconfig:/opt/$PHP_LIBDIR/pkgconfig" fi @@ -294,64 +298,9 @@ if test "$PHP_MEMCACHED" != "no"; then # # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once # - LIBS="$LIBS -lpthread" ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $INCLUDES" - AC_CACHE_CHECK([whether memcached_instance_st is defined], ac_cv_have_memcached_instance_st, [ - AC_TRY_COMPILE( - [ #include ], - [ const memcached_instance_st *instance = NULL; ], - [ ac_cv_have_memcached_instance_st="yes" ], - [ ac_cv_have_memcached_instance_st="no" ] - ) - ]) - - AC_CACHE_CHECK([whether MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS is defined], ac_cv_have_libmemcached_remove_failed_servers, [ - AC_TRY_COMPILE( - [ #include ], - [ (void)MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS; ], - [ ac_cv_have_libmemcached_remove_failed_servers="yes" ], - [ ac_cv_have_libmemcached_remove_failed_servers="no" ] - ) - ]) - - AC_CACHE_CHECK([whether MEMCACHED_SERVER_TEMPORARILY_DISABLED is defined], ac_cv_have_libmemcached_server_temporarily_disabled, [ - AC_TRY_COMPILE( - [ #include ], - [ (void)MEMCACHED_SERVER_TEMPORARILY_DISABLED; ], - [ ac_cv_have_libmemcached_server_temporarily_disabled="yes" ], - [ ac_cv_have_libmemcached_server_temporarily_disabled="no" ] - ) - ]) - - AC_CACHE_CHECK([whether memcached function exists], ac_cv_have_libmemcached_memcached, [ - AC_TRY_LINK( - [ #include ], - [ memcached("t", sizeof ("t")); ], - [ ac_cv_have_libmemcached_memcached="yes" ], - [ ac_cv_have_libmemcached_memcached="no" ] - ) - ]) - - AC_CACHE_CHECK([whether libmemcached_check_configuration function exists], ac_cv_have_libmemcached_check_configuration, [ - AC_TRY_LINK( - [ #include ], - [ libmemcached_check_configuration("", 1, "", 1); ], - [ ac_cv_have_libmemcached_check_configuration="yes" ], - [ ac_cv_have_libmemcached_check_configuration="no" ] - ) - ]) - - AC_CACHE_CHECK([whether memcached_touch function exists], ac_cv_have_libmemcached_touch, [ - AC_TRY_LINK( - [ #include ], - [ memcached_touch (NULL, NULL, 0, 0); ], - [ ac_cv_have_libmemcached_touch="yes" ], - [ ac_cv_have_libmemcached_touch="no" ] - ) - ]) - AC_MSG_CHECKING([whether to enable sasl support]) if test "$PHP_MEMCACHED_SASL" != "no"; then AC_MSG_RESULT(yes) @@ -387,30 +336,6 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi - if test "$ac_cv_have_memcached_instance_st" = "yes"; then - AC_DEFINE(HAVE_MEMCACHED_INSTANCE_ST, [1], [Whether memcached_instance_st is defined]) - fi - - if test "$ac_cv_have_libmemcached_remove_failed_servers" = "yes"; then - AC_DEFINE(HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS, [1], [Whether MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS is defined]) - fi - - if test "$ac_cv_have_libmemcached_server_temporarily_disabled" = "yes"; then - AC_DEFINE(HAVE_LIBMEMCACHED_SERVER_TEMPORARILY_MARKER_DISABLED, [1], [Whether MEMCACHED_SERVER_TEMPORARILY_DISABLED is defined]) - fi - - if test "$ac_cv_have_libmemcached_memcached" = "yes"; then - AC_DEFINE(HAVE_LIBMEMCACHED_MEMCACHED, [1], [Whether memcached is defined]) - fi - - if test "$ac_cv_have_libmemcached_check_configuration" = "yes"; then - AC_DEFINE(HAVE_LIBMEMCACHED_CHECK_CONFIGURATION, [1], [Whether libmemcached_check_configuration is defined]) - fi - - if test "$ac_cv_have_libmemcached_touch" = "yes"; then - AC_DEFINE(HAVE_LIBMEMCACHED_TOUCH, [1], [Whether memcached_touch is defined]) - fi - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" if test "$PHP_MEMCACHED_SESSION" != "no"; then diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index dee5f5b5..f238709e 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -20,7 +20,7 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len) { -#if HAVE_LIBMEMCACHED_MEMCACHED +#ifdef HAVE_LIBMEMCACHED_MEMCACHED return memcached (str, str_len); #else memcached_return rc; diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 7642f402..b76c62a7 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -22,10 +22,31 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len); -#ifndef HAVE_LIBMEMCACHED_SERVER_TEMPORARILY_MARKER_DISABLED +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000 # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) #endif +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 +# define HAVE_MEMCACHED_TOUCH 1 +#endif + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 +# define HAVE_MEMCACHED_INSTANCE_ST 1 +#endif + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 +# define HAVE_LIBMEMCACHED_CHECK_CONFIGURATION 1 +#endif + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 +# define HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS 1 +#endif + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 +# define HAVE_LIBMEMCACHED_MEMCACHED 1 +#endif + + #ifdef HAVE_MEMCACHED_INSTANCE_ST typedef const memcached_instance_st * php_memcached_instance_st; #else diff --git a/php_memcached.c b/php_memcached.c index f9434c32..b8b014ef 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -452,7 +452,7 @@ static PHP_METHOD(Memcached, __construct) if (plist_key) { efree(plist_key); } -#if HAVE_LIBMEMCACHED_CHECK_CONFIGURATION +#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION if (libmemcached_check_configuration(conn_str, conn_str_len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "configuration error %s", error_buffer); } else { @@ -1159,7 +1159,7 @@ PHP_METHOD(Memcached, setByKey) } /* }}} */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 +#ifdef HAVE_MEMCACHED_TOUCH /* {{{ Memcached::touch(string key, [, int expiration ]) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) @@ -1496,7 +1496,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool key_len, payload, payload_len, expiration, flags); } break; -#ifdef HAVE_LIBMEMCACHED_TOUCH +#ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: if (!server_key) { status = memcached_touch(m_obj->memc, key, key_len, expiration); @@ -2126,7 +2126,7 @@ PHP_METHOD(Memcached, flushBuffers) } /* }}} */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 +#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION /* {{{ Memcached::getLastErrorMessage() Returns the last error message that occurred */ PHP_METHOD(Memcached, getLastErrorMessage) @@ -2515,14 +2515,19 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML /* * Assume that it's a libmemcached behavior option. */ - flag = (memcached_behavior) option; - convert_to_long(value); - - if (flag >= 0 && flag < MEMCACHED_BEHAVIOR_MAX) { - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + if (option < 0) { + rc = MEMCACHED_INVALID_ARGUMENTS; } else { - rc = MEMCACHED_INVALID_ARGUMENTS; + flag = (memcached_behavior) option; + convert_to_long(value); + + if (flag < MEMCACHED_BEHAVIOR_MAX) { + rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + } + else { + rc = MEMCACHED_INVALID_ARGUMENTS; + } } if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { @@ -4124,7 +4129,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) -#if HAVE_LIBMEMCACHED_TOUCH +#ifdef HAVE_MEMCACHED_TOUCH MEMC_ME(touch, arginfo_touch) MEMC_ME(touchByKey, arginfo_touchByKey) #endif @@ -4155,10 +4160,9 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(addServers, arginfo_addServers) MEMC_ME(getServerList, arginfo_getServerList) MEMC_ME(getServerByKey, arginfo_getServerByKey) - MEMC_ME(resetServerList, arginfo_resetServerList) - MEMC_ME(quit, arginfo_quit) - MEMC_ME(flushBuffers, arginfo_flushBuffers) - + MEMC_ME(resetServerList, arginfo_resetServerList) + MEMC_ME(quit, arginfo_quit) + MEMC_ME(flushBuffers, arginfo_flushBuffers) #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) @@ -4346,7 +4350,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ); #endif -#if defined(HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS) && HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS +#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); #endif diff --git a/php_memcached_session.c b/php_memcached_session.c index 91529e0b..de8d1651 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -177,7 +177,7 @@ PS_OPEN_FUNC(memcached) } else { memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); if (!memc_sess->memc_sess) { -#if HAVE_LIBMEMCACHED_CHECK_CONFIGURATION +#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION char error_buffer[1024]; if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); @@ -247,7 +247,7 @@ PS_OPEN_FUNC(memcached) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached connection timeout"); return FAILURE; } -#if HAVE_LIBMEMCACHED_REMOVE_FAILED_SERVERS +#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { From 2aca48aa192915752301e1e091ff1b9d36e3704f Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 13:30:04 +0800 Subject: [PATCH 318/694] Add a few more versions --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4c82f64f..7de7bb7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,9 @@ env: - LIBMEMCACHED_VERSION=1.0.6 - LIBMEMCACHED_VERSION=1.0.2 - LIBMEMCACHED_VERSION=0.53 + - LIBMEMCACHED_VERSION=0.49 - LIBMEMCACHED_VERSION=0.44 + - LIBMEMCACHED_VERSION=0.40 services: - memcached # will start memcached From db9f9ef876d113506ed519022042d7efc59471a9 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 13:44:49 +0800 Subject: [PATCH 319/694] Skip test if touch is not available --- tests/expire.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/expire.phpt b/tests/expire.phpt index 92a63bf3..d4a306a1 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -3,7 +3,9 @@ Memcached store, fetch & touch expired key --XFAIL-- https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- - + --FILE-- Date: Mon, 25 Nov 2013 13:57:54 +0800 Subject: [PATCH 320/694] Skip test if touch is not available --- tests/expire.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/expire.phpt b/tests/expire.phpt index d4a306a1..0c8587ff 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -4,7 +4,7 @@ Memcached store, fetch & touch expired key https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- --FILE-- Date: Mon, 25 Nov 2013 15:02:54 +0800 Subject: [PATCH 321/694] Remove 0.40 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7de7bb7e..d529cf50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ env: - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.49 - LIBMEMCACHED_VERSION=0.44 - - LIBMEMCACHED_VERSION=0.40 services: - memcached # will start memcached From b1d21a7943d1612547f382127552a7dcc0e885f4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 15:42:01 +0800 Subject: [PATCH 322/694] Use ginit to initialise globals --- php_memcached.c | 97 ++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index b8b014ef..2464527c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3509,44 +3509,6 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ return retval; } -static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) -{ -#ifdef HAVE_MEMCACHED_SESSION - MEMC_G(sess_locking_enabled) = 1; - MEMC_G(sess_binary_enabled) = 1; - MEMC_G(sess_consistent_hash_enabled) = 0; - MEMC_G(sess_number_of_replicas) = 0; - MEMC_G(sess_remove_failed_enabled) = 0; - MEMC_G(sess_prefix) = NULL; - MEMC_G(sess_lock_wait) = 0; - MEMC_G(sess_lock_max_wait) = 0; - MEMC_G(sess_lock_expire) = 0; - MEMC_G(sess_locked) = 0; - MEMC_G(sess_lock_key) = NULL; - MEMC_G(sess_lock_key_len) = 0; - MEMC_G(sess_randomize_replica_read) = 0; - MEMC_G(sess_connect_timeout) = 1000; - MEMC_G(sess_sasl_username) = NULL; - MEMC_G(sess_sasl_password) = NULL; -#if HAVE_MEMCACHED_SASL - MEMC_G(sess_sasl_data) = 0; -#endif -#endif - MEMC_G(serializer_name) = NULL; - MEMC_G(serializer) = SERIALIZER_DEFAULT; - MEMC_G(compression_type) = NULL; - MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; - MEMC_G(compression_factor) = 1.30; -#if HAVE_MEMCACHED_SASL - MEMC_G(use_sasl) = 0; -#endif - MEMC_G(store_retry_count) = 2; -} - -static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) -{ -} - PHPAPI zend_class_entry *php_memc_get_ce(void) { @@ -4225,13 +4187,43 @@ static const zend_module_dep memcached_deps[] = { }; #endif +static +PHP_GINIT_FUNCTION(php_memcached) +{ +#ifdef HAVE_MEMCACHED_SESSION + php_memcached_globals->sess_locking_enabled = 1; + php_memcached_globals->sess_binary_enabled = 1; + php_memcached_globals->sess_consistent_hash_enabled = 0; + php_memcached_globals->sess_number_of_replicas = 0; + php_memcached_globals->sess_remove_failed_enabled = 0; + php_memcached_globals->sess_prefix = NULL; + php_memcached_globals->sess_lock_wait = 0; + php_memcached_globals->sess_lock_max_wait = 0; + php_memcached_globals->sess_lock_expire = 0; + php_memcached_globals->sess_locked = 0; + php_memcached_globals->sess_lock_key = NULL; + php_memcached_globals->sess_lock_key_len = 0; + php_memcached_globals->sess_randomize_replica_read = 0; + php_memcached_globals->sess_connect_timeout = 1000; + php_memcached_globals->sess_sasl_username = NULL; + php_memcached_globals->sess_sasl_password = NULL; +#if HAVE_MEMCACHED_SASL + php_memcached_globals->sess_sasl_data = 0; +#endif +#endif + php_memcached_globals->serializer_name = NULL; + php_memcached_globals->serializer = SERIALIZER_DEFAULT; + php_memcached_globals->compression_type = NULL; + php_memcached_globals->compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->compression_factor = 1.30; +#if HAVE_MEMCACHED_SASL + php_memcached_globals->use_sasl = 0; +#endif + php_memcached_globals->store_retry_count = 2; +} + zend_module_entry memcached_module_entry = { -#if ZEND_MODULE_API_NO >= 20050922 - STANDARD_MODULE_HEADER_EX, NULL, - (zend_module_dep*)memcached_deps, -#else STANDARD_MODULE_HEADER, -#endif "memcached", NULL, PHP_MINIT(memcached), @@ -4240,7 +4232,11 @@ zend_module_entry memcached_module_entry = { NULL, PHP_MINFO(memcached), PHP_MEMCACHED_VERSION, - STANDARD_MODULE_PROPERTIES + PHP_MODULE_GLOBALS(php_memcached), + PHP_GINIT(php_memcached), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ @@ -4514,13 +4510,6 @@ PHP_MINIT_FUNCTION(memcached) php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU); -#ifdef ZTS - ts_allocate_id(&php_memcached_globals_id, sizeof(zend_php_memcached_globals), - (ts_allocate_ctor) php_memc_init_globals, (ts_allocate_dtor) php_memc_destroy_globals); -#else - php_memc_init_globals(&php_memcached_globals TSRMLS_CC); -#endif - #ifdef HAVE_MEMCACHED_SESSION php_session_register_module(ps_memcached_ptr); #endif @@ -4547,12 +4536,6 @@ PHP_MSHUTDOWN_FUNCTION(memcached) } #endif -#ifdef ZTS - ts_free_id(php_memcached_globals_id); -#else - php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC); -#endif - UNREGISTER_INI_ENTRIES(); return SUCCESS; } From 619302c1ef60576e073f5c3753f8d14f61eac4e1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 16:23:06 +0800 Subject: [PATCH 323/694] These settings are not needed if sasl is disabled --- php_memcached.c | 5 +++-- php_memcached_private.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2464527c..21fe739a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -293,9 +293,10 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) - +#if HAVE_MEMCACHED_SASL STD_PHP_INI_ENTRY("memcached.sess_sasl_username", "", PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.sess_sasl_password", "", PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) +#endif #endif STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) @@ -4205,9 +4206,9 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->sess_lock_key_len = 0; php_memcached_globals->sess_randomize_replica_read = 0; php_memcached_globals->sess_connect_timeout = 1000; +#if HAVE_MEMCACHED_SASL php_memcached_globals->sess_sasl_username = NULL; php_memcached_globals->sess_sasl_password = NULL; -#if HAVE_MEMCACHED_SASL php_memcached_globals->sess_sasl_data = 0; #endif #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index 1a521349..c78abad1 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -146,9 +146,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool sess_consistent_hash_enabled; zend_bool sess_binary_enabled; +#if HAVE_MEMCACHED_SASL char *sess_sasl_username; char *sess_sasl_password; -#if HAVE_MEMCACHED_SASL zend_bool sess_sasl_data; #endif #endif From c3079ae8f51d0d33de4bd97992e558459d1909de Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 17:10:40 +0800 Subject: [PATCH 324/694] Fix release date --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 1a5d7e7e..afbe8d25 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-11-19 + 2013-11-25 2.2.0b1 2.2.0 From a555e381f063bacfeb8d71defa9e0d4d861952e4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 25 Nov 2013 17:11:53 +0800 Subject: [PATCH 325/694] Add a note regarding user flags --- ChangeLog | 1 + package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7e43c6b0..b9b00ea5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ Version 2.2.0b1 * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization * Memcached::setSaslAuthData returns correct status on success + * Added support for user-defined flags in set and get operations Version 2.1.0 ------------- diff --git a/package.xml b/package.xml index afbe8d25..0f5c164b 100644 --- a/package.xml +++ b/package.xml @@ -50,6 +50,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Added Memcached::setBucket for virtual bucket support - Added support for msgpack serialization - Memcached::setSaslAuthData returns correct status on success +- Added support for user-defined flags in set and get operations From 3d324df8b4cdb4c6eb5ed8d7d6d054ce32d84436 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 26 Nov 2013 13:47:28 +0800 Subject: [PATCH 326/694] Change windows stuff here, not that anyone uses it --- config.w32 | 1 + php_memcached.c | 6 +++--- php_memcached.h | 12 +++++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/config.w32 b/config.w32 index 8b10efbe..380a9a12 100644 --- a/config.w32 +++ b/config.w32 @@ -14,4 +14,5 @@ if (PHP_MEMCACHED == "yes") { } EXTENSION("memcached", "memcached.c"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); + AC_DEFINE("MEMCACHED_EXPORTS", 1) } diff --git a/php_memcached.c b/php_memcached.c index 21fe739a..71c7ef84 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3510,19 +3510,19 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ return retval; } -PHPAPI +PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void) { return memcached_ce; } -PHPAPI +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void) { return memcached_exception_ce; } -PHPAPI +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) { #if HAVE_SPL diff --git a/php_memcached.h b/php_memcached.h index 33306cf6..38811d1b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -28,9 +28,15 @@ #define PHP_MEMCACHED_VERSION "2.2.0b1" -PHPAPI zend_class_entry *php_memc_get_ce(void); -PHPAPI zend_class_entry *php_memc_get_exception(void); -PHPAPI zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); +#if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) +#define PHP_MEMCACHED_API __declspec(dllexport) +#else +#define PHP_MEMCACHED_API PHPAPI +#endif + +PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void); +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry From f794ebed54048e5dd6d858469a4b06e4722d331a Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 8 Jan 2014 11:36:21 +0100 Subject: [PATCH 327/694] Fix compression of serialized objects. Due to commit 0f5550efe0b00e90b00fef80d0de4840244c15f1, compressing a serialized object provided an inappropriate size to `s_compress_value()` which will eventually lead to a segfault during compression. Provide the the previously computed length instead. --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 71c7ef84..a6b2b231 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3266,7 +3266,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags /* If we have compression flag, compress the value */ if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ - *payload_len = Z_STRLEN_P(value); + *payload_len = pl_len; payload = s_compress_value (compression_type, pl, payload_len, flags TSRMLS_CC); } From 98e7e6bc1503fbd1571f4fc2bf8f1e22f587e317 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 8 Jan 2014 11:43:46 +0100 Subject: [PATCH 328/694] Fix compression on big-endian architecture On big-endian architecture where size_t is a 64-bit long, copying the 4 first bytes as the size is incorrect. We cast it to an unsigned 32-bit integer before copying it at the beginning of the provided buffer. --- php_memcached.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 71c7ef84..756ded4f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3084,9 +3084,10 @@ char *s_compress_value (enum memcached_compression_type compression_type, const /* Store compressed size here */ size_t compressed_size = 0; + uint32_t plen = *payload_len; /* Copy the uin32_t at the beginning */ - memcpy(buffer, payload_len, sizeof(uint32_t)); + memcpy(buffer, &plen, sizeof(uint32_t)); buffer += sizeof(uint32_t); switch (compression_type) { From a8a837d7f169cdbb35c5ff8ae496684288b2c8c5 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 8 Jan 2014 11:49:48 +0100 Subject: [PATCH 329/694] Add `sess_lock_*` and `store_retry_count` entries to moduleinfo test Those entries have been added recently but the test was not updated. --- tests/experimental/moduleinfo.phpt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 941e2f27..e4f2367a 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -26,10 +26,13 @@ memcached.serializer => %s => %s memcached.sess_binary => %d => %d memcached.sess_connect_timeout => %d => %d memcached.sess_consistent_hash => %d => %d +memcached.sess_lock_expire => %d => %d +memcached.sess_lock_max_wait => %d => %d memcached.sess_lock_wait => %d => %d memcached.sess_locking => %d => %d memcached.sess_number_of_replicas => %d => %d memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d memcached.sess_remove_failed => %d => %d -memcached.use_sasl => %d => %d \ No newline at end of file +memcached.use_sasl => %d => %d +memcached.store_retry_count => %d => %d \ No newline at end of file From 50651d58846c5672c8050e0c852cd0ce54297a2a Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 8 Jan 2014 11:53:35 +0100 Subject: [PATCH 330/694] Make output of `use_sasl` entry in moduleinfo test optional When SASL support is compiled out, this entry is absent. Nonetheless, test should succeed in a such case. --- tests/experimental/moduleinfo.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index e4f2367a..a1f59b44 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -34,5 +34,5 @@ memcached.sess_number_of_replicas => %d => %d memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d memcached.sess_remove_failed => %d => %d -memcached.use_sasl => %d => %d -memcached.store_retry_count => %d => %d \ No newline at end of file +%rmemcached.use_sasl => %d => %d +|%rmemcached.store_retry_count => %d => %d \ No newline at end of file From 391d0c14eb6e62a8a6caa662f1b47381ef9da611 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 9 Jan 2014 16:28:05 +0100 Subject: [PATCH 331/694] Move tests using serialized objects and compression out of experimental --- package.xml | 2 ++ tests/{experimental/serializer => }/serializer_php.phpt | 0 tests/{experimental => }/set_comp_below_factor.phpt | 0 3 files changed, 2 insertions(+) rename tests/{experimental/serializer => }/serializer_php.phpt (100%) rename tests/{experimental => }/set_comp_below_factor.phpt (100%) diff --git a/package.xml b/package.xml index 0f5c164b..ff1cfec4 100644 --- a/package.xml +++ b/package.xml @@ -151,6 +151,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + diff --git a/tests/experimental/serializer/serializer_php.phpt b/tests/serializer_php.phpt similarity index 100% rename from tests/experimental/serializer/serializer_php.phpt rename to tests/serializer_php.phpt diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/set_comp_below_factor.phpt similarity index 100% rename from tests/experimental/set_comp_below_factor.phpt rename to tests/set_comp_below_factor.phpt From 82227e5084e4530166cec21acaea99312f54a73b Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 8 Jan 2014 11:26:10 +0100 Subject: [PATCH 332/694] `getServerByKey` cannot report weight anymore Due to a change in libmemcached (exposed in 5450f45a3ee9ca520c108a043dd10fbe9b5535ac), `getServerByKey` is not able any more to report a server weight. It reports 0 instead. This makes the test on this function fails. We fix this by expecting a weight of 0 instead of a weight of 1. --- tests/experimental/getserverbykey.phpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/experimental/getserverbykey.phpt b/tests/experimental/getserverbykey.phpt index d35647cf..507bfb42 100644 --- a/tests/experimental/getserverbykey.phpt +++ b/tests/experimental/getserverbykey.phpt @@ -31,7 +31,7 @@ array(%d) { ["port"]=> int(%d) ["weight"]=> - int(1) + int(0) } array(%d) { ["host"]=> @@ -39,7 +39,7 @@ array(%d) { ["port"]=> int(%d) ["weight"]=> - int(1) + int(0) } array(%d) { ["host"]=> @@ -47,7 +47,7 @@ array(%d) { ["port"]=> int(%d) ["weight"]=> - int(1) + int(0) } array(%d) { ["host"]=> @@ -55,5 +55,5 @@ array(%d) { ["port"]=> int(%d) ["weight"]=> - int(1) + int(0) } From 77a217a21dfa1bf6117fef9894af61cd6ccfd73e Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 9 Jan 2014 16:36:03 +0100 Subject: [PATCH 333/694] Move `getserverbykey` test out of experimental --- package.xml | 1 + tests/{experimental => }/getserverbykey.phpt | 0 2 files changed, 1 insertion(+) rename tests/{experimental => }/getserverbykey.phpt (100%) diff --git a/package.xml b/package.xml index ff1cfec4..3e9ac6fe 100644 --- a/package.xml +++ b/package.xml @@ -153,6 +153,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/experimental/getserverbykey.phpt b/tests/getserverbykey.phpt similarity index 100% rename from tests/experimental/getserverbykey.phpt rename to tests/getserverbykey.phpt From 43460341a24b80ddb686e1f8c927071f87cbce69 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 16 Jan 2014 09:19:18 +0100 Subject: [PATCH 334/694] Revert "Move tests using serialized objects and compression out of experimental" This reverts commit 391d0c14eb6e62a8a6caa662f1b47381ef9da611. Conflicts: package.xml --- package.xml | 2 -- tests/{ => experimental/serializer}/serializer_php.phpt | 0 tests/{ => experimental}/set_comp_below_factor.phpt | 0 3 files changed, 2 deletions(-) rename tests/{ => experimental/serializer}/serializer_php.phpt (100%) rename tests/{ => experimental}/set_comp_below_factor.phpt (100%) diff --git a/package.xml b/package.xml index 3e9ac6fe..afd961f7 100644 --- a/package.xml +++ b/package.xml @@ -151,8 +151,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - diff --git a/tests/serializer_php.phpt b/tests/experimental/serializer/serializer_php.phpt similarity index 100% rename from tests/serializer_php.phpt rename to tests/experimental/serializer/serializer_php.phpt diff --git a/tests/set_comp_below_factor.phpt b/tests/experimental/set_comp_below_factor.phpt similarity index 100% rename from tests/set_comp_below_factor.phpt rename to tests/experimental/set_comp_below_factor.phpt From eb12debadea88170f16a3a9db468042548a6ebb3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 1 Mar 2014 21:03:20 +0800 Subject: [PATCH 335/694] Update package.xml for release --- package.xml | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/package.xml b/package.xml index afd961f7..fd97e76a 100644 --- a/package.xml +++ b/package.xml @@ -21,9 +21,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-11-25 + 2013-01-15 - 2.2.0b1 + 2.2.0b2 2.2.0 @@ -32,25 +32,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Reinstate support for libememcached 0.x series -- Added SASL support to session handler -- Added Memcached::flushBuffers as per GH #78 -- Fixes GH #54: Fixed UDP server adding with newer libmemcached -- Fixed PHP bug #65334: (Segfault if uncompress value failed) -- Fixes GH #14: get with cas token fails to fetch all results -- Fixes GH #68: memcached 2.1.0 requires libmemcached 1.0.10 -- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 -- Merged PR #91: More granular session locking support -- Added session handler settings: - * memcached.sess_number_of_replicas - * memcached.sess_randomize_replica_read - * memcached.sess_remove_failed - * memcached.sess_connect_timeout -- Added support for memcached protocol handlers -- Added Memcached::setBucket for virtual bucket support -- Added support for msgpack serialization -- Memcached::setSaslAuthData returns correct status on success -- Added support for user-defined flags in set and get operations +- Fixes incorrect size when compressing serialized objects +- Fixes endianess of compressed values From b37618ddf45647ca76e12d4c1aa026b1bbf991ac Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 1 Mar 2014 21:07:04 +0800 Subject: [PATCH 336/694] Prepare this as RC1, we need to get this stuff out --- package.xml | 6 ++++-- php_memcached.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index fd97e76a..0e997dfd 100644 --- a/package.xml +++ b/package.xml @@ -21,9 +21,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-01-15 + 2013-03-01 - 2.2.0b2 + 2.2.0RC1 2.2.0 @@ -134,6 +134,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + diff --git a/php_memcached.h b/php_memcached.h index 38811d1b..3d450e30 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -26,7 +26,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "2.2.0b1" +#define PHP_MEMCACHED_VERSION "2.2.0rc1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 303b9e5de372c88af014e4505b6d0e8a22e64766 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 1 Mar 2014 21:57:13 +0800 Subject: [PATCH 337/694] Remove the tests --- package.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.xml b/package.xml index 0e997dfd..6f36cfa6 100644 --- a/package.xml +++ b/package.xml @@ -134,8 +134,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - From 03811a17f4e7eb0536a4ee3d72e096077baf2464 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 12 Mar 2014 17:20:16 +0800 Subject: [PATCH 338/694] Update dates --- package.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 6f36cfa6..13e67750 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-03-01 + 2013-03-12 2.2.0RC1 2.2.0 @@ -155,6 +155,15 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + betastable + 2.2.0RC12.2.0 + 2014-03-12 + +- Fixes incorrect size when compressing serialized objects +- Fixes endianess of compressed values + + betastable 2.2.0b12.2.0 From 77a8089666d75793ab94cdd6d507a68ee3bed2dd Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Wed, 12 Mar 2014 15:38:37 +0100 Subject: [PATCH 339/694] Added the OPT_SERVER_TIMEOUT_LIMIT behaviour. The option MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT was added in libmemcached 1.0.18 (0x01000018). For more information see https://answers.launchpad.net/libmemcached/+question/239497 The merge request for libmemcached: https://code.launchpad.net/~493pocbrcycmdw7yksonho9o2qzz-o18bz-d18ecat4t1b76tkfi3vttrkfngli/libmemcached/feature-server_timeout --- memcached-api.php | 2 ++ php_libmemcached_compat.h | 3 +++ php_memcached.c | 3 +++ 3 files changed, 8 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 8319bfc9..d22d0cf9 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -65,6 +65,8 @@ class Memcached { const OPT_SERVER_FAILURE_LIMIT; + const OPT_SERVER_TIMEOUT_LIMIT; + const OPT_CACHE_LOOKUPS; const OPT_AUTO_EJECT_HOSTS; diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index b76c62a7..ae400d9c 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -46,6 +46,9 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len); # define HAVE_LIBMEMCACHED_MEMCACHED 1 #endif +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018 +# define HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT 1 +#endif #ifdef HAVE_MEMCACHED_INSTANCE_ST typedef const memcached_instance_st * php_memcached_instance_st; diff --git a/php_memcached.c b/php_memcached.c index 0b4c437e..8cd4ee8b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4351,6 +4351,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) #ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); #endif +#ifdef HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT + REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_TIMEOUT_LIMIT, MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT); +#endif /* * libmemcached result codes From 2bce9bc097df61a4426847efacc2b46eaa72b518 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:30:35 +0100 Subject: [PATCH 340/694] fix php_memcached.c:3737:21: warning: variable 'intern' set but not used --- php_memcached.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 0b4c437e..f4d7fd02 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3734,8 +3734,6 @@ PHP_METHOD(MemcachedServer, run) static PHP_METHOD(MemcachedServer, on) { - php_memc_server_t *intern; - long event; zend_fcall_info fci; zend_fcall_info_cache fci_cache; @@ -3745,8 +3743,6 @@ PHP_METHOD(MemcachedServer, on) return; } - intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); - if (event <= MEMC_SERVER_ON_MIN || event >= MEMC_SERVER_ON_MAX) { RETURN_FALSE; } From cb7a7fd65eae366b09fe333fa318581312c69002 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:35:53 +0100 Subject: [PATCH 341/694] fix warning: 'payload' may be used uninitialized in this function (ok, was a false positive) --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f4d7fd02..3ecc601a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1393,7 +1393,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval *value; long expiration = 0; long udf_flags = 0; - char *payload; + char *payload = NULL; size_t payload_len; uint32_t flags = 0; uint32_t retry = 0; @@ -1556,7 +1556,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool RETVAL_TRUE; } - if (op != MEMC_OP_TOUCH) { + if (payload) { efree(payload); } } From c616a1be161b90b4d37f06b4c7d6e75ade1eb5a5 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:41:21 +0100 Subject: [PATCH 342/694] Fix php_memcached_server.c:589:49: warning: array subscript is above array bounds --- php_memcached_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index c78abad1..0ec2d76e 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -165,7 +165,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #endif #ifdef HAVE_MEMCACHED_PROTOCOL struct { - php_memc_server_cb_t callbacks [14]; + php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX]; } server; #endif long store_retry_count; From 697e500b88138149cb1063cd18fcec63b2fff895 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:48:06 +0100 Subject: [PATCH 343/694] php_memcached.c:3317:11: warning: 'buffer' may be used uninitialized in this function (just to make gcc happy) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 3ecc601a..f170ca55 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3286,7 +3286,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags static char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) { - char *buffer; + char *buffer = NULL; uint32_t len; unsigned long length; zend_bool decompress_status = 0; From ccea7be732166c05f8f77ba9c244fc4a31baf2d1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:50:07 +0100 Subject: [PATCH 344/694] Fix warning: 'status' may be used uninitialized in this function --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index f170ca55..dff8276f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1545,6 +1545,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool default: /* not reached */ + status = 0; assert(0); break; } From 573c978f8abb07e897b60bda6493d58b3922d8ce Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 Mar 2014 10:52:42 +0100 Subject: [PATCH 345/694] Fix php_memcached.c:781:45: warning: 'orig_cas_flag' may be used uninitialized in this function (again... just to make gcc happy) --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index dff8276f..4b3f9495 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -702,7 +702,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint64_t cas = 0; zval *cas_tokens = NULL; zval *udf_flags = NULL; - uint64_t orig_cas_flag; + uint64_t orig_cas_flag = 0; zval *value; long get_flags = 0; int i = 0; @@ -907,7 +907,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ zval **entry = NULL; const char **mkeys = NULL; size_t *mkeys_len = NULL; - uint64_t orig_cas_flag; + uint64_t orig_cas_flag = 0; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; int i = 0; From ea6d0d83ea7c35c54b87e517514e030778f1d847 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 1 Apr 2014 09:33:42 +0800 Subject: [PATCH 346/694] Prepare a stable release --- package.xml | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/package.xml b/package.xml index 13e67750..0ada99cd 100644 --- a/package.xml +++ b/package.xml @@ -21,19 +21,18 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-03-12 + 2013-04-01 - 2.2.0RC1 + 2.2.0 2.2.0 - beta - beta + stable + stable PHP -- Fixes incorrect size when compressing serialized objects -- Fixes endianess of compressed values +- Added the OPT_SERVER_TIMEOUT_LIMIT behaviour @@ -155,6 +154,28 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + stablestable + 2.2.02.2.0 + 2014-04-01 + +- Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + + + + betastable + 2.2.0b12.2.0 + 2013-10-28 + +- Reinstate support for libememcached 0.x series +- Added SASL support to session handler +- Added Memcached::flushBuffers as per GH #78 +- Fixes GH #54: Fixed UDP server adding with newer libmemcached +- Fixed PHP bug #65334: (Segfault if uncompress value failed) +- Fixes GH #14: get with cas token fails to fetch all results +- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 + + betastable 2.2.0RC12.2.0 From f4c397786538da8874ec05a714421e1a913ba1d0 Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 1 Apr 2014 18:21:58 +0800 Subject: [PATCH 347/694] Update version number to indicate stable --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 3d450e30..bce8e37b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -26,7 +26,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "2.2.0rc1" +#define PHP_MEMCACHED_VERSION "2.2.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 7ad95cc555ea045e6f91852a1ee93c4348587edb Mon Sep 17 00:00:00 2001 From: Mikko Date: Tue, 1 Apr 2014 18:23:00 +0800 Subject: [PATCH 348/694] The year is 2014 --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 0ada99cd..9a4ff054 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2013-04-01 + 2014-04-01 2.2.0 2.2.0 From 85ca1f1b9d8d5642f73357fdd47c2602c5435065 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Sep 2014 16:28:07 +0300 Subject: [PATCH 349/694] This should resolve #144 --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index de8d1651..a3ef5678 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -51,7 +51,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) if (lock_expire <= 0) { lock_expire = lock_maxwait; } - expiration = time(NULL) + lock_expire + 1; + expiration = lock_expire + 1; attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ From ada08ebfe056514f9e67d84ec7690a8bb5987fc1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 5 Sep 2014 19:42:54 +0200 Subject: [PATCH 350/694] allow to use system FastLZ --- config.m4 | 21 ++++++++++++++++++--- php_memcached.c | 5 ++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/config.m4 b/config.m4 index b484f29f..94a0e7d3 100644 --- a/config.m4 +++ b/config.m4 @@ -26,6 +26,9 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocoll support], no, no) +PHP_ARG_WITH(system-fastlz, wheter to use system FastLZ bibrary, +[ --with-system-fastlz Use system FastLZ bibrary], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) @@ -336,7 +339,17 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" + + if test "$PHP_SYSTEM_FASTLZ" != "no"; then + AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) + PHP_CHECK_LIBRARY(fastlz, fastlz_compress, + [PHP_ADD_LIBRARY(fastlz, 1, MEMCACHED_SHARED_LIBADD)], + [AC_MSG_ERROR(FastLZ library not found)]) + else + ac_cv_have_fastlz="no" + PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} fastlz/fastlz.c" + fi if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" @@ -390,8 +403,10 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_SUBST(MEMCACHED_SHARED_LIBADD) PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $LIBEVENT_INCLUDES $MSGPACK_INCLUDES) - PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) - + if test "ac_cv_have_fastlz" != "yes"; then + PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) + fi + ifdef([PHP_ADD_EXTENSION_DEP], [ PHP_ADD_EXTENSION_DEP(memcached, spl, true) diff --git a/php_memcached.c b/php_memcached.c index b21ecd42..2bd39d10 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -30,8 +30,11 @@ #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" #endif - +#ifdef HAVE_FASTLZ_H +#include +#else #include "fastlz/fastlz.h" +#endif #include #ifdef HAVE_JSON_API From 7270cf3032f0f816ab60f42e9d657f01bc874fea Mon Sep 17 00:00:00 2001 From: Anthony Ryan Date: Sun, 28 Sep 2014 01:01:56 -0400 Subject: [PATCH 351/694] Fix a typo in the arguments help Just noticed this when skimming through the code. --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 94a0e7d3..107f8cbe 100644 --- a/config.m4 +++ b/config.m4 @@ -26,7 +26,7 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocoll support], no, no) -PHP_ARG_WITH(system-fastlz, wheter to use system FastLZ bibrary, +PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, [ --with-system-fastlz Use system FastLZ bibrary], no, no) if test -z "$PHP_ZLIB_DIR"; then From d9c085b0ca2e1a7fbb496eaa1c580a0bb6e09072 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 22 Oct 2014 16:20:59 +0100 Subject: [PATCH 352/694] Added test for bug #155 --- tests/gh_155.phpt | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/gh_155.phpt diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt new file mode 100644 index 00000000..c1f02bc6 --- /dev/null +++ b/tests/gh_155.phpt @@ -0,0 +1,41 @@ +--TEST-- +Test for bug 155 +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL,true); +$m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +$key = 'bug_155_' . uniqid(); + +$m->set ($key, 'test', time() + 86400); + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +$m->touch ($key, time() + 86400); +echo "TOUCH: " . $m->getResultMessage() . PHP_EOL; + +$m->touch ($key, time() + 86400); +echo "TOUCH: " . $m->getResultMessage() . PHP_EOL; + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +echo "DONE" . PHP_EOL; + +--EXPECT-- +GET: SUCCESS +TOUCH: SUCCESS +TOUCH: SUCCESS +GET: SUCCESS +GET: SUCCESS +DONE \ No newline at end of file From c157d8a3d0a2e57a3ef1bfbff0509545bf5482c6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 22 Oct 2014 16:22:01 +0100 Subject: [PATCH 353/694] Added bug #155 test to package.xml --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 9a4ff054..0ebc86f9 100644 --- a/package.xml +++ b/package.xml @@ -134,6 +134,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + From 657e373c9219782e317cefd5b8d7d50da1a9780c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 26 Nov 2014 09:23:01 +0100 Subject: [PATCH 354/694] Foreign serializers like msgpack and igbinary may crash on randomly initialized zval because they check of IS_ARRAY, IS_OBJECT (or any type) on certain circumstances. --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2bd39d10..c1bce93b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -838,7 +838,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); res_key [res_key_len] = '\0'; - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { zval_ptr_dtor(&value); @@ -1057,7 +1057,7 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { memcached_result_free(&result); @@ -1114,7 +1114,7 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { memcached_result_free(&result); @@ -3663,7 +3663,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); From 949195d28b4e4bf06a690b50379a22312f4f80a5 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 08:02:42 -0800 Subject: [PATCH 355/694] PHP7 Support --- php_memcached.c | 1197 +++++++++++++++++++-------------------- php_memcached.h | 2 +- php_memcached_private.h | 2 +- php_memcached_server.c | 478 ++++++++-------- php_memcached_server.h | 4 +- php_memcached_session.c | 78 +-- 6 files changed, 838 insertions(+), 923 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c1bce93b..33570992 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -122,14 +122,6 @@ php_memc_t* i_obj = NULL; \ struct memc_obj* m_obj = NULL; -#define MEMC_METHOD_FETCH_OBJECT \ - i_obj = (php_memc_t *) zend_object_store_get_object( object TSRMLS_CC ); \ - m_obj = i_obj->obj; \ - if (!m_obj) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memcached constructor was not called"); \ - return; \ - } - #ifndef DVAL_TO_LVAL #ifdef _WIN64 # define DVAL_TO_LVAL(d, l) \ @@ -150,12 +142,6 @@ #define RETURN_FROM_GET RETURN_FALSE -#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3) -#define zend_parse_parameters_none() \ - zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") -#endif - - /**************************************** Structures and definitions ****************************************/ @@ -165,8 +151,6 @@ enum memcached_compression_type { }; typedef struct { - zend_object zo; - struct memc_obj { memcached_st *memc; zend_bool compression; @@ -182,8 +166,22 @@ typedef struct { zend_bool is_pristine; int rescode; int memc_errno; + zend_object zo; } php_memc_t; +static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { + return (php_memc_t *)((char *)(obj) - XtOffsetOf(php_memc_t, zo)); +} +#define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); + +#define MEMC_METHOD_FETCH_OBJECT \ + i_obj = Z_MEMC_OBJ_P(object); \ + m_obj = i_obj->obj; \ + if (!m_obj) { \ + php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ + return; \ + } + #ifdef HAVE_MEMCACHED_PROTOCOL typedef struct { @@ -244,41 +242,41 @@ static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value, "fastlz")) { + } else if (!strcmp(new_value->val, "fastlz")) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value, "zlib")) { + } else if (!strcmp(new_value->val, "zlib")) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; } - return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { MEMC_G(serializer) = SERIALIZER_DEFAULT; - } else if (!strcmp(new_value, "php")) { + } else if (!strcmp(new_value->val, "php")) { MEMC_G(serializer) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY - } else if (!strcmp(new_value, "igbinary")) { + } else if (!strcmp(new_value->val, "igbinary")) { MEMC_G(serializer) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API - } else if (!strcmp(new_value, "json")) { + } else if (!strcmp(new_value->val, "json")) { MEMC_G(serializer) = SERIALIZER_JSON; - } else if (!strcmp(new_value, "json_array")) { + } else if (!strcmp(new_value->val, "json_array")) { MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK - } else if (!strcmp(new_value, "msgpack")) { + } else if (!strcmp(new_value->val, "msgpack")) { MEMC_G(serializer) = SERIALIZER_MSGPACK; #endif // msgpack } else { return FAILURE; } - return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } /* {{{ INI entries */ @@ -316,9 +314,9 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); -static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); +static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); +static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); +static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -326,68 +324,66 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); 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_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); +static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); /**************************************** Method implementations ****************************************/ -char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; - if (fci->object_ptr) { - spprintf (&buffer, 0, "%s::%s", Z_OBJCE_P (fci->object_ptr)->name, fci_cache->function_handler->common.function_name); + if (fci->object) { + spprintf (&buffer, 0, "%s::%s", fci->object->ce->name->val, fci_cache->function_handler->common.function_name); } else { - if (Z_TYPE_P (fci->function_name) == IS_OBJECT) { - spprintf (&buffer, 0, "%s", Z_OBJCE_P (fci->function_name)->name); + if (Z_TYPE (fci->function_name) == IS_OBJECT) { + spprintf (&buffer, 0, "%s", Z_OBJCE (fci->function_name)->name->val); } else { - spprintf (&buffer, 0, "%s", Z_STRVAL_P (fci->function_name)); + spprintf (&buffer, 0, "%s", Z_STRVAL (fci->function_name)); } } return buffer; } -static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len TSRMLS_DC) +static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { - zend_bool retval = 1; - zval pid_z; - zval *retval_ptr, *pid_z_ptr = &pid_z; - zval **params[2]; + zend_bool ret = 1; + zval retval; + zval params[2]; - INIT_ZVAL(pid_z); if (persistent_id) { - ZVAL_STRINGL(pid_z_ptr, persistent_id, persistent_id_len, 1); + ZVAL_STR(¶ms[1], persistent_id); + } else { + ZVAL_NULL(¶ms[1]); } /* Call the cb */ - params[0] = &object; - params[1] = &pid_z_ptr; + ZVAL_COPY_VALUE(¶ms[0], object); fci->params = params; fci->param_count = 2; - fci->retval_ptr_ptr = &retval_ptr; + fci->retval = &retval; fci->no_separation = 1; - if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { - char *buf = php_memc_printable_func (fci, fci_cache TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); + if (zend_call_function(fci, fci_cache) == FAILURE) { + char *buf = php_memc_printable_func (fci, fci_cache); + php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); efree (buf); - retval = 0; + ret = 0; } - zval_dtor(pid_z_ptr); - if (retval_ptr) { - zval_ptr_dtor(&retval_ptr); - } - return retval; + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); + return ret; } static int le_memc, le_memc_sess; @@ -404,32 +400,28 @@ static PHP_METHOD(Memcached, __construct) zval *object = getThis(); php_memc_t *i_obj; struct memc_obj *m_obj = NULL; - char *persistent_id = NULL, *conn_str = NULL; - int persistent_id_len, conn_str_len; + zend_string *persistent_id = NULL; + zend_string *conn_str = NULL; zend_bool is_persistent = 0; - - char *plist_key = NULL; - int plist_key_len = 0; - + zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f!s", &persistent_id, &persistent_id_len, &fci, &fci_cache, &conn_str, &conn_str_len) == FAILURE) { - ZVAL_NULL(object); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { + ZEND_CTOR_MAKE_NULL(); return; } - i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC); + i_obj = Z_MEMC_OBJ_P(object); i_obj->is_pristine = 0; - if (persistent_id && *persistent_id) { - zend_rsrc_list_entry *le = NULL; + if (persistent_id && persistent_id->len) { + zend_resource *le; is_persistent = 1; - plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id); - plist_key_len += 1; - - if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { + plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); + snprintf(plist_key->val, plist_key->len+1, "memcached:id=%s", persistent_id->val); + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; } @@ -443,27 +435,27 @@ static PHP_METHOD(Memcached, __construct) m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); if (m_obj == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle"); + php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); /* not reached */ } if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str, conn_str_len); + m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); if (!m_obj->memc) { char error_buffer[1024]; if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str, conn_str_len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "configuration error %s", error_buffer); + if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); } #else - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); #endif /* not reached */ } @@ -471,9 +463,9 @@ static PHP_METHOD(Memcached, __construct) m_obj->memc = memcached_create(NULL); if (m_obj->memc == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); /* not reached */ } } @@ -487,15 +479,15 @@ static PHP_METHOD(Memcached, __construct) i_obj->is_pristine = 1; if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len TSRMLS_CC) || EG(exception)) { + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { /* error calling or exception thrown from callback */ if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } i_obj->obj = NULL; if (is_persistent) { - php_memc_destroy(m_obj, is_persistent TSRMLS_CC); + php_memc_destroy(m_obj, is_persistent); } return; @@ -503,23 +495,23 @@ static PHP_METHOD(Memcached, __construct) } if (is_persistent) { - zend_rsrc_list_entry le; + zend_resource le; le.type = php_memc_list_entry(); le.ptr = m_obj; - if (zend_hash_update(&EG(persistent_list), (char *)plist_key, - plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + GC_REFCOUNT(&le) = 1; + if (zend_hash_update_mem(&EG(persistent_list), plist_key, &le, sizeof(le)) == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); /* not reached */ } } } if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } } /* }}} */ @@ -543,10 +535,8 @@ PHP_METHOD(Memcached, getByKey) /* {{{ -- php_memc_get_impl */ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key; + zend_string *server_key; const char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; @@ -562,12 +552,12 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|f!zz", &server_key, - &server_key_len, &key, &key_len, &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!zz", &server_key, &key, + &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!zz", &key, &key_len, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!zz", &key, &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } @@ -576,13 +566,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } - keys[0] = key; - key_lens[0] = key_len; + keys[0] = key->val; + key_lens[0] = key->len; uint64_t orig_cas_flag; orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); @@ -590,17 +580,17 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); - if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FROM_GET; } @@ -622,10 +612,10 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, return_value TSRMLS_CC); + status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { memcached_result_free(&result); RETURN_FROM_GET; } @@ -651,18 +641,22 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) cas = memcached_result_cas(&result); } - if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FROM_GET; } if (cas_token) { + ZVAL_DEREF(cas_token); + SEPARATE_ZVAL(cas_token); zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); } if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); } @@ -691,10 +685,9 @@ PHP_METHOD(Memcached, getMultiByKey) static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; size_t num_keys = 0; - zval **entry = NULL; + zval *entry = NULL; const char *payload = NULL; size_t payload_len = 0; const char **mkeys = NULL; @@ -706,7 +699,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *cas_tokens = NULL; zval *udf_flags = NULL; uint64_t orig_cas_flag = 0; - zval *value; + zval value; long get_flags = 0; int i = 0; zend_bool preserve_order; @@ -715,12 +708,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zlz", &server_key, - &server_key_len, &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zlz", &server_key, + &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } @@ -738,24 +731,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * Create the array of keys for libmemcached. If none of the keys were valid * (strings), set bad key result code and return. */ - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); - zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(keys))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } - if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { - mkeys[i] = Z_STRVAL_PP(entry); - mkeys_len[i] = Z_STRLEN_PP(entry); + if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { + mkeys[i] = Z_STRVAL_P(entry); + mkeys_len[i] = Z_STRLEN_P(entry); if (preserve_order) { - add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i] + 1); + add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i]); } i++; } - } + } ZEND_HASH_FOREACH_END(); if (i == 0) { i_obj->rescode = MEMCACHED_NOTFOUND; @@ -767,21 +757,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_tokens && PZVAL_IS_REF(cas_tokens)) { + if (cas_tokens && Z_IS_REF(cas_tokens)) { orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); /* Handle error, but ignore, there might still be some result */ - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); /* * Restore the CAS support flag, but only if we had to turn it on. */ - if (cas_tokens && PZVAL_IS_REF(cas_tokens) && orig_cas_flag == 0) { + if (cas_tokens && Z_IS_REF(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -793,15 +783,16 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as doubles, because we cannot store potential 64-bit values in longs. */ if (cas_tokens) { - if (PZVAL_IS_REF(cas_tokens)) { + if (Z_IS_REF(cas_tokens)) { /* cas_tokens was passed by reference, we'll create an array for it. */ + ZVAL_DEREF(cas_tokens); + SEPARATE_ZVAL(cas_tokens); zval_dtor(cas_tokens); array_init(cas_tokens); } else { /* Not passed by reference, we allow this (eg.: if you specify null to not enable cas but you want to use the udf_flags parameter). We destruct it and set it to null for the peace of mind. */ - zval_dtor(cas_tokens); cas_tokens = NULL; } } @@ -811,6 +802,8 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as longs. */ if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); array_init(udf_flags); } @@ -821,7 +814,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (status != MEMCACHED_SUCCESS) { status = MEMCACHED_SOME_ERRORS; - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); continue; } @@ -838,13 +831,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); res_key [res_key_len] = '\0'; - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { zval_ptr_dtor(&value); if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); memcached_quit(m_obj->memc); break; @@ -855,7 +846,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - add_assoc_zval_ex(return_value, res_key, res_key_len+1, value); + add_assoc_zval_ex(return_value, res_key, res_key_len+1, &value); if (cas_tokens) { cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); @@ -870,10 +861,14 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (EG(exception)) { /* XXX: cas_tokens should only be set on success, currently we're destructive */ if (cas_tokens) { + ZVAL_DEREF(cas_tokens); + SEPARATE_ZVAL(cas_tokens); zval_dtor(cas_tokens); ZVAL_NULL(cas_tokens); } if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); ZVAL_NULL(udf_flags); } @@ -903,11 +898,10 @@ PHP_METHOD(Memcached, getDelayedByKey) static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; zend_bool with_cas = 0; size_t num_keys = 0; - zval **entry = NULL; + zval *entry = NULL; const char **mkeys = NULL; size_t *mkeys_len = NULL; uint64_t orig_cas_flag = 0; @@ -918,12 +912,12 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|bf!", &server_key, - &server_key_len, &keys, &with_cas, &fci, &fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, + &keys, &with_cas, &fci, &fcc) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|bf!", &keys, &with_cas, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, &fci, &fcc) == FAILURE) { return; } @@ -940,20 +934,17 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); - zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(keys))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { - mkeys[i] = Z_STRVAL_PP(entry); - mkeys_len[i] = Z_STRLEN_PP(entry); + mkeys[i] = Z_STRVAL_P(entry); + mkeys_len[i] = Z_STRLEN_P(entry); i++; } - } + } ZEND_HASH_FOREACH_END(); if (i == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; @@ -976,7 +967,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* * Issue the request, but collect results only if the result callback is provided. */ - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); /* * Restore the CAS support flag, but only if we had to turn it on. @@ -987,7 +978,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ efree(mkeys); efree(mkeys_len); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1001,7 +992,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result TSRMLS_CC) < 0) { + if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result) < 0) { status = MEMCACHED_FAILURE; break; } @@ -1012,7 +1003,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (status == MEMCACHED_END) { status = MEMCACHED_SUCCESS; } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } } @@ -1029,7 +1020,7 @@ PHP_METHOD(Memcached, fetch) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value; + zval value; uint32_t flags = 0; uint64_t cas = 0; memcached_result_st result; @@ -1045,7 +1036,7 @@ PHP_METHOD(Memcached, fetch) memcached_result_create(m_obj->memc, &result); if ((memcached_fetch_result(m_obj->memc, &result, &status)) == NULL) { - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); memcached_result_free(&result); RETURN_FALSE; } @@ -1057,9 +1048,7 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1067,14 +1056,14 @@ PHP_METHOD(Memcached, fetch) } array_init(return_value); - add_assoc_stringl_ex(return_value, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(return_value, ZEND_STRS("value"), value); + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); if (cas != 0) { /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(return_value, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -1089,7 +1078,7 @@ PHP_METHOD(Memcached, fetchAll) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value, *entry; + zval value, entry; uint32_t flags; uint64_t cas = 0; memcached_result_st result; @@ -1114,9 +1103,7 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); zval_ptr_dtor(&value); zval_dtor(return_value); @@ -1124,23 +1111,22 @@ PHP_METHOD(Memcached, fetchAll) RETURN_FALSE; } - MAKE_STD_ZVAL(entry); - array_init(entry); - add_assoc_stringl_ex(entry, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(entry, ZEND_STRS("value"), value); + array_init(&entry); + add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); if (cas != 0) { /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(&entry, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } - add_next_index_zval(return_value, entry); + add_next_index_zval(return_value, &entry); } memcached_result_free(&result); - if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1227,13 +1213,11 @@ PHP_METHOD(Memcached, setMultiByKey) static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; time_t expiration = 0; long udf_flags = 0; - zval **entry; - char *str_key; - uint str_key_len; + zval *entry; + zend_string *str_key = NULL; ulong num_key; char *payload; size_t payload_len; @@ -1241,15 +1225,16 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint32_t retry = 0; memcached_return status; char tmp_key[MEMCACHED_MAX_KEY]; + int tmp_len = 0; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|ll", &server_key, - &server_key_len, &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, + &entries, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1263,24 +1248,21 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } } - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); - zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(entries))) { - int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(entries), &str_key, &str_key_len, &num_key, 0, NULL); - - if (key_type == HASH_KEY_IS_LONG) { + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, str_key, entry) { + if (str_key) { + str_key = zend_string_init(str_key->val, str_key->len, 0); + } else if (num_key || num_key == 0) { /* Array keys are unsigned, but php integers are signed. * Keys must be converted to signed strings that match * php integers. */ assert(sizeof(tmp_key) >= sizeof(ZEND_TOSTR(LONG_MIN))); - - str_key_len = sprintf(tmp_key, "%ld", (long)num_key) + 1; - str_key = (char *)tmp_key; - } else if (key_type != HASH_KEY_IS_STRING) { + tmp_len = sprintf(tmp_key, "%ld", (long)num_key); + str_key = zend_string_init(tmp_key, tmp_len, 0); + } else { continue; } @@ -1293,26 +1275,31 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } - payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + zend_string_release(str_key); RETURN_FALSE; } retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key, str_key_len-1, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); + zend_string_release(str_key); } else { - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); + zend_string_release(str_key); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY + zend_string_release(str_key); efree(payload); RETURN_FALSE; } + zend_string_release(str_key); efree(payload); - } + } ZEND_HASH_FOREACH_END(); RETURN_TRUE; } @@ -1382,16 +1369,12 @@ PHP_METHOD(Memcached, replaceByKey) } /* }}} */ - /* {{{ -- php_memc_store_impl */ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; - char *s_value = NULL; - int s_value_len = 0; + zend_string *key; + zend_string *server_key; + zend_string *s_value; zval s_zvalue; zval *value; long expiration = 0; @@ -1405,41 +1388,33 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &server_key, - &server_key_len, &key, &key_len, &s_value, &s_value_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { return; } - INIT_ZVAL(s_zvalue); value = &s_zvalue; - ZVAL_STRINGL(value, s_value, s_value_len, 0); + ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key, - &server_key_len, &key, &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|ll", &server_key, - &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|ll", &server_key, &key, &value, &expiration, &udf_flags) == FAILURE) { return; } } } else { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, - &s_value, &s_value_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { return; } - INIT_ZVAL(s_zvalue); value = &s_zvalue; - ZVAL_STRINGL(value, s_value, s_value_len, 0); + ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, - &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, - &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|ll", &key, &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1448,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1460,7 +1435,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * append/prepend new data, and store it again. */ if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on"); + php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); return; } MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); @@ -1472,7 +1447,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } @@ -1480,11 +1455,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (op == MEMC_OP_TOUCH) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif } else { - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1493,56 +1468,56 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool retry: switch (op) { case MEMC_OP_SET: - if (!server_key) { - status = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: - if (!server_key) { - status = memcached_touch(m_obj->memc, key, key_len, expiration); + if (!server_key->val) { + status = memcached_touch(m_obj->memc, key->val, key->len, expiration); } else { - status = memcached_touch_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, expiration); + status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, expiration); } break; #endif case MEMC_OP_ADD: - if (!server_key) { - status = memcached_add(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_add_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_REPLACE: - if (!server_key) { - status = memcached_replace(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_replace_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_APPEND: - if (!server_key) { - status = memcached_append(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_append_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_PREPEND: - if (!server_key) { - status = memcached_prepend(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_prepend_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; @@ -1553,7 +1528,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETVAL_FALSE; } else { @@ -1571,10 +1546,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { double cas_d; uint64_t cas; - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key; + zend_string *server_key; zval *value; time_t expiration = 0; long udf_flags = 0; @@ -1585,13 +1558,13 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|ll", &cas_d, &server_key, - &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, + &value, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|ll", &cas_d, &key, &key_len, - &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, + &expiration, &udf_flags) == FAILURE) { return; } } @@ -1599,7 +1572,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1616,24 +1589,24 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, payload, payload_len, expiration, flags, cas); + status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload, payload_len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key, key_len, payload, payload_len, expiration, flags, cas); + status = memcached_cas(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags, cas); } efree(payload); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1692,40 +1665,34 @@ PHP_METHOD(Memcached, deleteMultiByKey) /* {{{ -- php_memc_delete_impl */ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key, *server_key; time_t expiration = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key, - &server_key_len, &key, &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, - &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } - server_key = key; - server_key_len = key_len; + server_key = zend_string_copy(key); } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } - status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, expiration); + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, expiration); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1737,21 +1704,19 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; time_t expiration = 0; - zval **entry; + zval *entry; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|l", &server_key, - &server_key_len, &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|l", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { return; } } @@ -1760,31 +1725,28 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by i_obj->rescode = MEMCACHED_SUCCESS; array_init(return_value); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); - zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(entries))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } - if (Z_STRLEN_PP(entry) == 0) { + if (Z_STRLEN_P(entry) == 0) { continue; } - if (!by_key) { - server_key = Z_STRVAL_PP(entry); - server_key_len = Z_STRLEN_PP(entry); + if (by_key) { + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } else { + status = memcached_delete_by_key(m_obj->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } - status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), expiration); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - add_assoc_long(return_value, Z_STRVAL_PP(entry), status); + if (php_memc_handle_error(i_obj, status) < 0) { + add_assoc_long(return_value, Z_STRVAL_P(entry), status); } else { - add_assoc_bool(return_value, Z_STRVAL_PP(entry), 1); + add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); } - } + } ZEND_HASH_FOREACH_END(); return; } @@ -1793,8 +1755,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by /* {{{ -- php_memc_incdec_impl */ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - char *key, *server_key; - int key_len, server_key_len; + zend_string *key, *server_key; long offset = 1; uint64_t value, initial = 0; time_t expiry = 0; @@ -1805,11 +1766,11 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_INIT_VARS; if (!by_key) { - if (zend_parse_parameters(n_args TSRMLS_CC, "s|lll", &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { return; } } else { - if (zend_parse_parameters(n_args TSRMLS_CC, "ss|lll", &server_key, &server_key_len, &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { return; } } @@ -1817,13 +1778,13 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } if (offset < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset has to be > 0"); + php_error_docref(NULL, E_WARNING, "offset has to be > 0"); RETURN_FALSE; } @@ -1831,38 +1792,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + status = memcached_increment_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + status = memcached_increment(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + status = memcached_decrement(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); } } } else { if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initial value is only supported with binary protocol"); + php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); RETURN_FALSE; } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETURN_FALSE; } @@ -1907,14 +1868,12 @@ PHP_METHOD(Memcached, incrementByKey) Adds the given memcache server to the list */ PHP_METHOD(Memcached, addServer) { - char *host; - int host_len; + zend_string *host; long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &host, &host_len, - &port, &weight) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { return; } @@ -1922,18 +1881,18 @@ PHP_METHOD(Memcached, addServer) i_obj->rescode = MEMCACHED_SUCCESS; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); + if (host->val[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host->val, weight); } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_udp_with_weight(m_obj->memc, host->val, port, weight); } else { - status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); } #else - status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); #endif - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1946,45 +1905,46 @@ PHP_METHOD(Memcached, addServer) PHP_METHOD(Memcached, addServers) { zval *servers; - zval **entry; - zval **z_host, **z_port, **z_weight = NULL; + zval *entry; + zval *z_host, *z_port, *z_weight = NULL; uint32_t weight = 0; + HashPosition pos; int entry_size, i = 0; memcached_server_st *list = NULL; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &servers) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(servers)), i = 0; - zend_hash_get_current_data(Z_ARRVAL_P(servers), (void **)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(servers)), i++) { - - if (Z_TYPE_PP(entry) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "server list entry #%d is not an array", i+1); + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { + if (Z_TYPE_P(entry) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); + i++; continue; } - entry_size = zend_hash_num_elements(Z_ARRVAL_PP(entry)); + entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); if (entry_size > 1) { - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry)); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); /* Check that we have a host */ - if (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_host) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server host for entry #%d", i+1); + if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); + i++; continue; } /* Check that we have a port */ - if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE || - zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_port) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server port for entry #%d", i+1); + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); + i++; continue; } @@ -1994,30 +1954,31 @@ PHP_METHOD(Memcached, addServers) weight = 0; if (entry_size > 2) { /* Try to get weight */ - if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE || - zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_weight) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server weight for entry #%d", i+1); + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); } convert_to_long_ex(z_weight); - weight = Z_LVAL_PP(z_weight); + weight = Z_LVAL_P(z_weight); } - list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host), - Z_LVAL_PP(z_port), weight, &status); + list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), + Z_LVAL_P(z_port), weight, &status); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) == 0) { + if (php_memc_handle_error(i_obj, status) == 0) { + i++; continue; } } - + i++; /* catch-all for all errors */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not add entry #%d to the server list", i+1); - } + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + } ZEND_HASH_FOREACH_END(); status = memcached_server_push(m_obj->memc, list); memcached_server_list_free(list); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2025,7 +1986,6 @@ PHP_METHOD(Memcached, addServers) } /* }}} */ - /* {{{ Memcached::getServerList() Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) @@ -2051,32 +2011,31 @@ PHP_METHOD(Memcached, getServerList) Returns the server identified by the given server key */ PHP_METHOD(Memcached, getServerByKey) { - char *server_key; - int server_key_len; + zend_string *server_key; php_memcached_instance_st server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_key, &server_key_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (server_key_len == 0 || strchr(server_key, ' ')) { + if (server_key->len == 0 || strchr(server_key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } - server_instance = memcached_server_by_key(m_obj->memc, server_key, server_key_len, &error); + server_instance = memcached_server_by_key(m_obj->memc, server_key->val, server_key->len, &error); if (server_instance == NULL) { - php_memc_handle_error(i_obj, error TSRMLS_CC); + php_memc_handle_error(i_obj, error); RETURN_FALSE; } array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); add_assoc_long(return_value, "port", memcached_server_port(server_instance)); add_assoc_long(return_value, "weight", 0); } @@ -2144,7 +2103,7 @@ PHP_METHOD(Memcached, getLastErrorMessage) MEMC_METHOD_FETCH_OBJECT; - RETURN_STRING(memcached_last_error_message(m_obj->memc), 1); + RETURN_STRING(memcached_last_error_message(m_obj->memc)); } /* }}} */ @@ -2201,7 +2160,7 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) } array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); add_assoc_long(return_value, "port", memcached_server_port(server_instance)); } /* }}} */ @@ -2228,7 +2187,7 @@ PHP_METHOD(Memcached, getStats) } stats = memcached_stat(m_obj->memc, NULL, &status); - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); if (stats == NULL) { RETURN_FALSE; } else if (status != MEMCACHED_SUCCESS && status != MEMCACHED_SOME_ERRORS) { @@ -2266,7 +2225,7 @@ PHP_METHOD(Memcached, getVersion) array_init(return_value); status = memcached_version(m_obj->memc); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2284,7 +2243,7 @@ static memcached_return php_memc_dump_func_callback(const memcached_st *ptr __at const char *key, size_t key_length, void *context) { zval *ctx = (zval*) context; - add_next_index_string(ctx, (char*) key, 1); + add_next_index_string(ctx, (char*) key); return MEMCACHED_SUCCESS; } @@ -2300,7 +2259,7 @@ PHP_METHOD(Memcached, getAllKeys) array_init(return_value); rc = memcached_dump(m_obj->memc, callback, return_value, 1); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, rc) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2315,7 +2274,7 @@ static PHP_METHOD(Memcached, flush) memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &delay) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { return; } @@ -2323,7 +2282,7 @@ static PHP_METHOD(Memcached, flush) i_obj->rescode = MEMCACHED_SUCCESS; status = memcached_flush(m_obj->memc, delay); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2340,7 +2299,7 @@ static PHP_METHOD(Memcached, getOption) memcached_behavior flag; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &option) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &option) == FAILURE) { return; } @@ -2361,9 +2320,9 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result) - 1, 1); + RETURN_STRINGL(result, strlen(result) - 1); #else - RETURN_STRING(result, 1); + RETURN_STRING(result); #endif } else { RETURN_EMPTY_STRING(); @@ -2381,7 +2340,7 @@ static PHP_METHOD(Memcached, getOption) case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: if (memcached_server_count(m_obj->memc) == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "no servers defined"); + php_error_docref(NULL, E_WARNING, "no servers defined"); return; } @@ -2396,7 +2355,7 @@ static PHP_METHOD(Memcached, getOption) } /* }}} */ -static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRMLS_DC) +static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) { memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; @@ -2443,7 +2402,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided"); + php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } } @@ -2455,8 +2414,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML convert_to_long(value); rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(i_obj, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } @@ -2505,7 +2464,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } else { m_obj->serializer = SERIALIZER_PHP; i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid serializer provided"); + php_error_docref(NULL, E_WARNING, "invalid serializer provided"); return 0; } break; @@ -2535,8 +2494,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } } - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(i_obj, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } break; @@ -2545,9 +2504,9 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } static -uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) +uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) { - zval **ppzval; + zval *pzval; uint32_t *retval; size_t i = 0; @@ -2559,20 +2518,17 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) retval = ecalloc(*num_elements, sizeof(uint32_t)); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(input)); - zend_hash_get_current_data(Z_ARRVAL_P(input), (void **) &ppzval) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(input)), i++) { - + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), pzval) { long value = 0; - if (Z_TYPE_PP(ppzval) == IS_LONG) { - value = Z_LVAL_PP(ppzval); + if (Z_TYPE_P(pzval) == IS_LONG) { + value = Z_LVAL_P(pzval); } else { - zval tmp_zval, *tmp_pzval; - tmp_zval = **ppzval; - zval_copy_ctor(&tmp_zval); - tmp_pzval = &tmp_zval; + zval *tmp_zval, *tmp_pzval; + tmp_zval = pzval; + zval_copy_ctor(tmp_zval); + tmp_pzval = tmp_zval; convert_to_long(tmp_pzval); value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0; @@ -2580,13 +2536,14 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) } if (value < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "the map must contain positive integers"); + php_error_docref(NULL, E_WARNING, "the map must contain positive integers"); efree (retval); *num_elements = 0; return NULL; } retval [i] = (uint32_t) value; - } + i++; + } ZEND_HASH_FOREACH_END(); return retval; } @@ -2605,35 +2562,35 @@ PHP_METHOD(Memcached, setBucket) memcached_return rc; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; if (zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "server map cannot be empty"); + php_error_docref(NULL, E_WARNING, "server map cannot be empty"); RETURN_FALSE; } if (zforward_map && zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) != zend_hash_num_elements (Z_ARRVAL_P(zforward_map))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "forward_map length must match the server_map length"); + php_error_docref(NULL, E_WARNING, "forward_map length must match the server_map length"); RETURN_FALSE; } if (replicas < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "replicas must be larger than zero"); + php_error_docref(NULL, E_WARNING, "replicas must be larger than zero"); RETURN_FALSE; } - server_map = s_zval_to_uint32_array (zserver_map, &server_map_len TSRMLS_CC); + server_map = s_zval_to_uint32_array (zserver_map, &server_map_len); if (!server_map) { RETURN_FALSE; } if (zforward_map) { - forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len TSRMLS_CC); + forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len); if (!forward_map) { efree (server_map); @@ -2643,7 +2600,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, rc) < 0) { retval = 0;; } @@ -2662,38 +2619,33 @@ static PHP_METHOD(Memcached, setOptions) { zval *options; zend_bool ok = 1; - uint key_len; - char *key; + zend_string *key; ulong key_index; - zval **value; + zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &options) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(options)); - zend_hash_get_current_data(Z_ARRVAL_P(options), (void *) &value) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(options))) { - - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { - zval copy = **value; - zval_copy_ctor(©); - INIT_PZVAL(©); + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), key_index, key, value) { + if (key) { + php_error_docref(NULL, E_WARNING, "invalid configuration option"); + ok = 0; + } else { + zval copy; + ZVAL_DUP(©, value); - if (!php_memc_set_option(i_obj, (long) key_index, © TSRMLS_CC)) { + if (!php_memc_set_option(i_obj, (long) key_index, ©)) { ok = 0; } zval_dtor(©); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); - ok = 0; } - } + } ZEND_HASH_FOREACH_END(); RETURN_BOOL(ok); } @@ -2707,13 +2659,13 @@ static PHP_METHOD(Memcached, setOption) zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &option, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(php_memc_set_option(i_obj, option, value TSRMLS_CC)); + RETURN_BOOL(php_memc_set_option(i_obj, option, value)); } /* }}} */ @@ -2724,29 +2676,27 @@ static PHP_METHOD(Memcached, setSaslAuthData) { MEMC_METHOD_INIT_VARS; memcached_return status; + zend_string *user, *pass; - char *user, *pass; - int user_len, pass_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &user, &user_len, &pass, &pass_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { return; } if (!MEMC_G(use_sasl)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); + php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); RETURN_FALSE; } MEMC_METHOD_FETCH_OBJECT; if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL is only supported with binary protocol"); + php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); RETURN_FALSE; } m_obj->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(m_obj->memc, user, pass); + status = memcached_set_sasl_auth_data(m_obj->memc, user->val, pass->val); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } RETURN_TRUE; @@ -2784,7 +2734,7 @@ static PHP_METHOD(Memcached, getResultMessage) switch (i_obj->rescode) { case MEMC_RES_PAYLOAD_FAILURE: - RETURN_STRING("PAYLOAD FAILURE", 1); + RETURN_STRING("PAYLOAD FAILURE"); break; case MEMCACHED_ERRNO: @@ -2795,11 +2745,11 @@ static PHP_METHOD(Memcached, getResultMessage) int str_len; str_len = spprintf(&str, 0, "%s: %s", memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); - RETURN_STRINGL(str, str_len, 0); + RETURN_STRINGL(str, str_len); } /* Fall through */ default: - RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), 1); + RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode)); break; } @@ -2843,7 +2793,7 @@ static PHP_METHOD(Memcached, isPristine) ****************************************/ /* {{{ constructor/destructor */ -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC) +static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) { #if HAVE_MEMCACHED_SASL if (m_obj->has_sasl_data) { @@ -2857,56 +2807,47 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS pefree(m_obj, persistent); } -static void php_memc_free_storage(php_memc_t *i_obj TSRMLS_DC) +static void php_memc_free_storage(zend_object *obj) { - zend_object_std_dtor(&i_obj->zo TSRMLS_CC); - + php_memc_t *i_obj = php_memc_fetch_object(obj); + if (i_obj->obj && !i_obj->is_persistent) { - php_memc_destroy(i_obj->obj, 0 TSRMLS_CC); + php_memc_destroy(i_obj->obj, 0); } + zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; efree(i_obj); } -zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) +zend_object *php_memc_new(zend_class_entry *ce) { - zend_object_value retval; - php_memc_t *i_obj; - - i_obj = ecalloc(1, sizeof(*i_obj)); - zend_object_std_init( &i_obj->zo, ce TSRMLS_CC ); -#if PHP_VERSION_ID >= 50400 - object_properties_init( (zend_object *) i_obj, ce); -#else - { - zval *tmp; - zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - } -#endif - - retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); - retval.handlers = &memcached_object_handlers; - - return retval; + php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + sizeof(zval) * (ce->default_properties_count - 1)); + + zend_object_std_init(&i_obj->zo, ce); + object_properties_init(&i_obj->zo, ce); + + i_obj->zo.handlers = &memcached_object_handlers; + + return &i_obj->zo; } #ifdef HAVE_MEMCACHED_PROTOCOL static -void php_memc_server_free_storage(php_memc_server_t *intern TSRMLS_DC) +void php_memc_server_free_storage(php_memc_server_t *intern) { - zend_object_std_dtor(&intern->zo TSRMLS_CC); + zend_object_std_dtor(&intern->zo); efree (intern); } -zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) +zend_object_value php_memc_server_new(zend_class_entry *ce) { zend_object_value retval; php_memc_server_t *intern; zval *tmp; intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init (&intern->zo, ce TSRMLS_CC); + zend_object_std_init (&intern->zo, ce); #if PHP_VERSION_ID >= 50400 object_properties_init( (zend_object *) intern, ce); #else @@ -2915,7 +2856,7 @@ zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) intern->handler = php_memc_proto_handler_new (); - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL TSRMLS_CC); + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); retval.handlers = &memcached_server_object_handlers; return retval; @@ -2924,20 +2865,20 @@ zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { - if (rsrc->ptr) { - struct memc_obj *m_obj = (struct memc_obj *)rsrc->ptr; - php_memc_destroy(m_obj, 1 TSRMLS_CC); - rsrc->ptr = NULL; + if (res->ptr) { + struct memc_obj *m_obj = (struct memc_obj *)res->ptr; + php_memc_destroy(m_obj, 1); + res->ptr = NULL; } } ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) { - if (rsrc->ptr) { - memcached_sess *memc_sess = (memcached_sess *)rsrc->ptr; + if (res->ptr) { + memcached_sess *memc_sess = (memcached_sess *)res->ptr; memcached_free(memc_sess->memc_sess); - pefree(rsrc->ptr, 1); - rsrc->ptr = NULL; + pefree(res->ptr, 1); + res->ptr = NULL; } } /* }}} */ @@ -2946,18 +2887,17 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; - zval *array; + zval array; - MAKE_STD_ZVAL(array); - array_init(array); - add_assoc_string(array, "host", (char*) memcached_server_name(instance), 1); - add_assoc_long(array, "port", memcached_server_port(instance)); + array_init(&array); + add_assoc_string(&array, "host", (char*) memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); */ - add_next_index_zval(context->return_value, array); + add_next_index_zval(context->return_value, &array); return MEMCACHED_SUCCESS; } @@ -2966,38 +2906,37 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ char *hostport = NULL; int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; - zval *entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - - MAKE_STD_ZVAL(entry); - array_init(entry); - - add_assoc_long(entry, "pid", context->stats[context->i].pid); - add_assoc_long(entry, "uptime", context->stats[context->i].uptime); - add_assoc_long(entry, "threads", context->stats[context->i].threads); - add_assoc_long(entry, "time", context->stats[context->i].time); - add_assoc_long(entry, "pointer_size", context->stats[context->i].pointer_size); - add_assoc_long(entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); - add_assoc_long(entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); - add_assoc_long(entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); - add_assoc_long(entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); - add_assoc_long(entry, "curr_items", context->stats[context->i].curr_items); - add_assoc_long(entry, "total_items", context->stats[context->i].total_items); - add_assoc_long(entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); - add_assoc_long(entry, "curr_connections", context->stats[context->i].curr_connections); - add_assoc_long(entry, "total_connections", context->stats[context->i].total_connections); - add_assoc_long(entry, "connection_structures", context->stats[context->i].connection_structures); - add_assoc_long(entry, "bytes", context->stats[context->i].bytes); - add_assoc_long(entry, "cmd_get", context->stats[context->i].cmd_get); - add_assoc_long(entry, "cmd_set", context->stats[context->i].cmd_set); - add_assoc_long(entry, "get_hits", context->stats[context->i].get_hits); - add_assoc_long(entry, "get_misses", context->stats[context->i].get_misses); - add_assoc_long(entry, "evictions", context->stats[context->i].evictions); - add_assoc_long(entry, "bytes_read", context->stats[context->i].bytes_read); - add_assoc_long(entry, "bytes_written", context->stats[context->i].bytes_written); - add_assoc_stringl(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, entry); + zval entry; + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + + array_init(&entry); + + add_assoc_long(&entry, "pid", context->stats[context->i].pid); + add_assoc_long(&entry, "uptime", context->stats[context->i].uptime); + add_assoc_long(&entry, "threads", context->stats[context->i].threads); + add_assoc_long(&entry, "time", context->stats[context->i].time); + add_assoc_long(&entry, "pointer_size", context->stats[context->i].pointer_size); + add_assoc_long(&entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); + add_assoc_long(&entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); + add_assoc_long(&entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); + add_assoc_long(&entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); + add_assoc_long(&entry, "curr_items", context->stats[context->i].curr_items); + add_assoc_long(&entry, "total_items", context->stats[context->i].total_items); + add_assoc_long(&entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); + add_assoc_long(&entry, "curr_connections", context->stats[context->i].curr_connections); + add_assoc_long(&entry, "total_connections", context->stats[context->i].total_connections); + add_assoc_long(&entry, "connection_structures", context->stats[context->i].connection_structures); + add_assoc_long(&entry, "bytes", context->stats[context->i].bytes); + add_assoc_long(&entry, "cmd_get", context->stats[context->i].cmd_get); + add_assoc_long(&entry, "cmd_set", context->stats[context->i].cmd_set); + add_assoc_long(&entry, "get_hits", context->stats[context->i].get_hits); + add_assoc_long(&entry, "get_misses", context->stats[context->i].get_misses); + add_assoc_long(&entry, "evictions", context->stats[context->i].evictions); + add_assoc_long(&entry, "bytes_read", context->stats[context->i].bytes_read); + add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); + add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); + + add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, &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. */ @@ -3012,7 +2951,7 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph int hostport_len, version_len; struct callbackContext* context = (struct callbackContext*) in_context; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 version_len = snprintf(version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), @@ -3025,12 +2964,12 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1); + add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len); efree(hostport); return MEMCACHED_SUCCESS; } -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC) +static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) { int result = 0; @@ -3077,7 +3016,7 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM } static -char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags TSRMLS_DC) +char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags) { /* status */ zend_bool compress_status = 0; @@ -3117,7 +3056,7 @@ char *s_compress_value (enum memcached_compression_type compression_type, const *payload_len = compressed_size + sizeof(uint32_t); if (!compress_status) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); + php_error_docref(NULL, E_WARNING, "could not compress value"); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); @@ -3135,7 +3074,7 @@ char *s_compress_value (enum memcached_compression_type compression_type, const } static -zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags TSRMLS_DC) +zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags) { switch (serializer) { @@ -3144,8 +3083,8 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value TSRMLS_CC) != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with igbinary"); + if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value) != 0) { + php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); @@ -3160,9 +3099,9 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, case SERIALIZER_JSON_ARRAY: { #if HAVE_JSON_API_5_2 - php_json_encode(buf, value TSRMLS_CC); + php_json_encode(buf, value); #elif HAVE_JSON_API_5_3 - php_json_encode(buf, value, 0 TSRMLS_CC); /* options */ + php_json_encode(buf, value, 0); /* options */ #endif MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } @@ -3174,9 +3113,9 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_MSGPACK case SERIALIZER_MSGPACK: - php_msgpack_serialize(buf, value TSRMLS_CC); + php_msgpack_serialize(buf, value); if (!buf->c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); + php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); @@ -3190,11 +3129,11 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, { php_serialize_data_t var_hash; PHP_VAR_SERIALIZE_INIT(var_hash); - php_var_serialize(buf, &value, &var_hash TSRMLS_CC); + php_var_serialize(buf, value, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); - if (!buf->c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value"); + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); @@ -3203,14 +3142,14 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, } /* Check for exceptions caused by serializers */ - if (EG(exception) && buf->len) { + if (EG(exception) && buf->s->len) { return 0; } return 1; } static -char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) +char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) { const char *pl; size_t pl_len = 0; @@ -3240,26 +3179,28 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); break; - case IS_BOOL: - if (Z_BVAL_P(value)) { - pl_len = 1; - tmp[0] = '1'; - tmp[1] = '\0'; - } else { - pl_len = 0; - tmp[0] = '\0'; - } + case IS_TRUE: + pl_len = 1; + tmp[0] = '1'; + tmp[1] = '\0'; + pl = tmp; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + break; + + case IS_FALSE: + pl_len = 0; + tmp[0] = '\0'; pl = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; default: - if (!s_serialize_value (serializer, value, &buf, flags TSRMLS_CC)) { + if (!s_serialize_value (serializer, value, &buf, flags)) { smart_str_free (&buf); return NULL; } - pl = buf.c; - pl_len = buf.len; + pl = buf.s->val; + pl_len = buf.s->len; break; } @@ -3272,7 +3213,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ *payload_len = pl_len; - payload = s_compress_value (compression_type, pl, payload_len, flags TSRMLS_CC); + payload = s_compress_value (compression_type, pl, payload_len, flags); } /* If compression failed or value is below threshold we just use plain value */ @@ -3281,14 +3222,14 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags payload = estrndup(pl, pl_len); } - if (buf.len) { + if (buf.s) { smart_str_free(&buf); } return payload; } static -char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) +char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags) { char *buffer = NULL; uint32_t len; @@ -3329,7 +3270,7 @@ char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t fla } if (!decompress_status) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value"); + php_error_docref(NULL, E_WARNING, "could not decompress value"); efree(buffer); return NULL; } @@ -3339,7 +3280,7 @@ char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t fla } static -zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len TSRMLS_DC) +zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: @@ -3348,10 +3289,10 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { ZVAL_FALSE(value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value"); + php_error_docref(NULL, E_WARNING, "could not unserialize value"); return 0; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); @@ -3360,14 +3301,14 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { + if (igbinary_unserialize((uint8_t *)payload, payload_len, &value)) { ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); + php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; } #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no igbinary support"); return 0; #endif break; @@ -3375,23 +3316,23 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API # if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY)); # elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); # endif #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); return 0; #endif break; case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(value, payload, payload_len TSRMLS_CC); + php_msgpack_unserialize(value, payload, payload_len); #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); return 0; #endif break; @@ -3400,7 +3341,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ } /* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) +static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer) { /* A NULL payload is completely valid if length is 0, it is simply empty. @@ -3411,7 +3352,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ if (payload_in == NULL && payload_len > 0) { ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, + php_error_docref(NULL, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return -1; } else if (payload_in == NULL) { @@ -3424,7 +3365,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ } if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { - char *datas = s_decompress_value (payload_in, &payload_len, flags TSRMLS_CC); + char *datas = s_decompress_value (payload_in, &payload_len, flags); if (!datas) { ZVAL_FALSE(value); return -1; @@ -3438,10 +3379,10 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: if (payload_emalloc) { - ZVAL_STRINGL(value, pl, payload_len, 0); + ZVAL_STRINGL(value, pl, payload_len); payload_emalloc = 0; } else { - ZVAL_STRINGL(value, pl, payload_len, 1); + ZVAL_STRINGL(value, pl, payload_len); } break; @@ -3451,7 +3392,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ char conv_buf [128]; if (payload_len >= 128) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read long value, too big"); + php_error_docref(NULL, E_WARNING, "could not read long value, too big"); retval = -1; } else { @@ -3469,7 +3410,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ char conv_buf [128]; if (payload_len >= 128) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read double value, too big"); + php_error_docref(NULL, E_WARNING, "could not read double value, too big"); retval = -1; } else { @@ -3497,14 +3438,14 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len TSRMLS_CC)) { + if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len)) { retval = -1; } break; default: ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); + php_error_docref(NULL, E_WARNING, "unknown payload type"); retval = -1; break; } @@ -3528,17 +3469,20 @@ zend_class_entry *php_memc_get_exception(void) } PHP_MEMCACHED_API -zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) +zend_class_entry *php_memc_get_exception_base(int root) { #if HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { - zend_class_entry **pce; - - if (zend_hash_find(CG(class_table), "runtimeexception", - sizeof("RuntimeException"), (void **) &pce) == SUCCESS) { - spl_ce_RuntimeException = *pce; - return *pce; + zend_class_entry *pce; + zval *pce_z; + + if ((pce_z = zend_hash_str_find(CG(class_table), + "runtimeexception", + sizeof("RuntimeException") - 1)) != NULL) { + pce = Z_CE_P(pce_z); + spl_ce_RuntimeException = pce; + return pce; } } else { return spl_ce_RuntimeException; @@ -3548,20 +3492,19 @@ zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2) return zend_exception_get_default(); #else - return zend_exception_get_default(TSRMLS_C); + return zend_exception_get_default(); #endif } static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, char *key, - size_t key_len, zval *value TSRMLS_DC) + zend_fcall_info_cache *fcc, zend_string *key, zval *value) { char *payload = NULL; size_t payload_len = 0; - zval **params[4]; - zval *retval; - zval *z_key; - zval *z_expiration; + zval params[4]; + zval retval; + zval z_key; + zval z_expiration; uint32_t flags = 0; memcached_return rc; @@ -3569,40 +3512,38 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i memcached_return status = MEMCACHED_SUCCESS; int result; - MAKE_STD_ZVAL(z_key); - MAKE_STD_ZVAL(z_expiration); - ZVAL_STRINGL(z_key, key, key_len, 1); + ZVAL_STR(&z_key, key); ZVAL_NULL(value); - ZVAL_LONG(z_expiration, 0); + ZVAL_LONG(&z_expiration, 0); - params[0] = &zmemc_obj; - params[1] = &z_key; - params[2] = &value; - params[3] = &z_expiration; + ZVAL_COPY(¶ms[0], zmemc_obj); + ZVAL_COPY(¶ms[1], &z_key); + ZVAL_COPY(¶ms[2], value); + ZVAL_COPY(¶ms[3], &z_expiration); - fci->retval_ptr_ptr = &retval; + fci->retval = &retval; fci->params = params; - fci->param_count = sizeof(params) / sizeof(params[0]); + fci->param_count = 4; - result = zend_call_function(fci, fcc TSRMLS_CC); - if (result == SUCCESS && retval) { - i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); + result = zend_call_function(fci, fcc); + if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { + i_obj = (php_memc_t *) Z_OBJ_P(zmemc_obj); struct memc_obj *m_obj = i_obj->obj; - if (zend_is_true(retval)) { + if (zend_is_true(&retval)) { time_t expiration; - if (Z_TYPE_P(z_expiration) != IS_LONG) { - convert_to_long(z_expiration); + if (Z_TYPE(z_expiration) != IS_LONG) { + convert_to_long(&z_expiration); } - expiration = Z_LVAL_P(z_expiration); + expiration = Z_LVAL(z_expiration); - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } @@ -3616,14 +3557,16 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } else { if (result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke cache callback"); + zval_ptr_dtor(&z_key); + zval_ptr_dtor(&z_expiration); + php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); } status = MEMCACHED_FAILURE; zval_dtor(value); ZVAL_NULL(value); } - if (retval) { + if (&retval) { zval_ptr_dtor(&retval); } @@ -3635,24 +3578,23 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, - memcached_result_st *result TSRMLS_DC) + memcached_result_st *result) { const char *res_key = NULL; size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value, *retval = NULL; + zval value; + zval retval; uint64_t cas = 0; - zval **params[2]; - zval *z_result; + zval params[2]; + zval z_result; uint32_t flags = 0; int rc = 0; php_memc_t *i_obj = NULL; - params[0] = &zmemc_obj; - params[1] = &z_result; - - fci->retval_ptr_ptr = &retval; + ZVAL_COPY(¶ms[0], zmemc_obj); + fci->retval = &retval; fci->params = params; fci->param_count = 2; @@ -3663,35 +3605,35 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - ALLOC_INIT_ZVAL(value); - - i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); + i_obj = Z_MEMC_OBJ_P(zmemc_obj); - if (php_memc_zval_from_payload(value, payload, payload_len, flags, i_obj->obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, i_obj->obj->serializer) < 0) { zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } - MAKE_STD_ZVAL(z_result); - array_init(z_result); - add_assoc_stringl_ex(z_result, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(z_result, ZEND_STRS("value"), value); + array_init(&z_result); + ZVAL_COPY(¶ms[1], &z_result); + add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); if (cas != 0) { - add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(&z_result, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } - if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback"); + if (zend_call_function(fci, fcc) == FAILURE) { + php_error_docref(NULL, E_WARNING, "could not invoke result callback"); rc = -1; } - if (retval) { + if (&retval) { zval_ptr_dtor(&retval); } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); zval_ptr_dtor(&z_result); return rc; @@ -3716,13 +3658,12 @@ PHP_METHOD(MemcachedServer, run) { int i; zend_bool rc; - char *address; - int address_len; + zend *address; php_memc_server_t *intern; - intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_MEMC_OBJ_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &address, &address_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { return; } @@ -3743,7 +3684,7 @@ PHP_METHOD(MemcachedServer, on) zend_fcall_info_cache fci_cache; zend_bool rc = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lf!", &event, &fci, &fci_cache) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lf!", &event, &fci, &fci_cache) == FAILURE) { return; } @@ -4245,9 +4186,9 @@ zend_module_entry memcached_module_entry = { /* {{{ php_memc_register_constants */ static void php_memc_register_constants(INIT_FUNC_ARGS) { - #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC) - #define REGISTER_MEMC_CLASS_CONST_BOOL(name, value) zend_declare_class_constant_bool(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC) - #define REGISTER_MEMC_CLASS_CONST_NULL(name) zend_declare_class_constant_null(php_memc_get_ce() , ZEND_STRS( #name ) - 1 TSRMLS_CC) + #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value) + #define REGISTER_MEMC_CLASS_CONST_BOOL(name, value) zend_declare_class_constant_bool(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value) + #define REGISTER_MEMC_CLASS_CONST_NULL(name) zend_declare_class_constant_null(php_memc_get_ce() , ZEND_STRS( #name ) - 1) /* * Class options @@ -4489,13 +4430,15 @@ PHP_MINIT_FUNCTION(memcached) zend_class_entry ce; memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_object_handlers.offset = XtOffsetOf(php_memc_t, zo); memcached_object_handlers.clone_obj = NULL; + memcached_object_handlers.free_obj = php_memc_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); - memcached_ce = zend_register_internal_class(&ce TSRMLS_CC); + memcached_ce = zend_register_internal_class(&ce); memcached_ce->create_object = php_memc_new; #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4503,12 +4446,12 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); - memcached_server_ce = zend_register_internal_class(&ce TSRMLS_CC); + memcached_server_ce = zend_register_internal_class(&ce); memcached_server_ce->create_object = php_memc_server_new; #endif INIT_CLASS_ENTRY(ce, "MemcachedException", NULL); - memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC); + memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0)); /* TODO * possibly declare custom exception property here */ @@ -4523,7 +4466,7 @@ PHP_MINIT_FUNCTION(memcached) #if HAVE_MEMCACHED_SASL if (MEMC_G(use_sasl)) { if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); + php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); return FAILURE; } } diff --git a/php_memcached.h b/php_memcached.h index bce8e37b..da4d6b92 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -36,7 +36,7 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void); -PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry diff --git a/php_memcached_private.h b/php_memcached_private.h index 0ec2d76e..2929818e 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/php_memcached_server.c b/php_memcached_server.c index 42ccc8ee..eb225db0 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -60,7 +60,7 @@ typedef struct { } php_memc_client_t; static -long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count TSRMLS_DC) +long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count) { long retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *retval_ptr = NULL; @@ -72,9 +72,9 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa cb->fci.no_separation = 1; cb->fci.retval_ptr_ptr = &retval_ptr; - if (zend_call_function(&(cb->fci), &(cb->fci_cache) TSRMLS_CC) == FAILURE) { - char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache) TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback %s()", buf); + if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { + char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache)); + php_error_docref(NULL, E_WARNING, "Failed to invoke callback %s()", buf); efree (buf); } if (retval_ptr) { @@ -91,10 +91,8 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zresult_cas; - zval **params [6]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zflags, zexptime, zresult_cas; + zval params[6]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { return retval; @@ -102,32 +100,29 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_STRINGL(zvalue, data, data_len, 1); - - MAKE_STD_ZVAL(zflags); - ZVAL_LONG(zflags, flags); - - MAKE_STD_ZVAL(zexptime); - ZVAL_LONG(zexptime, exptime); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zvalue, data, data_len); + ZVAL_LONG(&zflags, flags); + ZVAL_LONG(&zexptime, exptime); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zexptime); + ZVAL_COPY(¶ms[5], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zflags; - params [4] = &zexptime; - params [5] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -143,10 +138,8 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zcas, *zresult_cas; - zval **params [5]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zcas, zresult_cas; + zval params[5]; if (!MEMC_HAS_CB(event)) { return retval; @@ -154,28 +147,26 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_STRINGL(zvalue, data, data_len, 1); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zvalue, data, data_len); + ZVAL_DOUBLE(&zcas, cas); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zcas); + ZVAL_COPY(¶ms[4], &zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); - - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zcas; - params [4] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -206,10 +197,8 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; - zval **params [7]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zdelta, zinital, zexpiration, zresult, zresult_cas; + zval params[7]; if (!MEMC_HAS_CB(event)) { return retval; @@ -217,41 +206,37 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zdelta); - ZVAL_LONG(zdelta, (long) delta); - - MAKE_STD_ZVAL(zinital); - ZVAL_LONG(zinital, (long) initial); - - MAKE_STD_ZVAL(zexpiration); - ZVAL_LONG(zexpiration, (long) expiration); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_LONG(&zdelta, (long) delta); + ZVAL_LONG(&zinital, (long) initial); + ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_LONG(&zresult, 0); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult); - ZVAL_LONG(zresult, 0); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zdelta); + ZVAL_COPY(¶ms[3], &zinital); + ZVAL_COPY(¶ms[4], &zexpiration); + ZVAL_COPY(¶ms[5], &zresult); + ZVAL_COPY(¶ms[6], &zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zdelta; - params [3] = &zinital; - params [4] = &zexpiration; - params [5] = &zresult; - params [6] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); - - if (Z_TYPE_P(zresult) != IS_LONG) { - convert_to_long (zresult); + if (Z_TYPE(zresult) != IS_LONG) { + convert_to_long (&zresult); } - *result = (uint64_t) Z_LVAL_P(zresult); + *result = (uint64_t) Z_LVAL(zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); + zval_ptr_dtor(¶ms[6]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zdelta); @@ -284,10 +269,8 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void uint16_t key_len, uint64_t cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zcas; - zval **params [3]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zcas; + zval params[3]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) { return retval; @@ -295,21 +278,21 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, (double) cas); - - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zcas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3 TSRMLS_CC); - - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zcas); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_DOUBLE(&zcas, (double) cas); + + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zcas); + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3); + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zkey); + zval_ptr_dtor(&zcas); return retval; } @@ -317,10 +300,8 @@ static protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t when) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zwhen; - zval **params [2]; - - TSRMLS_FETCH(); + zval zcookie, zwhen; + zval params[2]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) { return retval; @@ -328,16 +309,15 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zwhen); - ZVAL_LONG(zwhen, (long) when); - - params [0] = &zcookie; - params [1] = &zwhen; + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zwhen) - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zwhen); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zwhen); return retval; } @@ -346,10 +326,8 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k memcached_binary_protocol_get_response_handler response_handler) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zflags, *zresult_cas; - zval **params [5]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zflags, zresult_cas; + zval params[5]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_GET)) { return retval; @@ -357,52 +335,50 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_NULL(zvalue); - - MAKE_STD_ZVAL(zflags); - ZVAL_NULL(zflags); - - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zflags; - params [4] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5); /* Succeeded in getting the key */ if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { uint32_t flags = 0; uint64_t result_cas = 0; - if (Z_TYPE_P (zvalue) == IS_NULL) { - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zvalue); - zval_ptr_dtor (&zflags); - zval_ptr_dtor (&zresult_cas); + if (Z_TYPE(zvalue) == IS_NULL) { + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zkey); + zval_ptr_dtor(&zvalue); + zval_ptr_dtor(&zflags); + zval_ptr_dtor(&zresult_cas); return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT; } - if (Z_TYPE_P (zvalue) != IS_STRING) { - convert_to_string (zvalue); + if (Z_TYPE(zvalue) != IS_STRING) { + convert_to_string (&zvalue); } - if (Z_TYPE_P (zflags) == IS_LONG) { - flags = Z_LVAL_P (zflags); + if (Z_TYPE(zflags) == IS_LONG) { + flags = Z_LVAL(zflags); } MEMC_MAKE_RESULT_CAS(zresult_cas, result_cas); - retval = response_handler(cookie, key, key_len, Z_STRVAL_P(zvalue), Z_STRLEN_P(zvalue), flags, result_cas); + retval = response_handler(cookie, key, key_len, Z_STRVAL(zvalue), Z_STRLEN(zvalue), flags, result_cas); } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -415,10 +391,8 @@ static protocol_binary_response_status s_noop_handler(const void *cookie) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie; - zval **params [1]; - - TSRMLS_FETCH(); + zval zcookie; + zval params[1]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) { return retval; @@ -426,10 +400,11 @@ protocol_binary_response_status s_noop_handler(const void *cookie) MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - params [0] = &zcookie; + ZVAL_COPY(¶ms[0], &zcookie); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1); + zval_ptr_dtor(¶ms[0]); zval_ptr_dtor (&zcookie); return retval; } @@ -437,11 +412,9 @@ protocol_binary_response_status s_noop_handler(const void *cookie) static protocol_binary_response_status s_quit_handler(const void *cookie) { - zval **params [1]; + zval params[1]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie; - - TSRMLS_FETCH(); + zval zcookie; if (!MEMC_HAS_CB(MEMC_SERVER_ON_QUIT)) { return retval; @@ -449,9 +422,11 @@ protocol_binary_response_status s_quit_handler(const void *cookie) MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - params [0] = &zcookie; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1 TSRMLS_CC); + ZVAL_COPY(¶ms[0], &zcookie); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1); + + zval_ptr_dtor(¶ms[0]); zval_ptr_dtor (&zcookie); return retval; } @@ -463,10 +438,8 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c uint32_t data_len, uint32_t flags, uint32_t expiration, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zdata, *zflags, *zexpiration, *zcas, *zresult_cas; - zval **params [7]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zdata, zflags, zexpiration, zcas, zresult_cas; + zval params[7]; if (!MEMC_HAS_CB(event)) { return retval; @@ -474,36 +447,32 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zdata); - ZVAL_STRINGL(zdata, ((char *) data), (int) data_len, 1); - - MAKE_STD_ZVAL(zflags); - ZVAL_LONG(zflags, (long) flags); - - MAKE_STD_ZVAL(zexpiration); - ZVAL_LONG(zexpiration, (long) expiration); - - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, (double) cas); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zdata, ((char *) data), (int) data_len); + ZVAL_LONG(&zflags, (long) flags); + ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_DOUBLE(&zcas, (double) cas); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zdata); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zexpiration); + ZVAL_COPY(¶ms[5], &zcas); + ZVAL_COPY(¶ms[6], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zdata; - params [3] = &zflags; - params [4] = &zexpiration; - params [5] = &zcas; - params [6] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); + zval_ptr_dtor(¶ms[6]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zdata); @@ -535,11 +504,9 @@ static protocol_binary_response_status s_stat_handler (const void *cookie, const void *key, uint16_t key_len, memcached_binary_protocol_stat_response_handler response_handler) { - zval **params [3]; + zval params[3]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zbody; - - TSRMLS_FETCH(); + zval zcookie, zkey, zbody; if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { return retval; @@ -547,29 +514,30 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_NULL(&zbody); - MAKE_STD_ZVAL(zbody); - ZVAL_NULL(zbody); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zbody); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zbody; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE_P (zbody) == IS_NULL) { + if (Z_TYPE(zbody) == IS_NULL) { retval = response_handler(cookie, NULL, 0, NULL, 0); } else { - if (Z_TYPE_P (zbody) != IS_STRING) { - convert_to_string (zbody); + if (Z_TYPE(zbody) != IS_STRING) { + convert_to_string(&zbody); } - retval = response_handler(cookie, key, key_len, Z_STRVAL_P (zbody), (uint32_t) Z_STRLEN_P (zbody)); + retval = response_handler(cookie, key, key_len, Z_STRVAL(zbody), (uint32_t) Z_STRLEN(zbody)); } } + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zbody); @@ -580,11 +548,9 @@ static protocol_binary_response_status s_version_handler (const void *cookie, memcached_binary_protocol_version_response_handler response_handler) { - zval **params [2]; + zval params[2]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zversion; - - TSRMLS_FETCH(); + zval zcookie, zversion; if (!MEMC_HAS_CB(MEMC_SERVER_ON_VERSION)) { return retval; @@ -592,21 +558,23 @@ protocol_binary_response_status s_version_handler (const void *cookie, MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zversion); - ZVAL_NULL(zversion); + ZVAL_NULL(&zversion); - params [0] = &zcookie; - params [1] = &zversion; + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zversion); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE_P (zversion) != IS_STRING) { - convert_to_string (zversion); + if (Z_TYPE(zversion) != IS_STRING) { + convert_to_string(&zversion); } retval = response_handler (cookie, Z_STRVAL_P(zversion), (uint32_t) Z_STRLEN_P(zversion)); } + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zversion); return retval; @@ -623,36 +591,33 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) php_memc_client_t *client = (php_memc_client_t *) arg; memcached_protocol_event_t events; - TSRMLS_FETCH(); - if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { - zval *zremoteip, *zremoteport; - zval **params [2]; + zval zremoteip, zremoteport; + zval params[2]; protocol_binary_response_status retval; struct sockaddr_in addr_in; socklen_t addr_in_len = sizeof(addr_in); - MAKE_STD_ZVAL(zremoteip); - MAKE_STD_ZVAL(zremoteport); - if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(zremoteip, inet_ntoa (addr_in.sin_addr), 1); - ZVAL_LONG(zremoteport, ntohs (addr_in.sin_port)); + ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr), 1); + ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "getpeername failed: %s", strerror (errno)); - ZVAL_NULL(zremoteip); - ZVAL_NULL(zremoteport); + php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); + ZVAL_NULL(&zremoteip); + ZVAL_NULL(&zremoteport); } - params [0] = &zremoteip; - params [1] = &zremoteport; + ZVAL_COPY(¶ms[0], &zremoteip); + ZVAL_COPY(¶ms[1], &zremoteport); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); - zval_ptr_dtor (&zremoteip); - zval_ptr_dtor (&zremoteport); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&zremoteip); + zval_ptr_dtor(&zremoteport); if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { memcached_protocol_client_destroy (client->protocol_client); @@ -683,7 +648,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) rc = event_base_once (client->event_base, fd, flags, s_handle_memcached_event, client, NULL); if (rc != 0) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events"); + php_error_docref (NULL, E_WARNING, "Failed to schedule events"); } } @@ -698,14 +663,12 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) php_memc_proto_handler_t *handler = (php_memc_proto_handler_t *) arg; - TSRMLS_FETCH(); - /* Accept the connection */ addr_len = sizeof (addr); sock = accept (fd, (struct sockaddr *) &addr, &addr_len); if (sock == -1) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to accept the client: %s", strerror (errno)); + php_error_docref (NULL, E_WARNING, "Failed to accept the client: %s", strerror (errno)); return; } @@ -715,7 +678,7 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) client->on_connect_invoked = 0; if (!client->protocol_client) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); + php_error_docref (NULL, E_WARNING, "Failed to allocate protocol client"); efree (client); evutil_closesocket (sock); return; @@ -725,7 +688,7 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL); if (rc != 0) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client"); + php_error_docref (NULL, E_WARNING, "Failed to add event for client"); memcached_protocol_client_destroy (client->protocol_client); efree (client); evutil_closesocket (sock); @@ -771,59 +734,55 @@ evutil_socket_t s_create_listening_socket (const char *spec) int rc; - TSRMLS_FETCH(); - addr_len = sizeof (struct sockaddr); rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse bind address"); + php_error_docref(NULL, E_WARNING, "Failed to parse bind address"); return -1; } sock = socket (AF_INET, SOCK_STREAM, 0); if (sock < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "socket failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "socket failed: %s", strerror (errno)); return -1; } rc = bind (sock, (struct sockaddr *) &addr, addr_len); if (rc < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bind failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "bind failed: %s", strerror (errno)); return -1; } rc = listen (sock, 1024); if (rc < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "listen failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "listen failed: %s", strerror (errno)); return -1; } rc = evutil_make_socket_nonblocking (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket non-blocking: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket non-blocking: %s", strerror (errno)); return -1; } rc = evutil_make_listen_socket_reuseable (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket reuseable: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket reuseable: %s", strerror (errno)); return -1; } rc = evutil_make_socket_closeonexec (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket closeonexec: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket closeonexec: %s", strerror (errno)); return -1; } return sock; } -zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const char *address) +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, zend_string *address) { struct event *accept_event; - evutil_socket_t sock = s_create_listening_socket (address); - - TSRMLS_FETCH(); + evutil_socket_t sock = s_create_listening_socket (address->val); if (sock == -1) { return 0; @@ -831,22 +790,22 @@ zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const c handler->event_base = event_base_new(); if (!handler->event_base) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "failed to allocate memory: %s", strerror (errno)); } accept_event = event_new (handler->event_base, sock, EV_READ | EV_PERSIST, s_accept_cb, handler); if (!accept_event) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "failed to allocate memory: %s", strerror (errno)); } event_add (accept_event, NULL); switch (event_base_dispatch (handler->event_base)) { case -1: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno)); return 0; break; case 1: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "no events registered"); + php_error_docref(NULL, E_ERROR, "no events registered"); return 0; break; @@ -865,4 +824,11 @@ void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr) efree (handler); *ptr = NULL; -} \ No newline at end of file +} +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim: noet sw=4 ts=4 fdm=marker: + */ diff --git a/php_memcached_server.h b/php_memcached_server.h index 31676c53..285c608d 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -33,8 +33,8 @@ php_memc_proto_handler_t *php_memc_proto_handler_new (); void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); -zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, zend_string *address); #endif -#endif \ No newline at end of file +#endif diff --git a/php_memcached_session.c b/php_memcached_session.c index a3ef5678..118805aa 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -27,7 +27,7 @@ ps_module ps_mod_memcached = { PS_MOD(memcached) }; -static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) +static int php_memc_sess_lock(memcached_st *memc, const char *key) { char *lock_key = NULL; int lock_key_len = 0; @@ -72,7 +72,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) write_retry_attempts--; continue; } - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Write of lock failed"); + php_error_docref(NULL, E_WARNING, "Write of lock failed"); break; } @@ -85,7 +85,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) return -1; } -static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) +static void php_memc_sess_unlock(memcached_st *memc) { if (MEMC_G(sess_locked)) { memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); @@ -103,13 +103,14 @@ PS_OPEN_FUNC(memcached) int plist_key_len = 0; if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { - zend_rsrc_list_entry *le = NULL; + zend_resource *le = NULL; + zval *le_z = NULL; char *e; p = (char *)save_path + sizeof("PERSISTENT=") - 1; if (!*p) { error: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid persistent id for session storage"); + php_error_docref(NULL, E_WARNING, "Invalid persistent id for session storage"); return FAILURE; } if ((e = strchr(p, ' '))) { @@ -118,7 +119,9 @@ PS_OPEN_FUNC(memcached) goto error; } plist_key_len++; - if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { + + if ((le_z = zend_hash_str_find(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { + le = Z_RES_P(le_z); if (le->type == php_memc_sess_list_entry()) { memc_sess = (memcached_sess *) le->ptr; PS_SET_MOD_DATA(memc_sess); @@ -146,7 +149,7 @@ PS_OPEN_FUNC(memcached) efree(plist_key); } memcached_free(memc_sess->memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to enable memcached consistent hashing"); + php_error_docref(NULL, E_WARNING, "failed to enable memcached consistent hashing"); return FAILURE; } } @@ -160,7 +163,7 @@ PS_OPEN_FUNC(memcached) efree(plist_key); } memcached_free(memc_sess->memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); + php_error_docref(NULL, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); return FAILURE; } @@ -169,10 +172,10 @@ PS_OPEN_FUNC(memcached) } } else { memcached_server_list_free(servers); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_WARNING, "could not allocate libmemcached structure"); } } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); } } else { memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); @@ -180,12 +183,12 @@ PS_OPEN_FUNC(memcached) #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION char error_buffer[1024]; if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); + php_error_docref(NULL, E_WARNING, "session.save_path configuration error %s", error_buffer); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); + php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); } #else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); + php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); #endif } else { @@ -193,21 +196,25 @@ PS_OPEN_FUNC(memcached) PS_SET_MOD_DATA(memc_sess); if (plist_key) { - zend_rsrc_list_entry le; + zend_resource le; + zend_string *tmp_key; le.type = php_memc_sess_list_entry(); le.ptr = memc_sess; - if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + tmp_key = zend_string_init(plist_key, plist_key_len, 0); + if (zend_hash_update_mem(&EG(persistent_list), tmp_key, (void *)&le, sizeof(le)) == NULL) { + zend_string_release(tmp_key); efree(plist_key); - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); } + zend_string_release(tmp_key); efree(plist_key); } if (MEMC_G(sess_binary_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); return FAILURE; } } @@ -220,11 +227,11 @@ PS_OPEN_FUNC(memcached) if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) { /* Force binary protocol */ if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); return FAILURE; } if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session sasl credentials"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); return FAILURE; } MEMC_G(sess_sasl_data) = 1; @@ -235,23 +242,23 @@ PS_OPEN_FUNC(memcached) #endif if (MEMC_G(sess_number_of_replicas) > 0) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session number of replicas"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session number of replicas"); return FAILURE; } if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session randomize replica read"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session randomize replica read"); } } if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached connection timeout"); + php_error_docref(NULL, E_WARNING, "failed to set memcached connection timeout"); return FAILURE; } #ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set: remove failed servers"); + php_error_docref(NULL, E_WARNING, "failed to set: remove failed servers"); return FAILURE; } } @@ -272,7 +279,7 @@ PS_CLOSE_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess); } if (memc_sess->memc_sess) { if (!memc_sess->is_persistent) { @@ -294,7 +301,7 @@ PS_READ_FUNC(memcached) { char *payload = NULL; size_t payload_len = 0; - int key_len = strlen(key); + int key_len = key->len; uint32_t flags = 0; memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); @@ -302,23 +309,22 @@ PS_READ_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; } if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to clear session lock record"); + if (php_memc_sess_lock(memc_sess->memc_sess, key->val) < 0) { + php_error_docref(NULL, E_WARNING, "Unable to clear session lock record"); return FAILURE; } } - payload = memcached_get(memc_sess->memc_sess, key, key_len, &payload_len, &flags, &status); + payload = memcached_get(memc_sess->memc_sess, key->val, key_len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { - *val = estrndup(payload, payload_len); - *vallen = payload_len; + *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; } else { @@ -328,7 +334,7 @@ PS_READ_FUNC(memcached) PS_WRITE_FUNC(memcached) { - int key_len = strlen(key); + int key_len = key->len; time_t expiration = 0; long write_try_attempts = 1; memcached_return status; @@ -337,7 +343,7 @@ PS_WRITE_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; } @@ -352,7 +358,7 @@ PS_WRITE_FUNC(memcached) } do { - status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0); + status = memcached_set(memc_sess->memc_sess, key->val, key_len, val->val, val->len, expiration, 0); if (status == MEMCACHED_SUCCESS) { return SUCCESS; } else { @@ -367,9 +373,9 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - memcached_delete(memc_sess->memc_sess, key, strlen(key), 0); + memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess); } return SUCCESS; From 399b86bdcdd67039d271da9bbbe46cebe1749ffe Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 12:35:55 -0800 Subject: [PATCH 356/694] More tests pass now --- php_memcached.c | 54 ++++++++++++++++++++++++++--------------- php_memcached_session.c | 2 -- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 33570992..58fb66d4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -536,7 +536,7 @@ PHP_METHOD(Memcached, getByKey) static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; const char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; @@ -584,8 +584,11 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); - + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); + } else { + status = memcached_mget(m_obj->memc, keys, key_lens, 1); + } if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -685,7 +688,7 @@ PHP_METHOD(Memcached, getMultiByKey) static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - zend_string *server_key; + zend_string *server_key = NULL; size_t num_keys = 0; zval *entry = NULL; const char *payload = NULL; @@ -764,7 +767,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } } - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + } else { + status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + } /* Handle error, but ignore, there might still be some result */ php_memc_handle_error(i_obj, status); @@ -898,7 +905,7 @@ PHP_METHOD(Memcached, getDelayedByKey) static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - zend_string *server_key; + zend_string *server_key = NULL; zend_bool with_cas = 0; size_t num_keys = 0; zval *entry = NULL; @@ -967,8 +974,11 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* * Issue the request, but collect results only if the result callback is provided. */ - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + } else { + status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + } /* * Restore the CAS support flag, but only if we had to turn it on. */ @@ -1213,7 +1223,7 @@ PHP_METHOD(Memcached, setMultiByKey) static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - zend_string *server_key; + zend_string *server_key = NULL; time_t expiration = 0; long udf_flags = 0; zval *entry; @@ -1373,7 +1383,7 @@ PHP_METHOD(Memcached, replaceByKey) static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; zend_string *s_value; zval s_zvalue; zval *value; @@ -1468,7 +1478,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool retry: switch (op) { case MEMC_OP_SET: - if (!server_key->val) { + if (!server_key) { status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1477,7 +1487,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: - if (!server_key->val) { + if (!server_key) { status = memcached_touch(m_obj->memc, key->val, key->len, expiration); } else { status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1486,7 +1496,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; #endif case MEMC_OP_ADD: - if (!server_key->val) { + if (!server_key) { status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1495,7 +1505,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_REPLACE: - if (!server_key->val) { + if (!server_key) { status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1504,7 +1514,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_APPEND: - if (!server_key->val) { + if (!server_key) { status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1513,7 +1523,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_PREPEND: - if (!server_key->val) { + if (!server_key) { status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1547,7 +1557,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) double cas_d; uint64_t cas; zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; zval *value; time_t expiration = 0; long udf_flags = 0; @@ -1689,8 +1699,12 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + if (by_key) { + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, expiration); + } else { + status = memcached_delete(m_obj->memc, key->val, key->len, expiration); + } if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; @@ -1704,7 +1718,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - zend_string *server_key; + zend_string *server_key = NULL; time_t expiration = 0; zval *entry; @@ -1755,7 +1769,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by /* {{{ -- php_memc_incdec_impl */ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - zend_string *key, *server_key; + zend_string *key, *server_key = NULL; long offset = 1; uint64_t value, initial = 0; time_t expiry = 0; diff --git a/php_memcached_session.c b/php_memcached_session.c index 118805aa..1d2dbe32 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -310,7 +310,6 @@ PS_READ_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - PS(invalid_session_id) = 1; return FAILURE; } @@ -344,7 +343,6 @@ PS_WRITE_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - PS(invalid_session_id) = 1; return FAILURE; } From 479b6e2ef455e1a2679553a5538ba605f594363b Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 12:57:34 -0800 Subject: [PATCH 357/694] Fix 4 more tests --- php_memcached.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 58fb66d4..eda04625 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -580,7 +580,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } @@ -589,7 +589,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } else { status = memcached_mget(m_obj->memc, keys, key_lens, 1); } - if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -760,7 +760,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_tokens && Z_IS_REF(cas_tokens)) { + if (cas_tokens && Z_ISREF_P(cas_tokens)) { orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); @@ -778,7 +778,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Restore the CAS support flag, but only if we had to turn it on. */ - if (cas_tokens && Z_IS_REF(cas_tokens) && orig_cas_flag == 0) { + if (cas_tokens && Z_ISREF_P(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -790,7 +790,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as doubles, because we cannot store potential 64-bit values in longs. */ if (cas_tokens) { - if (Z_IS_REF(cas_tokens)) { + if (Z_ISREF_P(cas_tokens)) { /* cas_tokens was passed by reference, we'll create an array for it. */ ZVAL_DEREF(cas_tokens); SEPARATE_ZVAL(cas_tokens); From 3a93af390d0430dcae00b860b65e8ec5eddf82e9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 13:32:52 -0800 Subject: [PATCH 358/694] minor cleanup --- php_memcached.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index eda04625..9e381584 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2861,12 +2861,8 @@ zend_object_value php_memc_server_new(zend_class_entry *ce) zval *tmp; intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init (&intern->zo, ce); -#if PHP_VERSION_ID >= 50400 - object_properties_init( (zend_object *) intern, ce); -#else - zend_hash_copy(intern->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); -#endif + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); intern->handler = php_memc_proto_handler_new (); From a3279a8478483f750274bc1e74fe5d1a540aa354 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:30:29 +0800 Subject: [PATCH 359/694] Various bug fixes --- php_libmemcached_compat.c | 3 +- php_memcached.c | 73 ++++++++++++++++++++++----------------- php_memcached.h | 1 + tests/version.phpt | 4 +-- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index f238709e..f49b162b 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -49,4 +49,5 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len) } return memc; #endif -} \ No newline at end of file +} + diff --git a/php_memcached.c b/php_memcached.c index 9e381584..500110af 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -366,7 +366,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc } /* Call the cb */ - ZVAL_COPY_VALUE(¶ms[0], object); + ZVAL_COPY(¶ms[0], object); fci->params = params; fci->param_count = 2; @@ -420,7 +420,7 @@ static PHP_METHOD(Memcached, __construct) is_persistent = 1; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len+1, "memcached:id=%s", persistent_id->val); + snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; @@ -500,7 +500,8 @@ static PHP_METHOD(Memcached, __construct) le.type = php_memc_list_entry(); le.ptr = m_obj; GC_REFCOUNT(&le) = 1; - if (zend_hash_update_mem(&EG(persistent_list), plist_key, &le, sizeof(le)) == NULL) { + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { if (plist_key) { zend_string_release(plist_key); } @@ -853,13 +854,13 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - add_assoc_zval_ex(return_value, res_key, res_key_len+1, &value); + add_assoc_zval_ex(return_value, res_key, res_key_len, &value); if (cas_tokens) { cas = memcached_result_cas(&result); - add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); + add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); } if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } } @@ -946,7 +947,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ convert_to_string_ex(entry); } - if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { + if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { mkeys[i] = Z_STRVAL_P(entry); mkeys_len[i] = Z_STRLEN_P(entry); i++; @@ -1227,7 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke time_t expiration = 0; long udf_flags = 0; zval *entry; - zend_string *str_key = NULL; + zend_string *skey, *str_key = NULL; ulong num_key; char *payload; size_t payload_len; @@ -1262,9 +1263,9 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } } - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, str_key, entry) { - if (str_key) { - str_key = zend_string_init(str_key->val, str_key->len, 0); + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { + if (skey) { + str_key = skey; } else if (num_key || num_key == 0) { /* Array keys are unsigned, but php integers are signed. * Keys must be converted to signed strings that match @@ -1288,26 +1289,36 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } RETURN_FALSE; } retry: if (!by_key) { status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } } if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } efree(payload); RETURN_FALSE; } - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } efree(payload); } ZEND_HASH_FOREACH_END(); @@ -2334,7 +2345,7 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result) - 1); + RETURN_STRINGL(result, strlen(result)); #else RETURN_STRING(result); #endif @@ -2831,7 +2842,6 @@ static void php_memc_free_storage(zend_object *obj) zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; - efree(i_obj); } zend_object *php_memc_new(zend_class_entry *ce) @@ -2946,7 +2956,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); - add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, &entry); + add_assoc_zval_ex(context->return_value, hostport, hostport_len, &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. */ @@ -2974,7 +2984,7 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len); + add_assoc_stringl_ex(context->return_value, hostport, hostport_len, version, version_len); efree(hostport); return MEMCACHED_SUCCESS; } @@ -3206,7 +3216,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags default: if (!s_serialize_value (serializer, value, &buf, flags)) { - smart_str_free (&buf); + smart_str_free(&buf); return NULL; } pl = buf.s->val; @@ -3388,12 +3398,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: - if (payload_emalloc) { - ZVAL_STRINGL(value, pl, payload_len); - payload_emalloc = 0; - } else { - ZVAL_STRINGL(value, pl, payload_len); - } + ZVAL_STRINGL(value, pl, payload_len); break; case MEMC_VAL_IS_LONG: @@ -3514,6 +3519,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval params[4]; zval retval; zval z_key; + zval z_val; zval z_expiration; uint32_t flags = 0; @@ -3523,8 +3529,10 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i int result; ZVAL_STR(&z_key, key); - ZVAL_NULL(value); - ZVAL_LONG(&z_expiration, 0); + ZVAL_NULL(&z_val); + ZVAL_NEW_REF(value, &z_val); + ZVAL_NEW_REF(&z_expiration, &z_val); + ZVAL_LONG(Z_REFVAL(z_expiration), 0); ZVAL_COPY(¶ms[0], zmemc_obj); ZVAL_COPY(¶ms[1], &z_key); @@ -3536,9 +3544,12 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_UNREF(value); + ZVAL_UNREF(&z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - i_obj = (php_memc_t *) Z_OBJ_P(zmemc_obj); - struct memc_obj *m_obj = i_obj->obj; + struct memc_obj *m_obj; + i_obj = Z_MEMC_OBJ_P(zmemc_obj) + m_obj = i_obj->obj; if (zend_is_true(&retval)) { time_t expiration; diff --git a/php_memcached.h b/php_memcached.h index da4d6b92..2ce8e730 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -21,6 +21,7 @@ #include "php.h" #include "main/php_config.h" +#include "Zend/zend_smart_str.h" #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/tests/version.phpt b/tests/version.phpt index f9adcc52..8ffe275a 100644 --- a/tests/version.phpt +++ b/tests/version.phpt @@ -13,6 +13,6 @@ echo "OK" . PHP_EOL; --EXPECTF-- array(1) { ["%s:%d"]=> - string(6) "%d.%d.%d" + string(%d) "%d.%d.%d" } -OK \ No newline at end of file +OK From 35a543f0cb7a9825b8b19ddcf2ff44435a208355 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:48:36 +0800 Subject: [PATCH 360/694] Fixed memory leak --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 500110af..be745c26 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1699,7 +1699,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } - server_key = zend_string_copy(key); + server_key = key; } MEMC_METHOD_FETCH_OBJECT; From cbcbece3619bd067d64094cc04f7d6a676a28b66 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:54:26 +0800 Subject: [PATCH 361/694] Fixed getStat --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index be745c26..6a9776ab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2927,7 +2927,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; zval entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); array_init(&entry); From 6851bdd95f2a0f776fc55b4be8a43e2993a1268e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 18:01:11 +0800 Subject: [PATCH 362/694] Fixed memory leak --- php_memcached.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6a9776ab..99eed2f1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2548,16 +2548,9 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) if (Z_TYPE_P(pzval) == IS_LONG) { value = Z_LVAL_P(pzval); - } - else { - zval *tmp_zval, *tmp_pzval; - tmp_zval = pzval; - zval_copy_ctor(tmp_zval); - tmp_pzval = tmp_zval; - convert_to_long(tmp_pzval); - - value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0; - zval_dtor(tmp_pzval); + } else { + value = zval_get_long(pzval); + value = value > 0? value : 0; } if (value < 0) { From 229c6842225876c8f8bfca8706616db516451bc8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 18:34:34 +0800 Subject: [PATCH 363/694] Better implementation --- php_memcached.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 99eed2f1..ef49c8ec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3513,7 +3513,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval retval; zval z_key; zval z_val; - zval z_expiration; + zval *expiration, z_expiration; uint32_t flags = 0; memcached_return rc; @@ -3523,41 +3523,37 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i ZVAL_STR(&z_key, key); ZVAL_NULL(&z_val); - ZVAL_NEW_REF(value, &z_val); - ZVAL_NEW_REF(&z_expiration, &z_val); + ZVAL_NEW_REF(&z_val, value); + ZVAL_NEW_REF(&z_expiration, value); ZVAL_LONG(Z_REFVAL(z_expiration), 0); ZVAL_COPY(¶ms[0], zmemc_obj); ZVAL_COPY(¶ms[1], &z_key); - ZVAL_COPY(¶ms[2], value); - ZVAL_COPY(¶ms[3], &z_expiration); + ZVAL_COPY_VALUE(¶ms[2], &z_val); + ZVAL_COPY_VALUE(¶ms[3], &z_expiration); fci->retval = &retval; fci->params = params; fci->param_count = 4; result = zend_call_function(fci, fcc); - ZVAL_UNREF(value); - ZVAL_UNREF(&z_expiration); + ZVAL_DUP(value, Z_REFVAL(z_val)); + expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { struct memc_obj *m_obj; i_obj = Z_MEMC_OBJ_P(zmemc_obj) m_obj = i_obj->obj; if (zend_is_true(&retval)) { - time_t expiration; + time_t expir; - if (Z_TYPE(z_expiration) != IS_LONG) { - convert_to_long(&z_expiration); - } - - expiration = Z_LVAL(z_expiration); + expir = zval_get_long(expiration); payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expir, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } @@ -3571,8 +3567,6 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } else { if (result == FAILURE) { - zval_ptr_dtor(&z_key); - zval_ptr_dtor(&z_expiration); php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); } status = MEMCACHED_FAILURE; @@ -3585,6 +3579,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } zval_ptr_dtor(&z_key); + zval_ptr_dtor(&z_val); zval_ptr_dtor(&z_expiration); return status; From 1b2c2251f954d785c6ef9e05a8153eba69b96573 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 20:52:34 +0800 Subject: [PATCH 364/694] Fixed memleak, and use the recently added object_size api --- php_memcached.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index ef49c8ec..3a25a1a6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -546,6 +546,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) size_t key_lens[1] = { 0 }; zval *cas_token = NULL; zval *udf_flags = NULL; + uint64_t orig_cas_flag; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; @@ -575,7 +576,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) keys[0] = key->val; key_lens[0] = key->len; - uint64_t orig_cas_flag; orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); /* @@ -612,6 +612,8 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * ourselves. */ if (cas_token) { + ZVAL_DEREF(cas_token); + zval_ptr_dtor(cas_token); ZVAL_DOUBLE(cas_token, 0.0); } @@ -653,8 +655,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (cas_token) { ZVAL_DEREF(cas_token); - SEPARATE_ZVAL(cas_token); - zval_dtor(cas_token); + zval_ptr_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); } @@ -2839,7 +2840,7 @@ static void php_memc_free_storage(zend_object *obj) zend_object *php_memc_new(zend_class_entry *ce) { - php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + sizeof(zval) * (ce->default_properties_count - 1)); + php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); zend_object_std_init(&i_obj->zo, ce); object_properties_init(&i_obj->zo, ce); From e4f8f395f979a80e52ed04b32e6ce62eb2c9b298 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 4 Feb 2015 08:16:57 -0800 Subject: [PATCH 365/694] Down to 18 failed tests now --- php_memcached.h | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 2ce8e730..da4d6b92 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -21,7 +21,6 @@ #include "php.h" #include "main/php_config.h" -#include "Zend/zend_smart_str.h" #ifdef HAVE_CONFIG_H # include "config.h" From 1bb38ab0f7f58d2a7e91b90769e427a5066db4db Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 4 Feb 2015 09:37:06 -0800 Subject: [PATCH 366/694] Oops, need this for the inline stuff --- php_memcached.h | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.h b/php_memcached.h index da4d6b92..b96ef37a 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -20,6 +20,7 @@ #define PHP_MEMCACHED_H #include "php.h" +#include "Zend/zend_smart_str.h" #include "main/php_config.h" #ifdef HAVE_CONFIG_H From a9f703c3849a1056f356bdfc21ae1f3280fe2907 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 5 Feb 2015 11:15:51 +0800 Subject: [PATCH 367/694] Use strpprintf --- php_memcached.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3a25a1a6..a1ea6835 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2760,11 +2760,9 @@ static PHP_METHOD(Memcached, getResultMessage) case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: case MEMCACHED_UNKNOWN_READ_FAILURE: if (i_obj->memc_errno) { - char *str; - int str_len; - str_len = spprintf(&str, 0, "%s: %s", memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), - strerror(i_obj->memc_errno)); - RETURN_STRINGL(str, str_len); + zend_string *str = strpprintf(0, "%s: %s", + memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); + RETURN_STR(str); } /* Fall through */ default: From 0021b5c08344b84cfe9504dc9b5cbfaac331942b Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Thu, 12 Feb 2015 13:28:52 +0900 Subject: [PATCH 368/694] Use new session save handler --- php_memcached_session.c | 62 +++++++++++++++++++++++++++++++++++++-- php_memcached_session.h | 5 +++- tests/session_basic2.phpt | 47 +++++++++++++++++++++++++++++ tests/session_basic3.phpt | 47 +++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 tests/session_basic2.phpt create mode 100644 tests/session_basic3.phpt diff --git a/php_memcached_session.c b/php_memcached_session.c index 1d2dbe32..4d1a2572 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -24,7 +24,7 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_LOCK_EXPIRATION 30 ps_module ps_mod_memcached = { - PS_MOD(memcached) + PS_MOD_UPDATE_TIMESTAMP(memcached) }; static int php_memc_sess_lock(memcached_st *memc, const char *key) @@ -346,8 +346,8 @@ PS_WRITE_FUNC(memcached) return FAILURE; } - if (PS(gc_maxlifetime) > 0) { - expiration = PS(gc_maxlifetime); + if (maxlifetime > 0) { + expiration = maxlifetime; } /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ @@ -383,4 +383,60 @@ PS_GC_FUNC(memcached) { return SUCCESS; } + +PS_CREATE_SID_FUNC(memcached) +{ + zend_string *sid; + int maxfail = 3; + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + do { + sid = php_session_create_id((void**)&memc_sess); + if (!sid) { + if (--maxfail < 0) { + return NULL; + } else { + continue; + } + } + /* Check collision */ + /* FIXME: mod_data(memc_sess) should not be NULL (User handler could be NULL) */ + if (memc_sess && memcached_exist(memc_sess->memc_sess, sid->val, sid->len) == MEMCACHED_SUCCESS) { + if (sid) { + zend_string_release(sid); + sid = NULL; + } + if (--maxfail < 0) { + return NULL; + } + } + } while(!sid); + + return sid; +} + +PS_VALIDATE_SID_FUNC(memcached) +{ + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (memcached_exist(memc_sess->memc_sess, key->val, key->len) == MEMCACHED_SUCCESS) { + return SUCCESS; + } else { + return FAILURE; + } +} + +PS_UPDATE_TIMESTAMP_FUNC(memcached) +{ + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + time_t expiration = 0; + + if (maxlifetime > 0) { + expiration = maxlifetime; + } + if (memcached_touch(memc_sess->memc_sess, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + return FAILURE; + } + return SUCCESS; +} /* }}} */ diff --git a/php_memcached_session.h b/php_memcached_session.h index 97fe2005..4118362f 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -24,7 +24,7 @@ extern ps_module ps_mod_memcached; #define ps_memcached_ptr &ps_mod_memcached -PS_FUNCS(memcached); +PS_FUNCS_UPDATE_TIMESTAMP(memcached); PS_OPEN_FUNC(memcached); PS_CLOSE_FUNC(memcached); @@ -32,5 +32,8 @@ PS_READ_FUNC(memcached); PS_WRITE_FUNC(memcached); PS_DESTROY_FUNC(memcached); PS_GC_FUNC(memcached); +PS_CREATE_SID_FUNC(memcached); +PS_VALIDATE_SID_FUNC(memcached); +PS_UPDATE_TIMESTAMP_FUNC(memcached); #endif /* PHP_MEMCACHED_SESSION_H */ diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt new file mode 100644 index 00000000..f99063a8 --- /dev/null +++ b/tests/session_basic2.phpt @@ -0,0 +1,47 @@ +--TEST-- +Session basic open, write, destroy +--SKIPIF-- + +--INI-- +memcached.sess_locking = on +memcached.sess_lock_wait = 150000 +memcached.sess_prefix = "memc.sess.key." +session.save_handler = memcached + +--FILE-- +TRUE); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECT-- +NULL +array(1) { + ["foo"]=> + int(1) +} +array(0) { +} diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt new file mode 100644 index 00000000..fc4e7ae7 --- /dev/null +++ b/tests/session_basic3.phpt @@ -0,0 +1,47 @@ +--TEST-- +Session basic open, write, destroy +--SKIPIF-- + +--INI-- +memcached.sess_locking = on +memcached.sess_lock_wait = 150000 +memcached.sess_prefix = "memc.sess.key." +session.save_handler = memcached + +--FILE-- +TRUE); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECT-- +NULL +array(1) { + ["foo"]=> + int(1) +} +array(0) { +} From aa3bc57ac8807442ec707e6cd167ca246d2437e3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 12 Feb 2015 15:53:32 +0800 Subject: [PATCH 369/694] Fixed mem issue (double free) --- php_memcached.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a1ea6835..28675f14 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1299,14 +1299,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); - if (!skey) { - zend_string_release(str_key); - } } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); - if (!skey) { - zend_string_release(str_key); - } } if (php_memc_handle_error(i_obj, status) < 0) { From 4187e2277fa7469b0b8a67045083dde1950cecc0 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 22 Apr 2015 23:37:53 -0700 Subject: [PATCH 370/694] No more ZEND_CTOR_MAKE_NULL --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 28675f14..1063b229 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -407,8 +407,7 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - ZEND_CTOR_MAKE_NULL(); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } From 650b67c64ca8ac8bd140492fd1078015cb8eaa0b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 27 Jun 2015 18:28:31 +0200 Subject: [PATCH 371/694] Update php_memcached.c --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1063b229..9195bfcd 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3119,7 +3119,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, #ifdef HAVE_MEMCACHED_MSGPACK case SERIALIZER_MSGPACK: php_msgpack_serialize(buf, value); - if (!buf->c) { + if (!buf->s) { php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); return 0; } From 2af8314b36a4842c76c53be02550653a57445cf1 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 17:47:08 +0100 Subject: [PATCH 372/694] moar tests passing --- php_memcached.c | 26 ++++++++++++------------- tests/clone.phpt | 5 ++++- tests/experimental/cas_invalid_key.phpt | 4 ++-- tests/experimental/delete_bykey.phpt | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3a25a1a6..caf268cc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -170,7 +170,7 @@ typedef struct { } php_memc_t; static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { - return (php_memc_t *)((char *)(obj) - XtOffsetOf(php_memc_t, zo)); + return (php_memc_t *)((char *)obj - XtOffsetOf(php_memc_t, zo)); } #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); @@ -356,20 +356,17 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; - zval retval; - zval params[2]; + zval retval, id; if (persistent_id) { - ZVAL_STR(¶ms[1], persistent_id); + ZVAL_STR(&id, persistent_id); } else { - ZVAL_NULL(¶ms[1]); + ZVAL_NULL(&id); } - /* Call the cb */ - ZVAL_COPY(¶ms[0], object); + ZVAL_UNDEF(&retval); - fci->params = params; - fci->param_count = 2; + zend_fcall_info_argn(fci, 2, object, &id); fci->retval = &retval; fci->no_separation = 1; @@ -379,10 +376,12 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc efree (buf); ret = 0; } + + if (Z_TYPE(retval) != IS_UNDEF) + zval_ptr_dtor(&retval); + + zend_fcall_info_args_clear(fci, 1); - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(&retval); return ret; } @@ -408,7 +407,6 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info_cache fci_cache; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - ZEND_CTOR_MAKE_NULL(); return; } @@ -3304,6 +3302,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { + zval_ptr_dtor(value); ZVAL_FALSE(value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); php_error_docref(NULL, E_WARNING, "could not unserialize value"); @@ -3538,6 +3537,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_DUP(value, Z_REFVAL(z_val)); expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { diff --git a/tests/clone.phpt b/tests/clone.phpt index a0c49cd7..0b41c50c 100644 --- a/tests/clone.phpt +++ b/tests/clone.phpt @@ -12,4 +12,7 @@ $m = clone $m; echo "GOT HERE"; --EXPECTF-- -Fatal error: Trying to clone an uncloneable object of class Memcached in %s on line %d \ No newline at end of file +Fatal error: Uncaught Error: Trying to clone an uncloneable object of class Memcached in %s:6 +Stack trace: +#0 {main} + thrown in %s on line 6 diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/experimental/cas_invalid_key.phpt index c01d2c8d..3a69e40e 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/experimental/cas_invalid_key.phpt @@ -11,11 +11,11 @@ error_reporting(0); var_dump($m->cas(0, '', true, 10)); echo $m->getResultMessage(), "\n"; -var_dump($m->cas(0, ' �� jas kjjhask d ', true, 10)); +var_dump($m->cas(0, ' �� jas kjjhask d ', true, 10)); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- bool(false) A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) -%rCLIENT ERROR|NOT FOUND%r +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 87219539..9a198f15 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -21,7 +21,7 @@ var_dump($m->deleteByKey('keffe', '')); echo $m->getResultMessage(), "\n"; var_dump($m->deleteByKey('', 'keffe')); echo $m->getResultMessage(), "\n"; -var_dump($m->deleteByKey('keffe', '���as�� �a�sd�f asdf')); +var_dump($m->deleteByKey('keffe', '���as�� �a�sd�f asdf')); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- string(3) "foo" @@ -37,4 +37,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) NOT FOUND bool(false) -%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE|CLIENT ERROR%r +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE From 20636b2ae39a9c17d0e5b955770746a82b2bf4bb Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 18:22:15 +0100 Subject: [PATCH 373/694] down to four failures ... --- php_memcached.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index caf268cc..0c278505 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3582,6 +3582,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval_ptr_dtor(&z_key); zval_ptr_dtor(&z_val); zval_ptr_dtor(&z_expiration); + zval_ptr_dtor(zmemc_obj); return status; } @@ -3603,9 +3604,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, int rc = 0; php_memc_t *i_obj = NULL; - ZVAL_COPY(¶ms[0], zmemc_obj); fci->retval = &retval; - fci->params = params; fci->param_count = 2; payload = memcached_result_value(result); @@ -3624,7 +3623,6 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, } array_init(&z_result); - ZVAL_COPY(¶ms[1], &z_result); add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); if (cas != 0) { @@ -3634,16 +3632,19 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } + ZVAL_UNDEF(&retval); + zend_fcall_info_argn(fci, 2, zmemc_obj, &z_result); + if (zend_call_function(fci, fcc) == FAILURE) { php_error_docref(NULL, E_WARNING, "could not invoke result callback"); rc = -1; } - if (&retval) { + if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); } - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); + + zend_fcall_info_args_clear(fci, 1); zval_ptr_dtor(&z_result); return rc; From a335533ec8a4b6390196f5a1310f95aba8d37efc Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 19:08:15 +0100 Subject: [PATCH 374/694] another test expecting the wrong thing, it seems --- tests/experimental/get.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/experimental/get.phpt b/tests/experimental/get.phpt index 34537fc4..67e0b8f3 100644 --- a/tests/experimental/get.phpt +++ b/tests/experimental/get.phpt @@ -30,4 +30,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE string(4) "asdf" SUCCESS bool(false) -NOT FOUND +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE From 08cb8ff24caea581e97287de7c3427b67b20b1e6 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:15:02 +0100 Subject: [PATCH 375/694] bring travis up --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d529cf50..04f90cec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ language: php php: - - 5.5 - #- 5.4 - #- 5.3 + - 7.0 + env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 From 3a8c8fd7a016460d683fc68591072fce0a5c0c04 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:30:46 +0100 Subject: [PATCH 376/694] disable stuff not available for 7 yet --- .travis/travis.sh | 10 +++++----- php_memcached.c | 2 +- tests/bad_construct.phpt | 13 ++++++++----- tests/experimental/get_bykey_cas.phpt | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index f90cae9f..bda8646e 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -155,11 +155,11 @@ function run_memcached_tests() { pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" # We have one xfail test, we run it separately - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt + php run-tests.php -d extension=memcached.so -n ./tests/expire.phpt rm ./tests/expire.phpt # Run normal tests - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php -d extension=memcached.so -n ./tests/*.phpt retval=$? for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; @@ -213,14 +213,14 @@ case $ACTION in install_libmemcached # Install igbinary extension - install_igbinary + # install_igbinary # install msgpack - install_msgpack + # install_msgpack # install SASL if test "x$ENABLE_SASL" = "xyes"; then - install_sasl + # install_sasl fi ;; diff --git a/php_memcached.c b/php_memcached.c index 1cd97550..926db8a4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -406,7 +406,7 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } diff --git a/tests/bad_construct.phpt b/tests/bad_construct.phpt index 06bc7236..ab3079cf 100644 --- a/tests/bad_construct.phpt +++ b/tests/bad_construct.phpt @@ -4,7 +4,7 @@ Memcached construct with bad arguments --FILE-- setOption (Memcached::OPT_BINARY_PROTOCOL, true)); echo "OK" . PHP_EOL; --EXPECTF-- -Memcached::__construct() expects parameter %s -NULL +Warning: Memcached::__construct() expects parameter 1 to be string, object given in %s on line 3 +Memcached::__construct() expects parameter 1 to be string, object given +object(Memcached)#1 (0) { +} -Warning: Memcached::setOption(): Memcached constructor was not called in %s on line %d +Warning: Memcached::setOption(): Memcached constructor was not called in %s on line 14 NULL -OK \ No newline at end of file +OK + diff --git a/tests/experimental/get_bykey_cas.phpt b/tests/experimental/get_bykey_cas.phpt index ad94013e..6990927b 100644 --- a/tests/experimental/get_bykey_cas.phpt +++ b/tests/experimental/get_bykey_cas.phpt @@ -59,7 +59,7 @@ string(4) "asdf" float(%d) SUCCESS bool(false) -NULL +float(0) NOT FOUND bool(false) NULL From aaed3531e56d9d785e158645fdd47ebe6a7cd31c Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:34:27 +0100 Subject: [PATCH 377/694] some stabbing in the dark, why not --- .travis/travis.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index bda8646e..04f2603a 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -128,8 +128,9 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack - make + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + make make install popd } @@ -220,7 +221,7 @@ case $ACTION in # install SASL if test "x$ENABLE_SASL" = "xyes"; then - # install_sasl + install_sasl fi ;; From d354bf6551bc070e0c6374df8cadbc2c9e9f13df Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 19:07:42 +0100 Subject: [PATCH 378/694] update test to skip in appropriate versions (make travis more useful) --- tests/gh_155.phpt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index c1f02bc6..2e7f5643 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -1,7 +1,12 @@ --TEST-- Test for bug 155 --SKIPIF-- - + --FILE-- Date: Tue, 1 Sep 2015 19:12:52 +0100 Subject: [PATCH 379/694] omg, I'm a fumbling idiot --- tests/gh_155.phpt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 2e7f5643..643085ae 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,10 +2,9 @@ Test for bug 155 --SKIPIF-- --FILE-- Date: Tue, 1 Sep 2015 20:45:47 +0100 Subject: [PATCH 380/694] fix json support --- .travis/travis.sh | 5 +++-- config.m4 | 30 +++--------------------------- php_memcached.c | 21 +++------------------ 3 files changed, 9 insertions(+), 47 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 04f2603a..f045e594 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -73,6 +73,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php + git checkout php7 phpize ./configure make @@ -128,8 +129,8 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-igbinary --enable-memcached-msgpack + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json make make install popd diff --git a/config.m4 b/config.m4 index 107f8cbe..ec1e4ae8 100644 --- a/config.m4 +++ b/config.m4 @@ -127,7 +127,7 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_VERSION_MASK=`echo ${PHP_MEMCACHED_VERSION_ORIG} | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` - if test $PHP_MEMCACHED_VERSION_MASK -ge 5003000; then + if test $PHP_MEMCACHED_VERSION_MASK -ge 7000000; then if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then json_inc_path="$abs_srcdir/include/php" elif test -f "$abs_srcdir/ext/json/php_json.h"; then @@ -145,33 +145,9 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Cannot find php_json.h]) else AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_DEFINE(HAVE_JSON_API_5_3,1,[Whether JSON API for PHP 5.3 is available]) - AC_MSG_RESULT([$json_inc_path]) fi - elif test $PHP_MEMCACHED_VERSION_MASK -ge 5002009; then - dnl Check JSON for PHP 5.2.9+ - if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir/include/php" - elif test -f "$abs_srcdir/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir" - elif test -f "$phpincludedir/ext/json/php_json.h"; then - json_inc_path="$phpincludedir" - else - for i in php php4 php5 php6; do - if test -f "$prefix/include/$i/ext/json/php_json.h"; then - json_inc_path="$prefix/include/$i" - fi - done - fi - if test "$json_inc_path" = ""; then - AC_MSG_ERROR([Cannot find php_json.h]) - else - AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_DEFINE(HAVE_JSON_API_5_2,1,[Whether JSON API for PHP 5.2 is available]) - AC_MSG_RESULT([$json_inc_path]) - fi - else - AC_MSG_RESULT([the PHP version does not support JSON serialization API]) + else + AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) fi fi diff --git a/php_memcached.c b/php_memcached.c index 926db8a4..9f65e52f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,7 +37,7 @@ #endif #include -#ifdef HAVE_JSON_API +#ifdef HAVE_JSON # include "ext/json/php_json.h" #endif @@ -49,13 +49,6 @@ # include "ext/msgpack/php_msgpack.h" #endif -/* - * This is needed because PHP 5.3.[01] does not install JSON_parser.h by default. This - * constant will move into php_json.h in the future anyway. - */ -#ifndef JSON_PARSER_DEFAULT_DEPTH -#define JSON_PARSER_DEFAULT_DEPTH 512 -#endif /**************************************** Custom options @@ -3102,11 +3095,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, case SERIALIZER_JSON: case SERIALIZER_JSON_ARRAY: { -#if HAVE_JSON_API_5_2 - php_json_encode(buf, value); -#elif HAVE_JSON_API_5_3 - php_json_encode(buf, value, 0); /* options */ -#endif + php_json_encode(buf, value, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } break; @@ -3320,11 +3309,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API -# if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY)); -# elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); -# endif + php_json_decode(value, payload, payload_len, ,(serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); #else ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); From b04d020aa7accfa51b1f552bcb9a2f44e45d1a7c Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 20:52:00 +0100 Subject: [PATCH 381/694] minor woops --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 9f65e52f..fb68274a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,7 +37,7 @@ #endif #include -#ifdef HAVE_JSON +#ifdef HAVE_JSON_API # include "ext/json/php_json.h" #endif From 2f5a5b06b1296f081148eafa1d08c89b2b035ab8 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 21:25:01 +0100 Subject: [PATCH 382/694] woops --- config.m4 | 1 + php_memcached.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index ec1e4ae8..a4bbda4e 100644 --- a/config.m4 +++ b/config.m4 @@ -145,6 +145,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Cannot find php_json.h]) else AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) + AC_MSG_RESULT([$json_inc_path]) fi else AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) diff --git a/php_memcached.c b/php_memcached.c index fb68274a..a6c338b8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3309,7 +3309,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(value, payload, payload_len, ,(serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(value, (char*) payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); #else ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); From a24e439cb6f9c38d1a51c0df2cf6dab79e0a14bc Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 2 Sep 2015 08:06:48 +0100 Subject: [PATCH 383/694] tidy configure stuff for json --- .travis/travis.sh | 4 ++-- config.m4 | 54 +++++++++++++++-------------------------------- tests/types.inc | 5 +++-- 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index f045e594..e6733526 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -129,8 +129,8 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-igbinary --enable-memcached-msgpack - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag make make install popd diff --git a/config.m4 b/config.m4 index a4bbda4e..48efd176 100644 --- a/config.m4 +++ b/config.m4 @@ -106,49 +106,29 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([$session_inc_path]) fi fi - + if test "$PHP_MEMCACHED_JSON" != "no"; then AC_MSG_CHECKING([for json includes]) json_inc_path="" - - tmp_version=$PHP_VERSION - if test -z "$tmp_version"; then - if test -z "$PHP_CONFIG"; then - AC_MSG_ERROR([php-config not found]) - fi - PHP_MEMCACHED_VERSION_ORIG=`$PHP_CONFIG --version`; - else - PHP_MEMCACHED_VERSION_ORIG=$tmp_version - fi - if test -z $PHP_MEMCACHED_VERSION_ORIG; then - AC_MSG_ERROR([failed to detect PHP version, please report]) + if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then + json_inc_path="$abs_srcdir/include/php" + elif test -f "$abs_srcdir/ext/json/php_json.h"; then + json_inc_path="$abs_srcdir" + elif test -f "$phpincludedir/ext/json/php_json.h"; then + json_inc_path="$phpincludedir" + else + for i in php php4 php5 php6; do + if test -f "$prefix/include/$i/ext/json/php_json.h"; then + json_inc_path="$prefix/include/$i" + fi + done fi - - PHP_MEMCACHED_VERSION_MASK=`echo ${PHP_MEMCACHED_VERSION_ORIG} | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` - - if test $PHP_MEMCACHED_VERSION_MASK -ge 7000000; then - if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir/include/php" - elif test -f "$abs_srcdir/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir" - elif test -f "$phpincludedir/ext/json/php_json.h"; then - json_inc_path="$phpincludedir" - else - for i in php php4 php5 php6; do - if test -f "$prefix/include/$i/ext/json/php_json.h"; then - json_inc_path="$prefix/include/$i" - fi - done - fi - if test "$json_inc_path" = ""; then - AC_MSG_ERROR([Cannot find php_json.h]) - else - AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_MSG_RESULT([$json_inc_path]) - fi + if test "$json_inc_path" = ""; then + AC_MSG_ERROR([Cannot find php_json.h]) else - AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) + AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) + AC_MSG_RESULT([$json_inc_path]) fi fi diff --git a/tests/types.inc b/tests/types.inc index 5e0ad5d3..9532c8fc 100644 --- a/tests/types.inc +++ b/tests/types.inc @@ -54,11 +54,12 @@ function memc_types_test ($m, $options) if ($value == $actual && get_class($value) == get_class($actual)) continue; } - echo "=== $types[0] ===\n"; + echo "=== {$key} ===\n"; echo "Expected: "; - var_dump($types[1]); + var_dump($value); echo "Actual: "; var_dump($actual); + } } From d68098e61dc5d6501b3dbf08a3bf87837f4992cf Mon Sep 17 00:00:00 2001 From: Alex Samorukov Date: Thu, 12 Nov 2015 23:11:50 +0100 Subject: [PATCH 384/694] check if session was allocated on PS_OPEN_FUNC --- php_memcached_session.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index a3ef5678..a4e89aed 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -270,6 +270,11 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); @@ -300,6 +305,11 @@ PS_READ_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); @@ -334,6 +344,11 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { @@ -367,6 +382,11 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + memcached_delete(memc_sess->memc_sess, key, strlen(key), 0); if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); From 23db27a09ba3b35756305aa5bf487a9e530e9166 Mon Sep 17 00:00:00 2001 From: Alex Samorukov Date: Thu, 12 Nov 2015 23:20:44 +0100 Subject: [PATCH 385/694] check if session was allocated on PS_OPEN_FUNC --- php_memcached_session.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 1d2dbe32..b04cd925 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -277,6 +277,11 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess); @@ -307,6 +312,11 @@ PS_READ_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); @@ -339,6 +349,11 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { @@ -371,6 +386,11 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess); From fb8ce9e3cbfdacb50dc8b916e8502bb9e58d2e20 Mon Sep 17 00:00:00 2001 From: Will Gallego Date: Tue, 17 Nov 2015 20:52:04 +0000 Subject: [PATCH 386/694] removing unused var, fixing smart_str use w/ igbinary --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..a96a2aed 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3080,7 +3080,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value) != 0) { + if (igbinary_serialize((uint8_t **) &(buf->s), &buf->s->len, value) != 0) { php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } @@ -3575,7 +3575,6 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zval value; zval retval; uint64_t cas = 0; - zval params[2]; zval z_result; uint32_t flags = 0; int rc = 0; From b5a58cd207ca50df9288ba124c37fda65e1e1d4b Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 16 Dec 2015 13:42:28 +0000 Subject: [PATCH 387/694] remove duplicate class constant registration --- php_memcached.c | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..72637d1c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4319,7 +4319,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); REGISTER_MEMC_CLASS_CONST_LONG(RES_E2BIG, MEMCACHED_E2BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_KEY_TOO_BIG, MEMCACHED_KEY_TOO_BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_TEMPORARILY_DISABLED, MEMCACHED_SERVER_TEMPORARILY_DISABLED); From bd321830676d7e313b4b39bec6fbeb6ec9f9f7d8 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Sat, 16 Jan 2016 06:19:50 +0900 Subject: [PATCH 388/694] Fixed session read return value --- php_memcached_session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 4d1a2572..59b12467 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -326,6 +326,8 @@ PS_READ_FUNC(memcached) *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; + } else if (status = MEMCACHED_NOTFOUND) { + *val = ZSTR_EMPTY_ALLOC(); } else { return FAILURE; } From 9e11ffa8e5d5e6b1256dc44b7f043e7114122170 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 21:40:35 +0000 Subject: [PATCH 389/694] Revert the user flags and move into Memcached::getLastUserFlags --- php_memcached.c | 194 +++++++++++++++++++++--------------------- tests/user-flags.phpt | 72 +++++++++++----- 2 files changed, 148 insertions(+), 118 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..1339f308 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -58,6 +58,7 @@ #define MEMC_OPT_SERIALIZER -1003 #define MEMC_OPT_COMPRESSION_TYPE -1004 #define MEMC_OPT_STORE_RETRY_COUNT -1005 +#define MEMC_OPT_USER_FLAGS -1006 /**************************************** Custom result codes @@ -153,8 +154,10 @@ typedef struct { zend_bool has_sasl_data; #endif long store_retry_count; + zend_long set_udf_flags; } *obj; + zval last_udf_flags; zend_bool is_persistent; zend_bool is_pristine; int rescode; @@ -466,6 +469,9 @@ static PHP_METHOD(Memcached, __construct) m_obj->compression = 1; m_obj->store_retry_count = MEMC_G(store_retry_count); + m_obj->set_udf_flags = -1; + array_init(&i_obj->last_udf_flags); + i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -508,7 +514,23 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) +/* {{{ Memcached::getLastUserFlags() + Returns the user flags from last fetch operation */ +PHP_METHOD(Memcached, getLastUserFlags) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + RETVAL_ZVAL(&i_obj->last_udf_flags, 1, 0); +} +/* }}} */ + + +/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) Returns a value for the given key or false */ PHP_METHOD(Memcached, get) { @@ -516,7 +538,7 @@ PHP_METHOD(Memcached, get) } /* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) Returns a value for key from the server identified by the server key or false */ PHP_METHOD(Memcached, getByKey) { @@ -536,7 +558,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) const char* keys[1] = { NULL }; size_t key_lens[1] = { 0 }; zval *cas_token = NULL; - zval *udf_flags = NULL; uint64_t orig_cas_flag; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; @@ -545,13 +566,11 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!zz", &server_key, &key, - &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!z", &server_key, &key, &fci, &fcc, &cas_token) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!zz", &key, - &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!z", &key, &fci, &fcc, &cas_token) == FAILURE) { return; } } @@ -559,7 +578,9 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -650,18 +671,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) ZVAL_DOUBLE(cas_token, (double)cas); } - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); - } - + /* Parse user flags */ + add_assoc_long_ex(&i_obj->last_udf_flags, key->val, key->len, MEMC_VAL_GET_USER_FLAGS(flags)); memcached_result_free(&result); } /* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens [, array &udf_flags ] ]) +/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) Returns values for the given keys or false */ PHP_METHOD(Memcached, getMulti) { @@ -669,7 +685,7 @@ PHP_METHOD(Memcached, getMulti) } /* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens [, array &udf_flags ] ]) +/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) Returns values for the given keys from the server identified by the server key or false */ PHP_METHOD(Memcached, getMultiByKey) { @@ -693,7 +709,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint32_t flags; uint64_t cas = 0; zval *cas_tokens = NULL; - zval *udf_flags = NULL; uint64_t orig_cas_flag = 0; zval value; long get_flags = 0; @@ -704,12 +719,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zlz", &server_key, - &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zl", &server_key, + &keys, &cas_tokens, &get_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { return; } } @@ -717,6 +732,9 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; + /* clean flags */ + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); @@ -801,12 +819,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * Iterate through the result set and create the result array. The flags are * returned as longs. */ - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - array_init(udf_flags); - } memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { @@ -851,9 +863,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); } - if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); - } + add_assoc_long_ex(&i_obj->last_udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -866,12 +876,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval_dtor(cas_tokens); ZVAL_NULL(cas_tokens); } - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - ZVAL_NULL(udf_flags); - } + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); zval_dtor(return_value); RETURN_FALSE; } @@ -1136,7 +1141,7 @@ PHP_METHOD(Memcached, fetchAll) } /* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::set(string key, mixed value [, int expiration ]) Sets the value for the given key */ PHP_METHOD(Memcached, set) { @@ -1144,7 +1149,7 @@ PHP_METHOD(Memcached, set) } /* }}} */ -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the server key */ PHP_METHOD(Memcached, setByKey) { @@ -1171,7 +1176,7 @@ PHP_METHOD(Memcached, touchByKey) #endif -/* {{{ Memcached::setMulti(array items [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setMulti(array items [, int expiration ]) Sets the keys/values specified in the items array */ PHP_METHOD(Memcached, setMulti) { @@ -1179,7 +1184,7 @@ PHP_METHOD(Memcached, setMulti) } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) Sets the keys/values specified in the items array on the server identified by the given server key */ PHP_METHOD(Memcached, setMultiByKey) { @@ -1218,7 +1223,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *entries; zend_string *server_key = NULL; time_t expiration = 0; - long udf_flags = 0; zval *entry; zend_string *skey, *str_key = NULL; ulong num_key; @@ -1233,11 +1237,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration, &udf_flags) == FAILURE) { + &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { return; } } @@ -1245,16 +1249,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - } - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { if (skey) { str_key = skey; @@ -1274,8 +1268,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } - if (udf_flags > 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); @@ -1312,7 +1306,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::add(string key, mixed value [, int expiration ]) Sets the value for the given key, failing if the key already exists */ PHP_METHOD(Memcached, add) { @@ -1320,7 +1314,7 @@ PHP_METHOD(Memcached, add) } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ PHP_METHOD(Memcached, addByKey) { @@ -1360,7 +1354,7 @@ PHP_METHOD(Memcached, prependByKey) } /* }}} */ -/* {{{ Memcached::replace(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) Replaces the value for the given key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replace) { @@ -1368,7 +1362,7 @@ PHP_METHOD(Memcached, replace) } /* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replaceByKey) { @@ -1385,7 +1379,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; long expiration = 0; - long udf_flags = 0; char *payload = NULL; size_t payload_len; uint32_t flags = 0; @@ -1405,7 +1398,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|ll", &server_key, &key, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { return; } } @@ -1421,7 +1414,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|ll", &key, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { return; } } @@ -1430,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1452,11 +1445,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } if (op == MEMC_OP_TOUCH) { @@ -1557,7 +1547,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; time_t expiration = 0; - long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1566,12 +1555,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, - &value, &expiration, &udf_flags) == FAILURE) { + &value, &expiration) == FAILURE) { return; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, - &expiration, &udf_flags) == FAILURE) { + &expiration) == FAILURE) { return; } } @@ -1579,7 +1568,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1594,11 +1583,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags > 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); @@ -1621,7 +1607,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* }}} */ -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, cas) { @@ -1629,7 +1615,7 @@ PHP_METHOD(Memcached, cas) } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, casByKey) { @@ -2344,6 +2330,10 @@ static PHP_METHOD(Memcached, getOption) RETURN_LONG((long)m_obj->serializer); break; + case MEMC_OPT_USER_FLAGS: + RETURN_LONG(m_obj->set_udf_flags); + break; + case MEMC_OPT_STORE_RETRY_COUNT: RETURN_LONG((long)m_obj->store_retry_count); break; @@ -2481,6 +2471,21 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) break; } + case MEMC_OPT_USER_FLAGS: + convert_to_long(value); + + if (Z_LVAL_P(value) < 0) { + m_obj->set_udf_flags = -1; + return 1; + } + + if (Z_LVAL_P(value) > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); + return 0; + } + m_obj->set_udf_flags = Z_LVAL_P(value); + break; + case MEMC_OPT_STORE_RETRY_COUNT: convert_to_long(value); m_obj->store_retry_count = Z_LVAL_P(value); @@ -2805,23 +2810,23 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) if (m_obj->memc) { memcached_free(m_obj->memc); } - pefree(m_obj, persistent); } static void php_memc_free_storage(zend_object *obj) { php_memc_t *i_obj = php_memc_fetch_object(obj); - + if (i_obj->obj && !i_obj->is_persistent) { php_memc_destroy(i_obj->obj, 0); } + zval_ptr_dtor(&i_obj->last_udf_flags); zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; } -zend_object *php_memc_new(zend_class_entry *ce) +static zend_object *php_memc_new(zend_class_entry *ce) { php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); @@ -3514,7 +3519,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); - + ZVAL_DUP(value, Z_REFVAL(z_val)); expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { @@ -3552,7 +3557,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i ZVAL_NULL(value); } - if (&retval) { + if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } @@ -3712,7 +3717,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(2, cas_token) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) @@ -3720,14 +3724,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(2, cas_token) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) @@ -3735,7 +3737,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) @@ -3761,7 +3762,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) @@ -3769,7 +3769,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) @@ -3786,21 +3785,21 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_getLastUserFlags, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) @@ -3808,14 +3807,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) @@ -3823,7 +3820,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) @@ -3857,7 +3853,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) @@ -3866,7 +3861,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1) @@ -4029,6 +4023,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) + MEMC_ME(getLastUserFlags, arginfo_getLastUserFlags) + MEMC_ME(cas, arginfo_cas) MEMC_ME(casByKey, arginfo_casByKey) MEMC_ME(add, arginfo_add) @@ -4187,6 +4183,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); + + REGISTER_MEMC_CLASS_CONST_LONG(OPT_USER_FLAGS, MEMC_OPT_USER_FLAGS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT); /* diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 2ed44c9a..137ff1e8 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -22,46 +22,78 @@ define ('FLAG_4', 4); define ('FLAG_32', 32); define ('FLAG_64', 64); define ('FLAG_TOO_LARGE', pow(2, 16)); -$x = 0; include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true)); $key = uniqid ('udf_test_'); -echo "stored with flags" . PHP_EOL; +// Set with flags off +$m->set ($key, '1', 10); +$m->get($key); +var_dump($m->getLastUserFlags()); -$m->set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); -$udf_flags = 0; -$value = $m->get ($key, null, $x, $udf_flags); +// Set flags on +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1)); -check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); +// Multiple flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); -echo "stored without flags" . PHP_EOL; -$m->set ($key, '1'); -$value = $m->get ($key, null, $x, $udf_flags); +// Even more flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4 | FLAG_32 | FLAG_64); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); -var_dump ($udf_flags == 0); -$m->set ($key, '1', 10, FLAG_TOO_LARGE); +// User flags with get multi +$values = array( + uniqid ('udf_test_multi_') => "first", + uniqid ('udf_test_multi_') => "second", + uniqid ('udf_test_multi_') => "third", +); +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_2 | FLAG_4); +$m->setMulti($values); +$m->getMulti(array_keys($values)); +$flags = $m->getLastUserFlags(); + +foreach (array_keys($values) as $key) { + check_flags($flags[$key], array(FLAG_2, FLAG_4)); +} + +// User flags with compression on +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); $m->setOption(Memcached::OPT_COMPRESSION, true); $m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ); -$m->set ($key, str_repeat ("abcdef1234567890", 200), 10, FLAG_1 | FLAG_4 | FLAG_64); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); -$udf_flags = 0; -$value_back = $m->get($key, null, null, $udf_flags); -check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); +// Too large flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> --EXPECTF-- -stored with flags +array(1) { + ["udf_test_%s"]=> + int(0) +} +Flags OK Flags OK -stored without flags -bool(true) - -Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d Flags OK +Flags OK +Flags OK +Flags OK +Flags OK + +Warning: Memcached::setOption(): MEMC_OPT_USER_FLAGS must be < 65535 in %s on line %d DONE TEST \ No newline at end of file From 9d5f3b956a7d0575c748cb2a4526171f63cee058 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 21:53:07 +0000 Subject: [PATCH 390/694] Use cache with travis --- .travis.yml | 4 ++++ .travis/travis.sh | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04f90cec..188bedba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,7 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION + +cache: + directories: + - $HOME/cache \ No newline at end of file diff --git a/.travis/travis.sh b/.travis/travis.sh index e6733526..e87a372f 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -44,6 +44,12 @@ function validate_package_xml() { function install_libmemcached() { + if test -d "${LIBMEMCACHED_PREFIX}" + then + echo "Using cached libmemcached: ${LIBMEMCACHED_PREFIX}" + return + fi + wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" -O libmemcached-${LIBMEMCACHED_VERSION}.tar.gz tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz @@ -83,17 +89,25 @@ function install_msgpack() { function install_sasl() { - wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz -O memcached-1.4.15.tar.gz - tar xfz memcached-1.4.15.tar.gz + local prefix="${HOME}/cache/memcached" + + if test -f "${prefix}/bin/memcached" + then + echo "Using cached memcached-sasl: ${prefix}/bin/memcached" + return + fi + + wget http://www.memcached.org/files/memcached-1.4.25.tar.gz -O memcached-1.4.25.tar.gz + tar xfz memcached-1.4.25.tar.gz - pushd memcached-1.4.15 - ./configure --enable-sasl --prefix="${HOME}/memcached" + pushd memcached-1.4.25 + ./configure --enable-sasl --prefix="${prefix}" make make install popd sudo apt-get install sasl2-bin - export SASL_CONF_PATH="${HOME}/sasl2" + export SASL_CONF_PATH="${HOME}/cache/sasl2" # Create config path mkdir "${SASL_CONF_PATH}" @@ -109,7 +123,7 @@ EOF echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" # Run memcached on port 11212 with SASL support - "${HOME}/memcached/bin/memcached" -S -d -p 11212 + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { @@ -192,7 +206,7 @@ fi PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') # Libmemcached install dir -LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" +LIBMEMCACHED_PREFIX="${HOME}/cache/libmemcached-${LIBMEMCACHED_VERSION}" # Where to do the build PHP_MEMCACHED_BUILD_DIR="/tmp/php-memcached-build" From 852d60cbc726532310abf598c6ea391b0c6407c4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:00:30 +0000 Subject: [PATCH 391/694] More travis updates --- .travis.yml | 11 ++++++++++- .travis/travis.sh | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 188bedba..c60ed89c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,11 @@ env: - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.49 - LIBMEMCACHED_VERSION=0.44 +addons: + apt: + packages: + - sasl2-bin + - libsasl2-dev services: - memcached # will start memcached @@ -25,6 +30,10 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION +sudo: false + cache: directories: - - $HOME/cache \ No newline at end of file + - $HOME/cache + + \ No newline at end of file diff --git a/.travis/travis.sh b/.travis/travis.sh index e87a372f..923eb518 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -106,7 +106,6 @@ function install_sasl() { make install popd - sudo apt-get install sasl2-bin export SASL_CONF_PATH="${HOME}/cache/sasl2" # Create config path From f3bfce3ec85e7aa8a25a28de1bc04bb0263df993 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:17:21 +0000 Subject: [PATCH 392/694] Run our own memcached --- .travis.yml | 4 +--- .travis/travis.sh | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index c60ed89c..30e5c3e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ php: - 7.0 env: + - LIBMEMCACHED_VERSION=1.0.18 - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 - LIBMEMCACHED_VERSION=1.0.15 @@ -21,9 +22,6 @@ addons: - sasl2-bin - libsasl2-dev -services: - - memcached # will start memcached - before_script: - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION diff --git a/.travis/travis.sh b/.travis/travis.sh index 923eb518..a80e0cf3 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -1,5 +1,7 @@ #!/bin/bash +MEMCACHED_VERSION="1.4.25" + function version_compare() { DPKG=`which dpkg` @@ -87,27 +89,35 @@ function install_msgpack() { popd } -function install_sasl() { - +function install_memcached() { local prefix="${HOME}/cache/memcached" - if test -f "${prefix}/bin/memcached" + if test -d "$prefix" then - echo "Using cached memcached-sasl: ${prefix}/bin/memcached" + echo "Using cached memcached: ${prefix}" return fi - wget http://www.memcached.org/files/memcached-1.4.25.tar.gz -O memcached-1.4.25.tar.gz - tar xfz memcached-1.4.25.tar.gz + wget http://www.memcached.org/files/memcached-${MEMCACHED_VERSION}.tar.gz -O memcached-${MEMCACHED_VERSION}.tar.gz + tar xfz memcached-${MEMCACHED_VERSION}.tar.gz - pushd memcached-1.4.25 + pushd memcached-${MEMCACHED_VERSION} ./configure --enable-sasl --prefix="${prefix}" make make install popd +} + +function install_sasl_config() { export SASL_CONF_PATH="${HOME}/cache/sasl2" + if test -f "${SASL_CONF_PATH}/memcached.conf" + then + echo "Using cached SASL configuration: ${SASL_CONF_PATH}/memcached.conf" + return + fi + # Create config path mkdir "${SASL_CONF_PATH}" @@ -120,6 +130,13 @@ EOF # Create password echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" +} + +function run_memcached() { + local prefix="${HOME}/cache/memcached" + + # Run normal memcached + "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support "${prefix}/bin/memcached" -S -d -p 11212 @@ -232,11 +249,10 @@ case $ACTION in # install msgpack # install_msgpack - - # install SASL - if test "x$ENABLE_SASL" = "xyes"; then - install_sasl - fi + + install_memcached + install_sasl_config + run_memcached ;; script) From dcdd3b88c57f6ee2fc43d20f1ec7ad7444c42be5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:22:25 +0000 Subject: [PATCH 393/694] Allow specifying memcached version --- .travis/travis.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a80e0cf3..78ae9ffb 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -1,7 +1,5 @@ #!/bin/bash -MEMCACHED_VERSION="1.4.25" - function version_compare() { DPKG=`which dpkg` @@ -90,7 +88,7 @@ function install_msgpack() { } function install_memcached() { - local prefix="${HOME}/cache/memcached" + local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" if test -d "$prefix" then @@ -133,7 +131,7 @@ EOF } function run_memcached() { - local prefix="${HOME}/cache/memcached" + local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 @@ -207,6 +205,7 @@ function run_memcached_tests() { # Command line arguments ACTION=$1 LIBMEMCACHED_VERSION=$2 +MEMCACHED_VERSION="1.4.25" if test "x$ACTION" = "x"; then echo "Usage: $0 " @@ -218,6 +217,10 @@ if test "x$LIBMEMCACHED_VERSION" = "x"; then exit 1 fi +if test "x$3" != "x"; then + MEMCACHED_VERSION=$3 +fi + # the extension version PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') From 5eb3bfd4fe8a6532ad80fc784020e70fabfedfec Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:05:32 +0000 Subject: [PATCH 394/694] Fixes to keys and tests --- php_memcached.c | 14 +++++++------- tests/keys.phpt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c7fb08ba..f5a9ea22 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -424,6 +424,7 @@ static PHP_METHOD(Memcached, __construct) } i_obj->is_persistent = is_persistent; + array_init(&i_obj->last_udf_flags); if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); @@ -470,7 +471,6 @@ static PHP_METHOD(Memcached, __construct) m_obj->store_retry_count = MEMC_G(store_retry_count); m_obj->set_udf_flags = -1; - array_init(&i_obj->last_udf_flags); i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -580,7 +580,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1423,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1568,7 +1568,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1677,7 +1677,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1775,7 +1775,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -2020,7 +2020,7 @@ PHP_METHOD(Memcached, getServerByKey) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (server_key->len == 0 || strchr(server_key->val, ' ')) { + if (server_key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(server_key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } diff --git a/tests/keys.phpt b/tests/keys.phpt index 0ed90896..89632f5d 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -13,7 +13,7 @@ $binary = memc_get_instance (array ( $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -24,7 +24,7 @@ var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); echo "OK" . PHP_EOL; --EXPECT-- -bool(false) +bool(true) bool(true) bool(false) bool(true) From 029784c6870fcd812e58f56c4a17a51e198eb2fc Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:17:19 +0000 Subject: [PATCH 395/694] Show diff --- .travis/travis.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 78ae9ffb..a80ca77a 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -181,7 +181,7 @@ EOF function run_memcached_tests() { export NO_INTERACTION=1 export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` + export TEST_PHP_EXECUTABLE=$(which php) pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" # We have one xfail test, we run it separately @@ -189,14 +189,8 @@ function run_memcached_tests() { rm ./tests/expire.phpt # Run normal tests - php run-tests.php -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt retval=$? - for i in `ls tests/*.out 2>/dev/null`; do - echo "-- START ${i}"; - cat $i; - echo ""; - echo "-- END"; - done popd return $retval; From 00d99deb90d8bcd667f7ea2d008218d8e82ab601 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:42:16 +0000 Subject: [PATCH 396/694] Should fix sasl --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a80ca77a..b2ef1fb7 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -137,7 +137,7 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -p 11212 + MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From 238a403ea87036c18982dfcb1d7d3fea26cb367b Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:45:59 +0000 Subject: [PATCH 397/694] Should fix sasl --- .travis/travis.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index b2ef1fb7..d841a4b3 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -88,7 +88,7 @@ function install_msgpack() { } function install_memcached() { - local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" if test -d "$prefix" then @@ -100,7 +100,7 @@ function install_memcached() { tar xfz memcached-${MEMCACHED_VERSION}.tar.gz pushd memcached-${MEMCACHED_VERSION} - ./configure --enable-sasl --prefix="${prefix}" + ./configure --enable-sasl --enable-sasl-pwdb --prefix="${prefix}" make make install popd @@ -137,7 +137,8 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -p 11212 + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From 5a1d092b7fafbb80bc3e6eb47ead104b10ae1ad6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:49:03 +0000 Subject: [PATCH 398/694] Run right memcached --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index d841a4b3..3d2af8ae 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -131,7 +131,7 @@ EOF } function run_memcached() { - local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 From 37f261879742d52a329e9c172ef2cce6f1a34684 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:00:55 +0000 Subject: [PATCH 399/694] Memcached log --- .travis/travis.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 3d2af8ae..96f6bc31 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -137,8 +137,11 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support + echo "SASL users:" + sasldblistusers2 -f "${SASL_CONF_PATH}/sasldb2" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" - "${prefix}/bin/memcached" -S -d -p 11212 + "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 } function build_php_memcached() { @@ -194,6 +197,7 @@ function run_memcached_tests() { retval=$? popd + cat /tmp/memcached-sasl.log return $retval; } From 7e5f0922420ce5d4d472dcafd3e9569eec92fb8b Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:26:00 +0000 Subject: [PATCH 400/694] SASL is tricky --- .travis/travis.sh | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 96f6bc31..3924efd6 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -106,41 +106,32 @@ function install_memcached() { popd } -function install_sasl_config() { +function run_memcached() { + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - export SASL_CONF_PATH="${HOME}/cache/sasl2" + export SASL_CONF_PATH="/tmp/sasl2" - if test -f "${SASL_CONF_PATH}/memcached.conf" + if test -d "${SASL_CONF_PATH}" then - echo "Using cached SASL configuration: ${SASL_CONF_PATH}/memcached.conf" - return + rm -rf "${SASL_CONF_PATH}" fi - # Create config path mkdir "${SASL_CONF_PATH}" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" # Create configuration cat< "${SASL_CONF_PATH}/memcached.conf" mech_list: PLAIN plainlog_level: 5 -sasldb_path: ${SASL_CONF_PATH}/sasldb2 +sasldb_path: ${MEMCACHED_SASL_PWDB} EOF - # Create password - echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" -} - -function run_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" + echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - echo "SASL users:" - sasldblistusers2 -f "${SASL_CONF_PATH}/sasldb2" - - export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 } @@ -253,7 +244,6 @@ case $ACTION in # install_msgpack install_memcached - install_sasl_config run_memcached ;; From 1aab3f70f7c6a8cac480e1244b7eafbb75bc9c40 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:28:33 +0000 Subject: [PATCH 401/694] Remove debug logging --- .travis/travis.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 3924efd6..a6240d83 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -132,7 +132,7 @@ EOF "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 + "${prefix}/bin/memcached" -S -d -v -p 11212 } function build_php_memcached() { @@ -187,8 +187,6 @@ function run_memcached_tests() { php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt retval=$? popd - - cat /tmp/memcached-sasl.log return $retval; } From e6946ee636b6db6dae60b0c9067a9def42b4cbbc Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:30:26 +0000 Subject: [PATCH 402/694] Remove debug logging --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a6240d83..131e38bf 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -132,7 +132,7 @@ EOF "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -v -p 11212 + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From fd8fead6bd02f5aa28ac622b45dd2642763507af Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:41:18 +0000 Subject: [PATCH 403/694] Remove really old libmemcached versions. If anyone is using this old version they should be worried --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30e5c3e1..fb0d0fbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,9 @@ env: - LIBMEMCACHED_VERSION=1.0.7 - LIBMEMCACHED_VERSION=1.0.6 - LIBMEMCACHED_VERSION=1.0.2 - - LIBMEMCACHED_VERSION=0.53 - - LIBMEMCACHED_VERSION=0.49 - - LIBMEMCACHED_VERSION=0.44 + #- LIBMEMCACHED_VERSION=0.53 + #- LIBMEMCACHED_VERSION=0.49 + #- LIBMEMCACHED_VERSION=0.44 addons: apt: packages: From 582f4a030d15832475ea5baa70d2e92e298ec3c1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 00:02:11 +0000 Subject: [PATCH 404/694] Fix tests --- tests/session_basic2.phpt | 2 +- tests/session_basic3.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt index f99063a8..6ec4060e 100644 --- a/tests/session_basic2.phpt +++ b/tests/session_basic2.phpt @@ -18,7 +18,7 @@ ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); error_reporting(0); -session_start(['lazy_write'=>TRUE); +session_start(['lazy_write'=>TRUE]); $_SESSION['foo'] = 1; session_write_close(); diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index fc4e7ae7..b8e4f5f8 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -18,7 +18,7 @@ ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); error_reporting(0); -session_start(['read_only'=>TRUE); +session_start(['read_only'=>TRUE]); $_SESSION['foo'] = 1; session_write_close(); From 7ac4e83c6cf4aa8e16f8088534096293ee8e254d Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 00:32:09 +0000 Subject: [PATCH 405/694] Add to package.xml --- package.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.xml b/package.xml index 0ebc86f9..e42b8037 100644 --- a/package.xml +++ b/package.xml @@ -100,6 +100,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + From 7cb0c48c8da8fbcfdd04350338d6ebef15ddcd14 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 13:42:17 +0000 Subject: [PATCH 406/694] Fixes to session --- config.m4 | 22 +++++++++++++++++++++ php_memcached.c | 19 +++++++++++++++++++ php_memcached_private.h | 2 ++ php_memcached_session.c | 42 +++++++++++++++++++---------------------- 4 files changed, 62 insertions(+), 23 deletions(-) diff --git a/config.m4 b/config.m4 index 48efd176..e6a2dfd0 100644 --- a/config.m4 +++ b/config.m4 @@ -296,6 +296,28 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi + ORIG_CFLAGS="$CFLAGS" + ORIG_LIBS="$LIBS" + + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" + LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" + + AC_CACHE_CHECK([whether memcached_exist is defined], ac_cv_have_memcached_exist, [ + AC_TRY_LINK( + [ #include ], + [ memcached_exist (NULL, NULL, 0); ], + [ ac_cv_have_memcached_exist="yes" ], + [ ac_cv_have_memcached_exist="no" ] + ) + ]) + + CFLAGS="$ORIG_CFLAGS" + LIBS="$ORIG_LIBS" + + if test "$ac_cv_have_memcached_exist" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) + fi + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then diff --git a/php_memcached.c b/php_memcached.c index f5a9ea22..6f4ae3b1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -332,6 +332,25 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); ****************************************/ +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +{ +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); +#else + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); + } + return rc; +#endif +} + + char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; diff --git a/php_memcached_private.h b/php_memcached_private.h index 2929818e..ffca963d 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -192,6 +192,8 @@ int php_memc_sess_list_entry(void); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + #endif /* PHP_MEMCACHED_PRIVATE_H */ /* diff --git a/php_memcached_session.c b/php_memcached_session.c index 5f66e411..85baad03 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -277,7 +277,7 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - + if (!memc_sess) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; @@ -336,8 +336,9 @@ PS_READ_FUNC(memcached) *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; - } else if (status = MEMCACHED_NOTFOUND) { + } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); + return SUCCESS; } else { return FAILURE; } @@ -351,7 +352,7 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; - + if (!memc_sess) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; @@ -409,39 +410,34 @@ PS_GC_FUNC(memcached) PS_CREATE_SID_FUNC(memcached) { zend_string *sid; - int maxfail = 3; + int retries = 3; memcached_sess *memc_sess = PS_GET_MOD_DATA(); + time_t expiration = PS(gc_maxlifetime); - do { + if (!memc_sess) { + return NULL; + } + + while (retries-- > 0) { sid = php_session_create_id((void**)&memc_sess); - if (!sid) { - if (--maxfail < 0) { - return NULL; - } else { - continue; + + if (sid) { + if (memcached_add(memc_sess->memc_sess, sid->val, sid->len, "0", 0, expiration, 0) == MEMCACHED_SUCCESS) { + return sid; } - } - /* Check collision */ - /* FIXME: mod_data(memc_sess) should not be NULL (User handler could be NULL) */ - if (memc_sess && memcached_exist(memc_sess->memc_sess, sid->val, sid->len) == MEMCACHED_SUCCESS) { - if (sid) { + else { zend_string_release(sid); - sid = NULL; - } - if (--maxfail < 0) { - return NULL; } } - } while(!sid); - - return sid; + } + return NULL; } PS_VALIDATE_SID_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - if (memcached_exist(memc_sess->memc_sess, key->val, key->len) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc_sess->memc_sess, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From dc5b22a8dace7373c1ef9d2946e89a660ed35b20 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 29 Jan 2016 14:58:50 +0000 Subject: [PATCH 407/694] Cleaning up driver for php7. WIP --- php_memcached.c | 1141 ++++++++++++++++++-------------------- php_memcached_private.h | 83 +-- php_memcached_session.c | 628 +++++++++++---------- php_memcached_session.h | 3 + tests/cachecallback.phpt | 4 + tests/cas.phpt | 43 +- tests/cas_multi.phpt | 31 +- tests/multi_order.phpt | 3 +- tests/no-not-found.phpt | 3 +- tests/rescode.phpt | 1 + tests/set_large.phpt | 3 +- tests/user-flags.phpt | 28 +- 12 files changed, 967 insertions(+), 1004 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6f4ae3b1..23e9bde3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -49,6 +49,12 @@ # include "ext/msgpack/php_msgpack.h" #endif +#ifdef ZTS +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc_ini.v) +#else +#define MEMC_G(v) (php_memcached_globals.memc_ini.v) +#endif + /**************************************** Custom options @@ -106,7 +112,7 @@ "get" operation flags ****************************************/ #define MEMC_GET_PRESERVE_ORDER (1<<0) - +#define MEMC_GET_EXTENDED (2<<0) /**************************************** Helper macros @@ -136,6 +142,47 @@ #define RETURN_FROM_GET RETURN_FALSE +typedef memcached_return (*memc_store_fn)( + memcached_st *, + const char *key, size_t key_len, + const char *payload, size_t payload_len, + time_t expiration, uint32_t flags); + +typedef memcached_return (*memc_store_by_key_fn)( + memcached_st *, + const char *server_key, size_t server_key_len, + const char *key, size_t key_len, + const char *payload, size_t payload_len, + time_t expiration, uint32_t flags); + +static memc_store_fn php_memc_store_funcs[] = { + &memcached_set, + &memcached_add, + &memcached_replace, + &memcached_prepend, + &memcached_append +}; + +void s_call_store_func(int op, memcached_st *memc, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) +{ + (*php_memc_store_funcs[op])(memc, key, key_len,payload, payload_len, expiration, flags); +} + + +static memc_store_by_key_fn php_memc_store_by_keys_funcs[] = { + &memcached_set_by_key, + &memcached_add_by_key, + &memcached_replace_by_key, + &memcached_prepend_by_key, + &memcached_append_by_key +}; + +void s_call_store_by_key_func(int op, memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) +{ + (*php_memc_store_by_keys_funcs[op])(memc, server_key, server_key_len, key, key_len,payload, payload_len, expiration, flags); +} + + /**************************************** Structures and definitions ****************************************/ @@ -157,7 +204,6 @@ typedef struct { zend_long set_udf_flags; } *obj; - zval last_udf_flags; zend_bool is_persistent; zend_bool is_pristine; int rescode; @@ -220,14 +266,6 @@ struct callbackContext static zend_class_entry *spl_ce_RuntimeException = NULL; #endif -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) -const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; -#undef ZEND_BEGIN_ARG_INFO_EX -#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ - static zend_arg_info name[] = { \ - { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, -#endif - ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #ifdef COMPILE_DL_MEMCACHED @@ -275,44 +313,54 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY("memcached.##key", default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + +#define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY("memcached.session.##key", default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + + /* {{{ INI entries */ PHP_INI_BEGIN() + #ifdef HAVE_MEMCACHED_SESSION - STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_consistent_hash", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hash_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_max_wait", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_max_wait, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_expire", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_expire, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) - - STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) -#if HAVE_MEMCACHED_SASL - STD_PHP_INI_ENTRY("memcached.sess_sasl_username", "", PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_sasl_password", "", PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) + MEMC_SESSION_INI_ENTRY("lock_enabled", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) + MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) + MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) + MEMC_SESSION_INI_ENTRY("lock_expiration", "0", OnUpdateLongGEZero, lock_expiration) + MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) + MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) + MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) + MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) + MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) + MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) + MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) + MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateString, prefix) + MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) #endif -#endif - STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.compression_threshold", "2000", PHP_INI_ALL, OnUpdateLong, compression_threshold, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.serializer", SERIALIZER_DEFAULT_NAME, PHP_INI_ALL, OnUpdateSerializer, serializer_name, zend_php_memcached_globals, php_memcached_globals) -#if HAVE_MEMCACHED_SASL - STD_PHP_INI_ENTRY("memcached.use_sasl", "0", PHP_INI_SYSTEM, OnUpdateBool, use_sasl, zend_php_memcached_globals, php_memcached_globals) -#endif - STD_PHP_INI_ENTRY("memcached.store_retry_count", "2", PHP_INI_ALL, OnUpdateLong, store_retry_count, zend_php_memcached_globals, php_memcached_globals) + MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) + MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) + MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) + MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) + MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) + MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + PHP_INI_END() /* }}} */ +#undef MEMC_INI_ENTRY +#undef MEMC_SESSION_INI_ENTRY + /**************************************** Forward declarations ****************************************/ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); -static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer); + static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -327,6 +375,14 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); + +static + zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); + +static + zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); + + /**************************************** Method implementations ****************************************/ @@ -391,7 +447,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc efree (buf); ret = 0; } - + if (Z_TYPE(retval) != IS_UNDEF) zval_ptr_dtor(&retval); @@ -400,7 +456,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc return ret; } -static int le_memc, le_memc_sess; +static int le_memc; static int php_memc_list_entry(void) { @@ -443,7 +499,6 @@ static PHP_METHOD(Memcached, __construct) } i_obj->is_persistent = is_persistent; - array_init(&i_obj->last_udf_flags); if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); @@ -533,217 +588,211 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::getLastUserFlags() - Returns the user flags from last fetch operation */ -PHP_METHOD(Memcached, getLastUserFlags) +static +void s_uint64_to_zval (zval *target, uint64_t value) { - MEMC_METHOD_INIT_VARS; + if (value >= LONG_MAX) { + char *buffer; + spprintf (&buffer, 0, "%" PRIu64, value); + ZVAL_STRING (target, buffer); + efree(buffer); + } + else { + ZVAL_LONG (target, (zend_long) value); + } +} - if (zend_parse_parameters_none() == FAILURE) { +typedef struct { + + size_t num_valid_keys; + + const char **mkeys; + size_t *mkeys_len; + + zend_string **strings; + +} php_memcached_keys; + +static +void s_hash_to_keys(php_memcached_keys *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) +{ + size_t idx = 0, alloc_count; + zval *zv; + + keys_out->num_valid_keys = 0; + + alloc_count = zend_hash_num_elements(hash_in); + if (!alloc_count) { return; } + keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); + keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); + keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); - MEMC_METHOD_FETCH_OBJECT; - RETVAL_ZVAL(&i_obj->last_udf_flags, 1, 0); -} -/* }}} */ + ZEND_HASH_FOREACH_VAL(hash_in, zv) { + zend_string *key = zval_get_string(zv); + if (preserve_order && return_value) { + add_assoc_null_ex(return_value, key->val, key->len); + } -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) - Returns a value for the given key or false */ -PHP_METHOD(Memcached, get) -{ - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = key->val; + keys_out->mkeys_len[idx] = key->len; + + keys_out->strings[idx] = key; + idx++; + } + else { + zend_string_release (key); + } + + } ZEND_HASH_FOREACH_END(); + + if (!idx) { + efree (keys_out->mkeys); + efree (keys_out->mkeys_len); + efree (keys_out->strings); + } + keys_out->num_valid_keys = idx; } -/* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) - Returns a value for key from the server identified by the server key or false */ -PHP_METHOD(Memcached, getByKey) +static +void s_clear_keys(php_memcached_keys *keys) { - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + size_t i; + for (i = 0; i < keys->num_valid_keys; i++) { + zend_string_release (keys->strings[i]); + } + efree(keys->strings); + efree(keys->mkeys); + efree(keys->mkeys_len); } -/* }}} */ -/* {{{ -- php_memc_get_impl */ -static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, zend_string *server_key, zend_long get_flags, zval *return_value) { - zend_string *key; - zend_string *server_key = NULL; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - const char* keys[1] = { NULL }; - size_t key_lens[1] = { 0 }; - zval *cas_token = NULL; + php_memcached_keys keys = { 0 }; + zval values; + + memcached_return rc, status = MEMCACHED_SUCCESS; + + size_t num_keys; uint64_t orig_cas_flag; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!z", &server_key, &key, &fci, &fcc, &cas_token) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!z", &key, &fci, &fcc, &cas_token) == FAILURE) { - return; - } - } + zend_bool extended = (get_flags & MEMC_GET_EXTENDED); + zend_bool preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); - MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + array_init(&values); + s_hash_to_keys(&keys, hash_keys, preserve_order, &values); - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FROM_GET; + if (!keys.num_valid_keys) { + zval_ptr_dtor(&values); + return MEMCACHED_NO_KEY_PROVIDED; } - keys[0] = key->val; - key_lens[0] = key->len; + orig_cas_flag = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + if (extended && !orig_cas_flag) { + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); + if (server_key) { + status = memcached_mget_by_key(memc, server_key->val, server_key->len, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); } else { - status = memcached_mget(m_obj->memc, keys, key_lens, 1); - } - if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + status = memcached_mget(memc, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); } - if (php_memc_handle_error(i_obj, status) < 0) { - RETURN_FROM_GET; + s_clear_keys(&keys); + + if (extended && !orig_cas_flag) { + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 0); } - status = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &result); + memcached_result_create(memc, &result); + while ((memcached_fetch_result(memc, &result, &rc)) != NULL) { - if (memcached_fetch_result(m_obj->memc, &result, &status) == NULL) { - /* This is for historical reasons */ - if (status == MEMCACHED_END) - status = MEMCACHED_NOTFOUND; + const char *res_key = NULL; + size_t res_key_len = 0; + zval value; - /* - * If the result wasn't found, and we have the read-through callback, invoke - * it to get the value. The CAS token will be 0, because we cannot generate it - * ourselves. - */ - if (cas_token) { - ZVAL_DEREF(cas_token); - zval_ptr_dtor(cas_token); - ZVAL_DOUBLE(cas_token, 0.0); + /* For some reason instead of success it's end */ + if (rc == MEMCACHED_END) { + rc = MEMCACHED_SUCCESS; } - if (status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); + if (rc != MEMCACHED_SUCCESS) { + status = rc; + continue; } - if (php_memc_handle_error(i_obj, status) < 0) { - memcached_result_free(&result); - RETURN_FROM_GET; - } + ZVAL_UNDEF(&value); + if (!s_memcached_result_to_zval(&result, &value)) { + if (EG(exception)) { + status = MEMC_RES_PAYLOAD_FAILURE; - /* if we have a callback, all processing is done */ - if (fci.size != 0) { - memcached_result_free(&result); - return; + memcached_result_free(&result); + memcached_quit(memc); + zval_ptr_dtor (&values); + break; + } + status = MEMCACHED_SOME_ERRORS; + continue; } - } - /* Fetch all remaining results */ - memcached_result_st dummy_result; - memcached_return dummy_status = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &dummy_result); - while (memcached_fetch_result(m_obj->memc, &dummy_result, &dummy_status) != NULL) {} - memcached_result_free(&dummy_result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - if (cas_token) { - cas = memcached_result_cas(&result); - } + if (extended) { + uint32_t flags; + uint64_t cas; + zval cas_token, node; - if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer) < 0) { - memcached_result_free(&result); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FROM_GET; - } + cas = memcached_result_cas(&result); + flags = memcached_result_flags(&result); - if (cas_token) { - ZVAL_DEREF(cas_token); - zval_ptr_dtor(cas_token); - ZVAL_DOUBLE(cas_token, (double)cas); - } + s_uint64_to_zval (&cas_token, cas); - /* Parse user flags */ - add_assoc_long_ex(&i_obj->last_udf_flags, key->val, key->len, MEMC_VAL_GET_USER_FLAGS(flags)); + array_init (&node); + add_assoc_zval (&node, "value", &value); + add_assoc_zval (&node, "cas", &cas_token); + add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + + add_assoc_zval_ex(&values, res_key, res_key_len, &node); + } + else { + add_assoc_zval_ex(&values, res_key, res_key_len, &value); + } + } memcached_result_free(&result); -} -/* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) - Returns values for the given keys or false */ -PHP_METHOD(Memcached, getMulti) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + if (Z_TYPE(values) != IS_UNDEF) { + ZVAL_ZVAL(return_value, &values, 0, 0); + } + return status; } -/* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) - Returns values for the given keys from the server identified by the server key or false */ -PHP_METHOD(Memcached, getMultiByKey) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ -/* {{{ -- php_memc_getMulti_impl */ -static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *keys = NULL; + zend_long get_flags = 0; + zend_string *key; zend_string *server_key = NULL; - size_t num_keys = 0; - zval *entry = NULL; - const char *payload = NULL; - size_t payload_len = 0; - const char **mkeys = NULL; - size_t *mkeys_len = NULL; - const char *tmp_key = NULL; - size_t res_key_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval *cas_tokens = NULL; - uint64_t orig_cas_flag = 0; - zval value; - long get_flags = 0; - int i = 0; - zend_bool preserve_order; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + HashTable keys; + zval values, tmp; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zl", &server_key, - &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { return; } } @@ -751,157 +800,110 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - /* clean flags */ - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + zend_hash_init (&keys, 1, 0, NULL, 0); + ZVAL_STR(&tmp, key); + zend_hash_add(&keys, key, &tmp); - preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); - num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); - mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); - mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - array_init(return_value); + ZVAL_UNDEF(&values); + status = s_memcached_get_multi(m_obj->memc, &keys, server_key, get_flags, &values); + zend_hash_destroy (&keys); - /* - * Create the array of keys for libmemcached. If none of the keys were valid - * (strings), set bad key result code and return. - */ - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } - - if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { - mkeys[i] = Z_STRVAL_P(entry); - mkeys_len[i] = Z_STRLEN_P(entry); - - if (preserve_order) { - add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i]); - } - i++; - } - } ZEND_HASH_FOREACH_END(); - - if (i == 0) { - i_obj->rescode = MEMCACHED_NOTFOUND; - efree(mkeys); - efree(mkeys_len); - return; + if (EG(exception)) { + zval_ptr_dtor(&values); + RETURN_FROM_GET; } - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (cas_tokens && Z_ISREF_P(cas_tokens)) { - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + if (status == MEMCACHED_SUCCESS) { + zval *zv = zend_hash_find (Z_ARRVAL(values), key); + if (zv) { + RETVAL_ZVAL(zv, 1, 0); + zval_ptr_dtor(&values); + return; + } + else { + status = MEMCACHED_NOTFOUND; } } - if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - } else { - status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + if (Z_TYPE(values) != IS_UNDEF) { + zval_ptr_dtor(&values); } - /* Handle error, but ignore, there might still be some result */ - php_memc_handle_error(i_obj, status); - /* - * Restore the CAS support flag, but only if we had to turn it on. - */ - if (cas_tokens && Z_ISREF_P(cas_tokens) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + if (status == MEMCACHED_NOTFOUND && fci.size > 0) { + // try to invoke cache cb + status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); } - efree(mkeys); - efree(mkeys_len); - - /* - * Iterate through the result set and create the result array. The CAS tokens are - * returned as doubles, because we cannot store potential 64-bit values in longs. - */ - if (cas_tokens) { - if (Z_ISREF_P(cas_tokens)) { - /* cas_tokens was passed by reference, we'll create an array for it. */ - ZVAL_DEREF(cas_tokens); - SEPARATE_ZVAL(cas_tokens); - zval_dtor(cas_tokens); - array_init(cas_tokens); - } else { - /* Not passed by reference, we allow this (eg.: if you specify null - to not enable cas but you want to use the udf_flags parameter). - We destruct it and set it to null for the peace of mind. */ - cas_tokens = NULL; - } + if (php_memc_handle_error(i_obj, status) < 0) { + RETURN_FROM_GET; } +} - /* - * Iterate through the result set and create the result array. The flags are - * returned as longs. - */ - - memcached_result_create(m_obj->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - char res_key [MEMCACHED_MAX_KEY]; - - if (status != MEMCACHED_SUCCESS) { - status = MEMCACHED_SOME_ERRORS; - php_memc_handle_error(i_obj, status); - continue; - } - - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - tmp_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - - /* - * This may be a bug in libmemcached, the key is not null terminated - * whe using the binary protocol. - */ - memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); - res_key [res_key_len] = '\0'; +/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) + Returns a value for the given key or false */ +PHP_METHOD(Memcached, get) +{ + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { - zval_ptr_dtor(&value); - if (EG(exception)) { - status = MEMC_RES_PAYLOAD_FAILURE; - php_memc_handle_error(i_obj, status); - memcached_quit(m_obj->memc); +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) + Returns a value for key from the server identified by the server key or false */ +PHP_METHOD(Memcached, getByKey) +{ + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ - break; - } - status = MEMCACHED_SOME_ERRORS; - i_obj->rescode = MEMCACHED_SOME_ERRORS; +/* {{{ -- php_memc_getMulti_impl */ +static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +{ + zval *keys = NULL; + zend_string *server_key = NULL; + zend_bool extended_results = 0; + memcached_return rc; + zend_long flags = 0; + MEMC_METHOD_INIT_VARS; - continue; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, + &keys, &flags) == FAILURE) { + return; } - - add_assoc_zval_ex(return_value, res_key, res_key_len, &value); - if (cas_tokens) { - cas = memcached_result_cas(&result); - add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &keys, &flags) == FAILURE) { + return; } - add_assoc_long_ex(&i_obj->last_udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } - memcached_result_free(&result); + MEMC_METHOD_FETCH_OBJECT; + + rc = s_memcached_get_multi(m_obj->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); + php_memc_handle_error(i_obj, rc); if (EG(exception)) { - /* XXX: cas_tokens should only be set on success, currently we're destructive */ - if (cas_tokens) { - ZVAL_DEREF(cas_tokens); - SEPARATE_ZVAL(cas_tokens); - zval_dtor(cas_tokens); - ZVAL_NULL(cas_tokens); - } - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); zval_dtor(return_value); RETURN_FALSE; } } /* }}} */ +/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) + Returns values for the given keys or false */ +PHP_METHOD(Memcached, getMulti) +{ + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) + Returns values for the given keys from the server identified by the server key or false */ +PHP_METHOD(Memcached, getMultiByKey) +{ + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + /* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) Sends a request for the given keys and returns immediately */ PHP_METHOD(Memcached, getDelayed) @@ -1075,9 +1077,8 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { + if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1130,9 +1131,8 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { + if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - zval_ptr_dtor(&value); zval_dtor(return_value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1242,11 +1242,10 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *entries; zend_string *server_key = NULL; time_t expiration = 0; - zval *entry; + zval *value; zend_string *skey, *str_key = NULL; ulong num_key; - char *payload; - size_t payload_len; + zend_string *payload; uint32_t flags = 0; uint32_t retry = 0; memcached_return status; @@ -1268,7 +1267,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { if (skey) { str_key = skey; } else if (num_key || num_key == 0) { @@ -1291,7 +1290,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } - payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; if (!skey) { @@ -1302,9 +1301,9 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } if (php_memc_handle_error(i_obj, status) < 0) { @@ -1312,13 +1311,13 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (!skey) { zend_string_release(str_key); } - efree(payload); + zend_string_release(payload); RETURN_FALSE; } if (!skey) { zend_string_release(str_key); } - efree(payload); + zend_string_release(payload); } ZEND_HASH_FOREACH_END(); RETURN_TRUE; @@ -1395,11 +1394,10 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zend_string *key; zend_string *server_key = NULL; zend_string *s_value; - zval s_zvalue; + zval s_zvalue; zval *value; - long expiration = 0; - char *payload = NULL; - size_t payload_len; + zend_long expiration = 0; + zend_string *payload = NULL; uint32_t flags = 0; uint32_t retry = 0; memcached_return status; @@ -1474,8 +1472,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif - } else { - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + } + else { + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1485,10 +1484,10 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool switch (op) { case MEMC_OP_SET: if (!server_key) { - status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH @@ -1503,37 +1502,37 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool #endif case MEMC_OP_ADD: if (!server_key) { - status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_add(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_REPLACE: if (!server_key) { - status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_replace(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_APPEND: if (!server_key) { - status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_append(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_PREPEND: if (!server_key) { - status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_prepend(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; @@ -1552,7 +1551,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } if (payload) { - efree(payload); + zend_string_release(payload); } } /* }}} */ @@ -1566,8 +1565,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; time_t expiration = 0; - char *payload; - size_t payload_len; + zend_string *payload; uint32_t flags = 0; memcached_return status; MEMC_METHOD_INIT_VARS; @@ -1602,22 +1600,22 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags > 0) { + if (m_obj->set_udf_flags >= 0) { MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload, payload_len, expiration, flags, cas); + status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags, cas); + status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } - efree(payload); + zend_string_release(payload); if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2710,7 +2708,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) return; } - if (!MEMC_G(use_sasl)) { + if (!MEMC_G(sasl_enabled)) { php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); RETURN_FALSE; } @@ -2839,8 +2837,6 @@ static void php_memc_free_storage(zend_object *obj) if (i_obj->obj && !i_obj->is_persistent) { php_memc_destroy(i_obj->obj, 0); } - - zval_ptr_dtor(&i_obj->last_udf_flags); zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; } @@ -2893,15 +2889,6 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) } } -ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) -{ - if (res->ptr) { - memcached_sess *memc_sess = (memcached_sess *)res->ptr; - memcached_free(memc_sess->memc_sess); - pefree(res->ptr, 1); - res->ptr = NULL; - } -} /* }}} */ /* {{{ internal API functions */ @@ -3037,61 +3024,74 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) } static -char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags) +zend_bool s_compress_value (enum memcached_compression_type compression_type, zend_string **payload_in, uint32_t *flags) { /* status */ zend_bool compress_status = 0; + zend_string *payload = *payload_in; /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) *payload_len * 1.05) + 1.0); - char *buffer = emalloc(sizeof(uint32_t) + buffer_size); + size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + char *buffer = emalloc(buffer_size); /* Store compressed size here */ size_t compressed_size = 0; - uint32_t plen = *payload_len; - - /* Copy the uin32_t at the beginning */ - memcpy(buffer, &plen, sizeof(uint32_t)); - buffer += sizeof(uint32_t); + uint32_t original_size = payload->len; switch (compression_type) { case COMPRESSION_TYPE_FASTLZ: - compress_status = ((compressed_size = fastlz_compress(payload, *payload_len, buffer)) > 0); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + { + compressed_size = fastlz_compress(payload->val, payload->len, buffer); + + if (compressed_size > 0) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + } + } break; case COMPRESSION_TYPE_ZLIB: - /* ZLIB returns the compressed size in this buffer */ + { compressed_size = buffer_size; + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); - compress_status = (compress((Bytef *)buffer, &compressed_size, (Bytef *)payload, *payload_len) == Z_OK); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + if (status == Z_OK) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + } + } break; default: compress_status = 0; break; } - buffer -= sizeof(uint32_t); - *payload_len = compressed_size + sizeof(uint32_t); if (!compress_status) { php_error_docref(NULL, E_WARNING, "could not compress value"); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - *payload_len = 0; - return NULL; + return 0; } - else if (*payload_len > (compressed_size * MEMC_G(compression_factor))) { + /* This means the value was too small to be compressed, still a success */ + if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + efree(buffer); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - *payload_len = 0; - return NULL; + return 1; } - return buffer; + + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + + /* Copy the uin32_t at the beginning */ + memcpy(payload->val, &original_size, sizeof(uint32_t)); + memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); + + zend_string_forget_hash_val(payload); + *payload_in = payload; + return 1; } static @@ -3166,149 +3166,142 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, } static -char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) +zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) { - const char *pl; - size_t pl_len = 0; - - char *payload = NULL; - smart_str buf = {0}; - char tmp[40] = {0}; + zend_string *payload; switch (Z_TYPE_P(value)) { case IS_STRING: - pl = Z_STRVAL_P(value); - pl_len = Z_STRLEN_P(value); + payload = zval_get_string(value); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); + MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); break; case IS_LONG: - pl_len = sprintf(tmp, "%ld", Z_LVAL_P(value)); - pl = tmp; + { + smart_str buffer = {0}; + smart_str_append_long (&buffer, Z_LVAL_P(value)); + smart_str_0(&buffer); + payload = buffer.s; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + } break; case IS_DOUBLE: - php_memcached_g_fmt(tmp, Z_DVAL_P(value)); - pl = tmp; - pl_len = strlen(tmp); + { + char buffer[40]; + php_memcached_g_fmt(buffer, Z_DVAL_P(value)); + payload = zend_string_init (buffer, strlen (buffer), 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + } break; case IS_TRUE: - pl_len = 1; - tmp[0] = '1'; - tmp[1] = '\0'; - pl = tmp; + payload = zend_string_init ("1", 1, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; case IS_FALSE: - pl_len = 0; - tmp[0] = '\0'; - pl = tmp; + payload = zend_string_alloc (0, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; default: - if (!s_serialize_value (serializer, value, &buf, flags)) { - smart_str_free(&buf); + { + smart_str buffer = {0}; + + if (!s_serialize_value (serializer, value, &buffer, flags)) { + smart_str_free(&buffer); return NULL; } - pl = buf.s->val; - pl_len = buf.s->len; + payload = buffer.s; + MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); + } break; } + zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ - if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && pl_len < MEMC_G(compression_threshold)) { + if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); } /* If we have compression flag, compress the value */ if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ - *payload_len = pl_len; - payload = s_compress_value (compression_type, pl, payload_len, flags); - } - - /* If compression failed or value is below threshold we just use plain value */ - if (!payload || !MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { - *payload_len = (uint32_t) pl_len; - payload = estrndup(pl, pl_len); + if (!s_compress_value (compression_type, &payload, flags)) { + zend_string_release(payload); + return NULL; + } } - if (buf.s) { - smart_str_free(&buf); - } return payload; } static -char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags) +zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32_t flags) { - char *buffer = NULL; - uint32_t len; + zend_string *buffer; + + uint32_t stored_length; unsigned long length; zend_bool decompress_status = 0; + zend_bool is_fastlz = 0, is_zlib = 0; - /* Stored with newer memcached extension? */ - if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ) || MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { - /* This is copied from Ilia's patch */ - memcpy(&len, payload, sizeof(uint32_t)); - buffer = emalloc(len + 1); - *payload_len -= sizeof(uint32_t); - payload += sizeof(uint32_t); - length = len; - - if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ)) { - decompress_status = ((length = fastlz_decompress(payload, *payload_len, buffer, len)) > 0); - } else if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { - decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, *payload_len) == Z_OK); - } + if (payload_len < sizeof (uint32_t)) { + return NULL; } - /* Fall back to 'old style decompression' */ - if (!decompress_status) { - unsigned int factor = 1, maxfactor = 16; - int status; - - do { - length = (unsigned long)*payload_len * (1 << factor++); - buffer = erealloc(buffer, length + 1); - memset(buffer, 0, length + 1); - status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, *payload_len); - } while ((status==Z_BUF_ERROR) && (factor < maxfactor)); - - if (status == Z_OK) { - decompress_status = 1; - } + is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ); + is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); + + if (!is_fastlz && !is_zlib) { + php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised encryption type"); + return NULL; + } + + memcpy(&stored_length, payload, sizeof (uint32_t)); + + payload += sizeof (uint32_t); + payload_len -= sizeof (uint32_t); + + buffer = zend_string_alloc (stored_length, 0); + + if (is_fastlz) { + decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); + } + else if (is_zlib) { + decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); } if (!decompress_status) { php_error_docref(NULL, E_WARNING, "could not decompress value"); - efree(buffer); + zend_string_release (buffer); return NULL; } - buffer [length] = '\0'; - *payload_len = length; + + zend_string_forget_hash_val(buffer); return buffer; } static -zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len) +zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_value) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: { - const char *payload_tmp = payload; php_unserialize_data_t var_hash; + const unsigned char *p, *max; + + p = (const unsigned char *) payload->val; + max = p + payload->len; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { - zval_ptr_dtor(value); - ZVAL_FALSE(value); + if (!php_var_unserialize(return_value, &p, max, &var_hash)) { + zval_ptr_dtor(return_value); + ZVAL_FALSE(return_value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); php_error_docref(NULL, E_WARNING, "could not unserialize value"); return 0; @@ -3319,13 +3312,13 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value)) { - ZVAL_FALSE(value); + if (igbinary_unserialize((uint8_t *) payload->val, payload->len, &value)) { + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; } #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no igbinary support"); return 0; #endif @@ -3333,9 +3326,9 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(value, (char*) payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(return_value, payload->val, payload->len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); return 0; #endif @@ -3343,9 +3336,9 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(value, payload, payload_len); + php_msgpack_unserialize(return_value, payload->val, payload->len); #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); return 0; #endif @@ -3354,117 +3347,85 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ return 1; } -/* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer) +static +zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value) { - /* - A NULL payload is completely valid if length is 0, it is simply empty. - */ - int retval = 0; - zend_bool payload_emalloc = 0; - char *pl = NULL; - - if (payload_in == NULL && payload_len > 0) { - ZVAL_FALSE(value); - php_error_docref(NULL, E_WARNING, - "Could not handle non-existing value of length %zu", payload_len); - return -1; - } else if (payload_in == NULL) { - if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) { - ZVAL_FALSE(value); - } else { - ZVAL_EMPTY_STRING(value); - } + zend_string *data; + const char *payload; + size_t payload_len; + uint32_t flags; + zend_bool retval = 1; + + payload = memcached_result_value(result); + payload_len = memcached_result_length(result); + flags = memcached_result_flags(result); + + if (!payload && payload_len > 0) { + php_error_docref(NULL, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return 0; } if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { - char *datas = s_decompress_value (payload_in, &payload_len, flags); - if (!datas) { - ZVAL_FALSE(value); - return -1; + data = s_decompress_value (payload, payload_len, flags); + if (!data) { + return 0; } - pl = datas; - payload_emalloc = 1; } else { - pl = (char *) payload_in; + data = zend_string_init(payload, payload_len, 0); } switch (MEMC_VAL_GET_TYPE(flags)) { + case MEMC_VAL_IS_STRING: - ZVAL_STRINGL(value, pl, payload_len); + ZVAL_STR_COPY(return_value, data); break; case MEMC_VAL_IS_LONG: - { - long lval; - char conv_buf [128]; - - if (payload_len >= 128) { - php_error_docref(NULL, E_WARNING, "could not read long value, too big"); - retval = -1; - } - else { - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; - - lval = strtol(conv_buf, NULL, 10); - ZVAL_LONG(value, lval); - } - } + ZVAL_LONG(return_value, strtol(data->val, NULL, 10)); break; case MEMC_VAL_IS_DOUBLE: { - char conv_buf [128]; - - if (payload_len >= 128) { - php_error_docref(NULL, E_WARNING, "could not read double value, too big"); - retval = -1; + if (payload_len == 8 && memcmp(data->val, "Infinity", 8) == 0) { + ZVAL_DOUBLE(return_value, php_get_inf()); + } + else if (payload_len == 9 && memcmp(data->val, "-Infinity", 9) == 0) { + ZVAL_DOUBLE(return_value, -php_get_inf()); + } + else if (payload_len == 3 && memcmp(data->val, "NaN", 3) == 0) { + ZVAL_DOUBLE(return_value, php_get_nan()); } else { - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; - - if (payload_len == 8 && memcmp(conv_buf, "Infinity", 8) == 0) { - ZVAL_DOUBLE(value, php_get_inf()); - } else if (payload_len == 9 && memcmp(conv_buf, "-Infinity", 9) == 0) { - ZVAL_DOUBLE(value, -php_get_inf()); - } else if (payload_len == 3 && memcmp(conv_buf, "NaN", 3) == 0) { - ZVAL_DOUBLE(value, php_get_nan()); - } else { - ZVAL_DOUBLE(value, zend_strtod(conv_buf, NULL)); - } + ZVAL_DOUBLE(return_value, zend_strtod(data->val, NULL)); } } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(value, payload_len > 0 && pl[0] == '1'); + ZVAL_BOOL(return_value, payload_len > 0 && data->val[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len)) { - retval = -1; - } + retval = s_unserialize_value (MEMC_VAL_GET_TYPE(flags), data, return_value); break; default: - ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "unknown payload type"); - retval = -1; + retval = 0; break; } + zend_string_release(data); - if (payload_emalloc) { - efree(pl); + if (!retval) { + zval_ptr_dtor(return_value); } return retval; } + PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void) { @@ -3508,8 +3469,7 @@ zend_class_entry *php_memc_get_exception_base(int root) static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - char *payload = NULL; - size_t payload_len = 0; + zend_string *payload = NULL; zval params[4]; zval retval; zval z_key; @@ -3550,16 +3510,19 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i time_t expir; expir = zval_get_long(expiration); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expir, flags); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + } + rc = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expir, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } - efree(payload); + zend_string_release(payload); } } else { status = MEMCACHED_NOTFOUND; @@ -3616,8 +3579,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, i_obj = Z_MEMC_OBJ_P(zmemc_obj); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, i_obj->obj->serializer) < 0) { - zval_ptr_dtor(&value); + if (!s_memcached_result_to_zval(result, &value)) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -3734,27 +3696,23 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(2, cas_token) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(2, cas_token) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(2, cas_tokens) - ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(2, cas_tokens) - ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) @@ -3811,9 +3769,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_getLastUserFlags, 0, 0, 0) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) @@ -4041,8 +3996,6 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) - MEMC_ME(getLastUserFlags, arginfo_getLastUserFlags) - MEMC_ME(cas, arginfo_cas) MEMC_ME(casByKey, arginfo_casByKey) MEMC_ME(add, arginfo_add) @@ -4136,35 +4089,36 @@ static PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->sess_locking_enabled = 1; - php_memcached_globals->sess_binary_enabled = 1; - php_memcached_globals->sess_consistent_hash_enabled = 0; - php_memcached_globals->sess_number_of_replicas = 0; - php_memcached_globals->sess_remove_failed_enabled = 0; - php_memcached_globals->sess_prefix = NULL; - php_memcached_globals->sess_lock_wait = 0; - php_memcached_globals->sess_lock_max_wait = 0; - php_memcached_globals->sess_lock_expire = 0; - php_memcached_globals->sess_locked = 0; - php_memcached_globals->sess_lock_key = NULL; - php_memcached_globals->sess_lock_key_len = 0; - php_memcached_globals->sess_randomize_replica_read = 0; - php_memcached_globals->sess_connect_timeout = 1000; -#if HAVE_MEMCACHED_SASL - php_memcached_globals->sess_sasl_username = NULL; - php_memcached_globals->sess_sasl_password = NULL; - php_memcached_globals->sess_sasl_data = 0; -#endif + + php_memcached_globals->session_ini.lock_enabled = 0; + php_memcached_globals->session_ini.lock_wait_max = 2000; + php_memcached_globals->session_ini.lock_wait_min = 1000; + php_memcached_globals->session_ini.lock_retries = 5; + php_memcached_globals->session_ini.lock_expiration = 30; + php_memcached_globals->session_ini.compression_enabled = 1; + php_memcached_globals->session_ini.binary_protocol_enabled = 1; + php_memcached_globals->session_ini.consistent_hash_enabled = 1; + php_memcached_globals->session_ini.number_of_replicas = 0; + php_memcached_globals->session_ini.server_failure_limit = 1; + php_memcached_globals->session_ini.randomize_replica_read_enabled = 1; + php_memcached_globals->session_ini.remove_failed_servers_enabled = 1; + php_memcached_globals->session_ini.connect_timeout = 1000; + php_memcached_globals->session_ini.prefix = NULL; + php_memcached_globals->session_ini.persistent_enabled = 0; + php_memcached_globals->session_ini.sasl_username = NULL; + php_memcached_globals->session_ini.sasl_password = NULL; + #endif - php_memcached_globals->serializer_name = NULL; - php_memcached_globals->serializer = SERIALIZER_DEFAULT; - php_memcached_globals->compression_type = NULL; - php_memcached_globals->compression_type_real = COMPRESSION_TYPE_FASTLZ; - php_memcached_globals->compression_factor = 1.30; + php_memcached_globals->memc_ini.serializer_name = NULL; + php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; + php_memcached_globals->memc_ini.compression_type = NULL; + php_memcached_globals->memc_ini.compression_threshold = 2000; + php_memcached_globals->memc_ini.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc_ini.compression_factor = 1.30; + php_memcached_globals->memc_ini.store_retry_count = 2; #if HAVE_MEMCACHED_SASL - php_memcached_globals->use_sasl = 0; + php_memcached_globals->memc_ini.sasl_enabled = 0; #endif - php_memcached_globals->store_retry_count = 2; } zend_module_entry memcached_module_entry = { @@ -4374,6 +4328,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * Flags. */ REGISTER_MEMC_CLASS_CONST_LONG(GET_PRESERVE_ORDER, MEMC_GET_PRESERVE_ORDER); + REGISTER_MEMC_CLASS_CONST_LONG(GET_EXTENDED, MEMC_GET_EXTENDED); #ifdef HAVE_MEMCACHED_PROTOCOL /* @@ -4422,11 +4377,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) } /* }}} */ -int php_memc_sess_list_entry(void) -{ - return le_memc_sess; -} - /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(memcached) { @@ -4438,7 +4388,6 @@ PHP_MINIT_FUNCTION(memcached) memcached_object_handlers.free_obj = php_memc_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); memcached_ce = zend_register_internal_class(&ce); @@ -4462,12 +4411,12 @@ PHP_MINIT_FUNCTION(memcached) php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU); #ifdef HAVE_MEMCACHED_SESSION - php_session_register_module(ps_memcached_ptr); + php_memc_session_minit(module_number); #endif REGISTER_INI_ENTRIES(); #if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { + if (MEMC_G(sasl_enabled)) { if (sasl_client_init(NULL) != SASL_OK) { php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); return FAILURE; @@ -4482,7 +4431,7 @@ PHP_MINIT_FUNCTION(memcached) PHP_MSHUTDOWN_FUNCTION(memcached) { #if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { + if (MEMC_G(sasl_enabled)) { sasl_done(); } #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index ffca963d..46565e70 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -129,46 +129,60 @@ typedef struct { #endif ZEND_BEGIN_MODULE_GLOBALS(php_memcached) + #ifdef HAVE_MEMCACHED_SESSION - zend_bool sess_locking_enabled; - long sess_lock_wait; - long sess_lock_max_wait; - long sess_lock_expire; - char* sess_prefix; - zend_bool sess_locked; - char* sess_lock_key; - int sess_lock_key_len; - - int sess_number_of_replicas; - zend_bool sess_randomize_replica_read; - zend_bool sess_remove_failed_enabled; - long sess_connect_timeout; - zend_bool sess_consistent_hash_enabled; - zend_bool sess_binary_enabled; + /* Session related variables */ + struct { + zend_bool lock_enabled; + zend_long lock_wait_max; + zend_long lock_wait_min; + zend_long lock_retries; + zend_long lock_expiration; + + zend_bool compression_enabled; + zend_bool binary_protocol_enabled; + zend_bool consistent_hash_enabled; + + zend_long server_failure_limit; + zend_long number_of_replicas; + zend_bool randomize_replica_read_enabled; + zend_bool remove_failed_servers_enabled; + + zend_long connect_timeout; + + char *prefix; + zend_bool persistent_enabled; + + char *sasl_username; + char *sasl_password; + } session_ini; -#if HAVE_MEMCACHED_SASL - char *sess_sasl_username; - char *sess_sasl_password; - zend_bool sess_sasl_data; -#endif #endif - char *serializer_name; - enum memcached_serializer serializer; - char *compression_type; - int compression_type_real; - int compression_threshold; + struct { + char *serializer_name; + char *compression_type; + zend_long compression_threshold; + double compression_factor; + zend_long store_retry_count; - double compression_factor; #if HAVE_MEMCACHED_SASL - zend_bool use_sasl; + zend_bool sasl_enabled; #endif + + /* Converted values*/ + enum memcached_serializer serializer; + zend_long compression_type_real; + } memc_ini; + + + #ifdef HAVE_MEMCACHED_PROTOCOL struct { php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX]; } server; #endif - long store_retry_count; + ZEND_END_MODULE_GLOBALS(php_memcached) PHP_RINIT_FUNCTION(memcached); @@ -177,19 +191,6 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) -#else -#define MEMC_G(v) (php_memcached_globals.v) -#endif - -typedef struct { - memcached_st *memc_sess; - zend_bool is_persistent; -} memcached_sess; - -int php_memc_sess_list_entry(void); - char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); diff --git a/php_memcached_session.c b/php_memcached_session.c index 85baad03..8c6454a1 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -18,6 +18,8 @@ #include "php_memcached_private.h" #include "php_memcached_session.h" +#include "Zend/zend_smart_str_public.h" + extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 @@ -27,278 +29,350 @@ ps_module ps_mod_memcached = { PS_MOD_UPDATE_TIMESTAMP(memcached) }; -static int php_memc_sess_lock(memcached_st *memc, const char *key) +typedef struct { + zend_bool is_persistent; + zend_bool has_sasl_data; + zend_bool is_locked; + zend_string *lock_key; +} php_memcached_user_data; + +#ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +# define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#ifdef ZTS +#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session_ini.v) +#else +#define MEMC_SESS_INI(v) (php_memcached_globals.session_ini.v) +#endif + +#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) + +static + int le_memc_sess; + +static +int s_memc_sess_list_entry(void) { - char *lock_key = NULL; - int lock_key_len = 0; - unsigned long attempts; - long write_retry_attempts = 0; - long lock_maxwait = MEMC_G(sess_lock_max_wait); - long lock_wait = MEMC_G(sess_lock_wait); - long lock_expire = MEMC_G(sess_lock_expire); - time_t expiration; - memcached_return status; - /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ - if (lock_maxwait <= 0) { - lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); - if (lock_maxwait <= 0) { - lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; - } - } - if (lock_wait == 0) { - lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; + return le_memc_sess; +} + +static +void s_destroy_mod_data(memcached_st *memc) +{ + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + if (user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); } - if (lock_expire <= 0) { - lock_expire = lock_maxwait; + + memcached_free(memc); + pefree(memc, user_data->is_persistent); + pefree(user_data, user_data->is_persistent); +} + +ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) +{ + if (res->ptr) { + s_destroy_mod_data((memcached_st *) res->ptr); + res->ptr = NULL; } - expiration = lock_expire + 1; - attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); +} - /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ - if (MEMC_G(sess_remove_failed_enabled)) { - write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); +int php_memc_session_minit(int module_number) +{ + le_memc_sess = + zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); + + php_session_register_module(ps_memcached_ptr); + return SUCCESS; +} + +static +time_t s_lock_expiration() +{ + zend_long max_execution_time; + + if (MEMC_SESS_INI(lock_expiration) > 0) { + return time(NULL) + MEMC_SESS_INI(lock_expiration); } + else { + zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + if (max_execution_time > 0) { + return time(NULL) + max_execution_time; + } + } + return 0; +} + +static +zend_bool s_lock_session(memcached_st *memc, zend_string *sid) +{ + char *lock_key; + size_t lock_key_len; + time_t expiration; + zend_long wait_time, retries; + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + lock_key_len = spprintf(&lock_key, 0, "lock.%s", sid->val); + expiration = s_lock_expiration(); + + wait_time = MEMC_SESS_INI(lock_wait_min); + retries = MEMC_SESS_INI(lock_retries); - lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); do { - status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); - if (status == MEMCACHED_SUCCESS) { - MEMC_G(sess_locked) = 1; - MEMC_G(sess_lock_key) = lock_key; - MEMC_G(sess_lock_key_len) = lock_key_len; - return 0; - } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) { - if (write_retry_attempts > 0) { - write_retry_attempts--; - continue; - } - php_error_docref(NULL, E_WARNING, "Write of lock failed"); + memcached_return rc = + memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); + + switch (rc) { + + case MEMCACHED_SUCCESS: + user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); + user_data->is_locked = 1; + break; + + case MEMCACHED_NOTSTORED: + case MEMCACHED_DATA_EXISTS: + usleep(wait_time * 1000); + wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); break; - } - if (lock_wait > 0) { - usleep(lock_wait); + default: + php_error_docref(NULL, E_WARNING, "Failed to write session lock: %s", memcached_strerror (memc, rc)); + break; } - } while(--attempts > 0); + } while (!user_data->is_locked && retries-- > 0); efree(lock_key); - return -1; + return user_data->is_locked; } -static void php_memc_sess_unlock(memcached_st *memc) +static +void s_unlock_session(memcached_st *memc) { - if (MEMC_G(sess_locked)) { - memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); - MEMC_G(sess_locked) = 0; - efree(MEMC_G(sess_lock_key)); - MEMC_G(sess_lock_key_len) = 0; + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + if (user_data->is_locked) { + memcached_delete(memc, user_data->lock_key->val, user_data->lock_key->len, 0); + user_data->is_locked = 0; + zend_string_release (user_data->lock_key); } } -PS_OPEN_FUNC(memcached) +static +zend_bool s_configure_from_ini_values(memcached_st *memc) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - memcached_return status; - char *p, *plist_key = NULL; - int plist_key_len = 0; - - if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { - zend_resource *le = NULL; - zval *le_z = NULL; - char *e; - - p = (char *)save_path + sizeof("PERSISTENT=") - 1; - if (!*p) { -error: - php_error_docref(NULL, E_WARNING, "Invalid persistent id for session storage"); - return FAILURE; - } - if ((e = strchr(p, ' '))) { - plist_key_len = spprintf(&plist_key, 0, "memcached_sessions:id=%.*s", (int)(e - p), p); - } else { - goto error; - } - plist_key_len++; - - if ((le_z = zend_hash_str_find(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { - le = Z_RES_P(le_z); - if (le->type == php_memc_sess_list_entry()) { - memc_sess = (memcached_sess *) le->ptr; - PS_SET_MOD_DATA(memc_sess); - return SUCCESS; - } - } - p = e + 1; - memc_sess = pecalloc(sizeof(*memc_sess), 1, 1); - memc_sess->is_persistent = 1; - } else { - p = (char *)save_path; - memc_sess = ecalloc(sizeof(*memc_sess), 1); - memc_sess->is_persistent = 0; - } - - if (!strstr(p, "--SERVER")) { - memcached_server_st *servers = memcached_servers_parse(p); - if (servers) { - memc_sess->memc_sess = memcached_create(NULL); - if (memc_sess->memc_sess) { - if (MEMC_G(sess_consistent_hash_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, (uint64_t) 1) == MEMCACHED_FAILURE) { - PS_SET_MOD_DATA(NULL); - if (plist_key) { - efree(plist_key); - } - memcached_free(memc_sess->memc_sess); - php_error_docref(NULL, E_WARNING, "failed to enable memcached consistent hashing"); - return FAILURE; - } - } + memcached_return rc; - status = memcached_server_push(memc_sess->memc_sess, servers); - memcached_server_list_free(servers); - - if (MEMC_G(sess_prefix) && MEMC_G(sess_prefix)[0] != 0 && memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { - PS_SET_MOD_DATA(NULL); - if (plist_key) { - efree(plist_key); - } - memcached_free(memc_sess->memc_sess); - php_error_docref(NULL, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); - return FAILURE; - } +#define check_set_behavior(behavior, value) \ + if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + return 0; \ + } - if (status == MEMCACHED_SUCCESS) { - goto success; - } - } else { - memcached_server_list_free(servers); - php_error_docref(NULL, E_WARNING, "could not allocate libmemcached structure"); - } - } else { - php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); - } - } else { - memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); - if (!memc_sess->memc_sess) { -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - char error_buffer[1024]; - if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "session.save_path configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); - } -#else - php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); -#endif + if (MEMC_SESS_INI(binary_protocol_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + } - } else { -success: - PS_SET_MOD_DATA(memc_sess); + if (MEMC_SESS_INI(consistent_hash_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_KETAMA, 1); + } - if (plist_key) { - zend_resource le; - zend_string *tmp_key; + if (MEMC_SESS_INI(server_failure_limit)) { + check_set_behavior(MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, MEMC_SESS_INI(server_failure_limit)); + } - le.type = php_memc_sess_list_entry(); - le.ptr = memc_sess; + if (MEMC_SESS_INI(number_of_replicas)) { + check_set_behavior(MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, MEMC_SESS_INI(number_of_replicas)); + } - tmp_key = zend_string_init(plist_key, plist_key_len, 0); - if (zend_hash_update_mem(&EG(persistent_list), tmp_key, (void *)&le, sizeof(le)) == NULL) { - zend_string_release(tmp_key); - efree(plist_key); - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - } - zend_string_release(tmp_key); - efree(plist_key); - } + if (MEMC_SESS_INI(randomize_replica_read_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, 1); + } + + if (MEMC_SESS_INI(remove_failed_servers_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, 1); + } + + if (MEMC_SESS_INI(connect_timeout)) { + check_set_behavior(MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_SESS_INI(connect_timeout)); + } + + if (MEMC_SESS_STR_INI(prefix)) { + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, MEMC_SESS_STR_INI(prefix)); + } - if (MEMC_G(sess_binary_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); - return FAILURE; - } - } #ifdef HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { - /* - * Enable SASL support if username and password are set - * - */ - if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) { - /* Force binary protocol */ - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); - return FAILURE; - } - if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); - return FAILURE; - } - MEMC_G(sess_sasl_data) = 1; - } - } + if (MEMC_SESS_STR_INI(sasl_username) && MEMC_SESS_STR_INI(sasl_password)) { + php_memcached_user_data *user_data; + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (memcached_set_sasl_auth_data(memc, MEMC_SESS_STR_INI(sasl_username), MEMC_SESS_STR_INI(sasl_password)) == MEMCACHED_FAILURE) { + php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); + return 0; + } + user_data = memcached_get_user_data(memc); + user_data->has_sasl_data = 1; + } #endif - if (MEMC_G(sess_number_of_replicas) > 0) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session number of replicas"); - return FAILURE; - } - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session randomize replica read"); - } - } - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached connection timeout"); - return FAILURE; - } -#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS - /* Allow libmemcached remove failed servers */ - if (MEMC_G(sess_remove_failed_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set: remove failed servers"); - return FAILURE; +#undef safe_set_behavior + + return 1; +} + +static +void *s_pemalloc_fn(const memcached_st *memc, size_t size, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pemalloc(size, *is_persistent); +} + +static +void s_pefree_fn(const memcached_st *memc, void *mem, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pefree(mem, *is_persistent); +} + +static +void *s_perealloc_fn(const memcached_st *memc, void *mem, const size_t size, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + perealloc(mem, size, *is_persistent); +} + +static +void *s_pecalloc_fn(const memcached_st *memc, size_t nelem, const size_t elsize, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pecalloc(nelem, elsize, *is_persistent); +} + + +static +memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool is_persistent) +{ + void *buffer; + php_memcached_user_data *user_data; + memcached_st *memc; + + buffer = pecalloc(1, sizeof(memcached_st), is_persistent); + memc = memcached_create (buffer); + + if (!memc) { + php_error_docref(NULL, E_ERROR, "failed to allocate memcached structure"); + /* not reached */ + } + + memcached_set_memory_allocators(memc, s_pemalloc_fn, s_pefree_fn, s_perealloc_fn, s_pecalloc_fn, NULL); + + user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); + user_data->is_persistent = is_persistent; + user_data->has_sasl_data = 0; + user_data->lock_key = NULL; + user_data->is_locked = 0; + + memcached_set_user_data(memc, user_data); + memcached_server_push (memc, servers); + return memc; +} + +PS_OPEN_FUNC(memcached) +{ + memcached_st *memc = NULL; + char *plist_key = NULL; + size_t plist_key_len = 0; + memcached_server_list_st servers; + + // First parse servers + servers = memcached_servers_parse(save_path); + + if (!servers) { + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + + if (MEMC_SESS_INI(persistent_enabled)) { + zend_resource *le_p; + + plist_key_len = spprintf(&plist_key, 0, "memc-session:%s", save_path); + + if ((le_p = zend_hash_str_find_ptr(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { + if (le_p->type == s_memc_sess_list_entry()) { + memc = (memcached_st *) le_p->ptr; + + if (!s_configure_from_ini_values(memc)) { + // Remove existing plist entry + zend_hash_str_del(&EG(persistent_list), plist_key, plist_key_len); + memc = NULL; + } + else { + efree(plist_key); + PS_SET_MOD_DATA(memc); + return SUCCESS; } } -#endif - return SUCCESS; } } + memc = s_init_mod_data(servers, MEMC_SESS_INI(persistent_enabled)); + memcached_server_list_free(servers); + if (plist_key) { + zend_resource le; + + le.type = s_memc_sess_list_entry(); + le.ptr = memc; + + GC_REFCOUNT(&le) = 1; + + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(le)) == NULL) { + php_error_docref(NULL, E_ERROR, "Could not register persistent entry for the memcached session"); + /* not reached */ + } efree(plist_key); } - PS_SET_MOD_DATA(NULL); - return FAILURE; + PS_SET_MOD_DATA(memc); + return SUCCESS; } PS_CLOSE_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + memcached_st *memc = PS_GET_MOD_DATA(); + php_memcached_user_data *user_data; - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess); + user_data = memcached_get_user_data(memc); + + if (user_data->is_locked) { + s_unlock_session(memc); } - if (memc_sess->memc_sess) { - if (!memc_sess->is_persistent) { -#ifdef HAVE_MEMCACHED_SASL - if (MEMC_G(sess_sasl_data)) { - memcached_destroy_sasl_auth_data(memc_sess->memc_sess); - } -#endif - memcached_free(memc_sess->memc_sess); - efree(memc_sess); - } - PS_SET_MOD_DATA(NULL); + + if (!user_data->is_persistent) { + s_destroy_mod_data(memc); } + PS_SET_MOD_DATA(NULL); return SUCCESS; } @@ -306,35 +380,27 @@ PS_READ_FUNC(memcached) { char *payload = NULL; size_t payload_len = 0; - int key_len = key->len; uint32_t flags = 0; memcached_return status; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - size_t key_length; + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." - if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - return FAILURE; - } - - if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess->memc_sess, key->val) < 0) { + if (MEMC_SESS_INI(lock_enabled)) { + if (!s_lock_session(memc, key)) { php_error_docref(NULL, E_WARNING, "Unable to clear session lock record"); return FAILURE; } } - payload = memcached_get(memc_sess->memc_sess, key->val, key_len, &payload_len, &flags, &status); + payload = memcached_get(memc, key->val, key->len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { - *val = zend_string_init(payload, payload_len, 1); - free(payload); + *val = zend_string_init(payload, payload_len, 0); + efree(payload); return SUCCESS; } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); @@ -346,59 +412,53 @@ PS_READ_FUNC(memcached) PS_WRITE_FUNC(memcached) { - int key_len = key->len; - time_t expiration = 0; - long write_try_attempts = 1; - memcached_return status; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + zend_long retries = 1; + memcached_st *memc = PS_GET_MOD_DATA(); size_t key_length; + time_t expiration; - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." - if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - return FAILURE; - } + /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ + if (MEMC_SESS_INI(remove_failed_servers_enabled)) { + zend_long replicas, failure_limit; - if (maxlifetime > 0) { - expiration = maxlifetime; - } + replicas = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); + failure_limit = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT); - /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ - if (MEMC_G(sess_remove_failed_enabled)) { - write_try_attempts = 1 + MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); + retries = 1 + replicas * (failure_limit + 1); } + expiration = time(NULL) + maxlifetime; + do { - status = memcached_set(memc_sess->memc_sess, key->val, key_len, val->val, val->len, expiration, 0); - if (status == MEMCACHED_SUCCESS) { + if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; - } else { - write_try_attempts--; } - } while (write_try_attempts > 0); + } while (--retries > 0); return FAILURE; } PS_DESTROY_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + php_memcached_user_data *user_data; + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess); - } + memcached_delete(memc, key->val, key->len, 0); + user_data = memcached_get_user_data(memc); + if (user_data->is_locked) { + s_unlock_session(memc); + } return SUCCESS; } @@ -410,34 +470,31 @@ PS_GC_FUNC(memcached) PS_CREATE_SID_FUNC(memcached) { zend_string *sid; - int retries = 3; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - time_t expiration = PS(gc_maxlifetime); + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { - return NULL; + if (!memc) { + sid = php_session_create_id(NULL); } + else { + int retries = 3; + while (retries-- > 0) { + sid = php_session_create_id((void **) &memc); - while (retries-- > 0) { - sid = php_session_create_id((void**)&memc_sess); - - if (sid) { - if (memcached_add(memc_sess->memc_sess, sid->val, sid->len, "0", 0, expiration, 0) == MEMCACHED_SUCCESS) { - return sid; - } - else { - zend_string_release(sid); + if (memcached_add (memc, sid->val, sid->len, NULL, 0, s_lock_expiration(), 0) == MEMCACHED_SUCCESS) { + break; } + zend_string_release(sid); + sid = NULL; } } - return NULL; + return sid; } PS_VALIDATE_SID_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + memcached_st *memc = PS_GET_MOD_DATA(); - if (php_memcached_exist(memc_sess->memc_sess, key) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; @@ -446,13 +503,10 @@ PS_VALIDATE_SID_FUNC(memcached) PS_UPDATE_TIMESTAMP_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - time_t expiration = 0; + memcached_st *memc = PS_GET_MOD_DATA(); + time_t expiration = time(NULL) + maxlifetime; - if (maxlifetime > 0) { - expiration = maxlifetime; - } - if (memcached_touch(memc_sess->memc_sess, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; } return SUCCESS; diff --git a/php_memcached_session.h b/php_memcached_session.h index 4118362f..13ce363c 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -36,4 +36,7 @@ PS_CREATE_SID_FUNC(memcached); PS_VALIDATE_SID_FUNC(memcached); PS_UPDATE_TIMESTAMP_FUNC(memcached); +/* Called from php_memcached.c */ +int php_memc_session_minit(int module_number); + #endif /* PHP_MEMCACHED_SESSION_H */ diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 9fe8f4f8..31a736b7 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -13,6 +13,10 @@ $first_key = uniqid ('cache_test_'); $second_key = uniqid ('cache_test_'); $third_key = uniqid ('cache_test_'); +$m->delete($first_key); +$m->delete($second_key); +$m->delete($third_key); + var_dump ( $m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { $value = "hello"; diff --git a/tests/cas.phpt b/tests/cas.phpt index e9990798..c1c1752f 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -8,47 +8,12 @@ include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = null; +$cas_token = 0; -$m->set('cas_test', 10); -$v = $m->get('cas_test', null, $cas_token); - -if (is_null($cas_token)) { - echo "Null cas token for key: cas_test value: 10\n"; - return; -} - -$v = $m->cas($cas_token, 'cas_test', 11); -if (!$v) { - echo "Error setting key: cas_test value: 11 with CAS: $cas_token\n"; - return; -} - -$v = $m->get('cas_test'); - -if ($v !== 11) { - echo "Wanted cas_test to be 11, value is: "; - var_dump($v); -} - -$v = $m->get('cas_test', null, 2); -if ($v != 11) { - echo "Failed to get the value with \$cas_token passed by value (2)\n"; - return; -} - -$v = $m->get('cas_test', null, null); -if ($v != 11) { - echo "Failed to get the value with \$cas_token passed by value (null)\n"; - return; -} - -$v = $m->get('cas_test', null, $data = array(2, 4)); -if ($v != 11 || $data !== array(2, 4)) { - echo "Failed to get the value with \$cas_token passed by value (\$data = array(2, 4))\n"; - return; -} +$m->set('cas_test', 'hello'); +$cas_token = $m->get('cas_test', null, Memcached::GET_EXTENDED)['cas']; +$v = $m->cas($cas_token, 'cas_test', 0); echo "OK\n"; ?> --EXPECT-- diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index 240ecadd..499742be 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -16,25 +16,22 @@ foreach ($data as $key => $v) { $m->delete($key); } -$cas_tokens = array(); $m->setMulti($data, 10); -$actual = $m->getMulti(array_keys($data), $cas_tokens); +$actual = $m->getMulti(array_keys($data), Memcached::GET_EXTENDED); -foreach ($data as $key => $v) { - if (is_null($cas_tokens[$key])) { +foreach ($actual as $key => $v) { + if (is_null($v['cas'])) { echo "missing cas token(s)\n"; echo "data: "; var_dump($data); echo "actual data: "; var_dump($actual); - echo "cas tokens: "; - var_dump($cas_tokens); return; } - $v = $m->cas($cas_tokens[$key], $key, 11); + $v = $m->cas($v['cas'], $key, 11); if (!$v) { - echo "Error setting key: $key value: 11 with CAS: ", $cas_tokens[$key], "\n"; + echo "Error setting key: $key value: 11 with CAS: ", $v['cas'], "\n"; return; } $v = $m->get($key); @@ -54,24 +51,6 @@ if (array_keys($actual) !== array_keys($data)) { return; } -$actual = $m->getMulti(array_keys($data), 2); -if (array_keys($actual) !== array_keys($data)) { - echo "Failed to getMulti \$cas_token passed by value (2)\n"; - return; -} - -$actual = $m->getMulti(array_keys($data), null); -if (array_keys($actual) !== array_keys($data)) { - echo "Failed to getMulti \$cas_token passed by value (null)\n"; - return; -} - -$actual = $m->getMulti(array_keys($data), $cas_tokens = array(2, 4)); -if (array_keys($actual) !== array_keys($data) || $cas_tokens !== array(2, 4)) { - echo "Failed to getMulti \$cas_token passed by value (\$cas_tokens = array(2, 4))\n"; - return; -} - echo "OK\n"; ?> diff --git a/tests/multi_order.phpt b/tests/multi_order.phpt index 4fd5f5b4..876ddc66 100644 --- a/tests/multi_order.phpt +++ b/tests/multi_order.phpt @@ -21,10 +21,9 @@ foreach ($data as $k => $v) { $m->set($k, $v, 3600); } -$null = null; $keys = array_keys($data); $keys[] = 'zoo'; -$got = $m->getMulti($keys, $null, Memcached::GET_PRESERVE_ORDER); +$got = $m->getMulti($keys, Memcached::GET_PRESERVE_ORDER); foreach ($got as $k => $v) { echo "$k $v\n"; diff --git a/tests/no-not-found.phpt b/tests/no-not-found.phpt index de96d3e4..06ae85e9 100644 --- a/tests/no-not-found.phpt +++ b/tests/no-not-found.phpt @@ -11,8 +11,7 @@ $memcached->addServer('localhost', 5555); // Server should not exist $result = $memcached->get('foo_not_exists'); var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); -$cas = 7; -$result = $memcached->get('foo_not_exists', null, $cas); +$result = $memcached->get('foo_not_exists'); var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); echo "OK\n"; diff --git a/tests/rescode.phpt b/tests/rescode.phpt index fbda4f78..5b835d44 100644 --- a/tests/rescode.phpt +++ b/tests/rescode.phpt @@ -23,6 +23,7 @@ $m->delete('bar_foo'); echo $m->getResultCode(), "\n"; echo $m->getResultMessage(), "\n"; +$m->set ('asdf_a', 'aa'); $m->getMulti(array('asdf_a', 'jkhjkhjkb', 'nbahsdgc')); echo $m->getResultMessage(), "\n"; $code = $m->getResultCode(); diff --git a/tests/set_large.phpt b/tests/set_large.phpt index d9353a8e..bf1098ef 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -9,8 +9,9 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = str_repeat("foo bar", 1024 * 1024); -$m->set($key, $value, 360); +var_dump($m->set($key, $value, 360)); var_dump($m->get($key) === $value); ?> --EXPECT-- bool(true) +bool(true) diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 137ff1e8..7b02ea2d 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -16,6 +16,10 @@ function check_flags ($flags, $expected_flags) echo "Flags OK" . PHP_EOL; } +function get_flags($m, $key) { + return $m->get($key, null, Memcached::GET_EXTENDED)['flags']; +} + define ('FLAG_1', 1); define ('FLAG_2', 2); define ('FLAG_4', 4); @@ -30,26 +34,26 @@ $key = uniqid ('udf_test_'); // Set with flags off $m->set ($key, '1', 10); -$m->get($key); -var_dump($m->getLastUserFlags()); +$v = $m->get($key, null, Memcached::GET_EXTENDED); +var_dump($v); // Set flags on $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1)); +check_flags(get_flags($m, $key), array(FLAG_1)); // Multiple flags $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4)); // Even more flags $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4 | FLAG_32 | FLAG_64); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); // User flags with get multi $values = array( @@ -61,10 +65,10 @@ $values = array( $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_2 | FLAG_4); $m->setMulti($values); $m->getMulti(array_keys($values)); -$flags = $m->getLastUserFlags(); +$flags = $m->getMulti(array_keys($values), Memcached::GET_EXTENDED); foreach (array_keys($values) as $key) { - check_flags($flags[$key], array(FLAG_2, FLAG_4)); + check_flags($flags[$key]['flags'], array(FLAG_2, FLAG_4)); } // User flags with compression on @@ -74,7 +78,7 @@ $m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4)); // Too large flags @@ -83,8 +87,12 @@ $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> --EXPECTF-- -array(1) { - ["udf_test_%s"]=> +array(3) { + ["value"]=> + string(1) "1" + ["cas"]=> + int(%d) + ["flags"]=> int(0) } Flags OK From c15d792ec3b646df6fa06c39328441f107120e9e Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 30 Jan 2016 11:41:57 +0000 Subject: [PATCH 408/694] Clean up session code, start on the whole i_obj/m_obj confusion --- php_memcached.c | 255 ++++++++++++++++------------------ php_memcached_session.c | 49 ++++--- tests/callback_exception.phpt | 3 +- tests/cas.phpt | 5 +- 4 files changed, 155 insertions(+), 157 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 23e9bde3..e91a5600 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -122,67 +122,8 @@ php_memc_t* i_obj = NULL; \ struct memc_obj* m_obj = NULL; -#ifndef DVAL_TO_LVAL -#ifdef _WIN64 -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - (l) = (long)(unsigned long)(__int64) (d); \ - } else { \ - (l) = (long) (d); \ - } -#else -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - (l) = (unsigned long) (d); \ - } else { \ - (l) = (long) (d); \ - } -#endif -#endif - #define RETURN_FROM_GET RETURN_FALSE -typedef memcached_return (*memc_store_fn)( - memcached_st *, - const char *key, size_t key_len, - const char *payload, size_t payload_len, - time_t expiration, uint32_t flags); - -typedef memcached_return (*memc_store_by_key_fn)( - memcached_st *, - const char *server_key, size_t server_key_len, - const char *key, size_t key_len, - const char *payload, size_t payload_len, - time_t expiration, uint32_t flags); - -static memc_store_fn php_memc_store_funcs[] = { - &memcached_set, - &memcached_add, - &memcached_replace, - &memcached_prepend, - &memcached_append -}; - -void s_call_store_func(int op, memcached_st *memc, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) -{ - (*php_memc_store_funcs[op])(memc, key, key_len,payload, payload_len, expiration, flags); -} - - -static memc_store_by_key_fn php_memc_store_by_keys_funcs[] = { - &memcached_set_by_key, - &memcached_add_by_key, - &memcached_replace_by_key, - &memcached_prepend_by_key, - &memcached_append_by_key -}; - -void s_call_store_by_key_func(int op, memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) -{ - (*php_memc_store_by_keys_funcs[op])(memc, server_key, server_key_len, key, key_len,payload, payload_len, expiration, flags); -} - - /**************************************** Structures and definitions ****************************************/ @@ -314,10 +255,10 @@ static PHP_INI_MH(OnUpdateSerializer) } #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.##key", default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.session.##key", default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.session."key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ @@ -349,7 +290,6 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) - PHP_INI_END() /* }}} */ @@ -472,7 +412,6 @@ static PHP_METHOD(Memcached, __construct) struct memc_obj *m_obj = NULL; zend_string *persistent_id = NULL; zend_string *conn_str = NULL; - zend_bool is_persistent = 0; zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; @@ -483,102 +422,103 @@ static PHP_METHOD(Memcached, __construct) i_obj = Z_MEMC_OBJ_P(object); i_obj->is_pristine = 0; + i_obj->is_persistent = 0; if (persistent_id && persistent_id->len) { zend_resource *le; - is_persistent = 1; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; + + i_obj->obj = m_obj; + i_obj->is_persistent = 1; + zend_string_release (plist_key); + return; } } - i_obj->obj = m_obj; + i_obj->is_persistent = 1; } - i_obj->is_persistent = is_persistent; + m_obj = pecalloc(1, sizeof(*m_obj), i_obj->is_persistent); + if (m_obj == NULL) { + if (plist_key) { + zend_string_release(plist_key); + } + php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); + /* not reached */ + } - if (!m_obj) { - m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); - if (m_obj == NULL) { + if (conn_str) { + m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); + if (!m_obj->memc) { + char error_buffer[1024]; if (plist_key) { zend_string_release(plist_key); } - php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); - /* not reached */ - } - - if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!m_obj->memc) { - char error_buffer[1024]; - if (plist_key) { - zend_string_release(plist_key); - } #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - } -#else + if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); + } else { php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); -#endif - /* not reached */ } - } else { - m_obj->memc = memcached_create(NULL); - if (m_obj->memc == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - /* not reached */ +#else + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); +#endif + /* not reached */ + } + } else { + m_obj->memc = memcached_create(NULL); + if (m_obj->memc == NULL) { + if (plist_key) { + zend_string_release(plist_key); } + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); + /* not reached */ } + } - m_obj->serializer = MEMC_G(serializer); - m_obj->compression_type = MEMC_G(compression_type_real); - m_obj->compression = 1; - m_obj->store_retry_count = MEMC_G(store_retry_count); - - m_obj->set_udf_flags = -1; - - i_obj->obj = m_obj; - i_obj->is_pristine = 1; + m_obj->serializer = MEMC_G(serializer); + m_obj->compression_type = MEMC_G(compression_type_real); + m_obj->compression = 1; + m_obj->store_retry_count = MEMC_G(store_retry_count); + m_obj->set_udf_flags = -1; - if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } + i_obj->obj = m_obj; + i_obj->is_pristine = 1; - i_obj->obj = NULL; - if (is_persistent) { - php_memc_destroy(m_obj, is_persistent); - } + if (fci.size) { /* will be 0 when not available */ + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } - return; + i_obj->obj = NULL; + if (i_obj->is_persistent) { + php_memc_destroy(m_obj, i_obj->is_persistent); } + + return; } + } - if (is_persistent) { - zend_resource le; + if (i_obj->is_persistent) { + zend_resource le; - le.type = php_memc_list_entry(); - le.ptr = m_obj; - GC_REFCOUNT(&le) = 1; - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ + le.type = php_memc_list_entry(); + le.ptr = m_obj; + GC_REFCOUNT(&le) = 1; + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + if (plist_key) { + zend_string_release(plist_key); } + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ } } @@ -593,7 +533,12 @@ void s_uint64_to_zval (zval *target, uint64_t value) { if (value >= LONG_MAX) { char *buffer; +#ifdef PRIu64 spprintf (&buffer, 0, "%" PRIu64, value); +#else + /* Best effort */ + spprintf (&buffer, 0, "%llu", value); +#endif ZVAL_STRING (target, buffer); efree(buffer); } @@ -602,6 +547,41 @@ void s_uint64_to_zval (zval *target, uint64_t value) } } +static +uint64_t s_zval_to_uint64 (zval *cas) +{ + switch (Z_TYPE_P (cas)) { + case IS_LONG: + return (uint64_t) zval_get_long (cas); + break; + + case IS_DOUBLE: + if (Z_DVAL_P (cas) < 0.0) + return 0; + + return (uint64_t) zval_get_double (cas); + break; + + case IS_STRING: + { + uint64_t val; + char *end; + + errno = 0; + val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + + if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { + php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); + return 0; + } + return val; + } + break; + } + return 0; +} + + typedef struct { size_t num_valid_keys; @@ -674,10 +654,7 @@ memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, { php_memcached_keys keys = { 0 }; zval values; - memcached_return rc, status = MEMCACHED_SUCCESS; - - size_t num_keys; uint64_t orig_cas_flag; memcached_result_st result; @@ -860,7 +837,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *keys = NULL; zend_string *server_key = NULL; - zend_bool extended_results = 0; memcached_return rc; zend_long flags = 0; MEMC_METHOD_INIT_VARS; @@ -1559,7 +1535,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool /* {{{ -- php_memc_cas_impl */ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - double cas_d; + zval *zv_cas; uint64_t cas; zend_string *key; zend_string *server_key = NULL; @@ -1571,12 +1547,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, &value, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, &expiration) == FAILURE) { return; } @@ -1590,7 +1566,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } - DVAL_TO_LVAL(cas_d, cas); + cas = s_zval_to_uint64(zv_cas); if (m_obj->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); @@ -1615,6 +1591,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } else { status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } + zend_string_release(payload); if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; @@ -4122,7 +4099,8 @@ PHP_GINIT_FUNCTION(php_memcached) } zend_module_entry memcached_module_entry = { - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER_EX, NULL, + memcached_deps, "memcached", NULL, PHP_MINIT(memcached), @@ -4139,6 +4117,7 @@ zend_module_entry memcached_module_entry = { }; /* }}} */ + /* {{{ php_memc_register_constants */ static void php_memc_register_constants(INIT_FUNC_ARGS) { @@ -4409,12 +4388,12 @@ PHP_MINIT_FUNCTION(memcached) */ php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU); + REGISTER_INI_ENTRIES(); #ifdef HAVE_MEMCACHED_SESSION php_memc_session_minit(module_number); #endif - REGISTER_INI_ENTRIES(); #if HAVE_MEMCACHED_SASL if (MEMC_G(sasl_enabled)) { if (sasl_client_init(NULL) != SASL_OK) { diff --git a/php_memcached_session.c b/php_memcached_session.c index 8c6454a1..1a398ab7 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -95,8 +95,6 @@ int php_memc_session_minit(int module_number) static time_t s_lock_expiration() { - zend_long max_execution_time; - if (MEMC_SESS_INI(lock_expiration) > 0) { return time(NULL) + MEMC_SESS_INI(lock_expiration); } @@ -109,9 +107,19 @@ time_t s_lock_expiration() return 0; } +static +time_t s_session_expiration(zend_long maxlifetime) +{ + if (maxlifetime > 0) { + return time(NULL) + maxlifetime; + } + return 0; +} + static zend_bool s_lock_session(memcached_st *memc, zend_string *sid) { + memcached_return rc; char *lock_key; size_t lock_key_len; time_t expiration; @@ -125,8 +133,7 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) retries = MEMC_SESS_INI(lock_retries); do { - memcached_return rc = - memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); + rc = memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); switch (rc) { @@ -137,8 +144,10 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) case MEMCACHED_NOTSTORED: case MEMCACHED_DATA_EXISTS: - usleep(wait_time * 1000); - wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); + if (retries > 0) { + usleep(wait_time * 1000); + wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); + } break; default: @@ -164,13 +173,13 @@ void s_unlock_session(memcached_st *memc) } static -zend_bool s_configure_from_ini_values(memcached_st *memc) +zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { memcached_return rc; #define check_set_behavior(behavior, value) \ if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ - php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + if (!silent) { php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); } \ return 0; \ } @@ -280,7 +289,7 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_memory_allocators(memc, s_pemalloc_fn, s_pefree_fn, s_perealloc_fn, s_pecalloc_fn, NULL); - user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); + user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); user_data->is_persistent = is_persistent; user_data->has_sasl_data = 0; user_data->lock_key = NULL; @@ -316,7 +325,7 @@ PS_OPEN_FUNC(memcached) if (le_p->type == s_memc_sess_list_entry()) { memc = (memcached_st *) le_p->ptr; - if (!s_configure_from_ini_values(memc)) { + if (!s_configure_from_ini_values(memc, 1)) { // Remove existing plist entry zend_hash_str_del(&EG(persistent_list), plist_key, plist_key_len); memc = NULL; @@ -333,6 +342,14 @@ PS_OPEN_FUNC(memcached) memc = s_init_mod_data(servers, MEMC_SESS_INI(persistent_enabled)); memcached_server_list_free(servers); + if (!s_configure_from_ini_values(memc, 0)) { + if (plist_key) { + efree(plist_key); + } + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + if (plist_key) { zend_resource le; @@ -358,7 +375,7 @@ PS_CLOSE_FUNC(memcached) php_memcached_user_data *user_data; if (!memc) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } @@ -385,7 +402,7 @@ PS_READ_FUNC(memcached) memcached_st *memc = PS_GET_MOD_DATA(); if (!memc) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } @@ -414,8 +431,7 @@ PS_WRITE_FUNC(memcached) { zend_long retries = 1; memcached_st *memc = PS_GET_MOD_DATA(); - size_t key_length; - time_t expiration; + time_t expiration = s_session_expiration(maxlifetime); if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); @@ -432,8 +448,6 @@ PS_WRITE_FUNC(memcached) retries = 1 + replicas * (failure_limit + 1); } - expiration = time(NULL) + maxlifetime; - do { if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; @@ -504,7 +518,7 @@ PS_VALIDATE_SID_FUNC(memcached) PS_UPDATE_TIMESTAMP_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - time_t expiration = time(NULL) + maxlifetime; + time_t expiration = s_session_expiration(maxlifetime); if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; @@ -512,3 +526,4 @@ PS_UPDATE_TIMESTAMP_FUNC(memcached) return SUCCESS; } /* }}} */ + diff --git a/tests/callback_exception.phpt b/tests/callback_exception.phpt index 8f71d5f8..fa149077 100644 --- a/tests/callback_exception.phpt +++ b/tests/callback_exception.phpt @@ -37,7 +37,8 @@ try { } try { - + $m = new Memcached(null, 'throw_something'); + echo "fail\n"; } catch (Exception $e) { echo "fail\n"; } diff --git a/tests/cas.phpt b/tests/cas.phpt index c1c1752f..60090c97 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -8,12 +8,15 @@ include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = 0; $m->set('cas_test', 'hello'); $cas_token = $m->get('cas_test', null, Memcached::GET_EXTENDED)['cas']; $v = $m->cas($cas_token, 'cas_test', 0); +if ($v != true) { + echo "CAS failed"; +} + echo "OK\n"; ?> --EXPECT-- From bdd0911a9bdde9c3f1f4ab14e69055dbd5b643ad Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:07:48 +0000 Subject: [PATCH 409/694] Update to a simpler object structure, make session config match old setting names, key validation removed etc --- php_memcached.c | 1026 +++++++++++++----------- php_memcached_private.h | 3 + php_memcached_session.c | 17 + tests/bug_16084.phpt | 18 +- tests/callback_exception.phpt | 3 +- tests/getserverlist.phpt | 21 +- tests/invoke_callback.phpt | 5 +- tests/keys.phpt | 1 + tests/session_badconf_emptyprefix.phpt | 17 +- tests/session_badconf_prefix.phpt | 21 +- tests/session_badconf_servers.phpt | 4 - tests/session_basic.phpt | 6 +- tests/session_basic2.phpt | 6 +- tests/session_basic3.phpt | 12 +- 14 files changed, 631 insertions(+), 529 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e91a5600..1dbe0bab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -55,6 +55,8 @@ #define MEMC_G(v) (php_memcached_globals.memc_ini.v) #endif +#include + /**************************************** Custom options @@ -117,10 +119,7 @@ /**************************************** Helper macros ****************************************/ -#define MEMC_METHOD_INIT_VARS \ - zval* object = getThis(); \ - php_memc_t* i_obj = NULL; \ - struct memc_obj* m_obj = NULL; + #define RETURN_FROM_GET RETURN_FALSE @@ -133,37 +132,48 @@ enum memcached_compression_type { }; typedef struct { - struct memc_obj { - memcached_st *memc; - zend_bool compression; - enum memcached_serializer serializer; - enum memcached_compression_type compression_type; + + zend_bool is_persistent; + zend_bool compression; + enum memcached_serializer serializer; + enum memcached_compression_type compression_type; + + zend_long store_retry_count; + zend_long set_udf_flags; + #if HAVE_MEMCACHED_SASL - zend_bool has_sasl_data; + zend_bool has_sasl_data; #endif - long store_retry_count; - zend_long set_udf_flags; - } *obj; - zend_bool is_persistent; +} php_memc_user_data_t; + + +typedef struct { + memcached_st *memc; zend_bool is_pristine; int rescode; int memc_errno; zend_object zo; -} php_memc_t; +} php_memc_object_t; -static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { - return (php_memc_t *)((char *)obj - XtOffsetOf(php_memc_t, zo)); +static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { + return (php_memc_object_t *)((char *)obj - XtOffsetOf(php_memc_object_t, zo)); } #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); -#define MEMC_METHOD_FETCH_OBJECT \ - i_obj = Z_MEMC_OBJ_P(object); \ - m_obj = i_obj->obj; \ - if (!m_obj) { \ - php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ - return; \ - } +#define MEMC_METHOD_INIT_VARS \ + zval* object = getThis(); \ + php_memc_object_t* intern = NULL; \ + php_memc_user_data_t* memc_user_data = NULL; + +#define MEMC_METHOD_FETCH_OBJECT \ + intern = Z_MEMC_OBJ_P(object); \ + if (!intern->memc) { \ + php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ + return; \ + } \ + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); + #ifdef HAVE_MEMCACHED_PROTOCOL @@ -194,15 +204,6 @@ static zend_object_handlers memcached_server_object_handlers; static zend_class_entry *memcached_server_ce = NULL; #endif -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 */ -}; - #if HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -254,22 +255,51 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static +PHP_INI_MH(OnUpdateDeprecatedLockValue) +{ + if (new_value->len > 0 && strcmp(new_value->val, "not set")) { + php_error_docref(NULL, E_DEPRECATED, "memcached.sess_lock_wait and memcached.sess_lock_max_wait are deprecated. Please update your configuration to use memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries"); + } + return FAILURE; +} + +static +PHP_INI_MH(OnUpdateSessionPrefixString) +{ + if (new_value && new_value->len > 0) { + char *ptr = new_value->val; + + while (*ptr != '\0') { + if (isspace (*ptr++)) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace characters"); + return FAILURE; + } + } + if (new_value->len > MEMCACHED_MAX_KEY) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); + return FAILURE; + } + } + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.session."key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION - MEMC_SESSION_INI_ENTRY("lock_enabled", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) - MEMC_SESSION_INI_ENTRY("lock_expiration", "0", OnUpdateLongGEZero, lock_expiration) + MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) @@ -280,8 +310,13 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) - MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateString, prefix) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateSessionPrefixString, prefix) MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) + + /* Deprecated */ + STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_lock_max_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) + #endif MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) @@ -299,7 +334,7 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); +static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); @@ -308,14 +343,27 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); 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, zend_string *key, zval *value); -static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); + +/* Invoke PHP functions */ +static + memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + +static + int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); + +/* Callback functions for different server list iterations */ +static + memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); + +static + memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); + +/* Callback for dumping all keys to zval */ +static + void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); + static zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); @@ -364,7 +412,8 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ return buffer; } -static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) +static +zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; zval retval, id; @@ -388,17 +437,23 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc ret = 0; } - if (Z_TYPE(retval) != IS_UNDEF) + if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); + } - zend_fcall_info_args_clear(fci, 1); + if (EG(exception)) { + ret = 0; + } + zend_fcall_info_args_clear(fci, 1); return ret; } -static int le_memc; +static + int le_memc; -static int php_memc_list_entry(void) +static +int php_memc_list_entry(void) { return le_memc; } @@ -407,22 +462,23 @@ static int php_memc_list_entry(void) Creates a Memcached object, optionally using persistent memcache connection */ static PHP_METHOD(Memcached, __construct) { - zval *object = getThis(); - php_memc_t *i_obj; - struct memc_obj *m_obj = NULL; + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; + zend_string *persistent_id = NULL; zend_string *conn_str = NULL; zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; + zend_bool is_persistent = 0; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } - i_obj = Z_MEMC_OBJ_P(object); - i_obj->is_pristine = 0; - i_obj->is_persistent = 0; + intern = Z_MEMC_OBJ_P(getThis()); + intern->is_pristine = 1; if (persistent_id && persistent_id->len) { zend_resource *le; @@ -432,18 +488,74 @@ static PHP_METHOD(Memcached, __construct) if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { - m_obj = (struct memc_obj *) le->ptr; - - i_obj->obj = m_obj; - i_obj->is_persistent = 1; + intern->memc = le->ptr; + intern->is_pristine = 0; zend_string_release (plist_key); return; } } - i_obj->is_persistent = 1; + is_persistent = 1; + } + + if (conn_str && conn_str->len > 0) { + intern->memc = memcached (conn_str->val, conn_str->len); + } + else { + intern->memc = memcached (NULL, 0); + } + + if (!intern->memc) { + // TODO: handle allocation fail + } + + memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); + memc_user_data->serializer = MEMC_G(serializer); + memc_user_data->compression_type = MEMC_G(compression_type_real); + memc_user_data->compression = 1; + memc_user_data->store_retry_count = MEMC_G(store_retry_count); + memc_user_data->set_udf_flags = -1; + memc_user_data->is_persistent = is_persistent; + + memcached_set_user_data(intern->memc, memc_user_data); + + if (fci.size) { + if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } + /* + Setting intern->memc null prevents object destruction from freeing the memcached_st + We free it manually here because it might be persistent and has not been + registered to persistent_list yet + */ + php_memc_destroy(intern->memc, memc_user_data); + intern->memc = NULL; + return; + } } - m_obj = pecalloc(1, sizeof(*m_obj), i_obj->is_persistent); + if (plist_key) { + zend_resource le; + + le.type = php_memc_list_entry(); + le.ptr = intern->memc; + + GC_REFCOUNT(&le) = 1; + + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + zend_string_release(plist_key); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ + } + zend_string_release(plist_key); + } + + + +#if 0 + m_obj = pecalloc(1, sizeof(*m_obj), intern->is_persistent); if (m_obj == NULL) { if (plist_key) { zend_string_release(plist_key); @@ -453,8 +565,8 @@ static PHP_METHOD(Memcached, __construct) } if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!m_obj->memc) { + intern->memc = php_memc_create_str(conn_str->val, conn_str->len); + if (!intern->memc) { char error_buffer[1024]; if (plist_key) { zend_string_release(plist_key); @@ -471,8 +583,8 @@ static PHP_METHOD(Memcached, __construct) /* not reached */ } } else { - m_obj->memc = memcached_create(NULL); - if (m_obj->memc == NULL) { + intern->memc = memcached_create(NULL); + if (intern->memc == NULL) { if (plist_key) { zend_string_release(plist_key); } @@ -481,14 +593,10 @@ static PHP_METHOD(Memcached, __construct) } } - m_obj->serializer = MEMC_G(serializer); - m_obj->compression_type = MEMC_G(compression_type_real); - m_obj->compression = 1; - m_obj->store_retry_count = MEMC_G(store_retry_count); - m_obj->set_udf_flags = -1; - i_obj->obj = m_obj; - i_obj->is_pristine = 1; + + intern->obj = m_obj; + intern->is_pristine = 1; if (fci.size) { /* will be 0 when not available */ if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { @@ -497,16 +605,16 @@ static PHP_METHOD(Memcached, __construct) zend_string_release(plist_key); } - i_obj->obj = NULL; - if (i_obj->is_persistent) { - php_memc_destroy(m_obj, i_obj->is_persistent); + intern->obj = NULL; + if (intern->is_persistent) { + php_memc_destroy(m_obj, intern->is_persistent); } return; } } - if (i_obj->is_persistent) { + if (intern->is_persistent) { zend_resource le; le.type = php_memc_list_entry(); @@ -525,6 +633,7 @@ static PHP_METHOD(Memcached, __construct) if (plist_key) { zend_string_release(plist_key); } +#endif } /* }}} */ @@ -775,14 +884,14 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; zend_hash_init (&keys, 1, 0, NULL, 0); ZVAL_STR(&tmp, key); zend_hash_add(&keys, key, &tmp); ZVAL_UNDEF(&values); - status = s_memcached_get_multi(m_obj->memc, &keys, server_key, get_flags, &values); + status = s_memcached_get_multi(intern->memc, &keys, server_key, get_flags, &values); zend_hash_destroy (&keys); if (EG(exception)) { @@ -808,10 +917,10 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (status == MEMCACHED_NOTFOUND && fci.size > 0) { // try to invoke cache cb - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); + status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FROM_GET; } } @@ -854,8 +963,8 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; - rc = s_memcached_get_multi(m_obj->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); - php_memc_handle_error(i_obj, rc); + rc = s_memcached_get_multi(intern->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); + php_memc_handle_error(intern, rc); if (EG(exception)) { zval_dtor(return_value); @@ -926,7 +1035,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; /* * Create the array of keys for libmemcached. If none of the keys were valid @@ -949,7 +1058,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ } ZEND_HASH_FOREACH_END(); if (i == 0) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; efree(mkeys); efree(mkeys_len); zval_dtor(return_value); @@ -960,9 +1069,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ * Enable CAS support, but only if it is currently disabled. */ if (with_cas) { - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); + orig_cas_flag = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } @@ -970,20 +1079,20 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ * Issue the request, but collect results only if the result callback is provided. */ if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); } else { - status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + status = memcached_mget(intern->memc, mkeys, mkeys_len, i); } /* * Restore the CAS support flag, but only if we had to turn it on. */ if (with_cas && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } efree(mkeys); efree(mkeys_len); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -995,9 +1104,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ */ memcached_result_st result; - memcached_result_create(m_obj->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result) < 0) { + memcached_result_create(intern->memc, &result); + while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { + if (s_invoke_result_callback(getThis(), &fci, &fcc, &result) < 0) { status = MEMCACHED_FAILURE; break; } @@ -1008,7 +1117,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (status == MEMCACHED_END) { status = MEMCACHED_SUCCESS; } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } } @@ -1037,11 +1146,11 @@ PHP_METHOD(Memcached, fetch) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &result); - if ((memcached_fetch_result(m_obj->memc, &result, &status)) == NULL) { - php_memc_handle_error(i_obj, status); + memcached_result_create(intern->memc, &result); + if ((memcached_fetch_result(intern->memc, &result, &status)) == NULL) { + php_memc_handle_error(intern, status); memcached_result_free(&result); RETURN_FALSE; } @@ -1055,7 +1164,7 @@ PHP_METHOD(Memcached, fetch) if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1094,12 +1203,12 @@ PHP_METHOD(Memcached, fetchAll) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; array_init(return_value); - memcached_result_create(m_obj->memc, &result); + memcached_result_create(intern->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { + while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { payload = memcached_result_value(&result); payload_len = memcached_result_length(&result); flags = memcached_result_flags(&result); @@ -1110,7 +1219,7 @@ PHP_METHOD(Memcached, fetchAll) if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); zval_dtor(return_value); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1129,7 +1238,7 @@ PHP_METHOD(Memcached, fetchAll) memcached_result_free(&result); - if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status) < 0) { + if (status != MEMCACHED_END && php_memc_handle_error(intern, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1188,8 +1297,8 @@ PHP_METHOD(Memcached, setMultiByKey) /* }}} */ #define PHP_MEMC_FAILOVER_RETRY \ - if (!by_key && retry < m_obj->store_retry_count) { \ - switch (i_obj->rescode) { \ + if (!by_key && retry < memc_user_data->store_retry_count) { \ + switch (intern->rescode) { \ case MEMCACHED_HOST_LOOKUP_FAILURE: \ case MEMCACHED_CONNECTION_FAILURE: \ case MEMCACHED_CONNECTION_BIND_FAILURE: \ @@ -1203,9 +1312,9 @@ PHP_METHOD(Memcached, setMultiByKey) case MEMCACHED_FAIL_UNIX_SOCKET: \ case MEMCACHED_SERVER_MARKED_DEAD: \ case MEMCACHED_SERVER_TEMPORARILY_DISABLED: \ - if (memcached_server_count(m_obj->memc) > 0) { \ + if (memcached_server_count(intern->memc) > 0) { \ retry++; \ - i_obj->rescode = 0; \ + intern->rescode = 0; \ goto retry; \ } \ break; \ @@ -1241,7 +1350,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { if (skey) { @@ -1258,17 +1367,17 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } flags = 0; - if (m_obj->compression) { + if (memc_user_data->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; if (!skey) { zend_string_release(str_key); } @@ -1277,12 +1386,12 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); + status = memcached_set(intern->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); + status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY if (!skey) { zend_string_release(str_key); @@ -1414,14 +1523,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } - - if (m_obj->compression) { + if (memc_user_data->compression) { /* * When compression is enabled, we cannot do appends/prepends because that would * corrupt the compressed values. It is up to the user to fetch the value, @@ -1438,21 +1542,21 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } if (op == MEMC_OP_TOUCH) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif } else { - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } } @@ -1460,54 +1564,54 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool switch (op) { case MEMC_OP_SET: if (!server_key) { - status = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: if (!server_key) { - status = memcached_touch(m_obj->memc, key->val, key->len, expiration); + status = memcached_touch(intern->memc, key->val, key->len, expiration); } else { - status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); } break; #endif case MEMC_OP_ADD: if (!server_key) { - status = memcached_add(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_add(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_add_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_REPLACE: if (!server_key) { - status = memcached_replace(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_replace(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_replace_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_APPEND: if (!server_key) { - status = memcached_append(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_append(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_append_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_PREPEND: if (!server_key) { - status = memcached_prepend(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_prepend(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_prepend_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; @@ -1519,7 +1623,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETVAL_FALSE; } else { @@ -1559,16 +1663,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; cas = s_zval_to_uint64(zv_cas); - if (m_obj->compression) { + if (memc_user_data->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } @@ -1576,24 +1675,24 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } zend_string_release(payload); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1669,21 +1768,16 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; if (by_key) { - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); } else { - status = memcached_delete(m_obj->memc, key->val, key->len, expiration); + status = memcached_delete(intern->memc, key->val, key->len, expiration); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1713,7 +1807,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; array_init(return_value); ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { @@ -1726,13 +1820,13 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } if (by_key) { - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } else { - status = memcached_delete_by_key(m_obj->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { add_assoc_long(return_value, Z_STRVAL_P(entry), status); } else { add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); @@ -1767,12 +1861,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; if (offset < 0) { php_error_docref(NULL, E_WARNING, "offset has to be > 0"); @@ -1783,38 +1872,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); } } } else { - if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); RETURN_FALSE; } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETURN_FALSE; } @@ -1869,21 +1958,21 @@ PHP_METHOD(Memcached, addServer) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host->val, weight); - } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { + status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); } else { - status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); } #else - status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); #endif - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1910,7 +1999,7 @@ PHP_METHOD(Memcached, addServers) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { if (Z_TYPE_P(entry) != IS_ARRAY) { @@ -1957,7 +2046,7 @@ PHP_METHOD(Memcached, addServers) list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), Z_LVAL_P(z_port), weight, &status); - if (php_memc_handle_error(i_obj, status) == 0) { + if (php_memc_handle_error(intern, status) == 0) { i++; continue; } @@ -1967,9 +2056,9 @@ PHP_METHOD(Memcached, addServers) php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); } ZEND_HASH_FOREACH_END(); - status = memcached_server_push(m_obj->memc, list); + status = memcached_server_push(intern->memc, list); memcached_server_list_free(list); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1981,7 +2070,6 @@ PHP_METHOD(Memcached, addServers) Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) { - struct callbackContext context = {0}; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -1991,10 +2079,9 @@ PHP_METHOD(Memcached, getServerList) MEMC_METHOD_FETCH_OBJECT; - callbacks[0] = php_memc_do_serverlist_callback; + callbacks[0] = s_server_cursor_list_servers_cb; array_init(return_value); - context.return_value = return_value; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); + memcached_server_cursor(intern->memc, callbacks, return_value, 1); } /* }}} */ @@ -2012,16 +2099,11 @@ PHP_METHOD(Memcached, getServerByKey) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (server_key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(server_key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; - server_instance = memcached_server_by_key(m_obj->memc, server_key->val, server_key->len, &error); + server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); if (server_instance == NULL) { - php_memc_handle_error(i_obj, error); + php_memc_handle_error(intern, error); RETURN_FALSE; } @@ -2044,7 +2126,7 @@ PHP_METHOD(Memcached, resetServerList) MEMC_METHOD_FETCH_OBJECT; - memcached_servers_reset(m_obj->memc); + memcached_servers_reset(intern->memc); RETURN_TRUE; } /* }}} */ @@ -2061,7 +2143,7 @@ PHP_METHOD(Memcached, quit) MEMC_METHOD_FETCH_OBJECT; - memcached_quit(m_obj->memc); + memcached_quit(intern->memc); RETURN_TRUE; } /* }}} */ @@ -2077,7 +2159,7 @@ PHP_METHOD(Memcached, flushBuffers) } MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(memcached_flush_buffers(m_obj->memc) == MEMCACHED_SUCCESS); + RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); } /* }}} */ @@ -2094,7 +2176,7 @@ PHP_METHOD(Memcached, getLastErrorMessage) MEMC_METHOD_FETCH_OBJECT; - RETURN_STRING(memcached_last_error_message(m_obj->memc)); + RETURN_STRING(memcached_last_error_message(intern->memc)); } /* }}} */ @@ -2110,7 +2192,7 @@ PHP_METHOD(Memcached, getLastErrorCode) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(memcached_last_error(m_obj->memc)); + RETURN_LONG(memcached_last_error(intern->memc)); } /* }}} */ @@ -2126,7 +2208,7 @@ PHP_METHOD(Memcached, getLastErrorErrno) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(memcached_last_error_errno(m_obj->memc)); + RETURN_LONG(memcached_last_error_errno(intern->memc)); } /* }}} */ #endif @@ -2145,7 +2227,7 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) MEMC_METHOD_FETCH_OBJECT; - server_instance = memcached_server_get_last_disconnect(m_obj->memc); + server_instance = memcached_server_get_last_disconnect(intern->memc); if (server_instance == NULL) { RETURN_FALSE; } @@ -2156,14 +2238,81 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) } /* }}} */ +#include + +static +zend_bool s_long_value(const char *str, zend_long *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtol(str, &end, 10); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +zend_bool s_double_value(const char *str, double *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtod(str, &end); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) +{ + char *server_key; + size_t server_key_len; + zend_long long_val; + double d_val; + char *buffer; + + zval *return_value = (zval *) context; + zval *server_values; + + server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + + if (!server_values) { + zval zv; + array_init(&zv); + + server_values = &zv; + add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + } + + spprintf (&buffer, 0, "%.*s", value_length, value); + + /* Check type */ + if (s_long_value (buffer, &long_val)) { + add_assoc_long(server_values, key, long_val); + } + else if (s_double_value (buffer, &d_val)) { + add_assoc_double(server_values, key, d_val); + } + else { + add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + } + efree (buffer); + efree (server_key); + return MEMCACHED_SUCCESS; +} + /* {{{ Memcached::getStats() Returns statistics for the memcache servers */ PHP_METHOD(Memcached, getStats) { - memcached_stat_st *stats; memcached_return status; - struct callbackContext context = {0}; - memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { @@ -2172,29 +2321,12 @@ PHP_METHOD(Memcached, getStats) MEMC_METHOD_FETCH_OBJECT; - if (memcached_server_count(m_obj->memc) == 0) { - array_init(return_value); - return; - } - - stats = memcached_stat(m_obj->memc, NULL, &status); - php_memc_handle_error(i_obj, status); - if (stats == NULL) { - RETURN_FALSE; - } else if (status != MEMCACHED_SUCCESS && status != MEMCACHED_SOME_ERRORS) { - memcached_stat_free(m_obj->memc, stats); + array_init(return_value); + status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + if (php_memc_handle_error(intern, status) < 0) { + zval_ptr_dtor(return_value); RETURN_FALSE; } - - array_init(return_value); - - callbacks[0] = php_memc_do_stats_callback; - context.i = 0; - context.stats = stats; - context.return_value = return_value; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); - - memcached_stat_free(m_obj->memc, stats); } /* }}} */ @@ -2202,8 +2334,7 @@ PHP_METHOD(Memcached, getStats) Returns the version of each memcached server in the pool */ PHP_METHOD(Memcached, getVersion) { - memcached_return status = MEMCACHED_SUCCESS; - struct callbackContext context = {0}; + memcached_return rc; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -2213,28 +2344,29 @@ PHP_METHOD(Memcached, getVersion) MEMC_METHOD_FETCH_OBJECT; - array_init(return_value); - - status = memcached_version(m_obj->memc); - if (php_memc_handle_error(i_obj, status) < 0) { - zval_dtor(return_value); + rc = memcached_version(intern->memc); + if (php_memc_handle_error(intern, rc) < 0) { RETURN_FALSE; } - callbacks[0] = php_memc_do_version_callback; - context.return_value = return_value; + callbacks[0] = s_server_cursor_version_cb; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); + array_init(return_value); + rc = memcached_server_cursor(intern->memc, callbacks, return_value, 1); + if (php_memc_handle_error(intern, rc) < 0) { + zval_dtor(return_value); + RETURN_FALSE; + } } /* }}} */ /* {{{ Memcached::getAllKeys() Returns the keys stored on all the servers */ -static memcached_return php_memc_dump_func_callback(const memcached_st *ptr __attribute__((unused)), \ - const char *key, size_t key_length, void *context) +static +memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) { - zval *ctx = (zval*) context; - add_next_index_string(ctx, (char*) key); + zval *return_value = (zval*) in_context; + add_next_index_stringl(return_value, key, key_length); return MEMCACHED_SUCCESS; } @@ -2245,12 +2377,17 @@ PHP_METHOD(Memcached, getAllKeys) memcached_dump_func callback[1]; MEMC_METHOD_INIT_VARS; - callback[0] = php_memc_dump_func_callback; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + callback[0] = s_dump_keys_cb; MEMC_METHOD_FETCH_OBJECT; array_init(return_value); - rc = memcached_dump(m_obj->memc, callback, return_value, 1); - if (php_memc_handle_error(i_obj, rc) < 0) { + + rc = memcached_dump(intern->memc, callback, return_value, 1); + if (php_memc_handle_error(intern, rc) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2270,10 +2407,10 @@ static PHP_METHOD(Memcached, flush) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - status = memcached_flush(m_obj->memc, delay); - if (php_memc_handle_error(i_obj, status) < 0) { + status = memcached_flush(intern->memc, delay); + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -2298,17 +2435,17 @@ static PHP_METHOD(Memcached, getOption) switch (option) { case MEMC_OPT_COMPRESSION_TYPE: - RETURN_LONG(m_obj->compression_type); + RETURN_LONG(memc_user_data->compression_type); case MEMC_OPT_COMPRESSION: - RETURN_BOOL(m_obj->compression); + RETURN_BOOL(memc_user_data->compression); case MEMC_OPT_PREFIX_KEY: { memcached_return retval; char *result; - result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); + result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 RETURN_STRINGL(result, strlen(result)); @@ -2321,20 +2458,20 @@ static PHP_METHOD(Memcached, getOption) } case MEMC_OPT_SERIALIZER: - RETURN_LONG((long)m_obj->serializer); + RETURN_LONG((long)memc_user_data->serializer); break; case MEMC_OPT_USER_FLAGS: - RETURN_LONG(m_obj->set_udf_flags); + RETURN_LONG(memc_user_data->set_udf_flags); break; case MEMC_OPT_STORE_RETRY_COUNT: - RETURN_LONG((long)m_obj->store_retry_count); + RETURN_LONG((long)memc_user_data->store_retry_count); break; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: - if (memcached_server_count(m_obj->memc) == 0) { + if (memcached_server_count(intern->memc) == 0) { php_error_docref(NULL, E_WARNING, "no servers defined"); return; } @@ -2344,32 +2481,33 @@ static PHP_METHOD(Memcached, getOption) * Assume that it's a libmemcached behavior option. */ flag = (memcached_behavior) option; - result = memcached_behavior_get(m_obj->memc, flag); + result = memcached_behavior_get(intern->memc, flag); RETURN_LONG((long)result); } } /* }}} */ -static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) +static +int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; - struct memc_obj *m_obj = i_obj->obj; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); switch (option) { case MEMC_OPT_COMPRESSION: convert_to_long(value); - m_obj->compression = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression = Z_LVAL_P(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: convert_to_long(value); if (Z_LVAL_P(value) == COMPRESSION_TYPE_FASTLZ || Z_LVAL_P(value) == COMPRESSION_TYPE_ZLIB) { - m_obj->compression_type = Z_LVAL_P(value); + memc_user_data->compression_type = Z_LVAL_P(value); } else { /* invalid compression type */ - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; return 0; } break; @@ -2395,8 +2533,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) key = Z_STRVAL_P(value); #endif } - if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } @@ -2407,10 +2545,10 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) flag = (memcached_behavior) option; convert_to_long(value); - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(i_obj, rc) < 0) { - php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(intern, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2421,12 +2559,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) */ if (!Z_LVAL_P(value)) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 - (void)memcached_behavior_set_key_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution(m_obj->memc, MEMCACHED_DISTRIBUTION_MODULA); + (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); #else - m_obj->memc->hash = 0; - m_obj->memc->distribution = 0; + intern->memc->hash = 0; + intern->memc->distribution = 0; #endif } break; @@ -2437,28 +2575,28 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) /* igbinary serializer */ #ifdef HAVE_MEMCACHED_IGBINARY if (Z_LVAL_P(value) == SERIALIZER_IGBINARY) { - m_obj->serializer = SERIALIZER_IGBINARY; + memc_user_data->serializer = SERIALIZER_IGBINARY; } else #endif #ifdef HAVE_JSON_API if (Z_LVAL_P(value) == SERIALIZER_JSON) { - m_obj->serializer = SERIALIZER_JSON; + memc_user_data->serializer = SERIALIZER_JSON; } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { - m_obj->serializer = SERIALIZER_JSON_ARRAY; + memc_user_data->serializer = SERIALIZER_JSON_ARRAY; } else #endif /* msgpack serializer */ #ifdef HAVE_MEMCACHED_MSGPACK if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { - m_obj->serializer = SERIALIZER_MSGPACK; + memc_user_data->serializer = SERIALIZER_MSGPACK; } else #endif /* php serializer */ if (Z_LVAL_P(value) == SERIALIZER_PHP) { - m_obj->serializer = SERIALIZER_PHP; + memc_user_data->serializer = SERIALIZER_PHP; } else { - m_obj->serializer = SERIALIZER_PHP; - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + memc_user_data->serializer = SERIALIZER_PHP; + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "invalid serializer provided"); return 0; } @@ -2469,7 +2607,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) convert_to_long(value); if (Z_LVAL_P(value) < 0) { - m_obj->set_udf_flags = -1; + memc_user_data->set_udf_flags = -1; return 1; } @@ -2477,12 +2615,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); return 0; } - m_obj->set_udf_flags = Z_LVAL_P(value); + memc_user_data->set_udf_flags = Z_LVAL_P(value); break; case MEMC_OPT_STORE_RETRY_COUNT: convert_to_long(value); - m_obj->store_retry_count = Z_LVAL_P(value); + memc_user_data->store_retry_count = Z_LVAL_P(value); break; default: @@ -2497,15 +2635,15 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) convert_to_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); } else { rc = MEMCACHED_INVALID_ARGUMENTS; } } - if (php_memc_handle_error(i_obj, rc) < 0) { - php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(intern, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } break; @@ -2601,9 +2739,9 @@ PHP_METHOD(Memcached, setBucket) } } - rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); + rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(i_obj, rc) < 0) { + if (php_memc_handle_error(intern, rc) < 0) { retval = 0;; } @@ -2642,7 +2780,7 @@ static PHP_METHOD(Memcached, setOptions) zval copy; ZVAL_DUP(©, value); - if (!php_memc_set_option(i_obj, (long) key_index, ©)) { + if (!php_memc_set_option(intern, (long) key_index, ©)) { ok = 0; } @@ -2668,7 +2806,7 @@ static PHP_METHOD(Memcached, setOption) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(php_memc_set_option(i_obj, option, value)); + RETURN_BOOL(php_memc_set_option(intern, option, value)); } /* }}} */ @@ -2692,14 +2830,14 @@ static PHP_METHOD(Memcached, setSaslAuthData) MEMC_METHOD_FETCH_OBJECT; - if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); RETURN_FALSE; } - m_obj->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(m_obj->memc, user->val, pass->val); + memc_user_data->has_sasl_data = 1; + status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } RETURN_TRUE; @@ -2719,7 +2857,7 @@ static PHP_METHOD(Memcached, getResultCode) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(i_obj->rescode); + RETURN_LONG(intern->rescode); } /* }}} */ @@ -2735,7 +2873,7 @@ static PHP_METHOD(Memcached, getResultMessage) MEMC_METHOD_FETCH_OBJECT; - switch (i_obj->rescode) { + switch (intern->rescode) { case MEMC_RES_PAYLOAD_FAILURE: RETURN_STRING("PAYLOAD FAILURE"); break; @@ -2743,14 +2881,14 @@ static PHP_METHOD(Memcached, getResultMessage) case MEMCACHED_ERRNO: case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: case MEMCACHED_UNKNOWN_READ_FAILURE: - if (i_obj->memc_errno) { + if (intern->memc_errno) { zend_string *str = strpprintf(0, "%s: %s", - memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); + memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); RETURN_STR(str); } /* Fall through */ default: - RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode)); + RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); break; } @@ -2769,7 +2907,7 @@ static PHP_METHOD(Memcached, isPersistent) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(i_obj->is_persistent); + RETURN_BOOL(memc_user_data->is_persistent); } /* }}} */ @@ -2785,7 +2923,7 @@ static PHP_METHOD(Memcached, isPristine) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(i_obj->is_pristine); + RETURN_BOOL(intern->is_pristine); } /* }}} */ @@ -2794,40 +2932,47 @@ static PHP_METHOD(Memcached, isPristine) ****************************************/ /* {{{ constructor/destructor */ -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) +static +void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) { #if HAVE_MEMCACHED_SASL - if (m_obj->has_sasl_data) { - memcached_destroy_sasl_auth_data(m_obj->memc); + if (memc_user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); } #endif - if (m_obj->memc) { - memcached_free(m_obj->memc); - } - pefree(m_obj, persistent); + + memcached_set_memory_allocators(memc, NULL, NULL, NULL, NULL, NULL); + memcached_free(memc); + pefree(memc_user_data, memc_user_data->is_persistent); } -static void php_memc_free_storage(zend_object *obj) +static +void php_memc_object_free_storage(zend_object *object) { - php_memc_t *i_obj = php_memc_fetch_object(obj); + php_memc_object_t *intern = php_memc_fetch_object(object); - if (i_obj->obj && !i_obj->is_persistent) { - php_memc_destroy(i_obj->obj, 0); + if (intern->memc) { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + if (!memc_user_data->is_persistent) { + php_memc_destroy(intern->memc, memc_user_data); + } } - zend_object_std_dtor(&i_obj->zo); - i_obj->obj = NULL; + + intern->memc = NULL; + zend_object_std_dtor(&intern->zo); } -static zend_object *php_memc_new(zend_class_entry *ce) +static +zend_object *php_memc_object_new(zend_class_entry *ce) { - php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); - - zend_object_std_init(&i_obj->zo, ce); - object_properties_init(&i_obj->zo, ce); - - i_obj->zo.handlers = &memcached_object_handlers; - - return &i_obj->zo; + php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); + + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); + + intern->zo.handlers = &memcached_object_handlers; + return &intern->zo; } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -2860,8 +3005,8 @@ zend_object_value php_memc_server_new(zend_class_entry *ce) ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { if (res->ptr) { - struct memc_obj *m_obj = (struct memc_obj *)res->ptr; - php_memc_destroy(m_obj, 1); + memcached_st *memc = (memcached_st *) res->ptr; + php_memc_destroy(memc, memcached_get_user_data(memc)); res->ptr = NULL; } } @@ -2869,92 +3014,54 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) /* }}} */ /* {{{ internal API functions */ -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +static +memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - struct callbackContext* context = (struct callbackContext*) in_context; zval array; + zval *return_value = (zval *) in_context; array_init(&array); - add_assoc_string(&array, "host", (char*) memcached_server_name(instance)); - add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "type", memcached_server_type(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); */ - add_next_index_zval(context->return_value, &array); + add_next_index_zval(return_value, &array); return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +static +memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - char *hostport = NULL; - int hostport_len; - struct callbackContext* context = (struct callbackContext*) in_context; - zval entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - - array_init(&entry); - - add_assoc_long(&entry, "pid", context->stats[context->i].pid); - add_assoc_long(&entry, "uptime", context->stats[context->i].uptime); - add_assoc_long(&entry, "threads", context->stats[context->i].threads); - add_assoc_long(&entry, "time", context->stats[context->i].time); - add_assoc_long(&entry, "pointer_size", context->stats[context->i].pointer_size); - add_assoc_long(&entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); - add_assoc_long(&entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); - add_assoc_long(&entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); - add_assoc_long(&entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); - add_assoc_long(&entry, "curr_items", context->stats[context->i].curr_items); - add_assoc_long(&entry, "total_items", context->stats[context->i].total_items); - add_assoc_long(&entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); - add_assoc_long(&entry, "curr_connections", context->stats[context->i].curr_connections); - add_assoc_long(&entry, "total_connections", context->stats[context->i].total_connections); - add_assoc_long(&entry, "connection_structures", context->stats[context->i].connection_structures); - add_assoc_long(&entry, "bytes", context->stats[context->i].bytes); - add_assoc_long(&entry, "cmd_get", context->stats[context->i].cmd_get); - add_assoc_long(&entry, "cmd_set", context->stats[context->i].cmd_set); - add_assoc_long(&entry, "get_hits", context->stats[context->i].get_hits); - add_assoc_long(&entry, "get_misses", context->stats[context->i].get_misses); - add_assoc_long(&entry, "evictions", context->stats[context->i].evictions); - add_assoc_long(&entry, "bytes_read", context->stats[context->i].bytes_read); - add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); - add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); - - add_assoc_zval_ex(context->return_value, hostport, hostport_len, &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; -} + char *address, *version; + size_t address_len, version_len; -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - char *hostport = NULL; - char version[16]; - int hostport_len, version_len; - struct callbackContext* context = (struct callbackContext*) in_context; + zval *return_value = (zval *) in_context; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = snprintf(version, sizeof(version), "%d.%d.%d", + version_len = spprintf(&version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), memcached_server_micro_version(instance)); #else - version_len = snprintf(version, sizeof(version), "%d.%d.%d", + version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", instance->major_version, instance->minor_version, instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len, version, version_len); - efree(hostport); + address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + + efree(address); + efree(version); return MEMCACHED_SUCCESS; } -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) +static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status) { int result = 0; @@ -2964,35 +3071,25 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) case MEMCACHED_DELETED: case MEMCACHED_STAT: result = 0; - i_obj->memc_errno = 0; + intern->memc_errno = 0; break; case MEMCACHED_END: case MEMCACHED_BUFFERED: - i_obj->rescode = status; - i_obj->memc_errno = 0; + intern->rescode = status; + intern->memc_errno = 0; result = 0; break; case MEMCACHED_SOME_ERRORS: - i_obj->rescode = status; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 - i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); -#else - i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ - -#endif + intern->rescode = status; + intern->memc_errno = memcached_last_error_errno(intern->memc); result = 0; break; default: - i_obj->rescode = status; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 - i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); -#else - i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ - -#endif + intern->rescode = status; + intern->memc_errno = memcached_last_error_errno(intern->memc); result = -1; break; } @@ -3443,94 +3540,87 @@ zend_class_entry *php_memc_get_exception_base(int root) #endif } -static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, zend_string *key, zval *value) +static +memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - zend_string *payload = NULL; + memcached_return rc = MEMCACHED_SUCCESS; + int result; + zval params[4]; zval retval; - zval z_key; - zval z_val; - zval *expiration, z_expiration; + zval zv_key, ref_val; + zval ref_expiration, zv_expiration; - uint32_t flags = 0; - memcached_return rc; - php_memc_t* i_obj; - memcached_return status = MEMCACHED_SUCCESS; - int result; + /* Prepare params */ + ZVAL_STR(&zv_key, key); + + ZVAL_NULL(&ref_val); + ZVAL_NULL(&zv_expiration); - ZVAL_STR(&z_key, key); - ZVAL_NULL(&z_val); - ZVAL_NEW_REF(&z_val, value); - ZVAL_NEW_REF(&z_expiration, value); - ZVAL_LONG(Z_REFVAL(z_expiration), 0); + ZVAL_NEW_REF(&ref_val, value); + ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - ZVAL_COPY(¶ms[0], zmemc_obj); - ZVAL_COPY(¶ms[1], &z_key); - ZVAL_COPY_VALUE(¶ms[2], &z_val); - ZVAL_COPY_VALUE(¶ms[3], &z_expiration); + ZVAL_COPY(¶ms[0], zobject); + ZVAL_COPY(¶ms[1], &zv_key); + ZVAL_COPY_VALUE(¶ms[2], &ref_val); + ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); fci->retval = &retval; fci->params = params; fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_DUP(value, Z_REFVAL(ref_val)); - ZVAL_DUP(value, Z_REFVAL(z_val)); - expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - struct memc_obj *m_obj; - i_obj = Z_MEMC_OBJ_P(zmemc_obj) - m_obj = i_obj->obj; if (zend_is_true(&retval)) { - time_t expir; + time_t expiration; + zend_string *payload; + uint32_t flags = 0; + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; - expir = zval_get_long(expiration); - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + intern = Z_MEMC_OBJ_P(zobject); + memc_user_data = memcached_get_user_data(intern->memc); + + expiration = zval_get_long(Z_REFVAL(ref_expiration)); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; + rc = (memcached_return) MEMC_RES_PAYLOAD_FAILURE; } else { - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - rc = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expir, flags); - if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { - status = rc; + rc = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) { + rc = MEMCACHED_SOME_ERRORS; } zend_string_release(payload); } } else { - status = MEMCACHED_NOTFOUND; + rc = MEMCACHED_NOTFOUND; zval_dtor(value); ZVAL_NULL(value); } - - } else { - if (result == FAILURE) { - php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); - } - status = MEMCACHED_FAILURE; - zval_dtor(value); - ZVAL_NULL(value); } if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } - zval_ptr_dtor(&z_key); - zval_ptr_dtor(&z_val); - zval_ptr_dtor(&z_expiration); - zval_ptr_dtor(zmemc_obj); - - return status; + zval_ptr_dtor(&zv_key); + zval_ptr_dtor(&ref_val); + zval_ptr_dtor(&zv_expiration); + zval_ptr_dtor(&ref_expiration); + zval_ptr_dtor(zobject); + return rc; } -static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, - memcached_result_st *result) + +static +int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result) { const char *res_key = NULL; size_t res_key_len = 0; @@ -3542,7 +3632,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zval z_result; uint32_t flags = 0; int rc = 0; - php_memc_t *i_obj = NULL; + php_memc_object_t *intern = NULL; fci->retval = &retval; fci->param_count = 2; @@ -3554,10 +3644,10 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - i_obj = Z_MEMC_OBJ_P(zmemc_obj); + intern = Z_MEMC_OBJ_P(zmemc_obj); if (!s_memcached_result_to_zval(result, &value)) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -4085,6 +4175,8 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session_ini.sasl_username = NULL; php_memcached_globals->session_ini.sasl_password = NULL; + php_memcached_globals->no_effect = 0; + #endif php_memcached_globals->memc_ini.serializer_name = NULL; php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; @@ -4362,15 +4454,15 @@ PHP_MINIT_FUNCTION(memcached) zend_class_entry ce; memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - memcached_object_handlers.offset = XtOffsetOf(php_memc_t, zo); + memcached_object_handlers.offset = XtOffsetOf(php_memc_object_t, zo); memcached_object_handlers.clone_obj = NULL; - memcached_object_handlers.free_obj = php_memc_free_storage; + memcached_object_handlers.free_obj = php_memc_object_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); memcached_ce = zend_register_internal_class(&ce); - memcached_ce->create_object = php_memc_new; + memcached_ce->create_object = php_memc_object_new; #ifdef HAVE_MEMCACHED_PROTOCOL memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); diff --git a/php_memcached_private.h b/php_memcached_private.h index 46565e70..4a4dc4fe 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -176,6 +176,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) } memc_ini; + /* For deprecated values */ + zend_long no_effect; + #ifdef HAVE_MEMCACHED_PROTOCOL struct { diff --git a/php_memcached_session.c b/php_memcached_session.c index 1a398ab7..34bfc77c 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -297,6 +297,8 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_user_data(memc, user_data); memcached_server_push (memc, servers); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1); return memc; } @@ -501,6 +503,21 @@ PS_CREATE_SID_FUNC(memcached) sid = NULL; } } + + if (sid) { + if (sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id is too long to be stored in memcached"); + zend_string_release (sid); + return NULL; + } + if (MEMC_SESS_STR_INI(prefix)) { + if (strlen (MEMC_SESS_STR_INI(prefix)) + sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id with prefix is too long to be stored in memcached"); + zend_string_release (sid); + return NULL; + } + } + } return sid; } diff --git a/tests/bug_16084.phpt b/tests/bug_16084.phpt index c103b297..ba217a70 100644 --- a/tests/bug_16084.phpt +++ b/tests/bug_16084.phpt @@ -7,16 +7,14 @@ Memcached: Bug #16084 (Crash when addServers is called with an associative array $servers = array ( 0 => array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); $m = new memcached(); var_dump($m->addServers($servers)); -var_dump($m->getServerList()); +$list = $m->getServerList(); + +var_dump ($list[0]["host"], $list[0]["port"]); +echo "OK"; + ?> --EXPECT-- bool(true) -array(1) { - [0]=> - array(2) { - ["host"]=> - string(9) "localhost" - ["port"]=> - int(11211) - } -} +string(9) "localhost" +int(11211) +OK diff --git a/tests/callback_exception.phpt b/tests/callback_exception.phpt index fa149077..176163e8 100644 --- a/tests/callback_exception.phpt +++ b/tests/callback_exception.phpt @@ -40,7 +40,7 @@ try { $m = new Memcached(null, 'throw_something'); echo "fail\n"; } catch (Exception $e) { - echo "fail\n"; + echo "success\n"; } echo "OK\n"; @@ -50,4 +50,5 @@ echo "OK\n"; success success empty_cb called +success OK diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index e4ef5968..88b7d27c 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -14,41 +14,52 @@ var_dump($m->getServerList()); $m = new memcached(); $m->addServer('127.0.0.1', 11211); var_dump($m->getServerList()); + +echo "OK"; ?> ---EXPECTF-- +--EXPECT-- array(0) { } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } array(2) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } [1]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } +OK \ No newline at end of file diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index 55cbec1e..83e15ca2 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -12,6 +12,7 @@ function my_func(Memcached $obj, $persistent_id = null) $obj->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); } +$m = new Memcached('hi', 'my_func'); $m = new Memcached('hi', 'my_func'); var_dump($m->getServerList()); @@ -21,11 +22,13 @@ echo "OK\n"; --EXPECTF-- array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } OK diff --git a/tests/keys.phpt b/tests/keys.phpt index 89632f5d..927dc507 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -11,6 +11,7 @@ $binary = memc_get_instance (array ( )); $ascii = memc_get_instance (); +$ascii->setOption(Memcached::OPT_VERIFY_KEY, 1); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index 74d681dd..825bb8e2 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -7,25 +7,22 @@ if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- memcached.sess_locking = on -memcached.sess_lock_wait = 150000 memcached.sess_prefix = "memc.sess.key." -session.save_handler = memcached +session.save_handler = "memcached" --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- TRUE]); $_SESSION['foo'] = 1; diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index b8e4f5f8..21288571 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -6,26 +6,24 @@ if (!extension_loaded("memcached")) print "skip"; if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- TRUE]); +session_start(); $_SESSION['foo'] = 1; session_write_close(); $_SESSION = NULL; var_dump($_SESSION); -session_start(); +session_start([ + 'read_and_close' => true +]); var_dump($_SESSION); session_write_close(); From ecc7d8115191d2e42f8edbe28c819b899c1774f6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:11:05 +0000 Subject: [PATCH 410/694] Add tests, fix compilation error for non-sasl --- php_memcached.c | 2 ++ tests/get_flags.phpt | 65 +++++++++++++++++++++++++++++++++++ tests/session_lock.phpt | 58 +++++++++++++++++++++++++++++++ tests/session_regenerate.phpt | 26 ++++++++++++++ tests/stats.phpt | 23 +++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 tests/get_flags.phpt create mode 100644 tests/session_lock.phpt create mode 100644 tests/session_regenerate.phpt create mode 100644 tests/stats.phpt diff --git a/php_memcached.c b/php_memcached.c index 1dbe0bab..dc7d2c28 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -323,7 +323,9 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) +#if HAVE_MEMCACHED_SASL MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) +#endif MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) PHP_INI_END() /* }}} */ diff --git a/tests/get_flags.phpt b/tests/get_flags.phpt new file mode 100644 index 00000000..ef477fdc --- /dev/null +++ b/tests/get_flags.phpt @@ -0,0 +1,65 @@ +--TEST-- +Memcached::get/getMulti() flags +--SKIPIF-- + +--FILE-- +set ($key1, 'hello1', 20); +$m->set ($key2, 'hello2', 20); + +$value = $m->get($key1); +$extended = $m->get($key1, null, Memcached::GET_EXTENDED); + +var_dump ($value); +var_dump ($extended); + +$values = $m->getMulti(array ($key1, $key2), Memcached::GET_PRESERVE_ORDER); +$extended = $m->getMulti(array ($key1, $key2), Memcached::GET_EXTENDED | Memcached::GET_PRESERVE_ORDER); + +var_dump ($values); +var_dump ($extended); +echo "OK"; + +--EXPECTF-- +string(6) "hello1" +array(3) { + ["value"]=> + string(6) "hello1" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} +array(2) { + ["memc.test.%s"]=> + string(6) "hello1" + ["memc.test.%s"]=> + string(6) "hello2" +} +array(2) { + ["memc.test.%s"]=> + array(3) { + ["value"]=> + string(6) "hello1" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) + } + ["memc.test.%s"]=> + array(3) { + ["value"]=> + string(6) "hello2" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) + } +} +OK \ No newline at end of file diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt new file mode 100644 index 00000000..a328dd68 --- /dev/null +++ b/tests/session_lock.phpt @@ -0,0 +1,58 @@ +--TEST-- +Session lock +--SKIPIF-- + +--INI-- +memcached.sess_locking = true +memcached.sess_lock_wait_min = 500 +memcached.sess_lock_wait_max = 1000 +memcached.sess_lock_retries = 3 +memcached.sess_prefix = "memc.test." + +session.save_handler = memcached + +--FILE-- +addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +ob_start(); +ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); + +session_start(); +$session_id = session_id(); + +$_SESSION["test"] = "hello"; +session_write_close(); + +session_start(); +var_dump ($m->get ('memc.test.' . session_id())); +var_dump ($m->get ('memc.test.lock.' . session_id())); +session_write_close(); +var_dump ($m->get ('memc.test.lock.' . session_id())); + +// Test lock min / max +$m->set ('memc.test.lock.' . $session_id, '1'); + +$time_start = microtime(true); +session_start(); +$time = microtime(true) - $time_start; + +if (round ($time, 1) != 2.5) { + echo "Waited longer than expected: $time" . PHP_EOL; +} +echo "OK"; + +--EXPECTF-- +string(17) "test|s:5:"hello";" +string(1) "1" +bool(false) + +Warning: session_start(): Unable to clear session lock record in %s on line %d +OK diff --git a/tests/session_regenerate.phpt b/tests/session_regenerate.phpt new file mode 100644 index 00000000..794f46fc --- /dev/null +++ b/tests/session_regenerate.phpt @@ -0,0 +1,26 @@ +--TEST-- +Session regenerate +--SKIPIF-- + +--INI-- +session.save_handler = memcached +--FILE-- + +--FILE-- +getStats(); +$key = MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT; + +var_dump (count ($stats) === 1); +var_dump (isset ($stats[$key])); +var_dump (count ($stats[$key]) > 0); + +echo "OK"; +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +OK From 9ce59ef3c318e3c639c54cd433522834a436e56a Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:14:42 +0000 Subject: [PATCH 411/694] Add to package.xml --- package.xml | 4 ++++ tests/stats.phpt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/package.xml b/package.xml index e42b8037..11879322 100644 --- a/package.xml +++ b/package.xml @@ -137,6 +137,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + diff --git a/tests/stats.phpt b/tests/stats.phpt index ddd2ac4b..72b8014c 100644 --- a/tests/stats.phpt +++ b/tests/stats.phpt @@ -13,6 +13,7 @@ $key = MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT; var_dump (count ($stats) === 1); var_dump (isset ($stats[$key])); var_dump (count ($stats[$key]) > 0); +var_dump (is_int ($stats[$key]['cmd_get'])); echo "OK"; ?> @@ -20,4 +21,5 @@ echo "OK"; bool(true) bool(true) bool(true) +bool(true) OK From 782077ce575601855a169452a948077444d318e1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 23:11:11 +0000 Subject: [PATCH 412/694] Fix json serializer --- package.xml | 4 +- php_memcached.c | 187 ++++++++++++++++++------------------ php_memcached_private.h | 16 +-- php_memcached_session.c | 30 ++---- tests/types_json_multi.phpt | 2 +- 5 files changed, 112 insertions(+), 127 deletions(-) diff --git a/package.xml b/package.xml index 11879322..6c162a14 100644 --- a/package.xml +++ b/package.xml @@ -147,9 +147,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - 5.2.0 - 6.0.0 - 6.0.0 + 7.0.0 1.4.0b1 diff --git a/php_memcached.c b/php_memcached.c index dc7d2c28..cf8116a8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -50,9 +50,9 @@ #endif #ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc_ini.v) +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) #else -#define MEMC_G(v) (php_memcached_globals.memc_ini.v) +#define MEMC_G(v) (php_memcached_globals.memc.v) #endif #include @@ -285,10 +285,10 @@ PHP_INI_MH(OnUpdateSessionPrefixString) } #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ @@ -298,7 +298,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) - MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) + MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) @@ -323,9 +323,6 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) -#if HAVE_MEMCACHED_SASL - MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) -#endif MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) PHP_INI_END() /* }}} */ @@ -367,7 +364,7 @@ static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); static - zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); + zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value); static zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); @@ -377,6 +374,24 @@ static Method implementations ****************************************/ +zend_bool php_memc_init_sasl_if_needed() +{ +#if HAVE_MEMCACHED_SASL + if (MEMC_G(sasl_initialised)) { + return 1; + } + if (sasl_client_init(NULL) != SASL_OK) { + php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); + return 0; + } + return 1; +#else + php_error_docref(NULL, E_ERROR, "Memcached not built with sasl support"); + return 0; +#endif +} + + memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) { @@ -816,7 +831,7 @@ memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, } ZVAL_UNDEF(&value); - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(memc, &result, &value)) { if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; @@ -1136,9 +1151,9 @@ PHP_METHOD(Memcached, fetch) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval value; uint32_t flags = 0; uint64_t cas = 0; + zval value, zv_cas; memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1157,29 +1172,25 @@ PHP_METHOD(Memcached, fetch) RETURN_FALSE; } - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); - - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { memcached_result_free(&result); intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } array_init(return_value); - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); - if (cas != 0) { - /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(return_value, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } + + flags = memcached_result_flags(&result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *) res_key, res_key_len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); + + s_uint64_to_zval (&zv_cas, cas); + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), &zv_cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); memcached_result_free(&result); } @@ -1193,9 +1204,9 @@ PHP_METHOD(Memcached, fetchAll) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval value, entry; uint32_t flags; uint64_t cas = 0; + zval value, entry, zv_cas; memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1211,30 +1222,27 @@ PHP_METHOD(Memcached, fetchAll) memcached_result_create(intern->memc, &result); while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { memcached_result_free(&result); zval_dtor(return_value); intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } + flags = memcached_result_flags(&result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + array_init(&entry); add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); - if (cas != 0) { - /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(&entry, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } + add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); + + s_uint64_to_zval (&zv_cas, cas); + add_assoc_zval_ex(&entry, ZEND_STRL("cas"), &zv_cas); + add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_next_index_zval(return_value, &entry); } @@ -2825,8 +2833,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) return; } - if (!MEMC_G(sasl_enabled)) { - php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); + if (!php_memc_init_sasl_if_needed()) { RETURN_FALSE; } @@ -3363,7 +3370,7 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 } static -zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_value) +zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *payload, zval *return_value) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: @@ -3402,7 +3409,10 @@ zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(return_value, payload->val, payload->len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(memc); + php_json_decode(return_value, payload->val, payload->len, (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + } #else ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); @@ -3424,7 +3434,7 @@ zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_ } static -zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value) +zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value) { zend_string *data; const char *payload; @@ -3485,7 +3495,7 @@ zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_v case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - retval = s_unserialize_value (MEMC_VAL_GET_TYPE(flags), data, return_value); + retval = s_unserialize_value (memc, MEMC_VAL_GET_TYPE(flags), data, return_value); break; default: @@ -3648,7 +3658,7 @@ int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_i intern = Z_MEMC_OBJ_P(zmemc_obj); - if (!s_memcached_result_to_zval(result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, result, &value)) { intern->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -4159,37 +4169,35 @@ PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->session_ini.lock_enabled = 0; - php_memcached_globals->session_ini.lock_wait_max = 2000; - php_memcached_globals->session_ini.lock_wait_min = 1000; - php_memcached_globals->session_ini.lock_retries = 5; - php_memcached_globals->session_ini.lock_expiration = 30; - php_memcached_globals->session_ini.compression_enabled = 1; - php_memcached_globals->session_ini.binary_protocol_enabled = 1; - php_memcached_globals->session_ini.consistent_hash_enabled = 1; - php_memcached_globals->session_ini.number_of_replicas = 0; - php_memcached_globals->session_ini.server_failure_limit = 1; - php_memcached_globals->session_ini.randomize_replica_read_enabled = 1; - php_memcached_globals->session_ini.remove_failed_servers_enabled = 1; - php_memcached_globals->session_ini.connect_timeout = 1000; - php_memcached_globals->session_ini.prefix = NULL; - php_memcached_globals->session_ini.persistent_enabled = 0; - php_memcached_globals->session_ini.sasl_username = NULL; - php_memcached_globals->session_ini.sasl_password = NULL; + php_memcached_globals->session.lock_enabled = 0; + php_memcached_globals->session.lock_wait_max = 2000; + php_memcached_globals->session.lock_wait_min = 1000; + php_memcached_globals->session.lock_retries = 5; + php_memcached_globals->session.lock_expiration = 30; + php_memcached_globals->session.compression_enabled = 1; + php_memcached_globals->session.binary_protocol_enabled = 1; + php_memcached_globals->session.consistent_hash_enabled = 1; + php_memcached_globals->session.number_of_replicas = 0; + php_memcached_globals->session.server_failure_limit = 1; + php_memcached_globals->session.randomize_replica_read_enabled = 1; + php_memcached_globals->session.remove_failed_servers_enabled = 1; + php_memcached_globals->session.connect_timeout = 1000; + php_memcached_globals->session.prefix = NULL; + php_memcached_globals->session.persistent_enabled = 0; + php_memcached_globals->session.sasl_username = NULL; + php_memcached_globals->session.sasl_password = NULL; - php_memcached_globals->no_effect = 0; - -#endif - php_memcached_globals->memc_ini.serializer_name = NULL; - php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; - php_memcached_globals->memc_ini.compression_type = NULL; - php_memcached_globals->memc_ini.compression_threshold = 2000; - php_memcached_globals->memc_ini.compression_type_real = COMPRESSION_TYPE_FASTLZ; - php_memcached_globals->memc_ini.compression_factor = 1.30; - php_memcached_globals->memc_ini.store_retry_count = 2; -#if HAVE_MEMCACHED_SASL - php_memcached_globals->memc_ini.sasl_enabled = 0; #endif + php_memcached_globals->memc.serializer_name = NULL; + php_memcached_globals->memc.serializer = SERIALIZER_DEFAULT; + php_memcached_globals->memc.compression_type = NULL; + php_memcached_globals->memc.compression_threshold = 2000; + php_memcached_globals->memc.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc.compression_factor = 1.30; + php_memcached_globals->memc.store_retry_count = 2; + + php_memcached_globals->memc.sasl_initialised = 0; + php_memcached_globals->no_effect = 0; } zend_module_entry memcached_module_entry = { @@ -4385,11 +4393,11 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) /* * Serializer types. */ - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_PHP, SERIALIZER_PHP); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_PHP, SERIALIZER_PHP); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON_ARRAY, SERIALIZER_JSON_ARRAY); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types @@ -4487,15 +4495,6 @@ PHP_MINIT_FUNCTION(memcached) #ifdef HAVE_MEMCACHED_SESSION php_memc_session_minit(module_number); #endif - -#if HAVE_MEMCACHED_SASL - if (MEMC_G(sasl_enabled)) { - if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); - return FAILURE; - } - } -#endif return SUCCESS; } /* }}} */ @@ -4504,7 +4503,7 @@ PHP_MINIT_FUNCTION(memcached) PHP_MSHUTDOWN_FUNCTION(memcached) { #if HAVE_MEMCACHED_SASL - if (MEMC_G(sasl_enabled)) { + if (MEMC_G(sasl_initialised)) { sasl_done(); } #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index 4a4dc4fe..c6c0b77c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -155,8 +155,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *sasl_username; char *sasl_password; - } session_ini; - + } session; #endif struct { @@ -166,15 +165,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) double compression_factor; zend_long store_retry_count; -#if HAVE_MEMCACHED_SASL - zend_bool sasl_enabled; -#endif - /* Converted values*/ enum memcached_serializer serializer; zend_long compression_type_real; - } memc_ini; + /* Whether we have initialised sasl for this process */ + zend_bool sasl_initialised; + + } memc; /* For deprecated values */ zend_long no_effect; @@ -194,10 +192,12 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); +zend_bool php_memc_init_sasl_if_needed(); + #endif /* PHP_MEMCACHED_PRIVATE_H */ /* diff --git a/php_memcached_session.c b/php_memcached_session.c index 34bfc77c..bfb34e99 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -45,9 +45,9 @@ typedef struct { #endif #ifdef ZTS -#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session_ini.v) +#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) #else -#define MEMC_SESS_INI(v) (php_memcached_globals.session_ini.v) +#define MEMC_SESS_INI(v) (php_memcached_globals.session.v) #endif #define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) @@ -138,7 +138,7 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) switch (rc) { case MEMCACHED_SUCCESS: - user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); + user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); user_data->is_locked = 1; break; @@ -215,10 +215,13 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, MEMC_SESS_STR_INI(prefix)); } -#ifdef HAVE_MEMCACHED_SASL if (MEMC_SESS_STR_INI(sasl_username) && MEMC_SESS_STR_INI(sasl_password)) { php_memcached_user_data *user_data; + if (!php_memc_init_sasl_if_needed()) { + return 0; + } + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); if (memcached_set_sasl_auth_data(memc, MEMC_SESS_STR_INI(sasl_username), MEMC_SESS_STR_INI(sasl_password)) == MEMCACHED_FAILURE) { @@ -228,7 +231,6 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) user_data = memcached_get_user_data(memc); user_data->has_sasl_data = 1; } -#endif #undef safe_set_behavior @@ -297,7 +299,6 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_user_data(memc, user_data); memcached_server_push (memc, servers); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1); return memc; } @@ -307,6 +308,7 @@ PS_OPEN_FUNC(memcached) memcached_st *memc = NULL; char *plist_key = NULL; size_t plist_key_len = 0; + memcached_server_list_st servers; // First parse servers @@ -348,6 +350,7 @@ PS_OPEN_FUNC(memcached) if (plist_key) { efree(plist_key); } + s_destroy_mod_data(memc); PS_SET_MOD_DATA(NULL); return FAILURE; } @@ -503,21 +506,6 @@ PS_CREATE_SID_FUNC(memcached) sid = NULL; } } - - if (sid) { - if (sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id is too long to be stored in memcached"); - zend_string_release (sid); - return NULL; - } - if (MEMC_SESS_STR_INI(prefix)) { - if (strlen (MEMC_SESS_STR_INI(prefix)) + sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id with prefix is too long to be stored in memcached"); - zend_string_release (sid); - return NULL; - } - } - } return sid; } diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt index 5535abb8..6a085039 100644 --- a/tests/types_json_multi.phpt +++ b/tests/types_json_multi.phpt @@ -3,7 +3,7 @@ Memcached multi store & multi fetch type and value correctness using JSON serial --SKIPIF-- --FILE-- Date: Mon, 1 Feb 2016 01:12:26 +0000 Subject: [PATCH 413/694] Fix serializers --- .travis/travis.sh | 18 +++++++++--------- php_memcached.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 131e38bf..1eab43fb 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git - pushd igbinary + git clone https://github.com/igbinary/igbinary7.git + pushd igbinary7 phpize ./configure make @@ -79,7 +79,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php7 + git checkout php7 phpize ./configure make @@ -152,9 +152,9 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag - make + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary + make make install popd } @@ -184,7 +184,7 @@ function run_memcached_tests() { rm ./tests/expire.phpt # Run normal tests - php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php --show-diff -d extension=modules/memcached.so -d extension=msgpack.so -d extension=igbinary.so -n ./tests/*.phpt retval=$? popd return $retval; @@ -236,10 +236,10 @@ case $ACTION in install_libmemcached # Install igbinary extension - # install_igbinary + install_igbinary # install msgpack - # install_msgpack + install_msgpack install_memcached run_memcached diff --git a/php_memcached.c b/php_memcached.c index cf8116a8..a8d9605b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3187,11 +3187,18 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &(buf->s), &buf->s->len, value) != 0) { + { + uint8_t *buffer; + size_t buffer_len; + + if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } + smart_str_appendl (buf, buffer, buffer_len); + efree(buffer); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); + } break; #endif @@ -3395,7 +3402,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *) payload->val, payload->len, &value)) { + if (igbinary_unserialize((uint8_t *) payload->val, payload->len, return_value)) { ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; From cf4d0ead4fcccbfd86cfd2ff1e0278d9c463f470 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:34:03 +0000 Subject: [PATCH 414/694] Update package.xml for release along with memcached.ini --- memcached.ini | 31 +++++++++++++------------------ package.xml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/memcached.ini b/memcached.ini index 1996eb27..1aa9f266 100644 --- a/memcached.ini +++ b/memcached.ini @@ -4,19 +4,19 @@ ; the default is On memcached.sess_locking = On -; Session spin lock retry wait time in microseconds. -; Be carefull when setting this value. -; Valid values are integers, where 0 is interpreted as -; the default value. Negative values result in a reduces -; locking to a try lock. -; the default is 150000 -memcached.sess_lock_wait = 150000 - -; The maximum time, in seconds, to wait for a session lock -; before timing out. -; Setting to 0 results in default behavior, which is to -; use max_execution_time. -memcached.sess_lock_max_wait = 0; +; !! DEPRECATED AND REMOVED in 3.x !! +; memcached.sess_lock_wait = 150000 + +; !! DEPRECATED AND REMOVED in 3.x !! +; memcached.sess_lock_max_wait = 0; + +; The minimum time, in milliseconds, to wait between session lock attempts. +; This value is double on each lock retry until memcached.sess_lock_wait_max +; is reached +memcached.sess_lock_wait_min = 0; + +; The maximum time, in milliseconds, to wait between session lock attempts. +memcached.sess_lock_wait_max = 0; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to @@ -105,11 +105,6 @@ memcached.compression_threshold = 2000 ; The default is igbinary if available, then msgpack if available, then php otherwise. memcached.serializer = "igbinary" -; Use SASL authentication for connections -; valid values: On, Off -; the default is Off -memcached.use_sasl = Off - ; The amount of retries for failed store commands. ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server diff --git a/package.xml b/package.xml index 6c162a14..39175882 100644 --- a/package.xml +++ b/package.xml @@ -159,6 +159,42 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + beta + beta + + + 3.0.0 + 3.0.0 + + 2016-02-01 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * set/get commands do not take cas or user flags parameters + * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + +Session handler + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several broken tests + + + + stablestable 2.2.02.2.0 From a93ff86f7c94b811a8bf5c69f8b576c2d08acc29 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:37:36 +0000 Subject: [PATCH 415/694] More package.xml / version updates --- package.xml | 12 ++++++------ php_memcached.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 39175882..29c617e7 100644 --- a/package.xml +++ b/package.xml @@ -21,14 +21,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2014-04-01 + 2016-02-01 - 2.2.0 - 2.2.0 + 3.0.0b1 + 3.0.0 - stable - stable + beta + beta PHP @@ -165,7 +165,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta - 3.0.0 + 3.0.0b1 3.0.0 2016-02-01 diff --git a/php_memcached.h b/php_memcached.h index b96ef37a..9e466cb4 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "2.2.0" +#define PHP_MEMCACHED_VERSION "3.0.0b1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 938f6bcf68ff5cf07884cbf4963336c3e8fe7f2f Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:40:17 +0000 Subject: [PATCH 416/694] Update right place in package.xml --- package.xml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 29c617e7..d2088a12 100644 --- a/package.xml +++ b/package.xml @@ -32,7 +32,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Added the OPT_SERVER_TIMEOUT_LIMIT behaviour +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * set/get commands do not take cas or user flags parameters + * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + +Session handler + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several broken tests @@ -191,10 +211,8 @@ Session handler Tests * Fix several broken tests - - stablestable 2.2.02.2.0 From a930b41fa138a55b976c55e21157e57b09355343 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 6 Feb 2016 05:07:52 +0000 Subject: [PATCH 417/694] Fixes memory errors, broken code, bugs etc --- package.xml | 1 + php_libmemcached_compat.c | 40 +- php_libmemcached_compat.h | 2 +- php_memcached.c | 4235 +++++++++++++++---------------- php_memcached_private.h | 29 +- tests/getdelayed.phpt | 37 +- tests/incrdecr_invalid_key.phpt | 1 + 7 files changed, 2128 insertions(+), 2217 deletions(-) diff --git a/package.xml b/package.xml index d2088a12..9d3be440 100644 --- a/package.xml +++ b/package.xml @@ -202,6 +202,7 @@ API * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and in case of too large values they overflow to strings Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index f49b162b..bd35d8fe 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -18,36 +18,20 @@ #include "php_memcached_private.h" #include "php_libmemcached_compat.h" -memcached_st *php_memc_create_str (const char *str, size_t str_len) +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) { -#ifdef HAVE_LIBMEMCACHED_MEMCACHED - return memcached (str, str_len); +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); #else - memcached_return rc; - memcached_st *memc; - memcached_server_st *servers; - - memc = memcached_create(NULL); - - if (!memc) { - return NULL; - } - - servers = memcached_servers_parse (str); - - if (!servers) { - memcached_free (memc); - return NULL; + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); } - - rc = memcached_server_push (memc, servers); - memcached_server_free (servers); - - if (rc != MEMCACHED_SUCCESS) { - memcached_free (memc); - return NULL; - } - return memc; + return rc; #endif } - diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index ae400d9c..e740d310 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -20,7 +20,7 @@ /* this is the version(s) we support */ #include -memcached_st *php_memc_create_str (const char *str, size_t str_len); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000 # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) diff --git a/php_memcached.c b/php_memcached.c index a8d9605b..c01b7f94 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -27,6 +27,9 @@ #include "php_memcached_server.h" #include "g_fmt.h" +#include +#include + #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" #endif @@ -55,8 +58,14 @@ #define MEMC_G(v) (php_memcached_globals.memc.v) #endif -#include + static + int le_memc; +static +int php_memc_list_entry(void) +{ + return le_memc; +} /**************************************** Custom options @@ -113,30 +122,34 @@ /**************************************** "get" operation flags ****************************************/ -#define MEMC_GET_PRESERVE_ORDER (1<<0) -#define MEMC_GET_EXTENDED (2<<0) +#define MEMC_GET_PRESERVE_ORDER 1 +#define MEMC_GET_EXTENDED 2 /**************************************** Helper macros ****************************************/ - - #define RETURN_FROM_GET RETURN_FALSE /**************************************** Structures and definitions ****************************************/ -enum memcached_compression_type { - COMPRESSION_TYPE_ZLIB = 1, - COMPRESSION_TYPE_FASTLZ = 2, -}; + +typedef enum { + MEMC_OP_SET, + MEMC_OP_TOUCH, + MEMC_OP_ADD, + MEMC_OP_REPLACE, + MEMC_OP_APPEND, + MEMC_OP_PREPEND +} php_memc_write_op; typedef struct { zend_bool is_persistent; - zend_bool compression; - enum memcached_serializer serializer; - enum memcached_compression_type compression_type; + zend_bool compression_enabled; + + zend_long serializer; + zend_long compression_type; zend_long store_retry_count; zend_long set_udf_flags; @@ -144,10 +157,8 @@ typedef struct { #if HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif - } php_memc_user_data_t; - typedef struct { memcached_st *memc; zend_bool is_pristine; @@ -156,6 +167,22 @@ typedef struct { zend_object zo; } php_memc_object_t; +typedef struct { + size_t num_valid_keys; + + const char **mkeys; + size_t *mkeys_len; + + zend_string **strings; + +} php_memc_keys_t; + +typedef struct { + zval *object; + zend_fcall_info fci; + zend_fcall_info_cache fcc; +} php_memc_result_callback_ctx_t; + static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { return (php_memc_object_t *)((char *)obj - XtOffsetOf(php_memc_object_t, zo)); } @@ -184,15 +211,6 @@ typedef struct { #endif -enum { - MEMC_OP_SET, - MEMC_OP_TOUCH, - MEMC_OP_ADD, - MEMC_OP_REPLACE, - MEMC_OP_APPEND, - MEMC_OP_PREPEND -}; - static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; @@ -217,11 +235,11 @@ ZEND_GET_MODULE(memcached) static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; + MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(new_value->val, "fastlz")) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; + MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(new_value->val, "zlib")) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_ZLIB; + MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; } @@ -231,22 +249,22 @@ static PHP_INI_MH(OnUpdateCompressionType) static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { - MEMC_G(serializer) = SERIALIZER_DEFAULT; + MEMC_G(serializer_type) = SERIALIZER_DEFAULT; } else if (!strcmp(new_value->val, "php")) { - MEMC_G(serializer) = SERIALIZER_PHP; + MEMC_G(serializer_type) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY } else if (!strcmp(new_value->val, "igbinary")) { - MEMC_G(serializer) = SERIALIZER_IGBINARY; + MEMC_G(serializer_type) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API } else if (!strcmp(new_value->val, "json")) { - MEMC_G(serializer) = SERIALIZER_JSON; + MEMC_G(serializer_type) = SERIALIZER_JSON; } else if (!strcmp(new_value->val, "json_array")) { - MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; + MEMC_G(serializer_type) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK } else if (!strcmp(new_value->val, "msgpack")) { - MEMC_G(serializer) = SERIALIZER_MSGPACK; + MEMC_G(serializer_type) = SERIALIZER_MSGPACK; #endif // msgpack } else { return FAILURE; @@ -300,7 +318,6 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) - MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) @@ -319,7 +336,7 @@ PHP_INI_BEGIN() #endif - MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) + MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name) MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) @@ -333,8 +350,6 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status); - static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -345,10 +360,19 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* Invoke PHP functions */ static - memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + +/* Iterate result sets */ +typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); + +static +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context); static - int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); +zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, + php_memc_keys_t *keys, php_memc_result_apply_fn result_apply_fn, + zend_bool with_cas, void *context); + /* Callback functions for different server list iterations */ static @@ -357,8 +381,8 @@ static static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -/* Callback for dumping all keys to zval */ - +static + zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, zend_string *server_key, zend_string *key, zval *value, time_t expiration); static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); @@ -367,11 +391,17 @@ static zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value); static - zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); + zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t *flags); + +static + void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value); + +static + void s_clear_keys(php_memc_keys_t *keys); /**************************************** - Method implementations + Exported helper functions ****************************************/ zend_bool php_memc_init_sasl_if_needed() @@ -391,27 +421,6 @@ zend_bool php_memc_init_sasl_if_needed() #endif } - - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) -{ -#ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); -#else - memcached_return rc = MEMCACHED_SUCCESS; - uint32_t flags = 0; - size_t value_length = 0; - char *value = NULL; - - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); - if (value) { - free (value); - } - return rc; -#endif -} - - char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; @@ -429,1646 +438,1558 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ return buffer; } + +/**************************************** + Handling error codes +****************************************/ + static -zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) +zend_bool s_memcached_return_is_error(memcached_return status, zend_bool strict) { - zend_bool ret = 1; - zval retval, id; - - if (persistent_id) { - ZVAL_STR(&id, persistent_id); - } else { - ZVAL_NULL(&id); - } + zend_bool result = 0; - ZVAL_UNDEF(&retval); + switch (status) { + case MEMCACHED_SUCCESS: + case MEMCACHED_STORED: + case MEMCACHED_DELETED: + case MEMCACHED_STAT: + case MEMCACHED_END: + case MEMCACHED_BUFFERED: + result = 0; + break; - zend_fcall_info_argn(fci, 2, object, &id); - fci->retval = &retval; - fci->no_separation = 1; + case MEMCACHED_SOME_ERRORS: + result = strict; + break; - if (zend_call_function(fci, fci_cache) == FAILURE) { - char *buf = php_memc_printable_func (fci, fci_cache); - php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); - efree (buf); - ret = 0; + default: + result = 1; + break; } + return result; +} - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } +static +int s_memc_status_handle_result_code(php_memc_object_t *intern, memcached_return status) +{ + intern->rescode = status; + intern->memc_errno = 0; - if (EG(exception)) { - ret = 0; + if (s_memcached_return_is_error(status, 1)) { + intern->memc_errno = memcached_last_error_errno(intern->memc); + return FAILURE; } - - zend_fcall_info_args_clear(fci, 1); - return ret; + return SUCCESS; } static - int le_memc; +void s_memc_set_status(php_memc_object_t *intern, memcached_return status, int memc_errno) +{ + intern->rescode = status; + intern->memc_errno = memc_errno; +} static -int php_memc_list_entry(void) +zend_bool s_memc_status_has_error(php_memc_object_t *intern) { - return le_memc; + return s_memcached_return_is_error(intern->rescode, 1); } -/* {{{ Memcached::__construct([string persistent_id[, callback on_new[, string connection_str]]])) - Creates a Memcached object, optionally using persistent memcache connection */ -static PHP_METHOD(Memcached, __construct) +static +zend_bool s_memc_status_has_result_code(php_memc_object_t *intern, memcached_return status) { - php_memc_object_t *intern; - php_memc_user_data_t *memc_user_data; - - zend_string *persistent_id = NULL; - zend_string *conn_str = NULL; - zend_string *plist_key = NULL; - zend_fcall_info fci = {0}; - zend_fcall_info_cache fci_cache; + return intern->rescode == status; +} - zend_bool is_persistent = 0; +/**************************************** + Marshall cas tokens +****************************************/ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - return; +static +void s_uint64_to_zval (zval *target, uint64_t value) +{ + if (value >= ((uint64_t) LONG_MAX)) { + char *buffer; +#ifdef PRIu64 + spprintf (&buffer, 0, "%" PRIu64, value); +#else + /* Best effort */ + spprintf (&buffer, 0, "%llu", value); +#endif + ZVAL_STRING (target, buffer); + efree(buffer); + } + else { + ZVAL_LONG (target, (zend_long) value); } +} - intern = Z_MEMC_OBJ_P(getThis()); - intern->is_pristine = 1; +static +uint64_t s_zval_to_uint64 (zval *cas) +{ + switch (Z_TYPE_P (cas)) { + case IS_LONG: + return (uint64_t) zval_get_long (cas); + break; - if (persistent_id && persistent_id->len) { - zend_resource *le; + case IS_DOUBLE: + if (Z_DVAL_P (cas) < 0.0) + return 0; - plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + return (uint64_t) zval_get_double (cas); + break; - if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { - if (le->type == php_memc_list_entry()) { - intern->memc = le->ptr; - intern->is_pristine = 0; - zend_string_release (plist_key); - return; + case IS_STRING: + { + uint64_t val; + char *end; + + errno = 0; + val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + + if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { + php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); + return 0; } + return val; } - is_persistent = 1; + break; } + return 0; +} - if (conn_str && conn_str->len > 0) { - intern->memc = memcached (conn_str->val, conn_str->len); - } - else { - intern->memc = memcached (NULL, 0); - } - if (!intern->memc) { - // TODO: handle allocation fail - } +/**************************************** + Iterate over memcached results and mget +****************************************/ - memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); - memc_user_data->serializer = MEMC_G(serializer); - memc_user_data->compression_type = MEMC_G(compression_type_real); - memc_user_data->compression = 1; - memc_user_data->store_retry_count = MEMC_G(store_retry_count); - memc_user_data->set_udf_flags = -1; - memc_user_data->is_persistent = is_persistent; +static +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context) +{ + memcached_result_st result, *result_ptr; + memcached_return rc, status = MEMCACHED_SUCCESS; - memcached_set_user_data(intern->memc, memc_user_data); + memcached_result_create(intern->memc, &result); - if (fci.size) { - if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } - /* - Setting intern->memc null prevents object destruction from freeing the memcached_st - We free it manually here because it might be persistent and has not been - registered to persistent_list yet - */ - php_memc_destroy(intern->memc, memc_user_data); - intern->memc = NULL; - return; + do { + result_ptr = memcached_fetch_result(intern->memc, &result, &rc); + + if (s_memcached_return_is_error(rc, 0)) { + status = rc; } - } - if (plist_key) { - zend_resource le; + /* nothing returned */ + if (!result_ptr) { + break; + } + else { + zend_string *key; + zval zv_value, zv_cas; + zend_bool retval; - le.type = php_memc_list_entry(); - le.ptr = intern->memc; + uint64_t cas; + uint32_t flags; - GC_REFCOUNT(&le) = 1; + const char *res_key; + size_t res_key_len; + - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - zend_string_release(plist_key); - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ - } - zend_string_release(plist_key); - } + ZVAL_UNDEF(&zv_value); + if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { + if (Z_TYPE(zv_value) != IS_UNDEF) { + zval_ptr_dtor(&zv_value); + } + if (EG(exception)) { + status = MEMC_RES_PAYLOAD_FAILURE; + memcached_quit(intern->memc); + break; + } + status = MEMCACHED_SOME_ERRORS; + continue; + } + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + flags = memcached_result_flags(&result); -#if 0 - m_obj = pecalloc(1, sizeof(*m_obj), intern->is_persistent); - if (m_obj == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); - /* not reached */ - } + s_uint64_to_zval(&zv_cas, cas); - if (conn_str) { - intern->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!intern->memc) { - char error_buffer[1024]; - if (plist_key) { - zend_string_release(plist_key); - } -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - } -#else - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); -#endif - /* not reached */ - } - } else { - intern->memc = memcached_create(NULL); - if (intern->memc == NULL) { - if (plist_key) { - zend_string_release(plist_key); + key = zend_string_init (res_key, res_key_len, 0); + retval = result_apply_fn(intern, key, &zv_value, &zv_cas, flags, context); + + zend_string_release (key); + zval_ptr_dtor(&zv_value); + zval_ptr_dtor(&zv_cas); + + /* Stop iterating on false */ + if (!retval) { + /* Make sure we clear our results */ + while (memcached_fetch_result(intern->memc, &result, &rc)) {} + break; } - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - /* not reached */ } - } + } while (result_ptr != NULL); + memcached_result_free(&result); + return status; +} +static +zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, php_memc_keys_t *keys, + php_memc_result_apply_fn result_apply_fn, zend_bool with_cas, void *context) +{ + memcached_return status; + memcached_result_st result; + int mget_status; + uint64_t orig_cas_flag = 0; - intern->obj = m_obj; - intern->is_pristine = 1; + // Reset status code + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } + if (!keys->num_valid_keys) { + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; + return 0; + } - intern->obj = NULL; - if (intern->is_persistent) { - php_memc_destroy(m_obj, intern->is_persistent); - } + if (with_cas) { + orig_cas_flag = memcached_behavior_get (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - return; + if (!orig_cas_flag) { + memcached_behavior_set (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } - if (intern->is_persistent) { - zend_resource le; + if (server_key) { + status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + } else { + status = memcached_mget(intern->memc, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + } - le.type = php_memc_list_entry(); - le.ptr = m_obj; - GC_REFCOUNT(&le) = 1; - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ - } + /* Need to handle result code before restoring cas flags, would mess up errno */ + mget_status = s_memc_status_handle_result_code(intern, status); + + if (with_cas && !orig_cas_flag) { + memcached_behavior_set (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } - if (plist_key) { - zend_string_release(plist_key); + /* Return on failure codes */ + if (mget_status == FAILURE) { + return 0; } -#endif -} -/* }}} */ -static -void s_uint64_to_zval (zval *target, uint64_t value) -{ - if (value >= LONG_MAX) { - char *buffer; -#ifdef PRIu64 - spprintf (&buffer, 0, "%" PRIu64, value); -#else - /* Best effort */ - spprintf (&buffer, 0, "%llu", value); -#endif - ZVAL_STRING (target, buffer); - efree(buffer); + if (!result_apply_fn) { + /* no callback, for example getDelayed */ + return 1; } - else { - ZVAL_LONG (target, (zend_long) value); + + status = php_memc_result_apply(intern, result_apply_fn, context); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + return 0; } + + return 1; } +/**************************************** + Invoke callbacks +****************************************/ + static -uint64_t s_zval_to_uint64 (zval *cas) +zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { - switch (Z_TYPE_P (cas)) { - case IS_LONG: - return (uint64_t) zval_get_long (cas); - break; + zend_bool ret = 1; + zval retval, id; - case IS_DOUBLE: - if (Z_DVAL_P (cas) < 0.0) - return 0; + if (persistent_id) { + ZVAL_STR(&id, persistent_id); + } else { + ZVAL_NULL(&id); + } - return (uint64_t) zval_get_double (cas); - break; + ZVAL_UNDEF(&retval); - case IS_STRING: - { - uint64_t val; - char *end; + zend_fcall_info_argn(fci, 2, object, &id); + fci->retval = &retval; + fci->no_separation = 1; - errno = 0; - val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + if (zend_call_function(fci, fci_cache) == FAILURE) { + char *buf = php_memc_printable_func (fci, fci_cache); + php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); + efree (buf); + ret = 0; + } - if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { - php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); - return 0; - } - return val; - } - break; + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); } - return 0; -} + if (EG(exception)) { + ret = 0; + } -typedef struct { + zend_fcall_info_args_clear(fci, 1); + return ret; +} - size_t num_valid_keys; +static +zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) +{ + memcached_return rc; + zend_bool status = 0; - const char **mkeys; - size_t *mkeys_len; + zval params[4]; + zval retval; + zval zv_key, ref_val; + zval ref_expiration, zv_expiration; + php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject); - zend_string **strings; + /* Prepare params */ + ZVAL_STR(&zv_key, key); -} php_memcached_keys; + ZVAL_NULL(&ref_val); + ZVAL_NULL(&zv_expiration); -static -void s_hash_to_keys(php_memcached_keys *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) -{ - size_t idx = 0, alloc_count; - zval *zv; + ZVAL_NEW_REF(&ref_val, value); + ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - keys_out->num_valid_keys = 0; + ZVAL_COPY(¶ms[0], zobject); + ZVAL_COPY(¶ms[1], &zv_key); + ZVAL_COPY_VALUE(¶ms[2], &ref_val); + ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); - alloc_count = zend_hash_num_elements(hash_in); - if (!alloc_count) { - return; - } - keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); - keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); - keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); + fci->retval = &retval; + fci->params = params; + fci->param_count = 4; - ZEND_HASH_FOREACH_VAL(hash_in, zv) { - zend_string *key = zval_get_string(zv); + ZVAL_UNDEF(&retval); - if (preserve_order && return_value) { - add_assoc_null_ex(return_value, key->val, key->len); + if (zend_call_function(fci, fcc) == SUCCESS) { + if (zend_is_true(&retval)) { + time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(ref_val), expiration); + ZVAL_DUP(value, Z_REFVAL(ref_val)); } + } + else { + s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); + } - if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { - keys_out->mkeys[idx] = key->val; - keys_out->mkeys_len[idx] = key->len; - keys_out->strings[idx] = key; - idx++; - } - else { - zend_string_release (key); - } - } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(zobject); + zval_ptr_dtor(&zv_key); + zval_ptr_dtor(&ref_val); + zval_ptr_dtor(&ref_expiration); - if (!idx) { - efree (keys_out->mkeys); - efree (keys_out->mkeys_len); - efree (keys_out->strings); + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); } - keys_out->num_valid_keys = idx; + return status; } -static -void s_clear_keys(php_memcached_keys *keys) -{ - size_t i; - for (i = 0; i < keys->num_valid_keys; i++) { - zend_string_release (keys->strings[i]); - } - efree(keys->strings); - efree(keys->mkeys); - efree(keys->mkeys_len); -} +/**************************************** + Wrapper for setting from zval +****************************************/ static -memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, zend_string *server_key, zend_long get_flags, zval *return_value) +zend_bool s_compress_value (php_memc_compression_type compression_type, zend_string **payload_in, uint32_t *flags) { - php_memcached_keys keys = { 0 }; - zval values; - memcached_return rc, status = MEMCACHED_SUCCESS; - uint64_t orig_cas_flag; - memcached_result_st result; + /* status */ + zend_bool compress_status = 0; + zend_string *payload = *payload_in; - zend_bool extended = (get_flags & MEMC_GET_EXTENDED); - zend_bool preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); + /* Additional 5% for the data */ + size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + char *buffer = emalloc(buffer_size); - array_init(&values); - s_hash_to_keys(&keys, hash_keys, preserve_order, &values); + /* Store compressed size here */ + size_t compressed_size = 0; + uint32_t original_size = payload->len; - if (!keys.num_valid_keys) { - zval_ptr_dtor(&values); - return MEMCACHED_NO_KEY_PROVIDED; - } + switch (compression_type) { - orig_cas_flag = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); + case COMPRESSION_TYPE_FASTLZ: + { + compressed_size = fastlz_compress(payload->val, payload->len, buffer); - if (extended && !orig_cas_flag) { - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); - } + if (compressed_size > 0) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + } + } + break; - if (server_key) { - status = memcached_mget_by_key(memc, server_key->val, server_key->len, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); - } else { - status = memcached_mget(memc, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); - } + case COMPRESSION_TYPE_ZLIB: + { + compressed_size = buffer_size; + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); - s_clear_keys(&keys); + if (status == Z_OK) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + } + } + break; - if (extended && !orig_cas_flag) { - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 0); + default: + compress_status = 0; + break; } - memcached_result_create(memc, &result); - while ((memcached_fetch_result(memc, &result, &rc)) != NULL) { - - const char *res_key = NULL; - size_t res_key_len = 0; - zval value; - - /* For some reason instead of success it's end */ - if (rc == MEMCACHED_END) { - rc = MEMCACHED_SUCCESS; - } - - if (rc != MEMCACHED_SUCCESS) { - status = rc; - continue; - } + if (!compress_status) { + php_error_docref(NULL, E_WARNING, "could not compress value"); + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + efree (buffer); + return 0; + } - ZVAL_UNDEF(&value); - if (!s_memcached_result_to_zval(memc, &result, &value)) { - if (EG(exception)) { - status = MEMC_RES_PAYLOAD_FAILURE; + /* This means the value was too small to be compressed, still a success */ + if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + efree (buffer); + return 1; + } - memcached_result_free(&result); - memcached_quit(memc); - zval_ptr_dtor (&values); - break; - } - status = MEMCACHED_SOME_ERRORS; - continue; - } + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); + /* Copy the uin32_t at the beginning */ + memcpy(payload->val, &original_size, sizeof(uint32_t)); + memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); - if (extended) { - uint32_t flags; - uint64_t cas; - zval cas_token, node; + zend_string_forget_hash_val(payload); + *payload_in = payload; + return 1; +} - cas = memcached_result_cas(&result); - flags = memcached_result_flags(&result); +static +zend_bool s_serialize_value (php_memc_serializer_type serializer, zval *value, smart_str *buf, uint32_t *flags) +{ + switch (serializer) { - s_uint64_to_zval (&cas_token, cas); + /* + Igbinary serialization + */ +#ifdef HAVE_MEMCACHED_IGBINARY + case SERIALIZER_IGBINARY: + { + uint8_t *buffer; + size_t buffer_len; - array_init (&node); - add_assoc_zval (&node, "value", &value); - add_assoc_zval (&node, "cas", &cas_token); - add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { + php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); + return 0; + } + smart_str_appendl (buf, buffer, buffer_len); + efree(buffer); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); + } + break; +#endif - add_assoc_zval_ex(&values, res_key, res_key_len, &node); + /* + JSON serialization + */ +#ifdef HAVE_JSON_API + case SERIALIZER_JSON: + case SERIALIZER_JSON_ARRAY: + { + php_json_encode(buf, value, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } - else { - add_assoc_zval_ex(&values, res_key, res_key_len, &value); + break; +#endif + + /* + msgpack serialization + */ +#ifdef HAVE_MEMCACHED_MSGPACK + case SERIALIZER_MSGPACK: + php_msgpack_serialize(buf, value); + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; +#endif + + /* + PHP serialization + */ + default: + { + php_serialize_data_t var_hash; + PHP_VAR_SERIALIZE_INIT(var_hash); + php_var_serialize(buf, value, &var_hash); + PHP_VAR_SERIALIZE_DESTROY(var_hash); + + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); } + break; } - memcached_result_free(&result); - if (Z_TYPE(values) != IS_UNDEF) { - ZVAL_ZVAL(return_value, &values, 0, 0); + /* Check for exceptions caused by serializers */ + if (EG(exception) && buf->s->len) { + return 0; } - return status; + return 1; } - static -void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t *flags) { - zend_long get_flags = 0; - zend_string *key; - zend_string *server_key = NULL; - memcached_return status = MEMCACHED_SUCCESS; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; - HashTable keys; - zval values, tmp; - MEMC_METHOD_INIT_VARS; + zend_string *payload; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + zend_bool should_compress = memc_user_data->compression_enabled; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { - return; + switch (Z_TYPE_P(value)) { + + case IS_STRING: + payload = zval_get_string(value); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); + break; + + case IS_LONG: + { + smart_str buffer = {0}; + smart_str_append_long (&buffer, Z_LVAL_P(value)); + smart_str_0(&buffer); + payload = buffer.s; + + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + should_compress = 0; } - } + break; - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + case IS_DOUBLE: + { + char buffer[40]; + php_memcached_g_fmt(buffer, Z_DVAL_P(value)); + payload = zend_string_init (buffer, strlen (buffer), 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + should_compress = 0; + } + break; - zend_hash_init (&keys, 1, 0, NULL, 0); - ZVAL_STR(&tmp, key); - zend_hash_add(&keys, key, &tmp); + case IS_TRUE: + payload = zend_string_init ("1", 1, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + should_compress = 0; + break; - ZVAL_UNDEF(&values); - status = s_memcached_get_multi(intern->memc, &keys, server_key, get_flags, &values); - zend_hash_destroy (&keys); + case IS_FALSE: + payload = zend_string_alloc (0, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + should_compress = 0; + break; - if (EG(exception)) { - zval_ptr_dtor(&values); - RETURN_FROM_GET; - } + default: + { + smart_str buffer = {0}; - if (status == MEMCACHED_SUCCESS) { - zval *zv = zend_hash_find (Z_ARRVAL(values), key); - if (zv) { - RETVAL_ZVAL(zv, 1, 0); - zval_ptr_dtor(&values); - return; - } - else { - status = MEMCACHED_NOTFOUND; + if (!s_serialize_value (memc_user_data->serializer, value, &buffer, flags)) { + smart_str_free(&buffer); + return NULL; + } + payload = buffer.s; } + break; } + zend_string_forget_hash_val(payload); - if (Z_TYPE(values) != IS_UNDEF) { - zval_ptr_dtor(&values); + /* turn off compression for values below the threshold */ + if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { + should_compress = 0; } - if (status == MEMCACHED_NOTFOUND && fci.size > 0) { - // try to invoke cache cb - status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + /* If we have compression flag, compress the value */ + if (should_compress) { + /* status */ + if (!s_compress_value (memc_user_data->compression_type, &payload, flags)) { + zend_string_release(payload); + return NULL; + } + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); } - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FROM_GET; + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(*flags, ((uint32_t) memc_user_data->set_udf_flags)); } -} -/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) - Returns a value for the given key or false */ -PHP_METHOD(Memcached, get) -{ - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + return payload; } -/* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) - Returns a value for key from the server identified by the server key or false */ -PHP_METHOD(Memcached, getByKey) +static +zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return status) { - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + if (memcached_server_count (intern->memc) == 0) { + return 0; + } + + return s_memcached_return_is_error (status, 1); } -/* }}} */ -/* {{{ -- php_memc_getMulti_impl */ -static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, zend_string *server_key, zend_string *key, zval *value, time_t expiration) { - zval *keys = NULL; - zend_string *server_key = NULL; - memcached_return rc; - zend_long flags = 0; - MEMC_METHOD_INIT_VARS; + uint32_t flags = 0; + zend_string *payload = NULL; + memcached_return status; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + zend_long retries = memc_user_data->store_retry_count; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, - &keys, &flags) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &keys, &flags) == FAILURE) { - return; + if (value) { + payload = s_zval_to_payload(intern, value, &flags); + + if (!payload) { + s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); + return 0; } } - MEMC_METHOD_FETCH_OBJECT; +#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; - rc = s_memcached_get_multi(intern->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); - php_memc_handle_error(intern, rc); + if (server_key) { + switch (op) { + case MEMC_OP_SET: + status = memc_write_using_fn_by_key(memcached_set_by_key); + break; - if (EG(exception)) { - zval_dtor(return_value); - RETURN_FALSE; - } -} -/* }}} */ + case MEMC_OP_TOUCH: + status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); + break; + + case MEMC_OP_ADD: + status = memc_write_using_fn_by_key(memcached_add_by_key); + break; + + case MEMC_OP_REPLACE: + status = memc_write_using_fn_by_key(memcached_replace_by_key); + break; + + case MEMC_OP_APPEND: + status = memc_write_using_fn_by_key(memcached_append_by_key); + break; -/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) - Returns values for the given keys or false */ -PHP_METHOD(Memcached, getMulti) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ + case MEMC_OP_PREPEND: + status = memc_write_using_fn_by_key(memcached_prepend_by_key); + break; + } -/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) - Returns values for the given keys from the server identified by the server key or false */ -PHP_METHOD(Memcached, getMultiByKey) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ + if (status == MEMCACHED_END) { + status = MEMCACHED_SUCCESS; + } + } + else { +retry: + switch (op) { + case MEMC_OP_SET: + status = memc_write_using_fn(memcached_set); + break; -/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) - Sends a request for the given keys and returns immediately */ -PHP_METHOD(Memcached, getDelayed) -{ - php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - -/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ]) - Sends a request for the given keys from the server identified by the server key and returns immediately */ -PHP_METHOD(Memcached, getDelayedByKey) -{ - php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ -- php_memc_getDelayed_impl */ -static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) -{ - zval *keys = NULL; - zend_string *server_key = NULL; - zend_bool with_cas = 0; - size_t num_keys = 0; - zval *entry = NULL; - const char **mkeys = NULL; - size_t *mkeys_len = NULL; - uint64_t orig_cas_flag = 0; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; - int i = 0; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + case MEMC_OP_TOUCH: + status = memcached_touch(intern->memc, key->val, key->len, expiration); + break; + + case MEMC_OP_ADD: + status = memc_write_using_fn(memcached_add); + break; + + case MEMC_OP_REPLACE: + status = memc_write_using_fn(memcached_replace); + break; + + case MEMC_OP_APPEND: + status = memc_write_using_fn(memcached_append); + break; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, - &keys, &with_cas, &fci, &fcc) == FAILURE) { - return; + case MEMC_OP_PREPEND: + status = memc_write_using_fn(memcached_prepend); + break; } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, - &fci, &fcc) == FAILURE) { - return; + if (status == MEMCACHED_END) { + status = MEMCACHED_SUCCESS; } } - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - /* - * Create the array of keys for libmemcached. If none of the keys were valid - * (strings), set bad key result code and return. - */ - num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); - mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); - mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } - - if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { - mkeys[i] = Z_STRVAL_P(entry); - mkeys_len[i] = Z_STRLEN_P(entry); - i++; - } - } ZEND_HASH_FOREACH_END(); - - if (i == 0) { - intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; - efree(mkeys); - efree(mkeys_len); - zval_dtor(return_value); - RETURN_FALSE; + if (s_should_retry_write (intern, status) && retries-- > 0) { + goto retry; } - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (with_cas) { - orig_cas_flag = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (orig_cas_flag == 0) { - memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); - } - } +#undef memc_write_using_fn +#undef memc_write_using_fn_by_key - /* - * Issue the request, but collect results only if the result callback is provided. - */ - if (by_key) { - status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - } else { - status = memcached_mget(intern->memc, mkeys, mkeys_len, i); + if (payload) { + zend_string_release(payload); } - /* - * Restore the CAS support flag, but only if we had to turn it on. - */ - if (with_cas && orig_cas_flag == 0) { - memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + return 0; } + return 1; +} - efree(mkeys); - efree(mkeys_len); - if (php_memc_handle_error(intern, status) < 0) { - zval_dtor(return_value); - RETURN_FALSE; - } - if (fci.size != 0) { - /* - * We have a result callback. Iterate through the result set and invoke the - * callback for each one. - */ - memcached_result_st result; +/**************************************** + Methods +****************************************/ - memcached_result_create(intern->memc, &result); - while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { - if (s_invoke_result_callback(getThis(), &fci, &fcc, &result) < 0) { - status = MEMCACHED_FAILURE; - break; - } - } - memcached_result_free(&result); - /* we successfully retrieved all rows */ - if (status == MEMCACHED_END) { - status = MEMCACHED_SUCCESS; - } - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } - } +/* {{{ Memcached::__construct([string persistent_id[, callback on_new[, string connection_str]]])) + Creates a Memcached object, optionally using persistent memcache connection */ +static PHP_METHOD(Memcached, __construct) +{ + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; - RETURN_TRUE; -} -/* }}} */ + zend_string *persistent_id = NULL; + zend_string *conn_str = NULL; + zend_string *plist_key = NULL; + zend_fcall_info fci = {0}; + zend_fcall_info_cache fci_cache; -/* {{{ Memcached::fetch() - Returns the next result from a previous delayed request */ -PHP_METHOD(Memcached, fetch) -{ - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - zval value, zv_cas; - memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + zend_bool is_persistent = 0; - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + intern = Z_MEMC_OBJ_P(getThis()); + intern->is_pristine = 1; - memcached_result_create(intern->memc, &result); - if ((memcached_fetch_result(intern->memc, &result, &status)) == NULL) { - php_memc_handle_error(intern, status); - memcached_result_free(&result); - RETURN_FALSE; + if (persistent_id && persistent_id->len) { + zend_resource *le; + + plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); + snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { + if (le->type == php_memc_list_entry()) { + intern->memc = le->ptr; + intern->is_pristine = 0; + zend_string_release (plist_key); + return; + } + } + is_persistent = 1; } - if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { - memcached_result_free(&result); - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; + if (conn_str && conn_str->len > 0) { + intern->memc = memcached (conn_str->val, conn_str->len); + } + else { + intern->memc = memcached (NULL, 0); } - array_init(return_value); + if (!intern->memc) { + // TODO: handle allocation fail + } + + memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); + memc_user_data->serializer = MEMC_G(serializer_type); + memc_user_data->compression_type = MEMC_G(compression_type); + memc_user_data->compression_enabled = 1; + memc_user_data->store_retry_count = MEMC_G(store_retry_count); + memc_user_data->set_udf_flags = -1; + memc_user_data->is_persistent = is_persistent; + + memcached_set_user_data(intern->memc, memc_user_data); + + if (fci.size) { + if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } + /* + Setting intern->memc null prevents object destruction from freeing the memcached_st + We free it manually here because it might be persistent and has not been + registered to persistent_list yet + */ + php_memc_destroy(intern->memc, memc_user_data); + intern->memc = NULL; + return; + } + } - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); + if (plist_key) { + zend_resource le; - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *) res_key, res_key_len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); + le.type = php_memc_list_entry(); + le.ptr = intern->memc; - s_uint64_to_zval (&zv_cas, cas); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), &zv_cas); - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + GC_REFCOUNT(&le) = 1; - memcached_result_free(&result); + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + zend_string_release(plist_key); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ + } + zend_string_release(plist_key); + } } /* }}} */ -/* {{{ Memcached::fetchAll() - Returns all the results from a previous delayed request */ -PHP_METHOD(Memcached, fetchAll) + + +static +void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval value, entry, zv_cas; - memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + size_t idx = 0, alloc_count; + zval *zv; - if (zend_parse_parameters_none() == FAILURE) { + keys_out->num_valid_keys = 0; + + alloc_count = zend_hash_num_elements(hash_in); + if (!alloc_count) { return; } + keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); + keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); + keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + ZEND_HASH_FOREACH_VAL(hash_in, zv) { + zend_string *key = zval_get_string(zv); - array_init(return_value); - memcached_result_create(intern->memc, &result); + if (preserve_order && return_value) { + add_assoc_null_ex(return_value, key->val, key->len); + } - while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { + if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = key->val; + keys_out->mkeys_len[idx] = key->len; - if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { - memcached_result_free(&result); - zval_dtor(return_value); - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; + keys_out->strings[idx] = key; + idx++; + } + else { + zend_string_release (key); } - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); + } ZEND_HASH_FOREACH_END(); - array_init(&entry); - add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); + if (!idx) { + efree (keys_out->mkeys); + efree (keys_out->mkeys_len); + efree (keys_out->strings); + } + keys_out->num_valid_keys = idx; +} - s_uint64_to_zval (&zv_cas, cas); - add_assoc_zval_ex(&entry, ZEND_STRL("cas"), &zv_cas); - add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); +static +void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) +{ + zval zv_keys; - add_next_index_zval(return_value, &entry); - } + array_init (&zv_keys); + add_next_index_stringl (&zv_keys, key->val, key->len); - memcached_result_free(&result); + s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); + zval_ptr_dtor(&zv_keys); +} - if (status != MEMCACHED_END && php_memc_handle_error(intern, status) < 0) { - zval_dtor(return_value); - RETURN_FALSE; +static +void s_clear_keys(php_memc_keys_t *keys) +{ + size_t i; + for (i = 0; i < keys->num_valid_keys; i++) { + zend_string_release (keys->strings[i]); } + efree(keys->strings); + efree(keys->mkeys); + efree(keys->mkeys_len); } -/* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration ]) - Sets the value for the given key */ -PHP_METHOD(Memcached, set) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0); -} -/* }}} */ +typedef struct { + zend_bool extended; + zval *return_value; +} php_memc_get_ctx_t; -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the server key */ -PHP_METHOD(Memcached, setByKey) +static +zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1); + php_memc_get_ctx_t *context = (php_memc_get_ctx_t *) in_context; + + if (context->extended) { + Z_TRY_ADDREF_P(value); + Z_TRY_ADDREF_P(cas); + + array_init (context->return_value); + add_assoc_zval (context->return_value, "value", value); + add_assoc_zval (context->return_value, "cas", cas); + add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + } + else { + ZVAL_ZVAL(context->return_value, value, 1, 0); + } + return 0; /* Stop after one */ } -/* }}} */ -#ifdef HAVE_MEMCACHED_TOUCH -/* {{{ Memcached::touch(string key, [, int expiration ]) - Sets a new expiration for the given key */ -PHP_METHOD(Memcached, touch) +static +void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); + php_memc_get_ctx_t context = {}; + php_memc_keys_t keys = {0}; + zend_long get_flags = 0; + zend_string *key; + zend_string *server_key = NULL; + zend_bool extended, mget_status; + memcached_return status = MEMCACHED_SUCCESS; + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + MEMC_METHOD_INIT_VARS; + + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { + return; + } + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + context.extended = (get_flags & MEMC_GET_EXTENDED); + + ZVAL_UNDEF(return_value); + context.return_value = return_value; + + s_key_to_keys(&keys, key); + mget_status = php_memc_mget_apply(intern, server_key, &keys, s_get_apply_fn, context.extended, &context); + s_clear_keys(&keys); + + if (!mget_status) { + if (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) && fci.size > 0) { + status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + + if (!status) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; + } + } + } + + if (s_memc_status_has_error(intern)) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; + } } -/* }}} */ -/* {{{ Memcached::touchbyKey(string key, [, int expiration ]) - Sets a new expiration for the given key */ -PHP_METHOD(Memcached, touchByKey) +/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) + Returns a value for the given key or false */ +PHP_METHOD(Memcached, get) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -#endif - -/* {{{ Memcached::setMulti(array items [, int expiration ]) - Sets the keys/values specified in the items array */ -PHP_METHOD(Memcached, setMulti) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) + Returns a value for key from the server identified by the server key or false */ +PHP_METHOD(Memcached, getByKey) { - php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) - Sets the keys/values specified in the items array on the server identified by the given server key */ -PHP_METHOD(Memcached, setMultiByKey) +static +zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ + php_memc_get_ctx_t *context = (php_memc_get_ctx_t *) in_context; + + Z_TRY_ADDREF_P(value); + + if (context->extended) { + zval node; + + Z_TRY_ADDREF_P(cas); + + array_init (&node); + add_assoc_zval (&node, "value", value); + add_assoc_zval (&node, "cas", cas); + add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); -#define PHP_MEMC_FAILOVER_RETRY \ - if (!by_key && retry < memc_user_data->store_retry_count) { \ - switch (intern->rescode) { \ - case MEMCACHED_HOST_LOOKUP_FAILURE: \ - case MEMCACHED_CONNECTION_FAILURE: \ - case MEMCACHED_CONNECTION_BIND_FAILURE: \ - case MEMCACHED_WRITE_FAILURE: \ - case MEMCACHED_READ_FAILURE: \ - case MEMCACHED_UNKNOWN_READ_FAILURE: \ - case MEMCACHED_PROTOCOL_ERROR: \ - case MEMCACHED_SERVER_ERROR: \ - case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: \ - case MEMCACHED_TIMEOUT: \ - case MEMCACHED_FAIL_UNIX_SOCKET: \ - case MEMCACHED_SERVER_MARKED_DEAD: \ - case MEMCACHED_SERVER_TEMPORARILY_DISABLED: \ - if (memcached_server_count(intern->memc) > 0) { \ - retry++; \ - intern->rescode = 0; \ - goto retry; \ - } \ - break; \ - } \ + add_assoc_zval_ex(context->return_value, key->val, key->len, &node); } + else { + add_assoc_zval_ex(context->return_value, key->val, key->len, value); + } + return 1; +} -/* {{{ -- php_memc_setMulti_impl */ -static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ -- php_memc_getMulti_impl */ +static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *entries; + php_memc_get_ctx_t context; + php_memc_keys_t keys_out; + + zval *keys = NULL; zend_string *server_key = NULL; - time_t expiration = 0; - zval *value; - zend_string *skey, *str_key = NULL; - ulong num_key; - zend_string *payload; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; - char tmp_key[MEMCACHED_MAX_KEY]; - int tmp_len = 0; + zend_long flags = 0; MEMC_METHOD_INIT_VARS; + zend_bool with_cas, retval, preserve_order, extended; + if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, + &keys, &flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &keys, &flags) == FAILURE) { return; } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - if (skey) { - str_key = skey; - } else if (num_key || num_key == 0) { - /* Array keys are unsigned, but php integers are signed. - * Keys must be converted to signed strings that match - * php integers. */ - assert(sizeof(tmp_key) >= sizeof(ZEND_TOSTR(LONG_MIN))); - tmp_len = sprintf(tmp_key, "%ld", (long)num_key); - str_key = zend_string_init(tmp_key, tmp_len, 0); - } else { - continue; - } + array_init(return_value); - flags = 0; - if (memc_user_data->compression) { - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); - } + preserve_order = (flags & MEMC_GET_PRESERVE_ORDER); + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), preserve_order, return_value); - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } + context.extended = (flags & MEMC_GET_EXTENDED); + context.return_value = return_value; - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - if (!skey) { - zend_string_release(str_key); - } - RETURN_FALSE; - } + retval = php_memc_mget_apply(intern, server_key, &keys_out, s_get_multi_apply_fn, context.extended, &context); -retry: - if (!by_key) { - status = memcached_set(intern->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); - } + s_clear_keys(&keys_out); - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - if (!skey) { - zend_string_release(str_key); - } - zend_string_release(payload); - RETURN_FALSE; - } - if (!skey) { - zend_string_release(str_key); - } - zend_string_release(payload); - } ZEND_HASH_FOREACH_END(); + if (!retval && (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) || s_memc_status_has_result_code(intern, MEMCACHED_SOME_ERRORS))) { + return; + } - RETURN_TRUE; + if (!retval || EG(exception)) { + zval_dtor(return_value); + RETURN_FROM_GET; + } } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration ]) - Sets the value for the given key, failing if the key already exists */ -PHP_METHOD(Memcached, add) +/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) + Returns values for the given keys or false */ +PHP_METHOD(Memcached, getMulti) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0); + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ -PHP_METHOD(Memcached, addByKey) +/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) + Returns values for the given keys from the server identified by the server key or false */ +PHP_METHOD(Memcached, getMultiByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1); + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::append(string key, mixed value) - Appends the value to existing one for the key */ -PHP_METHOD(Memcached, append) +/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) + Sends a request for the given keys and returns immediately */ +PHP_METHOD(Memcached, getDelayed) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0); + php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::appendByKey(string server_key, string key, mixed value) - Appends the value to existing one for the key on the server identified by the server key */ -PHP_METHOD(Memcached, appendByKey) +/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ]) + Sends a request for the given keys from the server identified by the server key and returns immediately */ +PHP_METHOD(Memcached, getDelayedByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1); + php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::prepend(string key, mixed value) - Prepends the value to existing one for the key */ -PHP_METHOD(Memcached, prepend) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0); -} -/* }}} */ -/* {{{ Memcached::prependByKey(string server_key, string key, mixed value) - Prepends the value to existing one for the key on the server identified by the server key */ -PHP_METHOD(Memcached, prependByKey) +static +void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t flags, zval *return_value) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1); -} -/* }}} */ + Z_TRY_ADDREF_P(value); + Z_TRY_ADDREF_P(cas); -/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) - Replaces the value for the given key, failing if the key doesn't exist */ -PHP_METHOD(Memcached, replace) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0); + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), key->val, key->len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); + + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } -/* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) - Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ -PHP_METHOD(Memcached, replaceByKey) +static +zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1); + zend_bool status = 1; + + zval retval, zv_result; + php_memc_result_callback_ctx_t *context = (php_memc_result_callback_ctx_t *) in_context; + + array_init(&zv_result); + s_create_result_array(key, value, cas, flags, &zv_result); + + zend_fcall_info_argn(&context->fci, 2, context->object, &zv_result); + + context->fci.retval = &retval; + context->fci.param_count = 2; + + ZVAL_UNDEF(&retval); + if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); + } + php_error_docref(NULL, E_WARNING, "could not invoke result callback"); + status = 0; + } + + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); + } + + zend_fcall_info_args_clear(&context->fci, 2); + zval_ptr_dtor(&zv_result); + return status; } -/* }}} */ -/* {{{ -- php_memc_store_impl */ -static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) +/* {{{ -- php_memc_getDelayed_impl */ +static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zend_string *key; + php_memc_keys_t keys_out = {0}; + + zval *keys = NULL; zend_string *server_key = NULL; - zend_string *s_value; - zval s_zvalue; - zval *value; - zend_long expiration = 0; - zend_string *payload = NULL; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; + zend_bool with_cas = 0; + + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; + if (by_key) { - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { - return; - } - value = &s_zvalue; - ZVAL_STR(value, s_value); - } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { - return; - } - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, + &keys, &with_cas, &fci, &fcc) == FAILURE) { + return; + } } else { - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { - return; - } - value = &s_zvalue; - ZVAL_STR(value, s_value); - } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { - return; - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, + &fci, &fcc) == FAILURE) { + return; } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (memc_user_data->compression) { - /* - * When compression is enabled, we cannot do appends/prepends because that would - * corrupt the compressed values. It is up to the user to fetch the value, - * append/prepend new data, and store it again. - */ - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); - return; - } - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); - if (op == MEMC_OP_TOUCH) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); - } -#endif + if (fci.size > 0) { + php_memc_result_callback_ctx_t context = { + getThis(), fci, fcc + }; + status = php_memc_mget_apply(intern, server_key, &keys_out, &s_result_callback_apply, with_cas, (void *) &context); } else { - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; - } + status = php_memc_mget_apply(intern, server_key, &keys_out, NULL, with_cas, NULL); } -retry: - switch (op) { - case MEMC_OP_SET: - if (!server_key) { - status = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; -#ifdef HAVE_MEMCACHED_TOUCH - case MEMC_OP_TOUCH: - if (!server_key) { - status = memcached_touch(intern->memc, key->val, key->len, expiration); - } else { - status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); - } - break; -#endif - case MEMC_OP_ADD: - if (!server_key) { - status = memcached_add(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_add_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_REPLACE: - if (!server_key) { - status = memcached_replace(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_replace_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_APPEND: - if (!server_key) { - status = memcached_append(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_append_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_PREPEND: - if (!server_key) { - status = memcached_prepend(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_prepend_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - default: - /* not reached */ - status = 0; - assert(0); - break; - } + s_clear_keys(&keys_out); + RETURN_BOOL(status); +} +/* }}} */ - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - RETVAL_FALSE; - } else { - RETVAL_TRUE; - } +static +zend_bool s_fetch_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) +{ + zval *return_value = (zval *) in_context; + s_create_result_array(key, value, cas, flags, return_value); - if (payload) { - zend_string_release(payload); - } + return 0; // stop iterating after one } -/* }}} */ -/* {{{ -- php_memc_cas_impl */ -static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ Memcached::fetch() + Returns the next result from a previous delayed request */ +PHP_METHOD(Memcached, fetch) { - zval *zv_cas; - uint64_t cas; - zend_string *key; - zend_string *server_key = NULL; - zval *value; - time_t expiration = 0; - zend_string *payload; + const char *res_key = NULL; + size_t res_key_len = 0; + const char *payload = NULL; + size_t payload_len = 0; uint32_t flags = 0; - memcached_return status; + uint64_t cas = 0; + zval value, zv_cas; + memcached_result_st result; + memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, - &value, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, - &expiration) == FAILURE) { - return; - } + if (zend_parse_parameters_none() == FAILURE) { + return; } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - cas = s_zval_to_uint64(zv_cas); + array_init(return_value); + status = php_memc_result_apply(intern, s_fetch_apply, return_value); - if (memc_user_data->compression) { - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; } +} +/* }}} */ - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } +static +zend_bool s_fetch_all_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) +{ + zval zv; + zval *return_value = (zval *) in_context; - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; - } + array_init (&zv); + s_create_result_array(key, value, cas, flags, &zv); - if (by_key) { - status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); - } else { - status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + add_next_index_zval(return_value, &zv); + return 1; +} + +/* {{{ Memcached::fetchAll() + Returns all the results from a previous delayed request */ +PHP_METHOD(Memcached, fetchAll) +{ + const char *res_key = NULL; + size_t res_key_len = 0; + const char *payload = NULL; + size_t payload_len = 0; + uint32_t flags; + uint64_t cas = 0; + zval value, entry, zv_cas; + memcached_result_st result; + memcached_return status = MEMCACHED_SUCCESS; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; } - zend_string_release(payload); - if (php_memc_handle_error(intern, status) < 0) { + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + array_init(return_value); + status = php_memc_result_apply(intern, s_fetch_all_apply, return_value); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_dtor(return_value); RETURN_FALSE; } - - RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) - Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, cas) +/* {{{ Memcached::set(string key, mixed value [, int expiration ]) + Sets the value for the given key */ +PHP_METHOD(Memcached, set) { - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0); } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, casByKey) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the server key */ +PHP_METHOD(Memcached, setByKey) { - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1); } /* }}} */ -/* {{{ Memcached::delete(string key [, int time ]) - Deletes the given key */ -PHP_METHOD(Memcached, delete) +#ifdef HAVE_MEMCACHED_TOUCH +/* {{{ Memcached::touch(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touch) { - php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); } /* }}} */ -/* {{{ Memcached::deleteMulti(array keys [, int time ]) - Deletes the given keys */ -PHP_METHOD(Memcached, deleteMulti) +/* {{{ Memcached::touchbyKey(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touchByKey) { - php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ +#endif -/* {{{ Memcached::deleteByKey(string server_key, string key [, int time ]) - Deletes the given key from the server identified by the server key */ -PHP_METHOD(Memcached, deleteByKey) + +/* {{{ Memcached::setMulti(array items [, int expiration ]) + Sets the keys/values specified in the items array */ +PHP_METHOD(Memcached, setMulti) { - php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::deleteMultiByKey(array keys [, int time ]) - Deletes the given key from the server identified by the server key */ -PHP_METHOD(Memcached, deleteMultiByKey) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) + Sets the keys/values specified in the items array on the server identified by the given server key */ +PHP_METHOD(Memcached, setMultiByKey) { - php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ -- php_memc_delete_impl */ -static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ -- php_memc_setMulti_impl */ +static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zend_string *key, *server_key; + zval *entries; + zend_string *server_key = NULL; time_t expiration = 0; + zval *value; + zend_string *skey, *str_key = NULL; + ulong num_key; + zend_string *payload; + uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; + char tmp_key[MEMCACHED_MAX_KEY]; + int tmp_len = 0; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, + &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { return; } - server_key = key; } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); - } else { - status = memcached_delete(intern->memc, key->val, key->len, expiration); - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - RETURN_TRUE; -} -/* }}} */ + zend_string *str_key; -/* {{{ -- php_memc_deleteMulti_impl */ -static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) -{ - zval *entries; - zend_string *server_key = NULL; - time_t expiration = 0; - zval *entry; - - memcached_return status; - MEMC_METHOD_INIT_VARS; - - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { - return; + if (skey) { + str_key = skey; } - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + else { + char tmp_key[64]; - array_init(return_value); - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); + tmp_len = snprintf(tmp_key, sizeof(tmp_key) - 1, "%ld", (long)num_key); + str_key = zend_string_init(tmp_key, tmp_len, 0); } - if (Z_STRLEN_P(entry) == 0) { - continue; + if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { + php_error_docref(NULL, E_WARNING, "failed to set key %s", str_key->val); } - if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); - } else { - status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + if (!skey) { + zend_string_release (str_key); } - - if (php_memc_handle_error(intern, status) < 0) { - add_assoc_long(return_value, Z_STRVAL_P(entry), status); - } else { - add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); - } } ZEND_HASH_FOREACH_END(); - return; + RETURN_BOOL(!s_memc_status_has_error(intern)); } /* }}} */ -/* {{{ -- php_memc_incdec_impl */ -static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) +/* {{{ Memcached::add(string key, mixed value [, int expiration ]) + Sets the value for the given key, failing if the key already exists */ +PHP_METHOD(Memcached, add) { - zend_string *key, *server_key = NULL; - long offset = 1; - uint64_t value, initial = 0; - time_t expiry = 0; - memcached_return status; - int n_args = ZEND_NUM_ARGS(); - uint32_t retry = 0; - - MEMC_METHOD_INIT_VARS; - - if (!by_key) { - if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { - return; - } - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (offset < 0) { - php_error_docref(NULL, E_WARNING, "offset has to be > 0"); - RETURN_FALSE; - } + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0); +} +/* }}} */ -retry: - if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { - if (by_key) { - if (incr) { - status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); - } else { - status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); - } - } else { - if (incr) { - status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); - } else { - status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); - } - } - } else { - if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); - RETURN_FALSE; - } - if (by_key) { - if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } else { - status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } - } else { - if (incr) { - status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } else { - status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } - } - } +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ +PHP_METHOD(Memcached, addByKey) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1); +} +/* }}} */ - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - RETURN_FALSE; - } +/* {{{ Memcached::append(string key, mixed value) + Appends the value to existing one for the key */ +PHP_METHOD(Memcached, append) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0); +} +/* }}} */ - RETURN_LONG((long)value); +/* {{{ Memcached::appendByKey(string server_key, string key, mixed value) + Appends the value to existing one for the key on the server identified by the server key */ +PHP_METHOD(Memcached, appendByKey) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1); } /* }}} */ -/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) - Increments the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, increment) +/* {{{ Memcached::prepend(string key, mixed value) + Prepends the value to existing one for the key */ +PHP_METHOD(Memcached, prepend) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0); } /* }}} */ -/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) - Decrements the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrement) +/* {{{ Memcached::prependByKey(string server_key, string key, mixed value) + Prepends the value to existing one for the key on the server identified by the server key */ +PHP_METHOD(Memcached, prependByKey) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1); } /* }}} */ -/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) - Decrements by server the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrementByKey) +/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) + Replaces the value for the given key, failing if the key doesn't exist */ +PHP_METHOD(Memcached, replace) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0); } /* }}} */ -/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) - Increments by server the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, incrementByKey) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) + Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ +PHP_METHOD(Memcached, replaceByKey) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1); } /* }}} */ -/* {{{ Memcached::addServer(string hostname, int port [, int weight ]) - Adds the given memcache server to the list */ -PHP_METHOD(Memcached, addServer) +/* {{{ -- php_memc_store_impl */ +static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { - zend_string *host; - long port, weight = 0; + zend_string *key; + zend_string *server_key = NULL; + zend_string *s_value; + zval s_zvalue; + zval *value = NULL; + zend_long expiration = 0; + zend_string *payload = NULL; + uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { - return; + if (by_key) { + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { + return; + } + value = &s_zvalue; + ZVAL_STR(value, s_value); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { + return; + } + } + } else { + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { + return; + } + value = &s_zvalue; + ZVAL_STR(value, s_value); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { + return; + } + } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); - } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); - } else { - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + if (memc_user_data->compression_enabled) { + /* + * When compression is enabled, we cannot do appends/prepends because that would + * corrupt the compressed values. It is up to the user to fetch the value, + * append/prepend new data, and store it again. + */ + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); + RETURN_NULL(); + } } -#else - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + + + if (op == MEMC_OP_TOUCH) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 + if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); + } #endif + } - if (php_memc_handle_error(intern, status) < 0) { + if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) { RETURN_FALSE; } - RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::addServers(array servers) - Adds the given memcache servers to the server list */ -PHP_METHOD(Memcached, addServers) +/* {{{ -- php_memc_cas_impl */ +static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *servers; - zval *entry; - zval *z_host, *z_port, *z_weight = NULL; - uint32_t weight = 0; - HashPosition pos; - int entry_size, i = 0; - memcached_server_st *list = NULL; - memcached_return status; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + zval *zv_cas; + uint64_t cas; + zend_string *key; + zend_string *server_key = NULL; + zval *value; + time_t expiration = 0; + zend_string *payload; + uint32_t flags = 0; + memcached_return status; + MEMC_METHOD_INIT_VARS; - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { - if (Z_TYPE_P(entry) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); - i++; - continue; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, + &value, &expiration) == FAILURE) { + return; } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, + &expiration) == FAILURE) { + return; + } + } - entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); - - if (entry_size > 1) { - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); - - /* Check that we have a host */ - if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); - i++; - continue; - } - - /* Check that we have a port */ - if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || - (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); - i++; - continue; - } - - convert_to_string_ex(z_host); - convert_to_long_ex(z_port); - - weight = 0; - if (entry_size > 2) { - /* Try to get weight */ - if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || - (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); - } + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - convert_to_long_ex(z_weight); - weight = Z_LVAL_P(z_weight); - } + cas = s_zval_to_uint64(zv_cas); - list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), - Z_LVAL_P(z_port), weight, &status); + payload = s_zval_to_payload(intern, value, &flags); + if (payload == NULL) { + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; + RETURN_FALSE; + } - if (php_memc_handle_error(intern, status) == 0) { - i++; - continue; - } - } - i++; - /* catch-all for all errors */ - php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); - } ZEND_HASH_FOREACH_END(); + if (by_key) { + status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + } else { + status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + } - status = memcached_server_push(intern->memc, list); - memcached_server_list_free(list); - if (php_memc_handle_error(intern, status) < 0) { + zend_string_release(payload); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } @@ -2076,351 +1997,725 @@ PHP_METHOD(Memcached, addServers) } /* }}} */ -/* {{{ Memcached::getServerList() - Returns the list of the memcache servers in use */ -PHP_METHOD(Memcached, getServerList) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) + Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, cas) { - memcached_server_function callbacks[1]; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - callbacks[0] = s_server_cursor_list_servers_cb; - array_init(return_value); - memcached_server_cursor(intern->memc, callbacks, return_value, 1); + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::getServerByKey(string server_key) - Returns the server identified by the given server key */ -PHP_METHOD(Memcached, getServerByKey) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, casByKey) { - zend_string *server_key; - php_memcached_instance_st server_instance; - memcached_return error; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); - if (server_instance == NULL) { - php_memc_handle_error(intern, error); - RETURN_FALSE; - } - - array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); - add_assoc_long(return_value, "port", memcached_server_port(server_instance)); - add_assoc_long(return_value, "weight", 0); + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::resetServerList() - Reset the server list in use */ -PHP_METHOD(Memcached, resetServerList) +/* {{{ Memcached::delete(string key [, int time ]) + Deletes the given key */ +PHP_METHOD(Memcached, delete) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - memcached_servers_reset(intern->memc); - RETURN_TRUE; + php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::quit() - Close any open connections */ -PHP_METHOD(Memcached, quit) +/* {{{ Memcached::deleteMulti(array keys [, int time ]) + Deletes the given keys */ +PHP_METHOD(Memcached, deleteMulti) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - memcached_quit(intern->memc); - RETURN_TRUE; + php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::flushBuffers() - Flush and senf buffered commands */ -PHP_METHOD(Memcached, flushBuffers) +/* {{{ Memcached::deleteByKey(string server_key, string key [, int time ]) + Deletes the given key from the server identified by the server key */ +PHP_METHOD(Memcached, deleteByKey) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); + php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION -/* {{{ Memcached::getLastErrorMessage() - Returns the last error message that occurred */ -PHP_METHOD(Memcached, getLastErrorMessage) +/* {{{ Memcached::deleteMultiByKey(array keys [, int time ]) + Deletes the given key from the server identified by the server key */ +PHP_METHOD(Memcached, deleteMultiByKey) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_STRING(memcached_last_error_message(intern->memc)); + php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::getLastErrorCode() - Returns the last error code that occurred */ -PHP_METHOD(Memcached, getLastErrorCode) +/* {{{ -- php_memc_delete_impl */ +static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { + zend_string *key, *server_key; + time_t expiration = 0; + memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + return; + } + server_key = key; } MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - RETURN_LONG(memcached_last_error(intern->memc)); + if (by_key) { + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, + key->len, expiration); + } else { + status = memcached_delete(intern->memc, key->val, key->len, expiration); + } + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::getLastErrorErrno() - Returns the last error errno that occurred */ -PHP_METHOD(Memcached, getLastErrorErrno) +/* {{{ -- php_memc_deleteMulti_impl */ +static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { + zval *entries; + zend_string *server_key = NULL; + time_t expiration = 0; + zval *entry; + + memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; - - RETURN_LONG(memcached_last_error_errno(intern->memc)); -} -/* }}} */ -#endif - -/* {{{ Memcached::getLastDisconnectedServer() - Returns the last disconnected server - Was added in 0.34 according to libmemcached's Changelog */ -PHP_METHOD(Memcached, getLastDisconnectedServer) -{ - php_memcached_instance_st server_instance; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - server_instance = memcached_server_get_last_disconnect(intern->memc); - if (server_instance == NULL) { - RETURN_FALSE; - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); - add_assoc_long(return_value, "port", memcached_server_port(server_instance)); -} -/* }}} */ - -#include - -static -zend_bool s_long_value(const char *str, zend_long *value) -{ - char *end = (char *) str; - - errno = 0; - *value = strtol(str, &end, 10); - - if (errno || str == end || *end != '\0') { - return 0; - } - return 1; -} - -static -zend_bool s_double_value(const char *str, double *value) -{ - char *end = (char *) str; - - errno = 0; - *value = strtod(str, &end); - - if (errno || str == end || *end != '\0') { - return 0; - } - return 1; -} - -static -memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) -{ - char *server_key; - size_t server_key_len; - zend_long long_val; - double d_val; - char *buffer; - - zval *return_value = (zval *) context; - zval *server_values; + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { + convert_to_string_ex(entry); + } - server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + if (Z_STRLEN_P(entry) == 0) { + continue; + } - if (!server_values) { - zval zv; - array_init(&zv); + if (by_key) { + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } else { + status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } - server_values = &zv; - add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); - } - spprintf (&buffer, 0, "%.*s", value_length, value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + add_assoc_long(return_value, Z_STRVAL_P(entry), status); + } else { + add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); + } + } ZEND_HASH_FOREACH_END(); - /* Check type */ - if (s_long_value (buffer, &long_val)) { - add_assoc_long(server_values, key, long_val); - } - else if (s_double_value (buffer, &d_val)) { - add_assoc_double(server_values, key, d_val); - } - else { - add_assoc_stringl_ex(server_values, key, key_length, value, value_length); - } - efree (buffer); - efree (server_key); - return MEMCACHED_SUCCESS; + return; } +/* }}} */ -/* {{{ Memcached::getStats() - Returns statistics for the memcache servers */ -PHP_METHOD(Memcached, getStats) +/* {{{ -- php_memc_incdec_impl */ +static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { + zend_string *key, *server_key = NULL; + long offset = 1; + uint64_t value = UINT64_MAX, initial = 0; + time_t expiry = 0; memcached_return status; + int n_args = ZEND_NUM_ARGS(); + MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (!by_key) { + if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - array_init(return_value); - status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); - if (php_memc_handle_error(intern, status) < 0) { - zval_ptr_dtor(return_value); + if (offset < 0) { + php_error_docref(NULL, E_WARNING, "offset has to be > 0"); RETURN_FALSE; } -} -/* }}} */ -/* {{{ Memcached::getVersion() - Returns the version of each memcached server in the pool */ -PHP_METHOD(Memcached, getVersion) -{ - memcached_return rc; - memcached_server_function callbacks[1]; - MEMC_METHOD_INIT_VARS; + if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { + if (by_key) { + if (incr) { + status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + } else { + status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + } + } else { + if (incr) { + status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); + } else { + status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); + } + } - if (zend_parse_parameters_none() == FAILURE) { - return; - } + } else { + zend_long retries = memc_user_data->store_retry_count; - MEMC_METHOD_FETCH_OBJECT; +retry_inc_dec: + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); + RETURN_FALSE; + } + if (by_key) { + if (incr) { + status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } + } else { + if (incr) { + status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } + } + if (s_should_retry_write(intern, status) && retries-- > 0) { + goto retry_inc_dec; + } + } - rc = memcached_version(intern->memc); - if (php_memc_handle_error(intern, rc) < 0) { + if (value == UINT64_MAX) { RETURN_FALSE; } - callbacks[0] = s_server_cursor_version_cb; - - array_init(return_value); - rc = memcached_server_cursor(intern->memc, callbacks, return_value, 1); - if (php_memc_handle_error(intern, rc) < 0) { - zval_dtor(return_value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } + + RETURN_LONG((long)value); } /* }}} */ -/* {{{ Memcached::getAllKeys() - Returns the keys stored on all the servers */ -static -memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) +/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, increment) { - zval *return_value = (zval*) in_context; - add_next_index_stringl(return_value, key, key_length); - - return MEMCACHED_SUCCESS; + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); } +/* }}} */ -PHP_METHOD(Memcached, getAllKeys) +/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrement) { - memcached_return rc; - memcached_dump_func callback[1]; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - callback[0] = s_dump_keys_cb; - MEMC_METHOD_FETCH_OBJECT; + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); +} +/* }}} */ - array_init(return_value); +/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); +} +/* }}} */ - rc = memcached_dump(intern->memc, callback, return_value, 1); - if (php_memc_handle_error(intern, rc) < 0) { - zval_dtor(return_value); - RETURN_FALSE; - } +/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, incrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); } /* }}} */ -/* {{{ Memcached::flush([ int delay ]) - Flushes the data on all the servers */ -static PHP_METHOD(Memcached, flush) +/* {{{ Memcached::addServer(string hostname, int port [, int weight ]) + Adds the given memcache server to the list */ +PHP_METHOD(Memcached, addServer) { - time_t delay = 0; + zend_string *host; + long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; intern->rescode = MEMCACHED_SUCCESS; - status = memcached_flush(intern->memc, delay); - if (php_memc_handle_error(intern, status) < 0) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 + if (host->val[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { + status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); + } else { + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + } +#else + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); +#endif + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::addServers(array servers) + Adds the given memcache servers to the server list */ +PHP_METHOD(Memcached, addServers) +{ + zval *servers; + zval *entry; + zval *z_host, *z_port, *z_weight = NULL; + uint32_t weight = 0; + HashPosition pos; + int entry_size, i = 0; + memcached_server_st *list = NULL; + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { + if (Z_TYPE_P(entry) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); + i++; + continue; + } + + entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); + + if (entry_size > 1) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); + + /* Check that we have a host */ + if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); + i++; + continue; + } + + /* Check that we have a port */ + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); + i++; + continue; + } + + convert_to_string_ex(z_host); + convert_to_long_ex(z_port); + + weight = 0; + if (entry_size > 2) { + /* Try to get weight */ + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); + } + + convert_to_long_ex(z_weight); + weight = Z_LVAL_P(z_weight); + } + + list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), + Z_LVAL_P(z_port), weight, &status); + + if (s_memc_status_handle_result_code(intern, status) == SUCCESS) { + i++; + continue; + } + } + i++; + /* catch-all for all errors */ + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + } ZEND_HASH_FOREACH_END(); + + status = memcached_server_push(intern->memc, list); + memcached_server_list_free(list); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::getServerList() + Returns the list of the memcache servers in use */ +PHP_METHOD(Memcached, getServerList) +{ + memcached_server_function callbacks[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + callbacks[0] = s_server_cursor_list_servers_cb; + array_init(return_value); + memcached_server_cursor(intern->memc, callbacks, return_value, 1); +} +/* }}} */ + +/* {{{ Memcached::getServerByKey(string server_key) + Returns the server identified by the given server key */ +PHP_METHOD(Memcached, getServerByKey) +{ + zend_string *server_key; + php_memcached_instance_st server_instance; + memcached_return error; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); + if (server_instance == NULL) { + s_memc_status_handle_result_code(intern, error); + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); + add_assoc_long(return_value, "weight", 0); +} +/* }}} */ + +/* {{{ Memcached::resetServerList() + Reset the server list in use */ +PHP_METHOD(Memcached, resetServerList) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_servers_reset(intern->memc); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::quit() + Close any open connections */ +PHP_METHOD(Memcached, quit) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_quit(intern->memc); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::flushBuffers() + Flush and senf buffered commands */ +PHP_METHOD(Memcached, flushBuffers) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); +} +/* }}} */ + +#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION +/* {{{ Memcached::getLastErrorMessage() + Returns the last error message that occurred */ +PHP_METHOD(Memcached, getLastErrorMessage) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_STRING(memcached_last_error_message(intern->memc)); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorCode() + Returns the last error code that occurred */ +PHP_METHOD(Memcached, getLastErrorCode) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error(intern->memc)); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorErrno() + Returns the last error errno that occurred */ +PHP_METHOD(Memcached, getLastErrorErrno) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error_errno(intern->memc)); +} +/* }}} */ +#endif + +/* {{{ Memcached::getLastDisconnectedServer() + Returns the last disconnected server + Was added in 0.34 according to libmemcached's Changelog */ +PHP_METHOD(Memcached, getLastDisconnectedServer) +{ + php_memcached_instance_st server_instance; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + server_instance = memcached_server_get_last_disconnect(intern->memc); + if (server_instance == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); +} +/* }}} */ + + + +static +zend_bool s_long_value(const char *str, zend_long *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtol(str, &end, 10); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +zend_bool s_double_value(const char *str, double *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtod(str, &end); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) +{ + char *server_key; + size_t server_key_len; + zend_long long_val; + double d_val; + char *buffer; + + zval *return_value = (zval *) context; + zval *server_values; + + server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + + if (!server_values) { + zval zv; + array_init(&zv); + + server_values = &zv; + add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + } + + spprintf (&buffer, 0, "%.*s", value_length, value); + + /* Check type */ + if (s_long_value (buffer, &long_val)) { + add_assoc_long(server_values, key, long_val); + } + else if (s_double_value (buffer, &d_val)) { + add_assoc_double(server_values, key, d_val); + } + else { + add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + } + efree (buffer); + efree (server_key); + return MEMCACHED_SUCCESS; +} + +/* {{{ Memcached::getStats() + Returns statistics for the memcache servers */ +PHP_METHOD(Memcached, getStats) +{ + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + array_init(return_value); + status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::getVersion() + Returns the version of each memcached server in the pool */ +PHP_METHOD(Memcached, getVersion) +{ + memcached_return status; + memcached_server_function callbacks[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + status = memcached_version(intern->memc); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + callbacks[0] = s_server_cursor_version_cb; + + array_init(return_value); + status = memcached_server_cursor(intern->memc, callbacks, return_value, 1); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::getAllKeys() + Returns the keys stored on all the servers */ +static +memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) +{ + zval *return_value = (zval*) in_context; + add_next_index_stringl(return_value, key, key_length); + + return MEMCACHED_SUCCESS; +} + +PHP_METHOD(Memcached, getAllKeys) +{ + memcached_return rc; + memcached_dump_func callback[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + callback[0] = s_dump_keys_cb; + MEMC_METHOD_FETCH_OBJECT; + + array_init(return_value); + + rc = memcached_dump(intern->memc, callback, return_value, 1); + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { + zval_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::flush([ int delay ]) + Flushes the data on all the servers */ +static PHP_METHOD(Memcached, flush) +{ + time_t delay = 0; + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + intern->rescode = MEMCACHED_SUCCESS; + + status = memcached_flush(intern->memc, delay); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } @@ -2448,7 +2743,7 @@ static PHP_METHOD(Memcached, getOption) RETURN_LONG(memc_user_data->compression_type); case MEMC_OPT_COMPRESSION: - RETURN_BOOL(memc_user_data->compression); + RETURN_BOOL(memc_user_data->compression_enabled); case MEMC_OPT_PREFIX_KEY: { @@ -2507,7 +2802,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) switch (option) { case MEMC_OPT_COMPRESSION: convert_to_long(value); - memc_user_data->compression = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression_enabled = Z_LVAL_P(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: @@ -2557,7 +2852,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) convert_to_long(value); rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2652,7 +2947,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } } - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2751,7 +3046,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { retval = 0;; } @@ -2790,546 +3085,286 @@ static PHP_METHOD(Memcached, setOptions) zval copy; ZVAL_DUP(©, value); - if (!php_memc_set_option(intern, (long) key_index, ©)) { - ok = 0; - } - - zval_dtor(©); - } - } ZEND_HASH_FOREACH_END(); - - RETURN_BOOL(ok); -} -/* }}} */ - -/* {{{ Memcached::setOption(int option, mixed value) - Sets the value for the given option constant */ -static PHP_METHOD(Memcached, setOption) -{ - long option; - zval *value; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(php_memc_set_option(intern, option, value)); -} -/* }}} */ - -#ifdef HAVE_MEMCACHED_SASL -/* {{{ Memcached::setSaslAuthData(string user, string pass) - Sets sasl credentials */ -static PHP_METHOD(Memcached, setSaslAuthData) -{ - MEMC_METHOD_INIT_VARS; - memcached_return status; - zend_string *user, *pass; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { - return; - } - - if (!php_memc_init_sasl_if_needed()) { - RETURN_FALSE; - } - - MEMC_METHOD_FETCH_OBJECT; - - if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); - RETURN_FALSE; - } - memc_user_data->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } - RETURN_TRUE; -} -/* }}} */ -#endif /* HAVE_MEMCACHED_SASL */ - -/* {{{ Memcached::getResultCode() - Returns the result code from the last operation */ -static PHP_METHOD(Memcached, getResultCode) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_LONG(intern->rescode); -} -/* }}} */ - -/* {{{ Memcached::getResultMessage() - Returns the result message from the last operation */ -static PHP_METHOD(Memcached, getResultMessage) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - switch (intern->rescode) { - case MEMC_RES_PAYLOAD_FAILURE: - RETURN_STRING("PAYLOAD FAILURE"); - break; - - case MEMCACHED_ERRNO: - case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: - case MEMCACHED_UNKNOWN_READ_FAILURE: - if (intern->memc_errno) { - zend_string *str = strpprintf(0, "%s: %s", - memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); - RETURN_STR(str); - } - /* Fall through */ - default: - RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); - break; - } - -} -/* }}} */ - -/* {{{ Memcached::isPersistent() - Returns the true if instance uses a persistent connection */ -static PHP_METHOD(Memcached, isPersistent) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(memc_user_data->is_persistent); -} -/* }}} */ - -/* {{{ Memcached::isPristine() - Returns the true if instance is recently created */ -static PHP_METHOD(Memcached, isPristine) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(intern->is_pristine); -} -/* }}} */ - -/**************************************** - Internal support code -****************************************/ - -/* {{{ constructor/destructor */ -static -void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) -{ -#if HAVE_MEMCACHED_SASL - if (memc_user_data->has_sasl_data) { - memcached_destroy_sasl_auth_data(memc); - } -#endif - - memcached_set_memory_allocators(memc, NULL, NULL, NULL, NULL, NULL); - memcached_free(memc); - pefree(memc_user_data, memc_user_data->is_persistent); -} - -static -void php_memc_object_free_storage(zend_object *object) -{ - php_memc_object_t *intern = php_memc_fetch_object(object); - - if (intern->memc) { - php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); - - if (!memc_user_data->is_persistent) { - php_memc_destroy(intern->memc, memc_user_data); - } - } - - intern->memc = NULL; - zend_object_std_dtor(&intern->zo); -} - -static -zend_object *php_memc_object_new(zend_class_entry *ce) -{ - php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); - - zend_object_std_init(&intern->zo, ce); - object_properties_init(&intern->zo, ce); - - intern->zo.handlers = &memcached_object_handlers; - return &intern->zo; -} - -#ifdef HAVE_MEMCACHED_PROTOCOL -static -void php_memc_server_free_storage(php_memc_server_t *intern) -{ - zend_object_std_dtor(&intern->zo); - efree (intern); -} - -zend_object_value php_memc_server_new(zend_class_entry *ce) -{ - zend_object_value retval; - php_memc_server_t *intern; - zval *tmp; - - intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init(&intern->zo, ce); - object_properties_init(&intern->zo, ce); - - intern->handler = php_memc_proto_handler_new (); - - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); - retval.handlers = &memcached_server_object_handlers; - - return retval; -} -#endif - -ZEND_RSRC_DTOR_FUNC(php_memc_dtor) -{ - if (res->ptr) { - memcached_st *memc = (memcached_st *) res->ptr; - php_memc_destroy(memc, memcached_get_user_data(memc)); - res->ptr = NULL; - } -} - -/* }}} */ - -/* {{{ internal API functions */ -static -memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - zval array; - zval *return_value = (zval *) in_context; - - array_init(&array); - add_assoc_string(&array, "host", memcached_server_name(instance)); - add_assoc_long(&array, "port", memcached_server_port(instance)); - add_assoc_string(&array, "type", memcached_server_type(instance)); - /* - * API does not allow to get at this field. - add_assoc_long(array, "weight", instance->weight); - */ + if (!php_memc_set_option(intern, (long) key_index, ©)) { + ok = 0; + } - add_next_index_zval(return_value, &array); - return MEMCACHED_SUCCESS; + zval_dtor(©); + } + } ZEND_HASH_FOREACH_END(); + + RETURN_BOOL(ok); } +/* }}} */ -static -memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +/* {{{ Memcached::setOption(int option, mixed value) + Sets the value for the given option constant */ +static PHP_METHOD(Memcached, setOption) { - char *address, *version; - size_t address_len, version_len; - - zval *return_value = (zval *) in_context; + long option; + zval *value; + MEMC_METHOD_INIT_VARS; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = spprintf(&version, sizeof(version), "%d.%d.%d", - memcached_server_major_version(instance), - memcached_server_minor_version(instance), - memcached_server_micro_version(instance)); -#else - version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", - instance->major_version, - instance->minor_version, - instance->micro_version); -#endif + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { + return; + } - address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); - add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + MEMC_METHOD_FETCH_OBJECT; - efree(address); - efree(version); - return MEMCACHED_SUCCESS; + RETURN_BOOL(php_memc_set_option(intern, option, value)); } +/* }}} */ -static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status) +#ifdef HAVE_MEMCACHED_SASL +/* {{{ Memcached::setSaslAuthData(string user, string pass) + Sets sasl credentials */ +static PHP_METHOD(Memcached, setSaslAuthData) { - int result = 0; + MEMC_METHOD_INIT_VARS; + memcached_return status; + zend_string *user, *pass; - switch (status) { - case MEMCACHED_SUCCESS: - case MEMCACHED_STORED: - case MEMCACHED_DELETED: - case MEMCACHED_STAT: - result = 0; - intern->memc_errno = 0; - break; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { + return; + } - case MEMCACHED_END: - case MEMCACHED_BUFFERED: - intern->rescode = status; - intern->memc_errno = 0; - result = 0; - break; + if (!php_memc_init_sasl_if_needed()) { + RETURN_FALSE; + } - case MEMCACHED_SOME_ERRORS: - intern->rescode = status; - intern->memc_errno = memcached_last_error_errno(intern->memc); - result = 0; - break; + MEMC_METHOD_FETCH_OBJECT; - default: - intern->rescode = status; - intern->memc_errno = memcached_last_error_errno(intern->memc); - result = -1; - break; + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); + RETURN_FALSE; } + memc_user_data->has_sasl_data = 1; + status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - return result; + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + RETURN_TRUE; } +/* }}} */ +#endif /* HAVE_MEMCACHED_SASL */ -static -zend_bool s_compress_value (enum memcached_compression_type compression_type, zend_string **payload_in, uint32_t *flags) +/* {{{ Memcached::getResultCode() + Returns the result code from the last operation */ +static PHP_METHOD(Memcached, getResultCode) { - /* status */ - zend_bool compress_status = 0; - zend_string *payload = *payload_in; + MEMC_METHOD_INIT_VARS; - /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); - char *buffer = emalloc(buffer_size); + if (zend_parse_parameters_none() == FAILURE) { + return; + } - /* Store compressed size here */ - size_t compressed_size = 0; - uint32_t original_size = payload->len; + MEMC_METHOD_FETCH_OBJECT; - switch (compression_type) { + RETURN_LONG(intern->rescode); +} +/* }}} */ - case COMPRESSION_TYPE_FASTLZ: - { - compressed_size = fastlz_compress(payload->val, payload->len, buffer); +/* {{{ Memcached::getResultMessage() + Returns the result message from the last operation */ +static PHP_METHOD(Memcached, getResultMessage) +{ + MEMC_METHOD_INIT_VARS; - if (compressed_size > 0) { - compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); - } - } - break; + if (zend_parse_parameters_none() == FAILURE) { + return; + } - case COMPRESSION_TYPE_ZLIB: - { - compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); + MEMC_METHOD_FETCH_OBJECT; - if (status == Z_OK) { - compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); - } - } + switch (intern->rescode) { + case MEMC_RES_PAYLOAD_FAILURE: + RETURN_STRING("PAYLOAD FAILURE"); break; + case MEMCACHED_ERRNO: + case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: + case MEMCACHED_UNKNOWN_READ_FAILURE: + if (intern->memc_errno) { + zend_string *str = strpprintf(0, "%s: %s", + memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); + RETURN_STR(str); + } + /* Fall through */ default: - compress_status = 0; + RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); break; } - if (!compress_status) { - php_error_docref(NULL, E_WARNING, "could not compress value"); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - return 0; - } +} +/* }}} */ - /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (payload->len * MEMC_G(compression_factor))) { - efree(buffer); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - return 1; - } +/* {{{ Memcached::isPersistent() + Returns the true if instance uses a persistent connection */ +static PHP_METHOD(Memcached, isPersistent) +{ + MEMC_METHOD_INIT_VARS; - payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + if (zend_parse_parameters_none() == FAILURE) { + return; + } - /* Copy the uin32_t at the beginning */ - memcpy(payload->val, &original_size, sizeof(uint32_t)); - memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); - efree(buffer); + MEMC_METHOD_FETCH_OBJECT; - zend_string_forget_hash_val(payload); - *payload_in = payload; - return 1; + RETURN_BOOL(memc_user_data->is_persistent); } +/* }}} */ -static -zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags) +/* {{{ Memcached::isPristine() + Returns the true if instance is recently created */ +static PHP_METHOD(Memcached, isPristine) { - switch (serializer) { + MEMC_METHOD_INIT_VARS; - /* - Igbinary serialization - */ -#ifdef HAVE_MEMCACHED_IGBINARY - case SERIALIZER_IGBINARY: - { - uint8_t *buffer; - size_t buffer_len; + if (zend_parse_parameters_none() == FAILURE) { + return; + } - if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { - php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); - return 0; - } - smart_str_appendl (buf, buffer, buffer_len); - efree(buffer); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); - } - break; -#endif + MEMC_METHOD_FETCH_OBJECT; - /* - JSON serialization - */ -#ifdef HAVE_JSON_API - case SERIALIZER_JSON: - case SERIALIZER_JSON_ARRAY: - { - php_json_encode(buf, value, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); - } - break; -#endif + RETURN_BOOL(intern->is_pristine); +} +/* }}} */ - /* - msgpack serialization - */ -#ifdef HAVE_MEMCACHED_MSGPACK - case SERIALIZER_MSGPACK: - php_msgpack_serialize(buf, value); - if (!buf->s) { - php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); - return 0; - } - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); - break; +/**************************************** + Internal support code +****************************************/ + +/* {{{ constructor/destructor */ +static +void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) +{ +#if HAVE_MEMCACHED_SASL + if (memc_user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); + } #endif - /* - PHP serialization - */ - default: - { - php_serialize_data_t var_hash; - PHP_VAR_SERIALIZE_INIT(var_hash); - php_var_serialize(buf, value, &var_hash); - PHP_VAR_SERIALIZE_DESTROY(var_hash); + memcached_free(memc); + pefree(memc_user_data, memc_user_data->is_persistent); +} - if (!buf->s) { - php_error_docref(NULL, E_WARNING, "could not serialize value"); - return 0; - } - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); +static +void php_memc_object_free_storage(zend_object *object) +{ + php_memc_object_t *intern = php_memc_fetch_object(object); + + if (intern->memc) { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + if (!memc_user_data->is_persistent) { + php_memc_destroy(intern->memc, memc_user_data); } - break; } - /* Check for exceptions caused by serializers */ - if (EG(exception) && buf->s->len) { - return 0; - } - return 1; + intern->memc = NULL; + zend_object_std_dtor(&intern->zo); } static -zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) +zend_object *php_memc_object_new(zend_class_entry *ce) { - zend_string *payload; + php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); - switch (Z_TYPE_P(value)) { + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); - case IS_STRING: - payload = zval_get_string(value); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); - MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); - break; + intern->zo.handlers = &memcached_object_handlers; + return &intern->zo; +} - case IS_LONG: - { - smart_str buffer = {0}; - smart_str_append_long (&buffer, Z_LVAL_P(value)); - smart_str_0(&buffer); - payload = buffer.s; +#ifdef HAVE_MEMCACHED_PROTOCOL +static +void php_memc_server_free_storage(php_memc_server_t *intern) +{ + zend_object_std_dtor(&intern->zo); + efree (intern); +} - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); - } - break; +zend_object_value php_memc_server_new(zend_class_entry *ce) +{ + zend_object_value retval; + php_memc_server_t *intern; + zval *tmp; - case IS_DOUBLE: - { - char buffer[40]; - php_memcached_g_fmt(buffer, Z_DVAL_P(value)); - payload = zend_string_init (buffer, strlen (buffer), 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); - } - break; + intern = ecalloc(1, sizeof(php_memc_server_t)); + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); - case IS_TRUE: - payload = zend_string_init ("1", 1, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); - break; + intern->handler = php_memc_proto_handler_new (); - case IS_FALSE: - payload = zend_string_alloc (0, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); - break; + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); + retval.handlers = &memcached_server_object_handlers; - default: - { - smart_str buffer = {0}; + return retval; +} +#endif - if (!s_serialize_value (serializer, value, &buffer, flags)) { - smart_str_free(&buffer); - return NULL; - } - payload = buffer.s; - MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); - } - break; +ZEND_RSRC_DTOR_FUNC(php_memc_dtor) +{ + if (res->ptr) { + memcached_st *memc = (memcached_st *) res->ptr; + php_memc_destroy(memc, memcached_get_user_data(memc)); + res->ptr = NULL; } - zend_string_forget_hash_val(payload); +} - /* turn off compression for values below the threshold */ - if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - } +/* }}} */ - /* If we have compression flag, compress the value */ - if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { - /* status */ - if (!s_compress_value (compression_type, &payload, flags)) { - zend_string_release(payload); - return NULL; - } - } +/* {{{ internal API functions */ +static +memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + zval array; + zval *return_value = (zval *) in_context; - return payload; + array_init(&array); + add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "type", memcached_server_type(instance)); + /* + * API does not allow to get at this field. + add_assoc_long(array, "weight", instance->weight); + */ + + add_next_index_zval(return_value, &array); + return MEMCACHED_SUCCESS; +} + +static +memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + char *address, *version; + size_t address_len, version_len; + + zval *return_value = (zval *) in_context; + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 + version_len = spprintf(&version, sizeof(version), "%d.%d.%d", + memcached_server_major_version(instance), + memcached_server_minor_version(instance), + memcached_server_micro_version(instance)); +#else + version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", + instance->major_version, + instance->minor_version, + instance->micro_version); +#endif + + address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + + efree(address); + efree(version); + return MEMCACHED_SUCCESS; } + static zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32_t flags) { @@ -3559,145 +3594,6 @@ zend_class_entry *php_memc_get_exception_base(int root) #endif } -static -memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) -{ - memcached_return rc = MEMCACHED_SUCCESS; - int result; - - zval params[4]; - zval retval; - zval zv_key, ref_val; - zval ref_expiration, zv_expiration; - - /* Prepare params */ - ZVAL_STR(&zv_key, key); - - ZVAL_NULL(&ref_val); - ZVAL_NULL(&zv_expiration); - - ZVAL_NEW_REF(&ref_val, value); - ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - - ZVAL_COPY(¶ms[0], zobject); - ZVAL_COPY(¶ms[1], &zv_key); - ZVAL_COPY_VALUE(¶ms[2], &ref_val); - ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); - - fci->retval = &retval; - fci->params = params; - fci->param_count = 4; - - result = zend_call_function(fci, fcc); - ZVAL_DUP(value, Z_REFVAL(ref_val)); - - if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - - if (zend_is_true(&retval)) { - time_t expiration; - zend_string *payload; - uint32_t flags = 0; - php_memc_object_t *intern; - php_memc_user_data_t *memc_user_data; - - intern = Z_MEMC_OBJ_P(zobject); - memc_user_data = memcached_get_user_data(intern->memc); - - expiration = zval_get_long(Z_REFVAL(ref_expiration)); - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - - if (payload == NULL) { - rc = (memcached_return) MEMC_RES_PAYLOAD_FAILURE; - } else { - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } - rc = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) { - rc = MEMCACHED_SOME_ERRORS; - } - zend_string_release(payload); - } - } else { - rc = MEMCACHED_NOTFOUND; - zval_dtor(value); - ZVAL_NULL(value); - } - } - - if (!Z_ISUNDEF(retval)) { - zval_ptr_dtor(&retval); - } - - zval_ptr_dtor(&zv_key); - zval_ptr_dtor(&ref_val); - zval_ptr_dtor(&zv_expiration); - zval_ptr_dtor(&ref_expiration); - zval_ptr_dtor(zobject); - return rc; -} - - -static -int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result) -{ - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - zval value; - zval retval; - uint64_t cas = 0; - zval z_result; - uint32_t flags = 0; - int rc = 0; - php_memc_object_t *intern = NULL; - - fci->retval = &retval; - fci->param_count = 2; - - payload = memcached_result_value(result); - payload_len = memcached_result_length(result); - flags = memcached_result_flags(result); - res_key = memcached_result_key_value(result); - res_key_len = memcached_result_key_length(result); - cas = memcached_result_cas(result); - - intern = Z_MEMC_OBJ_P(zmemc_obj); - - if (!s_memcached_result_to_zval(intern->memc, result, &value)) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - return -1; - } - - array_init(&z_result); - add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); - if (cas != 0) { - add_assoc_double_ex(&z_result, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } - - ZVAL_UNDEF(&retval); - zend_fcall_info_argn(fci, 2, zmemc_obj, &z_result); - - if (zend_call_function(fci, fcc) == FAILURE) { - php_error_docref(NULL, E_WARNING, "could not invoke result callback"); - rc = -1; - } - - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } - - zend_fcall_info_args_clear(fci, 1); - zval_ptr_dtor(&z_result); - - return rc; -} -/* }}} */ #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4181,7 +4077,6 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.lock_wait_min = 1000; php_memcached_globals->session.lock_retries = 5; php_memcached_globals->session.lock_expiration = 30; - php_memcached_globals->session.compression_enabled = 1; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; php_memcached_globals->session.number_of_replicas = 0; @@ -4196,10 +4091,10 @@ PHP_GINIT_FUNCTION(php_memcached) #endif php_memcached_globals->memc.serializer_name = NULL; - php_memcached_globals->memc.serializer = SERIALIZER_DEFAULT; - php_memcached_globals->memc.compression_type = NULL; + php_memcached_globals->memc.serializer_type = SERIALIZER_DEFAULT; + php_memcached_globals->memc.compression_name = NULL; php_memcached_globals->memc.compression_threshold = 2000; - php_memcached_globals->memc.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; php_memcached_globals->memc.store_retry_count = 2; diff --git a/php_memcached_private.h b/php_memcached_private.h index c6c0b77c..d19fe974 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -75,13 +75,24 @@ typedef unsigned long int uint32_t; /**************************************** Structures and definitions ****************************************/ -enum memcached_serializer { - SERIALIZER_PHP = 1, - SERIALIZER_IGBINARY = 2, - SERIALIZER_JSON = 3, +typedef enum { + SERIALIZER_PHP = 1, + SERIALIZER_IGBINARY = 2, + SERIALIZER_JSON = 3, SERIALIZER_JSON_ARRAY = 4, - SERIALIZER_MSGPACK = 5, -}; + SERIALIZER_MSGPACK = 5 +} php_memc_serializer_type; + +typedef enum { + COMPRESSION_TYPE_ZLIB = 1, + COMPRESSION_TYPE_FASTLZ = 2 +} php_memc_compression_type; + +typedef struct { + const char *name; + php_memc_serializer_type type; +} php_memc_serializer; + #ifdef HAVE_MEMCACHED_IGBINARY #define SERIALIZER_DEFAULT SERIALIZER_IGBINARY #define SERIALIZER_DEFAULT_NAME "igbinary" @@ -160,14 +171,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) struct { char *serializer_name; - char *compression_type; + char *compression_name; zend_long compression_threshold; double compression_factor; zend_long store_retry_count; /* Converted values*/ - enum memcached_serializer serializer; - zend_long compression_type_real; + php_memc_serializer_type serializer_type; + php_memc_compression_type compression_type; /* Whether we have initialised sasl for this process */ zend_bool sasl_initialised; diff --git a/tests/getdelayed.phpt b/tests/getdelayed.phpt index 7479e97b..c07acada 100644 --- a/tests/getdelayed.phpt +++ b/tests/getdelayed.phpt @@ -22,42 +22,61 @@ foreach ($data as $k => $v) { function myfunc() { $datas = func_get_args(); if (isset($datas[1])) { - unset($datas[1]['cas']); var_dump($datas[1]); } } -$m->getDelayed(array_keys($data), false, 'myfunc'); +$m->getDelayed(array_keys($data), true, 'myfunc'); ?> ---EXPECT-- -array(2) { +--EXPECTF-- +array(4) { ["key"]=> string(3) "foo" ["value"]=> string(8) "foo-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "bar" ["value"]=> string(8) "bar-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "baz" ["value"]=> string(8) "baz-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "lol" ["value"]=> string(8) "lol-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "kek" ["value"]=> string(8) "kek-data" -} + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} \ No newline at end of file diff --git a/tests/incrdecr_invalid_key.phpt b/tests/incrdecr_invalid_key.phpt index 8d4ab671..cd8c6b9b 100644 --- a/tests/incrdecr_invalid_key.phpt +++ b/tests/incrdecr_invalid_key.phpt @@ -9,6 +9,7 @@ $m = memc_get_instance (); var_dump($m->increment('', 1)); var_dump($m->decrement('', 1)); +?> --EXPECT-- bool(false) bool(false) From 27a22f3c0ab62f98d4e01e43caf2ad80840043fd Mon Sep 17 00:00:00 2001 From: Manabu Matsui Date: Mon, 8 Feb 2016 15:35:46 +0900 Subject: [PATCH 418/694] fix expiration --- php_memcached_session.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index bfb34e99..6dcb4cbe 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -25,6 +25,8 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 #define MEMC_SESS_LOCK_EXPIRATION 30 +#define REALTIME_MAXDELTA 60*60*24*30 + ps_module ps_mod_memcached = { PS_MOD_UPDATE_TIMESTAMP(memcached) }; @@ -92,16 +94,26 @@ int php_memc_session_minit(int module_number) return SUCCESS; } +static +time_t s_adjust_expiration(zend_long expiration) +{ + if (expiration <= REALTIME_MAXDELTA) { + return expiration; + } else { + return time(NULL) + expiration; + } +} + static time_t s_lock_expiration() { if (MEMC_SESS_INI(lock_expiration) > 0) { - return time(NULL) + MEMC_SESS_INI(lock_expiration); + return s_adjust_expiration(MEMC_SESS_INI(lock_expiration)); } else { zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); if (max_execution_time > 0) { - return time(NULL) + max_execution_time; + return s_adjust_expiration(max_execution_time); } } return 0; @@ -111,7 +123,7 @@ static time_t s_session_expiration(zend_long maxlifetime) { if (maxlifetime > 0) { - return time(NULL) + maxlifetime; + return s_adjust_expiration(maxlifetime); } return 0; } From 27fa80fb260ee7d71b3562051d5a16c3f1fd1da0 Mon Sep 17 00:00:00 2001 From: Paul Werelds Date: Fri, 12 Feb 2016 15:50:58 +0100 Subject: [PATCH 419/694] Adds a missed SASL presence constraint --- php_memcached_session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 6dcb4cbe..61738559 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -68,9 +68,11 @@ void s_destroy_mod_data(memcached_st *memc) { php_memcached_user_data *user_data = memcached_get_user_data(memc); +#if HAVE_MEMCACHED_SASL if (user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } +#endif memcached_free(memc); pefree(memc, user_data->is_persistent); From 4ff385988358f12c577ac1a7d9282600d6992b25 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 17 Feb 2016 14:30:43 +0100 Subject: [PATCH 420/694] Update package.xml for release --- package.xml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/package.xml b/package.xml index 9d3be440..8ec578a7 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-01 + 2016-02-17 3.0.0b1 3.0.0 @@ -33,17 +33,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated +before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters + * set/get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) @@ -52,7 +54,7 @@ Session handler * Fixes crash with session_regenerate_id (work-around for PHP bug) Tests - * Fix several broken tests + * Fix several problematic tests @@ -161,6 +163,7 @@ Tests + @@ -188,21 +191,22 @@ Tests 3.0.0b1 3.0.0 - 2016-02-01 + 2016-02-17 PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated +before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters + * set/get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed - * CAS tokens are returned as integers and in case of too large values they overflow to strings + * CAS tokens are returned as integers and they overflow to strings as needed Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) @@ -211,7 +215,7 @@ Session handler * Fixes crash with session_regenerate_id (work-around for PHP bug) Tests - * Fix several broken tests + * Fix several problematic tests From 6ace07da69a5ebc021e56a9d2f52cdc8897b4f23 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 17 Feb 2016 14:39:49 +0100 Subject: [PATCH 421/694] Tests for default behavior --- php_memcached.c | 49 ++++++++++++++++++++++++++++++++++--- php_memcached_private.h | 9 ++++++- tests/default_behavior.phpt | 32 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 tests/default_behavior.phpt diff --git a/php_memcached.c b/php_memcached.c index c01b7f94..04e330fc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -341,6 +341,11 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + + MEMC_INI_ENTRY("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) + MEMC_INI_ENTRY("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) + MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) + PHP_INI_END() /* }}} */ @@ -1190,7 +1195,8 @@ static PHP_METHOD(Memcached, __construct) } if (!intern->memc) { - // TODO: handle allocation fail + php_error_docref(NULL, E_ERROR, "Failed to allocate memory for memcached structure"); + /* never reached */ } memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); @@ -1203,6 +1209,38 @@ static PHP_METHOD(Memcached, __construct) memcached_set_user_data(intern->memc, memc_user_data); + /* Set default behaviors */ + { +#ifdef mikko_0 + fprintf (stderr, "consistent_hash_enabled=%d binary_protocol_enabled=%d connect_timeout=%ld\n", + MEMC_G(default_behavior.consistent_hash_enabled), MEMC_G(default_behavior.binary_protocol_enabled), MEMC_G(default_behavior.connect_timeout)); +#endif + + memcached_return rc; + + if (MEMC_G(default_behavior.consistent_hash_enabled)) { + + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); + } + } + + if (MEMC_G(default_behavior.binary_protocol_enabled)) { + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); + } + } + + if (MEMC_G(default_behavior.connect_timeout)) { + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); + } + } + } + if (fci.size) { if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { /* error calling or exception thrown from callback */ @@ -2263,7 +2301,7 @@ PHP_METHOD(Memcached, addServer) } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 if (host->val[0] == '/') { /* unix domain socket */ @@ -2712,7 +2750,7 @@ static PHP_METHOD(Memcached, flush) } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); status = memcached_flush(intern->memc, delay); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -4100,6 +4138,11 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.sasl_initialised = 0; php_memcached_globals->no_effect = 0; + + /* Defaults for certain options */ + php_memcached_globals->memc.default_behavior.consistent_hash_enabled = 0; + php_memcached_globals->memc.default_behavior.binary_protocol_enabled = 0; + php_memcached_globals->memc.default_behavior.connect_timeout = 0; } zend_module_entry memcached_module_entry = { diff --git a/php_memcached_private.h b/php_memcached_private.h index d19fe974..329afc8d 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -150,7 +150,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_long lock_retries; zend_long lock_expiration; - zend_bool compression_enabled; zend_bool binary_protocol_enabled; zend_bool consistent_hash_enabled; @@ -183,6 +182,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) /* Whether we have initialised sasl for this process */ zend_bool sasl_initialised; + struct { + + zend_bool consistent_hash_enabled; + zend_bool binary_protocol_enabled; + zend_long connect_timeout; + + } default_behavior; + } memc; /* For deprecated values */ diff --git a/tests/default_behavior.phpt b/tests/default_behavior.phpt new file mode 100644 index 00000000..de46cec2 --- /dev/null +++ b/tests/default_behavior.phpt @@ -0,0 +1,32 @@ +--TEST-- +Default behaviors +--SKIPIF-- + +--FILE-- +getOption(Memcached::OPT_DISTRIBUTION) == Memcached::DISTRIBUTION_MODULA); +var_dump ($m->getOption(Memcached::OPT_BINARY_PROTOCOL) == false); +var_dump ($m->getOption(Memcached::OPT_CONNECT_TIMEOUT) != 0); + +ini_set('memcached.default_consistent_hash', true); +ini_set('memcached.default_binary_protocol', true); +ini_set('memcached.default_connect_timeout', 1212); + +$m = new Memcached(); +var_dump ($m->getOption(Memcached::OPT_DISTRIBUTION) == Memcached::DISTRIBUTION_CONSISTENT); +var_dump ($m->getOption(Memcached::OPT_BINARY_PROTOCOL) == true); +var_dump ($m->getOption(Memcached::OPT_CONNECT_TIMEOUT) == 1212); + +echo "OK"; + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +OK From 21fd64ff3182accc38273d7c3aebd914f15e6f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Mon, 22 Feb 2016 17:54:53 +0100 Subject: [PATCH 422/694] Up-to-date link to igbinary --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e827e6fa..53a466e4 100644 --- a/README.markdown +++ b/README.markdown @@ -23,4 +23,4 @@ Resources --------- * [libmemcached](http://libmemcached.org/libMemcached.html) * [memcached](http://memcached.org/) - * [igbinary](https://github.com/phadej/igbinary/) + * [igbinary](https://github.com/igbinary/igbinary) From 3537b50d2548eb9d884cb8e980456bdfc9594523 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 22 Feb 2016 20:17:57 +0000 Subject: [PATCH 423/694] Update for release --- package.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.xml b/package.xml index 8ec578a7..40f0323f 100644 --- a/package.xml +++ b/package.xml @@ -21,14 +21,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-17 + 2016-02-22 - 3.0.0b1 + 3.0.0a1 3.0.0 - beta - beta + alpha + alpha PHP @@ -38,7 +38,7 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters. + * get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour @@ -184,14 +184,14 @@ Tests - beta - beta + alpha + alpha - 3.0.0b1 + 3.0.0a1 3.0.0 - 2016-02-17 + 2016-02-22 PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of @@ -199,7 +199,7 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters. + * get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour From 9b8126c043c79d75b3a160735a66572e5debdb0a Mon Sep 17 00:00:00 2001 From: xjewer Date: Thu, 3 Mar 2016 23:43:20 +0300 Subject: [PATCH 424/694] fix arginfo_get* --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 04e330fc..ced03752 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3716,12 +3716,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) From 4ee38195289edfa7ae936d2b0a434869c97d8817 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 5 Mar 2016 18:22:05 +0000 Subject: [PATCH 425/694] Fixes crash --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 04e330fc..804af76f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1339,6 +1339,11 @@ static void s_clear_keys(php_memc_keys_t *keys) { size_t i; + + if (!keys->num_valid_keys) { + return; + } + for (i = 0; i < keys->num_valid_keys; i++) { zend_string_release (keys->strings[i]); } From 412daa91ce3fb9b4fa6aa50f118db1b17cb6cd3c Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:39:57 +0100 Subject: [PATCH 426/694] remove duplicate 2.2.0b1 from package.xml --- package.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/package.xml b/package.xml index 0ebc86f9..fe35edac 100644 --- a/package.xml +++ b/package.xml @@ -162,20 +162,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Added the OPT_SERVER_TIMEOUT_LIMIT behaviour - - - betastable - 2.2.0b12.2.0 - 2013-10-28 - -- Reinstate support for libememcached 0.x series -- Added SASL support to session handler -- Added Memcached::flushBuffers as per GH #78 -- Fixes GH #54: Fixed UDP server adding with newer libmemcached -- Fixed PHP bug #65334: (Segfault if uncompress value failed) -- Fixes GH #14: get with cas token fails to fetch all results -- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - betastable From 0569c515c921e697b076008fabbc92a78222d882 Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:40:14 +0100 Subject: [PATCH 427/694] add missing releases (and dates for all) to changelog --- ChangeLog | 76 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9b00ea5..05f77181 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,17 @@ memcached extension changelog -Version 2.2.0b1 ---------------- +Version 2.2.0 (2014-04-01) +-------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + +Version 2.2.0RC1 (2014-03-12) +----------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + * Fixes incorrect size when compressing serialized objects + * Fixes endianess of compressed values + +Version 2.2.0b1 (2013-10-28) +---------------------------- * Reinstate support for libememcached 0.x series * Added SASL support to session handler * Added Memcached::flushBuffers as per GH #78 @@ -20,28 +30,28 @@ Version 2.2.0b1 * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization * Memcached::setSaslAuthData returns correct status on success - * Added support for user-defined flags in set and get operations + * Added support for user-defined flags in set and get operations -Version 2.1.0 -------------- +Version 2.1.0 (2012-08-06) +-------------------------- * Drop support for libmemcached 0.x series, now 1.0.x is required * Add support for virtual bucket distribution * Fix compilation against PHP 5.2 -Version 2.0.1 -------------- +Version 2.0.1 (2012-03-03) +-------------------------- * Fix embedded version number to be not -dev -Version 2.0.0 -------------- +Version 2.0.0 (2012-03-02) +-------------------------- * Add touch() and touchByKey() methods * Add resetServerList() and quit() methods * Support binary protocol in sessions * Make it work with libmemcached up to 1.0.4 * Test against PHP 5.4.0 -Version 2.0.0b2 ---------------- +Version 2.0.0b2 (2011-06-24) +---------------------------- * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. @@ -61,8 +71,8 @@ Version 2.0.0b2 * Make increment/decrement initialize value when it is not available (when using binary protocol) -Version 2.0.0b1 ---------------- +Version 2.0.0b1 (2011-03-12) +---------------------------- * Add fastlz library that provides better/faster payload compression * Add configure switch to enable/disable JSON serialization support * Add getAllKeys() method @@ -84,23 +94,27 @@ Version 2.0.0b1 * Add 'on_new' callback to constructor * Add SASL support -Version 1.0.1 -------------- +Version 1.0.2 (2010-05-03) +-------------------------- + * Fix build for libmemcached-0.39 (memcached_server_list() issue) + +Version 1.0.1 (2010-03-11) +-------------------------- * Fix JSON API handling to account for PHP 5.2/5.3 version differences. * Add memcached.sess_locking, memcached.sess_lock_wait, and memcached.sess_prefix INI entries. * Add OPT_AUTO_EJECT_HOSTS option. -Version 1.0.0 -------------- +Version 1.0.0 (2009-07-04) +-------------------------- * 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). -Version 0.2.0 -------------- +Version 0.2.0 (2009-06-04) +-------------------------- * Add JSON serializer support, requires PHP 5.2.10+. * Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective serializers are available. @@ -114,25 +128,25 @@ Version 0.2.0 the cache when upgrading to this version. * Add several tests. -Version 0.1.5 -------------- +Version 0.1.5 (2009-03-31) +-------------------------- * Implement getVersion(). * Add support for preserving boolean value types. * Fix crash when child class does not call constructor. * Fix bug #16084 (Crash when addServers is called with an associative array). * ZTS compilation fixes. -Version 0.1.4 -------------- +Version 0.1.4 (2009-02-13) +-------------------------- * Fix compilation against PHP 5.3. * Add support for 'igbinary' serializer (Oleg Grenrus) -Version 0.1.3 -------------- +Version 0.1.3 (2009-02-06) +-------------------------- * Bludgeon bug #15896 (Memcached setMulti error) into submission. -Version 0.1.2 -------------- +Version 0.1.2 (2009-02-06) +-------------------------- * Fix bug #15896 (Memcached setMulti error). * Check for empty key in getServerByKey(). * Allow passing 'null' for callbacks. @@ -141,12 +155,12 @@ Version 0.1.2 * Allow only strings as the append/prepend value. * Remove expiration parameter from append/prepend. -Version 0.1.1 -------------- +Version 0.1.1 (2009-02-02) +-------------------------- * Add OPT_LIBKETAMA_COMPATIBLE option. * Implement addServers() method. * Swap internal compressed and serialized flags to be compatible with other clients. -Version 0.1.0 -------------- +Version 0.1.0 (2009-01-29) +-------------------------- * Initial release From 4bb264e60005e19b5573822d9d374b4cde8d1c3b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:37:27 -0700 Subject: [PATCH 428/694] Document ini settings for the default memcached connection configurations This documents memcached.default_consistent_hash, default_binary_protocol, and default_connect_timeout. For issue #233 --- memcached.ini | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/memcached.ini b/memcached.ini index 1aa9f266..e70c6b41 100644 --- a/memcached.ini +++ b/memcached.ini @@ -111,3 +111,32 @@ memcached.serializer = "igbinary" ; environment. ; the default is 2 memcached.store_retry_count = 2 + +; Sets the default for consistent hashing for new connections. +; (To configure consistent hashing for session connections, +; use memcached.sess_consistent_hash instead) +; +; If set to On, consistent hashing (libketama) is used +; for session handling. +; When consistent hashing is used, one can add or remove cache +; node(s) without messing up too much with existing keys +; default is Off +memcached.default_consistent_hash = Off + +; Sets the default memcached protocol for new connections. +; (To configure the memcached protocol for connections used by sessions, +; use memcached.sess_binary_protocol instead) +; +; If set to On, the memcached binary protocol is used by default. +; If set to Off, the memcached text protocol is used. +; Default is Off +memcached.default_binary_protocol = Off + +; Sets the default memcached connection timeout for new connections. +; (To configure the memcached connection timeout for sessions, +; use memcached.sess_connect_timeout instead) +; In non-blocking mode this changes the value of the timeout. +; during socket connection in milliseconds. Specifying -1 means an infinite timeout. +; Specifying 0 means using the memcached library's default connection timeout. +; Default is 0. +memcached.default_connect_timeout = 0 From e755d9db127d946740314d48dd01c81f43df0a7b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:16:35 -0700 Subject: [PATCH 429/694] Document miscellaneous ini settings and new defaults for PHP7 release This updates some of the memcached.ini documentation settings to reflect the default ini settings used in php_memcached.c. Some new settings were added, and other settings had changes to their defaults. There are other new/updated settings, which can be changed in other PRs. For issue #233 --- memcached.ini | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/memcached.ini b/memcached.ini index 1aa9f266..68f0a1ab 100644 --- a/memcached.ini +++ b/memcached.ini @@ -12,11 +12,17 @@ memcached.sess_locking = On ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max -; is reached -memcached.sess_lock_wait_min = 0; +; is reached, after which any further retries will take sess_lock_wait_max seconds. +; Default is 1000. +memcached.sess_lock_wait_min = 1000; ; The maximum time, in milliseconds, to wait between session lock attempts. -memcached.sess_lock_wait_max = 0; +; Default is 2000. +memcached.sess_lock_wait_max = 2000; + +; The number of times to retry locking the session lock, not including the first attempt. +; Default is 5. +memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to @@ -29,16 +35,24 @@ memcached.sess_lock_expire = 0; ; the default value is "memc.sess.key." memcached.sess_prefix = "memc.sess.key." +; Whether or not to re-use the memcached connections corresponding to the value(s) +; of session.save_path after the execution of the script ends. +; Don't use this if certain settings (e.g. SASL settings, sess_binary_protocol) would +; be overridden between requests. +; Default is Off. +memcached.sess_persistent = Off + ; memcached session consistent hash mode ; if set to On, consistent hashing (libketama) is used ; for session handling. ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys -; default is Off -memcached.sess_consistent_hash = Off +; default is On +memcached.sess_consistent_hash = On -; Allow failed memcached server to automatically be removed -memcached.sess_remove_failed = 1 +; Allow failed memcached server to automatically be removed. +; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) +memcached.sess_remove_failed_servers = Off ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. @@ -57,7 +71,7 @@ memcached.sess_binary = Off memcached.sess_randomize_replica_read = Off ; memcached connect timeout value -; In non-blocking mode this changes the value of the timeout +; In non-blocking mode this changes the value of the timeout ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. memcached.sess_connect_timeout = 1000 From b86282c5d6b7bacb435b4a49e5b986409a1c7c8a Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:40:14 +0100 Subject: [PATCH 430/694] add missing releases (and dates for all) to changelog --- ChangeLog | 76 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9b00ea5..05f77181 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,17 @@ memcached extension changelog -Version 2.2.0b1 ---------------- +Version 2.2.0 (2014-04-01) +-------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + +Version 2.2.0RC1 (2014-03-12) +----------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + * Fixes incorrect size when compressing serialized objects + * Fixes endianess of compressed values + +Version 2.2.0b1 (2013-10-28) +---------------------------- * Reinstate support for libememcached 0.x series * Added SASL support to session handler * Added Memcached::flushBuffers as per GH #78 @@ -20,28 +30,28 @@ Version 2.2.0b1 * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization * Memcached::setSaslAuthData returns correct status on success - * Added support for user-defined flags in set and get operations + * Added support for user-defined flags in set and get operations -Version 2.1.0 -------------- +Version 2.1.0 (2012-08-06) +-------------------------- * Drop support for libmemcached 0.x series, now 1.0.x is required * Add support for virtual bucket distribution * Fix compilation against PHP 5.2 -Version 2.0.1 -------------- +Version 2.0.1 (2012-03-03) +-------------------------- * Fix embedded version number to be not -dev -Version 2.0.0 -------------- +Version 2.0.0 (2012-03-02) +-------------------------- * Add touch() and touchByKey() methods * Add resetServerList() and quit() methods * Support binary protocol in sessions * Make it work with libmemcached up to 1.0.4 * Test against PHP 5.4.0 -Version 2.0.0b2 ---------------- +Version 2.0.0b2 (2011-06-24) +---------------------------- * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. @@ -61,8 +71,8 @@ Version 2.0.0b2 * Make increment/decrement initialize value when it is not available (when using binary protocol) -Version 2.0.0b1 ---------------- +Version 2.0.0b1 (2011-03-12) +---------------------------- * Add fastlz library that provides better/faster payload compression * Add configure switch to enable/disable JSON serialization support * Add getAllKeys() method @@ -84,23 +94,27 @@ Version 2.0.0b1 * Add 'on_new' callback to constructor * Add SASL support -Version 1.0.1 -------------- +Version 1.0.2 (2010-05-03) +-------------------------- + * Fix build for libmemcached-0.39 (memcached_server_list() issue) + +Version 1.0.1 (2010-03-11) +-------------------------- * Fix JSON API handling to account for PHP 5.2/5.3 version differences. * Add memcached.sess_locking, memcached.sess_lock_wait, and memcached.sess_prefix INI entries. * Add OPT_AUTO_EJECT_HOSTS option. -Version 1.0.0 -------------- +Version 1.0.0 (2009-07-04) +-------------------------- * 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). -Version 0.2.0 -------------- +Version 0.2.0 (2009-06-04) +-------------------------- * Add JSON serializer support, requires PHP 5.2.10+. * Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective serializers are available. @@ -114,25 +128,25 @@ Version 0.2.0 the cache when upgrading to this version. * Add several tests. -Version 0.1.5 -------------- +Version 0.1.5 (2009-03-31) +-------------------------- * Implement getVersion(). * Add support for preserving boolean value types. * Fix crash when child class does not call constructor. * Fix bug #16084 (Crash when addServers is called with an associative array). * ZTS compilation fixes. -Version 0.1.4 -------------- +Version 0.1.4 (2009-02-13) +-------------------------- * Fix compilation against PHP 5.3. * Add support for 'igbinary' serializer (Oleg Grenrus) -Version 0.1.3 -------------- +Version 0.1.3 (2009-02-06) +-------------------------- * Bludgeon bug #15896 (Memcached setMulti error) into submission. -Version 0.1.2 -------------- +Version 0.1.2 (2009-02-06) +-------------------------- * Fix bug #15896 (Memcached setMulti error). * Check for empty key in getServerByKey(). * Allow passing 'null' for callbacks. @@ -141,12 +155,12 @@ Version 0.1.2 * Allow only strings as the append/prepend value. * Remove expiration parameter from append/prepend. -Version 0.1.1 -------------- +Version 0.1.1 (2009-02-02) +-------------------------- * Add OPT_LIBKETAMA_COMPATIBLE option. * Implement addServers() method. * Swap internal compressed and serialized flags to be compatible with other clients. -Version 0.1.0 -------------- +Version 0.1.0 (2009-01-29) +-------------------------- * Initial release From ffd1c64ccc5d38c4a12d6bd880e917171a77a8da Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:39:57 +0100 Subject: [PATCH 431/694] remove duplicate 2.2.0b1 from package.xml --- package.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/package.xml b/package.xml index 40f0323f..244acfab 100644 --- a/package.xml +++ b/package.xml @@ -225,20 +225,6 @@ Tests - Added the OPT_SERVER_TIMEOUT_LIMIT behaviour - - - betastable - 2.2.0b12.2.0 - 2013-10-28 - -- Reinstate support for libememcached 0.x series -- Added SASL support to session handler -- Added Memcached::flushBuffers as per GH #78 -- Fixes GH #54: Fixed UDP server adding with newer libmemcached -- Fixed PHP bug #65334: (Segfault if uncompress value failed) -- Fixes GH #14: get with cas token fails to fetch all results -- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - betastable From 4c13c4721fbac47262bd04bc6de47ea9f968b103 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 20:44:01 +0100 Subject: [PATCH 432/694] fix travis build, msgpack changed structure --- .travis/travis.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 1eab43fb..453ed6be 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,6 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php7 phpize ./configure make From 65ebcd5d62d6e374dadf6c335ba1736855e56f71 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 21:00:31 +0100 Subject: [PATCH 433/694] fix travis build, msgpack changed structure --- .travis/travis.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/travis.sh b/.travis/travis.sh index f90cae9f..05f3da95 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -73,6 +73,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php + git checkout php5 phpize ./configure make From b79eebc923795d11ecb27ba9ee32cffcea09f033 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 21:01:59 +0100 Subject: [PATCH 434/694] fix ci img in readme [ci skip] --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e827e6fa..bb76f076 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,6 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=master)](https://travis-ci.org/php-memcached-dev/php-memcached) +[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=php7)](https://travis-ci.org/php-memcached-dev/php-memcached) Description ----------- From 6ee96cad7be5caa1f13a1f3e5a4d5f900b9c04ce Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 4 Apr 2016 06:40:56 +0100 Subject: [PATCH 435/694] Fix #238 (memory errors in s_stat_execute_cb) --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9bff2fa8..dcf1f0da 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2635,8 +2635,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch zval zv; array_init(&zv); - server_values = &zv; - add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + server_values = zend_hash_str_add(Z_ARRVAL_P(return_value), server_key, server_key_len, &zv); } spprintf (&buffer, 0, "%.*s", value_length, value); From f31ad20468a8b0ccdd57cf8028b807bd887b4089 Mon Sep 17 00:00:00 2001 From: Konstantin Leboev Date: Tue, 10 May 2016 13:25:28 +0300 Subject: [PATCH 436/694] Check the existence of an error, and only then if it is the maximum value. --- php_memcached.c | 4 ++-- tests/incrdecr.phpt | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index dcf1f0da..d9879f8c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2248,11 +2248,11 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } } - if (value == UINT64_MAX) { + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } - if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + if (value == UINT64_MAX) { RETURN_FALSE; } diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index 3addcfd3..4a30daa6 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -10,8 +10,11 @@ $m = memc_get_instance (); echo "Not there\n"; $m->delete('foo'); var_dump($m->increment('foo', 1)); +var_dump($m->getResultCode()); var_dump($m->decrement('foo', 1)); +var_dump($m->getResultCode()); var_dump($m->get('foo')); +var_dump($m->getResultCode()); echo "Normal\n"; $m->set('foo', 1); @@ -37,8 +40,11 @@ var_dump($m->get('foo')); --EXPECT-- Not there bool(false) +int(16) bool(false) +int(16) bool(false) +int(16) Normal int(1) int(2) From d9b2c9f38410471adc5775543ac11aa5021b7647 Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Thu, 9 Jun 2016 00:43:42 +0800 Subject: [PATCH 437/694] fix: null-terminated zend_string in s_decompress_value --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index dcf1f0da..72db2cb2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3443,6 +3443,8 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); } + ZSTR_VAL(buffer)[stored_length] = '\0'; + if (!decompress_status) { php_error_docref(NULL, E_WARNING, "could not decompress value"); zend_string_release (buffer); From 7266824772d51f4a064e7478d6bbc551dcf445d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Thu, 9 Jun 2016 23:49:49 +0200 Subject: [PATCH 438/694] Fix object key validation --- php_memcached.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c1bce93b..72bc8991 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -576,7 +576,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1448,7 +1448,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1599,7 +1599,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1717,7 +1717,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1817,7 +1817,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } From 382a786f9808e5b46cccf7e8e75399eaa79a7412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Fri, 10 Jun 2016 00:15:18 +0200 Subject: [PATCH 439/694] Added tests for the extended key validation --- tests/keys.phpt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/keys.phpt b/tests/keys.phpt index 0ed90896..7453d537 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -15,9 +15,18 @@ $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->set ('binarykeywith\nnewline', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->set ('asciikeywith\nnewline', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +var_dump ($ascii->set (''/*empty key*/, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -30,4 +39,10 @@ bool(false) bool(true) bool(false) bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) OK From 5bd1a1fac50bf836fd96b0797326dd6b3f6663ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Fri, 10 Jun 2016 00:33:14 +0200 Subject: [PATCH 440/694] fix added tests --- tests/keys.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/keys.phpt b/tests/keys.phpt index 7453d537..978670dc 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -15,13 +15,13 @@ $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -var_dump ($binary->set ('binarykeywith\nnewline', 'this is a test')); +var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -var_dump ($binary->set ('asciikeywith\nnewline', 'this is a test')); +var_dump ($binary->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set (''/*empty key*/, 'this is a test')); From 6e32d4013357ccc89c980ae6bf04bfa5efd1e15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Sat, 11 Jun 2016 01:45:40 +0200 Subject: [PATCH 441/694] Use a constant for object key max length --- php_memcached.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 72bc8991..77dd8c29 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -57,6 +57,11 @@ #define JSON_PARSER_DEFAULT_DEPTH 512 #endif +/**************************************** + Protocol parameters +****************************************/ +#define MEMC_OBJECT_KEY_MAX_LENGTH 250 + /**************************************** Custom options ****************************************/ @@ -576,7 +581,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1448,7 +1453,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1599,7 +1604,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1717,7 +1722,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1817,7 +1822,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } From 0e517902d63ed82a9390bd8094d546f52899ce9f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 21 Jul 2016 18:59:01 +0800 Subject: [PATCH 442/694] Improved the tests --- tests/001.phpt | 2 +- tests/add.phpt | 2 +- tests/append.phpt | 2 +- tests/bad_construct.phpt | 2 +- tests/bug_16084.phpt | 2 +- tests/bug_16959.phpt | 2 +- tests/bug_17137.phpt | 2 +- tests/bug_18639.phpt | 6 +++--- tests/cachecallback.phpt | 2 +- tests/callback_exception.phpt | 2 +- tests/callback_exception_2.phpt | 2 +- tests/cas.phpt | 2 +- tests/cas_multi.phpt | 2 +- tests/check_if_persistent.phpt | 2 +- tests/check_if_pristine.phpt | 2 +- tests/clone.phpt | 2 +- tests/compression_types.phpt | 2 +- tests/conf_persist.phpt | 2 +- tests/config.inc | 4 +++- tests/construct.phpt | 2 +- tests/construct_persistent.phpt | 2 +- tests/default_behavior.phpt | 2 +- tests/deleted.phpt | 2 +- tests/deletemulti.phpt | 2 +- tests/deletemultitypes.phpt | 2 +- tests/experimental/add_bykey.phpt | 6 +++--- tests/experimental/addserver_unixdomain.phpt | 2 +- tests/experimental/append_bykey.phpt | 6 +++--- tests/experimental/cas_bykey.phpt | 6 +++--- tests/experimental/cas_invalid_key.phpt | 6 +++--- tests/experimental/delete_bykey.phpt | 6 +++--- tests/experimental/deletemulti_nonstringkeys.phpt | 7 +++---- tests/experimental/extreme_floats.phpt | 6 +++--- tests/experimental/fetch.phpt | 6 +++--- tests/experimental/fetch_badunserialize.phpt | 6 +++--- tests/experimental/fetchall_badunserialize.phpt | 6 +++--- tests/experimental/get.phpt | 6 +++--- tests/experimental/get_bykey.phpt | 6 +++--- tests/experimental/get_bykey_cas.phpt | 6 +++--- tests/experimental/get_udp.phpt | 6 +++--- tests/experimental/getdelayed_badserver.phpt | 2 +- tests/experimental/getdelayed_badunserialize.phpt | 6 +++--- tests/experimental/getdelayed_bykey.phpt | 6 +++--- tests/experimental/getdelayed_bykey_cas.phpt | 6 +++--- tests/experimental/getdelayed_cbthrows.phpt | 6 +++--- tests/experimental/getdelayed_nonstring_keys.phpt | 6 +++--- tests/experimental/getmulti_badserver.phpt | 2 +- tests/experimental/getmulti_badunserialize.phpt | 6 +++--- tests/experimental/getmulti_bykey.phpt | 6 +++--- tests/experimental/getmulti_empty.phpt | 6 +++--- tests/experimental/getmulti_partial_error.phpt | 6 +++--- tests/experimental/getversion.phpt | 5 +++-- tests/experimental/locale_float.phpt | 13 +++++++------ tests/experimental/moduleinfo.phpt | 4 ++-- tests/experimental/prepend_bykey.phpt | 6 +++--- tests/experimental/replace_bykey.phpt | 6 +++--- tests/experimental/serializer/serializer_php.phpt | 6 +++--- .../serializer/serializer_php_bad_serialize.phpt | 6 +++--- .../serializer/serializer_php_bad_unserialize.phpt | 12 ++++++------ tests/experimental/serializer_igbinary.phpt | 2 +- tests/experimental/serializer_json.phpt | 2 +- tests/experimental/session_gc.phpt | 5 ++++- tests/experimental/set_bykey.phpt | 6 +++--- tests/experimental/set_comp_below_factor.phpt | 6 +++--- tests/experimental/set_default_serializer.phpt | 2 +- tests/experimental/set_invalid_serializer.phpt | 2 +- tests/experimental/setget_zero_factor.phpt | 6 +++--- tests/experimental/setmulti_badserialize.phpt | 6 +++--- tests/experimental/setmulti_bykey.phpt | 6 +++--- tests/experimental/stats.phpt | 2 +- tests/experimental/stats_badserver.phpt | 2 +- tests/expire.phpt | 2 +- tests/flush_buffers.phpt | 2 +- tests/get_flags.phpt | 2 +- tests/getdelayed.phpt | 2 +- tests/getmulti.phpt | 2 +- tests/getserverbykey.phpt | 2 +- tests/getserverlist.phpt | 2 +- tests/gh_155.phpt | 3 +-- tests/gh_21.phpt | 2 +- tests/gh_77.phpt | 2 +- tests/gh_90.phpt | 2 +- tests/gh_93.phpt | 2 +- tests/incrdecr.phpt | 2 +- tests/incrdecr_bykey.phpt | 2 +- tests/incrdecr_initial.phpt | 2 +- tests/incrdecr_invalid_key.phpt | 2 +- tests/invalid_options.phpt | 2 +- tests/invoke_callback.phpt | 6 +++--- tests/invoke_callback_2.phpt | 2 +- tests/invoke_callback_twice.phpt | 2 +- tests/keys.phpt | 2 +- tests/localserver.phpt | 2 +- tests/multi_order.phpt | 2 +- tests/no-not-found.phpt | 2 +- tests/options.phpt | 2 +- tests/pr_75.phpt | 2 +- tests/prepend.phpt | 2 +- tests/replace.phpt | 2 +- tests/rescode.phpt | 2 +- tests/session_badconf_emptyprefix.phpt | 2 +- tests/session_badconf_locktime.phpt | 2 +- tests/session_badconf_prefix.phpt | 2 +- tests/session_badconf_servers.phpt | 2 +- tests/session_basic.phpt | 2 +- tests/session_basic2.phpt | 2 +- tests/session_basic3.phpt | 2 +- tests/session_lock.phpt | 2 +- tests/session_regenerate.phpt | 2 +- tests/set_large.phpt | 2 +- tests/setmulti.phpt | 2 +- tests/setoptions.phpt | 2 +- tests/stats.phpt | 2 +- tests/touch_binary.phpt | 2 +- tests/types_igbinary.phpt | 2 +- tests/types_igbinary_multi.phpt | 2 +- tests/types_json.phpt | 2 +- tests/types_json_multi.phpt | 2 +- tests/types_msgpack.phpt | 2 +- tests/types_msgpack_multi.phpt | 2 +- tests/types_php.phpt | 2 +- tests/types_php_multi.phpt | 2 +- tests/undefined_set.phpt | 2 +- tests/user-flags.phpt | 2 +- tests/vbucket.phpt | 4 ++-- tests/version.phpt | 2 +- 126 files changed, 214 insertions(+), 209 deletions(-) diff --git a/tests/001.phpt b/tests/001.phpt index d5085cd5..a66d6df3 100644 --- a/tests/001.phpt +++ b/tests/001.phpt @@ -1,7 +1,7 @@ --TEST-- Check for memcached presence --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); diff --git a/tests/bug_16959.phpt b/tests/bug_16959.phpt index f03a7091..2411e15a 100644 --- a/tests/bug_16959.phpt +++ b/tests/bug_16959.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached: Bug #16959 (getMulti + BINARY_PROTOCOL problem) --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- getServerByKey('1')); bool(true) array(3) { ["host"]=> - string(9) "127.0.0.1" + string(9) "%s" ["port"]=> - int(11211) + int(%d) ["weight"]=> int(%r[01]%r) } diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 31a736b7..41edfc5c 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::get() with cache callback --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- --FILE-- + --FILE-- + --FILE-- + --FILE-- addServer($host, $port); - $memcached->flush (); + if ($memcached->flush() === false) { + return NULL; + } return $memcached; } diff --git a/tests/construct.phpt b/tests/construct.phpt index c5c78977..49e508e7 100644 --- a/tests/construct.phpt +++ b/tests/construct.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached constructor --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); var_dump($m->addByKey('foo', 'foo', 1, 10)); diff --git a/tests/experimental/addserver_unixdomain.phpt b/tests/experimental/addserver_unixdomain.phpt index aaec92ae..4848015d 100644 --- a/tests/experimental/addserver_unixdomain.phpt +++ b/tests/experimental/addserver_unixdomain.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::addServer() unix doamin socket --SKIPIF-- - + --CLEAN-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setOption(Memcached::OPT_COMPRESSION, false); var_dump($m->setByKey('foo', 'foo', 'bar', 10)); diff --git a/tests/experimental/cas_bykey.phpt b/tests/experimental/cas_bykey.phpt index f33e24ad..f8c80fa5 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/experimental/cas_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::casByKey() --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('cas_test'); $cas_token = null; diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/experimental/cas_invalid_key.phpt index 3a69e40e..6011c4b8 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/experimental/cas_invalid_key.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::cas() with strange key --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); error_reporting(0); var_dump($m->cas(0, '', true, 10)); diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 9a198f15..807af8ca 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::deleteByKey() --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setByKey('keffe', 'eisaleeoo', "foo"); var_dump($m->getByKey('keffe', 'eisaleeoo')); diff --git a/tests/experimental/deletemulti_nonstringkeys.phpt b/tests/experimental/deletemulti_nonstringkeys.phpt index 69d56c78..2dac8920 100644 --- a/tests/experimental/deletemulti_nonstringkeys.phpt +++ b/tests/experimental/deletemulti_nonstringkeys.phpt @@ -1,12 +1,11 @@ --TEST-- Delete multi with integer keys --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); -$m->addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 1 => '1-data', diff --git a/tests/experimental/extreme_floats.phpt b/tests/experimental/extreme_floats.phpt index 0d530370..80ef568d 100644 --- a/tests/experimental/extreme_floats.phpt +++ b/tests/experimental/extreme_floats.phpt @@ -1,11 +1,11 @@ --TEST-- Extreme floats: max, min, Inf, -Inf, and NaN --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('float_inf', INF); $m->set('float_ninf', -INF); diff --git a/tests/experimental/fetch.phpt b/tests/experimental/fetch.phpt index e7eee9d3..13136c5b 100644 --- a/tests/experimental/fetch.phpt +++ b/tests/experimental/fetch.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached getDelayed() and fetch() with and without cas --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/fetch_badunserialize.phpt b/tests/experimental/fetch_badunserialize.phpt index 36a3049e..251d2ca5 100644 --- a/tests/experimental/fetch_badunserialize.phpt +++ b/tests/experimental/fetch_badunserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/experimental/fetchall_badunserialize.phpt index 6108498a..e3ad3310 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/experimental/fetchall_badunserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/get.phpt b/tests/experimental/get.phpt index 67e0b8f3..308bda98 100644 --- a/tests/experimental/get.phpt +++ b/tests/experimental/get.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::get() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); diff --git a/tests/experimental/get_bykey.phpt b/tests/experimental/get_bykey.phpt index 220dd44a..a392aaeb 100644 --- a/tests/experimental/get_bykey.phpt +++ b/tests/experimental/get_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('foo', 1, 10); diff --git a/tests/experimental/get_bykey_cas.phpt b/tests/experimental/get_bykey_cas.phpt index 6990927b..501b13a7 100644 --- a/tests/experimental/get_bykey_cas.phpt +++ b/tests/experimental/get_bykey_cas.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getByKey() with CAS --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); function the_callback(Memcached $memc, $key, &$value) { echo "called\n"; diff --git a/tests/experimental/get_udp.phpt b/tests/experimental/get_udp.phpt index 3e038e10..ad10a7cf 100644 --- a/tests/experimental/get_udp.phpt +++ b/tests/experimental/get_udp.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::set()/delete() UDP --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m_udp = new Memcached(); $m_udp->setOption(Memcached::OPT_USE_UDP, true); diff --git a/tests/experimental/getdelayed_badserver.phpt b/tests/experimental/getdelayed_badserver.phpt index dc0508fb..c4902174 100644 --- a/tests/experimental/getdelayed_badserver.phpt +++ b/tests/experimental/getdelayed_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getDelayedByKey() with bad server --SKIPIF-- - + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/getdelayed_bykey.phpt b/tests/experimental/getdelayed_bykey.phpt index 4b3ddf6b..a29f646b 100644 --- a/tests/experimental/getdelayed_bykey.phpt +++ b/tests/experimental/getdelayed_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_bykey_cas.phpt b/tests/experimental/getdelayed_bykey_cas.phpt index b874e739..43b19596 100644 --- a/tests/experimental/getdelayed_bykey_cas.phpt +++ b/tests/experimental/getdelayed_bykey_cas.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() with CAS --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_cbthrows.phpt b/tests/experimental/getdelayed_cbthrows.phpt index 482034b6..2b71b4b4 100644 --- a/tests/experimental/getdelayed_cbthrows.phpt +++ b/tests/experimental/getdelayed_cbthrows.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() with callback exception --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_nonstring_keys.phpt b/tests/experimental/getdelayed_nonstring_keys.phpt index 0e68344f..81363f3b 100644 --- a/tests/experimental/getdelayed_nonstring_keys.phpt +++ b/tests/experimental/getdelayed_nonstring_keys.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached getDelayed non string keys --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Bar { public function __toString() { diff --git a/tests/experimental/getmulti_badserver.phpt b/tests/experimental/getmulti_badserver.phpt index 21bbe192..a34825c2 100644 --- a/tests/experimental/getmulti_badserver.phpt +++ b/tests/experimental/getmulti_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getMulti() bad server --SKIPIF-- - + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public function __sleep() { diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/experimental/getmulti_bykey.phpt index 70ae01c5..e4eb112c 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/experimental/getmulti_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMultiByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('foo', 1, 10); $m->set('bar', 2, 10); diff --git a/tests/experimental/getmulti_empty.phpt b/tests/experimental/getmulti_empty.phpt index 7c8621da..6279104d 100644 --- a/tests/experimental/getmulti_empty.phpt +++ b/tests/experimental/getmulti_empty.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMulti() with empty array --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $v = $m->getMulti(array()); var_dump($v); diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/experimental/getmulti_partial_error.phpt index dc4daa50..fa392e9e 100644 --- a/tests/experimental/getmulti_partial_error.phpt +++ b/tests/experimental/getmulti_partial_error.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMulti() partial error --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array(); for ($i = 0; $i < 1000; $i++) { diff --git a/tests/experimental/getversion.phpt b/tests/experimental/getversion.phpt index 509ff5d5..55d06714 100644 --- a/tests/experimental/getversion.phpt +++ b/tests/experimental/getversion.phpt @@ -1,13 +1,14 @@ --TEST-- Memcached::getVersion() --SKIPIF-- - + --FILE-- getVersion()); -$m->addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . "/config.inc"; +$m = memc_get_instance (); $stats = $m->getVersion(); var_dump($stats); diff --git a/tests/experimental/locale_float.phpt b/tests/experimental/locale_float.phpt index e6967bdb..9c512124 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/experimental/locale_float.phpt @@ -2,14 +2,15 @@ Float should not consider locale --SKIPIF-- addServer('127.0.0.1', 11211); + +include dirname (__FILE__) . '/config.inc'; +$memcache = memc_get_instance (); setlocale(LC_NUMERIC, "fi_FI", 'sv_SV', 'nl_NL'); diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index a1f59b44..0f02a570 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -2,7 +2,7 @@ Memcached::phpinfo() --SKIPIF-- --FILE-- @@ -35,4 +35,4 @@ memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d memcached.sess_remove_failed => %d => %d %rmemcached.use_sasl => %d => %d -|%rmemcached.store_retry_count => %d => %d \ No newline at end of file +|%rmemcached.store_retry_count => %d => %d diff --git a/tests/experimental/prepend_bykey.phpt b/tests/experimental/prepend_bykey.phpt index 85b12f98..87d3fd38 100644 --- a/tests/experimental/prepend_bykey.phpt +++ b/tests/experimental/prepend_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::appendByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setOption(Memcached::OPT_COMPRESSION, false); var_dump($m->setByKey('foo', 'foo', 'bar', 10)); diff --git a/tests/experimental/replace_bykey.phpt b/tests/experimental/replace_bykey.phpt index 1cd858fb..b2f72836 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/experimental/replace_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::replaceByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); error_reporting(0); $m->delete('foo'); diff --git a/tests/experimental/serializer/serializer_php.phpt b/tests/experimental/serializer/serializer_php.phpt index ce3e7266..853d5bf4 100644 --- a/tests/experimental/serializer/serializer_php.phpt +++ b/tests/experimental/serializer/serializer_php.phpt @@ -2,12 +2,12 @@ Serializer basic --SKIPIF-- --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer/serializer_php_bad_serialize.phpt b/tests/experimental/serializer/serializer_php_bad_serialize.phpt index 39ef4745..81e88b0c 100644 --- a/tests/experimental/serializer/serializer_php_bad_serialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_serialize.phpt @@ -2,7 +2,7 @@ Serializer: exception while serializing --SKIPIF-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt index 86fba091..39d2cc37 100644 --- a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt @@ -2,10 +2,10 @@ Serializer: exception while unserializing --SKIPIF-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer_igbinary.phpt b/tests/experimental/serializer_igbinary.phpt index a762121e..4d2360bc 100644 --- a/tests/experimental/serializer_igbinary.phpt +++ b/tests/experimental/serializer_igbinary.phpt @@ -2,7 +2,7 @@ Serialize igbinary --SKIPIF-- diff --git a/tests/experimental/session_gc.phpt b/tests/experimental/session_gc.phpt index 561901fc..61dc7d3d 100644 --- a/tests/experimental/session_gc.phpt +++ b/tests/experimental/session_gc.phpt @@ -2,7 +2,10 @@ Session expiration --SKIPIF-- --INI-- diff --git a/tests/experimental/set_bykey.phpt b/tests/experimental/set_bykey.phpt index fa6d6a4b..e1fec459 100644 --- a/tests/experimental/set_bykey.phpt +++ b/tests/experimental/set_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::setByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); var_dump($m->setByKey('foo', 'foo', 1, 10)); echo $m->getResultMessage(), "\n"; diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/experimental/set_comp_below_factor.phpt index f3eece2f..12e6d6a4 100644 --- a/tests/experimental/set_comp_below_factor.phpt +++ b/tests/experimental/set_comp_below_factor.phpt @@ -1,11 +1,11 @@ --TEST-- Compress below factor and fail to plain. --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); ini_set('memcached.compression_threshold', 100); ini_set('memcached.compression_factor', 10); diff --git a/tests/experimental/set_default_serializer.phpt b/tests/experimental/set_default_serializer.phpt index f9658736..4886e9b7 100644 --- a/tests/experimental/set_default_serializer.phpt +++ b/tests/experimental/set_default_serializer.phpt @@ -1,7 +1,7 @@ --TEST-- Set default serializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); ini_set('memcached.compression_factor', 0); $array = range(1, 20000, 1); diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index b12b1d3a..5081eedc 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::setMultiByKey() with bad serialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public function __sleep() { diff --git a/tests/experimental/setmulti_bykey.phpt b/tests/experimental/setmulti_bykey.phpt index fad3db29..e3533c2f 100644 --- a/tests/experimental/setmulti_bykey.phpt +++ b/tests/experimental/setmulti_bykey.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::setMultiByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/stats.phpt b/tests/experimental/stats.phpt index 4f416384..26d814ce 100644 --- a/tests/experimental/stats.phpt +++ b/tests/experimental/stats.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getStats() --SKIPIF-- - + --FILE-- + --FILE-- --FILE-- diff --git a/tests/flush_buffers.phpt b/tests/flush_buffers.phpt index 989a4b63..a345edce 100644 --- a/tests/flush_buffers.phpt +++ b/tests/flush_buffers.phpt @@ -1,7 +1,7 @@ --TEST-- Test flushing buffers --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 643085ae..54d2b77f 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,8 +2,7 @@ Test for bug 155 --SKIPIF-- --FILE-- diff --git a/tests/gh_21.phpt b/tests/gh_21.phpt index 7302220e..920fb659 100644 --- a/tests/gh_21.phpt +++ b/tests/gh_21.phpt @@ -1,7 +1,7 @@ --TEST-- Test for Github issue 21 --SKIPIF-- - + --FILE-- --FILE-- diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt index 9434a2d7..733b7615 100644 --- a/tests/gh_90.phpt +++ b/tests/gh_90.phpt @@ -1,7 +1,7 @@ --TEST-- Test for GH #90 --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array(3) { ["host"]=> - string(9) "127.0.0.1" + string(9) "%s" ["port"]=> - int(11211) + int(%d) ["type"]=> string(3) "TCP" } diff --git a/tests/invoke_callback_2.phpt b/tests/invoke_callback_2.phpt index 276d1c26..07e84f94 100644 --- a/tests/invoke_callback_2.phpt +++ b/tests/invoke_callback_2.phpt @@ -1,7 +1,7 @@ --TEST-- Use callback initializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- --INI-- diff --git a/tests/session_badconf_locktime.phpt b/tests/session_badconf_locktime.phpt index 9bda76b6..edb2a49f 100644 --- a/tests/session_badconf_locktime.phpt +++ b/tests/session_badconf_locktime.phpt @@ -1,7 +1,7 @@ --TEST-- Session bad configurations, lock wait time --SKIPIF-- - --INI-- diff --git a/tests/session_badconf_prefix.phpt b/tests/session_badconf_prefix.phpt index 093485c4..c42e8376 100644 --- a/tests/session_badconf_prefix.phpt +++ b/tests/session_badconf_prefix.phpt @@ -2,7 +2,7 @@ Session bad configurations, prefix --SKIPIF-- --INI-- diff --git a/tests/session_badconf_servers.phpt b/tests/session_badconf_servers.phpt index 9fd911cd..b5c0803b 100644 --- a/tests/session_badconf_servers.phpt +++ b/tests/session_badconf_servers.phpt @@ -2,7 +2,7 @@ Session bad configurations, invalid save path (server list) --SKIPIF-- --INI-- diff --git a/tests/session_basic.phpt b/tests/session_basic.phpt index c5a464b5..3fdb6bd7 100644 --- a/tests/session_basic.phpt +++ b/tests/session_basic.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt index 782ae6d3..0a06c457 100644 --- a/tests/session_basic2.phpt +++ b/tests/session_basic2.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index 21288571..d684fa35 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index a328dd68..79c32888 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -2,7 +2,7 @@ Session lock --SKIPIF-- --INI-- diff --git a/tests/session_regenerate.phpt b/tests/session_regenerate.phpt index 794f46fc..bbd37fa2 100644 --- a/tests/session_regenerate.phpt +++ b/tests/session_regenerate.phpt @@ -2,7 +2,7 @@ Session regenerate --SKIPIF-- --INI-- diff --git a/tests/set_large.phpt b/tests/set_large.phpt index bf1098ef..f3cb4cc3 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -1,7 +1,7 @@ --TEST-- set large data --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- diff --git a/tests/types_igbinary.phpt b/tests/types_igbinary.phpt index 62fcc29b..da1b26fa 100644 --- a/tests/types_igbinary.phpt +++ b/tests/types_igbinary.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using igbinary serializer --SKIPIF-- --FILE-- diff --git a/tests/types_igbinary_multi.phpt b/tests/types_igbinary_multi.phpt index 33f4df67..2a0823e0 100644 --- a/tests/types_igbinary_multi.phpt +++ b/tests/types_igbinary_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & multi fetch type and value correctness using igbinary serializer --SKIPIF-- --FILE-- diff --git a/tests/types_json.phpt b/tests/types_json.phpt index f5735f6d..2491fea7 100644 --- a/tests/types_json.phpt +++ b/tests/types_json.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using JSON serializer --SKIPIF-- --FILE-- diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt index 6a085039..b6bc203e 100644 --- a/tests/types_json_multi.phpt +++ b/tests/types_json_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & multi fetch type and value correctness using JSON serializer --SKIPIF-- --FILE-- diff --git a/tests/types_msgpack.phpt b/tests/types_msgpack.phpt index aed43627..aad0d5bb 100644 --- a/tests/types_msgpack.phpt +++ b/tests/types_msgpack.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using msgpack serializer --SKIPIF-- --FILE-- diff --git a/tests/types_msgpack_multi.phpt b/tests/types_msgpack_multi.phpt index dcf251e1..4ba42347 100644 --- a/tests/types_msgpack_multi.phpt +++ b/tests/types_msgpack_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & fetch type and value correctness using msgpack serializer --SKIPIF-- --FILE-- diff --git a/tests/types_php.phpt b/tests/types_php.phpt index f6baab5b..8d99f375 100644 --- a/tests/types_php.phpt +++ b/tests/types_php.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached store & fetch type and value correctness using PHP serializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- @@ -45,4 +45,4 @@ NULL Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d bool(false) -OK \ No newline at end of file +OK diff --git a/tests/version.phpt b/tests/version.phpt index 8ffe275a..06cd537b 100644 --- a/tests/version.phpt +++ b/tests/version.phpt @@ -1,7 +1,7 @@ --TEST-- Get version --SKIPIF-- - + --FILE-- Date: Sat, 23 Jul 2016 11:11:34 +0800 Subject: [PATCH 443/694] Added skipif.inc --- tests/skipif.inc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/skipif.inc diff --git a/tests/skipif.inc b/tests/skipif.inc new file mode 100644 index 00000000..bcd32d25 --- /dev/null +++ b/tests/skipif.inc @@ -0,0 +1,10 @@ + Date: Sat, 23 Jul 2016 12:11:31 +0800 Subject: [PATCH 444/694] Cleanup --- php_memcached.c | 147 ++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 31bec912..3bd5ee48 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -241,9 +241,9 @@ static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value->val, "fastlz")) { + } else if (!strcmp(ZSTR_VAL(new_value), "fastlz")) { MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value->val, "zlib")) { + } else if (!strcmp(ZSTR_VAL(new_value), "zlib")) { MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; @@ -255,20 +255,20 @@ static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { MEMC_G(serializer_type) = SERIALIZER_DEFAULT; - } else if (!strcmp(new_value->val, "php")) { + } else if (!strcmp(ZSTR_VAL(new_value), "php")) { MEMC_G(serializer_type) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY - } else if (!strcmp(new_value->val, "igbinary")) { + } else if (!strcmp(ZSTR_VAL(new_value), "igbinary")) { MEMC_G(serializer_type) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API - } else if (!strcmp(new_value->val, "json")) { + } else if (!strcmp(ZSTR_VAL(new_value), "json")) { MEMC_G(serializer_type) = SERIALIZER_JSON; - } else if (!strcmp(new_value->val, "json_array")) { + } else if (!strcmp(ZSTR_VAL(new_value), "json_array")) { MEMC_G(serializer_type) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK - } else if (!strcmp(new_value->val, "msgpack")) { + } else if (!strcmp(ZSTR_VAL(new_value), "msgpack")) { MEMC_G(serializer_type) = SERIALIZER_MSGPACK; #endif // msgpack } else { @@ -281,7 +281,7 @@ static PHP_INI_MH(OnUpdateSerializer) static PHP_INI_MH(OnUpdateDeprecatedLockValue) { - if (new_value->len > 0 && strcmp(new_value->val, "not set")) { + if (ZSTR_LEN(new_value) > 0 && strcmp(ZSTR_VAL(new_value), "not set")) { php_error_docref(NULL, E_DEPRECATED, "memcached.sess_lock_wait and memcached.sess_lock_max_wait are deprecated. Please update your configuration to use memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries"); } return FAILURE; @@ -290,8 +290,8 @@ PHP_INI_MH(OnUpdateDeprecatedLockValue) static PHP_INI_MH(OnUpdateSessionPrefixString) { - if (new_value && new_value->len > 0) { - char *ptr = new_value->val; + if (new_value && ZSTR_LEN(new_value) > 0) { + char *ptr = ZSTR_VAL(new_value); while (*ptr != '\0') { if (isspace (*ptr++)) { @@ -299,7 +299,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) return FAILURE; } } - if (new_value->len > MEMCACHED_MAX_KEY) { + if (ZSTR_LEN(new_value) > MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } @@ -672,7 +672,7 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key } if (server_key) { - status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + status = memcached_mget_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), keys->mkeys, keys->mkeys_len, keys->num_valid_keys); } else { status = memcached_mget(intern->memc, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); } @@ -810,18 +810,18 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str zend_string *payload = *payload_in; /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + size_t buffer_size = (size_t) (((double) ZSTR_LEN(payload) * 1.05) + 1.0); char *buffer = emalloc(buffer_size); /* Store compressed size here */ size_t compressed_size = 0; - uint32_t original_size = payload->len; + uint32_t original_size = ZSTR_LEN(payload); switch (compression_type) { case COMPRESSION_TYPE_FASTLZ: { - compressed_size = fastlz_compress(payload->val, payload->len, buffer); + compressed_size = fastlz_compress(ZSTR_VAL(payload), ZSTR_LEN(payload), buffer); if (compressed_size > 0) { compress_status = 1; @@ -833,7 +833,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload)); if (status == Z_OK) { compress_status = 1; @@ -855,7 +855,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 1; @@ -864,8 +864,8 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); /* Copy the uin32_t at the beginning */ - memcpy(payload->val, &original_size, sizeof(uint32_t)); - memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); + memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); efree(buffer); zend_string_forget_hash_val(payload); @@ -1014,7 +1014,7 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ - if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { + if (ZSTR_LEN(payload) == 0 || ZSTR_LEN(payload) < MEMC_G(compression_threshold)) { should_compress = 0; } @@ -1063,8 +1063,8 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze } } -#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; -#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; if (server_key) { switch (op) { @@ -1073,7 +1073,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); + status = memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1105,7 +1105,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch(intern->memc, key->val, key->len, expiration); + status = memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1302,12 +1302,12 @@ void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool pre zend_string *key = zval_get_string(zv); if (preserve_order && return_value) { - add_assoc_null_ex(return_value, key->val, key->len); + add_assoc_null_ex(return_value, ZSTR_VAL(key), ZSTR_LEN(key)); } - if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { - keys_out->mkeys[idx] = key->val; - keys_out->mkeys_len[idx] = key->len; + if (ZSTR_LEN(key) > 0 && ZSTR_LEN(key) < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = ZSTR_VAL(key); + keys_out->mkeys_len[idx] = ZSTR_LEN(key); keys_out->strings[idx] = key; idx++; @@ -1331,8 +1331,8 @@ void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) { zval zv_keys; - array_init (&zv_keys); - add_next_index_stringl (&zv_keys, key->val, key->len); + array_init(&zv_keys); + add_next_index_str(&zv_keys, zend_string_copy(key)); s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); zval_ptr_dtor(&zv_keys); @@ -1409,7 +1409,6 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) context.extended = (get_flags & MEMC_GET_EXTENDED); - ZVAL_UNDEF(return_value); context.return_value = return_value; s_key_to_keys(&keys, key); @@ -1461,15 +1460,15 @@ zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval Z_TRY_ADDREF_P(cas); - array_init (&node); - add_assoc_zval (&node, "value", value); - add_assoc_zval (&node, "cas", cas); - add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + array_init(&node); + add_assoc_zval(&node, "value", value); + add_assoc_zval(&node, "cas", cas); + add_assoc_long(&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - add_assoc_zval_ex(context->return_value, key->val, key->len, &node); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); } else { - add_assoc_zval_ex(context->return_value, key->val, key->len, value); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, value); } return 1; } @@ -1563,10 +1562,10 @@ void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t fl Z_TRY_ADDREF_P(value); Z_TRY_ADDREF_P(cas); - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), key->val, key->len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); + add_assoc_str_ex(return_value, ZEND_STRL("key"), zend_string_copy(key)); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } @@ -2029,9 +2028,9 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (by_key) { - status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } else { - status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } zend_string_release(payload); @@ -2114,10 +2113,10 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), + ZSTR_LEN(key), expiration); } else { - status = memcached_delete(intern->memc, key->val, key->len, expiration); + status = memcached_delete(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); } if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -2131,10 +2130,10 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* {{{ -- php_memc_deleteMulti_impl */ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *entries; + zval *entries, *zv, ret; zend_string *server_key = NULL; time_t expiration = 0; - zval *entry; + zend_string *entry; memcached_return status; MEMC_METHOD_INIT_VARS; @@ -2153,27 +2152,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), zv) { + entry = zval_get_string(zv); - if (Z_STRLEN_P(entry) == 0) { + if (ZSTR_LEN(entry) == 0) { + zend_string_release(entry); continue; } if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(entry), ZSTR_LEN(entry), expiration); } else { - status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(entry), ZSTR_LEN(entry), ZSTR_VAL(entry), ZSTR_LEN(entry), expiration); } - if (s_memc_status_handle_result_code(intern, status) == FAILURE) { - add_assoc_long(return_value, Z_STRVAL_P(entry), status); + ZVAL_LONG(&ret, status); } else { - add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); + ZVAL_TRUE(&ret); } + zend_symtable_update(Z_ARRVAL_P(return_value), entry, &ret); + zend_string_release(entry); } ZEND_HASH_FOREACH_END(); return; @@ -2213,15 +2212,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } else { - status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } } @@ -2235,15 +2234,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { @@ -2452,7 +2451,7 @@ PHP_METHOD(Memcached, getServerByKey) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); + server_instance = memcached_server_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), &error); if (server_instance == NULL) { s_memc_status_handle_result_code(intern, error); RETURN_FALSE; @@ -2651,7 +2650,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch add_assoc_double(server_values, key, d_val); } else { - add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + add_assoc_stringl_ex(server_values, key, key_length, (char*)value, value_length); } efree (buffer); efree (server_key); @@ -3369,9 +3368,9 @@ memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_me zval *return_value = (zval *) in_context; array_init(&array); - add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_string(&array, "host", (char*)memcached_server_name(instance)); add_assoc_long(&array, "port", memcached_server_port(instance)); - add_assoc_string(&array, "type", memcached_server_type(instance)); + add_assoc_string(&array, "type", (char*)memcached_server_type(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); @@ -3467,8 +3466,8 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa php_unserialize_data_t var_hash; const unsigned char *p, *max; - p = (const unsigned char *) payload->val; - max = p + payload->len; + p = (const unsigned char *) ZSTR_VAL(payload); + max = p + ZSTR_LEN(payload); PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(return_value, &p, max, &var_hash)) { @@ -3484,7 +3483,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *) payload->val, payload->len, return_value)) { + if (igbinary_unserialize((uint8_t *) ZSTR_VAL(payload), ZSTR_LEN(payload), return_value)) { ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; @@ -3500,7 +3499,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa #ifdef HAVE_JSON_API { php_memc_user_data_t *memc_user_data = memcached_get_user_data(memc); - php_json_decode(return_value, payload->val, payload->len, (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload), (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); } #else ZVAL_FALSE(return_value); @@ -3511,7 +3510,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(return_value, payload->val, payload->len); + php_msgpack_unserialize(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload)); #else ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); From 09e29e65deabae5b23fdf5db1928992d6107d9c9 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:27:52 +0800 Subject: [PATCH 445/694] Fixed possible crash with opcache (We should never edit a zval in place) --- php_memcached.c | 94 +++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3bd5ee48..078f1b25 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1819,8 +1819,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - - zend_string *str_key; + zend_string *str_key = NULL; if (skey) { str_key = skey; @@ -2337,7 +2336,6 @@ PHP_METHOD(Memcached, addServers) zval *servers; zval *entry; zval *z_host, *z_port, *z_weight = NULL; - uint32_t weight = 0; HashPosition pos; int entry_size, i = 0; memcached_server_st *list = NULL; @@ -2361,6 +2359,10 @@ PHP_METHOD(Memcached, addServers) entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); if (entry_size > 1) { + zend_string *host; + zend_long port; + uint32_t weight; + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); /* Check that we have a host */ @@ -2378,8 +2380,8 @@ PHP_METHOD(Memcached, addServers) continue; } - convert_to_string_ex(z_host); - convert_to_long_ex(z_port); + host = zval_get_string(z_host); + port = zval_get_long(z_port); weight = 0; if (entry_size > 2) { @@ -2389,12 +2391,12 @@ PHP_METHOD(Memcached, addServers) php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); } - convert_to_long_ex(z_weight); - weight = Z_LVAL_P(z_weight); + weight = zval_get_long(z_weight); } - list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), - Z_LVAL_P(z_port), weight, &status); + list = memcached_server_list_append_with_weight(list, ZSTR_VAL(host), port, weight, &status); + + zend_string_release(host); if (s_memc_status_handle_result_code(intern, status) == SUCCESS) { i++; @@ -2839,21 +2841,21 @@ static PHP_METHOD(Memcached, getOption) static int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { + zend_long lval; memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); switch (option) { case MEMC_OPT_COMPRESSION: - convert_to_long(value); - memc_user_data->compression_enabled = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression_enabled = zval_get_long(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: - convert_to_long(value); - if (Z_LVAL_P(value) == COMPRESSION_TYPE_FASTLZ || - Z_LVAL_P(value) == COMPRESSION_TYPE_ZLIB) { - memc_user_data->compression_type = Z_LVAL_P(value); + lval = zval_get_long(value); + if (lval == COMPRESSION_TYPE_FASTLZ || + lval == COMPRESSION_TYPE_ZLIB) { + memc_user_data->compression_type = lval; } else { /* invalid compression type */ intern->rescode = MEMCACHED_INVALID_ARGUMENTS; @@ -2863,12 +2865,13 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_PREFIX_KEY: { + zend_string *str; char *key; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; #endif - convert_to_string(value); - if (Z_STRLEN_P(value) == 0) { + str = zval_get_string(value); + if (ZSTR_VAL(str) == 0) { key = NULL; } else { /* @@ -2876,25 +2879,27 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) character of the key prefix, to avoid the issue we pad it with a '0' */ #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - snprintf(tmp, sizeof(tmp), "%s0", Z_STRVAL_P(value)); + snprintf(tmp, sizeof(tmp), "%s0", ZSTR_VAL(str)); key = tmp; #else - key = Z_STRVAL_P(value); + key = ZSTR_VAL(str); #endif } if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { + zend_string_release(str); intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } + zend_string_release(str); } break; case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: flag = (memcached_behavior) option; - convert_to_long(value); - rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); + lval = zval_get_long(value); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); @@ -2906,7 +2911,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) * options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA * (non-weighted) case. We have to clean up ourselves. */ - if (!Z_LVAL_P(value)) { + if (!lval) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); @@ -2920,28 +2925,28 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_SERIALIZER: { - convert_to_long(value); + lval = zval_get_long(value); /* igbinary serializer */ #ifdef HAVE_MEMCACHED_IGBINARY - if (Z_LVAL_P(value) == SERIALIZER_IGBINARY) { + if (lval == SERIALIZER_IGBINARY) { memc_user_data->serializer = SERIALIZER_IGBINARY; } else #endif #ifdef HAVE_JSON_API - if (Z_LVAL_P(value) == SERIALIZER_JSON) { + if (lval == SERIALIZER_JSON) { memc_user_data->serializer = SERIALIZER_JSON; - } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { + } else if (lval == SERIALIZER_JSON_ARRAY) { memc_user_data->serializer = SERIALIZER_JSON_ARRAY; } else #endif /* msgpack serializer */ #ifdef HAVE_MEMCACHED_MSGPACK - if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { + if (lval == SERIALIZER_MSGPACK) { memc_user_data->serializer = SERIALIZER_MSGPACK; } else #endif /* php serializer */ - if (Z_LVAL_P(value) == SERIALIZER_PHP) { + if (lval == SERIALIZER_PHP) { memc_user_data->serializer = SERIALIZER_PHP; } else { memc_user_data->serializer = SERIALIZER_PHP; @@ -2953,23 +2958,23 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } case MEMC_OPT_USER_FLAGS: - convert_to_long(value); + lval = zval_get_long(value); - if (Z_LVAL_P(value) < 0) { + if (lval < 0) { memc_user_data->set_udf_flags = -1; return 1; } - if (Z_LVAL_P(value) > MEMC_VAL_USER_FLAGS_MAX) { + if (lval > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); return 0; } - memc_user_data->set_udf_flags = Z_LVAL_P(value); + memc_user_data->set_udf_flags = lval; break; case MEMC_OPT_STORE_RETRY_COUNT: - convert_to_long(value); - memc_user_data->store_retry_count = Z_LVAL_P(value); + lval = zval_get_long(value); + memc_user_data->store_retry_count = lval; break; default: @@ -2981,10 +2986,10 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } else { flag = (memcached_behavior) option; - convert_to_long(value); + lval = zval_get_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { - rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); } else { rc = MEMCACHED_INVALID_ARGUMENTS; @@ -3016,15 +3021,9 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) retval = ecalloc(*num_elements, sizeof(uint32_t)); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), pzval) { - long value = 0; - - if (Z_TYPE_P(pzval) == IS_LONG) { - value = Z_LVAL_P(pzval); - } else { - value = zval_get_long(pzval); - value = value > 0? value : 0; - } + zend_long value = 0; + value = zval_get_long(pzval); if (value < 0) { php_error_docref(NULL, E_WARNING, "the map must contain positive integers"); efree (retval); @@ -3126,14 +3125,9 @@ static PHP_METHOD(Memcached, setOptions) php_error_docref(NULL, E_WARNING, "invalid configuration option"); ok = 0; } else { - zval copy; - ZVAL_DUP(©, value); - - if (!php_memc_set_option(intern, (long) key_index, ©)) { + if (!php_memc_set_option(intern, (long) key_index, value)) { ok = 0; } - - zval_dtor(©); } } ZEND_HASH_FOREACH_END(); From 010d8e4894f068fda6b70d9b2dd6ada42b62beca Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:33:56 +0800 Subject: [PATCH 446/694] Fixed possbile memleak --- php_memcached_server.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index eb225db0..ad33e0bc 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -29,19 +29,15 @@ #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ do { \ - char *cookie_buf; \ - spprintf (&cookie_buf, 0, "%p", my_ptr); \ - MAKE_STD_ZVAL(my_zcookie); \ - ZVAL_STRING(my_zcookie, cookie_buf, 0); \ + zend_string *cookie_buf; \ + cookie_buf = zend_strpprintf(0, "%p", my_ptr); \ + ZVAL_STR(&my_zcookie, cookie_buf); \ } while (0) #define MEMC_MAKE_RESULT_CAS(my_zresult_cas, my_result_cas) \ do { \ my_result_cas = 0; \ - if (Z_TYPE_P(my_zresult_cas) != IS_NULL) { \ - convert_to_double (my_zresult_cas); \ - my_result_cas = (uint64_t) Z_DVAL_P(my_zresult_cas); \ - } \ + my_result_cas = zval_get_double(my_zresult_cas); \ } while (0) @@ -78,9 +74,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa efree (buf); } if (retval_ptr) { - convert_to_long (retval_ptr); - retval = Z_LVAL_P(retval_ptr); - zval_ptr_dtor(&retval_ptr); + retval = zval_get_long(retval_ptr); } return retval; } @@ -223,10 +217,7 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - if (Z_TYPE(zresult) != IS_LONG) { - convert_to_long (&zresult); - } - *result = (uint64_t) Z_LVAL(zresult); + *result = (uint64_t)zval_get_long(zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); From 95f26c4f75dc9d29e5d7b1f8b4e6f8204b7db850 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:38:41 +0800 Subject: [PATCH 447/694] Fixed warning in run-test.php and also fixed test --- tests/experimental/moduleinfo.phpt | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 0f02a570..8605c11a 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -19,20 +19,4 @@ echo implode("\n", $array); --EXPECTF-- memcached memcached support => enabled -memcached.compression_factor => %f => %f -memcached.compression_threshold => %d => %d -memcached.compression_type => %s => %s -memcached.serializer => %s => %s -memcached.sess_binary => %d => %d -memcached.sess_connect_timeout => %d => %d -memcached.sess_consistent_hash => %d => %d -memcached.sess_lock_expire => %d => %d -memcached.sess_lock_max_wait => %d => %d -memcached.sess_lock_wait => %d => %d -memcached.sess_locking => %d => %d -memcached.sess_number_of_replicas => %d => %d -memcached.sess_prefix => %s => %s -memcached.sess_randomize_replica_read => %d => %d -memcached.sess_remove_failed => %d => %d -%rmemcached.use_sasl => %d => %d -|%rmemcached.store_retry_count => %d => %d +%A From a1aab4e85576a008fd87eb50aa11668fa92842e0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:13:30 +0800 Subject: [PATCH 448/694] Avoid str duplication --- php_memcached.c | 12 ++++++------ php_memcached_server.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 078f1b25..48c3cc24 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2623,8 +2623,7 @@ zend_bool s_double_value(const char *str, double *value) static memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) { - char *server_key; - size_t server_key_len; + zend_string *server_key; zend_long long_val; double d_val; char *buffer; @@ -2632,14 +2631,14 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch zval *return_value = (zval *) context; zval *server_values; - server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + server_key = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_find(Z_ARRVAL_P(return_value), server_key); if (!server_values) { zval zv; array_init(&zv); - server_values = zend_hash_str_add(Z_ARRVAL_P(return_value), server_key, server_key_len, &zv); + server_values = zend_hash_add(Z_ARRVAL_P(return_value), server_key, &zv); } spprintf (&buffer, 0, "%.*s", value_length, value); @@ -2655,7 +2654,8 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch add_assoc_stringl_ex(server_values, key, key_length, (char*)value, value_length); } efree (buffer); - efree (server_key); + zend_string_release(server_key); + return MEMCACHED_SUCCESS; } diff --git a/php_memcached_server.c b/php_memcached_server.c index ad33e0bc..94305101 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -30,7 +30,7 @@ #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ do { \ zend_string *cookie_buf; \ - cookie_buf = zend_strpprintf(0, "%p", my_ptr); \ + cookie_buf = strpprintf(0, "%p", my_ptr); \ ZVAL_STR(&my_zcookie, cookie_buf); \ } while (0) From 6405d96c54e41ce9020c80bfd48ab325789f29d7 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:17:42 +0800 Subject: [PATCH 449/694] Msgpack master is php7 branch now --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index b587f5c5..d43a15fc 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php5 + git checkout master phpize ./configure make From d67517b04d92464928f06402ac104bc133227d5f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:48:09 +0800 Subject: [PATCH 450/694] Fixed tests/keys.phpt --- php_memcached.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 48c3cc24..be9f229f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -206,6 +206,16 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); +#define MEMC_CHECK_KEY(intern, key) \ + if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ + ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + (memcached_behavior_get(intern->memc, \ + MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? \ + strchr(ZSTR_VAL(key), '\n') : \ + strchr(ZSTR_VAL(key), ' ')))) { \ + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ + RETURN_FALSE; \ + } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -1406,6 +1416,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); context.extended = (get_flags & MEMC_GET_EXTENDED); @@ -1960,6 +1971,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (memc_user_data->compression_enabled) { /* @@ -2017,6 +2029,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); cas = s_zval_to_uint64(zv_cas); @@ -2110,6 +2123,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (by_key) { status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), @@ -2202,6 +2216,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (offset < 0) { php_error_docref(NULL, E_WARNING, "offset has to be > 0"); From 0acaa06d98b2447c6c981bbed7b8a500fc46188f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 15:14:48 +0800 Subject: [PATCH 451/694] call_function always initialized retval --- php_memcached.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index be9f229f..81dd92f3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -613,13 +613,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul const char *res_key; size_t res_key_len; - - ZVAL_UNDEF(&zv_value); if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { - if (Z_TYPE(zv_value) != IS_UNDEF) { - zval_ptr_dtor(&zv_value); - } - if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; memcached_quit(intern->memc); @@ -729,8 +723,6 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal ZVAL_NULL(&id); } - ZVAL_UNDEF(&retval); - zend_fcall_info_argn(fci, 2, object, &id); fci->retval = &retval; fci->no_separation = 1; @@ -784,8 +776,6 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal fci->params = params; fci->param_count = 4; - ZVAL_UNDEF(&retval); - if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); @@ -1596,7 +1586,6 @@ zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, z context->fci.retval = &retval; context->fci.param_count = 2; - ZVAL_UNDEF(&retval); if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); @@ -3597,14 +3586,10 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re default: php_error_docref(NULL, E_WARNING, "unknown payload type"); - retval = 0; break; } zend_string_release(data); - if (!retval) { - zval_ptr_dtor(return_value); - } return retval; } From a0ed436fca84faab5a1cbe978789c7e1c97970f3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 15:15:30 +0800 Subject: [PATCH 452/694] According to memcached wiki, touch is added since 1.4.8 https://github.com/memcached/memcached/wiki/ReleaseNotes148 --- tests/config.inc | 5 +++++ tests/expire.phpt | 4 +++- tests/gh_155.phpt | 1 + tests/gh_77.phpt | 6 ++++-- tests/skipif.inc | 8 +++++++- tests/touch_binary.phpt | 6 ++++-- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/config.inc b/tests/config.inc index 4f275af1..a5f3cc2f 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -66,3 +66,8 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ), ); } + +function memc_get_version($memc, $host = '') { + $version = $memc->getVersion(); + return array_pop($version); +} diff --git a/tests/expire.phpt b/tests/expire.phpt index 0aa1a555..eac02408 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -3,7 +3,9 @@ Memcached store, fetch & touch expired key --XFAIL-- https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- - --FILE-- diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 54d2b77f..a5b61d00 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,6 +2,7 @@ Test for bug 155 --SKIPIF-- diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 193b6916..8f241ff4 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -1,8 +1,10 @@ --TEST-- Test for Github issue #77 --SKIPIF-- - --FILE-- --FILE-- Date: Sat, 23 Jul 2016 15:18:54 +0800 Subject: [PATCH 453/694] Remove unused arg --- tests/config.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/config.inc b/tests/config.inc index a5f3cc2f..98747d79 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -67,7 +67,7 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ); } -function memc_get_version($memc, $host = '') { +function memc_get_version($memc) { $version = $memc->getVersion(); return array_pop($version); } From 09e13048ecb813e2d0866c34d7319024d11f91b0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 19:48:13 +0800 Subject: [PATCH 454/694] cleanup --- php_memcached.c | 143 ++++++++++++++++-------------------------------- 1 file changed, 47 insertions(+), 96 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 81dd92f3..2b543e73 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -58,12 +58,9 @@ #define MEMC_G(v) (php_memcached_globals.memc.v) #endif - static - int le_memc; +static int le_memc; -static -int php_memc_list_entry(void) -{ +static int php_memc_list_entry(void) { return le_memc; } @@ -379,8 +376,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); /* Invoke PHP functions */ -static - zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); /* Iterate result sets */ typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); @@ -655,7 +651,6 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key php_memc_result_apply_fn result_apply_fn, zend_bool with_cas, void *context) { memcached_return status; - memcached_result_st result; int mget_status; uint64_t orig_cas_flag = 0; @@ -715,17 +710,19 @@ static zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; - zval retval, id; + zval retval; + zval params[2]; + ZVAL_COPY(¶ms[0], object); if (persistent_id) { - ZVAL_STR(&id, persistent_id); + ZVAL_STR(¶ms[1], zend_string_copy(persistent_id)); } else { - ZVAL_NULL(&id); + ZVAL_NULL(¶ms[1]); } - zend_fcall_info_argn(fci, 2, object, &id); - fci->retval = &retval; - fci->no_separation = 1; + fci->retval = &retval; + fci->params = params; + fci->param_count = 2; if (zend_call_function(fci, fci_cache) == FAILURE) { char *buf = php_memc_printable_func (fci, fci_cache); @@ -734,43 +731,27 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal ret = 0; } - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); - if (EG(exception)) { - ret = 0; - } - - zend_fcall_info_args_clear(fci, 1); return ret; } static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - memcached_return rc; zend_bool status = 0; - zval params[4]; zval retval; - zval zv_key, ref_val; - zval ref_expiration, zv_expiration; php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject); /* Prepare params */ - ZVAL_STR(&zv_key, key); - - ZVAL_NULL(&ref_val); - ZVAL_NULL(&zv_expiration); - - ZVAL_NEW_REF(&ref_val, value); - ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - ZVAL_COPY(¶ms[0], zobject); - ZVAL_COPY(¶ms[1], &zv_key); - ZVAL_COPY_VALUE(¶ms[2], &ref_val); - ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); + ZVAL_STR(¶ms[1], zend_string_copy(key)); /* key */ + ZVAL_NEW_REF(¶ms[2], value); /* value */ + ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ + ZVAL_NULL(Z_REFVAL(params[3])); fci->retval = &retval; fci->params = params; @@ -778,23 +759,22 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { - time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); - status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(ref_val), expiration); - ZVAL_DUP(value, Z_REFVAL(ref_val)); + time_t expiration = zval_get_long(Z_REFVAL(params[3])); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(params[2]), expiration); + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, Z_REFVAL(params[2])); } } else { s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); } - zval_ptr_dtor(zobject); - zval_ptr_dtor(&zv_key); - zval_ptr_dtor(&ref_val); - zval_ptr_dtor(&ref_expiration); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(&retval); - if (!Z_ISUNDEF(retval)) { - zval_ptr_dtor(&retval); - } return status; } @@ -1388,7 +1368,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_long get_flags = 0; zend_string *key; zend_string *server_key = NULL; - zend_bool extended, mget_status; + zend_bool mget_status; memcached_return status = MEMCACHED_SUCCESS; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; @@ -1484,8 +1464,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_string *server_key = NULL; zend_long flags = 0; MEMC_METHOD_INIT_VARS; - - zend_bool with_cas, retval, preserve_order, extended; + zend_bool retval, preserve_order; if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, @@ -1574,32 +1553,29 @@ static zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { zend_bool status = 1; - - zval retval, zv_result; + zval params[2]; + zval retval; php_memc_result_callback_ctx_t *context = (php_memc_result_callback_ctx_t *) in_context; - array_init(&zv_result); - s_create_result_array(key, value, cas, flags, &zv_result); + ZVAL_COPY(¶ms[0], context->object); + array_init(¶ms[1]); - zend_fcall_info_argn(&context->fci, 2, context->object, &zv_result); + s_create_result_array(key, value, cas, flags, ¶ms[1]); context->fci.retval = &retval; + context->fci.params = params; context->fci.param_count = 2; if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } php_error_docref(NULL, E_WARNING, "could not invoke result callback"); status = 0; } - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(&retval); + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); - zend_fcall_info_args_clear(&context->fci, 2); - zval_ptr_dtor(&zv_result); return status; } @@ -1663,14 +1639,6 @@ zend_bool s_fetch_apply(php_memc_object_t *intern, zend_string *key, zval *value Returns the next result from a previous delayed request */ PHP_METHOD(Memcached, fetch) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - zval value, zv_cas; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1708,14 +1676,6 @@ zend_bool s_fetch_all_apply(php_memc_object_t *intern, zend_string *key, zval *v Returns all the results from a previous delayed request */ PHP_METHOD(Memcached, fetchAll) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval value, entry, zv_cas; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1794,13 +1754,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_string *server_key = NULL; time_t expiration = 0; zval *value; - zend_string *skey, *str_key = NULL; - ulong num_key; - zend_string *payload; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; - char tmp_key[MEMCACHED_MAX_KEY]; + zend_string *skey; + zend_ulong num_key; int tmp_len = 0; MEMC_METHOD_INIT_VARS; @@ -1918,10 +1873,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value = NULL; zend_long expiration = 0; - zend_string *payload = NULL; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { @@ -2314,15 +2265,15 @@ PHP_METHOD(Memcached, addServer) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + if (ZSTR_VAL(host)[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(intern->memc, ZSTR_VAL(host), weight); } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_udp_with_weight(intern->memc, ZSTR_VAL(host), port, weight); } else { - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); } #else - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); #endif if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -2409,7 +2360,7 @@ PHP_METHOD(Memcached, addServers) } i++; /* catch-all for all errors */ - php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i + 1); } ZEND_HASH_FOREACH_END(); status = memcached_server_push(intern->memc, list); From 513c091a67539efbd8f9ade7c9bb7c6815fe95c1 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 20:13:36 +0800 Subject: [PATCH 455/694] Fixed locale_float.phpt test --- tests/experimental/locale_float.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/experimental/locale_float.phpt b/tests/experimental/locale_float.phpt index 9c512124..c071d974 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/experimental/locale_float.phpt @@ -9,7 +9,7 @@ if (!setlocale(LC_NUMERIC, "fi_FI", 'sv_SV', 'nl_NL')) { --FILE-- Date: Sat, 23 Jul 2016 20:32:06 +0800 Subject: [PATCH 456/694] Fixed OOM (tests/experimental/locale_float.phpt) --- php_memcached.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2b543e73..907914f3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -829,18 +829,18 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (!compress_status) { php_error_docref(NULL, E_WARNING, "could not compress value"); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 0; } /* This means the value was too small to be compressed, still a success */ if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 1; } + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); /* Copy the uin32_t at the beginning */ @@ -1005,7 +1005,6 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t zend_string_release(payload); return NULL; } - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); } if (memc_user_data->set_udf_flags >= 0) { From 6837d894944a488ecd2b15d2e700e6183fcc4d2e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 20:44:03 +0800 Subject: [PATCH 457/694] Fixed test (tests/experimental/setmulti_badserialize.phpt) --- php_memcached.c | 2 +- tests/experimental/setmulti_badserialize.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 907914f3..0d208819 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1786,7 +1786,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { - php_error_docref(NULL, E_WARNING, "failed to set key %s", str_key->val); + php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); } if (!skey) { diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index 5081eedc..3bba314a 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -42,6 +42,6 @@ try { var_dump($m->getByKey('kef', 'foo')); --EXPECT-- - +Memcached::setMultiByKey(): failed to set key foo 1234 int(10) From f73befd69c2ff79456c0b9e2515e4f7c7172afa7 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 22:35:13 +0800 Subject: [PATCH 458/694] Use zend_string_equals_literal --- php_memcached.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 0d208819..e1d9d837 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -442,13 +442,13 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ char *buffer = NULL; if (fci->object) { - spprintf (&buffer, 0, "%s::%s", fci->object->ce->name->val, fci_cache->function_handler->common.function_name); + spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), fci_cache->function_handler->common.function_name); } else { if (Z_TYPE (fci->function_name) == IS_OBJECT) { - spprintf (&buffer, 0, "%s", Z_OBJCE (fci->function_name)->name->val); + spprintf (&buffer, 0, "%s", ZSTR_VAL(Z_OBJCE(fci->function_name)->name)); } else { - spprintf (&buffer, 0, "%s", Z_STRVAL (fci->function_name)); + spprintf (&buffer, 0, "%s", Z_STRVAL(fci->function_name)); } } return buffer; @@ -1156,7 +1156,7 @@ static PHP_METHOD(Memcached, __construct) zend_resource *le; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + snprintf(ZSTR_VAL(plist_key), plist_key->len + 1, "memcached:id=%s", ZSTR_VAL(persistent_id)); if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { @@ -1170,7 +1170,7 @@ static PHP_METHOD(Memcached, __construct) } if (conn_str && conn_str->len > 0) { - intern->memc = memcached (conn_str->val, conn_str->len); + intern->memc = memcached (ZSTR_VAL(conn_str), ZSTR_LEN(conn_str)); } else { intern->memc = memcached (NULL, 0); @@ -1249,7 +1249,7 @@ static PHP_METHOD(Memcached, __construct) GC_REFCOUNT(&le) = 1; /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(plist_key), ZSTR_LEN(plist_key), &le, sizeof(le)) == NULL) { zend_string_release(plist_key); php_error_docref(NULL, E_ERROR, "could not register persistent entry"); /* not reached */ @@ -3131,7 +3131,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) RETURN_FALSE; } memc_user_data->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); + status = memcached_set_sasl_auth_data(intern->memc, ZSTR_VAL(user), ZSTR_VAL(pass)); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; @@ -3503,28 +3503,28 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re break; case MEMC_VAL_IS_LONG: - ZVAL_LONG(return_value, strtol(data->val, NULL, 10)); + ZVAL_LONG(return_value, strtol(ZSTR_VAL(data), NULL, 10)); break; case MEMC_VAL_IS_DOUBLE: { - if (payload_len == 8 && memcmp(data->val, "Infinity", 8) == 0) { + if (zend_string_equals_literal(data, "Infinity")) { ZVAL_DOUBLE(return_value, php_get_inf()); } - else if (payload_len == 9 && memcmp(data->val, "-Infinity", 9) == 0) { + else if (zend_string_equals_literal(data, "-Infinity")) { ZVAL_DOUBLE(return_value, -php_get_inf()); } - else if (payload_len == 3 && memcmp(data->val, "NaN", 3) == 0) { + else if (zend_string_equals_literal(data, "NaN")) { ZVAL_DOUBLE(return_value, php_get_nan()); } else { - ZVAL_DOUBLE(return_value, zend_strtod(data->val, NULL)); + ZVAL_DOUBLE(return_value, zend_strtod(ZSTR_VAL(data), NULL)); } } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(return_value, payload_len > 0 && data->val[0] == '1'); + ZVAL_BOOL(return_value, payload_len > 0 && ZSTR_VAL(data)[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: From 441168bebeab63b35813ded34c68d548bc3a1e4c Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 24 Jul 2016 12:37:29 +0800 Subject: [PATCH 459/694] avoided memory duplication --- php_memcached.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e1d9d837..71b3c255 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -525,15 +525,14 @@ static void s_uint64_to_zval (zval *target, uint64_t value) { if (value >= ((uint64_t) LONG_MAX)) { - char *buffer; + zend_string *buffer; #ifdef PRIu64 - spprintf (&buffer, 0, "%" PRIu64, value); + buffer = strpprintf (0, "%" PRIu64, value); #else /* Best effort */ - spprintf (&buffer, 0, "%llu", value); + buffer = strpprintf (0, "%llu", value); #endif - ZVAL_STRING (target, buffer); - efree(buffer); + ZVAL_STR(target, buffer); } else { ZVAL_LONG (target, (zend_long) value); @@ -3331,28 +3330,28 @@ memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_me static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - char *address, *version; - size_t address_len, version_len; - - zval *return_value = (zval *) in_context; + zend_string *address, *version; + zval rv, *return_value = (zval *)in_context; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = spprintf(&version, sizeof(version), "%d.%d.%d", + version = strpprintf(0, "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), memcached_server_micro_version(instance)); #else - version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", + version = strpprintf(0, "%d.%d.%d", instance->major_version, instance->minor_version, instance->micro_version); #endif - address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); - add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + + ZVAL_STR(&rv, version); + zend_hash_add(Z_ARRVAL_P(return_value), address, &rv); + + zend_string_release(address); - efree(address); - efree(version); return MEMCACHED_SUCCESS; } From 5e42fa985b05cb1063a74a74ac14220d52652686 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 24 Jul 2016 12:41:53 +0800 Subject: [PATCH 460/694] Remove old version staff --- php_memcached.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 71b3c255..f2cd38e3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3565,8 +3565,8 @@ zend_class_entry *php_memc_get_exception_base(int root) zval *pce_z; if ((pce_z = zend_hash_str_find(CG(class_table), - "runtimeexception", - sizeof("RuntimeException") - 1)) != NULL) { + "runtimeexception", + sizeof("RuntimeException") - 1)) != NULL) { pce = Z_CE_P(pce_z); spl_ce_RuntimeException = pce; return pce; @@ -3576,11 +3576,7 @@ zend_class_entry *php_memc_get_exception_base(int root) } } #endif -#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2) return zend_exception_get_default(); -#else - return zend_exception_get_default(); -#endif } From bb4556a38ce1fa87c088d05e8d7bf28792a794c8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 25 Jul 2016 08:38:22 -0700 Subject: [PATCH 461/694] Partial fix build for memcached-protocl --- php_memcached.c | 56 +++++++++++++++++++++++------------------ php_memcached_private.h | 1 - 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f2cd38e3..a7c1f42e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -217,10 +217,20 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { #ifdef HAVE_MEMCACHED_PROTOCOL typedef struct { - zend_object zo; php_memc_proto_handler_t *handler; + zend_object zo; } php_memc_server_t; +static inline php_memc_server_t *php_memc_server_fetch_object(zend_object *obj) { + return (php_memc_server_t *)((char *)obj - XtOffsetOf(php_memc_server_t, zo)); +} +#define Z_MEMC_SERVER_P(zv) php_memc_server_fetch_object(Z_OBJ_P(zv)) + +#ifdef ZTS +#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +#else +#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +#endif #endif static zend_class_entry *memcached_ce = NULL; @@ -3271,28 +3281,24 @@ zend_object *php_memc_object_new(zend_class_entry *ce) #ifdef HAVE_MEMCACHED_PROTOCOL static -void php_memc_server_free_storage(php_memc_server_t *intern) +void php_memc_server_free_storage(zend_object *object) { + php_memc_server_t *intern = php_memc_server_fetch_object(object); zend_object_std_dtor(&intern->zo); - efree (intern); } -zend_object_value php_memc_server_new(zend_class_entry *ce) +zend_object *php_memc_server_new(zend_class_entry *ce) { - zend_object_value retval; php_memc_server_t *intern; - zval *tmp; - intern = ecalloc(1, sizeof(php_memc_server_t)); + intern = ecalloc(1, sizeof(php_memc_server_t) + zend_object_properties_size(ce)); + zend_object_std_init(&intern->zo, ce); object_properties_init(&intern->zo, ce); - intern->handler = php_memc_proto_handler_new (); - - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); - retval.handlers = &memcached_server_object_handlers; + intern->zo.handlers = &memcached_server_object_handlers; - return retval; + return &intern->zo; } #endif @@ -3587,8 +3593,8 @@ void s_destroy_cb (zend_fcall_info *fci) { if (fci->size > 0) { zval_ptr_dtor(&fci->function_name); - if (fci->object_ptr != NULL) { - zval_ptr_dtor(&fci->object_ptr); + if (fci->object) { + OBJ_RELEASE(fci->object); } } } @@ -3598,19 +3604,19 @@ PHP_METHOD(MemcachedServer, run) { int i; zend_bool rc; - zend *address; + zend_string *address; php_memc_server_t *intern; - intern = Z_MEMC_OBJ_P(getThis()); + intern = Z_MEMC_SERVER_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { return; } - rc = php_memc_proto_handler_run (intern->handler, address); + rc = php_memc_proto_handler_run(intern->handler, address); for (i = MEMC_SERVER_ON_MIN + 1; i < MEMC_SERVER_ON_MAX; i++) { - s_destroy_cb (&MEMC_G(server.callbacks) [i].fci); + s_destroy_cb(&MEMC_SERVER_G(callbacks) [i].fci); } RETURN_BOOL(rc); @@ -3633,14 +3639,14 @@ PHP_METHOD(MemcachedServer, on) } if (fci.size > 0) { - s_destroy_cb (&MEMC_G(server.callbacks) [event].fci); + s_destroy_cb (&MEMC_SERVER_G(callbacks) [event].fci); - MEMC_G(server.callbacks) [event].fci = fci; - MEMC_G(server.callbacks) [event].fci_cache = fci_cache; + MEMC_SERVER_G(callbacks) [event].fci = fci; + MEMC_SERVER_G(callbacks) [event].fci_cache = fci_cache; - Z_ADDREF_P (fci.function_name); - if (fci.object_ptr) { - Z_ADDREF_P (fci.object_ptr); + Z_TRY_ADDREF(fci.function_name); + if (fci.object) { + GC_REFCOUNT(fci.object)++; } } RETURN_BOOL(rc); @@ -4370,7 +4376,9 @@ PHP_MINIT_FUNCTION(memcached) #ifdef HAVE_MEMCACHED_PROTOCOL memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_server_object_handlers.offset = XtOffsetOf(php_memc_server_t, zo); memcached_server_object_handlers.clone_obj = NULL; + memcached_server_object_handlers.free_obj = php_memc_server_free_storage; INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); memcached_server_ce = zend_register_internal_class(&ce); diff --git a/php_memcached_private.h b/php_memcached_private.h index 329afc8d..c06bd626 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -195,7 +195,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) /* For deprecated values */ zend_long no_effect; - #ifdef HAVE_MEMCACHED_PROTOCOL struct { php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX]; From 045ab843ce47e6c2e9d0dbbe20bb4d0fc3dd56f4 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:16:35 -0700 Subject: [PATCH 462/694] Document memcached.sess_binary_protocol And remove a TODO found in the code for allowing users to configure whether or not to use binary protocols for sessions. For issue #233 --- memcached.ini | 8 +++++--- php_memcached.c | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/memcached.ini b/memcached.ini index 31a6eced..59001aaf 100644 --- a/memcached.ini +++ b/memcached.ini @@ -63,9 +63,11 @@ memcached.sess_remove_failed_servers = Off ; which could have old data or no data at all memcached.sess_number_of_replicas = 0 -; memcached session binary mode -; libmemcached replicas only work if binary mode is enabled -memcached.sess_binary = Off +; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) +; libmemcached replicas work only if binary mode is enabled. +; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. +; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +memcached.sess_binary_protocol = On ; memcached session replica read randomize memcached.sess_randomize_replica_read = Off diff --git a/php_memcached.c b/php_memcached.c index a7c1f42e..efc58218 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -19,7 +19,6 @@ /* TODO * - set LIBKETAMA_COMPATIBLE as the default? * - fix unserialize(serialize($memc)) - * - ability to set binary protocol for sessions */ #include "php_memcached.h" From 4d9fda94df531ea07753bba5744671c994619ad8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 14:54:59 +0800 Subject: [PATCH 463/694] use zval_copy --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index f2cd38e3..e426f04c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1353,7 +1353,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); } else { - ZVAL_ZVAL(context->return_value, value, 1, 0); + ZVAL_COPY(context->return_value, value); } return 0; /* Stop after one */ } From 56171da73e3d23f2728715abec261a97bfeed9c0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 17:07:14 +0800 Subject: [PATCH 464/694] Fixed bug fetch only fetched one result --- php_memcached.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e426f04c..e7f73f31 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -382,7 +382,7 @@ static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, ze typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); static -memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context); +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, zend_bool fetch_delay, void *context); static zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, @@ -579,7 +579,7 @@ uint64_t s_zval_to_uint64 (zval *cas) ****************************************/ static -memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context) +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, zend_bool fetch_delay, void *context) { memcached_result_st result, *result_ptr; memcached_return rc, status = MEMCACHED_SUCCESS; @@ -599,7 +599,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul } else { zend_string *key; - zval zv_value, zv_cas; + zval val, zcas; zend_bool retval; uint64_t cas; @@ -608,7 +608,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul const char *res_key; size_t res_key_len; - if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &val)) { if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; memcached_quit(intern->memc); @@ -623,19 +623,21 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul cas = memcached_result_cas(&result); flags = memcached_result_flags(&result); - s_uint64_to_zval(&zv_cas, cas); + s_uint64_to_zval(&zcas, cas); key = zend_string_init (res_key, res_key_len, 0); - retval = result_apply_fn(intern, key, &zv_value, &zv_cas, flags, context); + retval = result_apply_fn(intern, key, &val, &zcas, flags, context); - zend_string_release (key); - zval_ptr_dtor(&zv_value); - zval_ptr_dtor(&zv_cas); + zend_string_release(key); + zval_ptr_dtor(&val); + zval_ptr_dtor(&zcas); /* Stop iterating on false */ if (!retval) { - /* Make sure we clear our results */ - while (memcached_fetch_result(intern->memc, &result, &rc)) {} + if (!fetch_delay) { + /* Make sure we clear our results */ + while (memcached_fetch_result(intern->memc, &result, &rc)) {} + } break; } } @@ -692,7 +694,7 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key return 1; } - status = php_memc_result_apply(intern, result_apply_fn, context); + status = php_memc_result_apply(intern, result_apply_fn, 0, context); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { return 0; @@ -1543,8 +1545,11 @@ void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t fl add_assoc_str_ex(return_value, ZEND_STRL("key"), zend_string_copy(key)); add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + if (Z_LVAL_P(cas)) { + /* BC compatible */ + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + } } static @@ -1648,7 +1653,7 @@ PHP_METHOD(Memcached, fetch) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - status = php_memc_result_apply(intern, s_fetch_apply, return_value); + status = php_memc_result_apply(intern, s_fetch_apply, 1, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); @@ -1685,7 +1690,7 @@ PHP_METHOD(Memcached, fetchAll) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - status = php_memc_result_apply(intern, s_fetch_all_apply, return_value); + status = php_memc_result_apply(intern, s_fetch_all_apply, 0, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_dtor(return_value); From 41b005fd0f8587f105f673ef3ab77bd31d1285cd Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 17:48:00 +0800 Subject: [PATCH 465/694] Fixed test --- tests/experimental/cas_bykey.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/experimental/cas_bykey.phpt b/tests/experimental/cas_bykey.phpt index f8c80fa5..0a9da94e 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/experimental/cas_bykey.phpt @@ -8,12 +8,12 @@ include dirname(dirname(__FILE__)) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = null; $m->setByKey('keffe', 'cas_test', 10); -$v = $m->getbyKey('keffe', 'cas_test', null, $cas_token); +$v = $m->getbyKey('keffe', 'cas_test', null, Memcached::GET_EXTENDED); -if (is_null($cas_token)) { +$cas_token = $v["cas"]; +if (empty($cas_token)) { echo "Null cas token for key: cas_test value: 10\n"; return; } From 4fa21116f1e32efa4a9ef2045d32950649e6a508 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 19:11:54 +0800 Subject: [PATCH 466/694] Value pass to callback behavior consistently with get (GET_EXTENED return array) --- php_memcached.c | 57 +++++++++++++++++++------- tests/experimental/getmulti_bykey.phpt | 6 +-- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a5dd979c..095366c4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -386,7 +386,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); /* Invoke PHP functions */ -static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_bool with_cas, zend_string *key, zval *value); /* Iterate result sets */ typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); @@ -750,7 +750,7 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal } static -zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) +zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_bool with_cas, zend_string *key, zval *value) { zend_bool status = 0; zval params[4]; @@ -759,21 +759,42 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal /* Prepare params */ ZVAL_COPY(¶ms[0], zobject); - ZVAL_STR(¶ms[1], zend_string_copy(key)); /* key */ - ZVAL_NEW_REF(¶ms[2], value); /* value */ - ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ - ZVAL_NULL(Z_REFVAL(params[3])); + ZVAL_STR_COPY(¶ms[1], key); /* key */ + ZVAL_NEW_REF(¶ms[2], value); /* value */ + + if (with_cas) { + fci->param_count = 3; + } else { + ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ + ZVAL_NULL(Z_REFVAL(params[3])); + fci->param_count = 4; + } fci->retval = &retval; fci->params = params; - fci->param_count = 4; if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { - time_t expiration = zval_get_long(Z_REFVAL(params[3])); - status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(params[2]), expiration); - /* memleak? zval_ptr_dtor(value); */ - ZVAL_COPY(value, Z_REFVAL(params[2])); + time_t expiration; + zval *val = Z_REFVAL(params[2]); + + if (with_cas) { + if (Z_TYPE_P(val) == IS_ARRAY) { + zval *rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); + if (rv) { + zval *cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") -1); + expiration = cas? Z_LVAL_P(cas) : 0; + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv, expiration); + } + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, val); + } + } else { + expiration = zval_get_long(Z_REFVAL(params[3])); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, val, expiration); + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, val); + } } } else { @@ -783,7 +804,9 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(¶ms[1]); zval_ptr_dtor(¶ms[2]); - zval_ptr_dtor(¶ms[3]); + if (!with_cas) { + zval_ptr_dtor(¶ms[3]); + } zval_ptr_dtor(&retval); return status; @@ -1408,7 +1431,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (!mget_status) { if (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) && fci.size > 0) { - status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + status = s_invoke_cache_callback(object, &fci, &fcc, context.extended, key, return_value); if (!status) { zval_ptr_dtor(return_value); @@ -1488,9 +1511,15 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } MEMC_METHOD_FETCH_OBJECT; - s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); + if (zend_hash_num_elements(Z_ARRVAL_P(keys)) == 0) { + /* BC compatible */ + s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); + return; + } + + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); preserve_order = (flags & MEMC_GET_PRESERVE_ORDER); s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), preserve_order, return_value); diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/experimental/getmulti_bykey.phpt index e4eb112c..3f7a6f78 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/experimental/getmulti_bykey.phpt @@ -11,12 +11,10 @@ $m->set('foo', 1, 10); $m->set('bar', 2, 10); $m->delete('baz'); -$cas = array(); -var_dump($m->getMultiByKey('foo', array('foo', 'bar', 'baz'), $cas, Memcached::GET_PRESERVE_ORDER)); +var_dump($m->getMultiByKey('foo', array('foo', 'bar', 'baz'), Memcached::GET_PRESERVE_ORDER)); echo $m->getResultMessage(), "\n"; -$cas = array(); -var_dump($m->getMultiByKey('foo', array(), $cas, Memcached::GET_PRESERVE_ORDER)); +var_dump($m->getMultiByKey('foo', array(), Memcached::GET_PRESERVE_ORDER)); echo $m->getResultMessage(), "\n"; --EXPECT-- From 35ef91129d1303bd7d5c7e742d27c08d35d5728c Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 8 Aug 2016 00:37:20 -0400 Subject: [PATCH 467/694] Igbinary php7 development is in igbinary/igbinary master branch now igbinary7 was moved to src/php7, and bug fixes/improvements were/will be added there later. See https://github.com/igbinary/igbinary/pull/62 --- .travis/travis.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index d43a15fc..264a7f3b 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary7.git - pushd igbinary7 + git clone https://github.com/igbinary/igbinary.git + pushd igbinary phpize ./configure make From 5bcf2008eedf90c38c57e51be0af677672606976 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:23:16 -0700 Subject: [PATCH 468/694] Use only the HAVE_MEMCACHED_SASL definition from config.h --- php_memcached_private.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index c06bd626..4c4f6375 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -104,11 +104,8 @@ typedef struct { #define SERIALIZER_DEFAULT_NAME "php" #endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ -#if LIBMEMCACHED_WITH_SASL_SUPPORT -# if defined(HAVE_SASL_SASL_H) -# include -# define HAVE_MEMCACHED_SASL 1 -# endif +#ifdef HAVE_MEMCACHED_SASL +# include #endif #ifdef HAVE_MEMCACHED_PROTOCOL From 957024f777e7e9514a4f4794c3726cb5472b2754 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:29:33 -0700 Subject: [PATCH 469/694] Consistently use #ifdef instead of #if for autoconf definitions --- php_memcached.c | 16 ++++++++-------- php_memcached_private.h | 16 ++++++++-------- php_memcached_session.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 35dc0aac..c468163e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -155,7 +155,7 @@ typedef struct { zend_long store_retry_count; zend_long set_udf_flags; -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif } php_memc_user_data_t; @@ -243,7 +243,7 @@ static zend_object_handlers memcached_server_object_handlers; static zend_class_entry *memcached_server_ce = NULL; #endif -#if HAVE_SPL +#ifdef HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -431,7 +431,7 @@ static zend_bool php_memc_init_sasl_if_needed() { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (MEMC_G(sasl_initialised)) { return 1; } @@ -3273,7 +3273,7 @@ static PHP_METHOD(Memcached, isPristine) static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (memc_user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } @@ -3597,7 +3597,7 @@ zend_class_entry *php_memc_get_exception(void) PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root) { -#if HAVE_SPL +#ifdef HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { zend_class_entry *pce; @@ -4311,7 +4311,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MEMORY_ALLOCATION_FAILURE, MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE); #endif -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE); @@ -4437,7 +4437,7 @@ PHP_MINIT_FUNCTION(memcached) /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(memcached) { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (MEMC_G(sasl_initialised)) { sasl_done(); } @@ -4456,7 +4456,7 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL php_info_print_table_row(2, "SASL support", "yes"); #else php_info_print_table_row(2, "SASL support", "no"); diff --git a/php_memcached_private.h b/php_memcached_private.h index 4c4f6375..a04e19be 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -93,15 +93,15 @@ typedef struct { php_memc_serializer_type type; } php_memc_serializer; -#ifdef HAVE_MEMCACHED_IGBINARY -#define SERIALIZER_DEFAULT SERIALIZER_IGBINARY -#define SERIALIZER_DEFAULT_NAME "igbinary" -#elif HAVE_MEMCACHED_MSGPACK -#define SERIALIZER_DEFAULT SERIALIZER_MSGPACK -#define SERIALIZER_DEFAULT_NAME "msgpack" +#if defined(HAVE_MEMCACHED_IGBINARY) +# define SERIALIZER_DEFAULT SERIALIZER_IGBINARY +# define SERIALIZER_DEFAULT_NAME "igbinary" +#elif defined(HAVE_MEMCACHED_MSGPACK) +# define SERIALIZER_DEFAULT SERIALIZER_MSGPACK +# define SERIALIZER_DEFAULT_NAME "msgpack" #else -#define SERIALIZER_DEFAULT SERIALIZER_PHP -#define SERIALIZER_DEFAULT_NAME "php" +# define SERIALIZER_DEFAULT SERIALIZER_PHP +# define SERIALIZER_DEFAULT_NAME "php" #endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ #ifdef HAVE_MEMCACHED_SASL diff --git a/php_memcached_session.c b/php_memcached_session.c index 59f6b238..42659fe5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -68,7 +68,7 @@ void s_destroy_mod_data(memcached_st *memc) { php_memcached_user_data *user_data = memcached_get_user_data(memc); -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } From c032fba4901de9049e13097a2699f4e76ef780f7 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:58:07 -0700 Subject: [PATCH 470/694] Whitespace --- php_memcached.c | 54 ++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c468163e..e6b741ef 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -190,9 +190,9 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); #define MEMC_METHOD_INIT_VARS \ - zval* object = getThis(); \ - php_memc_object_t* intern = NULL; \ - php_memc_user_data_t* memc_user_data = NULL; + zval* object = getThis(); \ + php_memc_object_t* intern = NULL; \ + php_memc_user_data_t* memc_user_data = NULL; #define MEMC_METHOD_FETCH_OBJECT \ intern = Z_MEMC_OBJ_P(object); \ @@ -1341,13 +1341,13 @@ void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool pre static void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) { - zval zv_keys; + zval zv_keys; - array_init(&zv_keys); - add_next_index_str(&zv_keys, zend_string_copy(key)); + array_init(&zv_keys); + add_next_index_str(&zv_keys, zend_string_copy(key)); - s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); - zval_ptr_dtor(&zv_keys); + s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); + zval_ptr_dtor(&zv_keys); } static @@ -1385,7 +1385,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu add_assoc_zval (context->return_value, "value", value); add_assoc_zval (context->return_value, "cas", cas); add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - } + } else { ZVAL_COPY(context->return_value, value); } @@ -1650,7 +1650,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); if (fci.size > 0) { php_memc_result_callback_ctx_t context = { @@ -1758,7 +1758,7 @@ PHP_METHOD(Memcached, setByKey) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); } /* }}} */ @@ -1766,7 +1766,7 @@ PHP_METHOD(Memcached, touch) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touchByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ #endif @@ -2466,16 +2466,16 @@ PHP_METHOD(Memcached, getServerByKey) Reset the server list in use */ PHP_METHOD(Memcached, resetServerList) { - MEMC_METHOD_INIT_VARS; + MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; - memcached_servers_reset(intern->memc); - RETURN_TRUE; + memcached_servers_reset(intern->memc); + RETURN_TRUE; } /* }}} */ @@ -2483,16 +2483,16 @@ PHP_METHOD(Memcached, resetServerList) Close any open connections */ PHP_METHOD(Memcached, quit) { - MEMC_METHOD_INIT_VARS; + MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; - memcached_quit(intern->memc); - RETURN_TRUE; + memcached_quit(intern->memc); + RETURN_TRUE; } /* }}} */ @@ -2506,7 +2506,7 @@ PHP_METHOD(Memcached, flushBuffers) return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); } /* }}} */ @@ -3494,7 +3494,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa #endif break; - case MEMC_VAL_IS_MSGPACK: + case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK php_msgpack_unserialize(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload)); #else @@ -4050,7 +4050,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setOptions, arginfo_setOptions) MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL - MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) + MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) #endif MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) @@ -4191,9 +4191,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); #endif - /* - * Indicate whether msgpack serializer is available - */ + /* + * Indicate whether msgpack serializer is available + */ #ifdef HAVE_MEMCACHED_MSGPACK REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); #else @@ -4330,7 +4330,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON_ARRAY, SERIALIZER_JSON_ARRAY); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types From e65be324557eda7167c4831b4bfb1ad23a152beb Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 7 Dec 2016 04:44:48 +0000 Subject: [PATCH 471/694] Adjust the Travis CI matrix: PHP 7.0 and 7.1, fewer revisions of libmemcached (#273) --- .travis.yml | 29 ++++++++++++++--------------- .travis/travis.sh | 3 +-- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2e113ef..4aae7552 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,26 +1,27 @@ +sudo: required +dist: trusty + language: php php: - 7.0 + - 7.1 + +matrix: + fast_finish: true + allow_failures: + - php: 7.1 env: - - LIBMEMCACHED_VERSION=1.0.18 - - LIBMEMCACHED_VERSION=1.0.17 - - LIBMEMCACHED_VERSION=1.0.16 - - LIBMEMCACHED_VERSION=1.0.15 - - LIBMEMCACHED_VERSION=1.0.14 - - LIBMEMCACHED_VERSION=1.0.10 - - LIBMEMCACHED_VERSION=1.0.8 - - LIBMEMCACHED_VERSION=1.0.7 - - LIBMEMCACHED_VERSION=1.0.6 - - LIBMEMCACHED_VERSION=1.0.2 - #- LIBMEMCACHED_VERSION=0.53 - #- LIBMEMCACHED_VERSION=0.49 - #- LIBMEMCACHED_VERSION=0.44 + - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial + - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 + - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty + addons: apt: packages: - sasl2-bin - libsasl2-dev + - libevent-dev before_script: - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION @@ -28,8 +29,6 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION -sudo: false - cache: directories: - $HOME/cache diff --git a/.travis/travis.sh b/.travis/travis.sh index 264a7f3b..81049355 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,6 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout master phpize ./configure make @@ -238,7 +237,7 @@ case $ACTION in # Install igbinary extension install_igbinary - # install msgpack + # Install msgpack extension install_msgpack install_memcached From 67750f851ad01d054401ce988fe95f7bfe4cb9bf Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 4 Jan 2017 18:57:02 -0800 Subject: [PATCH 472/694] Update the README in preparation for php-memcached 3.x release --- README.markdown | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/README.markdown b/README.markdown index ae1b86db..35f4d7a0 100644 --- a/README.markdown +++ b/README.markdown @@ -1,15 +1,15 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=php7)](https://travis-ci.org/php-memcached-dev/php-memcached) +[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png)](https://travis-ci.org/php-memcached-dev/php-memcached) Description ----------- -This extension uses libmemcached library to provide API for communicating with -memcached servers. +This is the [PECL memcached](https://pecl.php.net/package/memcached) extension, +using the libmemcached library to connect to memcached servers. -memcached is a high-performance, distributed memory object caching system, -generic in nature, but intended for use in speeding up dynamic web applications -by alleviating database load. +[memcached](https://memcached.org) is a high-performance, distributed memory +object caching system, generic in nature, but intended for use in speeding up +dynamic web applications by alleviating database load. Building -------- @@ -19,8 +19,19 @@ Building $ make $ make test -Resources ---------- - * [libmemcached](http://libmemcached.org/libMemcached.html) - * [memcached](http://memcached.org/) - * [igbinary](https://github.com/igbinary/igbinary) +Dependencies +------------ + +php-memcached 3.x releases support PHP 7.0 - 7.1, and require libmemcached 1.x or higher, and optionally support igbinary 2.0 or higher. + +php-memcached 2.x releases support PHP 5.2 - 5.6, and require libmemcached 0.44 or higher, and optionally support igbinary 1.0 or higher. + +[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or +higher is recommended for best performance and compatibility with memcached +servers. + +[igbinary](https://github.com/igbinary/igbinary) is a faster and more compact +binary serializer for PHP data structures. When installing php-memcached from +source code, the igbinary module must be installed first so that php-memcached +can access its C header files. Load both modules in your `php.ini` at runtime +to begin using igbinary. From dd0219168659419ff4e936b6f77d75e199b2e2d7 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 5 Jan 2017 11:45:07 -0800 Subject: [PATCH 473/694] Add mention of msgpack to the README --- README.markdown | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.markdown b/README.markdown index 35f4d7a0..0cb2c032 100644 --- a/README.markdown +++ b/README.markdown @@ -22,9 +22,17 @@ Building Dependencies ------------ -php-memcached 3.x releases support PHP 7.0 - 7.1, and require libmemcached 1.x or higher, and optionally support igbinary 2.0 or higher. - -php-memcached 2.x releases support PHP 5.2 - 5.6, and require libmemcached 0.44 or higher, and optionally support igbinary 1.0 or higher. +php-memcached 3.x: +* Supports PHP 7.0 - 7.1. +* Requires libmemcached 1.x or higher. +* Optionally supports igbinary 2.0 or higher. +* Optionally supports msgpack 2.0 or higher. + +php-memcached 2.x: +* Supports PHP 5.2 - 5.6. +* Requires libmemcached 0.44 or higher. +* Optionally supports igbinary 1.0 or higher. +* Optionally supports msgpack 0.5 or higher. [libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or higher is recommended for best performance and compatibility with memcached @@ -35,3 +43,9 @@ binary serializer for PHP data structures. When installing php-memcached from source code, the igbinary module must be installed first so that php-memcached can access its C header files. Load both modules in your `php.ini` at runtime to begin using igbinary. + +[msgpack](https://msgpack.org) is a faster and more compact data structure +representation that is interoperable with msgpack implementations for other +languages. When installing php-memcached from source code, the msgpack module +must be installed first so that php-memcached can access its C header files. +Load both modules in your `php.ini` at runtime to begin using msgpack. From 7f6c3330327d5a89f9ced7fabbe63ac7fc7f4196 Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 13:20:42 +0100 Subject: [PATCH 474/694] Cannot reset OPT_PREFIX_KEY #293 (#294) - ZSTR_VAL(str) == 0 should be ZSTR_LEN(str) == 0 - add reset_keyprefix.phpt to package.xml --- package.xml | 1 + php_memcached.c | 2 +- tests/reset_keyprefix.phpt | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/reset_keyprefix.phpt diff --git a/package.xml b/package.xml index 244acfab..f2b81369 100644 --- a/package.xml +++ b/package.xml @@ -164,6 +164,7 @@ Tests + diff --git a/php_memcached.c b/php_memcached.c index e6b741ef..e1a045b5 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2867,7 +2867,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; #endif str = zval_get_string(value); - if (ZSTR_VAL(str) == 0) { + if (ZSTR_LEN(str) == 0) { key = NULL; } else { /* diff --git a/tests/reset_keyprefix.phpt b/tests/reset_keyprefix.phpt new file mode 100644 index 00000000..385a21d5 --- /dev/null +++ b/tests/reset_keyprefix.phpt @@ -0,0 +1,38 @@ +--TEST-- +Cannot reset OPT_PREFIX_KEY #293 +--SKIPIF-- + +--FILE-- +set('key1', 'abc'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, false); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, ''); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, null); +var_dump($m->get('key1')); +--EXPECTF-- +string(3) "abc" +bool(false) +string(3) "abc" +bool(false) +string(3) "abc" +bool(false) +string(3) "abc" \ No newline at end of file From c564fd875ead3110b27dd3e1dfb9e5d4afabd042 Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 14:26:57 +0100 Subject: [PATCH 475/694] Cleanup all checks for unsupported libmemcached versions (#295) --- config.m4 | 2 +- package.xml | 2 -- php_libmemcached_compat.c | 37 ------------------------ php_libmemcached_compat.h | 59 --------------------------------------- php_memcached.c | 58 ++++++-------------------------------- php_memcached_private.h | 10 +++++-- php_memcached_session.c | 2 +- 7 files changed, 17 insertions(+), 153 deletions(-) delete mode 100644 php_libmemcached_compat.c delete mode 100644 php_libmemcached_compat.h diff --git a/config.m4 b/config.m4 index e6a2dfd0..ab6142a1 100644 --- a/config.m4 +++ b/config.m4 @@ -318,7 +318,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) diff --git a/package.xml b/package.xml index f2b81369..e8d5c743 100644 --- a/package.xml +++ b/package.xml @@ -72,8 +72,6 @@ Tests - - diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c deleted file mode 100644 index bd35d8fe..00000000 --- a/php_libmemcached_compat.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) 2009 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andrei Zmievski | - +----------------------------------------------------------------------+ -*/ - -#include "php_memcached.h" -#include "php_memcached_private.h" -#include "php_libmemcached_compat.h" - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) -{ -#ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); -#else - memcached_return rc = MEMCACHED_SUCCESS; - uint32_t flags = 0; - size_t value_length = 0; - char *value = NULL; - - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); - if (value) { - free (value); - } - return rc; -#endif -} diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h deleted file mode 100644 index e740d310..00000000 --- a/php_libmemcached_compat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) 2009 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andrei Zmievski | - +----------------------------------------------------------------------+ -*/ - -#ifndef PHP_LIBMEMCACHED_COMPAT -#define PHP_LIBMEMCACHED_COMPAT - -/* this is the version(s) we support */ -#include - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000 -# define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 -# define HAVE_MEMCACHED_TOUCH 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 -# define HAVE_MEMCACHED_INSTANCE_ST 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 -# define HAVE_LIBMEMCACHED_CHECK_CONFIGURATION 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 -# define HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 -# define HAVE_LIBMEMCACHED_MEMCACHED 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018 -# define HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT 1 -#endif - -#ifdef HAVE_MEMCACHED_INSTANCE_ST -typedef const memcached_instance_st * php_memcached_instance_st; -#else -typedef memcached_server_instance_st php_memcached_instance_st; -#endif - -#endif diff --git a/php_memcached.c b/php_memcached.c index e1a045b5..79001319 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1753,7 +1753,6 @@ PHP_METHOD(Memcached, setByKey) } /* }}} */ -#ifdef HAVE_MEMCACHED_TOUCH /* {{{ Memcached::touch(string key, [, int expiration ]) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) @@ -1769,8 +1768,6 @@ PHP_METHOD(Memcached, touchByKey) php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ -#endif - /* {{{ Memcached::setMulti(array items [, int expiration ]) Sets the keys/values specified in the items array */ @@ -2305,17 +2302,7 @@ PHP_METHOD(Memcached, addServer) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (ZSTR_VAL(host)[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, ZSTR_VAL(host), weight); - } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, ZSTR_VAL(host), port, weight); - } else { - status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); - } -#else status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); -#endif if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; @@ -2511,7 +2498,6 @@ PHP_METHOD(Memcached, flushBuffers) } /* }}} */ -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION /* {{{ Memcached::getLastErrorMessage() Returns the last error message that occurred */ PHP_METHOD(Memcached, getLastErrorMessage) @@ -2559,7 +2545,6 @@ PHP_METHOD(Memcached, getLastErrorErrno) RETURN_LONG(memcached_last_error_errno(intern->memc)); } /* }}} */ -#endif /* {{{ Memcached::getLastDisconnectedServer() Returns the last disconnected server @@ -2794,11 +2779,7 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result)); -#else RETURN_STRING(result); -#endif } else { RETURN_EMPTY_STRING(); } @@ -2863,23 +2844,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { zend_string *str; char *key; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; -#endif str = zval_get_string(value); if (ZSTR_LEN(str) == 0) { key = NULL; } else { - /* - work-around a bug in libmemcached in version 0.49 that truncates the trailing - character of the key prefix, to avoid the issue we pad it with a '0' - */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - snprintf(tmp, sizeof(tmp), "%s0", ZSTR_VAL(str)); - key = tmp; -#else key = ZSTR_VAL(str); -#endif } if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { zend_string_release(str); @@ -2908,14 +2877,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) * (non-weighted) case. We have to clean up ourselves. */ if (!lval) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 - (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); -#else - intern->memc->hash = 0; - intern->memc->distribution = 0; -#endif + (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); } break; @@ -3997,10 +3961,10 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) -#ifdef HAVE_MEMCACHED_TOUCH + MEMC_ME(touch, arginfo_touch) MEMC_ME(touchByKey, arginfo_touchByKey) -#endif + MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) @@ -4032,11 +3996,10 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(quit, arginfo_quit) MEMC_ME(flushBuffers, arginfo_flushBuffers) -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) -#endif + MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) MEMC_ME(getStats, arginfo_getStats) @@ -4229,9 +4192,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); -#endif + REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); @@ -4257,14 +4219,10 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_SORT_HOSTS, MEMCACHED_BEHAVIOR_SORT_HOSTS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_VERIFY_KEY, MEMCACHED_BEHAVIOR_VERIFY_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_USE_UDP, MEMCACHED_BEHAVIOR_USE_UDP); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ); -#endif -#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); -#endif -#ifdef HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018 REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_TIMEOUT_LIMIT, MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT); #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index a04e19be..fe6ccc2c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -25,7 +25,13 @@ # include "config.h" #endif -#include "php_libmemcached_compat.h" +#include + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif #include #include @@ -208,8 +214,6 @@ PHP_MINFO_FUNCTION(memcached); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); - zend_bool php_memc_init_sasl_if_needed(); #endif /* PHP_MEMCACHED_PRIVATE_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c index 42659fe5..c7e6d1cd 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -527,7 +527,7 @@ PS_VALIDATE_SID_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { + if (memcached_exist(memc, key->val, key->len) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From d9dea45e9719abd0761ae51368359975cb26534b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 20 Jan 2017 07:21:39 -0500 Subject: [PATCH 476/694] Add release notes about session protocol,get and getMulti changing (#271) And update the memcached-api.php file for the branch. --- memcached-api.php | 8 ++++---- package.xml | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index d22d0cf9..e0e8f944 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -189,13 +189,13 @@ class Memcached { public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - public function get( $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} + public function get( $key, callable $cache_cb = null, $flags = 0) {} - public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} + public function getByKey( $server_key, $key, callable $cache_cb = null, $flags = 0 ) {} - public function getMulti( array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} + public function getMulti( array $keys, $flags = 0) {} - public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} + public function getMultiByKey( $server_key, array $keys, $flags = 0) {} public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} diff --git a/package.xml b/package.xml index e8d5c743..0dd61ada 100644 --- a/package.xml +++ b/package.xml @@ -38,8 +38,9 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * get commands do not take cas or user flags parameters. - * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly @@ -48,6 +49,7 @@ API * CAS tokens are returned as integers and they overflow to strings as needed Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) * Session extension uses PHP allocators (still some work to do on the rest of the extension) * Ini-values take effect during session_start or session_regenerate_id From 172d1ffe694406bf64193070b5498f44c4db093a Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 19:14:54 +0100 Subject: [PATCH 477/694] Fix tests for PHP 7.1 (#297) invoke_callback_2 fails because of ArgumentCountException (init_cb_arg gets only 2 args) Check number of passed arguments with func_num_args() insteadof checking $args is null session_lock fails because of second warning in 7.1 Skip session_lock.phpt for php < 7.1 and create new testcase for >= 7.1 which tests both warnings. Update .travis.yml, don't allow failures for 7.1 anymore! --- .travis.yml | 6 +--- package.xml | 1 + tests/invoke_callback_2.phpt | 17 +++++----- tests/session_lock-php71.phpt | 62 +++++++++++++++++++++++++++++++++++ tests/session_lock.phpt | 2 ++ 5 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 tests/session_lock-php71.phpt diff --git a/.travis.yml b/.travis.yml index 4aae7552..02c367a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,6 @@ php: matrix: fast_finish: true - allow_failures: - - php: 7.1 env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial @@ -31,6 +29,4 @@ script: cache: directories: - - $HOME/cache - - + - $HOME/cache \ No newline at end of file diff --git a/package.xml b/package.xml index 0dd61ada..2091f2e2 100644 --- a/package.xml +++ b/package.xml @@ -165,6 +165,7 @@ Tests + diff --git a/tests/invoke_callback_2.phpt b/tests/invoke_callback_2.phpt index 07e84f94..9749ed18 100644 --- a/tests/invoke_callback_2.phpt +++ b/tests/invoke_callback_2.phpt @@ -18,9 +18,9 @@ function init_cb_fail($m, $id) { echo "configured, should not be called.\n"; } -function init_cb_arg($m, $id, $arg) { +function init_cb_arg($m, $id) { + var_dump(func_num_args()); var_dump($id); - var_dump($arg); } function init_nopersist_cb($m, $id) { @@ -33,15 +33,14 @@ class Foo extends Memcached { parent::__construct($id, array($this, 'init')); } - function init($obj, $id, $options) { + function init($obj, $id) { + var_dump(func_num_args()); var_dump($this->isPristine()); var_dump($this->isPersistent()); var_dump($id); } } -error_reporting(0); - echo "cb call\n"; $m1 = new Memcached('foo1', 'init_cb'); @@ -50,7 +49,6 @@ $m1 = new Memcached('foo1', 'init_cb_fail'); echo "cb arg without arg\n"; $m1 = new Memcached('foo3', 'init_cb_arg'); -echo $php_errormsg, "\n"; echo "cb arg not persistent\n"; $m1 = new Memcached(null, 'init_nopersist_cb'); @@ -63,7 +61,7 @@ $m1 = new Foo('baz'); echo "cb second persistent in object\n"; $m1 = new Foo('baz'); - +?> --EXPECT-- cb call string(9) "Memcached" @@ -71,17 +69,18 @@ bool(true) string(4) "foo1" cb not run cb arg without arg +int(2) string(4) "foo3" -NULL - cb arg not persistent bool(false) NULL cb in object +int(2) bool(true) bool(false) NULL cb persistent in object +int(2) bool(true) bool(true) string(3) "baz" diff --git a/tests/session_lock-php71.phpt b/tests/session_lock-php71.phpt new file mode 100644 index 00000000..207f64cf --- /dev/null +++ b/tests/session_lock-php71.phpt @@ -0,0 +1,62 @@ +--TEST-- +Session lock +--SKIPIF-- + +--INI-- +memcached.sess_locking = true +memcached.sess_lock_wait_min = 500 +memcached.sess_lock_wait_max = 1000 +memcached.sess_lock_retries = 3 +memcached.sess_prefix = "memc.test." + +session.save_handler = memcached + +--FILE-- +addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +ob_start(); +ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); + +session_start(); +$session_id = session_id(); + +$_SESSION["test"] = "hello"; +session_write_close(); + +session_start(); +var_dump ($m->get ('memc.test.' . session_id())); +var_dump ($m->get ('memc.test.lock.' . session_id())); +session_write_close(); +var_dump ($m->get ('memc.test.lock.' . session_id())); + +// Test lock min / max +$m->set ('memc.test.lock.' . $session_id, '1'); + +$time_start = microtime(true); +session_start(); +$time = microtime(true) - $time_start; + +if (round ($time, 1) != 2.5) { + echo "Waited longer than expected: $time" . PHP_EOL; +} +echo "OK"; + +--EXPECTF-- +string(17) "test|s:5:"hello";" +string(1) "1" +bool(false) + +Warning: session_start(): Unable to clear session lock record in %s on line %d + +Warning: session_start(): Failed to read session data: memcached (path: 127.0.0.1:11211) in %s on line %d +OK diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index 79c32888..570e5a2a 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -4,6 +4,8 @@ Session lock = 70100) print "skip"; ?> --INI-- memcached.sess_locking = true From c3f90bcb59dc434986844cc1c91db0e1cd8b078d Mon Sep 17 00:00:00 2001 From: Frost Wong Date: Sat, 21 Jan 2017 02:19:34 +0800 Subject: [PATCH 478/694] correct a spelling mistake (#207) --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index ab6142a1..50e2d3bd 100644 --- a/config.m4 +++ b/config.m4 @@ -24,7 +24,7 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], yes, no) PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, -[ --enable-memcached-protocol Enable memcached protocoll support], no, no) +[ --enable-memcached-protocol Enable memcached protocol support], no, no) PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, [ --with-system-fastlz Use system FastLZ bibrary], no, no) From 5fee5fa9099af5094b1ecc65945fff07918dd6f0 Mon Sep 17 00:00:00 2001 From: Steven Hilder Date: Fri, 20 Jan 2017 21:02:47 +0200 Subject: [PATCH 479/694] Use bool data type for HAVE_* class constants (#166) --- php_memcached.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 79001319..b500b887 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4140,39 +4140,39 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * Indicate whether igbinary serializer is available */ #ifdef HAVE_MEMCACHED_IGBINARY - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0); #endif /* * Indicate whether json serializer is available */ #ifdef HAVE_JSON_API - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 0); #endif /* * Indicate whether msgpack serializer is available */ #ifdef HAVE_MEMCACHED_MSGPACK - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 0); #endif #ifdef HAVE_MEMCACHED_SESSION - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 0); #endif #ifdef HAVE_MEMCACHED_SASL - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 0); #endif /* From b15936c0c04b3c24ec5677f1c4a8bc694d455a4a Mon Sep 17 00:00:00 2001 From: Timandes White Date: Sun, 22 Jan 2017 10:34:50 +0800 Subject: [PATCH 480/694] Add optional parameter 'type' for method 'getStats' (#298) --- memcached-api.php | 2 +- php_memcached.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index e0e8f944..64b20b26 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -275,7 +275,7 @@ public function getLastDisconnectedServer( ) {} public function flush( $delay = 0 ) {} - public function getStats( ) {} + public function getStats( $type = null ) {} public function getVersion( ) {} diff --git a/php_memcached.c b/php_memcached.c index b500b887..0a19f204 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2645,16 +2645,21 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch PHP_METHOD(Memcached, getStats) { memcached_return status; + char *args = NULL; + zend_string *args_string = NULL; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &args_string) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; + if (args_string) + args = ZSTR_VAL(args_string); + array_init(return_value); - status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + status = memcached_stat_execute(intern->memc, args, s_stat_execute_cb, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -3927,6 +3932,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0) + ZEND_ARG_INFO(0, args) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) From 493d6911bfc5460039b428b8c7c66b577511a19c Mon Sep 17 00:00:00 2001 From: Aris Buzachis Date: Sun, 22 Jan 2017 23:37:42 +0200 Subject: [PATCH 481/694] fix: 0 max_execution_time ini value (#266) It seems that zend_ini_long doesn't work anymore with ZEND_STRS and that the extesion should use ZEND_STRL, back again. --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index c7e6d1cd..e8f61cf5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -113,7 +113,7 @@ time_t s_lock_expiration() return s_adjust_expiration(MEMC_SESS_INI(lock_expiration)); } else { - zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + zend_long max_execution_time = zend_ini_long(ZEND_STRL("max_execution_time"), 0); if (max_execution_time > 0) { return s_adjust_expiration(max_execution_time); } From 2af9b615907109874988ff57c27b04eecc862ee2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 23 Jan 2017 07:28:10 +0000 Subject: [PATCH 482/694] Fix port number in getVersion (#300) (390) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 0a19f204..cf26bff6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3353,7 +3353,7 @@ memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcach instance->micro_version); #endif - address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); ZVAL_STR(&rv, version); zend_hash_add(Z_ARRVAL_P(return_value), address, &rv); From 9debfacb8c1c3daeb18388796711c87ad56d6c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samantha=20Qui=C3=B1ones?= Date: Tue, 17 Mar 2015 00:32:06 -0400 Subject: [PATCH 483/694] Extended key checking to match the language of the memcached spec (#167) Updated to php7 branch by Aaron Stone --- php_memcached.c | 43 +++++++++------- tests/keys.phpt | 69 ++++++++++++++++++++++++++ tests/session_badconf_emptyprefix.phpt | 2 +- tests/session_badconf_prefix.phpt | 2 +- 4 files changed, 97 insertions(+), 19 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index cf26bff6..64f135ad 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -202,15 +202,28 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); -#define MEMC_CHECK_KEY(intern, key) \ - if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ - ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ - (memcached_behavior_get(intern->memc, \ - MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? \ - strchr(ZSTR_VAL(key), '\n') : \ - strchr(ZSTR_VAL(key), ' ')))) { \ - intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ - RETURN_FALSE; \ +static +zend_bool s_memc_valid_key_binary(const char *key) +{ + return strchr(key, '\n') == NULL; +} + +static +zend_bool s_memc_valid_key_ascii(const char *key) +{ + while (*key && !iscntrl(*key) && !isspace(*key)) ++key; + return *key == '\0'; +} + +#define MEMC_CHECK_KEY(intern, key) \ + if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ + ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ + ? !s_memc_valid_key_binary(ZSTR_VAL(key)) \ + : !s_memc_valid_key_ascii(ZSTR_VAL(key)) \ + ))) { \ + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ + RETURN_FALSE; \ } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -307,18 +320,14 @@ static PHP_INI_MH(OnUpdateSessionPrefixString) { if (new_value && ZSTR_LEN(new_value) > 0) { - char *ptr = ZSTR_VAL(new_value); - - while (*ptr != '\0') { - if (isspace (*ptr++)) { - php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace characters"); - return FAILURE; - } - } if (ZSTR_LEN(new_value) > MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } + if (!s_memc_valid_key_ascii(ZSTR_VAL(new_value))) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); + return FAILURE; + } } return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } diff --git a/tests/keys.phpt b/tests/keys.phpt index 63cce0a3..f320e03f 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -28,6 +28,11 @@ var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set (''/*empty key*/, 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +for ($i=0;$i<32;$i++) { + var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -46,4 +51,68 @@ bool(false) bool(true) bool(false) bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) OK diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index fd19f1df..f49a8417 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -24,5 +24,5 @@ session_write_close(); echo "OK"; --EXPECTF-- -Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d +Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d OK diff --git a/tests/session_badconf_prefix.phpt b/tests/session_badconf_prefix.phpt index c42e8376..8421edc3 100644 --- a/tests/session_badconf_prefix.phpt +++ b/tests/session_badconf_prefix.phpt @@ -18,7 +18,7 @@ ini_set('memcached.sess_prefix', str_repeat('a', 512)); echo "OK"; --EXPECTF-- -Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d +Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d Warning: ini_set(): memcached.sess_prefix too long (max: %d) in %s on line %d OK \ No newline at end of file From e1932dceb68767995a03345164db8437e00d04e8 Mon Sep 17 00:00:00 2001 From: dyeldandi Date: Tue, 24 Jan 2017 15:37:37 +0400 Subject: [PATCH 484/694] Added error reporting to session code (#301) --- php_memcached_session.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index e8f61cf5..25ca0ae2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -442,6 +442,7 @@ PS_READ_FUNC(memcached) *val = ZSTR_EMPTY_ALLOC(); return SUCCESS; } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); return FAILURE; } } @@ -470,6 +471,8 @@ PS_WRITE_FUNC(memcached) do { if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); } } while (--retries > 0); From 8924e3d72b9c735ec3e411f1958d84ac68b139c7 Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Wed, 25 Jan 2017 02:17:07 +0800 Subject: [PATCH 485/694] fix: compression edge case (#255) * correct the compression_factor calculation * send uncompress value and proper set compressed flags when compression saving is too small --- php_memcached.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 64f135ad..b014ecc6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -108,10 +108,10 @@ static int php_memc_list_entry(void) { #define MEMC_VAL_COMPRESSION_ZLIB (1<<1) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) -#define MEMC_VAL_GET_FLAGS(internal_flags) ((internal_flags & MEMC_MASK_INTERNAL) >> 4) -#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= ((internal_flag << 4) & MEMC_MASK_INTERNAL)) -#define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & internal_flag) == internal_flag) -#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL) +#define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4) +#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL)) +#define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & (internal_flag)) == (internal_flag)) +#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) (internal_flags &= (~(((internal_flag) << 4) & MEMC_MASK_INTERNAL))) /**************************************** User-defined flags @@ -876,7 +876,8 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { + if (ZSTR_LEN(payload) <= (compressed_size * MEMC_G(compression_factor))) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ | MEMC_VAL_COMPRESSION_ZLIB); efree (buffer); return 1; } From 7283b11d147c7fab4915623c627a75a612534a6b Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Fri, 10 Jun 2016 21:37:55 +0800 Subject: [PATCH 486/694] test: compression edge case verification (#256) test compressed SET/GET under various settings of - compression_factor - compression_threshold - data length --- package.xml | 1 + tests/compression_conditions.phpt | 125 ++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 tests/compression_conditions.phpt diff --git a/package.xml b/package.xml index 2091f2e2..27491332 100644 --- a/package.xml +++ b/package.xml @@ -94,6 +94,7 @@ Tests + diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt new file mode 100644 index 00000000..ca3c2d77 --- /dev/null +++ b/tests/compression_conditions.phpt @@ -0,0 +1,125 @@ +--TEST-- +Memcached compression test +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_COMPRESSION, false); + } else { + $m->setOption(Memcached::OPT_COMPRESSION, true); + $m->setOption(Memcached::OPT_COMPRESSION_TYPE, get_compression($set_compression)); + } + + $m->set($key, $value, 1800); + + $value_back = $m->get($key); + var_dump($value === $value_back); +} + +fetch_with_compression($m, 'hello01', $data, 'zlib', 1.3, 4); +fetch_with_compression($m, 'hello02', $data, 'fastlz', 1.3, 4); +fetch_with_compression($m, 'hello03', $data, '', 1.3, 4); +fetch_with_compression($m, 'hello04', $short_data, 'zlib', 1.3, 4); +fetch_with_compression($m, 'hello05', $short_data, 'fastlz', 1.3, 4); +fetch_with_compression($m, 'hello06', $short_data, '', 1.3, 4); +fetch_with_compression($m, 'hello11', $data, 'zlib', 0.3, 4); +fetch_with_compression($m, 'hello12', $data, 'fastlz', 0.3, 4); +fetch_with_compression($m, 'hello13', $data, '', 0.3, 4); +fetch_with_compression($m, 'hello14', $short_data, 'zlib', 0.3, 4); +fetch_with_compression($m, 'hello15', $short_data, 'fastlz', 0.3, 4); +fetch_with_compression($m, 'hello16', $short_data, '', 0.3, 4); +fetch_with_compression($m, 'hello21', $data, 'zlib', 1.3, 2000); +fetch_with_compression($m, 'hello22', $data, 'fastlz', 1.3, 2000); +fetch_with_compression($m, 'hello23', $data, '', 1.3, 2000); +fetch_with_compression($m, 'hello24', $short_data, 'zlib', 1.3, 2000); +fetch_with_compression($m, 'hello25', $short_data, 'fastlz', 1.3, 2000); +fetch_with_compression($m, 'hello26', $short_data, '', 1.3, 2000); +fetch_with_compression($m, 'hello31', $data, 'zlib', 0.3, 2000); +fetch_with_compression($m, 'hello32', $data, 'fastlz', 0.3, 2000); +fetch_with_compression($m, 'hello33', $data, '', 0.3, 2000); +fetch_with_compression($m, 'hello34', $short_data, 'zlib', 0.3, 2000); +fetch_with_compression($m, 'hello35', $short_data, 'fastlz', 0.3, 2000); +fetch_with_compression($m, 'hello36', $short_data, '', 0.3, 2000); +?> +--EXPECT-- +len=[4877] set=[zlib] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[fastlz] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[] factor=[1.3] threshold=[4] +bool(true) +len=[7] set=[zlib] factor=[1.3] threshold=[4] +Memcached::set(): could not compress value +bool(true) +len=[7] set=[fastlz] factor=[1.3] threshold=[4] +bool(true) +len=[7] set=[] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[zlib] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[fastlz] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[] factor=[0.3] threshold=[4] +bool(true) +len=[7] set=[zlib] factor=[0.3] threshold=[4] +Memcached::set(): could not compress value +bool(true) +len=[7] set=[fastlz] factor=[0.3] threshold=[4] +bool(true) +len=[7] set=[] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[zlib] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[fastlz] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[zlib] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[fastlz] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[zlib] factor=[0.3] threshold=[2000] +bool(true) +len=[4877] set=[fastlz] factor=[0.3] threshold=[2000] +bool(true) +len=[4877] set=[] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[zlib] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[fastlz] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[] factor=[0.3] threshold=[2000] +bool(true) From c85f34c01ba884987fa3ed4daf7846e503a89cdf Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 25 Jan 2017 00:12:44 -0800 Subject: [PATCH 487/694] Make sure that s_compress_value() will always leave a valid payload, even if it did not get compressed --- php_memcached.c | 53 ++++++++++++++++--------------- tests/compression_conditions.phpt | 2 -- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index b014ecc6..1e73a4f9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -830,6 +830,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str /* status */ zend_bool compress_status = 0; zend_string *payload = *payload_in; + uint32_t compression_type_flag = 0; /* Additional 5% for the data */ size_t buffer_size = (size_t) (((double) ZSTR_LEN(payload) * 1.05) + 1.0); @@ -847,7 +848,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (compressed_size > 0) { compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + compression_type_flag = MEMC_VAL_COMPRESSION_FASTLZ; } } break; @@ -859,7 +860,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (status == Z_OK) { compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB; } } break; @@ -869,31 +870,29 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str break; } - if (!compress_status) { - php_error_docref(NULL, E_WARNING, "could not compress value"); - efree (buffer); - return 0; - } - - /* This means the value was too small to be compressed, still a success */ + /* This means the value was too small to be compressed and ended up larger */ if (ZSTR_LEN(payload) <= (compressed_size * MEMC_G(compression_factor))) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ | MEMC_VAL_COMPRESSION_ZLIB); - efree (buffer); - return 1; + compress_status = 0; } - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); + /* Replace the payload with the compressed copy */ + if (compress_status) { + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED | compression_type_flag); + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); - payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + /* Copy the uin32_t at the beginning */ + memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); + memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); - /* Copy the uin32_t at the beginning */ - memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); - memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); - efree(buffer); + zend_string_forget_hash_val(payload); + *payload_in = payload; - zend_string_forget_hash_val(payload); - *payload_in = payload; - return 1; + return 1; + } + + /* Original payload was not modified */ + return 0; } static @@ -1043,11 +1042,13 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t /* If we have compression flag, compress the value */ if (should_compress) { - /* status */ - if (!s_compress_value (memc_user_data->compression_type, &payload, flags)) { - zend_string_release(payload); - return NULL; - } + /* s_compress_value() will always leave a valid payload, even if that payload + * did not actually get compressed. The flags will be set according to the + * to the compression type or no compression. + * + * No need to check the return value because the payload is always valid. + */ + (void)s_compress_value (memc_user_data->compression_type, &payload, flags); } if (memc_user_data->set_udf_flags >= 0) { diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt index ca3c2d77..749ebe8a 100644 --- a/tests/compression_conditions.phpt +++ b/tests/compression_conditions.phpt @@ -80,7 +80,6 @@ bool(true) len=[4877] set=[] factor=[1.3] threshold=[4] bool(true) len=[7] set=[zlib] factor=[1.3] threshold=[4] -Memcached::set(): could not compress value bool(true) len=[7] set=[fastlz] factor=[1.3] threshold=[4] bool(true) @@ -93,7 +92,6 @@ bool(true) len=[4877] set=[] factor=[0.3] threshold=[4] bool(true) len=[7] set=[zlib] factor=[0.3] threshold=[4] -Memcached::set(): could not compress value bool(true) len=[7] set=[fastlz] factor=[0.3] threshold=[4] bool(true) From 6085768b48705b1e2a8f4ca516e43e0105850f3d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 26 Jan 2017 02:06:30 +0000 Subject: [PATCH 488/694] Support for 64-bit offsets for increment and decrement (#306) While the memcached protocol allows for 64-bit increments or decrements, there is a quirk in the libmemcached API that the memcached_increment() and memcached_decrement() functions take only a 32-bit adjustment value. Since the memcached_increment_by_key() and memcached_decrement_by_key() functions do accept 64-bit adjustment values, and the memcached_increment() and memcached_decrement() functions are simply wrappers around those, we'll use them directly and thus support 64-bit adjustments in all cases. --- php_memcached.c | 25 +++++++++++++++---------- tests/incrdecr.phpt | 22 ++++++++++++++++++---- tests/incrdecr_bykey.phpt | 22 ++++++++++++++++++---- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1e73a4f9..93d8738f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2185,7 +2185,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { zend_string *key, *server_key = NULL; - long offset = 1; + zend_long offset = 1; uint64_t value = UINT64_MAX, initial = 0; time_t expiry = 0; memcached_return status; @@ -2208,22 +2208,27 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_CHECK_KEY(intern, key); if (offset < 0) { - php_error_docref(NULL, E_WARNING, "offset has to be > 0"); + php_error_docref(NULL, E_WARNING, "offset cannot be a negative value"); RETURN_FALSE; } if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } else { - status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } } else { + /* The libmemcached API has a quirk that memcached_increment() takes only a 32-bit + * offset, but memcached_increment_by_key() and all other increment and decrement + * functions take a 64-bit offset. The memcached protocol allows increment/decrement + * greater than UINT_MAX, so we just work around memcached_increment() here. + */ if (incr) { - status = memcached_increment(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } else { - status = memcached_decrement(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } } @@ -2237,15 +2242,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index fc640985..cb3914a4 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -29,14 +29,25 @@ $m->decrement('foo', 2); var_dump($m->get('foo')); error_reporting(0); -echo "Invalid offset\n"; + +echo "Negative offset\n"; +$php_errormsg = ''; $m->increment('foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); + +$php_errormsg = ''; $m->decrement('foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); +echo "Enormous offset\n"; +$m->increment('foo', 4294967296); +var_dump($m->get('foo')); + +$m->decrement('foo', 4294967296); +var_dump($m->get('foo')); + --EXPECT-- Not there bool(false) @@ -51,8 +62,11 @@ int(2) int(4) int(3) int(1) -Invalid offset -Memcached::increment(): offset has to be > 0 +Negative offset +Memcached::increment(): offset cannot be a negative value +int(1) +Memcached::decrement(): offset cannot be a negative value int(1) -Memcached::decrement(): offset has to be > 0 +Enormous offset +int(4294967297) int(1) diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 9c2db8dd..809f3b83 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -26,14 +26,25 @@ $m->decrementByKey('foo', 'foo', 2); var_dump($m->get('foo')); error_reporting(0); -echo "Invalid offset\n"; + +echo "Negative offset\n"; +$php_errormsg = ''; $m->incrementByKey('foo', 'foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); + +$php_errormsg = ''; $m->decrementByKey('foo', 'foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); +echo "Enormous offset\n"; +$m->incrementByKey('foo', 'foo', 4294967296); +var_dump($m->get('foo')); + +$m->decrementByKey('foo', 'foo', 4294967296); +var_dump($m->get('foo')); + --EXPECT-- Not there bool(false) @@ -45,8 +56,11 @@ int(2) int(4) int(3) int(1) -Invalid offset -Memcached::incrementByKey(): offset has to be > 0 +Negative offset +Memcached::incrementByKey(): offset cannot be a negative value +int(1) +Memcached::decrementByKey(): offset cannot be a negative value int(1) -Memcached::decrementByKey(): offset has to be > 0 +Enormous offset +int(4294967297) int(1) From 7a3b50992c5f68ed07132b6780128b3c7a1295e8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 26 Jan 2017 01:43:46 -0800 Subject: [PATCH 489/694] Add ChangeLog notes and tentative release date for 3.0.0 --- ChangeLog | 39 +++++++++++++++++++++++++++++++++++++++ package.xml | 21 +++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05f77181..24cb0a74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,44 @@ memcached extension changelog +Version 3.0.0 (2017-01-27) +-------------------------- + * Support for PHP 7.0 and PHP 7.1 + * Fix compiling with SASL disabled + * Improved the test suite and Travis CI test runners + * Fix small string compression / decompression + * Fix increment/decrement with adjustments greater than 32-bit integers + * Fix session.gc_maxlifetime to handle both relative and absolute times + * Fix inability to reset OPT_PREFIX_KEY + +Version 3.0.0a1 (2016-02-22) +---------------------------- + Dependencies + * Support for PHP 7.0 + * Requires libmemcached 1.0 or higher + * Optional extension igbinary must 2.0 or higher + * Optional extension msgpack must be 2.0 or higher + + API + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed + + Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + + Tests + * Fix several problematic tests + Version 2.2.0 (2014-04-01) -------------------------- * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour diff --git a/package.xml b/package.xml index 27491332..357086f8 100644 --- a/package.xml +++ b/package.xml @@ -21,21 +21,20 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-22 + 2017-01-27 - 3.0.0a1 + 3.0.0 3.0.0 - alpha - alpha + stable + stable PHP PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated -before we move closer to releasing stable version. +libmemcached. API * The method signature of get, getByKey, getMulti, and getMultiByKey changed. @@ -179,6 +178,16 @@ Tests 1.4.0b1 + + + igbinary + 2.0 + + + msgpack + 2.0 + + memcached From e495a6bb1de9ab7940d431f3deecf6d8e71584d2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 30 Jan 2017 14:27:55 -0800 Subject: [PATCH 490/694] Bump version to 3.0.0 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 9e466cb4..0b1a9264 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.0b1" +#define PHP_MEMCACHED_VERSION "3.0.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 218b019509453a463b8485afe1869a42051a6414 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 30 Jan 2017 21:58:31 -0800 Subject: [PATCH 491/694] Fix memory leak from recent change to s_compress_value Commit c85f34c01ba884987fa3ed4daf7846e503a89cdf cleaned up the function, but missed an all-important efree(buffer) on the no-compression path. --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 93d8738f..ba3473de 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -892,6 +892,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* Original payload was not modified */ + efree(buffer); return 0; } From e4f4878f123b1b7c2ef839e12c022de9629937ec Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 2 Feb 2017 19:53:25 +0000 Subject: [PATCH 492/694] Travis CI purge old versions of memcached and libmemcached (#309) * Purge all things memcached from Travis CI before installing local copies * Add ancient libmemcached 1.0.2 to Travis CI matrix --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 02c367a9..2581b516 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty + - LIBMEMCACHED_VERSION=1.0.2 # Ancient addons: apt: @@ -22,6 +23,7 @@ addons: - libevent-dev before_script: + - sudo apt-get purge -qq '^memcached*' '^libmemcached*' - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION script: @@ -29,4 +31,4 @@ script: cache: directories: - - $HOME/cache \ No newline at end of file + - $HOME/cache From fa620a48c4e5676c9f79b49694d90e3c3d7e78b6 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:07 +0000 Subject: [PATCH 493/694] Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) This partially reverts commit c564fd875ead3110b27dd3e1dfb9e5d4afabd042 from #295 --- config.m4 | 2 +- package.xml | 2 ++ php_libmemcached_compat.c | 37 +++++++++++++++++++++++++++++++++++++ php_libmemcached_compat.h | 31 +++++++++++++++++++++++++++++++ php_memcached.c | 2 -- php_memcached_private.h | 10 +++------- php_memcached_session.c | 2 +- 7 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 php_libmemcached_compat.c create mode 100644 php_libmemcached_compat.h diff --git a/config.m4 b/config.m4 index 50e2d3bd..b34c30bf 100644 --- a/config.m4 +++ b/config.m4 @@ -318,7 +318,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi - PHP_MEMCACHED_FILES="php_memcached.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) diff --git a/package.xml b/package.xml index 357086f8..2f01cf46 100644 --- a/package.xml +++ b/package.xml @@ -73,6 +73,8 @@ Tests + + diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c new file mode 100644 index 00000000..bd35d8fe --- /dev/null +++ b/php_libmemcached_compat.c @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#include "php_memcached.h" +#include "php_memcached_private.h" +#include "php_libmemcached_compat.h" + +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +{ +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); +#else + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); + } + return rc; +#endif +} diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h new file mode 100644 index 00000000..9bcbc20f --- /dev/null +++ b/php_libmemcached_compat.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_LIBMEMCACHED_COMPAT +#define PHP_LIBMEMCACHED_COMPAT + +/* this is the version(s) we support */ +#include + +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif + +#endif diff --git a/php_memcached.c b/php_memcached.c index ba3473de..514f4c33 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4022,7 +4022,6 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) - MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) MEMC_ME(getStats, arginfo_getStats) @@ -4216,7 +4215,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); - REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); diff --git a/php_memcached_private.h b/php_memcached_private.h index fe6ccc2c..a04e19be 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -25,13 +25,7 @@ # include "config.h" #endif -#include - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 -typedef const memcached_instance_st * php_memcached_instance_st; -#else -typedef memcached_server_instance_st php_memcached_instance_st; -#endif +#include "php_libmemcached_compat.h" #include #include @@ -214,6 +208,8 @@ PHP_MINFO_FUNCTION(memcached); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + zend_bool php_memc_init_sasl_if_needed(); #endif /* PHP_MEMCACHED_PRIVATE_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c index 25ca0ae2..1695b330 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -530,7 +530,7 @@ PS_VALIDATE_SID_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - if (memcached_exist(memc, key->val, key->len) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From a86de05e86c47542f03084b6a6f37b5ba1e733cc Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:23 +0000 Subject: [PATCH 494/694] Fix compiling with memcached binary protocol enabled (#312) --- php_memcached.c | 22 +++------------------- php_memcached.h | 8 ++++++++ php_memcached_server.c | 33 ++++++++++++++------------------- 3 files changed, 25 insertions(+), 38 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 514f4c33..78528332 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -51,12 +51,6 @@ # include "ext/msgpack/php_msgpack.h" #endif -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) -#else -#define MEMC_G(v) (php_memcached_globals.memc.v) -#endif - static int le_memc; static int php_memc_list_entry(void) { @@ -238,24 +232,14 @@ static inline php_memc_server_t *php_memc_server_fetch_object(zend_object *obj) } #define Z_MEMC_SERVER_P(zv) php_memc_server_fetch_object(Z_OBJ_P(zv)) -#ifdef ZTS -#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) -#else -#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) -#endif +static zend_object_handlers memcached_server_object_handlers; +static zend_class_entry *memcached_server_ce = NULL; #endif static zend_class_entry *memcached_ce = NULL; - static zend_class_entry *memcached_exception_ce = NULL; - static zend_object_handlers memcached_object_handlers; -#ifdef HAVE_MEMCACHED_PROTOCOL -static zend_object_handlers memcached_server_object_handlers; -static zend_class_entry *memcached_server_ce = NULL; -#endif - #ifdef HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -3644,7 +3628,7 @@ PHP_METHOD(MemcachedServer, run) static PHP_METHOD(MemcachedServer, on) { - long event; + zend_long event; zend_fcall_info fci; zend_fcall_info_cache fci_cache; zend_bool rc = 0; diff --git a/php_memcached.h b/php_memcached.h index 0b1a9264..5d1e3a77 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,6 +42,14 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry +#ifdef ZTS +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) +#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +#else +#define MEMC_G(v) (php_memcached_globals.memc.v) +#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +#endif + #endif /* PHP_MEMCACHED_H */ /* diff --git a/php_memcached_server.c b/php_memcached_server.c index 94305101..4c0080e8 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -24,7 +24,7 @@ #undef _NDEBUG #include -#define MEMC_GET_CB(cb_type) (MEMC_G(server.callbacks)[cb_type]) +#define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ @@ -37,7 +37,7 @@ #define MEMC_MAKE_RESULT_CAS(my_zresult_cas, my_result_cas) \ do { \ my_result_cas = 0; \ - my_result_cas = zval_get_double(my_zresult_cas); \ + my_result_cas = zval_get_double(&my_zresult_cas); \ } while (0) @@ -56,27 +56,22 @@ typedef struct { } php_memc_client_t; static -long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count) +long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t param_count) { - long retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *retval_ptr = NULL; + zval *retval = NULL; - cb->fci.params = params; + cb->fci.retval = retval; + cb->fci.params = params; cb->fci.param_count = param_count; - - /* Call the cb */ - cb->fci.no_separation = 1; - cb->fci.retval_ptr_ptr = &retval_ptr; + cb->fci.no_separation = 1; if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { - char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache)); + char *buf = php_memc_printable_func(&(cb->fci), &(cb->fci_cache)); php_error_docref(NULL, E_WARNING, "Failed to invoke callback %s()", buf); efree (buf); } - if (retval_ptr) { - retval = zval_get_long(retval_ptr); - } - return retval; + + return retval == NULL ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(retval); } // memcached protocol callbacks @@ -217,7 +212,7 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - *result = (uint64_t)zval_get_long(zresult); + *result = (uint64_t)zval_get_long(&zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); @@ -301,7 +296,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_COPY(¶ms[0], &zcookie); - ZVAL_COPY(¶ms[1], &zwhen) + ZVAL_COPY(¶ms[1], &zwhen); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); @@ -561,7 +556,7 @@ protocol_binary_response_status s_version_handler (const void *cookie, convert_to_string(&zversion); } - retval = response_handler (cookie, Z_STRVAL_P(zversion), (uint32_t) Z_STRLEN_P(zversion)); + retval = response_handler (cookie, Z_STRVAL(zversion), (uint32_t) Z_STRLEN(zversion)); } zval_ptr_dtor(¶ms[0]); @@ -592,7 +587,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) socklen_t addr_in_len = sizeof(addr_in); if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr), 1); + ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr)); ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); From 08b39ed6b142a1a059295c803d50e625741e3f5a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:41 +0000 Subject: [PATCH 495/694] Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) --- php_memcached.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 78528332..d6f42575 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2725,7 +2725,15 @@ PHP_METHOD(Memcached, getAllKeys) array_init(return_value); rc = memcached_dump(intern->memc, callback, return_value, 1); - if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { + + /* Ignore two errors. libmemcached has a hardcoded loop of 200 slab + * classes that matches memcached < 1.4.24, at which version the server + * has only 63 slabs and throws an error when requesting the 64th slab. + * + * In multi-server some non-deterministic number of elements will be dropped. + */ + if (rc != MEMCACHED_CLIENT_ERROR && rc != MEMCACHED_SERVER_ERROR + && s_memc_status_handle_result_code(intern, rc) == FAILURE) { zval_dtor(return_value); RETURN_FALSE; } From 115cc0a2c41f617b639c55beed5513a06898403f Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:54 +0000 Subject: [PATCH 496/694] Add API entries for flushBuffers() and getAllKeys() (#316) --- memcached-api.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 64b20b26..df725091 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -275,7 +275,11 @@ public function getLastDisconnectedServer( ) {} public function flush( $delay = 0 ) {} + public function flushBuffers( ) {} + public function getStats( $type = null ) {} + + public function getAllKeys( ) {} public function getVersion( ) {} From d019588648d3e7dd8d642234c95ff6f85cac1d94 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 06:19:13 -0800 Subject: [PATCH 497/694] Notes for version 3.0.1 --- ChangeLog | 9 +++++++ package.xml | 67 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 24cb0a74..a21e14b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ memcached extension changelog +Version 3.0.1 (2017-02-07) +------------- + + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) + Version 3.0.0 (2017-01-27) -------------------------- * Support for PHP 7.0 and PHP 7.1 diff --git a/package.xml b/package.xml index 2f01cf46..3366baf3 100644 --- a/package.xml +++ b/package.xml @@ -21,9 +21,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2017-01-27 + 2017-02-07 - 3.0.0 + 3.0.1 3.0.0 @@ -36,26 +36,12 @@ PHP7 release of memcached extension. Note that support for libmemcached 0.x seri and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of libmemcached. -API - * The method signature of get, getByKey, getMulti, and getMultiByKey changed. - * get* and getMulti* commands no longer take cas or user flags parameters. - * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. - * Fixes getStats command to return all stats from all servers - * Fixes allKeys command behaviour - * Fixes error where cache callback for get command was not setting expiration time properly - * Added server type to server list - * Remove use_sasl ini-variable and initialise sasl as needed - * CAS tokens are returned as integers and they overflow to strings as needed - -Session handler - * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) - * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) - * Session extension uses PHP allocators (still some work to do on the rest of the extension) - * Ini-values take effect during session_start or session_regenerate_id - * Fixes crash with session_regenerate_id (work-around for PHP bug) - -Tests - * Fix several problematic tests +Fixes + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) @@ -196,6 +182,43 @@ Tests + + + stable + stable + + + 3.0.0 + 3.0.0 + + 2016-01-27 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed + +Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using tw + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several problematic tests + + alpha From 71f20e19253f27d6deaeab200007bd4cf9d8aec4 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 06:20:51 -0800 Subject: [PATCH 498/694] Bump version to 3.0.1 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 5d1e3a77..1a9411f9 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.0" +#define PHP_MEMCACHED_VERSION "3.0.1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 8a40f2ca5f08f3b3d9fe1eb7f068737484b0bc03 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 8 Feb 2017 10:00:47 -0800 Subject: [PATCH 499/694] Add myself to package.xml before uploading to PECL --- package.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.xml b/package.xml index 3366baf3..bbec4158 100644 --- a/package.xml +++ b/package.xml @@ -21,6 +21,12 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes + + Aaron Stone + sodabrew + aaron@serendipity.cx + yes + 2017-02-07 3.0.1 From f8fd6228e34e1b49947890b060a501a6eab6978c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 9 Feb 2017 07:24:15 +0100 Subject: [PATCH 500/694] ensure tests are ok for 32bits build --- tests/gh_90.phpt | 4 ++-- tests/incrdecr.phpt | 6 +++--- tests/incrdecr_bykey.phpt | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt index 733b7615..2a16f603 100644 --- a/tests/gh_90.phpt +++ b/tests/gh_90.phpt @@ -12,7 +12,7 @@ $memcached = memc_get_instance (array ( // Create a key for use as a lock. If this key already exists, wait till it doesn't exist. { $key = 'LockKey'; - $lockToken = mt_rand(0, pow(2, 32)); //Random value betwen 0 and 2^32 for ownership verification + $lockToken = mt_rand(0, mt_getrandmax()); //Random value for ownership verification while (true) { @@ -88,4 +88,4 @@ array(10) { int(1) ["9_%s"]=> int(1) -} \ No newline at end of file +} diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index cb3914a4..b4e9469b 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -42,10 +42,10 @@ echo $php_errormsg, "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; -$m->increment('foo', 4294967296); +$m->increment('foo', 0x7f000000); var_dump($m->get('foo')); -$m->decrement('foo', 4294967296); +$m->decrement('foo', 0x7f000000); var_dump($m->get('foo')); --EXPECT-- @@ -68,5 +68,5 @@ int(1) Memcached::decrement(): offset cannot be a negative value int(1) Enormous offset -int(4294967297) +int(2130706433) int(1) diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 809f3b83..8b931fa7 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -39,10 +39,10 @@ echo $php_errormsg, "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; -$m->incrementByKey('foo', 'foo', 4294967296); +$m->incrementByKey('foo', 'foo', 0x7f000000); var_dump($m->get('foo')); -$m->decrementByKey('foo', 'foo', 4294967296); +$m->decrementByKey('foo', 'foo', 0x7f000000); var_dump($m->get('foo')); --EXPECT-- @@ -62,5 +62,5 @@ int(1) Memcached::decrementByKey(): offset cannot be a negative value int(1) Enormous offset -int(4294967297) +int(2130706433) int(1) From ecd77ab93ff060f27bef32e40c2bd88fba3df199 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 9 Feb 2017 06:40:50 -0800 Subject: [PATCH 501/694] Recommend libmemcached 1.0.18 or higher to match the release notes --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 0cb2c032..f145c2df 100644 --- a/README.markdown +++ b/README.markdown @@ -34,7 +34,7 @@ php-memcached 2.x: * Optionally supports igbinary 1.0 or higher. * Optionally supports msgpack 0.5 or higher. -[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or +[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.18 or higher is recommended for best performance and compatibility with memcached servers. From 83d5f308999ffad2c0642b7e450e2e350e464342 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 10 Feb 2017 13:51:14 +0000 Subject: [PATCH 502/694] Separate test for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) --- package.xml | 2 ++ tests/incrdecr_64.phpt | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/incrdecr_64.phpt diff --git a/package.xml b/package.xml index bbec4158..7aadf4db 100644 --- a/package.xml +++ b/package.xml @@ -74,6 +74,7 @@ Fixes + @@ -143,6 +144,7 @@ Fixes + diff --git a/tests/incrdecr_64.phpt b/tests/incrdecr_64.phpt new file mode 100644 index 00000000..dfa32c6a --- /dev/null +++ b/tests/incrdecr_64.phpt @@ -0,0 +1,39 @@ +--TEST-- +64-bit Memcached::increment() decrement() incrementByKey() decrementByKey() +--SKIPIF-- + +--FILE-- +set('foo', 1); +var_dump($m->get('foo')); + +echo "Enormous offset 64-bit\n"; +$m->increment('foo', 0x100000000); +var_dump($m->get('foo')); + +$m->decrement('foo', 0x100000000); +var_dump($m->get('foo')); + +echo "Enormous offset 64-bit by key\n"; +$m->incrementByKey('foo', 'foo', 0x100000000); +var_dump($m->get('foo')); + +$m->decrementByKey('foo', 'foo', 0x100000000); +var_dump($m->get('foo')); + +--EXPECT-- +Normal +int(1) +Enormous offset 64-bit +int(4294967297) +int(1) +Enormous offset 64-bit by key +int(4294967297) +int(1) From f7c92b06997d298f63a13d1791fa7a050c8598b9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 15:56:22 +0000 Subject: [PATCH 503/694] Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) --- package.xml | 1 + php_libmemcached_compat.c | 21 +++++++++++++++ php_libmemcached_compat.h | 3 +++ php_memcached.c | 13 ++------- php_memcached_session.c | 2 +- tests/gh_155.phpt | 7 +++-- tests/session_basic.phpt | 1 + tests/session_basic2.phpt | 1 + tests/session_basic3.phpt | 1 + tests/session_lazy_warning.phpt | 47 +++++++++++++++++++++++++++++++++ tests/session_lock-php71.phpt | 4 +++ tests/session_lock.phpt | 4 +++ tests/touch_binary.phpt | 5 +++- 13 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 tests/session_lazy_warning.phpt diff --git a/package.xml b/package.xml index 7aadf4db..a5c7c07b 100644 --- a/package.xml +++ b/package.xml @@ -157,6 +157,7 @@ Fixes + diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index bd35d8fe..7f003b1d 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -35,3 +35,24 @@ memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) return rc; #endif } + +memcached_return php_memcached_touch(memcached_st *memc, const char *key, size_t key_len, time_t expiration) +{ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached"); + } +#endif + return memcached_touch(memc, key, key_len, expiration); +} + +memcached_return php_memcached_touch_by_key(memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, time_t expiration) +{ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached"); + } +#endif + return memcached_touch_by_key(memc, server_key, server_key_len, key, key_len, expiration); +} + diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 9bcbc20f..42a409dc 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -22,6 +22,9 @@ memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); +memcached_return php_memcached_touch(memcached_st *memc, const char *key, size_t key_len, time_t expiration); +memcached_return php_memcached_touch_by_key(memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, time_t expiration); + #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 typedef const memcached_instance_st * php_memcached_instance_st; #else diff --git a/php_memcached.c b/php_memcached.c index d6f42575..19673323 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1081,7 +1081,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); + status = php_memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1113,7 +1113,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); + status = php_memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1959,15 +1959,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } } - - if (op == MEMC_OP_TOUCH) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); - } -#endif - } - if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) { RETURN_FALSE; } diff --git a/php_memcached_session.c b/php_memcached_session.c index 1695b330..b6d93c5f 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -542,7 +542,7 @@ PS_UPDATE_TIMESTAMP_FUNC(memcached) memcached_st *memc = PS_GET_MOD_DATA(); time_t expiration = s_session_expiration(maxlifetime); - if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + if (php_memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; } return SUCCESS; diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index a5b61d00..699e8eca 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -4,7 +4,10 @@ Test for bug 155 --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL,true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); $key = 'bug_155_' . uniqid(); diff --git a/tests/session_basic.phpt b/tests/session_basic.phpt index 3fdb6bd7..0e8b3469 100644 --- a/tests/session_basic.phpt +++ b/tests/session_basic.phpt @@ -7,6 +7,7 @@ if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- = 0x01000018) die ('skip too old libmemcached'); +?> +--INI-- +session.save_handler = memcached +memcached.sess_binary_protocol = On +--FILE-- +TRUE]); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECTF-- +NULL +array(1) { + ["foo"]=> + int(1) +} + +Warning: session_write_close(): using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached in %s on line %d +array(0) { +} diff --git a/tests/session_lock-php71.phpt b/tests/session_lock-php71.phpt index 207f64cf..c0fceb67 100644 --- a/tests/session_lock-php71.phpt +++ b/tests/session_lock-php71.phpt @@ -14,6 +14,10 @@ memcached.sess_lock_wait_max = 1000 memcached.sess_lock_retries = 3 memcached.sess_prefix = "memc.test." +# Turn off binary protocol while the test matrix has older versions of +# libmemcached for which the extension warns of a broken touch command. +memcached.sess_binary_protocol = Off + session.save_handler = memcached --FILE-- diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index 570e5a2a..cedc83bb 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -14,6 +14,10 @@ memcached.sess_lock_wait_max = 1000 memcached.sess_lock_retries = 3 memcached.sess_prefix = "memc.test." +# Turn off binary protocol while the test matrix has older versions of +# libmemcached for which the extension warns of a broken touch command. +memcached.sess_binary_protocol = Off + session.save_handler = memcached --FILE-- diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index cc35e8fb..382c1778 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -4,7 +4,10 @@ Touch in binary mode --FILE-- Date: Sun, 12 Feb 2017 08:05:55 -0800 Subject: [PATCH 504/694] Release notes for 3.0.2 --- ChangeLog | 9 ++++++++- package.xml | 36 +++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index a21e14b8..914cb4e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,14 @@ memcached extension changelog +Version 3.0.2 (2017-02-12) +-------------------------- + + * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + Version 3.0.1 (2017-02-07) -------------- +-------------------------- * Add API entries for flushBuffers() and getAllKeys() (#316) * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) diff --git a/package.xml b/package.xml index a5c7c07b..82b6a39e 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-07 + 2017-02-12 - 3.0.1 + 3.0.2 3.0.0 @@ -43,11 +43,10 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Add API entries for flushBuffers() and getAllKeys() (#316) - * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) - * Fix compiling with memcached binary protocol enabled (#312) - * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) - * Travis CI purge old versions of memcached and libmemcached (#309) + * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + @@ -191,6 +190,29 @@ Fixes + + + stable + stable + + + 3.0.1 + 3.0.0 + + 2016-02-07 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) + + stable From de250ed68cce14b6779316b3909b22e777469bf8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 08:06:04 -0800 Subject: [PATCH 505/694] Bump version to 3.0.2 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 1a9411f9..e36b614b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.1" +#define PHP_MEMCACHED_VERSION "3.0.2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 81bc04f1ac45181b06a788124c04e381d8aa2481 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 16:04:39 -0800 Subject: [PATCH 506/694] Use the word below instead of less-than symbol in package.xml because XML --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 82b6a39e..bfaf51ae 100644 --- a/package.xml +++ b/package.xml @@ -43,7 +43,7 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) From 1e7e4eedb62befa7449a92528d6e0adaf8786369 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:26:55 +0800 Subject: [PATCH 507/694] Fixed issue #327 --- php_memcached_session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index b6d93c5f..8678ffff 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -435,8 +435,9 @@ PS_READ_FUNC(memcached) payload = memcached_get(memc, key->val, key->len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { + zend_bool *is_persistent = memcached_get_user_data(memc); *val = zend_string_init(payload, payload_len, 0); - efree(payload); + pefree(payload, *is_persistent); return SUCCESS; } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); From bff303547f67f6832a5df48b3e5eb78642871156 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:32:16 +0800 Subject: [PATCH 508/694] Fixed memleak (severs) --- package.xml | 1 + php_memcached_session.c | 1 + tests/session_persistent.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/session_persistent.phpt diff --git a/package.xml b/package.xml index bfaf51ae..554aa428 100644 --- a/package.xml +++ b/package.xml @@ -118,6 +118,7 @@ Fixes + diff --git a/php_memcached_session.c b/php_memcached_session.c index 8678ffff..afa973bb 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -351,6 +351,7 @@ PS_OPEN_FUNC(memcached) else { efree(plist_key); PS_SET_MOD_DATA(memc); + memcached_server_list_free(servers); return SUCCESS; } } diff --git a/tests/session_persistent.phpt b/tests/session_persistent.phpt new file mode 100644 index 00000000..cb29c3e8 --- /dev/null +++ b/tests/session_persistent.phpt @@ -0,0 +1,27 @@ +--TEST-- +Session persistent +--SKIPIF-- + +--INI-- +session.save_handler=memcached +memcached.sess_persistent=1 +--FILE-- + +--EXPECT-- +array(1) { + ["test"]=> + bool(true) +} From a8517cd97b4df25cdc04b3f40b810c0202c7daba Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:34:48 +0800 Subject: [PATCH 509/694] dev version --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index e36b614b..1ec55df6 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.2" +#define PHP_MEMCACHED_VERSION "3.0.3-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 99cab0e08166ca9b4219016b30cf0d5e2c0f393c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 17:23:35 -0800 Subject: [PATCH 510/694] Fix session-persistent test failures on older libmemcached versions --- tests/session_persistent.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/session_persistent.phpt b/tests/session_persistent.phpt index cb29c3e8..e096f2b6 100644 --- a/tests/session_persistent.phpt +++ b/tests/session_persistent.phpt @@ -3,7 +3,8 @@ Session persistent --SKIPIF-- --INI-- session.save_handler=memcached From beb58dc69f59fff185baa92cef6a6e739769a5ab Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:30:22 -0800 Subject: [PATCH 511/694] Replace traditional free with pefree to match the registered allocators, fixes #328 --- php_libmemcached_compat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index 7f003b1d..4e294647 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -18,19 +18,20 @@ #include "php_memcached_private.h" #include "php_libmemcached_compat.h" -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +memcached_return php_memcached_exist(memcached_st *memc, zend_string *key) { #ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); + return memcached_exist(memc, key->val, key->len); #else memcached_return rc = MEMCACHED_SUCCESS; uint32_t flags = 0; size_t value_length = 0; char *value = NULL; - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + value = memcached_get(memc, key->val, key->len, &value_length, &flags, &rc); if (value) { - free (value); + zend_bool *is_persistent = memcached_get_user_data(memc); + pefree(value, *is_persistent); } return rc; #endif From 357efc40df1fee72a5fca918be308ebf97afd87b Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:48:33 -0800 Subject: [PATCH 512/694] Release notes for 3.0.3 --- ChangeLog | 6 ++++++ package.xml | 31 +++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 914cb4e3..1db3dd44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ memcached extension changelog +Version 3.0.3 (2017-02-19) +-------------------------- + + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) + Version 3.0.2 (2017-02-12) -------------------------- diff --git a/package.xml b/package.xml index 554aa428..2306344d 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-12 + 2017-02-19 - 3.0.2 + 3.0.3 3.0.0 @@ -43,10 +43,8 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) - * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) - * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) - + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) @@ -191,6 +189,27 @@ Fixes + + + stable + stable + + + 3.0.2 + 3.0.0 + + 2016-02-12 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + + stable From 466485a2ca98b4c1354c7815d23e3bdc64b69db9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:48:43 -0800 Subject: [PATCH 513/694] Bump version to 3.0.3 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 1ec55df6..65a0349f 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.3-dev" +#define PHP_MEMCACHED_VERSION "3.0.3" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From d81697f7a04646edbbed8ecf34cb524ab1ff8d3c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 20 Feb 2017 19:27:39 +0100 Subject: [PATCH 514/694] Refresh memcached.ini provided configuration - remove deprecated options - add missing memcached.sess_server_failure_limit option - comment all options default value (only needed when not default value) see php.ini-production which follow this convention --- memcached.ini | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/memcached.ini b/memcached.ini index 59001aaf..fa9a6fd4 100644 --- a/memcached.ini +++ b/memcached.ini @@ -2,45 +2,39 @@ ; Use session locking ; valid values: On, Off ; the default is On -memcached.sess_locking = On - -; !! DEPRECATED AND REMOVED in 3.x !! -; memcached.sess_lock_wait = 150000 - -; !! DEPRECATED AND REMOVED in 3.x !! -; memcached.sess_lock_max_wait = 0; +;memcached.sess_locking = On ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max ; is reached, after which any further retries will take sess_lock_wait_max seconds. ; Default is 1000. -memcached.sess_lock_wait_min = 1000; +;memcached.sess_lock_wait_min = 1000; ; The maximum time, in milliseconds, to wait between session lock attempts. ; Default is 2000. -memcached.sess_lock_wait_max = 2000; +;memcached.sess_lock_wait_max = 2000; ; The number of times to retry locking the session lock, not including the first attempt. ; Default is 5. -memcached.sess_lock_retries = 5; +;memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to ; use the memcached.sess_lock_max_wait setting. If that is ; also 0, max_execution_time will be used. -memcached.sess_lock_expire = 0; +;memcached.sess_lock_expire = 0; ; memcached session key prefix ; valid values are strings less than 219 bytes long ; the default value is "memc.sess.key." -memcached.sess_prefix = "memc.sess.key." +;memcached.sess_prefix = "memc.sess.key." ; Whether or not to re-use the memcached connections corresponding to the value(s) ; of session.save_path after the execution of the script ends. ; Don't use this if certain settings (e.g. SASL settings, sess_binary_protocol) would ; be overridden between requests. ; Default is Off. -memcached.sess_persistent = Off +;memcached.sess_persistent = Off ; memcached session consistent hash mode ; if set to On, consistent hashing (libketama) is used @@ -48,11 +42,15 @@ memcached.sess_persistent = Off ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys ; default is On -memcached.sess_consistent_hash = On +;memcached.sess_consistent_hash = On ; Allow failed memcached server to automatically be removed. ; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) -memcached.sess_remove_failed_servers = Off +;memcached.sess_remove_failed_servers = Off + +; Set this value to enable the server be removed after +; configured number of continuous times connection failure. +;memcached.sess_server_failure_limit = 0 ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. @@ -61,34 +59,34 @@ memcached.sess_remove_failed_servers = Off ; from a replica. However, if the failed memcache server ; becomes available again it will read the session from there ; which could have old data or no data at all -memcached.sess_number_of_replicas = 0 +;memcached.sess_number_of_replicas = 0 ; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) ; libmemcached replicas work only if binary mode is enabled. ; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. ; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. -memcached.sess_binary_protocol = On +;memcached.sess_binary_protocol = On ; memcached session replica read randomize -memcached.sess_randomize_replica_read = Off +;memcached.sess_randomize_replica_read = Off ; memcached connect timeout value ; In non-blocking mode this changes the value of the timeout ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. -memcached.sess_connect_timeout = 1000 +;memcached.sess_connect_timeout = 1000 ; Session SASL username ; Both username and password need to be set for SASL to be enabled ; In addition to this memcached.use_sasl needs to be on -memcached.sess_sasl_username = NULL +;memcached.sess_sasl_username = NULL ; Session SASL password -memcached.sess_sasl_password = NULL +;memcached.sess_sasl_password = NULL ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz -memcached.compression_type = "fastlz" +;memcached.compression_type = "fastlz" ; Compression factor ; Store compressed value only if the compression @@ -98,13 +96,13 @@ memcached.compression_type = "fastlz" ; plain_len > comp_len * factor ; ; the default value is 1.3 (23% space saving) -memcached.compression_factor = "1.3" +;memcached.compression_factor = "1.3" ; The compression threshold ; ; Do not compress serialized values below this threshold. ; the default is 2000 bytes -memcached.compression_threshold = 2000 +;memcached.compression_threshold = 2000 ; Set the default serializer for new memcached objects. ; valid values are: php, igbinary, json, json_array, msgpack @@ -119,14 +117,14 @@ memcached.compression_threshold = 2000 ; msgpack - a cross-language binary serializer ; ; The default is igbinary if available, then msgpack if available, then php otherwise. -memcached.serializer = "igbinary" +;memcached.serializer = "igbinary" ; The amount of retries for failed store commands. ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server ; environment. ; the default is 2 -memcached.store_retry_count = 2 +;memcached.store_retry_count = 2 ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, @@ -137,7 +135,7 @@ memcached.store_retry_count = 2 ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys ; default is Off -memcached.default_consistent_hash = Off +;memcached.default_consistent_hash = Off ; Sets the default memcached protocol for new connections. ; (To configure the memcached protocol for connections used by sessions, @@ -146,7 +144,7 @@ memcached.default_consistent_hash = Off ; If set to On, the memcached binary protocol is used by default. ; If set to Off, the memcached text protocol is used. ; Default is Off -memcached.default_binary_protocol = Off +;memcached.default_binary_protocol = Off ; Sets the default memcached connection timeout for new connections. ; (To configure the memcached connection timeout for sessions, @@ -155,4 +153,4 @@ memcached.default_binary_protocol = Off ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. ; Specifying 0 means using the memcached library's default connection timeout. ; Default is 0. -memcached.default_connect_timeout = 0 +;memcached.default_connect_timeout = 0 From 0a90491dd13af8dfc9a2e1ee600590fe9245ac50 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 20 Feb 2017 19:32:37 +0100 Subject: [PATCH 515/694] set sess_binary_protocol off by default with older libmemcached --- memcached.ini | 4 +++- php_memcached.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index fa9a6fd4..6d05da3c 100644 --- a/memcached.ini +++ b/memcached.ini @@ -64,7 +64,9 @@ ; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) ; libmemcached replicas work only if binary mode is enabled. ; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. -; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +; In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +; Default is On with libmemcached 1.0.18 or newer. +; Default is Off with older version. ;memcached.sess_binary_protocol = On ; memcached session replica read randomize diff --git a/php_memcached.c b/php_memcached.c index 19673323..b920970b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -332,7 +332,11 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + MEMC_SESSION_INI_ENTRY("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) +#else MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) +#endif MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) From 3b3e63dac7df9e6085442d7cd4f1e898e1af9114 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 21 Feb 2017 23:47:15 +0100 Subject: [PATCH 516/694] typo in skip message (#331) --- tests/session_lazy_warning.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/session_lazy_warning.phpt b/tests/session_lazy_warning.phpt index 79d7f2f3..6847f5b5 100644 --- a/tests/session_lazy_warning.phpt +++ b/tests/session_lazy_warning.phpt @@ -4,7 +4,7 @@ Session lazy binary warning old libmemcached = 0x01000018) die ('skip too old libmemcached'); +if (Memcached::LIBMEMCACHED_VERSION_HEX >= 0x01000018) die ('skip too recent libmemcached'); ?> --INI-- session.save_handler = memcached From 037ed570bae27a7a3d47fda9f38f6d0355554e9b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 22 Feb 2017 01:22:11 +0100 Subject: [PATCH 517/694] Fix build warnings (#329) --- php_memcached.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 19673323..55d1bdb8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -194,7 +194,8 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ return; \ } \ - memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ + (void)memc_user_data; /* avoid unused variable warning */ static zend_bool s_memc_valid_key_binary(const char *key) @@ -898,7 +899,7 @@ zend_bool s_serialize_value (php_memc_serializer_type serializer, zval *value, s php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } - smart_str_appendl (buf, buffer, buffer_len); + smart_str_appendl (buf, (char *)buffer, buffer_len); efree(buffer); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); } @@ -1058,7 +1059,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze { uint32_t flags = 0; zend_string *payload = NULL; - memcached_return status; + memcached_return status = 0; php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); zend_long retries = memc_user_data->store_retry_count; @@ -3911,10 +3912,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) ZEND_ARG_INFO(0, option) ZEND_END_ARG_INFO() +#ifdef HAVE_MEMCACHED_SASL ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_END_ARG_INFO() +#endif ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) ZEND_ARG_INFO(0, option) From 6b660bd554368bae69c2fbf490c6e78712e50708 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Sun, 23 Apr 2017 15:12:36 +0900 Subject: [PATCH 518/694] Fix optional parameter getStats($type) (#337) * Fix 'type' is optional * Change argument name args -> type --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 55d1bdb8..3f3ac286 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3876,6 +3876,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2) ZEND_ARG_INFO(0, weight) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_getStats, 0, 0, 0) + ZEND_ARG_INFO(0, type) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_addServers, 0) ZEND_ARG_ARRAY_INFO(0, servers, 0) ZEND_END_ARG_INFO() @@ -3934,10 +3938,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) ZEND_ARG_INFO(0, replicas) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0) - ZEND_ARG_INFO(0, args) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) ZEND_END_ARG_INFO() From c23ea262f3b481951b0131db358770b352953e14 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 30 Apr 2017 08:15:36 -0700 Subject: [PATCH 519/694] Document GET_EXTENDED flag. Add/rename other missing/misnamed constants. (#335) --- memcached-api.php | 108 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 19 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index df725091..f5174e22 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -10,13 +10,13 @@ class Memcached { */ const OPT_HASH; - - const OPT_HASH_DEFAULT; + + const HASH_DEFAULT; const HASH_MD5; const HASH_CRC; - + const HASH_FNV1_64; const HASH_FNV1A_64; @@ -34,12 +34,16 @@ class Memcached { const DISTRIBUTION_MODULA; const DISTRIBUTION_CONSISTENT; - + const DISTRIBUTION_VIRTUAL_BUCKET; - const LIBKETAMA_COMPATIBLE; + const OPT_LIBKETAMA_COMPATIBLE; - const OPT_BUFFER_REQUESTS; + const OPT_LIBKETAMA_HASH; + + const OPT_TCP_KEEPALIVE; + + const OPT_BUFFER_WRITES; const OPT_BINARY_PROTOCOL; @@ -57,9 +61,9 @@ class Memcached { const OPT_DEAD_TIMEOUT; - const OPT_SND_TIMEOUT; + const OPT_SEND_TIMEOUT; - const OPT_RCV_TIMEOUT; + const OPT_RECV_TIMEOUT; const OPT_POLL_TIMEOUT; @@ -71,22 +75,34 @@ class Memcached { const OPT_AUTO_EJECT_HOSTS; - const OPT_NUMBER_OF_REPLICAS; - const OPT_NOREPLY; const OPT_VERIFY_KEY; - + + const OPT_USE_UDP; + + const OPT_NUMBER_OF_REPLICAS; + const OPT_RANDOMIZE_REPLICA_READS; + const OPT_REMOVE_FAILED_SERVERS; /** - * Class parameters + * Supported serializers */ const HAVE_JSON; const HAVE_IGBINARY; + const HAVE_MSGPACK; + + /** + * Feature support + */ + const HAVE_SESSION; + + const HAVE_SASL; + /** * Class options. */ @@ -107,18 +123,24 @@ class Memcached { const SERIALIZER_JSON_ARRAY; + const SERIALIZER_MSGPACK; + /** * Compression types */ - const COMPRESSION_TYPE_FASTLZ; + const COMPRESSION_FASTLZ; - const COMPRESSION_TYPE_ZLIB; + const COMPRESSION_ZLIB; /** - * Flags + * Flags for get and getMulti operations. */ + // Whether to preserve key order in the result const GET_PRESERVE_ORDER; + // Whether to fetch CAS token as well (use "gets"). + const GET_EXTENDED; + /** * Return values */ @@ -186,9 +208,57 @@ class Memcached { const RES_CONNECTION_SOCKET_CREATE_FAILURE; + const RES_E2BIG; + + const RES_KEY_TOO_BIG; + + const RES_SERVER_TEMPORARILY_DISABLED; + + const RES_SERVER_MEMORY_ALLOCATION_FAILURE; + + const RES_AUTH_PROBLEM; + + const RES_AUTH_FAILURE; + + const RES_AUTH_CONTINUE; + + /** Server callbacks, if compiled with --memcached-protocol */ + const ON_CONNECT; + const ON_ADD; + const ON_APPEND; + const ON_DECREMENT; + const ON_DELETE; + const ON_FLUSH; + const ON_GET; + const ON_INCREMENT; + const ON_NOOP; + const ON_PREPEND; + const ON_QUIT; + const ON_REPLACE; + const ON_SET; + const ON_STAT; + const ON_VERSION; + /** Constants used when compiled with --memcached-protocol */ + const RESPONSE_SUCCESS; + const RESPONSE_KEY_ENOENT; + const RESPONSE_KEY_EEXISTS; + const RESPONSE_E2BIG; + const RESPONSE_EINVAL; + const RESPONSE_NOT_STORED; + const RESPONSE_DELTA_BADVAL; + const RESPONSE_NOT_MY_VBUCKET; + const RESPONSE_AUTH_ERROR; + const RESPONSE_AUTH_CONTINUE; + const RESPONSE_UNKNOWN_COMMAND; + const RESPONSE_ENOMEM; + const RESPONSE_NOT_SUPPORTED; + const RESPONSE_EINTERNAL; + const RESPONSE_EBUSY; + const RESPONSE_ETMPFAIL; + public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - + public function get( $key, callable $cache_cb = null, $flags = 0) {} public function getByKey( $server_key, $key, callable $cache_cb = null, $flags = 0 ) {} @@ -202,7 +272,7 @@ public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} public function getDelayedByKey( $server_key, array $keys, $with_cas = null, $value_cb = null ) {} public function fetch( ) {} - + public function fetchAll( ) {} public function set( $key, $value, $expiration = 0, $udf_flags = 0 ) {} @@ -250,7 +320,7 @@ public function increment( $key, $offset = 1, $initial_value = 0, $expiry = 0) { public function decrement( $key, $offset = 1, $initial_value = 0, $expiry = 0) {} public function getOption( $option ) {} - + public function setOption( $option, $value ) {} public function setOptions( array $options ) {} @@ -280,7 +350,7 @@ public function flushBuffers( ) {} public function getStats( $type = null ) {} public function getAllKeys( ) {} - + public function getVersion( ) {} public function getResultCode( ) {} From 14581c4604b4e4a525e1a30a52a8ac39ac1ac7e4 Mon Sep 17 00:00:00 2001 From: Eric Norris Date: Tue, 2 May 2017 16:24:34 -0400 Subject: [PATCH 520/694] s/encryption/compression/g (#342) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 3f3ac286..7cda4ac3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3383,7 +3383,7 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); if (!is_fastlz && !is_zlib) { - php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised encryption type"); + php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type"); return NULL; } From 5f28025c15c87d0895f39def77068c8fd66d442a Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 23 May 2017 11:43:19 +0800 Subject: [PATCH 521/694] This will lead unexpected behavior if zval is an interned string --- php_memcached.c | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 7cda4ac3..9eacbbfb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1019,7 +1019,6 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t } break; } - zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ if (ZSTR_LEN(payload) == 0 || ZSTR_LEN(payload) < MEMC_G(compression_threshold)) { From 23cf6c60f398cecb896e4fead37c18c9b56717fa Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 9 Jun 2017 11:08:33 -0700 Subject: [PATCH 522/694] Fix ReflectionMethod signatures for appendByKey,prepend, etc. (#352) --- php_memcached.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9eacbbfb..7e020eaa 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3775,27 +3775,23 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) From 43bbf0080206b157b0d3f47ab1f07ede4bc80c86 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 7 Jul 2017 18:45:42 -0700 Subject: [PATCH 523/694] In PHP 7.2, php_errormsg is deprecated --- tests/append.phpt | 2 +- tests/bad_construct.phpt | 2 +- tests/experimental/fetch_badunserialize.phpt | 2 +- tests/experimental/fetchall_badunserialize.phpt | 2 +- tests/experimental/getdelayed_badunserialize.phpt | 2 +- tests/experimental/getdelayed_cbthrows.phpt | 2 +- tests/experimental/getmulti_badunserialize.phpt | 2 +- tests/experimental/replace_bykey.phpt | 2 +- .../serializer/serializer_php_bad_serialize.phpt | 2 +- .../serializer/serializer_php_bad_unserialize.phpt | 2 +- tests/experimental/setmulti_badserialize.phpt | 2 +- tests/incrdecr.phpt | 8 ++++---- tests/incrdecr_bykey.phpt | 8 ++++---- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/append.phpt b/tests/append.phpt index c463fde8..b958b391 100644 --- a/tests/append.phpt +++ b/tests/append.phpt @@ -11,7 +11,7 @@ error_reporting(0); $m->delete('foo'); $m->setOption(Memcached::OPT_COMPRESSION, true); var_dump($m->append('foo', 'a')); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; $m->setOption(Memcached::OPT_COMPRESSION, false); $m->delete('foo'); diff --git a/tests/bad_construct.phpt b/tests/bad_construct.phpt index aa9b18c4..0b740e00 100644 --- a/tests/bad_construct.phpt +++ b/tests/bad_construct.phpt @@ -6,7 +6,7 @@ Memcached construct with bad arguments getDelayed(array('foo'), false)); try { var_dump($m->fetch()); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/experimental/fetchall_badunserialize.phpt index e3ad3310..5684763f 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/experimental/fetchall_badunserialize.phpt @@ -42,7 +42,7 @@ var_dump($m->getDelayed(array('foo'), false)); try { var_dump($m->fetchAll()); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getdelayed_badunserialize.phpt b/tests/experimental/getdelayed_badunserialize.phpt index 571e76e0..397135ae 100644 --- a/tests/experimental/getdelayed_badunserialize.phpt +++ b/tests/experimental/getdelayed_badunserialize.phpt @@ -45,7 +45,7 @@ error_reporting(0); try { var_dump($m->getDelayed(array('foo'), false, 'mycb')); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getdelayed_cbthrows.phpt b/tests/experimental/getdelayed_cbthrows.phpt index 2b71b4b4..b0427ac9 100644 --- a/tests/experimental/getdelayed_cbthrows.phpt +++ b/tests/experimental/getdelayed_cbthrows.phpt @@ -24,7 +24,7 @@ error_reporting(0); try { $m->getDelayedByKey('kef', array_keys($data), false, 'myfunc'); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getmulti_badunserialize.phpt b/tests/experimental/getmulti_badunserialize.phpt index b33d5ccd..963e9730 100644 --- a/tests/experimental/getmulti_badunserialize.phpt +++ b/tests/experimental/getmulti_badunserialize.phpt @@ -32,7 +32,7 @@ error_reporting(0); try { var_dump($m->getMulti(array('bar', 'foo'))); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/replace_bykey.phpt b/tests/experimental/replace_bykey.phpt index b2f72836..cddf10f0 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/experimental/replace_bykey.phpt @@ -10,7 +10,7 @@ error_reporting(0); $m->delete('foo'); var_dump($m->replaceByKey('kef', 'foo', 'bar', 60)); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; echo $m->getResultMessage(), "\n"; var_dump($m->getByKey('kef', 'foo')); diff --git a/tests/experimental/serializer/serializer_php_bad_serialize.phpt b/tests/experimental/serializer/serializer_php_bad_serialize.phpt index 81e88b0c..76d3daca 100644 --- a/tests/experimental/serializer/serializer_php_bad_serialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_serialize.phpt @@ -44,7 +44,7 @@ error_reporting(0); try { var_dump($m->set('foo', new Foo(), 10)); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } try { diff --git a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt index 39d2cc37..341ddedc 100644 --- a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt @@ -40,7 +40,7 @@ var_dump($m->set('foo', new Foo(), 10)); try { var_dump($m->get('foo')); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index 3bba314a..eafc7772 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -36,7 +36,7 @@ try { } } - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } var_dump($m->getByKey('kef', 'foo')); diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index b4e9469b..87b410c9 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -31,14 +31,14 @@ var_dump($m->get('foo')); error_reporting(0); echo "Negative offset\n"; -$php_errormsg = ''; +error_clear_last(); $m->increment('foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); -$php_errormsg = ''; +error_clear_last(); $m->decrement('foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 8b931fa7..ee089938 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -28,14 +28,14 @@ var_dump($m->get('foo')); error_reporting(0); echo "Negative offset\n"; -$php_errormsg = ''; +error_clear_last(); $m->incrementByKey('foo', 'foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); -$php_errormsg = ''; +error_clear_last(); $m->decrementByKey('foo', 'foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; From e91eae7be3d6076f5a66f4ef3b588d61df8ec1a2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 10 Jul 2017 14:46:20 -0700 Subject: [PATCH 524/694] Split tests for invalid keys ascii and binary Test get command for invalid keys as well as set command --- package.xml | 3 +- tests/keys.phpt | 118 ------------------------- tests/keys_ascii.phpt | 190 +++++++++++++++++++++++++++++++++++++++++ tests/keys_binary.phpt | 190 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+), 119 deletions(-) delete mode 100644 tests/keys.phpt create mode 100644 tests/keys_ascii.phpt create mode 100644 tests/keys_binary.phpt diff --git a/package.xml b/package.xml index 2306344d..2cc8995b 100644 --- a/package.xml +++ b/package.xml @@ -147,7 +147,8 @@ Fixes - + + diff --git a/tests/keys.phpt b/tests/keys.phpt deleted file mode 100644 index f320e03f..00000000 --- a/tests/keys.phpt +++ /dev/null @@ -1,118 +0,0 @@ ---TEST-- -Test different kind of keys ---SKIPIF-- - ---FILE-- - true, - )); - -$ascii = memc_get_instance (); -$ascii->setOption(Memcached::OPT_VERIFY_KEY, 1); - -var_dump ($binary->set ('binary key with spaces', 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); - -var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($binary->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($ascii->set (''/*empty key*/, 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -for ($i=0;$i<32;$i++) { - var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); - var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -} - -var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -echo "OK" . PHP_EOL; - ---EXPECT-- -bool(true) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -OK diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt new file mode 100644 index 00000000..f7e98894 --- /dev/null +++ b/tests/keys_ascii.phpt @@ -0,0 +1,190 @@ +--TEST-- +Test valid and invalid keys - ascii +--SKIPIF-- + +--FILE-- + false, + Memcached::OPT_VERIFY_KEY => false + )); +// libmemcached can verify keys, but these are tests are for our own +// function s_memc_valid_key_ascii, so explicitly disable the checks +// that libmemcached can perform. + +echo 'ASCII: SPACES' . PHP_EOL; +var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: NEWLINE' . PHP_EOL; +var_dump ($ascii->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: EMPTY' . PHP_EOL; +var_dump ($ascii->set (''/*empty key*/, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: TOO LONG' . PHP_EOL; +var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: GET' . PHP_EOL; +for ($i=0;$i<32;$i++) { + var_dump ($ascii->get ('asciikeywithnonprintablechar-' . chr($i) . '-here')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'ASCII: SET' . PHP_EOL; +for ($i=0;$i<32;$i++) { + var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'OK' . PHP_EOL; + +--EXPECT-- +ASCII: SPACES +bool(false) +bool(true) +ASCII: NEWLINE +bool(false) +bool(true) +ASCII: EMPTY +bool(false) +bool(true) +ASCII: TOO LONG +bool(false) +bool(true) +ASCII: GET +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +ASCII: SET +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +OK diff --git a/tests/keys_binary.phpt b/tests/keys_binary.phpt new file mode 100644 index 00000000..f0ae67bd --- /dev/null +++ b/tests/keys_binary.phpt @@ -0,0 +1,190 @@ +--TEST-- +Test valid and invalid keys - binary +--SKIPIF-- + +--FILE-- + true, + )); + +echo 'BINARY: SPACES' . PHP_EOL; +var_dump ($binary->set ('binary key with spaces', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); + +echo 'BINARY: NEWLINE' . PHP_EOL; +var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: EMPTY' . PHP_EOL; +var_dump ($binary->set (''/*empty key*/, 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: TOO LONG' . PHP_EOL; +var_dump ($binary->set (str_repeat ('1234567890', 512), 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: GET' . PHP_EOL; +// Only newline fails in binary mode (char 10) +for ($i=0;$i<32;$i++) { + $binary->delete ('binarykeywithnonprintablechar-' . chr($i) . '-here'); + var_dump ($binary->get ('binarykeywithnonprintablechar-' . chr($i) . '-here')); + var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'BINARY: SET' . PHP_EOL; +// Only newline fails in binary mode (char 10) +for ($i=0;$i<32;$i++) { + var_dump ($binary->set ('binarykeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + $binary->delete ('binarykeywithnonprintablechar-' . chr($i) . '-here'); +} + +echo 'OK' . PHP_EOL; + +--EXPECT-- +BINARY: SPACES +bool(true) +bool(true) +BINARY: NEWLINE +bool(false) +bool(true) +BINARY: EMPTY +bool(false) +bool(true) +BINARY: TOO LONG +bool(false) +bool(true) +BINARY: GET +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +BINARY: SET +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +OK From be93a459eedc54fbbf2dfa63babea38b730fc313 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 10 Jul 2017 11:04:59 -0700 Subject: [PATCH 525/694] Fix the key validity tests to handle strings with embedded nulls --- php_memcached.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 4449200b..65d11eb2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -198,24 +198,30 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { (void)memc_user_data; /* avoid unused variable warning */ static -zend_bool s_memc_valid_key_binary(const char *key) +zend_bool s_memc_valid_key_binary(zend_string *key) { - return strchr(key, '\n') == NULL; + return memchr(ZSTR_VAL(key), '\n', ZSTR_LEN(key)) == NULL; } static -zend_bool s_memc_valid_key_ascii(const char *key) +zend_bool s_memc_valid_key_ascii(zend_string *key) { - while (*key && !iscntrl(*key) && !isspace(*key)) ++key; - return *key == '\0'; + const char *str = ZSTR_VAL(key); + size_t i, len = ZSTR_LEN(key); + + for (i = 0; i < len; i++) { + if (iscntrl(str[i]) || isspace(str[i])) + return 0; + } + return 1; } #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ - ? !s_memc_valid_key_binary(ZSTR_VAL(key)) \ - : !s_memc_valid_key_ascii(ZSTR_VAL(key)) \ + ? !s_memc_valid_key_binary(key) \ + : !s_memc_valid_key_ascii(key) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ @@ -309,7 +315,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } - if (!s_memc_valid_key_ascii(ZSTR_VAL(new_value))) { + if (!s_memc_valid_key_ascii(new_value)) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); return FAILURE; } From 39bfab06c0c27dc620486f56a926308df5d4c819 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Jul 2017 15:57:51 -0700 Subject: [PATCH 526/694] In PHP 7.2 the session_start() error messages have changed a bit (#359) See PHP Bug 71038 for details https://bugs.php.net/bug.php?id=71038 Added PHP 7.2.0alpha2 to Travis CI matrix --- .travis.yml | 3 ++- package.xml | 1 + tests/session_badconf_servers-php72.phpt | 30 ++++++++++++++++++++++++ tests/session_badconf_servers.phpt | 7 +++--- 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 tests/session_badconf_servers-php72.phpt diff --git a/.travis.yml b/.travis.yml index 2581b516..d12cd3c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,9 @@ dist: trusty language: php php: - - 7.0 + - 7.2.0alpha2 - 7.1 + - 7.0 matrix: fast_finish: true diff --git a/package.xml b/package.xml index 2cc8995b..5e1961f7 100644 --- a/package.xml +++ b/package.xml @@ -113,6 +113,7 @@ Fixes + diff --git a/tests/session_badconf_servers-php72.phpt b/tests/session_badconf_servers-php72.phpt new file mode 100644 index 00000000..92012369 --- /dev/null +++ b/tests/session_badconf_servers-php72.phpt @@ -0,0 +1,30 @@ +--TEST-- +Session bad configurations, invalid save path (server list) +--SKIPIF-- + +--INI-- +session.save_handler = memcached +--FILE-- + 70100) print "skip"; ?> --INI-- session.save_handler = memcached @@ -24,5 +25,5 @@ ini_set('session.save_path', ''); session_start(); session_write_close(); ---EXPECTF-- +--EXPECT-- session_start(): failed to parse session.save_path From 56145402e9d4a624037cdbfb5d9bab3bc7874e21 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 27 Jul 2017 00:03:48 -0700 Subject: [PATCH 527/694] Travis CI now provides the PHP 7.2 alias --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d12cd3c9..d2457f55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ dist: trusty language: php php: - - 7.2.0alpha2 + - 7.2 - 7.1 - 7.0 From f82e6845af474ff98c5b6dae283f8beb3f4e6d4d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 23:15:34 -0600 Subject: [PATCH 528/694] Use new fast_zpp parameter parsing API (#311) The one that took a while to figure out was zpp("f!") to Z_PARAM_FUNC_EX(fci, fcc, 1, 0) --- php_memcached.c | 368 +++++++++++++++++++++++++++++++----------------- 1 file changed, 242 insertions(+), 126 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 65d11eb2..891b2a3e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1184,9 +1184,13 @@ static PHP_METHOD(Memcached, __construct) zend_bool is_persistent = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - return; - } + /* "|S!f!S" */ + ZEND_PARSE_PARAMETERS_START(0, 3) + Z_PARAM_OPTIONAL + Z_PARAM_STR_EX(persistent_id, 1, 0) + Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0) + Z_PARAM_STR(conn_str) + ZEND_PARSE_PARAMETERS_END(); intern = Z_MEMC_OBJ_P(getThis()); intern->is_pristine = 1; @@ -1413,13 +1417,22 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } + /* "SS|f!l" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + Z_PARAM_LONG(get_flags) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } + /* "S|f!l" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + Z_PARAM_LONG(get_flags) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1505,14 +1518,20 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_bool retval, preserve_order; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, - &keys, &flags) == FAILURE) { - return; - } + /* "Sa|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY(keys) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(flags) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &keys, &flags) == FAILURE) { - return; - } + /* "a|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ARRAY(keys) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(flags) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1642,15 +1661,22 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, - &keys, &with_cas, &fci, &fcc) == FAILURE) { - return; - } + /* "Sa/|bf!" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY_EX(keys, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(with_cas) + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, - &fci, &fcc) == FAILURE) { - return; - } + /* "a/|bf!" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ARRAY_EX(keys, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(with_cas) + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1796,7 +1822,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *entries; zend_string *server_key = NULL; - time_t expiration = 0; + zend_long expiration = 0, ignored; zval *value; zend_string *skey; zend_ulong num_key; @@ -1804,14 +1830,22 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration) == FAILURE) { - return; - } + /* "Sa|ll" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY(entries) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { - return; - } + /* "a|ll" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ARRAY(entries) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1921,35 +1955,56 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { - return; - } + /* "SSS" */ + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_STR(s_value) + ZEND_PARSE_PARAMETERS_END(); value = &s_zvalue; ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } + /* "SS|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { - return; - } + /* "SSz|l" */ + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } } else { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { - return; - } + /* "SS" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(key) + Z_PARAM_STR(s_value) + ZEND_PARSE_PARAMETERS_END(); value = &s_zvalue; ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } + /* "S|l */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { - return; - } + /* "Sz|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } } @@ -1984,22 +2039,34 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *key; zend_string *server_key = NULL; zval *value; - time_t expiration = 0; + zend_long expiration = 0; + zend_long ignored; zend_string *payload; uint32_t flags = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, - &value, &expiration) == FAILURE) { - return; - } + /* "zSSz|ll" */ + ZEND_PARSE_PARAMETERS_START(4, 6) + Z_PARAM_ZVAL(zv_cas) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, - &expiration) == FAILURE) { - return; - } + /* "zSz|ll" */ + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_ZVAL(zv_cas) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2081,18 +2148,25 @@ PHP_METHOD(Memcached, deleteMultiByKey) static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zend_string *key, *server_key; - time_t expiration = 0; + zend_long expiration = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } + /* "SS|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } + /* "S|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); server_key = key; } @@ -2120,20 +2194,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by { zval *entries, *zv, ret; zend_string *server_key = NULL; - time_t expiration = 0; + zend_long expiration = 0; zend_string *entry; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { - return; - } + /* "Sa/|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY_EX(entries, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { - return; - } + /* "a/|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ARRAY_EX(entries, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2172,21 +2253,33 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, { zend_string *key, *server_key = NULL; zend_long offset = 1; - uint64_t value = UINT64_MAX, initial = 0; - time_t expiry = 0; + zend_long expiry = 0; + zend_long initial = 0; + uint64_t value = UINT64_MAX; memcached_return status; int n_args = ZEND_NUM_ARGS(); MEMC_METHOD_INIT_VARS; if (!by_key) { - if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { - return; - } + /* "S|lll" */ + ZEND_PARSE_PARAMETERS_START(1, 4) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + Z_PARAM_LONG(initial) + Z_PARAM_LONG(expiry) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { - return; - } + /* "SS|lll" */ + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + Z_PARAM_LONG(initial) + Z_PARAM_LONG(expiry) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2228,15 +2321,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { @@ -2293,13 +2386,17 @@ PHP_METHOD(Memcached, incrementByKey) PHP_METHOD(Memcached, addServer) { zend_string *host; - long port, weight = 0; + zend_long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { - return; - } + /* "Sa/|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(host) + Z_PARAM_LONG(port) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(weight) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2327,9 +2424,10 @@ PHP_METHOD(Memcached, addServers) memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { - return; - } + /* "a/" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_EX(servers, 0, 1) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2431,9 +2529,10 @@ PHP_METHOD(Memcached, getServerByKey) memcached_return error; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { - return; - } + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(server_key) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2651,9 +2750,11 @@ PHP_METHOD(Memcached, getStats) zend_string *args_string = NULL; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &args_string) == FAILURE) { - return; - } + /* "|S!" */ + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STR_EX(args_string, 1, 0) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -2745,13 +2846,15 @@ PHP_METHOD(Memcached, getAllKeys) Flushes the data on all the servers */ static PHP_METHOD(Memcached, flush) { - time_t delay = 0; + zend_long delay = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { - return; - } + /* "|l" */ + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(delay) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2769,14 +2872,15 @@ static PHP_METHOD(Memcached, flush) Returns the value for the given option constant */ static PHP_METHOD(Memcached, getOption) { - long option; + zend_long option; uint64_t result; memcached_behavior flag; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &option) == FAILURE) { - return; - } + /* "l" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(option) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3018,7 +3122,7 @@ PHP_METHOD(Memcached, setBucket) { zval *zserver_map; zval *zforward_map = NULL; - long replicas = 0; + zend_long replicas = 0; zend_bool retval = 1; uint32_t *server_map = NULL, *forward_map = NULL; @@ -3026,9 +3130,12 @@ PHP_METHOD(Memcached, setBucket) memcached_return rc; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { - return; - } + /* "aa!l" */ + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_ARRAY(zserver_map) + Z_PARAM_ARRAY_EX(zforward_map, 1, 0) + Z_PARAM_LONG(replicas) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3089,9 +3196,11 @@ static PHP_METHOD(Memcached, setOptions) MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) { - return; - } + /* "a" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(options) + ZEND_PARSE_PARAMETERS_END(); + MEMC_METHOD_FETCH_OBJECT; @@ -3114,13 +3223,15 @@ static PHP_METHOD(Memcached, setOptions) Sets the value for the given option constant */ static PHP_METHOD(Memcached, setOption) { - long option; + zend_long option; zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { - return; - } + /* "lz/" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(option) + Z_PARAM_ZVAL_EX(value, 0, 1) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3137,9 +3248,11 @@ static PHP_METHOD(Memcached, setSaslAuthData) memcached_return status; zend_string *user, *pass; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { - return; - } + /* "SS/" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(user) + Z_PARAM_STR(pass) + ZEND_PARSE_PARAMETERS_END(); if (!php_memc_init_sasl_if_needed()) { RETURN_FALSE; @@ -3621,9 +3734,10 @@ PHP_METHOD(MemcachedServer, run) php_memc_server_t *intern; intern = Z_MEMC_SERVER_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { - return; - } + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(address) + ZEND_PARSE_PARAMETERS_END(); rc = php_memc_proto_handler_run(intern->handler, address); @@ -3642,9 +3756,11 @@ PHP_METHOD(MemcachedServer, on) zend_fcall_info_cache fci_cache; zend_bool rc = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lf!", &event, &fci, &fci_cache) == FAILURE) { - return; - } + /* "lf!" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(event) + Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0) + ZEND_PARSE_PARAMETERS_END(); if (event <= MEMC_SERVER_ON_MIN || event >= MEMC_SERVER_ON_MAX) { RETURN_FALSE; From 3f1362ae8b5d4f4ed9ad01bc826c906608137746 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Tue, 21 Nov 2017 06:18:26 +0100 Subject: [PATCH 529/694] Remove unused defines MEMC_SESS_DEFAULT_LOCK_WAIT and MEMC_SESS_LOCK_EXPIRATION (#354) --- php_memcached_session.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index afa973bb..ab3e7222 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -22,9 +22,6 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) -#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 -#define MEMC_SESS_LOCK_EXPIRATION 30 - #define REALTIME_MAXDELTA 60*60*24*30 ps_module ps_mod_memcached = { From 5edd5bac25016646a4e6f4ad758847ceaaa1d874 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 23:48:40 -0600 Subject: [PATCH 530/694] Restore default value memcached.sess_prefix = "memc.sess.key." Resolves #340 --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 891b2a3e..952b582c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -352,7 +352,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) - MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateSessionPrefixString, prefix) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.key.", OnUpdateSessionPrefixString, prefix) MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) /* Deprecated */ From f30e7428e5f55f0dc8eec0dc6d30cc3f0f05d73e Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Tue, 5 Dec 2017 18:13:23 +0100 Subject: [PATCH 531/694] Fix typo bibrary to library (#372) --- config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.m4 b/config.m4 index b34c30bf..705f4957 100644 --- a/config.m4 +++ b/config.m4 @@ -26,8 +26,8 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocol support], no, no) -PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, -[ --with-system-fastlz Use system FastLZ bibrary], no, no) +PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, +[ --with-system-fastlz Use system FastLZ library], no, no) if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, From 809e4b078a6a4d8fc683b1160f1ae6e6b43bd925 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 22:43:00 -0600 Subject: [PATCH 532/694] Release notes for 3.0.4 --- ChangeLog | 11 +++++++++++ package.xml | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1db3dd44..5e406ee2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ memcached extension changelog +Version 3.0.4 (2017-11-20) +-------------------------- + + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + Version 3.0.3 (2017-02-19) -------------------------- diff --git a/package.xml b/package.xml index 5e1961f7..bbdaae81 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-19 + 2017-11-20 - 3.0.3 + 3.0.4 3.0.0 @@ -38,13 +38,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.2. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix crash when checking session data with older versions of libmemcached (#328) - * Fix crash due to zend_mm_corrupted when fetching session data (#327) + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) @@ -191,6 +197,26 @@ Fixes + + + stable + stable + + + 3.0.3 + 3.0.0 + + 2017-02-19 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) + + stable From 04e404631f4a94d825287cb92d55290395d77b73 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 10 Dec 2017 01:21:51 -0800 Subject: [PATCH 533/694] Bump version to 3.1.0-dev --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 65a0349f..5194c038 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.3" +#define PHP_MEMCACHED_VERSION "3.1.0-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 6767a79dc3f74e4a8bb214beaeccf0b2d769746b Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 19 Dec 2017 04:06:52 -0800 Subject: [PATCH 534/694] Supports PHP 7.0 - 7.2 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index f145c2df..19a8ab18 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.1. +* Supports PHP 7.0 - 7.2. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From c65cc1c2661e4bc529761bcc033247446b869f2c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 12:36:04 -0800 Subject: [PATCH 535/694] Fix session persistence by checking memcached behavior values before setting (#379) --- php_memcached_session.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index ab3e7222..d8e9be62 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -186,12 +186,15 @@ void s_unlock_session(memcached_st *memc) static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { - memcached_return rc; - #define check_set_behavior(behavior, value) \ - if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ - if (!silent) { php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); } \ - return 0; \ + if ((value) != memcached_behavior_get(memc, (behavior))) { \ + memcached_return rc; \ + if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + if (!silent) { \ + php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + } \ + return 0; \ + } \ } if (MEMC_SESS_INI(binary_protocol_enabled)) { @@ -243,7 +246,7 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) user_data->has_sasl_data = 1; } -#undef safe_set_behavior +#undef check_set_behavior return 1; } From 7ed5b38a3e0fb8ad490c095da9c659b50d7a0ebd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 19:21:41 -0800 Subject: [PATCH 536/694] Removed ifdef 0 code and trivial block cleanup --- php_memcached.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 952b582c..cc6456be 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -228,7 +228,6 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) } #ifdef HAVE_MEMCACHED_PROTOCOL - typedef struct { php_memc_proto_handler_t *handler; zend_object zo; @@ -1235,34 +1234,25 @@ static PHP_METHOD(Memcached, __construct) memcached_set_user_data(intern->memc, memc_user_data); /* Set default behaviors */ - { -#ifdef mikko_0 - fprintf (stderr, "consistent_hash_enabled=%d binary_protocol_enabled=%d connect_timeout=%ld\n", - MEMC_G(default_behavior.consistent_hash_enabled), MEMC_G(default_behavior.binary_protocol_enabled), MEMC_G(default_behavior.connect_timeout)); -#endif - - memcached_return rc; + if (MEMC_G(default_behavior.consistent_hash_enabled)) { - if (MEMC_G(default_behavior.consistent_hash_enabled)) { - - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); - } + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); } + } - if (MEMC_G(default_behavior.binary_protocol_enabled)) { - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); - } + if (MEMC_G(default_behavior.binary_protocol_enabled)) { + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); } + } - if (MEMC_G(default_behavior.connect_timeout)) { - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); - } + if (MEMC_G(default_behavior.connect_timeout)) { + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); } } From e622992e6f6d7c3098eb3c42c1b5f80d9cdf1c6a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 23:58:19 -0800 Subject: [PATCH 537/694] The configure script warns if libmemcached needs sasl.h if sasl.h cannot be found (#380) --- config.m4 | 65 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/config.m4 b/config.m4 index 705f4957..7a4a6c9f 100644 --- a/config.m4 +++ b/config.m4 @@ -184,7 +184,7 @@ if test "$PHP_MEMCACHED" != "no"; then else AC_MSG_RESULT([$msgpack_inc_path]) fi - fi + fi AC_MSG_CHECKING([for memcached session support]) if test "$PHP_MEMCACHED_SESSION" != "no"; then @@ -255,42 +255,45 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) - # - # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once - # + dnl # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $INCLUDES" + dnl # Always check if libmemcached was built with SASL support, + dnl # because it will require sasl.h even if not used here. + AC_CACHE_CHECK([for libmemcached sasl.h requirement], ac_cv_memc_sasl_support, [ + AC_TRY_COMPILE( + [ #include ], + [ + #if LIBMEMCACHED_WITH_SASL_SUPPORT + /* yes */ + #else + # error "no sasl support" + #endif + ], + [ ac_cv_memc_sasl_support="yes" ], + [ ac_cv_memc_sasl_support="no" ] + ) + ]) + + if test "$ac_cv_memc_sasl_support" = "yes"; then + AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) + fi + + dnl # If libmemcached requires sasl.h but we can't find sasl.h, that's a hard error + dnl # regardless of the option --enable-memcached-sasl or --disable-memcached-sasl AC_MSG_CHECKING([whether to enable sasl support]) + if test "$ac_cv_memc_sasl_support" = "yes" && test "$ac_cv_have_memc_sasl_h" = "no"; then + AC_MSG_ERROR([no, libmemcached built with sasl required, but sasl.h not found.]) + fi + if test "$PHP_MEMCACHED_SASL" != "no"; then AC_MSG_RESULT(yes) - AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) - - if test "$ac_cv_have_memc_sasl_h" = "yes"; then - - AC_CACHE_CHECK([whether libmemcached supports sasl], ac_cv_memc_sasl_support, [ - AC_TRY_COMPILE( - [ #include ], - [ - #if LIBMEMCACHED_WITH_SASL_SUPPORT - /* yes */ - #else - # error "no sasl support" - #endif - ], - [ ac_cv_memc_sasl_support="yes" ], - [ ac_cv_memc_sasl_support="no" ] - ) - ]) - - if test "$ac_cv_memc_sasl_support" = "yes"; then - PHP_CHECK_LIBRARY(sasl2, sasl_client_init, [PHP_ADD_LIBRARY(sasl2, 1, MEMCACHED_SHARED_LIBADD)]) - AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) - else - AC_MSG_ERROR([no, libmemcached sasl support is not enabled. Run configure with --disable-memcached-sasl to disable this check]) - fi + if test "$ac_cv_memc_sasl_support" = "yes" && test "$ac_cv_have_memc_sasl_h" = "yes"; then + PHP_CHECK_LIBRARY(sasl2, sasl_client_init, [PHP_ADD_LIBRARY(sasl2, 1, MEMCACHED_SHARED_LIBADD)]) + AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) else - AC_MSG_ERROR([no, sasl.h is not available. Run configure with --disable-memcached-sasl to disable this check]) + AC_MSG_ERROR([no, libmemcached built with sasl disabled. Run configure with --disable-memcached-sasl or update libmemcached with sasl support]) fi else AC_MSG_RESULT([no]) @@ -298,7 +301,7 @@ if test "$PHP_MEMCACHED" != "no"; then ORIG_CFLAGS="$CFLAGS" ORIG_LIBS="$LIBS" - + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" From 5c6de2b0e4096211d56f11131acb5d5bdc794190 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 20 Jan 2018 08:04:40 -0800 Subject: [PATCH 538/694] Add support for libmemcached encryption (#381) This feature is fully supported in libmemcached 1.0.18 and higher, but has a notable bug in the original implementation in libmemcached versions 1.0.6 - 1.0.17 that the encryption key, once set, cannot be changed otherwise all further get/set operations fail. --- config.m4 | 19 ++++++++++++ memcached-api.php | 4 +++ package.xml | 2 ++ php_memcached.c | 56 ++++++++++++++++++++++++++++++++++ tests/set_encoding_key.phpt | 59 ++++++++++++++++++++++++++++++++++++ tests/set_encoding_key2.phpt | 37 ++++++++++++++++++++++ 6 files changed, 177 insertions(+) create mode 100644 tests/set_encoding_key.phpt create mode 100644 tests/set_encoding_key2.phpt diff --git a/config.m4 b/config.m4 index 7a4a6c9f..d38d5dc4 100644 --- a/config.m4 +++ b/config.m4 @@ -317,10 +317,29 @@ if test "$PHP_MEMCACHED" != "no"; then CFLAGS="$ORIG_CFLAGS" LIBS="$ORIG_LIBS" + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" + LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" + if test "$ac_cv_have_memcached_exist" = "yes"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi + AC_CACHE_CHECK([whether memcached_set_encoding_key is defined], ac_cv_have_memcached_set_encoding_key, [ + AC_TRY_LINK( + [ #include ], + [ memcached_set_encoding_key (NULL, NULL, 0); ], + [ ac_cv_have_memcached_set_encoding_key="yes" ], + [ ac_cv_have_memcached_set_encoding_key="no" ] + ) + ]) + + CFLAGS="$ORIG_CFLAGS" + LIBS="$ORIG_LIBS" + + if test "$ac_cv_have_memcached_set_encoding_key" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_SET_ENCODING_KEY, [1], [Whether memcached_set_encoding_key is defined]) + fi + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then diff --git a/memcached-api.php b/memcached-api.php index f5174e22..8ab03d4c 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -96,6 +96,8 @@ class Memcached { const HAVE_MSGPACK; + const HAVE_ENCODING; + /** * Feature support */ @@ -363,6 +365,8 @@ public function isPristine( ) {} public function setSaslAuthData( $username, $password ) {} + public function setEncodingKey( $key ) {} + } class MemcachedException extends Exception { diff --git a/package.xml b/package.xml index bbdaae81..a8ece289 100644 --- a/package.xml +++ b/package.xml @@ -159,6 +159,8 @@ Fixes + + diff --git a/php_memcached.c b/php_memcached.c index cc6456be..ec76f9bb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -142,6 +142,7 @@ typedef struct { zend_bool is_persistent; zend_bool compression_enabled; + zend_bool encoding_enabled; zend_long serializer; zend_long compression_type; @@ -1227,6 +1228,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data->serializer = MEMC_G(serializer_type); memc_user_data->compression_type = MEMC_G(compression_type); memc_user_data->compression_enabled = 1; + memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); memc_user_data->set_udf_flags = -1; memc_user_data->is_persistent = is_persistent; @@ -3265,6 +3267,42 @@ static PHP_METHOD(Memcached, setSaslAuthData) /* }}} */ #endif /* HAVE_MEMCACHED_SASL */ +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY +/* {{{ Memcached::setEncodingKey(string key) + Sets AES encryption key (libmemcached 1.0.6 and higher) */ +static PHP_METHOD(Memcached, setEncodingKey) +{ + MEMC_METHOD_INIT_VARS; + memcached_return status; + zend_string *key; + + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(key) + ZEND_PARSE_PARAMETERS_END(); + + MEMC_METHOD_FETCH_OBJECT; + + // libmemcached < 1.0.18 cannot handle a change of encoding key. Warn about this and return false. +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memc_user_data->encoding_enabled) { + php_error_docref(NULL, E_WARNING, "libmemcached versions less than 1.0.18 cannot change encoding key"); + RETURN_FALSE; + } +#endif + + status = memcached_set_encoding_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key)); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + memc_user_data->encoding_enabled = 1; + RETURN_TRUE; +} +/* }}} */ +#endif /* HAVE_MEMCACHED_SET_ENCODING_KEY */ + /* {{{ Memcached::getResultCode() Returns the result code from the last operation */ static PHP_METHOD(Memcached, getResultCode) @@ -4034,6 +4072,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) ZEND_END_ARG_INFO() #endif +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY +ZEND_BEGIN_ARG_INFO(arginfo_setEncodingKey, 0) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) ZEND_ARG_INFO(0, option) ZEND_ARG_INFO(0, value) @@ -4133,6 +4177,9 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) +#endif +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY + MEMC_ME(setEncodingKey, arginfo_setEncodingKey) #endif MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) @@ -4282,6 +4329,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 0); #endif + /* + * Indicate whether set_encoding_key is available + */ +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ENCODING, 1); +#else + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ENCODING, 0); +#endif + #ifdef HAVE_MEMCACHED_SESSION REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 1); #else diff --git a/tests/set_encoding_key.phpt b/tests/set_encoding_key.phpt new file mode 100644 index 00000000..72d96daa --- /dev/null +++ b/tests/set_encoding_key.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test libmemcached encryption +--SKIPIF-- + +--FILE-- +setEncodingKey("Hello")); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# Change the encryption key. The old value will be inaccessible. +var_dump ($m->setEncodingKey("World")); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# Restore the original key to retrieve old values again. +var_dump ($m->setEncodingKey("Hello")); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# With a new encoding key we can still write new values, +# this works as expected with libmemcached 1.0.18 and higher. +var_dump ($m->setEncodingKey("World")); +var_dump ($m->get ($key)); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +?> +--EXPECT-- +bool(true) +bool(true) +string(18) "set using encoding" +OK +bool(true) +bool(false) +OK +bool(true) +string(18) "set using encoding" +OK +bool(true) +bool(false) +bool(true) +string(18) "set using encoding" +OK diff --git a/tests/set_encoding_key2.phpt b/tests/set_encoding_key2.phpt new file mode 100644 index 00000000..f8d21a16 --- /dev/null +++ b/tests/set_encoding_key2.phpt @@ -0,0 +1,37 @@ +--TEST-- +Test libmemcached encryption +--SKIPIF-- += 0x01000018) die ("skip test for libmemcached lower than 1.0.18"); +?> +--FILE-- +setEncodingKey("Hello")); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# libmemcached < 1.0.18 goes into a bad state when the encoding key is changed, +# so php-memcached warns and returns false when trying to change the key. +var_dump ($m->setEncodingKey("World")); + +echo "OK" . PHP_EOL; + +?> +--EXPECTF-- +bool(true) +bool(true) +string(18) "set using encoding" +OK + +Warning: Memcached::setEncodingKey(): libmemcached versions less than 1.0.18 cannot change encoding key in %s on line %d +bool(false) +OK From 2fc7d3659c127eaabc0458e46e7118bcd721f92c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 21 Jan 2018 21:46:56 -0800 Subject: [PATCH 539/694] Fix wrong INI parsing method for memcached.sess_randomize_replica_read --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index ec76f9bb..8a5afa57 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -346,7 +346,7 @@ PHP_INI_BEGIN() #endif MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) - MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) + MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) From deb451ae9e519b326becfe51f4097918684d9003 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 21 Jan 2018 21:47:48 -0800 Subject: [PATCH 540/694] Fix wrong undefs of local macros for registering constants --- php_memcached.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 8a5afa57..6a03b0c3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4514,12 +4514,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_ETMPFAIL, PROTOCOL_BINARY_RESPONSE_ETMPFAIL); #endif - #undef REGISTER_MEMC_CLASS_CONST_LONG - /* * Return value from simple get errors */ REGISTER_MEMC_CLASS_CONST_BOOL(GET_ERROR_RETURN_VALUE, 0); + + #undef REGISTER_MEMC_CLASS_CONST_LONG + #undef REGISTER_MEMC_CLASS_CONST_BOOL + #undef REGISTER_MEMC_CLASS_CONST_NULL + } /* }}} */ From f54ed299c0220a0a308b346e53944a35247e4efa Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 03:32:07 -0800 Subject: [PATCH 541/694] Use STD_PHP_INI_BOOLEAN to correctly display php.ini booleans --- php_memcached.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6a03b0c3..495cfd1e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -326,34 +326,40 @@ PHP_INI_MH(OnUpdateSessionPrefixString) #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_INI_BOOL(key, default_value, update_fn, gkey) \ + STD_PHP_INI_BOOLEAN("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) + #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_SESSION_INI_BOOL(key, default_value, update_fn, gkey) \ + STD_PHP_INI_BOOLEAN("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) + /* {{{ INI entries */ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION - MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_BOOL ("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 - MEMC_SESSION_INI_ENTRY("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_BOOL ("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) #else - MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_BOOL ("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) #endif - MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_BOOL ("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) - MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) - MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) + MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) + MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) + MEMC_SESSION_INI_BOOL ("persistent", "0", OnUpdateBool, persistent_enabled) MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.key.", OnUpdateSessionPrefixString, prefix) - MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) /* Deprecated */ STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) @@ -367,14 +373,16 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) - MEMC_INI_ENTRY("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) - MEMC_INI_ENTRY("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) + MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) + MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) PHP_INI_END() /* }}} */ +#undef MEMC_INI_BOOL #undef MEMC_INI_ENTRY +#undef MEMC_SESSION_INI_BOOL #undef MEMC_SESSION_INI_ENTRY /**************************************** From 2c693c7a9b8239ccc73d6c8ae8f95f21ae282b5e Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 03:52:34 -0800 Subject: [PATCH 542/694] Allow connect_timeout value of -1 and show Unlimited in phpinfo() --- php_memcached.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 495cfd1e..1d015ccc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -329,12 +329,18 @@ PHP_INI_MH(OnUpdateSessionPrefixString) #define MEMC_INI_BOOL(key, default_value, update_fn, gkey) \ STD_PHP_INI_BOOLEAN("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_INI_LINK(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY_EX("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals, display_link_numbers) + #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_BOOL(key, default_value, update_fn, gkey) \ STD_PHP_INI_BOOLEAN("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_SESSION_INI_LINK(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY_EX("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals, display_link_numbers) + /* {{{ INI entries */ PHP_INI_BEGIN() @@ -355,7 +361,8 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) - MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) + MEMC_SESSION_INI_LINK ("connect_timeout", "0", OnUpdateLong, connect_timeout) + MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) MEMC_SESSION_INI_BOOL ("persistent", "0", OnUpdateBool, persistent_enabled) @@ -375,14 +382,16 @@ PHP_INI_BEGIN() MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) - MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) + MEMC_INI_LINK ("default_connect_timeout", "0", OnUpdateLong, default_behavior.connect_timeout) PHP_INI_END() /* }}} */ #undef MEMC_INI_BOOL +#undef MEMC_INI_LINK #undef MEMC_INI_ENTRY #undef MEMC_SESSION_INI_BOOL +#undef MEMC_SESSION_INI_LINK #undef MEMC_SESSION_INI_ENTRY /**************************************** From dfcbc02693d49fa8708f6282776f7af4a884d904 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 04:13:27 -0800 Subject: [PATCH 543/694] Remove memcached.ini reference to deprecated sess_lock_max_wait setting --- memcached.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/memcached.ini b/memcached.ini index 6d05da3c..e4256c10 100644 --- a/memcached.ini +++ b/memcached.ini @@ -20,8 +20,7 @@ ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to -; use the memcached.sess_lock_max_wait setting. If that is -; also 0, max_execution_time will be used. +; use PHP's max_execution_time. ;memcached.sess_lock_expire = 0; ; memcached session key prefix From e0ccf87c517bc3ec54067166d34058f21d67b0b3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 06:21:40 -0800 Subject: [PATCH 544/694] Avoid hanging getStats() when binary protocol and non-blocking are both enabled Fixes #348. --- package.xml | 1 + php_memcached.c | 12 ++++++ tests/stats_hang.phpt | 89 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 tests/stats_hang.phpt diff --git a/package.xml b/package.xml index a8ece289..c0e8e09d 100644 --- a/package.xml +++ b/package.xml @@ -168,6 +168,7 @@ Fixes + diff --git a/php_memcached.c b/php_memcached.c index 1d015ccc..a42ff195 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2757,6 +2757,7 @@ PHP_METHOD(Memcached, getStats) memcached_return status; char *args = NULL; zend_string *args_string = NULL; + uint64_t orig_no_block, orig_protocol; MEMC_METHOD_INIT_VARS; /* "|S!" */ @@ -2770,8 +2771,19 @@ PHP_METHOD(Memcached, getStats) if (args_string) args = ZSTR_VAL(args_string); + /* stats hangs in nonblocking mode, turn off during the call. Only change the + * value if needed, because libmemcached reconnects for this behavior_set. */ + orig_no_block = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK); + orig_protocol = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL); + if (orig_no_block && orig_protocol) + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); + array_init(return_value); status = memcached_stat_execute(intern->memc, args, s_stat_execute_cb, return_value); + + if (orig_no_block && orig_protocol) + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK, orig_no_block); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); RETURN_FALSE; diff --git a/tests/stats_hang.phpt b/tests/stats_hang.phpt new file mode 100644 index 00000000..181e15e0 --- /dev/null +++ b/tests/stats_hang.phpt @@ -0,0 +1,89 @@ +--TEST-- +Check stats does not hang on non-blocking binary protocol +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_NO_BLOCK, true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, false); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, false); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, false); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, false); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +?> +--EXPECT-- +bool(false) +int(1) +int(1) +OK +bool(true) +int(0) +int(1) +OK +bool(true) +int(1) +int(0) +OK +bool(true) +int(0) +int(0) +OK From 8bfdbcc9063dafcb25fdb1d1705e07ee027d7379 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 29 Mar 2018 23:26:46 -0700 Subject: [PATCH 545/694] Update for new PHP 7.3 REFCOUNT macros (#390) --- .travis.yml | 3 +++ php_memcached.c | 4 ++-- php_memcached_private.h | 7 +++++++ php_memcached_session.c | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d2457f55..26973f0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,15 @@ dist: trusty language: php php: + - master - 7.2 - 7.1 - 7.0 matrix: fast_finish: true + allow_failures: + - php: master env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial diff --git a/php_memcached.c b/php_memcached.c index a42ff195..bd0f559e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1298,7 +1298,7 @@ static PHP_METHOD(Memcached, __construct) le.type = php_memc_list_entry(); le.ptr = intern->memc; - GC_REFCOUNT(&le) = 1; + GC_SET_REFCOUNT(&le, 1); /* plist_key is not a persistent allocated key, thus we use str_update here */ if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(plist_key), ZSTR_LEN(plist_key), &le, sizeof(le)) == NULL) { @@ -3831,7 +3831,7 @@ PHP_METHOD(MemcachedServer, on) Z_TRY_ADDREF(fci.function_name); if (fci.object) { - GC_REFCOUNT(fci.object)++; + GC_ADDREF(fci.object); } } RETURN_BOOL(rc); diff --git a/php_memcached_private.h b/php_memcached_private.h index a04e19be..abc0459c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -72,6 +72,13 @@ typedef unsigned long int uint32_t; # endif #endif +/* Backwards compatibility for GC API change in PHP 7.3 */ +#if PHP_VERSION_ID < 70300 +# define GC_ADDREF(p) ++GC_REFCOUNT(p) +# define GC_DELREF(p) --GC_REFCOUNT(p) +# define GC_SET_REFCOUNT(p, rc) GC_REFCOUNT(p) = rc +#endif + /**************************************** Structures and definitions ****************************************/ diff --git a/php_memcached_session.c b/php_memcached_session.c index d8e9be62..607a02c2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -376,7 +376,7 @@ PS_OPEN_FUNC(memcached) le.type = s_memc_sess_list_entry(); le.ptr = memc; - GC_REFCOUNT(&le) = 1; + GC_SET_REFCOUNT(&le, 1); /* plist_key is not a persistent allocated key, thus we use str_update here */ if (zend_hash_str_update_mem(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(le)) == NULL) { From 893d7d53062a0ff0a4112c22ce048db0b2afc67d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 29 Mar 2018 23:42:08 -0700 Subject: [PATCH 546/694] Expose build configuration via PECL (#383) --- package.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index c0e8e09d..0edfd3da 100644 --- a/package.xml +++ b/package.xml @@ -197,7 +197,15 @@ Fixes memcached - + + + + + + + + + From f4dafd207e4b3f1f54a7ce52194dda7cf40b0934 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 8 Apr 2018 19:39:38 -0700 Subject: [PATCH 547/694] Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#392) Provides a new INI option to select the same consistent hash behavior as older versions of php-memcached, to aid in migration from PHP 5.x to PHP 7.x. When `memcached_sess_consistent_hash_type` is set to `ketama` or `ketama_weighted`, that sets either MEMCACHED_BEHAVIOR_KETAMA or MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, respectively. Resolves #344 --- memcached.ini | 7 +++++++ php_memcached.c | 20 +++++++++++++++++++- php_memcached.h | 8 -------- php_memcached_private.h | 15 +++++++++++++++ php_memcached_session.c | 16 +++++----------- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/memcached.ini b/memcached.ini index e4256c10..138fd09a 100644 --- a/memcached.ini +++ b/memcached.ini @@ -43,6 +43,13 @@ ; default is On ;memcached.sess_consistent_hash = On +; memcached session consistent hash type +; if set to 'ketama', consistent hashing (libketama) is used +; for session handling (default for php-memcached 3.x) +; if set to 'ketama_weighted', weighted consistent hashing (libketama) is used +; for session handling (default for php-memcached 2.x) +;memcached.sess_consistent_hash_type = "ketama" + ; Allow failed memcached server to automatically be removed. ; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) ;memcached.sess_remove_failed_servers = Off diff --git a/php_memcached.c b/php_memcached.c index bd0f559e..c24e58af 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -323,6 +323,22 @@ PHP_INI_MH(OnUpdateSessionPrefixString) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static +PHP_INI_MH(OnUpdateConsistentHash) +{ + if (!new_value) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA; + } else if (!strcmp(ZSTR_VAL(new_value), "ketama")) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA; + } else if (!strcmp(ZSTR_VAL(new_value), "ketama_weighted")) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED; + } else { + php_error_docref(NULL, E_WARNING, "memcached.sess_consistent_hash_type must be ketama or ketama_weighted"); + return FAILURE; + } + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) @@ -357,6 +373,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_BOOL ("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) #endif MEMC_SESSION_INI_BOOL ("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_ENTRY("consistent_hash_type", "ketama", OnUpdateConsistentHash, consistent_hash_name) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) @@ -1254,7 +1271,6 @@ static PHP_METHOD(Memcached, __construct) /* Set default behaviors */ if (MEMC_G(default_behavior.consistent_hash_enabled)) { - memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); if (rc != MEMCACHED_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); @@ -4263,6 +4279,8 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.lock_expiration = 30; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; + php_memcached_globals->session.consistent_hash_type = MEMCACHED_BEHAVIOR_KETAMA; + php_memcached_globals->session.consistent_hash_name = NULL; php_memcached_globals->session.number_of_replicas = 0; php_memcached_globals->session.server_failure_limit = 1; php_memcached_globals->session.randomize_replica_read_enabled = 1; diff --git a/php_memcached.h b/php_memcached.h index 5194c038..a33f8be6 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,14 +42,6 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) -#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) -#else -#define MEMC_G(v) (php_memcached_globals.memc.v) -#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) -#endif - #endif /* PHP_MEMCACHED_H */ /* diff --git a/php_memcached_private.h b/php_memcached_private.h index abc0459c..cf652e39 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -156,6 +156,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool binary_protocol_enabled; zend_bool consistent_hash_enabled; + char *consistent_hash_name; + int consistent_hash_type; zend_long server_failure_limit; zend_long number_of_replicas; @@ -207,6 +209,19 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) ZEND_END_MODULE_GLOBALS(php_memcached) +/* Globals accessor macros */ +#ifdef ZTS +# define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) +# define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +# define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) +#else +# define MEMC_G(v) (php_memcached_globals.memc.v) +# define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +# define MEMC_SESS_INI(v) (php_memcached_globals.session.v) +#endif + +#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) + PHP_RINIT_FUNCTION(memcached); PHP_RSHUTDOWN_FUNCTION(memcached); PHP_MINIT_FUNCTION(memcached); diff --git a/php_memcached_session.c b/php_memcached_session.c index 607a02c2..7d072af2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -43,14 +43,6 @@ typedef struct { # define MAX(a,b) (((a)>(b))?(a):(b)) #endif -#ifdef ZTS -#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) -#else -#define MEMC_SESS_INI(v) (php_memcached_globals.session.v) -#endif - -#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) - static int le_memc_sess; @@ -187,9 +179,11 @@ static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { #define check_set_behavior(behavior, value) \ - if ((value) != memcached_behavior_get(memc, (behavior))) { \ + int b = (behavior); \ + uint64_t v = (value); \ + if (v != memcached_behavior_get(memc, b)) { \ memcached_return rc; \ - if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + if ((rc = memcached_behavior_set(memc, b, v)) != MEMCACHED_SUCCESS) { \ if (!silent) { \ php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ } \ @@ -202,7 +196,7 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) } if (MEMC_SESS_INI(consistent_hash_enabled)) { - check_set_behavior(MEMCACHED_BEHAVIOR_KETAMA, 1); + check_set_behavior(MEMC_SESS_INI(consistent_hash_type), 1); } if (MEMC_SESS_INI(server_failure_limit)) { From f5f84c592f8950ae150d7123704feb6a1258e3c5 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 30 Jun 2018 19:00:44 +0200 Subject: [PATCH 548/694] Remove unused Git attributes ident (#402) The $Id$ keywords were used in Subversion where they can be substituted with filename, last revision number change, last changed date, and last user who changed it. In Git this functionality is different and can be done with Git attribute ident. These need to be defined manually for each file in the .gitattributes file and are afterwards replaced with 40-character hexadecimal blob object name which is based only on the particular file contents. This patch simplifies handling of $Id$ keywords by removing them since they are not used anymore. --- config.m4 | 2 -- config.w32 | 1 - php_memcached.c | 2 -- php_memcached.h | 2 -- php_memcached_private.h | 2 -- 5 files changed, 9 deletions(-) diff --git a/config.m4 b/config.m4 index d38d5dc4..f086d492 100644 --- a/config.m4 +++ b/config.m4 @@ -1,5 +1,3 @@ -dnl -dnl $ Id: $ dnl vim:se ts=2 sw=2 et: PHP_ARG_ENABLE(memcached, whether to enable memcached support, diff --git a/config.w32 b/config.w32 index 380a9a12..e6e0c425 100644 --- a/config.w32 +++ b/config.w32 @@ -1,4 +1,3 @@ -// $ Id: $ // vim:ft=javascript ARG_WITH('memcached', 'libmemcached extension', 'no'); diff --git a/php_memcached.c b/php_memcached.c index c24e58af..01f98729 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - /* TODO * - set LIBKETAMA_COMPATIBLE as the default? * - fix unserialize(serialize($memc)) diff --git a/php_memcached.h b/php_memcached.h index a33f8be6..59989f5b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - #ifndef PHP_MEMCACHED_H #define PHP_MEMCACHED_H diff --git a/php_memcached_private.h b/php_memcached_private.h index cf652e39..561812e5 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - #ifndef PHP_MEMCACHED_PRIVATE_H #define PHP_MEMCACHED_PRIVATE_H From c54075a1bf77188af172287395dee4b81bbafd74 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Mon, 2 Jul 2018 19:16:12 +0200 Subject: [PATCH 549/694] Remove .cvsignore unused file (#404) The .cvsignore file was used in CVS. In Git the .gitignore file includes the ignored project files. --- .cvsignore | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 .cvsignore diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index cc617d3d..00000000 --- a/.cvsignore +++ /dev/null @@ -1,46 +0,0 @@ -*.lo -*.la -.deps -.libs -Makefile -Makefile.fragments -Makefile.global -Makefile.objects -acinclude.m4 -aclocal.m4 -autom4te.cache -build -config.cache -config.guess -config.h -config.h.in -config.log -config.nice -config.status -config.sub -configure -configure.in -conftest -conftest.c -include -install-sh -libtool -ltmain.sh -missing -mkinstalldirs -modules -scan_makefile_in.awk -*.dsw -*.plg -*.opt -*.ncb -Release -Release_inline -Debug -Release_TS -Release_TSDbg -Release_TS_inline -Debug_TS -memcached*.tgz -run-tests.php -cscope.out From b70b82ee4a793e3664394a20f92dd711044eea5b Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Jul 2018 00:57:05 +0200 Subject: [PATCH 550/694] Remove forgotten unused comment about -lpthread (#406) The -lpthread option has been added long time ago in commit c10de3699faa3ecb4cb6861d6c92157e0c7e18ce and has been since also refactored and therefore comment is not needed anymore: feed35e22040b874ba6fc8659dc16b498e6e4150 --- config.m4 | 1 - 1 file changed, 1 deletion(-) diff --git a/config.m4 b/config.m4 index f086d492..9694b5e2 100644 --- a/config.m4 +++ b/config.m4 @@ -253,7 +253,6 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) - dnl # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $INCLUDES" From 549e7c8a3af643ab5ce76002a6748990f04570d2 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Sat, 21 Jul 2018 01:01:55 +0200 Subject: [PATCH 551/694] Change session_lock default ini values (#350) --- memcached.ini | 12 ++++++------ php_memcached.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/memcached.ini b/memcached.ini index 138fd09a..c2072324 100644 --- a/memcached.ini +++ b/memcached.ini @@ -7,16 +7,16 @@ ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max ; is reached, after which any further retries will take sess_lock_wait_max seconds. -; Default is 1000. -;memcached.sess_lock_wait_min = 1000; +; Default is 150. +;memcached.sess_lock_wait_min = 150; ; The maximum time, in milliseconds, to wait between session lock attempts. -; Default is 2000. -;memcached.sess_lock_wait_max = 2000; +; Default is 150. +;memcached.sess_lock_wait_max = 150; ; The number of times to retry locking the session lock, not including the first attempt. -; Default is 5. -;memcached.sess_lock_retries = 5; +; Default is 200. +;memcached.sess_lock_retries = 200; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to diff --git a/php_memcached.c b/php_memcached.c index 01f98729..2e283818 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -361,8 +361,8 @@ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION MEMC_SESSION_INI_BOOL ("locking", "1", OnUpdateBool, lock_enabled) - MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) - MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) + MEMC_SESSION_INI_ENTRY("lock_wait_min", "150", OnUpdateLongGEZero, lock_wait_min) + MEMC_SESSION_INI_ENTRY("lock_wait_max", "150", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 @@ -4271,9 +4271,9 @@ PHP_GINIT_FUNCTION(php_memcached) #ifdef HAVE_MEMCACHED_SESSION php_memcached_globals->session.lock_enabled = 0; - php_memcached_globals->session.lock_wait_max = 2000; - php_memcached_globals->session.lock_wait_min = 1000; - php_memcached_globals->session.lock_retries = 5; + php_memcached_globals->session.lock_wait_max = 150; + php_memcached_globals->session.lock_wait_min = 150; + php_memcached_globals->session.lock_retries = 200; php_memcached_globals->session.lock_expiration = 30; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; From 58b299e5856f6728e9adef4cd8d5b33a4aaf3748 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 1 Sep 2018 18:27:21 +0200 Subject: [PATCH 552/694] Add configure.ac to Git ignored files (#405) Starting with PHP 7.2, the phpize script outputs configure.ac. Earlier verisons of phpize generated configure.in. Since configure.in was already on the gitignore list, this PR adds configure.ac to the gitignore list. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bc9d558c..0cbefe90 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ config.status config.sub configure configure.in +configure.ac conftest conftest.c include From f773f278c9c43a40f3a66fea792247b4e04df931 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 1 Sep 2018 18:30:31 +0200 Subject: [PATCH 553/694] Replace obsolete AC_TRY_FOO with AC_FOO_IFELSE (#403) Autoconf made several macros obsolete including the AC_TRY_COMPILE and AC_TRY_LINK in 2000 and since Autoconf 2.50: http://git.savannah.gnu.org/cgit/autoconf.git/tree/ChangeLog.2 These macros should be replaced with the current AC_FOO_IFELSE instead. It is fairly safe to upgrade and take the recommendation advice of autoconf upgrade manual since the upgrade should be compatible at least with PHP versions 5.4 and up, on some systems even with PHP 5.3. PHP versions from 5.4 to 7.1 require Autoconf 2.59+ and PHP 7.2+ require Autoconf 2.64+. This patch was created with the help of autoupdate script. Reference docs: - https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Obsolete-Macros.html - https://www.gnu.org/software/autoconf/manual/autoconf-2.59/autoconf.pdf --- config.m4 | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/config.m4 b/config.m4 index 9694b5e2..1f75d622 100644 --- a/config.m4 +++ b/config.m4 @@ -259,17 +259,15 @@ if test "$PHP_MEMCACHED" != "no"; then dnl # Always check if libmemcached was built with SASL support, dnl # because it will require sasl.h even if not used here. AC_CACHE_CHECK([for libmemcached sasl.h requirement], ac_cv_memc_sasl_support, [ - AC_TRY_COMPILE( - [ #include ], - [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #if LIBMEMCACHED_WITH_SASL_SUPPORT /* yes */ #else # error "no sasl support" #endif - ], - [ ac_cv_memc_sasl_support="yes" ], - [ ac_cv_memc_sasl_support="no" ] + ]])], + [ac_cv_memc_sasl_support="yes"], + [ac_cv_memc_sasl_support="no"] ) ]) @@ -303,12 +301,11 @@ if test "$PHP_MEMCACHED" != "no"; then LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" AC_CACHE_CHECK([whether memcached_exist is defined], ac_cv_have_memcached_exist, [ - AC_TRY_LINK( - [ #include ], - [ memcached_exist (NULL, NULL, 0); ], - [ ac_cv_have_memcached_exist="yes" ], - [ ac_cv_have_memcached_exist="no" ] - ) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[memcached_exist (NULL, NULL, 0);]])], + [ac_cv_have_memcached_exist="yes"], + [ac_cv_have_memcached_exist="no"]) ]) CFLAGS="$ORIG_CFLAGS" @@ -322,12 +319,11 @@ if test "$PHP_MEMCACHED" != "no"; then fi AC_CACHE_CHECK([whether memcached_set_encoding_key is defined], ac_cv_have_memcached_set_encoding_key, [ - AC_TRY_LINK( - [ #include ], - [ memcached_set_encoding_key (NULL, NULL, 0); ], - [ ac_cv_have_memcached_set_encoding_key="yes" ], - [ ac_cv_have_memcached_set_encoding_key="no" ] - ) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[memcached_set_encoding_key (NULL, NULL, 0);]])], + [ac_cv_have_memcached_set_encoding_key="yes"], + [ac_cv_have_memcached_set_encoding_key="no"]) ]) CFLAGS="$ORIG_CFLAGS" @@ -359,13 +355,12 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([enabled]) AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [ - AC_TRY_COMPILE( - [ #include ], - [ memcached_binary_protocol_callback_st s_test_impl; + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[memcached_binary_protocol_callback_st s_test_impl; s_test_impl.interface.v1.delete_object = 0; - ], - [ ac_cv_have_libmemcachedprotocol="yes" ], - [ ac_cv_have_libmemcachedprotocol="no" ] + ]])], + [ac_cv_have_libmemcachedprotocol="yes"], + [ac_cv_have_libmemcachedprotocol="no"] ) ]) From 6220e207b05e7ff8ef0ed3ac79907bcd753c4a65 Mon Sep 17 00:00:00 2001 From: "Michael D. Stemle, Jr" Date: Wed, 14 Nov 2018 19:25:58 -0500 Subject: [PATCH 554/694] In the latest zlib package for homebrew, the install target is /usr/local/opt/zlib, so I'm adding that to the list. (#410) --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 1f75d622..6deddfb9 100644 --- a/config.m4 +++ b/config.m4 @@ -60,7 +60,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"]) fi else - for i in /usr/local /usr; do + for i in /usr/local /usr/local/opt/zlib /usr; do if test -f "$i/include/zlib/zlib.h"; then PHP_ZLIB_DIR="$i" PHP_ZLIB_INCDIR="$i/include/zlib" From 6d8f5d524f35e72422b9e81319b96f23af02adcc Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 15 Nov 2018 11:27:53 +1100 Subject: [PATCH 555/694] Windows fixes (#411) --- README.win32.txt | 13 +++++++++++++ config.w32 | 30 ++++++++++++++++++++++++++++-- php_memcached.c | 8 +++++++- php_memcached.h | 5 +++++ php_memcached_private.h | 4 ++++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 README.win32.txt diff --git a/README.win32.txt b/README.win32.txt new file mode 100644 index 00000000..c717aa8a --- /dev/null +++ b/README.win32.txt @@ -0,0 +1,13 @@ +Build Steps for Windows +------------------------- + +Follow https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2#building_pecl_extensions + +- Add igbinary module to pecl directory if support desired +- Download/Compile libmemcached & add to deps folders (includes & lib). Lib should be named memcache.lib + - Important for 32bit: libmemcached must be built with _USE_32BIT_TIME_T defined (confirmed on PHP 7.2, VC15) + - https://github.com/yshurik/libmemcached-win/tree/1.0.18 is confirmed working + - To use the dll on the releases page you'd likely need to change the header files to use __time64_t instead of time_t +- Enable all options desired: --enable-memcached=shared --enable-memcached-session --enable-memcached-json + - for igbinary, add --enable-memcached-igbinary --enable-igbinary=shared +- Run nmake \ No newline at end of file diff --git a/config.w32 b/config.w32 index e6e0c425..9c84a059 100644 --- a/config.w32 +++ b/config.w32 @@ -1,6 +1,10 @@ // vim:ft=javascript -ARG_WITH('memcached', 'libmemcached extension', 'no'); +ARG_ENABLE('memcached', 'libmemcached extension', 'no'); + +ARG_ENABLE('memcached-session', 'whether to enable memcached session handler support', 'no'); +ARG_ENABLE('memcached-igbinary', 'whether to enable memcached igbinary serializer support', 'no'); +ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer support', 'no'); if (PHP_MEMCACHED == "yes") { @@ -11,7 +15,29 @@ if (PHP_MEMCACHED == "yes") { if (!CHECK_HEADER_ADD_INCLUDE("libmemcached/memcached.h", "CFLAGS_MEMCACHED")) { ERROR("memcached: header 'libmemcached/memcached.h' not found"); } - EXTENSION("memcached", "memcached.c"); + + if (PHP_MEMCACHED_JSON != "no"){ + AC_DEFINE("HAVE_JSON_API",1); + } + + var memcached_extra_src = ""; + + if (PHP_MEMCACHED_SESSION != "no"){ + AC_DEFINE("HAVE_MEMCACHED_SESSION",1); + ADD_EXTENSION_DEP("memcached", "session", true) + memcached_extra_src += " php_memcached_session.c"; + } + + if (PHP_MEMCACHED_IGBINARY != "no"){ + AC_DEFINE("HAVE_MEMCACHED_IGBINARY",1); + ADD_EXTENSION_DEP("memcached", "igbinary", true); + if (!CHECK_HEADER_ADD_INCLUDE("igbinary.h", "CFLAGS_MEMCACHED")) { + ERROR("memcached: header 'igbinary.h' not found"); + } + } + + EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src); + ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); AC_DEFINE("MEMCACHED_EXPORTS", 1) } diff --git a/php_memcached.c b/php_memcached.c index 2e283818..760c2c45 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -42,8 +42,14 @@ #endif #ifdef HAVE_MEMCACHED_IGBINARY +#ifdef PHP_WIN32 +//Windows extensions are generally built together, +//so it wont be in the installed location +#include "igbinary.h" +#else # include "ext/igbinary/igbinary.h" #endif +#endif #ifdef HAVE_MEMCACHED_MSGPACK # include "ext/msgpack/php_msgpack.h" @@ -1428,7 +1434,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - php_memc_get_ctx_t context = {}; + php_memc_get_ctx_t context = {0}; php_memc_keys_t keys = {0}; zend_long get_flags = 0; zend_string *key; diff --git a/php_memcached.h b/php_memcached.h index 59989f5b..b391790a 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -19,7 +19,12 @@ #include "php.h" #include "Zend/zend_smart_str.h" + +#ifdef PHP_WIN32 +#include "main/config.w32.h" +#else #include "main/php_config.h" +#endif #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/php_memcached_private.h b/php_memcached_private.h index 561812e5..3e1f3586 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -17,7 +17,11 @@ #ifndef PHP_MEMCACHED_PRIVATE_H #define PHP_MEMCACHED_PRIVATE_H +#ifdef PHP_WIN32 +#include "main/config.w32.h" +#else #include "main/php_config.h" +#endif #ifdef HAVE_CONFIG_H # include "config.h" From 0b79956e6d92268295c67e26bc173d44724bf5a8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 9 Apr 2018 00:35:56 -0700 Subject: [PATCH 556/694] Error message if old PERSISTENT=n flag is used in session.save_path --- package.xml | 1 + php_memcached_session.c | 7 +++++++ tests/session_badconf_persistent.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/session_badconf_persistent.phpt diff --git a/package.xml b/package.xml index 0edfd3da..2c537c02 100644 --- a/package.xml +++ b/package.xml @@ -117,6 +117,7 @@ Fixes + diff --git a/php_memcached_session.c b/php_memcached_session.c index 7d072af2..6acd9d3e 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -319,6 +319,13 @@ PS_OPEN_FUNC(memcached) memcached_server_list_st servers; + // Fail on incompatible PERSISTENT identifier (removed in php-memcached 3.0) + if (strstr(save_path, "PERSISTENT=")) { + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path: PERSISTENT is replaced by memcached.sess_persistent = On"); + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + // First parse servers servers = memcached_servers_parse(save_path); diff --git a/tests/session_badconf_persistent.phpt b/tests/session_badconf_persistent.phpt new file mode 100644 index 00000000..04b5e44e --- /dev/null +++ b/tests/session_badconf_persistent.phpt @@ -0,0 +1,25 @@ +--TEST-- +Session bad configurations, persistent +--SKIPIF-- + +--INI-- +session.save_handler = "memcached" +session.save_path = "PERSISTENT=1 hello:11211,world:11211" + +--FILE-- + Date: Mon, 9 Apr 2018 02:15:58 -0700 Subject: [PATCH 557/694] Nits --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 760c2c45..a7c33d31 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1526,7 +1526,7 @@ zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval add_assoc_zval(&node, "cas", cas); add_assoc_long(&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); } else { zend_symtable_update(Z_ARRVAL_P(context->return_value), key, value); @@ -3213,7 +3213,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { - retval = 0;; + retval = 0; } efree(server_map); From 282eca70cb6f4466093ab9a2f89ee1fbea5f1abd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 01:29:12 -0800 Subject: [PATCH 558/694] Add PHP 7.3 to Travis CI matrix, drop ancient libmemcached --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26973f0a..ddc6d379 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ dist: trusty language: php php: - master + - 7.3 - 7.2 - 7.1 - 7.0 @@ -17,7 +18,6 @@ env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty - - LIBMEMCACHED_VERSION=1.0.2 # Ancient addons: apt: From e9381d07ca09367846d974b1ce1d4b02f8ba7c0a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 01:39:33 -0800 Subject: [PATCH 559/694] Travis CI switch to Xenial, remove deprecated sudo flag --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ddc6d379..5ce37750 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ -sudo: required -dist: trusty +dist: xenial language: php php: From c5618158c56569a1c20a94b4d792a3e182b528d0 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 02:08:04 -0800 Subject: [PATCH 560/694] Handle fatal error in session badconf persistent test --- tests/session_badconf_persistent.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/session_badconf_persistent.phpt b/tests/session_badconf_persistent.phpt index 04b5e44e..7deeb1e1 100644 --- a/tests/session_badconf_persistent.phpt +++ b/tests/session_badconf_persistent.phpt @@ -16,10 +16,10 @@ ob_start(); session_start(); session_write_close(); -echo "OK"; +// In PHP < 7.2 this is a Fatal Error so the OK is not printed +// echo "OK"; --EXPECTF-- Warning: session_start(): failed to parse session.save_path: PERSISTENT is replaced by memcached.sess_persistent = On in %s on line %d -Warning: session_start(): Failed to initialize storage module: memcached (path: PERSISTENT=1 %s) in %s on line %d -OK +%s: session_start(): Failed to initialize storage module: memcached (path: PERSISTENT=1 %s) in %s on line %d From 193590e93b4169fb830791d68b28d748f3951729 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 03:48:49 -0800 Subject: [PATCH 561/694] Release notes for 3.1.0 --- ChangeLog | 28 +++++++++++++++++++++++ package.xml | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e406ee2..71536d94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,33 @@ memcached extension changelog +Version 3.1.0 (2017-12-21) +-------------------------- + + New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + + Fixes + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + + Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) + Version 3.0.4 (2017-11-20) -------------------------- diff --git a/package.xml b/package.xml index 2c537c02..3015d032 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-11-20 + 2018-12-21 - 3.0.4 + 3.1.0 3.0.0 @@ -38,19 +38,35 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested -version is 1.0.2. It is highly recommended to use version 1.0.18 of +version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. +New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + Fixes - * Fix corrupted interned strings (#338) - * Fix unit tests for compatibility with PHP 7.2 (#358, #359) - * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) - * Fix missing optional parameter getStats($type) (#337) - * Fix typo in skip message (#331) - * Fix build warnings (#329) - * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + +Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) @@ -209,6 +225,32 @@ Fixes + + + stable + stable + + + 3.0.4 + 3.0.0 + + 2017-11-20 + +PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + + stable From 699e68953a908e90235cf23671ce245ad35c5ef6 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 03:49:01 -0800 Subject: [PATCH 562/694] Bump version to 3.1.0 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index b391790a..97c64404 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.0-dev" +#define PHP_MEMCACHED_VERSION "3.1.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4a82c59f49fe0a222a6cab6cc612f899ccc199a5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:44:15 -0800 Subject: [PATCH 563/694] Document that --disable-x options are --enable-x --- config.m4 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/config.m4 b/config.m4 index 6deddfb9..c7a15f11 100644 --- a/config.m4 +++ b/config.m4 @@ -1,40 +1,40 @@ dnl vim:se ts=2 sw=2 et: PHP_ARG_ENABLE(memcached, whether to enable memcached support, -[ --enable-memcached Enable memcached support]) +[ --enable-memcached Enable memcached support]) PHP_ARG_WITH(libmemcached-dir, for libmemcached, -[ --with-libmemcached-dir[=DIR] Set the path to libmemcached install prefix.], yes) +[ --with-libmemcached-dir=DIR Set the path to libmemcached install prefix.], yes) PHP_ARG_ENABLE(memcached-session, whether to enable memcached session handler support, -[ --disable-memcached-session Disable memcached session handler support], yes, no) +[ --enable-memcached-session Enable memcached session handler support], yes, no) PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializer support, -[ --enable-memcached-igbinary Enable memcached igbinary serializer support], no, no) +[ --enable-memcached-igbinary Enable memcached igbinary serializer support], no, no) PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support, -[ --enable-memcached-json Enable memcached json serializer support], no, no) +[ --enable-memcached-json Enable memcached json serializer support], no, no) PHP_ARG_ENABLE(memcached-msgpack, whether to enable memcached msgpack serializer support, -[ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) +[ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, -[ --disable-memcached-sasl Disable memcached sasl support], yes, no) +[ --enable-memcached-sasl Enable memcached sasl support], yes, no) PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, -[ --enable-memcached-protocol Enable memcached protocol support], no, no) +[ --enable-memcached-protocol Enable memcached protocol support], no, no) PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, -[ --with-system-fastlz Use system FastLZ library], no, no) +[ --with-system-fastlz Use system FastLZ library], no, no) if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, -[ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) +[ --with-zlib-dir=DIR Set the path to ZLIB install prefix.], no) fi if test -z "$PHP_DEBUG"; then AC_ARG_ENABLE(debug, - [ --enable-debug compile with debugging symbols],[ + [ --enable-debug Compile with debugging symbols],[ PHP_DEBUG=$enableval ],[ PHP_DEBUG=no ]) From b4d105bd41f1b6a54635d1e681f38924b264ec67 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:45:44 -0800 Subject: [PATCH 564/694] Set defaults to match --enable-x rather than --disable-x --- package.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 3015d032..d9270d03 100644 --- a/package.xml +++ b/package.xml @@ -220,9 +220,9 @@ Changes - - - + + + From 9f7d049737f6ebe77013e6a21906959844696ade Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:46:06 -0800 Subject: [PATCH 565/694] Fix zend_string warning --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index a7c33d31..858d0aca 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -493,7 +493,7 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ char *buffer = NULL; if (fci->object) { - spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), fci_cache->function_handler->common.function_name); + spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), ZSTR_VAL(fci_cache->function_handler->common.function_name)); } else { if (Z_TYPE (fci->function_name) == IS_OBJECT) { spprintf (&buffer, 0, "%s", ZSTR_VAL(Z_OBJCE(fci->function_name)->name)); From e2dbf33fe9a9fcced24dc2728084fd09e1fe8b72 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:51:32 -0800 Subject: [PATCH 566/694] Release notes for 3.1.1 --- ChangeLog | 5 ++++ package.xml | 68 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71536d94..4a1748b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ memcached extension changelog +Version 3.1.1 (2017-12-21) +-------------------------- + + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + Version 3.1.0 (2017-12-21) -------------------------- diff --git a/package.xml b/package.xml index d9270d03..9b6faf68 100644 --- a/package.xml +++ b/package.xml @@ -29,7 +29,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2018-12-21 - 3.1.0 + 3.1.1 3.0.0 @@ -43,30 +43,8 @@ libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. -New - * Support for PHP 7.3 (#385, #390) - * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) - * Add support for libmemcached encryption (#345, #381) - * Add error reporting to session code (#165) - * Expose build configuration via PECL (#383) - Fixes - * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) - * Fix session persistence by checking memcached behavior values before setting (#379) - * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) - * Configure warns if libmemcached needs sasl.h (#341, #380) - * Resolve various INI deviations in 3.0.3 (#351) - * Turn off sess_binary_protocol by default with older libmemcached (#330) - -Changes - * Impove Windows builds (#411) - * Support Homebrew ZLIB path (#410) - * Remove forgotten unused comment about -lpthread (#406) - * Git ignore configure.ac (#405) - * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) - * Remove unused defines (#354) - * Change session_lock and sess_prefix default ini values (#340, #350) - * Use new fast_zpp parameter parsing API (#302, #311) + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) @@ -225,6 +203,48 @@ Changes + + + stable + stable + + + 3.1.0 + 3.0.0 + + 2018-12-21 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + +Fixes + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + +Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) + + stable From b4103acd0356db74518534c5da1702c72b38d459 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:51:44 -0800 Subject: [PATCH 567/694] Bump version to 3.1.1 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 97c64404..3197d058 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.0" +#define PHP_MEMCACHED_VERSION "3.1.1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 5ad7c05614dc2ea7f977193ad6157187d15fc89e Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 05:59:52 -0800 Subject: [PATCH 568/694] Partially revert b4d105b caught one option too many --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 9b6faf68..7eca1a2c 100644 --- a/package.xml +++ b/package.xml @@ -198,7 +198,7 @@ Fixes - + From 206f12bddaf014eec4a53437c16c99ae9537216c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 07:54:24 -0800 Subject: [PATCH 569/694] Release notes for 3.1.2 --- package.xml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 7eca1a2c..8f54da93 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-21 + 2018-12-22 - 3.1.1 + 3.1.2 3.0.0 @@ -44,7 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) @@ -203,6 +203,26 @@ Fixes + + + stable + stable + + + 3.1.1 + 3.0.0 + + 2018-12-21 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + + stable From 02e1e2ffd25fc0cc5e8b0507e83d28612128cc8c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 07:54:42 -0800 Subject: [PATCH 570/694] Bump version to 3.1.2 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 3197d058..810b62ed 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.1" +#define PHP_MEMCACHED_VERSION "3.1.2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 35292435e29795166b65bbb73653a957c9f91cee Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 22 Dec 2018 17:00:04 +0100 Subject: [PATCH 571/694] fix build warning (#417) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 858d0aca..4deb5de8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2752,7 +2752,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch server_values = zend_hash_add(Z_ARRVAL_P(return_value), server_key, &zv); } - spprintf (&buffer, 0, "%.*s", value_length, value); + spprintf (&buffer, 0, "%.*s", (int)value_length, value); /* Check type */ if (s_long_value (buffer, &long_val)) { From c85d9029fbe525fb1cd113d22d61aba1eb9876bd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:16:42 -0800 Subject: [PATCH 572/694] Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#420) Resolves #396 --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 4deb5de8..930e1189 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -302,6 +302,7 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#ifdef HAVE_MEMCACHED_SESSION static PHP_INI_MH(OnUpdateDeprecatedLockValue) { @@ -342,6 +343,7 @@ PHP_INI_MH(OnUpdateConsistentHash) } return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#endif // HAVE_MEMCACHED_SESSION #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) From c76ec9e6ea3e15f239f71532025762a0217afb44 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:38:57 -0800 Subject: [PATCH 573/694] Release notes for 3.1.2 and 3.1.3, fix dates for 3.1.x --- ChangeLog | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4a1748b3..e55dd8fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,21 @@ memcached extension changelog -Version 3.1.1 (2017-12-21) +Version 3.1.3 (2018-12-24) +-------------------------- + + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + +Version 3.1.2 (2018-12-22) +-------------------------- + + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + +Version 3.1.1 (2018-12-21) -------------------------- * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) -Version 3.1.0 (2017-12-21) +Version 3.1.0 (2018-12-21) -------------------------- New From 9cf95806225d79716db606ae9351b0c4043f6862 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:40:29 -0800 Subject: [PATCH 574/694] Release notes for 3.1.3 --- package.xml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 8f54da93..a801f856 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-22 + 2018-12-24 - 3.1.2 + 3.1.3 3.0.0 @@ -44,7 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) @@ -203,6 +203,26 @@ Fixes + + + stable + stable + + + 3.1.2 + 3.0.0 + + 2018-12-22 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + + stable From 3ba380c1290959f67fc0d00755c93918037ead71 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:40:44 -0800 Subject: [PATCH 575/694] Bump version to 3.1.3 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 810b62ed..be1235e7 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.2" +#define PHP_MEMCACHED_VERSION "3.1.3" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 37f2cf98ae8000e54aab3c1be558d2dfc667304b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 11 Mar 2019 17:39:57 -0400 Subject: [PATCH 576/694] Fix segfault for unknown memcache flags Set retval to false so that the resulting uninitialized zval won't be used. --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 930e1189..85c79901 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3745,6 +3745,7 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re default: php_error_docref(NULL, E_WARNING, "unknown payload type"); + retval = 0; break; } zend_string_release(data); From 455d7823b9d02c9cad442413de096baf98351ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20M?= Date: Thu, 11 Apr 2019 14:59:20 +0200 Subject: [PATCH 577/694] Supports PHP 7.3 Supported according to #408 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 19a8ab18..c3ee51a1 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.2. +* Supports PHP 7.0 - 7.3. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From cd62e8f463132c166697d5ae5e0026a255be13ac Mon Sep 17 00:00:00 2001 From: Gerry Demaret Date: Tue, 21 May 2019 20:44:17 +0200 Subject: [PATCH 578/694] Update documented default for sess_lock_retries (#432) The documented default was 200, while in reality it seems this is actually set to 5. While 5 is arguably on the low side, at least have the documentation in sync with reality. --- memcached.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/memcached.ini b/memcached.ini index c2072324..5ed79bdb 100644 --- a/memcached.ini +++ b/memcached.ini @@ -15,8 +15,8 @@ ;memcached.sess_lock_wait_max = 150; ; The number of times to retry locking the session lock, not including the first attempt. -; Default is 200. -;memcached.sess_lock_retries = 200; +; Default is 5. +;memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to From 7443d16d02fb73cdba2e90ae282446f80969229c Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Mon, 17 Jun 2019 16:04:47 +0100 Subject: [PATCH 579/694] Test on PHP 7.4 as well as 8.0 (#440) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5ce37750..22db51da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ dist: xenial language: php php: - master + - 7.4snapshot - 7.3 - 7.2 - 7.1 From 5d154be2864ce9b1572119e2416a874e73c0ccc5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Oct 2019 16:25:36 -0700 Subject: [PATCH 580/694] Remove stray instances of TSRMLS_CC macro This macro was defined empty in PHP 7.x, and removed in PHP 8.x. --- php_memcached_session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 6acd9d3e..ce9a46db 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -445,7 +445,7 @@ PS_READ_FUNC(memcached) *val = ZSTR_EMPTY_ALLOC(); return SUCCESS; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); + php_error_docref(NULL, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); return FAILURE; } } @@ -475,7 +475,7 @@ PS_WRITE_FUNC(memcached) if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); + php_error_docref(NULL, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); } } while (--retries > 0); From 26e38ccee6110a1491c5e36d297cdb12cb261a99 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Oct 2019 16:46:23 -0700 Subject: [PATCH 581/694] Use temporary fork of igbinary for php-8 support --- .travis/travis.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 81049355..090e3992 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,9 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git + git clone https://github.com/sodabrew/igbinary.git pushd igbinary + git checkout php-8 phpize ./configure make From 77120444b4f24b51621aa3e9088e08349597c786 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 5 Oct 2019 09:02:48 -0700 Subject: [PATCH 582/694] Revert "Use temporary fork of igbinary for php-8 support" Upstream accepted the patch for PHP master / PHP 8 support. This reverts commit 26e38ccee6110a1491c5e36d297cdb12cb261a99. --- .travis/travis.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 090e3992..81049355 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,9 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/sodabrew/igbinary.git + git clone https://github.com/igbinary/igbinary.git pushd igbinary - git checkout php-8 phpize ./configure make From 0ee62bd55d85ae1495ca87c096cde061df8df00a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 5 Oct 2019 09:32:26 -0700 Subject: [PATCH 583/694] Release notes for 3.1.4 --- ChangeLog | 8 ++++++++ README.markdown | 2 +- package.xml | 31 +++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index e55dd8fd..05060cb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ memcached extension changelog +Version 3.1.4 (2019-10-06) +-------------------------- + + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries( #432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + Version 3.1.3 (2018-12-24) -------------------------- diff --git a/README.markdown b/README.markdown index c3ee51a1..31f57b16 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.3. +* Supports PHP 7.0 - 7.4. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. diff --git a/package.xml b/package.xml index a801f856..0cbc9f63 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-24 + 2019-10-06 - 3.1.3 + 3.1.4 3.0.0 @@ -38,13 +38,16 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries( #432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) @@ -203,6 +206,26 @@ Fixes + + + stable + stable + + + 3.1.3 + 3.0.0 + + 2018-12-22 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + + stable From 5fd997fc68674a192db19c32c4c46aa201fff215 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 6 Oct 2019 09:01:37 -0700 Subject: [PATCH 584/694] Bump version to 3.1.4 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index be1235e7..71e3acef 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.3" +#define PHP_MEMCACHED_VERSION "3.1.4" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 03f034f63ea8224cf0072f9bcf3fd9c7b6141290 Mon Sep 17 00:00:00 2001 From: Po-Chuan Hsieh Date: Tue, 19 Nov 2019 02:01:10 +0800 Subject: [PATCH 585/694] Fix build with PHP 7.4 (#445) Build error on FreeBSD with PHP 7.4 RC6: --- php_memcached.lo --- /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:7: error: expected ';' after expression ulong key_index; ^ ; /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:2: error: use of undeclared identifier 'ulong' ulong key_index; ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:8: error: use of undeclared identifier 'key_index' ulong key_index; ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3250:49: error: use of undeclared identifier 'key_index' ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), key_index, key, value) { ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3255:44: error: use of undeclared identifier 'key_index' if (!php_memc_set_option(intern, (long) key_index, value)) { ^ 5 errors generated. *** [php_memcached.lo] Error code 1 --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 85c79901..50636952 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3234,7 +3234,7 @@ static PHP_METHOD(Memcached, setOptions) zval *options; zend_bool ok = 1; zend_string *key; - ulong key_index; + zend_ulong key_index; zval *value; MEMC_METHOD_INIT_VARS; From 7141624896470d28492a6f39c844f57ea57cbf1f Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 6 Oct 2019 09:04:40 -0700 Subject: [PATCH 586/694] Fix typo --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 0cbc9f63..4cf8d3ee 100644 --- a/package.xml +++ b/package.xml @@ -46,7 +46,7 @@ libmemcached. Fixes * Test on PHP 7.4 as well as 8.0 (#440) * Fix segfault for unknown memcached flags (#431) - * Update documented defaults for sess_lock_retries( #432) + * Update documented defaults for sess_lock_retries (#432) * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) From d7daff649406efbd43af3253212b1cb946ff3f85 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 3 Dec 2019 13:56:22 -0800 Subject: [PATCH 587/694] Bump version and release notes for 3.1.5 --- ChangeLog | 5 +++++ package.xml | 32 ++++++++++++++++++++++++++------ php_memcached.h | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05060cb7..31994e3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ memcached extension changelog +Version 3.1.5 (2019-12-03) +-------------------------- + + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) + Version 3.1.4 (2019-10-06) -------------------------- diff --git a/package.xml b/package.xml index 4cf8d3ee..c5588a3f 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2019-10-06 + 2019-12-03 - 3.1.4 + 3.1.5 3.0.0 @@ -44,10 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Test on PHP 7.4 as well as 8.0 (#440) - * Fix segfault for unknown memcached flags (#431) - * Update documented defaults for sess_lock_retries (#432) - * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) @@ -206,6 +203,29 @@ Fixes + + + stable + stable + + + 3.1.4 + 3.0.0 + + 2019-10-06 + +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries (#432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + + stable diff --git a/php_memcached.h b/php_memcached.h index 71e3acef..cccb6d47 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.4" +#define PHP_MEMCACHED_VERSION "3.1.5" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From ed3f39d07e08517e68acdbf57304da1328d7adac Mon Sep 17 00:00:00 2001 From: Julien Boulen Date: Wed, 11 Mar 2020 12:00:43 +0100 Subject: [PATCH 588/694] Fix memcached.ini comment - use new config name not the old one (#455) --- memcached.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index 5ed79bdb..35548f32 100644 --- a/memcached.ini +++ b/memcached.ini @@ -60,7 +60,7 @@ ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. -; If this value is positive and sess_remove_failed is enabled +; If this value is positive and sess_remove_failed_servers is enabled ; when a memcached server fails the session will continue to be available ; from a replica. However, if the failed memcache server ; becomes available again it will read the session from there From 2d43ce8c92c08f4576e57ad88c8521f85e90cd94 Mon Sep 17 00:00:00 2001 From: Jon Desrosiers Date: Tue, 29 Sep 2020 14:16:48 -0400 Subject: [PATCH 589/694] PHP 7.4 is no longer in "snapshot". (#460) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22db51da..7d6b57d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ dist: xenial language: php php: - master - - 7.4snapshot + - 7.4 - 7.3 - 7.2 - 7.1 @@ -34,5 +34,5 @@ script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION cache: - directories: + directories: - $HOME/cache From c94e014da53cc8a3d0510402f36bc6e5e17bf608 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 2 Oct 2020 19:34:31 +0300 Subject: [PATCH 590/694] fix php 8.0 build (#461) fci.no_separation removed on php 8.0. https://github.com/php/php-src/commit/302933daea77663f5759b10accd1d0231393b24c --- php_memcached_server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_server.c b/php_memcached_server.c index 4c0080e8..870209c1 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -63,7 +63,9 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t para cb->fci.retval = retval; cb->fci.params = params; cb->fci.param_count = param_count; +#if PHP_VERSION_ID < 80000 cb->fci.no_separation = 1; +#endif if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { char *buf = php_memc_printable_func(&(cb->fci), &(cb->fci_cache)); From e8f53777d3f578586f2a32f1b3bdcc3f53e74b39 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 11:58:43 +0200 Subject: [PATCH 591/694] generate arginfo from stub for PHP 7 and 8 --- php_memcached.c | 404 +------------------------------- php_memcached.stub.php | 94 ++++++++ php_memcached_arginfo.h | 411 +++++++++++++++++++++++++++++++++ php_memcached_legacy_arginfo.h | 407 ++++++++++++++++++++++++++++++++ tests/bad_construct.phpt | 5 +- tests/bad_construct_8.phpt | 34 +++ tests/expire.phpt | 1 + tests/undefined_set.phpt | 10 +- tests/vbucket.phpt | 20 -- tests/vbucket_error_7.phpt | 40 ++++ tests/vbucket_error_8.phpt | 41 ++++ 11 files changed, 1044 insertions(+), 423 deletions(-) create mode 100644 php_memcached.stub.php create mode 100644 php_memcached_arginfo.h create mode 100644 php_memcached_legacy_arginfo.h create mode 100644 tests/bad_construct_8.phpt create mode 100644 tests/vbucket_error_7.phpt create mode 100644 tests/vbucket_error_8.phpt diff --git a/php_memcached.c b/php_memcached.c index 50636952..147cb4ab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1853,7 +1853,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *entries; zend_string *server_key = NULL; - zend_long expiration = 0, ignored; + zend_long expiration = 0; zval *value; zend_string *skey; zend_ulong num_key; @@ -1867,7 +1867,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } else { /* "a|ll" */ @@ -1875,7 +1874,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } @@ -2071,7 +2069,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; zend_long expiration = 0; - zend_long ignored; zend_string *payload; uint32_t flags = 0; memcached_return status; @@ -2086,7 +2083,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_ZVAL(value) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } else { /* "zSz|ll" */ @@ -2096,7 +2092,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_ZVAL(value) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } @@ -3862,395 +3857,10 @@ PHP_METHOD(MemcachedServer, on) #endif -/* {{{ methods arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) - ZEND_ARG_INFO(0, persistent_id) - ZEND_ARG_INFO(0, callback) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getResultCode, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getResultMessage, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, with_cas) - ZEND_ARG_INFO(0, value_cb) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayedByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, with_cas) - ZEND_ARG_INFO(0, value_cb) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_fetch, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_fetchAll, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_touchByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, items, 0) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, items, 0) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) - ZEND_ARG_INFO(0, cas_token) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) - ZEND_ARG_INFO(0, cas_token) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMulti, 0, 0, 1) - ZEND_ARG_INFO(0, keys) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, keys) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_incrementByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_decrementByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0) - ZEND_ARG_INFO(0, delay) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2) - ZEND_ARG_INFO(0, host) - ZEND_ARG_INFO(0, port) - ZEND_ARG_INFO(0, weight) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getStats, 0, 0, 0) - ZEND_ARG_INFO(0, type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_addServers, 0) - ZEND_ARG_ARRAY_INFO(0, servers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getServerList, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_resetServerList, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_quit, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_flushBuffers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0) - ZEND_ARG_INFO(0, server_key) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorMessage, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorCode, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorErrno, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastDisconnectedServer, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) - ZEND_ARG_INFO(0, option) -ZEND_END_ARG_INFO() - -#ifdef HAVE_MEMCACHED_SASL -ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) - ZEND_ARG_INFO(0, username) - ZEND_ARG_INFO(0, password) -ZEND_END_ARG_INFO() -#endif - -#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY -ZEND_BEGIN_ARG_INFO(arginfo_setEncodingKey, 0) - ZEND_ARG_INFO(0, key) -ZEND_END_ARG_INFO() -#endif - -ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) - ZEND_ARG_INFO(0, option) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) - ZEND_ARG_INFO(0, host_map) - ZEND_ARG_INFO(0, forward_map) - ZEND_ARG_INFO(0, replicas) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_isPersistent, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_isPristine, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getAllKeys, 0) -ZEND_END_ARG_INFO() -/* }}} */ - -/* {{{ memcached_class_methods */ -#define MEMC_ME(name, args) PHP_ME(Memcached, name, args, ZEND_ACC_PUBLIC) -static zend_function_entry memcached_class_methods[] = { - MEMC_ME(__construct, arginfo___construct) - - MEMC_ME(getResultCode, arginfo_getResultCode) - MEMC_ME(getResultMessage, arginfo_getResultMessage) - - MEMC_ME(get, arginfo_get) - MEMC_ME(getByKey, arginfo_getByKey) - MEMC_ME(getMulti, arginfo_getMulti) - MEMC_ME(getMultiByKey, arginfo_getMultiByKey) - MEMC_ME(getDelayed, arginfo_getDelayed) - MEMC_ME(getDelayedByKey, arginfo_getDelayedByKey) - MEMC_ME(fetch, arginfo_fetch) - MEMC_ME(fetchAll, arginfo_fetchAll) - - MEMC_ME(set, arginfo_set) - MEMC_ME(setByKey, arginfo_setByKey) - - MEMC_ME(touch, arginfo_touch) - MEMC_ME(touchByKey, arginfo_touchByKey) - - MEMC_ME(setMulti, arginfo_setMulti) - MEMC_ME(setMultiByKey, arginfo_setMultiByKey) - - MEMC_ME(cas, arginfo_cas) - MEMC_ME(casByKey, arginfo_casByKey) - MEMC_ME(add, arginfo_add) - MEMC_ME(addByKey, arginfo_addByKey) - MEMC_ME(append, arginfo_append) - MEMC_ME(appendByKey, arginfo_appendByKey) - MEMC_ME(prepend, arginfo_prepend) - MEMC_ME(prependByKey, arginfo_prependByKey) - MEMC_ME(replace, arginfo_replace) - MEMC_ME(replaceByKey, arginfo_replaceByKey) - MEMC_ME(delete, arginfo_delete) - MEMC_ME(deleteMulti, arginfo_deleteMulti) - MEMC_ME(deleteByKey, arginfo_deleteByKey) - MEMC_ME(deleteMultiByKey, arginfo_deleteMultiByKey) - - MEMC_ME(increment, arginfo_increment) - MEMC_ME(decrement, arginfo_decrement) - MEMC_ME(incrementByKey, arginfo_incrementByKey) - MEMC_ME(decrementByKey, arginfo_decrementByKey) - - MEMC_ME(addServer, arginfo_addServer) - MEMC_ME(addServers, arginfo_addServers) - MEMC_ME(getServerList, arginfo_getServerList) - MEMC_ME(getServerByKey, arginfo_getServerByKey) - MEMC_ME(resetServerList, arginfo_resetServerList) - MEMC_ME(quit, arginfo_quit) - MEMC_ME(flushBuffers, arginfo_flushBuffers) - - MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) - MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) - MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) - MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) - - MEMC_ME(getStats, arginfo_getStats) - MEMC_ME(getVersion, arginfo_getVersion) - MEMC_ME(getAllKeys, arginfo_getAllKeys) - - MEMC_ME(flush, arginfo_flush) - - MEMC_ME(getOption, arginfo_getOption) - MEMC_ME(setOption, arginfo_setOption) - MEMC_ME(setOptions, arginfo_setOptions) - MEMC_ME(setBucket, arginfo_setBucket) -#ifdef HAVE_MEMCACHED_SASL - MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) -#endif -#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY - MEMC_ME(setEncodingKey, arginfo_setEncodingKey) -#endif - MEMC_ME(isPersistent, arginfo_isPersistent) - MEMC_ME(isPristine, arginfo_isPristine) - { NULL, NULL, NULL } -}; -#undef MEMC_ME -/* }}} */ - -#ifdef HAVE_MEMCACHED_PROTOCOL -/* {{{ */ -#define MEMC_SE_ME(name, args) PHP_ME(MemcachedServer, name, args, ZEND_ACC_PUBLIC) -static -zend_function_entry memcached_server_class_methods[] = { - MEMC_SE_ME(run, NULL) - MEMC_SE_ME(on, NULL) - { NULL, NULL, NULL } -}; -#undef MEMC_SE_ME -/* }}} */ +#if PHP_VERSION_ID < 80000 +#include "php_memcached_legacy_arginfo.h" +#else +#include "php_memcached_arginfo.h" #endif /* {{{ memcached_module_entry @@ -4592,7 +4202,7 @@ PHP_MINIT_FUNCTION(memcached) le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); memcached_ce = zend_register_internal_class(&ce); memcached_ce->create_object = php_memc_object_new; @@ -4602,7 +4212,7 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; memcached_server_object_handlers.free_obj = php_memc_server_free_storage; - INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); memcached_server_ce = zend_register_internal_class(&ce); memcached_server_ce->create_object = php_memc_server_new; #endif diff --git a/php_memcached.stub.php b/php_memcached.stub.php new file mode 100644 index 00000000..4ba6d5b6 --- /dev/null +++ b/php_memcached.stub.php @@ -0,0 +1,94 @@ + += 80000) die("skip PHP 7 only"); +?> --FILE-- +--FILE-- +getMessage() . PHP_EOL; +} + +class extended extends Memcached { + public function __construct () { + } +} + +error_reporting(E_ALL); +$extended = new extended (); +var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); + +echo "OK" . PHP_EOL; + +--EXPECTF-- +Memcached::__construct(): Argument #1 ($persistent_id) must be of type ?string, stdClass given + +Warning: Memcached::setOption(): Memcached constructor was not called in %s +NULL +OK + diff --git a/tests/expire.phpt b/tests/expire.phpt index eac02408..4fb49c55 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -7,6 +7,7 @@ https://code.google.com/p/memcached/issues/detail?id=275 $min_version = "1.4.8"; include dirname(__FILE__) . "/skipif.inc"; if (!method_exists("memcached", "touch")) die ("skip memcached::touch is not available"); +if (getenv("SKIP_SLOW_TESTS")) die('skip slow test'); ?> --FILE-- set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -Notice: Undefined variable: no_key in %s +%s: Undefined variable%sno_key in %s bool(false) -Notice: Undefined variable: no_value in %s +%s: Undefined variable%sno_value in %s bool(true) -Notice: Undefined variable: no_key in %s +%s: Undefined variable%sno_key in %s -Notice: Undefined variable: no_value in %s +%s: Undefined variable%sno_value in %s bool(false) -Notice: Undefined variable: no_time in %s +%s: Undefined variable%sno_time in %s bool(true) diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt index f17eb94a..a691680d 100644 --- a/tests/vbucket.phpt +++ b/tests/vbucket.phpt @@ -18,14 +18,6 @@ var_dump ($m->setBucket (array (1,2,2), array (1,2,2), 2)); var_dump ($m->setBucket (array ('a', 'b', 'c'), null, 2)); -var_dump ($m->setBucket (array (), null, 2)); - -var_dump ($m->setBucket (array (), array (), -1)); - -var_dump ($m->setBucket (null, array (), -1)); - -var_dump ($m->setBucket (array (-1), array (-1), 1)); - echo "OK\n"; ?> @@ -33,16 +25,4 @@ echo "OK\n"; bool(true) bool(true) bool(true) - -Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d -bool(false) - -Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d -bool(false) - -Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d -NULL - -Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d -bool(false) OK diff --git a/tests/vbucket_error_7.phpt b/tests/vbucket_error_7.phpt new file mode 100644 index 00000000..286534af --- /dev/null +++ b/tests/vbucket_error_7.phpt @@ -0,0 +1,40 @@ +--TEST-- +Memcached virtual buckets +--SKIPIF-- += 80000) die("skip PHP 7 only"); +?> +--FILE-- + Memcached::DISTRIBUTION_VIRTUAL_BUCKET + )); + +var_dump ($m->setBucket (array (), null, 2)); + +var_dump ($m->setBucket (array (), array (), -1)); + +var_dump ($m->setBucket (null, array (), -1)); + +var_dump ($m->setBucket (array (-1), array (-1), 1)); + +echo "OK\n"; + +?> +--EXPECTF-- + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d +NULL + +Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d +bool(false) +OK diff --git a/tests/vbucket_error_8.phpt b/tests/vbucket_error_8.phpt new file mode 100644 index 00000000..c8af2315 --- /dev/null +++ b/tests/vbucket_error_8.phpt @@ -0,0 +1,41 @@ +--TEST-- +Memcached virtual buckets +--SKIPIF-- + +--FILE-- + Memcached::DISTRIBUTION_VIRTUAL_BUCKET + )); + +var_dump ($m->setBucket (array (), null, 2)); + +var_dump ($m->setBucket (array (), array (), -1)); + +try { + var_dump ($m->setBucket (null, array (), -1)); +} catch (TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} + +var_dump ($m->setBucket (array (-1), array (-1), 1)); + +echo "OK\n"; + +?> +--EXPECTF-- +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) +Memcached::setBucket(): Argument #1 ($host_map) must be of type array, null given + +Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d +bool(false) +OK From 18945f9b5867e3c4c7016ded29801da7337301ec Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 12:37:20 +0200 Subject: [PATCH 592/694] add new file to pecl archive --- package.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.xml b/package.xml index c5588a3f..ec44bd1b 100644 --- a/package.xml +++ b/package.xml @@ -59,6 +59,9 @@ Fixes + + + @@ -133,10 +136,13 @@ Fixes + + + From baa6bfda6fbf4c1c75b5a7492db4cc40e6aa81f3 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 13:45:49 +0200 Subject: [PATCH 593/694] cleanup HAVE_SPL, removed in 8 as always there --- php_memcached.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 147cb4ab..8d9040ec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -55,6 +55,8 @@ # include "ext/msgpack/php_msgpack.h" #endif +# include "ext/spl/spl_exceptions.h" + static int le_memc; static int php_memc_list_entry(void) { @@ -251,10 +253,6 @@ static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; static zend_object_handlers memcached_object_handlers; -#ifdef HAVE_SPL -static zend_class_entry *spl_ce_RuntimeException = NULL; -#endif - ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #ifdef COMPILE_DL_MEMCACHED @@ -3764,7 +3762,6 @@ zend_class_entry *php_memc_get_exception(void) PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root) { -#ifdef HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { zend_class_entry *pce; @@ -3781,7 +3778,7 @@ zend_class_entry *php_memc_get_exception_base(int root) return spl_ce_RuntimeException; } } -#endif + return zend_exception_get_default(); } @@ -3877,10 +3874,8 @@ static const zend_module_dep memcached_deps[] = { #ifdef HAVE_MEMCACHED_MSGPACK ZEND_MOD_REQUIRED("msgpack") #endif -#ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") -#endif - {NULL, NULL, NULL} + ZEND_MOD_END }; #endif From 38ad2e0b0923230472118f97b3471529ee2353b2 Mon Sep 17 00:00:00 2001 From: Julien Boulen Date: Fri, 9 Oct 2020 11:52:03 +0200 Subject: [PATCH 594/694] Fix memcached.ini comment - remove reference to old config name (#456) Co-authored-by: julien --- memcached.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index 35548f32..c11db719 100644 --- a/memcached.ini +++ b/memcached.ini @@ -85,7 +85,6 @@ ; Session SASL username ; Both username and password need to be set for SASL to be enabled -; In addition to this memcached.use_sasl needs to be on ;memcached.sess_sasl_username = NULL ; Session SASL password From a452d9a1e59ae0bc58174d7bd8101ee440d4aa1d Mon Sep 17 00:00:00 2001 From: hulk Date: Fri, 9 Oct 2020 02:53:09 -0700 Subject: [PATCH 595/694] MOD: don't re-set the libmemcached option if not modified (#451) libmemcached would close all connections if the option(like MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) was set, even though value wasn't modified. --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 8d9040ec..4389fd2f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3104,6 +3104,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) lval = zval_get_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { + // don't reset the option when the option value wasn't modified, + // while the libmemcached may shutdown all connections. + if (memcached_behavior_get(intern->memc, flag) == (uint64_t)lval) { + return 1; + } rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); } else { From 7120d80cb9dc69a58c552ce44304c1e2f0eeaee3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 9 Oct 2020 03:23:41 -0700 Subject: [PATCH 596/694] Set TCP_NODELAY when setting binary protocol (#421) * Set TCP_NODELAY when setting binary protocol * Add braces to the check_set_behavior macro --- php_memcached.c | 5 +++++ php_memcached_session.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 4389fd2f..85799730 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1286,6 +1286,11 @@ static PHP_METHOD(Memcached, __construct) if (rc != MEMCACHED_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); } + /* Also enable TCP_NODELAY when binary protocol is enabled */ + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set TCP_NODELAY: %s", memcached_strerror(intern->memc, rc)); + } } if (MEMC_G(default_behavior.connect_timeout)) { diff --git a/php_memcached_session.c b/php_memcached_session.c index ce9a46db..e509cb84 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -178,7 +178,9 @@ void s_unlock_session(memcached_st *memc) static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { +/* This macro looks like a function but returns errors directly */ #define check_set_behavior(behavior, value) \ +{ \ int b = (behavior); \ uint64_t v = (value); \ if (v != memcached_behavior_get(memc, b)) { \ @@ -189,10 +191,13 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) } \ return 0; \ } \ - } + } \ +} if (MEMC_SESS_INI(binary_protocol_enabled)) { check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + /* Also enable TCP_NODELAY when binary protocol is enabled */ + check_set_behavior(MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); } if (MEMC_SESS_INI(consistent_hash_enabled)) { From f97b2e3ad95bbd83c862abba08c34ac3f4acc497 Mon Sep 17 00:00:00 2001 From: SpencerMalone Date: Fri, 9 Oct 2020 04:49:58 -0700 Subject: [PATCH 597/694] Include a fuller list of response constants from libmemcached (#457) --- php_memcached.c | 69 +++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 85799730..d49b7d57 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4073,34 +4073,47 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * libmemcached result codes */ - REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND); - REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END); - REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_STORED, MEMCACHED_STORED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_DELETED, MEMCACHED_DELETED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_STAT, MEMCACHED_STAT); - REGISTER_MEMC_CLASS_CONST_LONG(RES_ITEM, MEMCACHED_ITEM); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOT_SUPPORTED, MEMCACHED_NOT_SUPPORTED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_FETCH_NOTFINISHED, MEMCACHED_FETCH_NOTFINISHED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MARKED_DEAD, MEMCACHED_SERVER_MARKED_DEAD); - REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_STAT_KEY, MEMCACHED_UNKNOWN_STAT_KEY); - REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_FAILURE, MEMCACHED_CONNECTION_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_BIND_FAILURE, MEMCACHED_CONNECTION_BIND_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_READ_FAILURE, MEMCACHED_READ_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_DOES_NOT_EXIST, MEMCACHED_DATA_DOES_NOT_EXIST); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_STORED, MEMCACHED_STORED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DELETED, MEMCACHED_DELETED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_VALUE, MEMCACHED_VALUE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_STAT, MEMCACHED_STAT); + REGISTER_MEMC_CLASS_CONST_LONG(RES_ITEM, MEMCACHED_ITEM); + REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FAIL_UNIX_SOCKET, MEMCACHED_FAIL_UNIX_SOCKET); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOT_SUPPORTED, MEMCACHED_NOT_SUPPORTED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_KEY_PROVIDED, MEMCACHED_NO_KEY_PROVIDED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FETCH_NOTFINISHED, MEMCACHED_FETCH_NOTFINISHED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT); + REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MARKED_DEAD, MEMCACHED_SERVER_MARKED_DEAD); + REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_STAT_KEY, MEMCACHED_UNKNOWN_STAT_KEY); + REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_ARGUMENTS, MEMCACHED_INVALID_ARGUMENTS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARSE_ERROR, MEMCACHED_PARSE_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARSE_USER_ERROR, MEMCACHED_PARSE_USER_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DEPRECATED, MEMCACHED_DEPRECATED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_IN_PROGRESS, MEMCACHED_IN_PROGRESS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_MAXIMUM_RETURN, MEMCACHED_MAXIMUM_RETURN); REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); From 9a429d43f8a4aab9292287502a3393588e2255c1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 17 Nov 2020 12:04:15 +0100 Subject: [PATCH 598/694] Promote error "Memcached constructor was not called" to exception with PHP 8 (#465) For consistency with other PHP 8 extensions. --- php_memcached.c | 11 +++++++++++ tests/bad_construct_8.phpt | 12 +++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49b7d57..1e218a00 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -195,6 +195,7 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { php_memc_object_t* intern = NULL; \ php_memc_user_data_t* memc_user_data = NULL; +#if PHP_VERSION_ID < 80000 #define MEMC_METHOD_FETCH_OBJECT \ intern = Z_MEMC_OBJ_P(object); \ if (!intern->memc) { \ @@ -203,6 +204,16 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ (void)memc_user_data; /* avoid unused variable warning */ +#else +#define MEMC_METHOD_FETCH_OBJECT \ + intern = Z_MEMC_OBJ_P(object); \ + if (!intern->memc) { \ + zend_throw_error(NULL, "Memcached constructor was not called"); \ + RETURN_THROWS(); \ + } \ + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ + (void)memc_user_data; /* avoid unused variable warning */ +#endif static zend_bool s_memc_valid_key_binary(zend_string *key) diff --git a/tests/bad_construct_8.phpt b/tests/bad_construct_8.phpt index 81daa5a5..10928cfd 100644 --- a/tests/bad_construct_8.phpt +++ b/tests/bad_construct_8.phpt @@ -20,15 +20,17 @@ class extended extends Memcached { } error_reporting(E_ALL); -$extended = new extended (); -var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); +try { + $extended = new extended (); + var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); +} catch (Error $e) { + echo $e->getMessage() . PHP_EOL; +} echo "OK" . PHP_EOL; --EXPECTF-- Memcached::__construct(): Argument #1 ($persistent_id) must be of type ?string, stdClass given - -Warning: Memcached::setOption(): Memcached constructor was not called in %s -NULL +Memcached constructor was not called OK From 8f3c5dc0fa773aded5d169e5c5b8eab18c8931c6 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 1 Dec 2020 04:09:57 +0100 Subject: [PATCH 599/694] fix php8 arginfo (#467) --- php_memcached.stub.php | 14 +++++++------- php_memcached_arginfo.h | 28 ++++++++++++++-------------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 4ba6d5b6..e44ff4aa 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -35,16 +35,16 @@ public function cas(string $cas_token, string $key, mixed $value, int $expiratio public function casByKey(string $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function add(string $key, mixed $value, int $expiration=0): bool {} public function addByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} - public function append(string $key, string $value): bool {} - public function appendByKey(string $server_key, string $key, string $value): bool {} - public function prepend(string $key, string $value): bool {} - public function prependByKey(string $server_key, string $key, string $value): bool {} + public function append(string $key, string $value): ?bool {} + public function appendByKey(string $server_key, string $key, string $value): ?bool {} + public function prepend(string $key, string $value): ?bool {} + public function prependByKey(string $server_key, string $key, string $value): ?bool {} public function replace(string $key, mixed $value, int $expiration=0): bool {} public function replaceByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function delete(string $key, int $time=0): bool {} - public function deleteMulti(array $keys, int $time=0): bool {} + public function deleteMulti(array $keys, int $time=0): array {} public function deleteByKey(string $server_key, string $key, int $time=0): bool {} - public function deleteMultiByKey(string $server_key, array $keys, int $time=0): bool {} + public function deleteMultiByKey(string $server_key, array $keys, int $time=0): array {} public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} @@ -73,7 +73,7 @@ public function flush(int $delay=0): bool {} public function getOption(int $option): mixed {} public function setOption(int $option, mixed $value): bool {} public function setOptions(array $options): bool {} - public function setBucket(array $host_map, array $forward_map, int $replicas): bool {} + public function setBucket(array $host_map, ?array $forward_map, int $replicas): bool {} #ifdef HAVE_MEMCACHED_SASL public function setSaslAuthData(string $username, string $password): bool {} #endif diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 6729dd36..18b17cc7 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a33d23c6659922e98d3704879eb4bc820e1819df */ + * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -40,14 +40,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -109,12 +109,12 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_addByKey arginfo_class_Memcached_setByKey -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_append, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_append, 0, 2, _IS_BOOL, 1) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_appendByKey, 0, 3, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_appendByKey, 0, 3, _IS_BOOL, 1) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) @@ -133,7 +133,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_delete, 0, 1, _I ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMulti, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMulti, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -144,7 +144,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteByKey, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "NULL") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch @@ -228,7 +228,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_setBucket, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, host_map, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, forward_map, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, forward_map, IS_ARRAY, 1) ZEND_ARG_TYPE_INFO(0, replicas, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 6f21d2a8..2c0b2de3 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a33d23c6659922e98d3704879eb4bc820e1819df */ + * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From fc33513d32504843fe0864f9855d3a0b37a76ddc Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Dec 2020 09:16:42 -0800 Subject: [PATCH 600/694] Add PHP 8.0 to the Travis CI matrix, use 'nightly' builds (#462) --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d6b57d7..5478b296 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,8 @@ dist: xenial language: php php: - - master + - nightly + - 8.0 - 7.4 - 7.3 - 7.2 @@ -12,7 +13,7 @@ php: matrix: fast_finish: true allow_failures: - - php: master + - php: nightly env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial From b8202146903692e3ae2f2f7ad9915c3c03928ac3 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Thu, 17 Dec 2020 20:00:42 +0000 Subject: [PATCH 601/694] Fixed ParseError in stub file (#468) Match PHP 7 version of the file which has NULL as the default value of this bool argument. --- php_memcached.stub.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index e44ff4aa..6b84c5b7 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -17,8 +17,8 @@ public function get(string $key, callable $cache_cb=NULL, int $get_flags=0): mix public function getByKey(string $server_key, string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=0, callable $value_cb=NULL): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=0, callable $value_cb=NULL): bool {} + public function getDelayed(array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} From bfb0a66809d43080219ab5381235f848c91eff7e Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Fri, 18 Dec 2020 23:40:15 +0000 Subject: [PATCH 602/694] Re-generated .h files after stubs were modified (#469) --- php_memcached_arginfo.h | 22 +++++++++++----------- php_memcached_legacy_arginfo.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 18b17cc7..6b05cf4c 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ + * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -39,15 +39,15 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 2c0b2de3..c9426166 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ + * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From c8f9376a8b1399907e732064890101da7261d8bb Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 18 Jan 2021 16:34:41 +0100 Subject: [PATCH 603/694] fix php8 arginfo (#472) --- php_memcached.stub.php | 12 ++++++------ php_memcached_arginfo.h | 22 +++++++++++----------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 6b84c5b7..5a735b57 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -8,17 +8,17 @@ class Memcached { - public function __construct(string $persistent_id=NULL, callable $callback=NULL, string $connection_str=NULL) {} + public function __construct(string $persistent_id=null, callable $callback=null, string $connection_str=null) {} public function getResultCode(): int {} public function getResultMessage(): string {} - public function get(string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} - public function getByKey(string $server_key, string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} + public function get(string $key, callable $cache_cb=null, int $get_flags=0): mixed {} + public function getByKey(string $server_key, string $key, callable $cache_cb=null, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} + public function getDelayed(array $keys, bool $with_cas=false, callable $value_cb=null): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, callable $value_cb=null): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} @@ -64,7 +64,7 @@ public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} public function getLastDisconnectedServer(): false|array {} - public function getStats(string $type=NULL): false|array {} + public function getStats(string $type=null): false|array {} public function getVersion(): false|array {} public function getAllKeys(): false|array {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 6b05cf4c..4c8a6845 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ + * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -39,15 +39,15 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "null") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index c9426166..a615e3a6 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ + * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 19a02bb5bfaeb520b857a2d64172f7d2a9615fb3 Mon Sep 17 00:00:00 2001 From: Arjen de Korte Date: Thu, 21 Jan 2021 04:06:53 +0100 Subject: [PATCH 604/694] Don't expect tests/expire to fail (#475) The issue reported in https://code.google.com/archive/p/memcached/issues/275 was fixed more than 8 years ago and the test is no longer expected to fail --- tests/expire.phpt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/expire.phpt b/tests/expire.phpt index 4fb49c55..d53309e7 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -1,7 +1,5 @@ --TEST-- Memcached store, fetch & touch expired key ---XFAIL-- -https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- Date: Wed, 9 Jun 2021 14:53:43 +0200 Subject: [PATCH 605/694] fix incorrect zp, fixes #484 --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1e218a00..d2f23434 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1876,7 +1876,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (by_key) { /* "Sa|ll" */ - ZEND_PARSE_PARAMETERS_START(2, 4) + ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(server_key) Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL @@ -1884,7 +1884,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke ZEND_PARSE_PARAMETERS_END(); } else { /* "a|ll" */ - ZEND_PARSE_PARAMETERS_START(1, 3) + ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) From 51c9baf49f96c5f35be8257549f426ef1860f0ef Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 9 Jun 2021 14:58:37 +0200 Subject: [PATCH 606/694] fix zpp in mem_cas_impl --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d2f23434..2ea93604 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2089,8 +2089,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - /* "zSSz|ll" */ - ZEND_PARSE_PARAMETERS_START(4, 6) + /* "zSSz|l" */ + ZEND_PARSE_PARAMETERS_START(4, 5) Z_PARAM_ZVAL(zv_cas) Z_PARAM_STR(server_key) Z_PARAM_STR(key) @@ -2099,8 +2099,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_LONG(expiration) ZEND_PARSE_PARAMETERS_END(); } else { - /* "zSz|ll" */ - ZEND_PARSE_PARAMETERS_START(3, 5) + /* "zSz|l" */ + ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_ZVAL(zv_cas) Z_PARAM_STR(key) Z_PARAM_ZVAL(value) From 899e4dc27c672b1617a232e9757809bf0dd5b89a Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Jun 2021 14:30:12 +0200 Subject: [PATCH 607/694] fix test for PHP 8.1 --- tests/undefined_set.phpt | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/undefined_set.phpt b/tests/undefined_set.phpt index caeda19d..581c9406 100644 --- a/tests/undefined_set.phpt +++ b/tests/undefined_set.phpt @@ -10,30 +10,25 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = array('foo' => 'bar'); -$rv = $m->set($no_key, $value, 360); +// silent to hide: +// Warning: Undefined variable +// Deprecated: Memcached::set(): Passing null to parameter (PHP 8.1) + +$rv = @$m->set($no_key, $value, 360); var_dump($rv); -$rv = $m->set($key, $no_value, 360); +$rv = @$m->set($key, $no_value, 360); var_dump($rv); -$rv = $m->set($no_key, $no_value, 360); +$rv = @$m->set($no_key, $no_value, 360); var_dump($rv); -$rv = $m->set($key, $value, $no_time); +$rv = @$m->set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -%s: Undefined variable%sno_key in %s bool(false) - -%s: Undefined variable%sno_value in %s bool(true) - -%s: Undefined variable%sno_key in %s - -%s: Undefined variable%sno_value in %s bool(false) - -%s: Undefined variable%sno_time in %s bool(true) From 0c3f411e710a360a41c256c310f3e7440acb5add Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Jun 2021 14:30:12 +0200 Subject: [PATCH 608/694] fix test for PHP 8.1 --- tests/undefined_set.phpt | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/undefined_set.phpt b/tests/undefined_set.phpt index caeda19d..581c9406 100644 --- a/tests/undefined_set.phpt +++ b/tests/undefined_set.phpt @@ -10,30 +10,25 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = array('foo' => 'bar'); -$rv = $m->set($no_key, $value, 360); +// silent to hide: +// Warning: Undefined variable +// Deprecated: Memcached::set(): Passing null to parameter (PHP 8.1) + +$rv = @$m->set($no_key, $value, 360); var_dump($rv); -$rv = $m->set($key, $no_value, 360); +$rv = @$m->set($key, $no_value, 360); var_dump($rv); -$rv = $m->set($no_key, $no_value, 360); +$rv = @$m->set($no_key, $no_value, 360); var_dump($rv); -$rv = $m->set($key, $value, $no_time); +$rv = @$m->set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -%s: Undefined variable%sno_key in %s bool(false) - -%s: Undefined variable%sno_value in %s bool(true) - -%s: Undefined variable%sno_key in %s - -%s: Undefined variable%sno_value in %s bool(false) - -%s: Undefined variable%sno_time in %s bool(true) From c2a31946f0be9a12d2ebb54f876da9dce17c40a3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 06:52:02 -0800 Subject: [PATCH 609/694] Fix stubs to make them consistent for PHP 8 --- php_memcached.stub.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 5a735b57..1efc5877 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -8,17 +8,17 @@ class Memcached { - public function __construct(string $persistent_id=null, callable $callback=null, string $connection_str=null) {} + public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {} public function getResultCode(): int {} public function getResultMessage(): string {} - public function get(string $key, callable $cache_cb=null, int $get_flags=0): mixed {} - public function getByKey(string $server_key, string $key, callable $cache_cb=null, int $get_flags=0): mixed {} + public function get(string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} + public function getByKey(string $server_key, string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=false, callable $value_cb=null): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, callable $value_cb=null): bool {} + public function getDelayed(array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} @@ -64,7 +64,7 @@ public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} public function getLastDisconnectedServer(): false|array {} - public function getStats(string $type=null): false|array {} + public function getStats(?string $type=null): false|array {} public function getVersion(): false|array {} public function getAllKeys(): false|array {} From 7bbf4fbad3b25cb2628b96eafce50d19f22e3b47 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 07:52:54 -0800 Subject: [PATCH 610/694] Expose internal key check via checkKey() method Make ascii key check consistent with libmemcached's isgraph() check Add test to check that they match --- php_memcached.c | 20 +++++++++++++++++++- php_memcached.stub.php | 1 + php_memcached_arginfo.h | 8 +++++++- php_memcached_legacy_arginfo.h | 8 +++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2ea93604..d49cbeb4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -228,7 +228,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) size_t i, len = ZSTR_LEN(key); for (i = 0; i < len; i++) { - if (iscntrl(str[i]) || isspace(str[i])) + if (!isgraph(str[i]) || isspace(str[i])) return 0; } return 1; @@ -3450,6 +3450,24 @@ static PHP_METHOD(Memcached, isPristine) } /* }}} */ +/* {{{ bool Memcached::checkKey(string key) + Checks if a key is valid */ +PHP_METHOD(Memcached, checkKey) +{ + zend_string *key; + MEMC_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(key) + ZEND_PARSE_PARAMETERS_END(); + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); + RETURN_TRUE; +} +/* }}} */ + /**************************************** Internal support code ****************************************/ diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 1efc5877..819186f4 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -83,6 +83,7 @@ public function setEncodingKey(string $key): bool {} #endif public function isPersistent(): bool {} public function isPristine(): bool {} + public function checkKey(string $key): bool {} } #ifdef HAVE_MEMCACHED_PROTOCOL diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 4c8a6845..3373624e 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ + * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -249,6 +249,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_isPristine arginfo_class_Memcached_resetServerList +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_checkKey, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) +ZEND_END_ARG_INFO() + #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_MemcachedServer_run, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, address, IS_STRING, 0) @@ -325,6 +329,7 @@ ZEND_METHOD(Memcached, setEncodingKey); #endif ZEND_METHOD(Memcached, isPersistent); ZEND_METHOD(Memcached, isPristine); +ZEND_METHOD(Memcached, checkKey); #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_METHOD(MemcachedServer, run); #endif @@ -396,6 +401,7 @@ static const zend_function_entry class_Memcached_methods[] = { #endif ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC) ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC) + ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index a615e3a6..ad6d6562 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ + * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) @@ -245,6 +245,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_isPristine arginfo_class_Memcached_getResultCode +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_checkKey, 0, 0, 1) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MemcachedServer_run, 0, 0, 1) ZEND_ARG_INFO(0, address) @@ -321,6 +325,7 @@ ZEND_METHOD(Memcached, setEncodingKey); #endif ZEND_METHOD(Memcached, isPersistent); ZEND_METHOD(Memcached, isPristine); +ZEND_METHOD(Memcached, checkKey); #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_METHOD(MemcachedServer, run); #endif @@ -392,6 +397,7 @@ static const zend_function_entry class_Memcached_methods[] = { #endif ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC) ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC) + ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC) ZEND_FE_END }; From 7be9f007799ccdd9018176a0a3ea3cf7c7d56ab0 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 07:55:27 -0800 Subject: [PATCH 611/694] Add test --- package.xml | 1 + tests/check_key.phpt | 132 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 tests/check_key.phpt diff --git a/package.xml b/package.xml index ec44bd1b..519de583 100644 --- a/package.xml +++ b/package.xml @@ -87,6 +87,7 @@ Fixes + diff --git a/tests/check_key.phpt b/tests/check_key.phpt new file mode 100644 index 00000000..74ec6214 --- /dev/null +++ b/tests/check_key.phpt @@ -0,0 +1,132 @@ +--TEST-- +Memcached::checkKey() +--SKIPIF-- + +--FILE-- + false, + Memcached::OPT_VERIFY_KEY => true + )); + +$keys = [ + 'foo', + 'foo bar', + str_repeat('a',65), + str_repeat('b',250), + str_repeat('c',251), + 'Montréal', + 'København', + 'Düsseldorf', + 'Kraków', + 'İstanbul', + 'ﺎﺨﺘﺑﺍﺭ PHP', + '測試', + 'Тестирование', + 'پی ایچ پی کی جانچ ہو رہی ہے', + 'Testataan PHP: tä', + 'Að prófa PHP', + 'د پی ایچ پی ازمول', + 'Pruvà PHP' +]; +foreach($keys as $key) { + echo "Checking \"$key\"" . PHP_EOL; + echo "MEMC_CHECK_KEY: "; + var_dump($m->checkKey($key)); + echo "libmemcached: "; + var_dump($m->set($key, "this is a test")); + var_dump($m->getResultMessage()); + echo "\n"; +} +--EXPECT-- +Checking "foo" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "foo bar" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Montréal" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "København" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Düsseldorf" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Kraków" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "İstanbul" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "ﺎﺨﺘﺑﺍﺭ PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "測試" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Тестирование" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "پی ایچ پی کی جانچ ہو رہی ہے" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Testataan PHP: tä" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Að prófa PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "د پی ایچ پی ازمول" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Pruvà PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + From 8ed8092c7f4c07e170f38465dbf89a3447fe35cd Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:16:30 +0100 Subject: [PATCH 612/694] fix MemcachedServer related: #418, m6w6/libmemcached#94 --- php_memcached.c | 3 ++ php_memcached_server.c | 80 +++++++++++++++++++++++------------ server-example/run-server.php | 2 +- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..e7a28e0a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3520,6 +3520,8 @@ static void php_memc_server_free_storage(zend_object *object) { php_memc_server_t *intern = php_memc_server_fetch_object(object); + + php_memc_proto_handler_destroy(&intern->handler); zend_object_std_dtor(&intern->zo); } @@ -3533,6 +3535,7 @@ zend_object *php_memc_server_new(zend_class_entry *ce) object_properties_init(&intern->zo, ce); intern->zo.handlers = &memcached_server_object_handlers; + intern->handler = php_memc_proto_handler_new(); return &intern->zo; } diff --git a/php_memcached_server.c b/php_memcached_server.c index 870209c1..e816b90d 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -17,13 +17,16 @@ #include "php_memcached.h" #include "php_memcached_private.h" #include "php_memcached_server.h" +#include "php_network.h" #include -#undef NDEBUG -#undef _NDEBUG #include +#if HAVE_ARPA_INET_H +# include +#endif + #define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) @@ -58,9 +61,9 @@ typedef struct { static long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t param_count) { - zval *retval = NULL; + zval retval; - cb->fci.retval = retval; + cb->fci.retval = &retval; cb->fci.params = params; cb->fci.param_count = param_count; #if PHP_VERSION_ID < 80000 @@ -73,7 +76,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t para efree (buf); } - return retval == NULL ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(retval); + return Z_ISUNDEF(retval) ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(&retval); } // memcached protocol callbacks @@ -96,6 +99,7 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke ZVAL_LONG(&zflags, flags); ZVAL_LONG(&zexptime, exptime); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -142,6 +146,7 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event ZVAL_STRINGL(&zvalue, data, data_len); ZVAL_DOUBLE(&zcas, cas); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -198,11 +203,13 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_STRINGL(&zkey, key, key_len); - ZVAL_LONG(&zdelta, (long) delta); - ZVAL_LONG(&zinital, (long) initial); - ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_LONG(&zdelta, (zend_long) delta); + ZVAL_LONG(&zinital, (zend_long) initial); + ZVAL_LONG(&zexpiration, (zend_long) expiration); ZVAL_LONG(&zresult, 0); + ZVAL_MAKE_REF(&zresult); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -322,6 +329,13 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k } MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_NULL(&zvalue); + ZVAL_MAKE_REF(&zvalue); + ZVAL_NULL(&zflags); + ZVAL_MAKE_REF(&zflags); + ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -436,11 +450,12 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_STRINGL(&zkey, key, key_len); - ZVAL_STRINGL(&zdata, ((char *) data), (int) data_len); - ZVAL_LONG(&zflags, (long) flags); - ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_STRINGL(&zdata, data, data_len); + ZVAL_LONG(&zflags, (zend_long) flags); + ZVAL_LONG(&zexpiration, (zend_long) expiration); ZVAL_DOUBLE(&zcas, (double) cas); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -504,6 +519,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * ZVAL_STRINGL(&zkey, key, key_len); ZVAL_NULL(&zbody); + ZVAL_MAKE_REF(&zbody); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -584,17 +600,27 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) zval zremoteip, zremoteport; zval params[2]; protocol_binary_response_status retval; - - struct sockaddr_in addr_in; - socklen_t addr_in_len = sizeof(addr_in); - - if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr)); - ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); + + ZVAL_NULL(&zremoteip); + ZVAL_NULL(&zremoteport); + + if (getpeername (fd, (struct sockaddr *) &ss, &ss_len) == 0) { + char addr_buf[0x100]; + + switch (ss.ss_family) { + case AF_INET6: + ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in6 *) &ss)->sin6_addr, addr_buf, sizeof(addr_buf))); + ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in6 *) &ss)->sin6_port)); + break; + case AF_INET: + ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in *) &ss)->sin_addr, addr_buf, sizeof(addr_buf))); + ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in *) &ss)->sin_port)); + break; + } } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); - ZVAL_NULL(&zremoteip); - ZVAL_NULL(&zremoteport); } ZVAL_COPY(¶ms[0], &zremoteip); @@ -714,22 +740,20 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () } static -evutil_socket_t s_create_listening_socket (const char *spec) +evutil_socket_t s_create_listening_socket (const zend_string *spec) { evutil_socket_t sock; struct sockaddr_storage addr; - int addr_len; - + socklen_t addr_len; int rc; addr_len = sizeof (struct sockaddr); - rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); - if (rc != 0) { - php_error_docref(NULL, E_WARNING, "Failed to parse bind address"); + if (SUCCESS != php_network_parse_network_address_with_port(spec->val, spec->len, (struct sockaddr *) &addr, &addr_len)) { + php_error_docref(NULL, E_WARNING, "Failed to parse bind address: %s", spec->val); return -1; } - sock = socket (AF_INET, SOCK_STREAM, 0); + sock = socket (addr.ss_family, SOCK_STREAM, 0); if (sock < 0) { php_error_docref(NULL, E_WARNING, "socket failed: %s", strerror (errno)); return -1; @@ -770,7 +794,7 @@ evutil_socket_t s_create_listening_socket (const char *spec) zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, zend_string *address) { struct event *accept_event; - evutil_socket_t sock = s_create_listening_socket (address->val); + evutil_socket_t sock = s_create_listening_socket (address); if (sock == -1) { return 0; diff --git a/server-example/run-server.php b/server-example/run-server.php index a02c6a60..a9ba5834 100644 --- a/server-example/run-server.php +++ b/server-example/run-server.php @@ -89,4 +89,4 @@ function ($client_id) { return Memcached::RESPONSE_SUCCESS; }); -$server->run ("127.0.0.1:3434"); \ No newline at end of file +$server->run ("127.0.0.1:3434"); From 46967cc67fb7294893489b8317f5a3cc31b64079 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:32:52 +0100 Subject: [PATCH 613/694] use php_network_get_peer_name --- php_memcached_server.c | 38 ++++++++++------------------------- server-example/run-server.php | 4 ++-- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index e816b90d..fee8d28d 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -597,41 +597,25 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { - zval zremoteip, zremoteport; - zval params[2]; + zend_string *zremoteaddr_str; + zval zremoteaddr; + zval params[1]; protocol_binary_response_status retval; - struct sockaddr_storage ss; - socklen_t ss_len = sizeof(ss); - - ZVAL_NULL(&zremoteip); - ZVAL_NULL(&zremoteport); - - if (getpeername (fd, (struct sockaddr *) &ss, &ss_len) == 0) { - char addr_buf[0x100]; - - switch (ss.ss_family) { - case AF_INET6: - ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in6 *) &ss)->sin6_addr, addr_buf, sizeof(addr_buf))); - ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in6 *) &ss)->sin6_port)); - break; - case AF_INET: - ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in *) &ss)->sin_addr, addr_buf, sizeof(addr_buf))); - ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in *) &ss)->sin_port)); - break; - } + + ZVAL_NULL(&zremoteaddr); + + if (SUCCESS == php_network_get_peer_name (fd, &zremoteaddr_str, NULL, NULL)) { + ZVAL_STR(&zremoteaddr, zremoteaddr_str); } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); } - ZVAL_COPY(¶ms[0], &zremoteip); - ZVAL_COPY(¶ms[1], &zremoteport); + ZVAL_COPY(¶ms[0], &zremoteaddr); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 1); zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(&zremoteip); - zval_ptr_dtor(&zremoteport); + zval_ptr_dtor(&zremoteaddr); if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { memcached_protocol_client_destroy (client->protocol_client); diff --git a/server-example/run-server.php b/server-example/run-server.php index a9ba5834..b7612c80 100644 --- a/server-example/run-server.php +++ b/server-example/run-server.php @@ -3,8 +3,8 @@ $server = new MemcachedServer(); $server->on (Memcached::ON_CONNECT, - function ($remote_ip, $remote_port) { - echo "Incoming connection from {$remote_ip}:{$remote_port}" . PHP_EOL; + function ($remote_addr) { + echo "Incoming connection from {$remote_addr}" . PHP_EOL; return Memcached::RESPONSE_SUCCESS; }); From f4f724caf74f506b6121e87b95239a8a11795284 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:34:08 +0100 Subject: [PATCH 614/694] remove unused include again --- php_memcached_server.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index fee8d28d..ce93a2bf 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -23,10 +23,6 @@ #include -#if HAVE_ARPA_INET_H -# include -#endif - #define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) From 7381ce71b891d8500cecce91da00555366625b5c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:57:39 +0100 Subject: [PATCH 615/694] as per https://github.com/php-memcached-dev/php-memcached/pull/474#issuecomment-762934191 --- php_memcached_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached_server.c b/php_memcached_server.c index ce93a2bf..1f28d936 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -299,6 +299,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe } MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + ZVAL_LONG(&zwhen, when); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zwhen); From 57f2999ea5113b2b31523c659cfb223a8fd6a5ce Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 20 Jan 2021 10:54:13 +0100 Subject: [PATCH 616/694] add 1 test for MemcachedServer --- tests/memcachedserver.phpt | 58 +++++++++++++++++++++++ tests/server.inc | 78 +++++++++++++++++++++++++++++++ tests/server.php | 94 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 tests/memcachedserver.phpt create mode 100644 tests/server.inc create mode 100644 tests/server.php diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt new file mode 100644 index 00000000..54b7fe45 --- /dev/null +++ b/tests/memcachedserver.phpt @@ -0,0 +1,58 @@ +--TEST-- +Memcached::get() with cache callback +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('127.0.0.1', 3434); + +$cache->add("add_key", "hello", 500); +$cache->append("append_key", "world"); +$cache->prepend("prepend_key", "world"); + +$cache->increment("incr", 2, 1, 500); +$cache->decrement("decr", 2, 1, 500); + +$cache->delete("delete_k"); +$cache->flush(1); + +var_dump($cache->get('get_this')); + +$cache->set ('set_key', 'value 1', 100); +$cache->replace ('replace_key', 'value 2', 200); + +var_dump($cache->getStats()); + +$cache->quit(); + +memcached_server_stop($server); +?> +Done +--EXPECTF-- +Listening on 127.0.0.1:3434 +Incoming connection from 127.0.0.1:%s +Incoming connection from 127.0.0.1:%s +client_id=[%s]: Add key=[add_key], value=[hello], flags=[0], expiration=[500] +client_id=[%s]: Append key=[append_key], value=[world], cas=[0] +client_id=[%s]: Prepend key=[prepend_key], value=[world], cas=[0] +client_id=[%s]: Incrementing key=[incr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Decrementing key=[decr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Delete key=[delete_k], cas=[0] +client_id=[%s]: Flush when=[1] +client_id=[%s]: Get key=[get_this] +client_id=[%s]: Noop +string(20) "Hello to you client!" +client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] +client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +bool(false) +Done diff --git a/tests/server.inc b/tests/server.inc new file mode 100644 index 00000000..96cc942f --- /dev/null +++ b/tests/server.inc @@ -0,0 +1,78 @@ + STDIN, + 1 => STDOUT, + 2 => STDERR, + ); + + $cmd = "{$php_executable} {$php_args} {$code} {$host}:{$port} "; + if (substr(PHP_OS, 0, 3) == 'WIN') { + $cmd = "{$php_executable} {$php_args} {$code} {$host}:{$port} "; + + $handle = proc_open(addslashes($cmd), $descriptorspec, $pipes, __DIR__, NULL, array("bypass_shell" => true, "suppress_errors" => true)); + } else { + $cmd = "exec {$cmd} 2>/dev/null"; + + $handle = proc_open($cmd, $descriptorspec, $pipes, __DIR__); + } + + // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' + // it might not be listening yet...need to wait until fsockopen() call returns + $error = "Unable to connect to server\n"; + for ($i=0; $i < 60; $i++) { + usleep(50000); // 50ms per try + $status = proc_get_status($handle); + $fp = @fsockopen($host, $port); + // Failure, the server is no longer running + if (!($status && $status['running'])) { + $error = "Server is not running\n"; + break; + } + // Success, Connected to servers + if ($fp) { + $error = ''; + break; + } + } + + if ($fp) { + fclose($fp); + } + + if ($error) { + echo $error; + proc_terminate($handle); + exit(1); + } + + register_shutdown_function( + function($handle) { + proc_terminate($handle); + }, + $handle + ); + + return $handle; +} + +function memcached_server_stop($handle) { + $success = FALSE; + if ($handle) { + proc_terminate($handle); + /* Wait for server to shutdown */ + for ($i = 0; $i < 60; $i++) { + $status = proc_get_status($handle); + if (!($status && $status['running'])) { + $success = TRUE; + break; + } + usleep(50000); + } + } + return $success; +} + diff --git a/tests/server.php b/tests/server.php new file mode 100644 index 00000000..674f91ac --- /dev/null +++ b/tests/server.php @@ -0,0 +1,94 @@ +on (Memcached::ON_CONNECT, + function ($remote_addr) { + echo "Incoming connection from {$remote_addr}" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_ADD, + function ($client_id, $key, $value, $flags, $expiration, &$cas) { + echo "client_id=[$client_id]: Add key=[$key], value=[$value], flags=[$flags], expiration=[$expiration]" . PHP_EOL; + $cas = 15; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_APPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Append key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_PREPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Prepend key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_INCREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Incrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DECREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Decrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DELETE, + function ($client_id, $key, $cas) { + echo "client_id=[$client_id]: Delete key=[$key], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_FLUSH, + function ($client_id, $when) { + echo "client_id=[$client_id]: Flush when=[$when]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_GET, + function ($client_id, $key, &$value, &$flags, &$cas) { + echo "client_id=[$client_id]: Get key=[$key]" . PHP_EOL; + $value = "Hello to you client!"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_NOOP, + function ($client_id) { + echo "client_id=[$client_id]: Noop" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_REPLACE, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Replace key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_SET, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Set key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_STAT, + function ($client_id, $key, &$value) { + echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + $value = "Stat reply"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_QUIT, + function ($client_id) { + echo "client_id=[$client_id]: Client quit" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$addr = ($_SERVER['argv'][1] ?? "127.0.0.1:3434"); +echo "Listening on $addr" . PHP_EOL; +$server->run($addr); From d21814e647f15b654e6fa6009ef49d148e54dffc Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 20 Jan 2021 12:08:53 +0100 Subject: [PATCH 617/694] minor fix for version handler --- php_memcached_server.c | 1 + tests/memcachedserver.phpt | 5 +++-- tests/server.php | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index 1f28d936..57cb749b 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -560,6 +560,7 @@ protocol_binary_response_status s_version_handler (const void *cookie, MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_NULL(&zversion); + ZVAL_MAKE_REF(&zversion); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zversion); diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 54b7fe45..6d4abb9d 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -31,7 +31,8 @@ var_dump($cache->get('get_this')); $cache->set ('set_key', 'value 1', 100); $cache->replace ('replace_key', 'value 2', 200); -var_dump($cache->getStats()); +// TODO var_dump($cache->getVersion()); +// TODO var_dump($cache->getStats()); $cache->quit(); @@ -54,5 +55,5 @@ client_id=[%s]: Noop string(20) "Hello to you client!" client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] -bool(false) +client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index 674f91ac..c39b04e8 100644 --- a/tests/server.php +++ b/tests/server.php @@ -79,6 +79,13 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { $server->on (Memcached::ON_STAT, function ($client_id, $key, &$value) { echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + $value = "Stat reply for $key"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_VERSION, + function ($client_id, &$value) { + echo "client_id=[$client_id]: Version" . PHP_EOL; $value = "Stat reply"; return Memcached::RESPONSE_SUCCESS; }); From 0262e5c8031194736c6985f91a9ba7f2c7eea9db Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:43:57 +0100 Subject: [PATCH 618/694] handle empty STATS key --- php_memcached_server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index 57cb749b..d1e903a1 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -514,7 +514,11 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - ZVAL_STRINGL(&zkey, key, key_len); + if (key && key_len) { + ZVAL_STRINGL(&zkey, key, key_len); + } else { + ZVAL_NULL(&zkey); + } ZVAL_NULL(&zbody); ZVAL_MAKE_REF(&zbody); @@ -566,7 +570,6 @@ protocol_binary_response_status s_version_handler (const void *cookie, ZVAL_COPY(¶ms[1], &zversion); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); - if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { if (Z_TYPE(zversion) != IS_STRING) { convert_to_string(&zversion); From f064f6c817b899a7c0e8ea089c81163c66a9be05 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:51:34 +0100 Subject: [PATCH 619/694] fix running the server from command line --- tests/server.inc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/server.inc b/tests/server.inc index 96cc942f..5700a9d2 100644 --- a/tests/server.inc +++ b/tests/server.inc @@ -1,7 +1,7 @@ STDIN, @@ -29,7 +29,7 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port $fp = @fsockopen($host, $port); // Failure, the server is no longer running if (!($status && $status['running'])) { - $error = "Server is not running\n"; + $error = "Server is not running {$status['command']}\n"; break; } // Success, Connected to servers @@ -75,4 +75,3 @@ function memcached_server_stop($handle) { } return $success; } - From 941ae835441e38e61e5349969f58b120c4ec7506 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:52:31 +0100 Subject: [PATCH 620/694] add stats/version tests --- tests/memcachedserver.phpt | 31 ++++++++++++++++++++++++++++--- tests/server.php | 2 +- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 6d4abb9d..82601e12 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -1,10 +1,13 @@ --TEST-- -Memcached::get() with cache callback +MemcachedServer --SKIPIF-- --FILE-- get('get_this')); $cache->set ('set_key', 'value 1', 100); $cache->replace ('replace_key', 'value 2', 200); -// TODO var_dump($cache->getVersion()); -// TODO var_dump($cache->getStats()); +var_dump($cache->getVersion()); +var_dump($cache->getStats()); +var_dump($cache->getStats("foobar")); $cache->quit(); @@ -55,5 +59,26 @@ client_id=[%s]: Noop string(20) "Hello to you client!" client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +client_id=[%s]: Version +array(1) { + ["127.0.0.1:3434"]=> + string(5) "1.1.1" +} +client_id=[%s]: Stat key=[] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + [""]=> + string(15) "Stat reply for " + } +} +client_id=[%s]: Stat key=[foobar] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + ["foobar"]=> + string(21) "Stat reply for foobar" + } +} client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index c39b04e8..b6ab1cf6 100644 --- a/tests/server.php +++ b/tests/server.php @@ -86,7 +86,7 @@ function ($client_id, $key, &$value) { $server->on (Memcached::ON_VERSION, function ($client_id, &$value) { echo "client_id=[$client_id]: Version" . PHP_EOL; - $value = "Stat reply"; + $value = "1.1.1"; return Memcached::RESPONSE_SUCCESS; }); From bee6b53d57e18a13e21aa4d5c887b5303228a339 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 17:42:58 +0100 Subject: [PATCH 621/694] expect an array as STATS value and reply foreach key/value --- php_memcached_server.c | 36 +++++++++++++++++++++++++----------- tests/memcachedserver.phpt | 16 ++++++++++------ tests/server.php | 7 +++++-- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index d1e903a1..a166051e 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -506,7 +506,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * { zval params[3]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval zcookie, zkey, zbody; + zval zcookie, zkey, zstats; if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { return retval; @@ -519,24 +519,38 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * } else { ZVAL_NULL(&zkey); } - ZVAL_NULL(&zbody); - ZVAL_MAKE_REF(&zbody); + ZVAL_NULL(&zstats); + ZVAL_MAKE_REF(&zstats); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); - ZVAL_COPY(¶ms[2], &zbody); + ZVAL_COPY(¶ms[2], &zstats); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE(zbody) == IS_NULL) { + if (Z_ISNULL(zstats)) { retval = response_handler(cookie, NULL, 0, NULL, 0); - } - else { - if (Z_TYPE(zbody) != IS_STRING) { - convert_to_string(&zbody); + } else { + zval *zarray = &zstats; + zend_string *key; + zval *val; + + ZVAL_DEREF(zarray); + if (Z_TYPE_P(zarray) != IS_ARRAY) { + convert_to_array(zarray); + } + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zarray), key, val) + { + zend_string *val_str = zval_get_string(val); + retval = response_handler(cookie, key->val, key->len, val_str->val, val_str->len); + if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { + break; + } + zend_string_release(val_str); } - retval = response_handler(cookie, key, key_len, Z_STRVAL(zbody), (uint32_t) Z_STRLEN(zbody)); + ZEND_HASH_FOREACH_END(); } } @@ -545,7 +559,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * zval_ptr_dtor(¶ms[2]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zbody); + zval_ptr_dtor (&zstats); return retval; } diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 82601e12..d47dd73b 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -67,17 +67,21 @@ array(1) { client_id=[%s]: Stat key=[] array(1) { ["127.0.0.1:3434"]=> - array(1) { - [""]=> - string(15) "Stat reply for " + array(2) { + ["key"]=> + string(0) "" + ["foo"]=> + string(3) "bar" } } client_id=[%s]: Stat key=[foobar] array(1) { ["127.0.0.1:3434"]=> - array(1) { - ["foobar"]=> - string(21) "Stat reply for foobar" + array(2) { + ["key"]=> + string(6) "foobar" + ["foo"]=> + string(3) "bar" } } client_id=[%s]: Client quit diff --git a/tests/server.php b/tests/server.php index b6ab1cf6..f5ff2f6a 100644 --- a/tests/server.php +++ b/tests/server.php @@ -77,9 +77,12 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { }); $server->on (Memcached::ON_STAT, - function ($client_id, $key, &$value) { + function ($client_id, $key, array &$values = null) { echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; - $value = "Stat reply for $key"; + $values = [ + "key" => $key, + "foo" => "bar", + ]; return Memcached::RESPONSE_SUCCESS; }); From 984086633264d30fad442c4a2394145f9e014d1a Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 18:00:52 +0100 Subject: [PATCH 622/694] valgrind --- php_memcached.c | 5 ++++- tests/server.inc | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e7a28e0a..19af8fda 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3925,7 +3925,6 @@ static PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->session.lock_enabled = 0; php_memcached_globals->session.lock_wait_max = 150; php_memcached_globals->session.lock_wait_min = 150; @@ -3944,8 +3943,12 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.persistent_enabled = 0; php_memcached_globals->session.sasl_username = NULL; php_memcached_globals->session.sasl_password = NULL; +#endif +#ifdef HAVE_MEMCACHED_PROTOCOL + memset(&php_memcached_globals->server, 0, sizeof(php_memcached_globals->server)); #endif + php_memcached_globals->memc.serializer_name = NULL; php_memcached_globals->memc.serializer_type = SERIALIZER_DEFAULT; php_memcached_globals->memc.compression_name = NULL; diff --git a/tests/server.inc b/tests/server.inc index 5700a9d2..9678f043 100644 --- a/tests/server.inc +++ b/tests/server.inc @@ -23,7 +23,7 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' // it might not be listening yet...need to wait until fsockopen() call returns $error = "Unable to connect to server\n"; - for ($i=0; $i < 60; $i++) { + for ($i=0; $i < getenv("VALGRIND") ? 1000 : 60; $i++) { usleep(50000); // 50ms per try $status = proc_get_status($handle); $fp = @fsockopen($host, $port); @@ -46,12 +46,16 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port if ($error) { echo $error; proc_terminate($handle); + proc_close($handle); exit(1); } register_shutdown_function( function($handle) { - proc_terminate($handle); + if (is_resource($handle)) { + proc_terminate($handle); + proc_close($handle); + } }, $handle ); @@ -72,6 +76,7 @@ function memcached_server_stop($handle) { } usleep(50000); } + proc_close($handle); } return $success; } From 6dc086e721d2d843f240f69ed181575588a9c140 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 21 Jan 2021 17:28:07 +0100 Subject: [PATCH 623/694] add test files to package.xml --- package.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 519de583..8241d221 100644 --- a/package.xml +++ b/package.xml @@ -173,7 +173,10 @@ Fixes - + + + + From 4b6c45dd23be82abc2fdbf1655700ddd55c09538 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 25 Jan 2021 14:45:03 +0100 Subject: [PATCH 624/694] implement stats callback suggestions by Remi --- php_memcached_server.c | 45 +++++++++++++++++++++----------------- tests/memcachedserver.phpt | 22 +++++++++++++++++++ tests/server.php | 19 ++++++++++------ 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index a166051e..24c328f8 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -519,7 +519,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * } else { ZVAL_NULL(&zkey); } - ZVAL_NULL(&zstats); + array_init(&zstats); ZVAL_MAKE_REF(&zstats); ZVAL_COPY(¶ms[0], &zcookie); @@ -529,29 +529,34 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_ISNULL(zstats)) { - retval = response_handler(cookie, NULL, 0, NULL, 0); - } else { - zval *zarray = &zstats; - zend_string *key; - zval *val; - - ZVAL_DEREF(zarray); - if (Z_TYPE_P(zarray) != IS_ARRAY) { - convert_to_array(zarray); - } + zval *zarray = &zstats; + zend_string *key; + zend_long idx; + zval *val; + + ZVAL_DEREF(zarray); + if (Z_TYPE_P(zarray) != IS_ARRAY) { + convert_to_array(zarray); + } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zarray), key, val) - { - zend_string *val_str = zval_get_string(val); + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zarray), idx, key, val) + { + zend_string *val_str = zval_get_string(val); + + if (key) { retval = response_handler(cookie, key->val, key->len, val_str->val, val_str->len); - if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { - break; - } - zend_string_release(val_str); + } else { + char buf[0x20], *ptr, *end = &buf[sizeof(buf) - 1]; + ptr = zend_print_long_to_buf(end, idx); + retval = response_handler(cookie, ptr, end - ptr, val_str->val, val_str->len); + } + zend_string_release(val_str); + + if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { + break; } - ZEND_HASH_FOREACH_END(); } + ZEND_HASH_FOREACH_END(); } zval_ptr_dtor(¶ms[0]); diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index d47dd73b..8d6bf222 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -37,6 +37,8 @@ $cache->replace ('replace_key', 'value 2', 200); var_dump($cache->getVersion()); var_dump($cache->getStats()); var_dump($cache->getStats("foobar")); +var_dump($cache->getStats("scalar")); +var_dump($cache->getStats("numeric array")); $cache->quit(); @@ -84,5 +86,25 @@ array(1) { string(3) "bar" } } +client_id=[%s]: Stat key=[scalar] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + [0]=> + string(%d) "you want it, you get it" + } +} +client_id=[%s]: Stat key=[numeric array] +array(1) { + ["127.0.0.1:3434"]=> + array(3) { + [-1]=> + string(3) "one" + [0]=> + string(3) "two" + [1]=> + string(5) "three" + } +} client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index f5ff2f6a..bce4c0bf 100644 --- a/tests/server.php +++ b/tests/server.php @@ -77,13 +77,18 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { }); $server->on (Memcached::ON_STAT, - function ($client_id, $key, array &$values = null) { - echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; - $values = [ - "key" => $key, - "foo" => "bar", - ]; - return Memcached::RESPONSE_SUCCESS; + function ($client_id, $key, array &$values) { + echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + + if ($key === "scalar") { + $values = "you want it, you get it"; + } elseif ($key === "numeric array") { + $values = [-1 => "one", "two", "three"]; + } else { + $values["key"] = $key; + $values["foo"] = "bar"; + } + return Memcached::RESPONSE_SUCCESS; }); $server->on (Memcached::ON_VERSION, From 4e7f20cdb062537d5c4fc7ef0cf5d4e3b912fd13 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 25 Jan 2021 14:54:24 +0100 Subject: [PATCH 625/694] skip test with libmemcached < 1.1.0 --- tests/memcachedserver.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 8d6bf222..145acfba 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -8,6 +8,10 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } + +if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { + die("skip needs at least libmemcached 1.1.0\n"); +} ?> --FILE-- Date: Tue, 26 Jan 2021 11:38:12 +0100 Subject: [PATCH 626/694] add IPv6 test --- tests/memcachedserver.phpt | 4 ++ tests/memcachedserver6.phpt | 114 ++++++++++++++++++++++++++++++++++++ tests/server.php | 2 + 3 files changed, 120 insertions(+) create mode 100644 tests/memcachedserver6.phpt diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 145acfba..21ce8d64 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -40,6 +40,7 @@ $cache->replace ('replace_key', 'value 2', 200); var_dump($cache->getVersion()); var_dump($cache->getStats()); +var_dump($cache->getStats("empty")); var_dump($cache->getStats("foobar")); var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); @@ -80,6 +81,9 @@ array(1) { string(3) "bar" } } +client_id=[%s]: Stat key=[empty] +array(0) { +} client_id=[%s]: Stat key=[foobar] array(1) { ["127.0.0.1:3434"]=> diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt new file mode 100644 index 00000000..8ae0b362 --- /dev/null +++ b/tests/memcachedserver6.phpt @@ -0,0 +1,114 @@ +--TEST-- +MemcachedServer +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('[::1]', 3434); + +$cache->add("add_key", "hello", 500); +$cache->append("append_key", "world"); +$cache->prepend("prepend_key", "world"); + +$cache->increment("incr", 2, 1, 500); +$cache->decrement("decr", 2, 1, 500); + +$cache->delete("delete_k"); +$cache->flush(1); + +var_dump($cache->get('get_this')); + +$cache->set ('set_key', 'value 1', 100); +$cache->replace ('replace_key', 'value 2', 200); + +var_dump($cache->getVersion()); +var_dump($cache->getStats()); +var_dump($cache->getStats("empty")); +var_dump($cache->getStats("foobar")); +var_dump($cache->getStats("scalar")); +var_dump($cache->getStats("numeric array")); + +$cache->quit(); + +memcached_server_stop($server); +?> +Done +--EXPECTF-- +Listening on [::1]:3434 +Incoming connection from [::1]:%s +Incoming connection from [::1]:%s +client_id=[%s]: Add key=[add_key], value=[hello], flags=[0], expiration=[500] +client_id=[%s]: Append key=[append_key], value=[world], cas=[0] +client_id=[%s]: Prepend key=[prepend_key], value=[world], cas=[0] +client_id=[%s]: Incrementing key=[incr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Decrementing key=[decr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Delete key=[delete_k], cas=[0] +client_id=[%s]: Flush when=[1] +client_id=[%s]: Get key=[get_this] +client_id=[%s]: Noop +string(20) "Hello to you client!" +client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] +client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +client_id=[%s]: Version +array(1) { + ["[::1]:3434"]=> + string(5) "1.1.1" +} +client_id=[%s]: Stat key=[] +array(1) { + ["[::1]:3434"]=> + array(2) { + ["key"]=> + string(0) "" + ["foo"]=> + string(3) "bar" + } +} +client_id=[%s]: Stat key=[empty] +array(0) { +} +client_id=[%s]: Stat key=[foobar] +array(1) { + ["[::1]:3434"]=> + array(2) { + ["key"]=> + string(6) "foobar" + ["foo"]=> + string(3) "bar" + } +} +client_id=[%s]: Stat key=[scalar] +array(1) { + ["[::1]:3434"]=> + array(1) { + [0]=> + string(%d) "you want it, you get it" + } +} +client_id=[%s]: Stat key=[numeric array] +array(1) { + ["[::1]:3434"]=> + array(3) { + [-1]=> + string(3) "one" + [0]=> + string(3) "two" + [1]=> + string(5) "three" + } +} +client_id=[%s]: Client quit +Done diff --git a/tests/server.php b/tests/server.php index bce4c0bf..9a50eb06 100644 --- a/tests/server.php +++ b/tests/server.php @@ -84,6 +84,8 @@ function ($client_id, $key, array &$values) { $values = "you want it, you get it"; } elseif ($key === "numeric array") { $values = [-1 => "one", "two", "three"]; + } elseif ($key === "empty") { + $values = []; } else { $values["key"] = $key; $values["foo"] = "bar"; From 10f449752bb42459f7b29aeaf4583854ccc24678 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 26 Jan 2021 11:42:37 +0100 Subject: [PATCH 627/694] small sleep to avoid loosing message from subprocess --- tests/memcachedserver.phpt | 1 + tests/memcachedserver6.phpt | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 21ce8d64..7b058d70 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -46,6 +46,7 @@ var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); $cache->quit(); +usleep(50000); memcached_server_stop($server); ?> diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt index 8ae0b362..a2277b4a 100644 --- a/tests/memcachedserver6.phpt +++ b/tests/memcachedserver6.phpt @@ -42,6 +42,7 @@ var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); $cache->quit(); +usleep(50000); memcached_server_stop($server); ?> From 13ba74317d7a94f87b9d30e6297fb39142c04d36 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 27 Jul 2021 08:35:08 +0200 Subject: [PATCH 628/694] Improve phpinfo information - display libmemcached-awesome when used (since 1.1.1) - display both builtime and runtime versions when different --- php_memcached.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..0f42a97f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4300,7 +4300,22 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_start(); php_info_print_table_header(2, "memcached support", "enabled"); php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); - php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); + +#ifdef LIBMEMCACHED_AWESOME + if (strcmp(LIBMEMCACHED_VERSION_STRING, memcached_lib_version())) { + php_info_print_table_row(2, "libmemcached-awesome headers version", LIBMEMCACHED_VERSION_STRING); + php_info_print_table_row(2, "libmemcached-awesome library version", memcached_lib_version()); + } else { + php_info_print_table_row(2, "libmemcached-awesome version", memcached_lib_version()); + } +#else + if (strcmp(LIBMEMCACHED_VERSION_STRING, memcached_lib_version())) { + php_info_print_table_row(2, "libmemcached headers version", LIBMEMCACHED_VERSION_STRING); + php_info_print_table_row(2, "libmemcached library version", memcached_lib_version()); + } else { + php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); + } +#endif #ifdef HAVE_MEMCACHED_SASL php_info_print_table_row(2, "SASL support", "yes"); From 605a8a63a7461983512ce12601e995dad18f5a9b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 29 Jul 2021 04:55:08 +0200 Subject: [PATCH 629/694] fix zend_dtoa API change in 8.1.0beta1 (#487) --- g_fmt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/g_fmt.c b/g_fmt.c index 73f82fd0..f456790c 100644 --- a/g_fmt.c +++ b/g_fmt.c @@ -27,12 +27,17 @@ * // Teddy Grenman , 2010-05-18. */ -#include +#include char *php_memcached_g_fmt(register char *b, double x) { register int i, k; register char *s; - int decpt, j, sign; + int decpt, j; +#if PHP_VERSION_ID < 80100 + int sign; +#else + bool sign; +#endif char *b0, *s0, *se; b0 = b; From 6d457155fbdf2c8c4615c04a4beb1a7462d55097 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 23 Aug 2021 05:56:19 +0100 Subject: [PATCH 630/694] Remove "failed to set key" warning from setMulti (#490) This was introduced in https://github.com/php-memcached-dev/php-memcached/commit/6837d89494, pull https://github.com/php-memcached-dev/php-memcached/pull/214. I suspect it may have been a left-over from debugging something. The test was later changed in 6837d89494 to expect the warning in question, although other similar tests don't encounter such warning currently. It appears no other Memcached methods emit a PHP Warning when they encounter a write read or failure. Instead, they typically turn their return value into boolean false, and provide details via getResultMessage(). The introduction of this warning since php-memcached 3.0 has led to a number of confused consumers (locally #260, #409, #450, and more reports within downstream issue trackers). Closes https://github.com/php-memcached-dev/php-memcached/issues/409. --- php_memcached.c | 5 ++--- tests/experimental/setmulti_badserialize.phpt | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..069aa60d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1907,9 +1907,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke str_key = zend_string_init(tmp_key, tmp_len, 0); } - if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { - php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); - } + /* If this failed to write a value, intern stores the error for the return value */ + s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration); if (!skey) { zend_string_release (str_key); diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index eafc7772..2d8dde53 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -42,6 +42,5 @@ try { var_dump($m->getByKey('kef', 'foo')); --EXPECT-- -Memcached::setMultiByKey(): failed to set key foo 1234 int(10) From e6df8ab3f6620cf0b2d4e683753aae846a68b4e5 Mon Sep 17 00:00:00 2001 From: hulk Date: Mon, 23 Aug 2021 12:57:11 +0800 Subject: [PATCH 631/694] FIX: store_retry_count shouldn't be set implicitly (#452) It's wired that store commands would be auto-retry implicitly while the default value of store_retry_count was 2, as well as the timeout, would be 3 times in those store commands which may confuse users. IMHO, the retry should be set explicitly instead of implicitly. --- memcached.ini | 4 ++-- php_memcached.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/memcached.ini b/memcached.ini index c11db719..c54e1fd4 100644 --- a/memcached.ini +++ b/memcached.ini @@ -130,8 +130,8 @@ ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server ; environment. -; the default is 2 -;memcached.store_retry_count = 2 +; the default is 0 +;memcached.store_retry_count = 0 ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, diff --git a/php_memcached.c b/php_memcached.c index 069aa60d..0f02878c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -410,7 +410,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) - MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) From 60a8f9f8810aab2b4cff16b05667c6d4af85ef09 Mon Sep 17 00:00:00 2001 From: mszabo-wikia Date: Mon, 8 Nov 2021 18:18:14 +0100 Subject: [PATCH 632/694] Add GitHub Actions build (#492) travis-ci.org builds have ceased, so this patch adds a GitHub Actions workflow to build and test the extension, as well as a Dependabot configuration file to keep the referenced actions up to date. I've opted to slightly simplify the workflow compared to the Travis build script. For one, I have not included libmemcached protocol support, as most distros do not supply a libmemcached compiled with server protocol support, and previous discussion suggests its usefulness in the context of this extension may be limited.[1] I've also opted to remove multiversion libmemcached testing in favor of using the system libmemcached, as the referenced other versions seem to be old enough for this to hopefully not be a problem. These could conceivably be reintroduced if needed. --- [1] https://github.com/php-memcached-dev/php-memcached/issues/418#issuecomment-449587972 --- .github/dependabot.yml | 6 + .github/workflows/build-and-test.yml | 84 +++++++++ .travis.yml | 39 ---- .travis/travis.sh | 270 --------------------------- 4 files changed, 90 insertions(+), 309 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 .travis.yml delete mode 100755 .travis/travis.sh diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..12301490 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 00000000..eb19d01e --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,84 @@ +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + experimental: [false] + include: + - php: '8.1' + experimental: true + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: Install PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: none, json, igbinary, msgpack + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install libmemcached-dev memcached libsasl2-dev sasl2-bin zlib1g-dev + - name: Start memcached daemons + run: | + export SASL_CONF_PATH="/tmp/sasl2" + mkdir "${SASL_CONF_PATH}" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" + + # Create configuration + cat< "${SASL_CONF_PATH}/memcached.conf" + mech_list: PLAIN + plainlog_level: 5 + sasldb_path: ${MEMCACHED_SASL_PWDB} + EOF + + echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" + + # Run normal memcached + memcached -d -p 11211 + + # Run memcached on port 11212 with SASL support + memcached -S -d -p 11212 + - name: Build extension + run: | + phpize + ./configure \ + --enable-memcached-protocol=no \ + --enable-memcached-sasl \ + --enable-memcached-json \ + --enable-memcached-msgpack \ + --enable-memcached-igbinary + make + sudo make install + - name: Create test configuration + run: | + cat< tests/config.inc.local + /dev/null - if [ $? != 0 ]; then - echo "Missing $file from package.xml" - retval=1; - fi - done - return $retval -} - -function install_libmemcached() { - - if test -d "${LIBMEMCACHED_PREFIX}" - then - echo "Using cached libmemcached: ${LIBMEMCACHED_PREFIX}" - return - fi - - wget "https://launchpad.net/libmemcached/1.0/$%7BLIBMEMCACHED_VERSION%7D/+download/libmemcached-$%7BLIBMEMCACHED_VERSION%7D.tar.gz" -O libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - pushd "libmemcached-${LIBMEMCACHED_VERSION}" - - local protocol_flag="" - if test "x$ENABLE_PROTOOCOL" = "xyes"; then - protocol_flag="--enable-libmemcachedprotocol" - fi - - ./configure --prefix="$LIBMEMCACHED_PREFIX" $protocol_flag LDFLAGS="-lpthread" - make - make install - popd -} - -function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git - pushd igbinary - phpize - ./configure - make - make install - popd -} - -function install_msgpack() { - git clone https://github.com/msgpack/msgpack-php.git - pushd msgpack-php - phpize - ./configure - make - make install - popd -} - -function install_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - - if test -d "$prefix" - then - echo "Using cached memcached: ${prefix}" - return - fi - - wget http://www.memcached.org/files/memcached-${MEMCACHED_VERSION}.tar.gz -O memcached-${MEMCACHED_VERSION}.tar.gz - tar xfz memcached-${MEMCACHED_VERSION}.tar.gz - - pushd memcached-${MEMCACHED_VERSION} - ./configure --enable-sasl --enable-sasl-pwdb --prefix="${prefix}" - make - make install - popd -} - -function run_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - - export SASL_CONF_PATH="/tmp/sasl2" - - if test -d "${SASL_CONF_PATH}" - then - rm -rf "${SASL_CONF_PATH}" - fi - - mkdir "${SASL_CONF_PATH}" - export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" - - # Create configuration - cat< "${SASL_CONF_PATH}/memcached.conf" -mech_list: PLAIN -plainlog_level: 5 -sasldb_path: ${MEMCACHED_SASL_PWDB} -EOF - - echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" - - # Run normal memcached - "${prefix}/bin/memcached" -d -p 11211 - - # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -p 11212 -} - -function build_php_memcached() { - pear package - mkdir "$PHP_MEMCACHED_BUILD_DIR" - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C "$PHP_MEMCACHED_BUILD_DIR" - pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" - phpize - - local protocol_flag="" - if test "x$ENABLE_PROTOCOL" = "xyes"; then - protocol_flag="--enable-memcached-protocol" - fi - - local sasl_flag="--disable-memcached-sasl" - if test "x$ENABLE_SASL" = "xyes"; then - sasl_flag="--enable-memcached-sasl" - fi - - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary - make - make install - popd -} - -function create_memcached_test_configuration() { -cat< "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}/tests/config.inc.local" - " - exit 1 -fi - -if test "x$LIBMEMCACHED_VERSION" = "x"; then - echo "Usage: $0 " - exit 1 -fi - -if test "x$3" != "x"; then - MEMCACHED_VERSION=$3 -fi - -# the extension version -PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') - -# Libmemcached install dir -LIBMEMCACHED_PREFIX="${HOME}/cache/libmemcached-${LIBMEMCACHED_VERSION}" - -# Where to do the build -PHP_MEMCACHED_BUILD_DIR="/tmp/php-memcached-build" - -# Check whether to enable building with protoocol and sasl support -check_protocol_support -check_sasl_support - -echo "Enable protocol: $ENABLE_PROTOOCOL" -echo "Enable sasl: $ENABLE_SASL" - -set -e - -case $ACTION in - before_script) - # validate the package.xml - validate_package_xml || exit 1 - - # Install libmemcached version - install_libmemcached - - # Install igbinary extension - install_igbinary - - # Install msgpack extension - install_msgpack - - install_memcached - run_memcached - ;; - - script) - # Build the extension - build_php_memcached - - # Create configuration - if test "x$ENABLE_SASL" = "xyes"; then - create_memcached_test_configuration - fi - - # Run tests - set +e - run_memcached_tests || exit 1 - ;; - - *) - echo "Unknown action. Valid actions are: before_script and script" - exit 1 - ;; -esac - - - - - From d3b8ce13f13cee3017aa8a00a0cfb2e7709154d8 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Mon, 29 Nov 2021 19:58:58 +0100 Subject: [PATCH 633/694] Remove experimental for PHP 8.1 and add PHP 8.2 experimental (#494) --- .github/workflows/build-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index eb19d01e..aa1b22c7 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,10 +7,10 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] experimental: [false] include: - - php: '8.1' + - php: '8.2' experimental: true steps: - name: Checkout From 7a0623098261c4f9d20a9eb325e33474862a5524 Mon Sep 17 00:00:00 2001 From: lfeng Date: Wed, 29 Dec 2021 16:24:57 +0800 Subject: [PATCH 634/694] fix windows php8 php_stdint.h path --- php_memcached_private.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached_private.h b/php_memcached_private.h index 3e1f3586..127ff28c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,7 +48,11 @@ #include #ifdef PHP_WIN32 +#if PHP_VERSION_ID >= 80000 +#include "php_stdint.h" +#else # include "win32/php_stdint.h" +#endif #else /* Used to store the size of the block */ # if defined(HAVE_INTTYPES_H) From 5a8db865c16c95af56769c7e292fc6fe6c70635d Mon Sep 17 00:00:00 2001 From: lfeng Date: Thu, 30 Dec 2021 10:08:48 +0800 Subject: [PATCH 635/694] format code --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 127ff28c..2891d80b 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,8 +48,8 @@ #include #ifdef PHP_WIN32 -#if PHP_VERSION_ID >= 80000 -#include "php_stdint.h" +# if PHP_VERSION_ID >= 80000 +# include "php_stdint.h" #else # include "win32/php_stdint.h" #endif From 082615656f80e8654c22de97ed3017233dd18278 Mon Sep 17 00:00:00 2001 From: lfeng Date: Thu, 30 Dec 2021 14:04:09 +0800 Subject: [PATCH 636/694] format code --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 2891d80b..b4b1115b 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,8 +48,8 @@ #include #ifdef PHP_WIN32 -# if PHP_VERSION_ID >= 80000 -# include "php_stdint.h" + # if PHP_VERSION_ID >= 80000 + # include "php_stdint.h" #else # include "win32/php_stdint.h" #endif From 8a5ef9ef348f1cb6d3438072acc777b66eeb2ea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:57:02 -0800 Subject: [PATCH 637/694] Bump actions/checkout from 2 to 3 (#505) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index aa1b22c7..79b22569 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -14,7 +14,7 @@ jobs: experimental: true steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true - name: Install PHP ${{ matrix.php }} From 5bb007e62503cf2730514db742a3d47b2d28f9be Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 7 Mar 2022 14:47:06 +0100 Subject: [PATCH 638/694] Prepare 3.2.0RC1 --- package.xml | 49 +++++++++++++++++++++++++++++++++++++------------ php_memcached.h | 2 +- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/package.xml b/package.xml index 8241d221..99a1b204 100644 --- a/package.xml +++ b/package.xml @@ -27,24 +27,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2019-12-03 + + Remi Collet + remi + remi@php.net + yes + + 2022-03-07 - 3.1.5 - 3.0.0 + 3.2.0RC1 + 3.2.0 - stable - stable + beta + beta PHP -PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for -libmemcached 0.x series has been discontinued and the oldest actively tested -version is 1.0.8. It is highly recommended to use version 1.0.18 of -libmemcached. - -Fixes - * Fix build with PHP 7.4 release due to ulong typedef removal (#445) +- PHP 8.0 and 8.1 support +- store_retry_count is no more set explicitly (#452) +- fix MemcachedServer (libmemcached-awesome is recommended) +- code cleanup @@ -177,6 +180,7 @@ Fixes + @@ -213,6 +217,27 @@ Fixes + + 2019-12-03 + + 3.1.5 + 3.0.0 + + + stable + stable + + PHP + +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) + + stable diff --git a/php_memcached.h b/php_memcached.h index cccb6d47..f53f4a5c 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.5" +#define PHP_MEMCACHED_VERSION "3.2.0RC1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From e45fef86348b3fb58779f3cb601d7a0d8b425c5e Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Fri, 18 Feb 2022 00:03:42 +0200 Subject: [PATCH 639/694] Create gh_500.phpt --- package.xml | 1 + tests/gh_500.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/gh_500.phpt diff --git a/package.xml b/package.xml index 99a1b204..90844f21 100644 --- a/package.xml +++ b/package.xml @@ -107,6 +107,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/gh_500.phpt b/tests/gh_500.phpt new file mode 100644 index 00000000..366138db --- /dev/null +++ b/tests/gh_500.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test for Github issue 500 +--SKIPIF-- + +--FILE-- +addServers($newServers); + +$m->set('floatpoint', 100.2); +$n = $m->get('floatpoint'); +var_dump($n); + +$m->set('floatpoint_neg', -300.4); +$n = $m->get('floatpoint_neg'); +var_dump($n); +?> +--EXPECT-- +float(100.2) +float(-300.4) From 857b8afab80592f56349ace1f6d02f9002a1189d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 11:17:17 +0100 Subject: [PATCH 640/694] 8.x is supported + libmemcached-awesome --- README.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index 31f57b16..8819caf9 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.4. +* Supports PHP 7.0 - 8.1. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. @@ -34,9 +34,10 @@ php-memcached 2.x: * Optionally supports igbinary 1.0 or higher. * Optionally supports msgpack 0.5 or higher. -[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.18 or -higher is recommended for best performance and compatibility with memcached -servers. +[libmemcached](http://libmemcached.org/libMemcached.html) or the new +[libmemcached-awesome](https://github.com/awesomized/libmemcached) version +1.0.18 or higher is recommended for best performance and compatibility with +memcached servers. [igbinary](https://github.com/igbinary/igbinary) is a faster and more compact binary serializer for PHP data structures. When installing php-memcached from From c7433c9a53e6b8cafd28ca8a0aee6474763fc02d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 9 Mar 2022 14:22:40 +0100 Subject: [PATCH 641/694] Fix MSVC builds wrt. ssize_t The Windows SDK does not define `ssize_t`, so libmemcached does not define `HAVE_SSIZE_T`. However, PHP's config.w32.h has `#define ssize_t SSIZE_T`, so building memcached fails. We fix this by defining `HAVE_SSIZE_T` via the extension's `CFLAGS`. --- config.w32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 9c84a059..7ca3a498 100644 --- a/config.w32 +++ b/config.w32 @@ -36,7 +36,7 @@ if (PHP_MEMCACHED == "yes") { } } - EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src); + EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src, null, " /DHAVE_SSIZE_T"); ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); AC_DEFINE("MEMCACHED_EXPORTS", 1) From 1f4b029003896f8f891041070dc7f90ead45dff3 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 14:30:51 +0100 Subject: [PATCH 642/694] [ci skip] fix windows build in changelog --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 90844f21..cf13e03b 100644 --- a/package.xml +++ b/package.xml @@ -48,6 +48,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - store_retry_count is no more set explicitly (#452) - fix MemcachedServer (libmemcached-awesome is recommended) - code cleanup +- fix windows build From ca0d9392cb1f32754df99b2035fc3b3f0ddf493d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 14:34:33 +0100 Subject: [PATCH 643/694] Prepare 3.2.0RC2 --- package.xml | 4 ++-- php_memcached.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index cf13e03b..18926a80 100644 --- a/package.xml +++ b/package.xml @@ -33,9 +33,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-07 + 2022-03-09 - 3.2.0RC1 + 3.2.0RC2 3.2.0 diff --git a/php_memcached.h b/php_memcached.h index f53f4a5c..5fb082f3 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0RC1" +#define PHP_MEMCACHED_VERSION "3.2.0RC2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4694a665d23a39854cbb978a9bdbb566a2a90585 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 9 Mar 2022 14:49:44 +0100 Subject: [PATCH 644/694] Adhere to standard naming convention of Windows libs for PHP The memcached library is usually named libmemcached.lib, so we should check for this name, too. --- config.w32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 7ca3a498..51aa3bd0 100644 --- a/config.w32 +++ b/config.w32 @@ -8,7 +8,7 @@ ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer suppor if (PHP_MEMCACHED == "yes") { - if (!CHECK_LIB("memcached.lib", "memcached", PHP_MEMCACHED)) { + if (!CHECK_LIB("memcached.lib;libmemcached.lib", "memcached", PHP_MEMCACHED)) { ERROR("memcached: library 'memcached' not found"); } From d1cb3ae87be5382444322118f87324f4044d13b0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 24 Mar 2022 13:57:18 +0100 Subject: [PATCH 645/694] Prepare 3.2.0 --- package.xml | 8 ++++---- php_memcached.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.xml b/package.xml index 18926a80..761c9584 100644 --- a/package.xml +++ b/package.xml @@ -33,14 +33,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-09 + 2022-03-24 - 3.2.0RC2 + 3.2.0 3.2.0 - beta - beta + stable + stable PHP diff --git a/php_memcached.h b/php_memcached.h index 5fb082f3..dfb3444d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0RC2" +#define PHP_MEMCACHED_VERSION "3.2.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 09e094d3909ceb97bd98ccb658b5a7b6637650a4 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 24 Mar 2022 14:02:06 +0100 Subject: [PATCH 646/694] back to dev --- package.xml | 27 +++++++++++++++++++++------ php_memcached.h | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 761c9584..9dc283be 100644 --- a/package.xml +++ b/package.xml @@ -35,7 +35,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2022-03-24 - 3.2.0 + 3.2.1dev 3.2.0 @@ -44,11 +44,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- PHP 8.0 and 8.1 support -- store_retry_count is no more set explicitly (#452) -- fix MemcachedServer (libmemcached-awesome is recommended) -- code cleanup -- fix windows build +- @@ -219,6 +215,25 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2022-03-24 + + 3.2.0 + 3.2.0 + + + stable + stable + + PHP + +- PHP 8.0 and 8.1 support +- store_retry_count is no more set explicitly (#452) +- fix MemcachedServer (libmemcached-awesome is recommended) +- code cleanup +- fix windows build + + 2019-12-03 diff --git a/php_memcached.h b/php_memcached.h index dfb3444d..e966d19d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0" +#define PHP_MEMCACHED_VERSION "3.2.1-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 1f22de74379208d9758ba99a9bd7373eefeb48f2 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 28 Mar 2022 08:09:29 +0200 Subject: [PATCH 647/694] fix #513 skip test with old and dead libmemcached --- tests/memcachedserver.phpt | 1 - tests/memcachedserver6.phpt | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 7b058d70..407fcf97 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -8,7 +8,6 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } - if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { die("skip needs at least libmemcached 1.1.0\n"); } diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt index a2277b4a..3d02b244 100644 --- a/tests/memcachedserver6.phpt +++ b/tests/memcachedserver6.phpt @@ -8,6 +8,9 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } +if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { + die("skip needs at least libmemcached 1.1.0\n"); +} ?> --FILE-- Date: Fri, 3 Jun 2022 16:56:00 +0200 Subject: [PATCH 648/694] fix ${var} deprecation --- tests/touch_binary.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 382c1778..059ec74c 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -28,12 +28,12 @@ function status_print ($op, $mem, $expected) $code = $mem->getResultcode(); if ($code == $expected) - echo "${op} status code as expected" . PHP_EOL; + echo "{$op} status code as expected" . PHP_EOL; else { $expected = resolve_to_constant ($expected); $code = resolve_to_constant ($code); - echo "${op} status code mismatch, expected ${expected} but got ${code}" . PHP_EOL; + echo "{$op} status code mismatch, expected {$expected} but got {$code}" . PHP_EOL; } } From ce2dfa5e649e01e4b4df925ebaef95ca75a3f353 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 28 Jul 2022 09:28:33 +0200 Subject: [PATCH 649/694] mark password as a sensitive param for 8.2 (#516) * mark password as a sensitive param for 8.2 --- php_memcached.c | 7 +++---- php_memcached.stub.php | 6 +++--- php_memcached_arginfo.h | 37 +++++++++++++++++++++++++++++----- php_memcached_legacy_arginfo.h | 30 ++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 73deaf64..7ccc9b58 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3898,6 +3898,7 @@ PHP_METHOD(MemcachedServer, on) #if PHP_VERSION_ID < 80000 #include "php_memcached_legacy_arginfo.h" #else +#include "zend_attributes.h" #include "php_memcached_arginfo.h" #endif @@ -4254,8 +4255,7 @@ PHP_MINIT_FUNCTION(memcached) le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); - memcached_ce = zend_register_internal_class(&ce); + memcached_ce = register_class_Memcached(); memcached_ce->create_object = php_memc_object_new; #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4264,8 +4264,7 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; memcached_server_object_handlers.free_obj = php_memc_server_free_storage; - INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); - memcached_server_ce = zend_register_internal_class(&ce); + memcached_server_ce = register_class_MemcachedServer(); memcached_server_ce->create_object = php_memc_server_new; #endif diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 819186f4..a44b1801 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -3,9 +3,9 @@ /** * @generate-function-entries * @generate-legacy-arginfo + * @generate-class-entries */ - class Memcached { public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {} @@ -75,7 +75,7 @@ public function setOption(int $option, mixed $value): bool {} public function setOptions(array $options): bool {} public function setBucket(array $host_map, ?array $forward_map, int $replicas): bool {} #ifdef HAVE_MEMCACHED_SASL - public function setSaslAuthData(string $username, string $password): bool {} + public function setSaslAuthData(string $username, #[\SensitiveParameter] string $password): bool {} #endif #ifdef HAVE_MEMCACHED_SET_ENCODING_KEY @@ -86,7 +86,7 @@ public function isPristine(): bool {} public function checkKey(string $key): bool {} } -#ifdef HAVE_MEMCACHED_PROTOCOL +#if defined(HAVE_MEMCACHED_PROTOCOL) class MemcachedServer { public function run(string $address): bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 3373624e..3108e39f 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ + * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -406,12 +406,39 @@ static const zend_function_entry class_Memcached_methods[] = { }; -static const zend_function_entry class_MemcachedServer_methods[] = { #if defined(HAVE_MEMCACHED_PROTOCOL) +static const zend_function_entry class_MemcachedServer_methods[] = { ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC) -#endif -#if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC) -#endif ZEND_FE_END }; +#endif + +static zend_class_entry *register_class_Memcached(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); +#if (PHP_VERSION_ID >= 80200) + +#if defined(HAVE_MEMCACHED_SASL) + + zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setsaslauthdata", sizeof("setsaslauthdata") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); +#endif +#endif + + return class_entry; +} + +#if defined(HAVE_MEMCACHED_PROTOCOL) +static zend_class_entry *register_class_MemcachedServer(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} +#endif diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index ad6d6562..6bb8e2d6 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ + * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) @@ -402,12 +402,32 @@ static const zend_function_entry class_Memcached_methods[] = { }; -static const zend_function_entry class_MemcachedServer_methods[] = { #if defined(HAVE_MEMCACHED_PROTOCOL) +static const zend_function_entry class_MemcachedServer_methods[] = { ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC) -#endif -#if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC) -#endif ZEND_FE_END }; +#endif + +static zend_class_entry *register_class_Memcached(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} + +#if defined(HAVE_MEMCACHED_PROTOCOL) +static zend_class_entry *register_class_MemcachedServer(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} +#endif From 3ff7436dd9ff6b7951f5e9e93cc35242b41a26a8 Mon Sep 17 00:00:00 2001 From: LeoLee Date: Wed, 31 Aug 2022 03:41:08 +0800 Subject: [PATCH 650/694] Windows msgpack support (#518) Co-authored-by: lfeng --- config.w32 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 51aa3bd0..76d4ee3c 100644 --- a/config.w32 +++ b/config.w32 @@ -5,6 +5,7 @@ ARG_ENABLE('memcached', 'libmemcached extension', 'no'); ARG_ENABLE('memcached-session', 'whether to enable memcached session handler support', 'no'); ARG_ENABLE('memcached-igbinary', 'whether to enable memcached igbinary serializer support', 'no'); ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer support', 'no'); +ARG_ENABLE('memcached-msgpack', 'whether to enable memcached msgpack serializer support', 'no'); if (PHP_MEMCACHED == "yes") { @@ -35,7 +36,13 @@ if (PHP_MEMCACHED == "yes") { ERROR("memcached: header 'igbinary.h' not found"); } } - + if (PHP_MEMCACHED_MSGPACK != "no"){ + AC_DEFINE("HAVE_MEMCACHED_MSGPACK",1); + ADD_EXTENSION_DEP("memcached", "msgpack", true); + if (!CHECK_HEADER_ADD_INCLUDE("php_msgpack.h", "CFLAGS_MEMCACHED")) { + ERROR("memcached: header 'php_msgpack.h' not found"); + } + } EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src, null, " /DHAVE_SSIZE_T"); ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); From aa4868d0f1e91ad08f59fa93c60756587a26f8e5 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 27 Sep 2022 16:35:41 +0100 Subject: [PATCH 651/694] Put false in union types at the end --- php_memcached.stub.php | 26 +++++++++++++------------- php_memcached_arginfo.h | 16 ++++++++-------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index a44b1801..80cd44ca 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -15,12 +15,12 @@ public function getResultMessage(): string {} public function get(string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} public function getByKey(string $server_key, string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} - public function getMulti(array $keys, int $get_flags=0): false|array {} - public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} + public function getMulti(array $keys, int $get_flags=0): array|false {} + public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): array|false {} public function getDelayed(array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} - public function fetch(): false|array {} - public function fetchAll(): false|array {} + public function fetch(): array|false {} + public function fetchAll(): array|false {} public function set(string $key, mixed $value, int $expiration=0): bool {} public function setByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} @@ -46,15 +46,15 @@ public function deleteMulti(array $keys, int $time=0): array {} public function deleteByKey(string $server_key, string $key, int $time=0): bool {} public function deleteMultiByKey(string $server_key, array $keys, int $time=0): array {} - public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} + public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} public function addServer(string $host, int $port, int $weight=0): bool {} public function addServers(array $servers): bool {} public function getServerList(): array {} - public function getServerByKey(string $server_key): false|array {} + public function getServerByKey(string $server_key): array|false {} public function resetServerList(): bool {} public function quit(): bool {} public function flushBuffers(): bool {} @@ -62,11 +62,11 @@ public function flushBuffers(): bool {} public function getLastErrorMessage(): string {} public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} - public function getLastDisconnectedServer(): false|array {} + public function getLastDisconnectedServer(): array|false {} - public function getStats(?string $type=null): false|array {} - public function getVersion(): false|array {} - public function getAllKeys(): false|array {} + public function getStats(?string $type=null): array|false {} + public function getVersion(): array|false {} + public function getAllKeys(): array|false {} public function flush(int $delay=0): bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 3108e39f..2b6ef282 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ + * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -26,12 +26,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") @@ -50,7 +50,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_END_ARG_INFO() #define arginfo_class_Memcached_fetchAll arginfo_class_Memcached_fetch @@ -150,7 +150,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_FALSE|MAY_BE_LONG) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, initial_value, IS_LONG, 0, "0") @@ -159,7 +159,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_decrement arginfo_class_Memcached_increment -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_FALSE|MAY_BE_LONG) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1") @@ -182,7 +182,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getServerList, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -201,7 +201,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "null") ZEND_END_ARG_INFO() diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 6bb8e2d6..81edffa0 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ + * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 121473118ab13b4993c6623f4a63a7e91ce61261 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 14 Nov 2022 08:43:03 +0100 Subject: [PATCH 652/694] Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token --- php_memcached.stub.php | 4 ++-- php_memcached_arginfo.h | 6 +++--- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 80cd44ca..7e85ef32 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -31,8 +31,8 @@ public function touchByKey(string $server_key, string $key, int $expiration=0): public function setMulti(array $items, int $expiration=0): bool {} public function setMultiByKey(string $server_key, array $items, int $expiration=0): bool {} - public function cas(string $cas_token, string $key, mixed $value, int $expiration=0): bool {} - public function casByKey(string $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} + public function cas(string|int|float $cas_token, string $key, mixed $value, int $expiration=0): bool {} + public function casByKey(string|int|float $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function add(string $key, mixed $value, int $expiration=0): bool {} public function addByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function append(string $key, string $value): ?bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 2b6ef282..e8b999de 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ + * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -91,14 +91,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_setMultiByKey, 0 ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_cas, 0, 3, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, expiration, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_casByKey, 0, 4, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 81edffa0..66d5bb91 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ + * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 38c38d7b47074b3007a67c2d2b435011872469e8 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 16 Nov 2022 07:56:04 +0100 Subject: [PATCH 653/694] changelog --- package.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 9dc283be..6a14b96c 100644 --- a/package.xml +++ b/package.xml @@ -44,7 +44,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- +- mark password as a sensitive param for PHP 8.2 +- Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token From 3b0070aab2e5984e9ad322df51449b570f85bbc9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 6 Jan 2023 14:32:41 -0800 Subject: [PATCH 654/694] CI: Add PHP 8.2 to the required matrix, add PHP 8.3 to experimental (#529) --- .github/workflows/build-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 79b22569..a5995e3a 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,10 +7,10 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] experimental: [false] include: - - php: '8.2' + - php: '8.3' experimental: true steps: - name: Checkout From 04a0f72eaafc0ac4ba646b57761b8d7331cdc82a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 9 Jan 2023 11:07:54 -0800 Subject: [PATCH 655/694] CI: Add libmemcached-awesome to matrix (#530) --- .github/workflows/build-and-test.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a5995e3a..7384dd88 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -10,6 +10,9 @@ jobs: php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] experimental: [false] include: + - php: '8.2' + awesome: true + experimental: true - php: '8.3' experimental: true steps: @@ -25,7 +28,21 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install libmemcached-dev memcached libsasl2-dev sasl2-bin zlib1g-dev + sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev + - if: ${{ ! matrix.awesome }} + name: Install libmemcached-dev (from distro) + run: sudo apt-get install libmemcached-dev + - if: ${{ matrix.awesome }} + name: Install libmemcached-awesome (from source) + run: | + curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.3.tar.gz + mkdir libmemcached + tar --strip-components=1 -xf libmemcached.tgz -C libmemcached + mkdir build-libmemcached + cd build-libmemcached + cmake -D ENABLE_HASH_HSIEH=ON -D ENABLE_SASL=ON ../libmemcached + make + sudo make install - name: Start memcached daemons run: | export SASL_CONF_PATH="/tmp/sasl2" From 6a58af6abc3edbe3d4848f80e54e1fb5cb821ba4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Jan 2023 18:50:05 +0100 Subject: [PATCH 656/694] Add minimal Windows CI (#532) For now, only building the extension is supported. --- .github/workflows/build-windows.yml | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/build-windows.yml diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..36cf7cba --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,37 @@ +name: Build on Windows +on: [push, pull_request] +jobs: + windows: + defaults: + run: + shell: cmd + strategy: + matrix: + version: ['7.4', '8.0', '8.1'] + arch: [x64, x86] + ts: [nts, zts] + runs-on: windows-latest + steps: + - name: Checkout memcached + uses: actions/checkout@v2 + - name: Setup PHP + id: setup-php + uses: cmb69/setup-php-sdk@v0.7 + with: + version: ${{matrix.version}} + arch: ${{matrix.arch}} + ts: ${{matrix.ts}} + deps: zlib + - name: Fetch libmemcached + run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + - name: Enable Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{matrix.arch}} + toolset: ${{steps.setup-php.outputs.toolset}} + - name: phpize + run: phpize + - name: configure + run: configure --enable-memcached --enable-memcached-session --enable-memcached-json --with-prefix=${{steps.setup-php.outputs.prefix}} + - name: make + run: nmake From 1eac9f8b8e8998f2feefc47d3aa80cfe93da22af Mon Sep 17 00:00:00 2001 From: LeoLee Date: Wed, 1 Feb 2023 06:45:26 +0800 Subject: [PATCH 657/694] PHP 8 compatibility Windows (#528) Use PHP_VERSION_ID instead of _MSC_VER to select the right headers. win32/php_stdint.h was removed in PHP 8.0.0 and php_stdint.h file was removed in PHP 8.2.0 entirely: https://github.com/php/php-src/blob/PHP-8.2/UPGRADING.INTERNALS#L26 --- php_memcached_private.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index b4b1115b..48f1dfab 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,11 +48,11 @@ #include #ifdef PHP_WIN32 - # if PHP_VERSION_ID >= 80000 - # include "php_stdint.h" -#else -# include "win32/php_stdint.h" -#endif + # if PHP_VERSION_ID >= 80000 + # include + #else + # include "win32/php_stdint.h" + #endif #else /* Used to store the size of the block */ # if defined(HAVE_INTTYPES_H) From 811c8a142239242f928419d349eea092536c24aa Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 2 Feb 2023 20:42:07 +0100 Subject: [PATCH 658/694] Fix #522 Signed integer overflow (#526) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 7ccc9b58..ece54408 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -86,7 +86,7 @@ static int php_memc_list_entry(void) { /**************************************** Payload value flags ****************************************/ -#define MEMC_CREATE_MASK(start, n_bits) (((1 << n_bits) - 1) << start) +#define MEMC_CREATE_MASK(start, n_bits) (((1U << n_bits) - 1) << start) #define MEMC_MASK_TYPE MEMC_CREATE_MASK(0, 4) #define MEMC_MASK_INTERNAL MEMC_CREATE_MASK(4, 12) From 6926c53ac32a579b38a0dcc3c8aec662f8cd9dd5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Apr 2023 11:15:46 -0700 Subject: [PATCH 659/694] README.markdown: PHP 8.2 is supported --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 8819caf9..b17b7e55 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 8.1. +* Supports PHP 7.0 - 8.2 or higher. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From 58335902966f37f82548210556095a11759bcc60 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 27 Apr 2023 11:32:10 -0400 Subject: [PATCH 660/694] zstd support (#539) This adds zstd compression support. The current two options, zlib and fastlz is basically a choice between performance and compression ratio. You would choose zlib if you are memory-bound and fastlz if you are cpu-bound. With zstd, you get the performance of fastlz with the compression of zlib. And often it wins on both. See this benchmark I ran on json files of varying sizes: https://gist.github.com/rlerdorf/788f3d0144f9c5514d8fee9477cbe787 Taking just a 40k json blob, we see that zstd at compression level 3 reduces it to 8862 bytes. Our current zlib 1 gets worse compression at 10091 bytes and takes longer both to compress and decompress. C Size ratio% C MB/s D MB/s SCORE Name File 8037 19.9 0.58 2130.89 0.08 zstd 22 file-39.54k-json 8204 20.3 31.85 2381.59 0.01 zstd 10 file-39.54k-json 8371 20.7 47.52 547.12 0.01 zlib 9 file-39.54k-json 8477 20.9 74.84 539.83 0.01 zlib 6 file-39.54k-json 8862 21.9 449.86 2130.89 0.01 zstd 3 file-39.54k-json 9171 22.7 554.62 2381.59 0.01 zstd 1 file-39.54k-json 10091 24.9 153.94 481.99 0.01 zlib 1 file-39.54k-json 10646 26.3 43.39 8097.40 0.01 lz4 16 file-39.54k-json 10658 26.3 72.30 8097.40 0.01 lz4 10 file-39.54k-json 13004 32.1 1396.10 6747.83 0.01 lz4 1 file-39.54k-json 13321 32.9 440.08 1306.03 0.01 fastlz 2 file-39.54k-json 14807 36.6 444.91 1156.77 0.01 fastlz 1 file-39.54k-json 15517 38.3 1190.79 4048.70 0.02 zstd -10 file-39.54k-json The fact that decompression a dramatically faster with zstd is a win for most common memcache uses since they tend to be read-heavy. The PR also adds a `memcache.compression_level` INI switch which currently only applies to zstd compression. It could probably be made to also apply to zlib and fastlz. --- config.m4 | 10 ++++ php_memcached.c | 78 ++++++++++++++++++++++++++++++- php_memcached_private.h | 4 +- tests/compression_conditions.phpt | 2 + tests/compression_types.phpt | 34 ++++++++++++++ 5 files changed, 125 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index c7a15f11..0e4ef8cf 100644 --- a/config.m4 +++ b/config.m4 @@ -27,6 +27,9 @@ PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, [ --with-system-fastlz Use system FastLZ library], no, no) +PHP_ARG_WITH(zstd, whether to use system zstd library, +[ --with-zstd Use system zstd library], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir=DIR Set the path to ZLIB install prefix.], no) @@ -345,6 +348,13 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} fastlz/fastlz.c" fi + if test "$PHP_ZSTD" != "no"; then + AC_CHECK_HEADERS([zstd.h], [ac_cv_have_zstd="yes"], [ac_cv_have_zstd="no"]) + PHP_CHECK_LIBRARY(zstd, ZSTD_compress, + [PHP_ADD_LIBRARY(zstd, 1, MEMCACHED_SHARED_LIBADD)], + [AC_MSG_ERROR(zstd library not found)]) + fi + if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi diff --git a/php_memcached.c b/php_memcached.c index ece54408..e7d5736c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,6 +37,10 @@ #endif #include +#ifdef HAVE_ZSTD_H +#include +#endif + #ifdef HAVE_JSON_API # include "ext/json/php_json.h" #endif @@ -77,6 +81,7 @@ static int php_memc_list_entry(void) { #define MEMC_OPT_COMPRESSION_TYPE -1004 #define MEMC_OPT_STORE_RETRY_COUNT -1005 #define MEMC_OPT_USER_FLAGS -1006 +#define MEMC_OPT_COMPRESSION_LEVEL -1007 /**************************************** Custom result codes @@ -107,6 +112,7 @@ static int php_memc_list_entry(void) { #define MEMC_VAL_COMPRESSED (1<<0) #define MEMC_VAL_COMPRESSION_ZLIB (1<<1) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) +#define MEMC_VAL_COMPRESSION_ZSTD (1<<3) #define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4) #define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL)) @@ -152,6 +158,7 @@ typedef struct { zend_long serializer; zend_long compression_type; + zend_long compression_level; zend_long store_retry_count; zend_long set_udf_flags; @@ -278,6 +285,10 @@ static PHP_INI_MH(OnUpdateCompressionType) MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(ZSTR_VAL(new_value), "zlib")) { MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; +#ifdef HAVE_ZSTD_H + } else if (!strcmp(ZSTR_VAL(new_value), "zstd")) { + MEMC_G(compression_type) = COMPRESSION_TYPE_ZSTD; +#endif } else { return FAILURE; } @@ -408,6 +419,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name) MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) + MEMC_INI_ENTRY("compression_level", "3", OnUpdateLong, compression_level) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) @@ -897,6 +909,19 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } break; +#ifdef HAVE_ZSTD_H + case COMPRESSION_TYPE_ZSTD: + { + compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), MEMC_G(compression_level)); + + if (!ZSTD_isError(compressed_size)) { + compress_status = 1; + compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD; + } + } + break; +#endif + case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; @@ -2939,6 +2964,9 @@ static PHP_METHOD(Memcached, getOption) case MEMC_OPT_COMPRESSION_TYPE: RETURN_LONG(memc_user_data->compression_type); + case MEMC_OPT_COMPRESSION_LEVEL: + RETURN_LONG(memc_user_data->compression_level); + case MEMC_OPT_COMPRESSION: RETURN_BOOL(memc_user_data->compression_enabled); @@ -3001,6 +3029,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_COMPRESSION_TYPE: lval = zval_get_long(value); if (lval == COMPRESSION_TYPE_FASTLZ || +#ifdef HAVE_ZSTD_H + lval == COMPRESSION_TYPE_ZSTD || +#endif lval == COMPRESSION_TYPE_ZLIB) { memc_user_data->compression_type = lval; } else { @@ -3608,16 +3639,24 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 uint32_t stored_length; unsigned long length; zend_bool decompress_status = 0; - zend_bool is_fastlz = 0, is_zlib = 0; + zend_bool is_fastlz = 0, is_zlib = 0, is_zstd = 0; if (payload_len < sizeof (uint32_t)) { return NULL; } is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ); + is_zstd = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZSTD); is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); - if (!is_fastlz && !is_zlib) { +#ifndef HAVE_ZSTD_H + if (is_zstd) { + php_error_docref(NULL, E_WARNING, "could not decompress value: value was compressed with zstd but zstd support has not been compiled in"); + return NULL; + } +#endif + + if (!is_fastlz && !is_zlib && !is_zstd) { php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type"); return NULL; } @@ -3629,6 +3668,23 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 buffer = zend_string_alloc (stored_length, 0); +#ifdef HAVE_ZSTD_H + if (is_zstd) { + length = ZSTD_getFrameContentSize(payload, payload_len); + if (length == ZSTD_CONTENTSIZE_ERROR) { + php_error_docref(NULL, E_WARNING, "value was not compressed by zstd"); + zend_string_release (buffer); + return NULL; + } else if (length == ZSTD_CONTENTSIZE_UNKNOWN) { + php_error_docref(NULL, E_WARNING, "zstd streaming decompression not supported"); + zend_string_release (buffer); + return NULL; + } + decompress_status = !ZSTD_isError(ZSTD_decompress(&buffer->val, buffer->len, payload, payload_len)); + + } + else +#endif if (is_fastlz) { decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); } @@ -3955,6 +4011,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_threshold = 2000; php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; + php_memcached_globals->memc.compression_level = 3; php_memcached_globals->memc.store_retry_count = 2; php_memcached_globals->memc.sasl_initialised = 0; @@ -4000,6 +4057,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION); REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_LEVEL, MEMC_OPT_COMPRESSION_LEVEL); REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); @@ -4015,6 +4073,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0); #endif + /* + * Indicate whether zstd compression is available + */ +#ifdef HAVE_ZSTD_H + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 1); +#else + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 0); +#endif + /* * Indicate whether json serializer is available */ @@ -4186,6 +4253,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_FASTLZ, COMPRESSION_TYPE_FASTLZ); REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZLIB, COMPRESSION_TYPE_ZLIB); + REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZSTD, COMPRESSION_TYPE_ZSTD); /* * Flags. @@ -4351,6 +4419,12 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "msgpack support", "no"); #endif +#ifdef HAVE_ZSTD_H + php_info_print_table_row(2, "zstd support", "yes"); +#else + php_info_print_table_row(2, "zstd support", "no"); +#endif + php_info_print_table_end(); DISPLAY_INI_ENTRIES(); diff --git a/php_memcached_private.h b/php_memcached_private.h index 48f1dfab..aefaf4fb 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -98,7 +98,8 @@ typedef enum { typedef enum { COMPRESSION_TYPE_ZLIB = 1, - COMPRESSION_TYPE_FASTLZ = 2 + COMPRESSION_TYPE_FASTLZ = 2, + COMPRESSION_TYPE_ZSTD = 3 } php_memc_compression_type; typedef struct { @@ -186,6 +187,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_long compression_threshold; double compression_factor; zend_long store_retry_count; + zend_long compression_level; /* Converted values*/ php_memc_serializer_type serializer_type; diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt index 749ebe8a..960058b6 100644 --- a/tests/compression_conditions.phpt +++ b/tests/compression_conditions.phpt @@ -21,6 +21,8 @@ function get_compression($name) { return Memcached::COMPRESSION_ZLIB; case 'fastlz': return Memcached::COMPRESSION_FASTLZ; + case 'zstd': + return Memcached::COMPRESSION_ZSTD; default: echo "Strange compression type: $name\n"; return 0; diff --git a/tests/compression_types.phpt b/tests/compression_types.phpt index ce07aed5..81d7867c 100644 --- a/tests/compression_types.phpt +++ b/tests/compression_types.phpt @@ -15,6 +15,10 @@ function get_compression($name) { return Memcached::COMPRESSION_ZLIB; case 'fastlz': return Memcached::COMPRESSION_FASTLZ; + case 'zstd': + if (Memcached::HAVE_ZSTD) { + return Memcached::COMPRESSION_ZSTD; + } else return 0; default: echo "Strange compression type: $name\n"; return 0; @@ -54,6 +58,26 @@ fetch_with_compression($m, 'hello6', $data, '', 'fastlz'); fetch_with_compression($m, 'hello7', $data, 'zlib', ''); fetch_with_compression($m, 'hello8', $data, 'fastlz', ''); fetch_with_compression($m, 'hello9', $data, '', ''); +if (Memcached::HAVE_ZSTD) { +fetch_with_compression($m, 'hello10', $data, 'zstd', 'zstd'); +fetch_with_compression($m, 'hello11', $data, 'zstd', 'fastlz'); +fetch_with_compression($m, 'hello12', $data, 'fastlz', 'zstd'); +fetch_with_compression($m, 'hello13', $data, '', 'zstd'); +fetch_with_compression($m, 'hello14', $data, 'zstd', ''); +} else { + echo << --EXPECT-- set=[zlib] get=[zlib] @@ -74,3 +98,13 @@ set=[fastlz] get=[] bool(true) set=[] get=[] bool(true) +set=[zstd] get=[zstd] +bool(true) +set=[zstd] get=[fastlz] +bool(true) +set=[fastlz] get=[zstd] +bool(true) +set=[] get=[zstd] +bool(true) +set=[zstd] get=[] +bool(true) From 7348cc11f729432116b652ccddb87011d553ca42 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Thu, 27 Apr 2023 18:35:07 +0300 Subject: [PATCH 661/694] Move working tests up a folder (#503) Tests in the experimental/ folder were not executed on CI. The ones that work move up, the few that remain in experimental/ need further investigation to get working or remove. --- tests/{experimental => }/add_bykey.phpt | 6 +- .../addserver_unixdomain.phpt | 2 +- tests/{experimental => }/append_bykey.phpt | 4 +- tests/{experimental => }/cas_bykey.phpt | 4 +- tests/{experimental => }/cas_invalid_key.phpt | 6 +- tests/{experimental => }/delete_bykey.phpt | 6 +- .../deletemulti_nonstringkeys.phpt | 4 +- tests/experimental/get_bykey_cas.phpt | 70 ------------------- tests/{experimental => }/fetch.phpt | 4 +- .../fetch_badunserialize.phpt | 15 +++- .../fetchall_badunserialize.phpt | 15 +++- tests/{experimental => }/get.phpt | 6 +- tests/{experimental => }/get_bykey.phpt | 6 +- tests/get_bykey_cas.phpt | 61 ++++++++++++++++ .../getdelayed_badserver.phpt | 2 +- .../getdelayed_badunserialize.phpt | 15 +++- .../{experimental => }/getdelayed_bykey.phpt | 4 +- .../getdelayed_bykey_cas.phpt | 34 +++++---- .../getdelayed_nonstring_keys.phpt | 4 +- .../getmulti_badserver.phpt | 8 +-- .../getmulti_badunserialize.phpt | 12 +++- tests/{experimental => }/getmulti_bykey.phpt | 4 +- tests/{experimental => }/getmulti_empty.phpt | 4 +- .../getmulti_partial_error.phpt | 4 +- tests/{experimental => }/getversion.phpt | 4 +- tests/{experimental => }/locale_float.phpt | 4 +- tests/{experimental => }/moduleinfo.phpt | 2 +- tests/{experimental => }/prepend_bykey.phpt | 4 +- tests/{experimental => }/replace_bykey.phpt | 4 +- tests/{experimental => }/set_bykey.phpt | 6 +- .../set_comp_below_factor.phpt | 4 +- .../set_default_serializer.phpt | 2 +- .../set_invalid_serializer.phpt | 2 +- .../setget_zero_factor.phpt | 4 +- tests/{experimental => }/setmulti_bykey.phpt | 4 +- 35 files changed, 190 insertions(+), 150 deletions(-) rename tests/{experimental => }/add_bykey.phpt (84%) rename tests/{experimental => }/addserver_unixdomain.phpt (87%) rename tests/{experimental => }/append_bykey.phpt (78%) rename tests/{experimental => }/cas_bykey.phpt (84%) rename tests/{experimental => }/cas_invalid_key.phpt (65%) rename tests/{experimental => }/delete_bykey.phpt (82%) rename tests/{experimental => }/deletemulti_nonstringkeys.phpt (87%) delete mode 100644 tests/experimental/get_bykey_cas.phpt rename tests/{experimental => }/fetch.phpt (93%) rename tests/{experimental => }/fetch_badunserialize.phpt (76%) rename tests/{experimental => }/fetchall_badunserialize.phpt (76%) rename tests/{experimental => }/get.phpt (78%) rename tests/{experimental => }/get_bykey.phpt (75%) create mode 100644 tests/get_bykey_cas.phpt rename tests/{experimental => }/getdelayed_badserver.phpt (87%) rename tests/{experimental => }/getdelayed_badunserialize.phpt (77%) rename tests/{experimental => }/getdelayed_bykey.phpt (89%) rename tests/{experimental => }/getdelayed_bykey_cas.phpt (76%) rename tests/{experimental => }/getdelayed_nonstring_keys.phpt (90%) rename tests/{experimental => }/getmulti_badserver.phpt (85%) rename tests/{experimental => }/getmulti_badunserialize.phpt (77%) rename tests/{experimental => }/getmulti_bykey.phpt (82%) rename tests/{experimental => }/getmulti_empty.phpt (60%) rename tests/{experimental => }/getmulti_partial_error.phpt (84%) rename tests/{experimental => }/getversion.phpt (69%) rename tests/{experimental => }/locale_float.phpt (80%) rename tests/{experimental => }/moduleinfo.phpt (86%) rename tests/{experimental => }/prepend_bykey.phpt (78%) rename tests/{experimental => }/replace_bykey.phpt (82%) rename tests/{experimental => }/set_bykey.phpt (83%) rename tests/{experimental => }/set_comp_below_factor.phpt (74%) rename tests/{experimental => }/set_default_serializer.phpt (95%) rename tests/{experimental => }/set_invalid_serializer.phpt (92%) rename tests/{experimental => }/setget_zero_factor.phpt (70%) rename tests/{experimental => }/setmulti_bykey.phpt (87%) diff --git a/tests/experimental/add_bykey.phpt b/tests/add_bykey.phpt similarity index 84% rename from tests/experimental/add_bykey.phpt rename to tests/add_bykey.phpt index 195fe96d..1c1521d2 100644 --- a/tests/experimental/add_bykey.phpt +++ b/tests/add_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::addByKey() --SKIPIF-- - + --FILE-- delete('foo'); @@ -15,7 +15,7 @@ echo $m->getResultMessage(), "\n"; var_dump($m->addByKey('foo', '', 1, 10)); echo $m->getResultMessage(), "\n"; // This is OK for the binary protocol -$rv = $m->addByKey('foo', ' asd ���', 1, 1); +$rv = $m->addByKey('foo', ' asd åäö', 1, 1); if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) { if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) { var_dump($rv); diff --git a/tests/experimental/addserver_unixdomain.phpt b/tests/addserver_unixdomain.phpt similarity index 87% rename from tests/experimental/addserver_unixdomain.phpt rename to tests/addserver_unixdomain.phpt index 4848015d..7e16834c 100644 --- a/tests/experimental/addserver_unixdomain.phpt +++ b/tests/addserver_unixdomain.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::addServer() unix doamin socket --SKIPIF-- - + --CLEAN-- + --FILE-- setOption(Memcached::OPT_COMPRESSION, false); diff --git a/tests/experimental/cas_bykey.phpt b/tests/cas_bykey.phpt similarity index 84% rename from tests/experimental/cas_bykey.phpt rename to tests/cas_bykey.phpt index 0a9da94e..32808813 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/cas_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::casByKey() --SKIPIF-- - + --FILE-- delete('cas_test'); diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt similarity index 65% rename from tests/experimental/cas_invalid_key.phpt rename to tests/cas_invalid_key.phpt index 6011c4b8..b8a815dc 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/cas_invalid_key.phpt @@ -1,17 +1,17 @@ --TEST-- Memcached::cas() with strange key --SKIPIF-- - + --FILE-- cas(0, '', true, 10)); echo $m->getResultMessage(), "\n"; -var_dump($m->cas(0, ' �� jas kjjhask d ', true, 10)); # no spaces allowed +var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- diff --git a/tests/experimental/delete_bykey.phpt b/tests/delete_bykey.phpt similarity index 82% rename from tests/experimental/delete_bykey.phpt rename to tests/delete_bykey.phpt index 807af8ca..929ffbc1 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/delete_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::deleteByKey() --SKIPIF-- - + --FILE-- setByKey('keffe', 'eisaleeoo', "foo"); @@ -21,7 +21,7 @@ var_dump($m->deleteByKey('keffe', '')); echo $m->getResultMessage(), "\n"; var_dump($m->deleteByKey('', 'keffe')); echo $m->getResultMessage(), "\n"; -var_dump($m->deleteByKey('keffe', '���as�� �a�sd�f asdf')); # no spaces allowed +var_dump($m->deleteByKey('keffe', 'äöåasäö åaösdäf asdf')); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- string(3) "foo" diff --git a/tests/experimental/deletemulti_nonstringkeys.phpt b/tests/deletemulti_nonstringkeys.phpt similarity index 87% rename from tests/experimental/deletemulti_nonstringkeys.phpt rename to tests/deletemulti_nonstringkeys.phpt index 2dac8920..8e275e9c 100644 --- a/tests/experimental/deletemulti_nonstringkeys.phpt +++ b/tests/deletemulti_nonstringkeys.phpt @@ -1,10 +1,10 @@ --TEST-- Delete multi with integer keys --SKIPIF-- - + --FILE-- ---FILE-- -set('foo', 1, 10); - -$cas = null; -var_dump($m->getByKey('foo', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$cas = null; -var_dump($m->getByKey('', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->set('bar', "asdf", 10); - -$cas = null; -var_dump($m->getByKey('foo', 'bar', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->delete('foo'); -$cas = null; -var_dump($m->getByKey(' � foo jkh a s ���', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$cas = null; -var_dump($m->getByKey(' � foo jkh a s ���', '', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->delete('foo'); -$cas = null; -var_dump($m->getByKey('foo', 'foo', 'the_callback', $cas)); -var_dump($cas); -var_dump($m->getByKey('foo', 'foo')); ---EXPECTF-- -int(1) -float(%d) -SUCCESS -int(1) -float(%d) -SUCCESS -string(4) "asdf" -float(%d) -SUCCESS -bool(false) -float(0) -NOT FOUND -bool(false) -NULL -A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE -called -string(4) "1234" -float(0) -string(4) "1234" diff --git a/tests/experimental/fetch.phpt b/tests/fetch.phpt similarity index 93% rename from tests/experimental/fetch.phpt rename to tests/fetch.phpt index 13136c5b..68977466 100644 --- a/tests/experimental/fetch.phpt +++ b/tests/fetch.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached getDelayed() and fetch() with and without cas --SKIPIF-- - + --FILE-- + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } $data = new Foo(); diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/fetchall_badunserialize.phpt similarity index 76% rename from tests/experimental/fetchall_badunserialize.phpt rename to tests/fetchall_badunserialize.phpt index 5684763f..815c9e21 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/fetchall_badunserialize.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } $data = new Foo(); diff --git a/tests/experimental/get.phpt b/tests/get.phpt similarity index 78% rename from tests/experimental/get.phpt rename to tests/get.phpt index 308bda98..71889064 100644 --- a/tests/experimental/get.phpt +++ b/tests/get.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::get() --SKIPIF-- - + --FILE-- delete('foo'); @@ -20,7 +20,7 @@ var_dump($m->get('foo')); echo $m->getResultMessage(), "\n"; $m->delete('foo'); -var_dump($m->get(' � foo jkh a s ���')); +var_dump($m->get(' ä foo jkh a s åäö')); echo $m->getResultMessage(), "\n"; --EXPECT-- bool(false) diff --git a/tests/experimental/get_bykey.phpt b/tests/get_bykey.phpt similarity index 75% rename from tests/experimental/get_bykey.phpt rename to tests/get_bykey.phpt index a392aaeb..704e8f04 100644 --- a/tests/experimental/get_bykey.phpt +++ b/tests/get_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getByKey() --SKIPIF-- - + --FILE-- set('foo', 1, 10); @@ -20,7 +20,7 @@ var_dump($m->getByKey('foo', 'bar')); echo $m->getResultMessage(), "\n"; $m->delete('foo'); -var_dump($m->getByKey(' � foo jkh a s ���', 'foo')); +var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo')); echo $m->getResultMessage(), "\n"; --EXPECTF-- diff --git a/tests/get_bykey_cas.phpt b/tests/get_bykey_cas.phpt new file mode 100644 index 00000000..90b566c4 --- /dev/null +++ b/tests/get_bykey_cas.phpt @@ -0,0 +1,61 @@ +--TEST-- +Memcached::getByKey() with CAS +--SKIPIF-- + +--FILE-- +set('foo', 1, 10); + +$v = $m->getByKey('foo', 'foo', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$v = $m->getByKey('', 'foo', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$m->set('bar', "asdf", 10); + +$v = $m->getByKey('foo', 'bar', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$m->delete('foo'); +var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo', null, Memcached::GET_EXTENDED)); +echo $m->getResultMessage(), "\n"; + +var_dump($m->getByKey(' ä foo jkh a s åäö', '', null, Memcached::GET_EXTENDED)); +echo $m->getResultMessage(), "\n"; + +$m->delete('foo'); +var_dump($m->getByKey('foo', 'foo', 'the_callback', Memcached::GET_EXTENDED)); +var_dump($m->getByKey('foo', 'foo')); +--EXPECTF-- +int(1) +int(%d) +SUCCESS +int(1) +int(%d) +SUCCESS +string(4) "asdf" +int(%d) +SUCCESS +bool(false) +NOT FOUND +bool(false) +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE +called +bool(false) +bool(false) \ No newline at end of file diff --git a/tests/experimental/getdelayed_badserver.phpt b/tests/getdelayed_badserver.phpt similarity index 87% rename from tests/experimental/getdelayed_badserver.phpt rename to tests/getdelayed_badserver.phpt index c4902174..5d274efb 100644 --- a/tests/experimental/getdelayed_badserver.phpt +++ b/tests/getdelayed_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getDelayedByKey() with bad server --SKIPIF-- - + --FILE-- + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } function mycb($memc, $key, $value) { diff --git a/tests/experimental/getdelayed_bykey.phpt b/tests/getdelayed_bykey.phpt similarity index 89% rename from tests/experimental/getdelayed_bykey.phpt rename to tests/getdelayed_bykey.phpt index a29f646b..442320a2 100644 --- a/tests/experimental/getdelayed_bykey.phpt +++ b/tests/getdelayed_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getDelayedByKey() --SKIPIF-- - + --FILE-- + --FILE-- getDelayedByKey('kef', array_keys($data), true, 'myfunc'); ?> --EXPECTF-- -array(3) { +array(4) { ["key"]=> string(3) "foo" ["value"]=> string(8) "foo-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "bar" ["value"]=> string(8) "bar-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "baz" ["value"]=> string(8) "baz-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "lol" ["value"]=> string(8) "lol-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "kek" ["value"]=> string(8) "kek-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } diff --git a/tests/experimental/getdelayed_nonstring_keys.phpt b/tests/getdelayed_nonstring_keys.phpt similarity index 90% rename from tests/experimental/getdelayed_nonstring_keys.phpt rename to tests/getdelayed_nonstring_keys.phpt index 81363f3b..005d0579 100644 --- a/tests/experimental/getdelayed_nonstring_keys.phpt +++ b/tests/getdelayed_nonstring_keys.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached getDelayed non string keys --SKIPIF-- - + --FILE-- + --FILE-- getResultCode()) { } --EXPECTF-- -array(0) { -} +bool(false) NO SERVERS DEFINED -array(0) { -} +bool(false) %d: %s diff --git a/tests/experimental/getmulti_badunserialize.phpt b/tests/getmulti_badunserialize.phpt similarity index 77% rename from tests/experimental/getmulti_badunserialize.phpt rename to tests/getmulti_badunserialize.phpt index 963e9730..280feed3 100644 --- a/tests/experimental/getmulti_badunserialize.phpt +++ b/tests/getmulti_badunserialize.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() with bad unserialize --SKIPIF-- - + --FILE-- set('bar', "12", 10)); diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/getmulti_bykey.phpt similarity index 82% rename from tests/experimental/getmulti_bykey.phpt rename to tests/getmulti_bykey.phpt index 3f7a6f78..b615dc66 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/getmulti_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMultiByKey() --SKIPIF-- - + --FILE-- set('foo', 1, 10); diff --git a/tests/experimental/getmulti_empty.phpt b/tests/getmulti_empty.phpt similarity index 60% rename from tests/experimental/getmulti_empty.phpt rename to tests/getmulti_empty.phpt index 6279104d..3550e814 100644 --- a/tests/experimental/getmulti_empty.phpt +++ b/tests/getmulti_empty.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() with empty array --SKIPIF-- - + --FILE-- getMulti(array()); diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/getmulti_partial_error.phpt similarity index 84% rename from tests/experimental/getmulti_partial_error.phpt rename to tests/getmulti_partial_error.phpt index fa392e9e..928f49f4 100644 --- a/tests/experimental/getmulti_partial_error.phpt +++ b/tests/getmulti_partial_error.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() partial error --SKIPIF-- - + --FILE-- + --FILE-- getVersion()); -include dirname(dirname(__FILE__)) . "/config.inc"; +include dirname(__FILE__) . "/config.inc"; $m = memc_get_instance (); $stats = $m->getVersion(); diff --git a/tests/experimental/locale_float.phpt b/tests/locale_float.phpt similarity index 80% rename from tests/experimental/locale_float.phpt rename to tests/locale_float.phpt index c071d974..2f25ea73 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/locale_float.phpt @@ -2,14 +2,14 @@ Float should not consider locale --SKIPIF-- --FILE-- diff --git a/tests/experimental/prepend_bykey.phpt b/tests/prepend_bykey.phpt similarity index 78% rename from tests/experimental/prepend_bykey.phpt rename to tests/prepend_bykey.phpt index 87d3fd38..482899de 100644 --- a/tests/experimental/prepend_bykey.phpt +++ b/tests/prepend_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::appendByKey() --SKIPIF-- - + --FILE-- setOption(Memcached::OPT_COMPRESSION, false); diff --git a/tests/experimental/replace_bykey.phpt b/tests/replace_bykey.phpt similarity index 82% rename from tests/experimental/replace_bykey.phpt rename to tests/replace_bykey.phpt index cddf10f0..b844824c 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/replace_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::replaceByKey() --SKIPIF-- - + --FILE-- + --FILE-- setByKey('foo', 'foo', 1, 10)); @@ -14,7 +14,7 @@ echo $m->getResultMessage(), "\n"; var_dump($m->setByKey('foo', '', 1, 10)); echo $m->getResultMessage(), "\n"; // This is OK for the binary protocol -$rv = $m->setByKey('foo', ' asd ���', 1, 1); +$rv = $m->setByKey('foo', ' asd åäö', 1, 1); if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) { if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) { var_dump($rv); diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/set_comp_below_factor.phpt similarity index 74% rename from tests/experimental/set_comp_below_factor.phpt rename to tests/set_comp_below_factor.phpt index 12e6d6a4..80d28006 100644 --- a/tests/experimental/set_comp_below_factor.phpt +++ b/tests/set_comp_below_factor.phpt @@ -1,10 +1,10 @@ --TEST-- Compress below factor and fail to plain. --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- Date: Thu, 27 Apr 2023 10:48:49 -0500 Subject: [PATCH 662/694] Add option to locally enforce payload size limit (#515) Add a configuration option to enforce an item size limit on the client side. This avoids sending large items over the wire and getting rejected by the server which can cause delays. The default is 0 for no limit. The same error code RES_E2BIG is used for the client side limit as for the server side limit. --- memcached.ini | 6 +++++ php_memcached.c | 45 ++++++++++++++++++++++++++++++++++++++ php_memcached_private.h | 5 +++-- tests/cas_e2big.phpt | 32 +++++++++++++++++++++++++++ tests/options.phpt | 32 +++++++++++++++++++++++++++ tests/set_large.phpt | 4 +++- tests/set_large_e2big.phpt | 27 +++++++++++++++++++++++ tests/setoptions.phpt | 3 +++ 8 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 tests/cas_e2big.phpt create mode 100644 tests/set_large_e2big.phpt diff --git a/memcached.ini b/memcached.ini index c54e1fd4..5decf399 100644 --- a/memcached.ini +++ b/memcached.ini @@ -133,6 +133,12 @@ ; the default is 0 ;memcached.store_retry_count = 0 +; The maximum payload size in bytes that can be written. +; Writing a payload larger than the limit will result in RES_E2BIG error. +; Specifying 0 means no limit is enforced, though the server may still reject with RES_E2BIG. +; Default is 0. +;memcached.item_size_limit = 1000000 + ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, ; use memcached.sess_consistent_hash instead) diff --git a/php_memcached.c b/php_memcached.c index e7d5736c..9c5ba8aa 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -82,6 +82,7 @@ static int php_memc_list_entry(void) { #define MEMC_OPT_STORE_RETRY_COUNT -1005 #define MEMC_OPT_USER_FLAGS -1006 #define MEMC_OPT_COMPRESSION_LEVEL -1007 +#define MEMC_OPT_ITEM_SIZE_LIMIT -1008 /**************************************** Custom result codes @@ -162,6 +163,7 @@ typedef struct { zend_long store_retry_count; zend_long set_udf_flags; + zend_long item_size_limit; #ifdef HAVE_MEMCACHED_SASL zend_bool has_sasl_data; @@ -423,6 +425,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) + MEMC_INI_ENTRY("item_size_limit", "0", OnUpdateLongGEZero, item_size_limit) MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) @@ -1127,6 +1130,21 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t return payload; } +static +zend_bool s_is_payload_too_big(php_memc_object_t *intern, zend_string *payload) +{ + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + /* An item size limit of 0 implies no limit enforced */ + if (memc_user_data->item_size_limit == 0) { + return 0; + } + if (ZSTR_LEN(payload) > memc_user_data->item_size_limit) { + return 1; + } + return 0; +} + static zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return status) { @@ -1153,6 +1171,12 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); return 0; } + + if (s_is_payload_too_big(intern, payload)) { + s_memc_set_status(intern, MEMCACHED_E2BIG, 0); + zend_string_release(payload); + return 0; + } } #define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; @@ -1305,6 +1329,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); memc_user_data->set_udf_flags = -1; + memc_user_data->item_size_limit = MEMC_G(item_size_limit); memc_user_data->is_persistent = is_persistent; memcached_set_user_data(intern->memc, memc_user_data); @@ -2145,6 +2170,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } + if (s_is_payload_too_big(intern, payload)) { + intern->rescode = MEMCACHED_E2BIG; + zend_string_release(payload); + RETURN_FALSE; + } + if (by_key) { status = memcached_cas_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } else { @@ -2970,6 +3001,9 @@ static PHP_METHOD(Memcached, getOption) case MEMC_OPT_COMPRESSION: RETURN_BOOL(memc_user_data->compression_enabled); + case MEMC_OPT_ITEM_SIZE_LIMIT: + RETURN_LONG(memc_user_data->item_size_limit); + case MEMC_OPT_PREFIX_KEY: { memcached_return retval; @@ -3041,6 +3075,15 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } break; + case MEMC_OPT_ITEM_SIZE_LIMIT: + lval = zval_get_long(value); + if (lval < 0) { + php_error_docref(NULL, E_WARNING, "ITEM_SIZE_LIMIT must be >= 0"); + return 0; + } + memc_user_data->item_size_limit = lval; + break; + case MEMC_OPT_PREFIX_KEY: { zend_string *str; @@ -4013,6 +4056,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_factor = 1.30; php_memcached_globals->memc.compression_level = 3; php_memcached_globals->memc.store_retry_count = 2; + php_memcached_globals->memc.item_size_limit = 0; php_memcached_globals->memc.sasl_initialised = 0; php_memcached_globals->no_effect = 0; @@ -4063,6 +4107,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_USER_FLAGS, MEMC_OPT_USER_FLAGS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_ITEM_SIZE_LIMIT, MEMC_OPT_ITEM_SIZE_LIMIT); /* * Indicate whether igbinary serializer is available diff --git a/php_memcached_private.h b/php_memcached_private.h index aefaf4fb..93c20570 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -186,8 +186,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *compression_name; zend_long compression_threshold; double compression_factor; - zend_long store_retry_count; - zend_long compression_level; + zend_long store_retry_count; + zend_long compression_level; + zend_long item_size_limit; /* Converted values*/ php_memc_serializer_type serializer_type; diff --git a/tests/cas_e2big.phpt b/tests/cas_e2big.phpt new file mode 100644 index 00000000..99c3562b --- /dev/null +++ b/tests/cas_e2big.phpt @@ -0,0 +1,32 @@ +--TEST-- +set data exceeding size limit +--SKIPIF-- + +--FILE-- + 100, +)); + +$m->delete('cas_e2big_test'); + +$m->set('cas_e2big_test', 'hello'); +$result = $m->get('cas_e2big_test', null, Memcached::GET_EXTENDED); +var_dump(is_array($result) && isset($result['cas']) && isset($result['value']) && $result['value'] == 'hello'); + +$value = str_repeat('a large payload', 1024 * 1024); + +var_dump($m->cas($result['cas'], 'cas_e2big_test', $value, 360)); +var_dump($m->getResultCode() == Memcached::RES_E2BIG); +var_dump($m->getResultMessage() == 'ITEM TOO BIG'); +var_dump($m->get('cas_e2big_test') == 'hello'); +var_dump($m->getResultCode() == Memcached::RES_SUCCESS); +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/tests/options.phpt b/tests/options.phpt index ce895385..a096c8f1 100644 --- a/tests/options.phpt +++ b/tests/options.phpt @@ -26,6 +26,26 @@ var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSIO var_dump($m->setOption(Memcached::OPT_COMPRESSION_TYPE, 0)); var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSION_FASTLZ); + +echo "item_size_limit setOption\n"; +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 0)); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, -1)); +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 1000000)); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); + +echo "item_size_limit ini\n"; +ini_set('memcached.item_size_limit', '0'); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); + +ini_set('memcached.item_size_limit', '1000000'); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); + +ini_set('memcached.item_size_limit', null); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); ?> --EXPECTF-- bool(true) @@ -41,3 +61,15 @@ bool(true) bool(true) bool(false) bool(true) +item_size_limit setOption +bool(true) +bool(true) + +Warning: Memcached::setOption(): ITEM_SIZE_LIMIT must be >= 0 in %s on line %d +bool(false) +bool(true) +bool(true) +item_size_limit ini +bool(true) +bool(true) +bool(true) diff --git a/tests/set_large.phpt b/tests/set_large.phpt index f3cb4cc3..ba9fbca1 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -5,7 +5,9 @@ set large data --FILE-- 0, +)); $key = 'foobarbazDEADC0DE'; $value = str_repeat("foo bar", 1024 * 1024); diff --git a/tests/set_large_e2big.phpt b/tests/set_large_e2big.phpt new file mode 100644 index 00000000..498231e4 --- /dev/null +++ b/tests/set_large_e2big.phpt @@ -0,0 +1,27 @@ +--TEST-- +set data exceeding size limit +--SKIPIF-- + +--FILE-- + 100, +)); + +$m->delete('set_large_e2big_test'); + +$value = str_repeat('a large payload', 1024 * 1024); + +var_dump($m->set('set_large_e2big_test', $value)); +var_dump($m->getResultCode() == Memcached::RES_E2BIG); +var_dump($m->getResultMessage() == 'ITEM TOO BIG'); +var_dump($m->get('set_large_e2big_test') === false); +var_dump($m->getResultCode() == Memcached::RES_NOTFOUND); +?> +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/tests/setoptions.phpt b/tests/setoptions.phpt index 4bf39d14..9cefd138 100644 --- a/tests/setoptions.phpt +++ b/tests/setoptions.phpt @@ -13,12 +13,14 @@ var_dump($m->setOptions(array( Memcached::OPT_COMPRESSION => 0, Memcached::OPT_LIBKETAMA_COMPATIBLE => 1, Memcached::OPT_CONNECT_TIMEOUT => 5000, + Memcached::OPT_ITEM_SIZE_LIMIT => 1000000, ))); var_dump($m->getOption(Memcached::OPT_PREFIX_KEY) == 'a_prefix'); var_dump($m->getOption(Memcached::OPT_SERIALIZER) == Memcached::SERIALIZER_PHP); var_dump($m->getOption(Memcached::OPT_COMPRESSION) == 0); var_dump($m->getOption(Memcached::OPT_LIBKETAMA_COMPATIBLE) == 1); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); echo "test invalid options\n"; @@ -36,6 +38,7 @@ bool(true) bool(true) bool(true) bool(true) +bool(true) test invalid options Warning: Memcached::setOptions(): invalid configuration option in %s on line %d From 7fefcb792423906bba2bac66a49194f98bf11aa6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 3 May 2023 19:10:38 -0400 Subject: [PATCH 663/694] Make the compression_level at settable option and expand it to zlib (#540) Make it possible to use setOption to set Memcached::OPT_COMPRESSION_LEVEL which was missed in the original zstd PR #539 zlib compression was using the default zlib compression level of 6. With this PR it is now possible to choose other levels for zlib as well. The default remains at 6 so nothing will change for people upgrading unless they explicitly set a different level. Here is some more benchmarking data using php serialized data https://gist.github.com/rlerdorf/b9bae385446d5a30b65e6e241e34d0a8 fastlz is not really useful at any value size anymore. Anybody looking for lightning quick compression and decompression should use zstd at level 1. compression_level is not applied to fastlz because it only has 2 levels and php-memcached already switches from level 1 to 2 automatically for values larger than 65535 bytes. Forcing it to one or the other doesn't seem useful. --- php_memcached.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9c5ba8aa..00d5e3d4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -884,7 +884,7 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal ****************************************/ static -zend_bool s_compress_value (php_memc_compression_type compression_type, zend_string **payload_in, uint32_t *flags) +zend_bool s_compress_value (php_memc_compression_type compression_type, zend_long compression_level, zend_string **payload_in, uint32_t *flags) { /* status */ zend_bool compress_status = 0; @@ -915,7 +915,13 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str #ifdef HAVE_ZSTD_H case COMPRESSION_TYPE_ZSTD: { - compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), MEMC_G(compression_level)); + compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); + + if (compression_level < -22) { + compression_level = -22; + } else if (compression_level > 22) { + compression_level = 22; + } if (!ZSTD_isError(compressed_size)) { compress_status = 1; @@ -928,7 +934,14 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload)); + + if (compression_level < 0) { + compression_level = 0; + } else if (compression_level > 9) { + compression_level = 9; + } + + int status = compress2((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); if (status == Z_OK) { compress_status = 1; @@ -1120,7 +1133,7 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t * * No need to check the return value because the payload is always valid. */ - (void)s_compress_value (memc_user_data->compression_type, &payload, flags); + (void)s_compress_value (memc_user_data->compression_type, memc_user_data->compression_level, &payload, flags); } if (memc_user_data->set_udf_flags >= 0) { @@ -1325,6 +1338,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); memc_user_data->serializer = MEMC_G(serializer_type); memc_user_data->compression_type = MEMC_G(compression_type); + memc_user_data->compression_level = MEMC_G(compression_level); memc_user_data->compression_enabled = 1; memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); @@ -3075,6 +3089,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } break; + case MEMC_OPT_COMPRESSION_LEVEL: + lval = zval_get_long(value); + memc_user_data->compression_level = lval; + break; + case MEMC_OPT_ITEM_SIZE_LIMIT: lval = zval_get_long(value); if (lval < 0) { @@ -4054,7 +4073,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_threshold = 2000; php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; - php_memcached_globals->memc.compression_level = 3; + php_memcached_globals->memc.compression_level = 6; php_memcached_globals->memc.store_retry_count = 2; php_memcached_globals->memc.item_size_limit = 0; From d2b1172dffbee713857a960bd10b550f7921a1eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 07:57:32 -0700 Subject: [PATCH 664/694] Bump actions/checkout from 2 to 3 (#534) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 36cf7cba..de13c538 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -13,7 +13,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP id: setup-php uses: cmb69/setup-php-sdk@v0.7 From eb39e469d02576033e75848ca757a32e3502a3a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:33:10 -0700 Subject: [PATCH 665/694] Bump actions/checkout from 3 to 4 (#548) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 2 +- .github/workflows/build-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 7384dd88..2dcb6673 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,7 +17,7 @@ jobs: experimental: true steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Install PHP ${{ matrix.php }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index de13c538..a7aa8577 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -13,7 +13,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP id: setup-php uses: cmb69/setup-php-sdk@v0.7 From dfd038f13c4347fc15835cd9077a960218e01d98 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 27 Dec 2023 19:55:59 -0500 Subject: [PATCH 666/694] Correct whitespace formatting (#553) --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 93c20570..2c22ecba 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -186,8 +186,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *compression_name; zend_long compression_threshold; double compression_factor; - zend_long store_retry_count; - zend_long compression_level; + zend_long store_retry_count; + zend_long compression_level; zend_long item_size_limit; /* Converted values*/ From 7f31d8651b9ec98b2eb46705d1d17983b9999c13 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 7 Mar 2024 10:36:43 -0500 Subject: [PATCH 667/694] The key length check was not taking the prefix into account --- php_memcached.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 00d5e3d4..1e686f17 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -230,6 +230,19 @@ zend_bool s_memc_valid_key_binary(zend_string *key) return memchr(ZSTR_VAL(key), '\n', ZSTR_LEN(key)) == NULL; } +static +uint32_t s_memc_object_key_max_length(php_memc_object_t *intern) { + memcached_return retval; + char *result; + + result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); + if (retval == MEMCACHED_SUCCESS && result) { + return MEMC_OBJECT_KEY_MAX_LENGTH - strlen(result); + } else { + return MEMC_OBJECT_KEY_MAX_LENGTH; + } +} + static zend_bool s_memc_valid_key_ascii(zend_string *key) { @@ -245,7 +258,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ - ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + ZSTR_LEN(key) > s_memc_object_key_max_length(intern) || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ : !s_memc_valid_key_ascii(key) \ From abd372b454986afbea0a53ee1eb8393ff1145216 Mon Sep 17 00:00:00 2001 From: William Van Hevelingen Date: Wed, 15 May 2024 18:31:36 -0700 Subject: [PATCH 668/694] CI: Add PHP 8.3 to the required matrix, add PHP 8.4 to experimental (#557) --- .github/workflows/build-and-test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2dcb6673..14733ec1 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,13 +7,13 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] experimental: [false] include: - php: '8.2' awesome: true experimental: true - - php: '8.3' + - php: '8.4' experimental: true steps: - name: Checkout @@ -35,7 +35,7 @@ jobs: - if: ${{ matrix.awesome }} name: Install libmemcached-awesome (from source) run: | - curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.3.tar.gz + curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.4.tar.gz mkdir libmemcached tar --strip-components=1 -xf libmemcached.tgz -C libmemcached mkdir build-libmemcached @@ -83,7 +83,7 @@ jobs: define ("MEMC_SASL_SERVER_HOST", "127.0.0.1"); define ("MEMC_SASL_SERVER_PORT", 11212); - + define ('MEMC_SASL_USER', 'memcached'); define ('MEMC_SASL_PASS', 'test'); EOF From d8d99f07846d201836fe2308263dd0fac087c7be Mon Sep 17 00:00:00 2001 From: William Van Hevelingen Date: Wed, 15 May 2024 22:39:48 -0700 Subject: [PATCH 669/694] docs: fix build status on README.md (#558) --- README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index b17b7e55..38dbd5bc 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,6 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png)](https://travis-ci.org/php-memcached-dev/php-memcached) +![Build Status](https://github.com/php-memcached-dev/php-memcached/actions/workflows/build-and-test.yml/badge.svg?branch=master) Description ----------- @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 8.2 or higher. +* Supports PHP 7.0 - 8.3 or higher. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From 93c1bc449ff32e2a26b5f922fdd6dfa43edaeeb9 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 25 Sep 2024 23:54:00 +0200 Subject: [PATCH 670/694] ci: attempt to fix windows build --- .github/workflows/build-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index a7aa8577..fefd7deb 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,7 +7,7 @@ jobs: shell: cmd strategy: matrix: - version: ['7.4', '8.0', '8.1'] + version: ['8.3'] arch: [x64, x86] ts: [nts, zts] runs-on: windows-latest @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: cmb69/setup-php-sdk@v0.7 + uses: php/setup-php-sdk@v0.9 with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 8a6b0c78014dfb0d133595f06fc4c5bb29ba9a83 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 25 Sep 2024 23:54:27 +0200 Subject: [PATCH 671/694] ci: ubuntu already ships with awesomized/libmemcached --- .github/workflows/build-and-test.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 14733ec1..a142e10b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -10,9 +10,6 @@ jobs: php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] experimental: [false] include: - - php: '8.2' - awesome: true - experimental: true - php: '8.4' experimental: true steps: @@ -29,20 +26,8 @@ jobs: run: | sudo apt-get update sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev - - if: ${{ ! matrix.awesome }} - name: Install libmemcached-dev (from distro) + - name: Install libmemcached-dev run: sudo apt-get install libmemcached-dev - - if: ${{ matrix.awesome }} - name: Install libmemcached-awesome (from source) - run: | - curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.4.tar.gz - mkdir libmemcached - tar --strip-components=1 -xf libmemcached.tgz -C libmemcached - mkdir build-libmemcached - cd build-libmemcached - cmake -D ENABLE_HASH_HSIEH=ON -D ENABLE_SASL=ON ../libmemcached - make - sudo make install - name: Start memcached daemons run: | export SASL_CONF_PATH="/tmp/sasl2" From 899f0d52425b3efe2f67ed73eca115a0b5dc6c34 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 30 Jan 2024 09:44:48 +0100 Subject: [PATCH 672/694] Fix incompatible pointer types --- php_memcached.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 00d5e3d4..c3ef16e8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -933,7 +933,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon case COMPRESSION_TYPE_ZLIB: { - compressed_size = buffer_size; + unsigned long cs = compressed_size = buffer_size; if (compression_level < 0) { compression_level = 0; @@ -941,9 +941,10 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon compression_level = 9; } - int status = compress2((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); + int status = compress2((Bytef *) buffer, &cs, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); if (status == Z_OK) { + compressed_size = cs; compress_status = 1; compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB; } @@ -3751,7 +3752,10 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); } else if (is_zlib) { - decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); + unsigned long ds = buffer->len; + + decompress_status = (uncompress((Bytef *) buffer->val, &ds, (Bytef *)payload, payload_len) == Z_OK); + buffer->len = ds; } ZSTR_VAL(buffer)[stored_length] = '\0'; From 7227982467bb16786817b6c1aec85f99ce1e3a2e Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 19 Sep 2024 07:52:19 +0100 Subject: [PATCH 673/694] Added a composer.json to enable support for PIE --- composer.json | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..3356c89d --- /dev/null +++ b/composer.json @@ -0,0 +1,68 @@ +{ + "name": "php-memcached/php-memcached", + "type": "php-ext", + "license": "PHP-3.01", + "description": "memcached extension based on libmemcached library ", + "require": { + "php": ">= 7.0.0" + }, + "suggest": { + "ext-igbinary": "igbinary is a faster and more compact binary serializer for PHP data structures.", + "ext-msgpack": "msgpack is a faster and more compact data structure representation that is interoperable with msgpack implementations for other languages." + }, + "php-ext": { + "extension-name": "memcached", + "configure-options": [ + { + "name": "enable-memcached", + "description": "Enable memcached support" + }, + { + "name": "with-libmemcached-dir", + "description": "Set the path to libmemcached install prefix.", + "needs-value": true + }, + { + "name": "enable-memcached-session", + "description": "Enable memcached session handler support" + }, + { + "name": "enable-memcached-igbinary", + "description": "Enable memcached igbinary serializer support" + }, + { + "name": "enable-memcached-json", + "description": "Enable memcached json serializer support" + }, + { + "name": "enable-memcached-msgpack", + "description": "Enable memcached msgpack serializer support" + }, + { + "name": "enable-memcached-sasl", + "description": "Enable memcached sasl support" + }, + { + "name": "enable-memcached-protocol", + "description": "Enable memcached protocol support" + }, + { + "name": "with-system-fastlz", + "description": "Use system FastLZ library" + }, + { + "name": "with-zstd", + "description": "Use system zstd library" + }, + { + "name": "with-zlib-dir", + "description": "Set the path to ZLIB install prefix.", + "needs-value": true + }, + { + "name": "enable-debug", + "description": "Compile with debugging symbols" + } + ] + } +} From 0987380a558c4dadb9e0fa909132c5adea1f44ad Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 18:07:48 -0700 Subject: [PATCH 674/694] If client-side verify_key is not enabled, don't check it automatically --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index c3ef16e8..71725bb9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -246,6 +246,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ : !s_memc_valid_key_ascii(key) \ From 198e9b3681bb0a401385271e5a25b0d863b89d8f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 19:06:12 -0700 Subject: [PATCH 675/694] fix tests --- tests/cas_invalid_key.phpt | 5 ++++- tests/delete_bykey.phpt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt index b8a815dc..9cb7293c 100644 --- a/tests/cas_invalid_key.phpt +++ b/tests/cas_invalid_key.phpt @@ -5,7 +5,10 @@ Memcached::cas() with strange key --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); error_reporting(0); var_dump($m->cas(0, '', true, 10)); diff --git a/tests/delete_bykey.phpt b/tests/delete_bykey.phpt index 929ffbc1..6aa589c5 100644 --- a/tests/delete_bykey.phpt +++ b/tests/delete_bykey.phpt @@ -5,7 +5,10 @@ Memcached::deleteByKey() --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); $m->setByKey('keffe', 'eisaleeoo', "foo"); var_dump($m->getByKey('keffe', 'eisaleeoo')); From da71ae036237130b9e879f02326690e8ca73358a Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 21:42:43 -0700 Subject: [PATCH 676/694] Fix more tests with a slight refactor --- php_memcached.c | 3 +-- tests/get.phpt | 5 ++++- tests/keys_ascii.phpt | 5 +---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 71725bb9..55c20089 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -246,10 +246,9 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ - memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ - : !s_memc_valid_key_ascii(key) \ + : (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && !s_memc_valid_key_ascii(key)) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ diff --git a/tests/get.phpt b/tests/get.phpt index 71889064..722308f0 100644 --- a/tests/get.phpt +++ b/tests/get.phpt @@ -5,7 +5,10 @@ Memcached::get() --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); $m->delete('foo'); diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt index f7e98894..e7846e99 100644 --- a/tests/keys_ascii.phpt +++ b/tests/keys_ascii.phpt @@ -8,11 +8,8 @@ Test valid and invalid keys - ascii include dirname (__FILE__) . '/config.inc'; $ascii = memc_get_instance (array ( Memcached::OPT_BINARY_PROTOCOL => false, - Memcached::OPT_VERIFY_KEY => false + Memcached::OPT_VERIFY_KEY => true )); -// libmemcached can verify keys, but these are tests are for our own -// function s_memc_valid_key_ascii, so explicitly disable the checks -// that libmemcached can perform. echo 'ASCII: SPACES' . PHP_EOL; var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); From d15c2e2fdf3791a0fc7b711a8b02cfce1e78b76f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Fri, 20 Oct 2023 08:00:37 -0700 Subject: [PATCH 677/694] Check for spaces in keys when using the non-binary protocol even if key verification is disabled to avoid injection issues --- php_memcached.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 55c20089..e77e99b0 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -231,14 +231,21 @@ zend_bool s_memc_valid_key_binary(zend_string *key) } static -zend_bool s_memc_valid_key_ascii(zend_string *key) +zend_bool s_memc_valid_key_ascii(zend_string *key, uint64_t verify_key) { const char *str = ZSTR_VAL(key); size_t i, len = ZSTR_LEN(key); - for (i = 0; i < len; i++) { - if (!isgraph(str[i]) || isspace(str[i])) - return 0; + if (verify_key) { + for (i = 0; i < len; i++) { + if (!isgraph(str[i]) || isspace(str[i])) + return 0; + } + } else { /* if key verification is disabled, only check for spaces to avoid injection issues */ + for (i = 0; i < len; i++) { + if (isspace(str[i])) + return 0; + } } return 1; } @@ -248,7 +255,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ - : (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && !s_memc_valid_key_ascii(key)) \ + : !s_memc_valid_key_ascii(key, memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ @@ -342,7 +349,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } - if (!s_memc_valid_key_ascii(new_value)) { + if (!s_memc_valid_key_ascii(new_value, 1)) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); return FAILURE; } From 3ca10ec762c3844088f49d2f82a64ee188582d83 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 26 Sep 2024 13:28:51 +0200 Subject: [PATCH 678/694] ci: supply a name for the ubuntu workflow --- .github/workflows/build-and-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a142e10b..2e10b05b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,3 +1,5 @@ + +name: Test on Ubuntu on: [push, pull_request] jobs: From 2719e1ec2d0050d9ad82f32528b866c6cacfa586 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 26 Sep 2024 13:29:34 +0200 Subject: [PATCH 679/694] prepare v3.3.0RC1 - Add #515 option to locally enforce payload size limit - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow - Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token - Fix #546 don't check key automatically, unless client-side verify_key is enabled - Fix #555 incompatible pointer types (32-bit) --- package.xml | 20 ++++++++++++++------ php_memcached.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 6a14b96c..bee0600e 100644 --- a/package.xml +++ b/package.xml @@ -33,19 +33,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-24 + 2024-09-26 - 3.2.1dev - 3.2.0 + 3.3.0RC1 + 3.3.0 - stable + beta stable PHP -- mark password as a sensitive param for PHP 8.2 -- Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token +- Add #515 option to locally enforce payload size limit +- Add #539 zstd support +- Add #540 compression_level option +- Mark password as a sensitive param for PHP 8.2 +- Fix Windows PHP 8 compatibility +- Fix #518 Windows msgpack support +- Fix #522 signed integer overflow +- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token +- Fix #546 don't check key automatically, unless client-side verify_key is enabled +- Fix #555 incompatible pointer types (32-bit) diff --git a/php_memcached.h b/php_memcached.h index e966d19d..56664235 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.1-dev" +#define PHP_MEMCACHED_VERSION "3.3.0RC1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 25a192cde20e43e1a1200f6aee74aebeb3bfb435 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 4 Oct 2024 16:45:19 +0200 Subject: [PATCH 680/694] release v3.3.0RC1 - Add #515 option to locally enforce payload size limit - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow - Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token - Fix #546 don't check key automatically, unless client-side verify_key is enabled --- package.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index bee0600e..e1d6f060 100644 --- a/package.xml +++ b/package.xml @@ -33,7 +33,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2024-09-26 + + Michael Wallner + mike + mike@php.net + yes + + 2024-10-04 3.3.0RC1 3.3.0 From 6189c32892d4bc553a3707160656469a089b5d43 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:00:37 +0200 Subject: [PATCH 681/694] Use setup-php-sdk caching While a new release is pending, it seems worthwhile to make use of the caching as soon as possible to speed up Windows CI. --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index fefd7deb..b4231090 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@v0.9 + uses: php/setup-php-sdk@d07cd9875fcb041bbfa63c2c592c4e68a137e1ca with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 61957273e30537c3b14ec0413bc6863156d1b538 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:07:18 +0200 Subject: [PATCH 682/694] Actually enable caching --- .github/workflows/build-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index b4231090..c30c9dfe 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -22,6 +22,7 @@ jobs: arch: ${{matrix.arch}} ts: ${{matrix.ts}} deps: zlib + cache: true - name: Fetch libmemcached run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps - name: Enable Developer Command Prompt From cf30549f250690607d8c7363051a6a7bd3f637b6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:20:10 +0200 Subject: [PATCH 683/694] Test PHP 8.4 on Windows, too While caching speeds up the Windows builds, allocating an available runner takes some time (especially for many pushes in a short time). Thus we only build PHP 8.4 x64,zts, which should already suffice to detect most issues. --- .github/workflows/build-windows.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c30c9dfe..3356c265 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,9 +7,13 @@ jobs: shell: cmd strategy: matrix: - version: ['8.3'] + version: ['8.3', '8.4'] arch: [x64, x86] ts: [nts, zts] + exclude: + - { version: '8.4', arch: x64, ts: zts } + - { version: '8.4', arch: x86, ts: nts } + - { version: '8.4', arch: x86, ts: zts } runs-on: windows-latest steps: - name: Checkout memcached From 8877b9ac8ab6dfc29384a549e06de0c03f8081eb Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:25:46 +0200 Subject: [PATCH 684/694] Use new download server windows.php.net is in the process of being replaced by downloads.php.net, so we switch right away. --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 3356c265..d4d6133b 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -28,7 +28,7 @@ jobs: deps: zlib cache: true - name: Fetch libmemcached - run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + run: curl -OLs https://downloads.php.net/~windows/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 with: From c6f7d8d2beb4e9172ef517e7f99046db803f23ac Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:31:04 +0200 Subject: [PATCH 685/694] Cater to yet missing libmemcached-vs17 Using libmemcached-vs16 instead should be fine. --- .github/workflows/build-windows.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index d4d6133b..c5b04ce6 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -28,7 +28,9 @@ jobs: deps: zlib cache: true - name: Fetch libmemcached - run: curl -OLs https://downloads.php.net/~windows/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + run: | + set MEMCACHED_FILENAME=libmemcached-1.1.1-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip + curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 with: From 089a367fe211ca4eebe5b7ae8fb1370ac00add94 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 15:07:48 +0200 Subject: [PATCH 686/694] Update setup-php-sdk to v0.10 --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c5b04ce6..4c2640e4 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@d07cd9875fcb041bbfa63c2c592c4e68a137e1ca + uses: php/setup-php-sdk@v0.10 with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 9243f1ff40a771de11093726a7862cc085b19da2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 15 Oct 2024 15:02:35 +0200 Subject: [PATCH 687/694] Update libmemcached to 1.1.4 for Windows CI --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 4c2640e4..15dba3f2 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -29,7 +29,7 @@ jobs: cache: true - name: Fetch libmemcached run: | - set MEMCACHED_FILENAME=libmemcached-1.1.1-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip + set MEMCACHED_FILENAME=libmemcached-1.1.4-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 From b0b82692d789a2a5fd95b3910e87f73615c0f918 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 17 Oct 2024 19:33:43 +0200 Subject: [PATCH 688/694] release v3.3.0 --- package.xml | 7 ++++--- php_memcached.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index e1d6f060..1acb7c73 100644 --- a/package.xml +++ b/package.xml @@ -39,13 +39,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2024-10-04 + 2024-10-17 - 3.3.0RC1 + 3.3.0 3.3.0 - beta + stable stable PHP @@ -54,6 +54,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 +- Upgrade Windows libmemcached to v1.1.4 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow diff --git a/php_memcached.h b/php_memcached.h index 56664235..905f941d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.0RC1" +#define PHP_MEMCACHED_VERSION "3.3.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From bfcd9e7bbac40693cc055adc5f8722ef13909e38 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 17 Oct 2024 19:50:29 +0200 Subject: [PATCH 689/694] back to dev --- package.xml | 41 ++++++++++++++++++++++++++++------------- php_memcached.h | 2 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/package.xml b/package.xml index 1acb7c73..5565863e 100644 --- a/package.xml +++ b/package.xml @@ -41,26 +41,16 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2024-10-17 - 3.3.0 + 3.3.1dev 3.3.0 - stable + beta stable PHP -- Add #515 option to locally enforce payload size limit -- Add #539 zstd support -- Add #540 compression_level option -- Mark password as a sensitive param for PHP 8.2 -- Upgrade Windows libmemcached to v1.1.4 -- Fix Windows PHP 8 compatibility -- Fix #518 Windows msgpack support -- Fix #522 signed integer overflow -- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token -- Fix #546 don't check key automatically, unless client-side verify_key is enabled -- Fix #555 incompatible pointer types (32-bit) +- @@ -231,6 +221,31 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2024-10-17 + + 3.3.0 + 3.3.0 + + + stable + stable + + PHP + +- Add #515 option to locally enforce payload size limit +- Add #539 zstd support +- Add #540 compression_level option +- Mark password as a sensitive param for PHP 8.2 +- Upgrade Windows libmemcached to v1.1.4 +- Fix Windows PHP 8 compatibility +- Fix #518 Windows msgpack support +- Fix #522 signed integer overflow +- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token +- Fix #546 don't check key automatically, unless client-side verify_key is enabled +- Fix #555 incompatible pointer types (32-bit) + + 2022-03-24 diff --git a/php_memcached.h b/php_memcached.h index 905f941d..dfd19185 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.0" +#define PHP_MEMCACHED_VERSION "3.3.1dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From bb83855d1874d1741ec51277f2ed496a476d35ff Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 15 Jul 2025 19:56:33 +0200 Subject: [PATCH 690/694] use zend_ce_exception (#573) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index c8abb844..b78eb82a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3961,7 +3961,7 @@ zend_class_entry *php_memc_get_exception_base(int root) } } - return zend_exception_get_default(); + return zend_ce_exception; } From de7d53d13aecd329f03eab2eaf51c1ad8fa5c18f Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 31 Jul 2025 01:30:53 +0200 Subject: [PATCH 691/694] use Zend/zend_smart_string.h (#574) --- php_memcached_private.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached_private.h b/php_memcached_private.h index 2c22ecba..b7d2a5e1 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -43,7 +43,11 @@ #include #include #include +#if PHP_VERSION_ID < 70200 #include +#else +#include +#endif #include #include From 44868b5b25c4f94bb09116cc50faab8eafc20da4 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 20:45:03 -0700 Subject: [PATCH 692/694] Release 3.4.0 with tests for PHP 8.5 (#575) --- .github/workflows/build-and-test.yml | 6 +++--- .github/workflows/build-windows.yml | 7 ++++--- package.xml | 24 ++++++++++++++++++++---- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2e10b05b..50a0c2fd 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -9,14 +9,14 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] experimental: [false] include: - - php: '8.4' + - php: '8.6' experimental: true steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: true - name: Install PHP ${{ matrix.php }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 15dba3f2..b12a3557 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,9 +7,10 @@ jobs: shell: cmd strategy: matrix: - version: ['8.3', '8.4'] arch: [x64, x86] + os: [windows-2022] ts: [nts, zts] + version: ['8.3', '8.4', '8.5'] exclude: - { version: '8.4', arch: x64, ts: zts } - { version: '8.4', arch: x86, ts: nts } @@ -17,10 +18,10 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@v0.10 + uses: php/setup-php-sdk@v0.11 with: version: ${{matrix.version}} arch: ${{matrix.arch}} diff --git a/package.xml b/package.xml index 5565863e..384e7ea1 100644 --- a/package.xml +++ b/package.xml @@ -39,13 +39,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2024-10-17 + 2025-10-12 - 3.3.1dev - 3.3.0 + 3.4.0 + 3.4.0 - beta + stable stable PHP @@ -221,6 +221,22 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2025-10-12 + + 3.4.0 + 3.4.0 + + + stable + stable + + PHP + +- Use Zend/zend_smart_string.h for PHP 8.5 compatibility (#574) +- Use zen_ce_exception for PHP 8.5 compatibility (#573) + + 2024-10-17 From ce37962769fc7b25f9905c4b23fa53df92447a32 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 22:03:44 -0700 Subject: [PATCH 693/694] Release 3.4.0 --- package.xml | 2 +- php_memcached.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 384e7ea1..bfcd6edd 100644 --- a/package.xml +++ b/package.xml @@ -39,7 +39,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2025-10-12 + 2025-10-13 3.4.0 3.4.0 diff --git a/php_memcached.h b/php_memcached.h index dfd19185..dda3353f 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.1dev" +#define PHP_MEMCACHED_VERSION "3.4.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4ef6dce3bd1b486b372c79b398e86b03b8c76df3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 22:04:37 -0700 Subject: [PATCH 694/694] Mark as next dev version 3.4.1dev --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index dda3353f..60b916e9 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.4.0" +#define PHP_MEMCACHED_VERSION "3.4.1dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport)