mirror of
https://github.com/php-win-ext/php-memcached.git
synced 2026-03-24 00:52:18 +01:00
Merge remote-tracking branch 'parent/master' into feature-udf
This commit is contained in:
43
.travis.yml
Normal file
43
.travis.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.5
|
||||
#- 5.4
|
||||
#- 5.3
|
||||
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.10
|
||||
- LIBMEMCACHED_VERSION=1.0.8
|
||||
- LIBMEMCACHED_VERSION=1.0.2
|
||||
- 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/${LIBMEMCACHED_VERSION}/+download/libmemcached-${LIBMEMCACHED_VERSION}.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:
|
||||
- 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
|
||||
- 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 ""; echo "-- END"; done
|
||||
|
||||
|
||||
19
ChangeLog
19
ChangeLog
@@ -1,5 +1,22 @@
|
||||
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 #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:
|
||||
- memcached.sess_number_of_replicas
|
||||
- memcached.sess_randomize_replica_read
|
||||
- memcached.sess_remove_failed
|
||||
- memcached.sess_connect_timeout
|
||||
|
||||
Version 2.1.0
|
||||
-------------
|
||||
* Drop support for libmemcached 0.x series, now 1.0.x is required
|
||||
@@ -41,8 +58,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
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Build Status
|
||||
------------
|
||||
[](https://travis-ci.org/php-memcached-dev/php-memcached)
|
||||
|
||||
Description
|
||||
-----------
|
||||
This extension uses libmemcached library to provide API for communicating with
|
||||
@@ -7,8 +11,16 @@ 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)
|
||||
* [memcached](http://www.danga.com/memcached/)
|
||||
* [libmemcached](http://libmemcached.org/libMemcached.html)
|
||||
* [memcached](http://memcached.org/)
|
||||
* [igbinary](https://github.com/phadej/igbinary/)
|
||||
|
||||
101
config.m4
101
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,
|
||||
@@ -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=<DIR> to specify the prefix where libmemcached headers and library are located])
|
||||
AC_MSG_ERROR([memcached support requires libmemcached. Use --with-libmemcached-dir=<DIR> to specify the prefix where libmemcached headers and library are located])
|
||||
else
|
||||
AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR])
|
||||
|
||||
@@ -246,9 +246,100 @@ 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"
|
||||
ORIG_LIBS="$LIBS"
|
||||
|
||||
CFLAGS="$CFLAGS -I$PHP_LIBMEMCACHED_INCDIR"
|
||||
|
||||
#
|
||||
# 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(
|
||||
[ #include <libmemcached/memcached.h> ],
|
||||
[ 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 <libmemcached/memcached.h> ],
|
||||
[ 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 <libmemcached/memcached.h> ],
|
||||
[ 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 <libmemcached/memcached.h> ],
|
||||
[ 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/memcached.h> ],
|
||||
[ 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 <libmemcached/memcached.h> ],
|
||||
[ 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"
|
||||
|
||||
@@ -241,9 +241,9 @@ class Memcached {
|
||||
|
||||
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 ) {}
|
||||
|
||||
@@ -281,6 +281,8 @@ class Memcached {
|
||||
|
||||
public function isPristine( ) {}
|
||||
|
||||
public function setSaslAuthData( $username, $password ) {}
|
||||
|
||||
}
|
||||
|
||||
class MemcachedException extends Exception {
|
||||
|
||||
@@ -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."
|
||||
@@ -35,18 +47,28 @@ 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
|
||||
|
||||
; 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
|
||||
|
||||
; 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
|
||||
@@ -81,3 +103,9 @@ 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
|
||||
|
||||
|
||||
102
package.xml
102
package.xml
@@ -15,20 +15,37 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<email>andrei@php.net</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2012-08-06</date>
|
||||
<lead>
|
||||
<name>Mikko Koppanen</name>
|
||||
<user>mkoppanen</user>
|
||||
<email>mkoppanen@php.net</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2013-10-28</date>
|
||||
<version>
|
||||
<release>2.1.0</release>
|
||||
<api>2.1.0</api>
|
||||
<release>2.2.0b1</release>
|
||||
<api>2.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<release>beta</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://www.php.net/license">PHP</license>
|
||||
<notes>
|
||||
- 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 #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
|
||||
</notes>
|
||||
<contents>
|
||||
<dir name="/">
|
||||
@@ -46,11 +63,62 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file role='src' name='php_memcached_session.c'/>
|
||||
<file role='src' name='php_memcached_session.h'/>
|
||||
<file role='src' name='php_libmemcached_compat.h'/>
|
||||
<file role='src' name='php_libmemcached_compat.c'/>
|
||||
<file role='src' name='g_fmt.c'/>
|
||||
<file role='src' name='g_fmt.h'/>
|
||||
<file role='src' name='fastlz/fastlz.c'/>
|
||||
<file role='src' name='fastlz/fastlz.h'/>
|
||||
</dir> <!-- / -->
|
||||
<dir name="tests">
|
||||
<file role='test' name='001.phpt'/>
|
||||
<file role='test' name='version.phpt'/>
|
||||
<file role='test' name='bug_16084.phpt'/>
|
||||
<file role='test' name='bug_16959.phpt'/>
|
||||
<file role='test' name='bug_17137.phpt'/>
|
||||
<file role='test' name='bug_18639.phpt'/>
|
||||
<file role='test' name='callback_exception.phpt'/>
|
||||
<file role='test' name='callback_exception_2.phpt'/>
|
||||
<file role='test' name='cas.phpt'/>
|
||||
<file role='test' name='cas_multi.phpt'/>
|
||||
<file role='test' name='check_if_persistent.phpt'/>
|
||||
<file role='test' name='check_if_pristine.phpt'/>
|
||||
<file role='test' name='clone.phpt'/>
|
||||
<file role='test' name='compression_types.phpt'/>
|
||||
<file role='test' name='conf_persist.phpt'/>
|
||||
<file role='test' name='construct.phpt'/>
|
||||
<file role='test' name='construct_persistent.phpt'/>
|
||||
<file role='test' name='deleted.phpt'/>
|
||||
<file role='test' name='deletemulti.phpt'/>
|
||||
<file role='test' name='deletemultitypes.phpt'/>
|
||||
<file role='test' name='expire.phpt'/>
|
||||
<file role='test' name='flush_buffers.phpt'/>
|
||||
<file role='test' name='getdelayed.phpt'/>
|
||||
<file role='test' name='getserverlist.phpt'/>
|
||||
<file role='test' name='gh_21.phpt'/>
|
||||
<file role='test' name='gh_77.phpt'/>
|
||||
<file role='test' name='gh_90.phpt'/>
|
||||
<file role='test' name='invoke_callback.phpt'/>
|
||||
<file role='test' name='invoke_callback_2.phpt'/>
|
||||
<file role='test' name='invoke_callback_twice.phpt'/>
|
||||
<file role='test' name='localserver.phpt'/>
|
||||
<file role='test' name='multi_order.phpt'/>
|
||||
<file role='test' name='no-not-found.phpt'/>
|
||||
<file role='test' name='options.phpt'/>
|
||||
<file role='test' name='pr_75.phpt'/>
|
||||
<file role='test' name='rescode.phpt'/>
|
||||
<file role='test' name='session_badconf_emptyprefix.phpt'/>
|
||||
<file role='test' name='session_badconf_locktime.phpt'/>
|
||||
<file role='test' name='session_badconf_prefix.phpt'/>
|
||||
<file role='test' name='session_badconf_servers.phpt'/>
|
||||
<file role='test' name='session_basic.phpt'/>
|
||||
<file role='test' name='set_large.phpt'/>
|
||||
<file role='test' name='setoptions.phpt'/>
|
||||
<file role='test' name='touch_binary.phpt'/>
|
||||
<file role='test' name='types.phpt'/>
|
||||
<file role='test' name='types_multi.phpt'/>
|
||||
<file role='test' name='undefined_set.phpt'/>
|
||||
<file role='test' name='testdata.res'/>
|
||||
</dir>
|
||||
</dir>
|
||||
</contents>
|
||||
<dependencies>
|
||||
<required>
|
||||
@@ -65,8 +133,24 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
</required>
|
||||
</dependencies>
|
||||
<providesextension>memcached</providesextension>
|
||||
<extsrcrelease/>
|
||||
<extsrcrelease>
|
||||
<configureoption name="with-libmemcached-dir" default="no" prompt="libmemcached directory"/>
|
||||
</extsrcrelease>
|
||||
<changelog>
|
||||
<release>
|
||||
<stability><release>beta</release><api>stable</api></stability>
|
||||
<version><release>2.2.0b1</release><api>2.2.0</api></version>
|
||||
<date>2013-10-28</date>
|
||||
<notes>
|
||||
- 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
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<stability><release>stable</release><api>stable</api></stability>
|
||||
<version><release>2.1.0</release><api>2.1.0</api></version>
|
||||
|
||||
50
php_libmemcached_compat.c
Normal file
50
php_libmemcached_compat.c
Normal file
@@ -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 <andrei@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#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
|
||||
}
|
||||
@@ -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 <andrei@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_LIBMEMCACHED_COMPAT
|
||||
#define PHP_LIBMEMCACHED_COMPAT
|
||||
|
||||
/* this is the version(s) we support */
|
||||
#include <libmemcached-1.0/memcached.h>
|
||||
#include <libmemcached/memcached.h>
|
||||
|
||||
#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
|
||||
|
||||
518
php_memcached.c
518
php_memcached.c
@@ -54,6 +54,13 @@
|
||||
#include "fastlz/fastlz.h"
|
||||
#include <zlib.h>
|
||||
|
||||
/* 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 <inttypes.h>
|
||||
@@ -271,7 +278,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
|
||||
@@ -295,12 +302,17 @@ 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)
|
||||
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)
|
||||
|
||||
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)
|
||||
@@ -318,7 +330,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);
|
||||
@@ -328,9 +340,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);
|
||||
|
||||
/****************************************
|
||||
@@ -429,17 +441,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 {
|
||||
@@ -521,7 +537,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;
|
||||
@@ -550,7 +566,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;
|
||||
}
|
||||
@@ -558,127 +574,88 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
|
||||
keys[0] = key;
|
||||
key_lens[0] = key_len;
|
||||
|
||||
if (cas_token && Z_TYPE_P(cas_token) != IS_NULL) {
|
||||
uint64_t orig_cas_flag;
|
||||
uint64_t orig_cas_flag;
|
||||
orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
/*
|
||||
* Enable CAS support, but only if it is currently disabled.
|
||||
*/
|
||||
if (cas_token && Z_TYPE_P(cas_token) != IS_NULL && 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, 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 (cas_token && Z_TYPE_P(cas_token) != IS_NULL && 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;
|
||||
}
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
zval_dtor(cas_token);
|
||||
ZVAL_DOUBLE(cas_token, (double)cas);
|
||||
|
||||
if (udf_flags) {
|
||||
ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags));
|
||||
}
|
||||
|
||||
memcached_result_free(&result);
|
||||
|
||||
} else {
|
||||
int rc;
|
||||
zend_bool return_value_set = 0;
|
||||
|
||||
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 (udf_flags) {
|
||||
ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags));
|
||||
/* if we have a callback, all processing is done */
|
||||
if (fci.size != 0) {
|
||||
memcached_result_free(&result);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
if (udf_flags) {
|
||||
zval_dtor(udf_flags);
|
||||
ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags));
|
||||
}
|
||||
|
||||
memcached_result_free(&result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -706,11 +683,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 *tmp_key = NULL;
|
||||
size_t res_key_len = 0;
|
||||
uint32_t flags;
|
||||
uint64_t cas = 0;
|
||||
@@ -819,6 +796,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);
|
||||
@@ -828,14 +807,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);
|
||||
|
||||
@@ -1024,9 +1004,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;
|
||||
@@ -1084,9 +1064,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;
|
||||
@@ -1212,6 +1192,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; \
|
||||
@@ -1392,7 +1373,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;
|
||||
uint32_t udf_flags = 0;
|
||||
char *payload;
|
||||
size_t payload_len;
|
||||
@@ -1446,7 +1427,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;
|
||||
}
|
||||
@@ -1477,10 +1458,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool
|
||||
}
|
||||
|
||||
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;
|
||||
#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");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC);
|
||||
if (payload == NULL) {
|
||||
@@ -1498,7 +1480,7 @@ retry:
|
||||
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);
|
||||
@@ -1507,8 +1489,7 @@ retry:
|
||||
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);
|
||||
@@ -1597,7 +1578,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;
|
||||
}
|
||||
@@ -1716,7 +1697,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;
|
||||
}
|
||||
@@ -1816,7 +1797,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;
|
||||
}
|
||||
@@ -1842,6 +1823,10 @@ retry:
|
||||
}
|
||||
}
|
||||
} 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");
|
||||
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);
|
||||
@@ -1916,6 +1901,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)) {
|
||||
@@ -1923,6 +1909,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;
|
||||
@@ -2044,7 +2033,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;
|
||||
|
||||
@@ -2055,7 +2044,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;
|
||||
}
|
||||
@@ -2107,6 +2096,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 */
|
||||
@@ -2162,7 +2167,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) {
|
||||
@@ -2370,6 +2375,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;
|
||||
|
||||
@@ -2422,8 +2428,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;
|
||||
}
|
||||
|
||||
@@ -2477,18 +2483,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 (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");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2567,12 +2567,18 @@ 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)) {
|
||||
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));
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2734,7 +2740,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;
|
||||
@@ -2752,7 +2758,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;
|
||||
@@ -2796,7 +2802,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];
|
||||
@@ -2804,7 +2810,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),
|
||||
@@ -3026,20 +3032,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 {
|
||||
@@ -3049,91 +3107,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) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value");
|
||||
efree(buffer);
|
||||
char *datas = s_handle_decompressed (payload_in, &payload_len, flags TSRMLS_CC);
|
||||
if (!datas) {
|
||||
ZVAL_FALSE(value);
|
||||
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);
|
||||
@@ -3149,12 +3179,13 @@ 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;
|
||||
}
|
||||
#else
|
||||
ZVAL_FALSE(value);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support");
|
||||
goto my_error;
|
||||
#endif
|
||||
@@ -3163,30 +3194,32 @@ 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);
|
||||
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;
|
||||
}
|
||||
|
||||
if (payload_emalloc) {
|
||||
efree(payload);
|
||||
efree(pl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
my_error:
|
||||
if (payload_emalloc) {
|
||||
efree(payload);
|
||||
efree(pl);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -3196,16 +3229,23 @@ 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;
|
||||
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_number_of_replicas) = 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;
|
||||
@@ -3343,9 +3383,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;
|
||||
@@ -3653,6 +3693,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()
|
||||
@@ -3722,7 +3765,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
|
||||
@@ -3755,6 +3798,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)
|
||||
@@ -3811,13 +3856,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
|
||||
@@ -3834,6 +3874,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);
|
||||
@@ -3919,7 +3960,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
|
||||
|
||||
@@ -3996,27 +4037,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;
|
||||
@@ -4057,6 +4077,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;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -4064,6 +4092,12 @@ PHP_MINIT_FUNCTION(memcached)
|
||||
/* {{{ PHP_MSHUTDOWN_FUNCTION */
|
||||
PHP_MSHUTDOWN_FUNCTION(memcached)
|
||||
{
|
||||
#if HAVE_MEMCACHED_SASL
|
||||
if (MEMC_G(use_sasl)) {
|
||||
sasl_done();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
ts_free_id(php_memcached_globals_id);
|
||||
#else
|
||||
@@ -4083,6 +4117,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
|
||||
|
||||
@@ -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;
|
||||
@@ -70,7 +72,15 @@ 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;
|
||||
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;
|
||||
@@ -83,8 +93,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);
|
||||
@@ -107,7 +115,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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -138,11 +143,11 @@ error:
|
||||
}
|
||||
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")) {
|
||||
@@ -186,14 +191,19 @@ error:
|
||||
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);
|
||||
@@ -217,7 +227,28 @@ success:
|
||||
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;
|
||||
}
|
||||
MEMC_G(sess_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 TSRMLS_CC, E_WARNING, "failed to set memcached session number of replicas");
|
||||
@@ -228,13 +259,11 @@ success:
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#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) {
|
||||
@@ -242,7 +271,7 @@ success:
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -262,7 +291,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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,11 +24,12 @@ 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_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
|
||||
memcached.sess_remove_failed => %d => %d
|
||||
memcached.use_sasl => %d => %d
|
||||
@@ -1,50 +1,67 @@
|
||||
--TEST--
|
||||
Memcached store, fetch & touch expired key
|
||||
--XFAIL--
|
||||
https://code.google.com/p/memcached/issues/detail?id=275
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
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($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);
|
||||
return;
|
||||
}
|
||||
echo "All OK" . PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
$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->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);
|
||||
}
|
||||
echo '-- binary protocol' . PHP_EOL;
|
||||
run_expiry_test ($m);
|
||||
|
||||
sleep(3);
|
||||
$v = $m->get('will_expire');
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 '-- 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
|
||||
|
||||
31
tests/flush_buffers.phpt
Normal file
31
tests/flush_buffers.phpt
Normal file
@@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
Test flushing buffers
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$m = new Memcached();
|
||||
$m->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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
34
tests/gh_21.phpt
Normal file
34
tests/gh_21.phpt
Normal file
@@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
Test for Github issue 21
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$m = new Memcached();
|
||||
$newServers = array(
|
||||
array('127.0.0.1', 11211),
|
||||
);
|
||||
$m->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)
|
||||
32
tests/gh_77.phpt
Normal file
32
tests/gh_77.phpt
Normal file
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Test for Github issue #77
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip";
|
||||
if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x01000016) die ('skip too old libmemcached');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$mc = new Memcached();
|
||||
$mc->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
|
||||
|
||||
93
tests/gh_90.phpt
Normal file
93
tests/gh_90.phpt
Normal file
@@ -0,0 +1,93 @@
|
||||
--TEST--
|
||||
Test for GH #90
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
//Setup MemcacheD
|
||||
{
|
||||
$memcached = new Memcached();
|
||||
$memcached->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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
24
tests/no-not-found.phpt
Normal file
24
tests/no-not-found.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Test that correct return value is returned
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$memcached = new Memcached();
|
||||
$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);
|
||||
var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE);
|
||||
|
||||
echo "OK\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
OK
|
||||
27
tests/pr_75.phpt
Normal file
27
tests/pr_75.phpt
Normal file
@@ -0,0 +1,27 @@
|
||||
--TEST--
|
||||
Wrong return values for binary protocol
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$client = new Memcached();
|
||||
$client->addServer ('127.0.0.1', 11211);
|
||||
$client->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
|
||||
@@ -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
|
||||
|
||||
69
tests/touch_binary.phpt
Normal file
69
tests/touch_binary.phpt
Normal file
@@ -0,0 +1,69 @@
|
||||
--TEST--
|
||||
Touch in binary mode
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip";
|
||||
if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x01000016) die ('skip too old libmemcached');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function resolve_to_constant ($code)
|
||||
{
|
||||
$refl = new ReflectionClass ('memcached');
|
||||
$c = $refl->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 ($expected);
|
||||
$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_');
|
||||
|
||||
$mem->get($key);
|
||||
status_print ('get', $mem, Memcached::RES_NOTFOUND);
|
||||
|
||||
$mem->set ($key, 1);
|
||||
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);
|
||||
|
||||
$mem->get($key);
|
||||
status_print ('get', $mem, Memcached::RES_SUCCESS);
|
||||
|
||||
echo "OK\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
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
|
||||
get status code as expected
|
||||
OK
|
||||
@@ -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(),
|
||||
);
|
||||
|
||||
|
||||
18
tests/version.phpt
Normal file
18
tests/version.phpt
Normal file
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Get version
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("memcached")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$m = new Memcached();
|
||||
$m->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
|
||||
Reference in New Issue
Block a user