package.xml 0000644 0000765 0000024 00000106777 14704245235 012033 0 ustar mike staff
memcached
pecl.php.net
PHP extension for interfacing with memcached via libmemcached library
This extension uses libmemcached library to provide API for communicating with memcached servers.
Andrei Zmievski
andrei
andrei@php.net
yes
Mikko Koppanen
mkoppanen
mkoppanen@php.net
yes
Aaron Stone
sodabrew
aaron@serendipity.cx
yes
Remi Collet
remi
remi@php.net
yes
Michael Wallner
mike
mike@php.net
yes
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)
7.0.0
1.4.0b1
igbinary
2.0
msgpack
2.0
memcached
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
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
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
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
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
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
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
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
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
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
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
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
alpha
3.0.0a1
3.0.0
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
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
* 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)
* 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
stable
stable
2.2.0
2.2.0
2014-04-01
- Added the OPT_SERVER_TIMEOUT_LIMIT behaviour
beta
stable
2.2.0RC1
2.2.0
2014-03-12
- Fixes incorrect size when compressing serialized objects
- Fixes endianess of compressed values
beta
stable
2.2.0b1
2.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
stable
stable
2.1.0
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
stable
stable
2.0.1
2.0.1
2012-03-03
- Fix embedded version number to be not -dev
stable
stable
2.0.0
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
beta
beta
2.0.0b2
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.
- 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)
beta
beta
2.0.0b1
2.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
stable
stable
1.0.2
1.0.2
2010-05-03
- Fix build for libmemcached-0.39 (memcached_server_list() issue)
stable
stable
1.0.1
1.0.1
2010-03-11
- Fix build for libmemcached-0.38.
stable
stable
1.0.0
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).
beta
beta
0.2.0
0.2.0
2009-06-04
- Refactor the way payload types are stored in memcached flags to optimize the structure
and allow for future expansion. WARNING! You have to flush the cache when upgrading from
an older version.
- 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.
- Add 'flags' parameter to getMulti() and getMultiByKey().
- Add GET_PRESERVE_ORDER class constant that can be used with abovementioned flags
parameter to make the order of the keys in the response match the request.
- Fix an issue with retrieving 0-length payloads (FALSE boolean value).
- Add several tests.
beta
beta
0.1.5
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.
beta
beta
0.1.4
0.1.4
2009-02-13
- Fix compilation against PHP 5.3.
- Add support for 'igbinary' serializer (Oleg Grenrus)
beta
beta
0.1.3
0.1.3
2009-02-06
- Bludgeon bug #15896 (Memcached setMulti error) into submission.
beta
beta
0.1.2
0.1.2
2009-02-06
- Fix bug #15896 (Memcached setMulti error).
- Check for empty key in getServerByKey().
- Allow passing 'null' for callbacks.
- get() with cas token fetching wasn't erroring out properly.
- Rename certain parameters in the API to be more clear.
- Allow only strings as the append/prepend value.
- Remove expiration parameter from append/prepend.
beta
beta
0.1.1
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.
beta
beta
0.1.0
0.1.0
2009-01-29
- Initial PECL release
memcached-3.3.0/tests/skipif.inc 0000644 0000765 0000024 00000000612 14704245235 015362 0 ustar mike staff
--FILE--
--EXPECT--
memcached extension is available
memcached-3.3.0/tests/version.phpt 0000644 0000765 0000024 00000000415 14704245235 015765 0 ustar mike staff --TEST--
Get version
--SKIPIF--
--FILE--
getVersion ());
echo "OK" . PHP_EOL;
?>
--EXPECTF--
array(1) {
["%s:%d"]=>
string(%d) "%d.%d.%d"
}
OK
memcached-3.3.0/tests/bug_16084.phpt 0000644 0000765 0000024 00000000655 14704245235 015625 0 ustar mike staff --TEST--
Memcached: Bug #16084 (Crash when addServers is called with an associative array)
--SKIPIF--
--FILE--
array ( 'KEYHERE' => 'localhost', 11211, 3 ), );
$m = new memcached();
var_dump($m->addServers($servers));
$list = $m->getServerList();
var_dump ($list[0]["host"], $list[0]["port"]);
echo "OK";
?>
--EXPECT--
bool(true)
string(9) "localhost"
int(11211)
OK
memcached-3.3.0/tests/bug_16959.phpt 0000644 0000765 0000024 00000002373 14704245235 015637 0 ustar mike staff --TEST--
Memcached: Bug #16959 (getMulti + BINARY_PROTOCOL problem)
--SKIPIF--
--FILE--
true
));
$cache->set('key_0', 'value0');
$cache->set('key_0_additional', 'value0_additional');
// -------------- NORMAL
echo "NORMAL\n";
$keys = array( 'key_0', 'key_0_additional' );
$values = $cache->getMulti($keys);
echo $cache->getResultMessage(), "\n";
echo "Values:\n";
foreach ($values as $k => $v) {
var_dump($k);
var_dump($v);
var_dump($values[$k]);
}
// --------------- REVERSED KEY ORDER
echo "REVERSED KEY ORDER\n";
$keys = array( 'key_0_additional', 'key_0' );
$values = $cache->getMulti($keys);
echo $cache->getResultMessage(), "\n";
echo "Values:\n";
foreach ($values as $k => $v) {
var_dump($k);
var_dump($v);
var_dump($values[$k]);
}
--EXPECT--
NORMAL
SUCCESS
Values:
string(5) "key_0"
string(6) "value0"
string(6) "value0"
string(16) "key_0_additional"
string(17) "value0_additional"
string(17) "value0_additional"
REVERSED KEY ORDER
SUCCESS
Values:
string(16) "key_0_additional"
string(17) "value0_additional"
string(17) "value0_additional"
string(5) "key_0"
string(6) "value0"
string(6) "value0"
memcached-3.3.0/tests/bug_17137.phpt 0000644 0000765 0000024 00000001631 14704245235 015620 0 ustar mike staff --TEST--
Change prefix, pecl bug #17137
--SKIPIF--
--FILE--
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'));
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"
memcached-3.3.0/tests/bug_18639.phpt 0000644 0000765 0000024 00000000622 14704245235 015627 0 ustar mike staff --TEST--
Memcached::getServerByKey(): Bug pecl#18639 (Segfault in getServerByKey)
--SKIPIF--
--FILE--
set('test', 'test1'));
var_dump($m->getServerByKey('1'));
--EXPECTF--
bool(true)
array(3) {
["host"]=>
string(9) "%s"
["port"]=>
int(%d)
["weight"]=>
int(%r[01]%r)
}
memcached-3.3.0/tests/callback_exception.phpt 0000644 0000765 0000024 00000001607 14704245235 020116 0 ustar mike staff --TEST--
make sure that callback exception behaves correctly
--SKIPIF--
--FILE--
--EXPECT--
success
success
empty_cb called
success
OK
memcached-3.3.0/tests/callback_exception_2.phpt 0000644 0000765 0000024 00000001720 14704245235 020333 0 ustar mike staff --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
memcached-3.3.0/tests/cas.phpt 0000644 0000765 0000024 00000000626 14704245235 015052 0 ustar mike staff --TEST--
Memcached fetch cas & set cas
--SKIPIF--
--FILE--
delete('cas_test');
$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--
OK memcached-3.3.0/tests/cas_multi.phpt 0000644 0000765 0000024 00000001764 14704245235 016270 0 ustar mike staff --TEST--
Memcached multi fetch cas & set cas
--SKIPIF--
--FILE--
1,
'cas_test_2' => 2,
);
foreach ($data as $key => $v) {
$m->delete($key);
}
$m->setMulti($data, 10);
$actual = $m->getMulti(array_keys($data), Memcached::GET_EXTENDED);
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);
return;
}
$v = $m->cas($v['cas'], $key, 11);
if (!$v) {
echo "Error setting key: $key value: 11 with CAS: ", $v['cas'], "\n";
return;
}
$v = $m->get($key);
if ($v !== 11) {
echo "Wanted $key to be 11, value is: ";
var_dump($v);
return;
}
}
if (array_keys($actual) !== array_keys($data)) {
echo "missing value(s)\n";
echo "data :";
var_dump($data);
echo "actual data: ";
var_dump($actual);
return;
}
echo "OK\n";
?>
--EXPECT--
OK memcached-3.3.0/tests/check_if_persistent.phpt 0000644 0000765 0000024 00000001433 14704245235 020314 0 ustar mike staff --TEST--
Check if persistent object is persistent
--SKIPIF--
--FILE--
setOption(Memcached::OPT_PREFIX_KEY, "foo_");
var_dump($m1->isPersistent());
$m1 = new Memcached('id1');
var_dump($m1->isPersistent());
$m2 = new Memcached('id1');
var_dump($m2->isPersistent());
// this change affects $m1
$m2->setOption(Memcached::OPT_PREFIX_KEY, "bar_");
$m3 = new Memcached('id2');
var_dump($m3->isPersistent());
$m3 = new Memcached();
var_dump($m3->isPersistent());
// objects have the same resource, but they are not the same object.
var_dump($m1 === $m2);
var_dump($m1->getOption(Memcached::OPT_PREFIX_KEY));
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)
string(4) "bar_"
memcached-3.3.0/tests/check_if_pristine.phpt 0000644 0000765 0000024 00000001165 14704245235 017753 0 ustar mike staff --TEST--
Check if persistent object is new or an old persistent one
--SKIPIF--
--FILE--
setOption(Memcached::OPT_PREFIX_KEY, "foo_");
var_dump($m1->isPristine());
$m1 = new Memcached('id1');
var_dump($m1->isPristine());
$m2 = new Memcached('id1');
var_dump($m2->isPristine());
// this change affects $m1
$m2->setOption(Memcached::OPT_PREFIX_KEY, "bar_");
$m3 = new Memcached('id2');
var_dump($m3->isPristine());
$m3 = new Memcached();
var_dump($m3->isPristine());
--EXPECT--
bool(true)
bool(false)
bool(false)
bool(true)
bool(true)
memcached-3.3.0/tests/check_key.phpt 0000644 0000765 0000024 00000007373 14704245235 016237 0 ustar mike staff --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"
memcached-3.3.0/tests/clone.phpt 0000644 0000765 0000024 00000000504 14704245235 015377 0 ustar mike staff --TEST--
Test cloning
--SKIPIF--
--FILE--
--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]
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]
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)
memcached-3.3.0/tests/compression_types.phpt 0000644 0000765 0000024 00000005406 14704245235 020072 0 ustar mike staff --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);
if (!$get_compression) {
$m->setOption(Memcached::OPT_COMPRESSION, true);
} else {
$m->setOption(Memcached::OPT_COMPRESSION, true);
$m->setOption(Memcached::OPT_COMPRESSION_TYPE, get_compression($get_compression));
}
$value_back = $m->get($key);
var_dump($value === $value_back);
}
fetch_with_compression($m, 'hello1', $data, 'zlib', 'zlib');
fetch_with_compression($m, 'hello2', $data, 'zlib', 'fastlz');
fetch_with_compression($m, 'hello3', $data, 'fastlz', 'fastlz');
fetch_with_compression($m, 'hello4', $data, 'fastlz', 'zlib');
fetch_with_compression($m, 'hello5', $data, '', 'zlib');
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]
bool(true)
set=[zlib] get=[fastlz]
bool(true)
set=[fastlz] get=[fastlz]
bool(true)
set=[fastlz] get=[zlib]
bool(true)
set=[] get=[zlib]
bool(true)
set=[] get=[fastlz]
bool(true)
set=[zlib] get=[]
bool(true)
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)
memcached-3.3.0/tests/conf_persist.phpt 0000644 0000765 0000024 00000001117 14704245235 016776 0 ustar mike staff --TEST--
Conf settings persist.
--SKIPIF--
--FILE--
'php'
), 'id1');
$m1->set('foo', 'bar');
for ($i = 1000; $i > 0; $i--) {
$m1 = new Memcached('id1');
$rv = $m1->get('foo');
if ($rv !== 'bar') {
echo "Expected bar got:";
var_dump($rv);
die();
}
$prefix = $m1->getOption(Memcached::OPT_PREFIX_KEY);
if ($prefix !== 'php') {
echo "Expected prefix php got:";
var_dump($prefix);
die();
}
}
echo "OK\n";
?>
--EXPECT--
OK memcached-3.3.0/tests/construct.phpt 0000644 0000765 0000024 00000000232 14704245235 016321 0 ustar mike staff --TEST--
Memcached constructor
--SKIPIF--
--FILE--
--EXPECT--
Memcached
memcached-3.3.0/tests/construct_persistent.phpt 0000644 0000765 0000024 00000000677 14704245235 020616 0 ustar mike staff --TEST--
persistent memcached connection
--SKIPIF--
--FILE--
setOption(Memcached::OPT_PREFIX_KEY, 'php');
var_dump($m1->getOption(Memcached::OPT_PREFIX_KEY));
$m2 = new Memcached('id1');
var_dump($m1->getOption(Memcached::OPT_PREFIX_KEY));
$m3 = new Memcached();
var_dump($m3->getOption(Memcached::OPT_PREFIX_KEY));
?>
--EXPECT--
string(3) "php"
string(3) "php"
string(0) ""
memcached-3.3.0/tests/deleted.phpt 0000644 0000765 0000024 00000000663 14704245235 015713 0 ustar mike staff --TEST--
Memcached store & fetch type correctness
--SKIPIF--
--FILE--
set('eisaleeoo', "foo");
$m->delete('eisaleeoo');
$v = $m->get('eisaleeoo');
if ($v !== Memcached::GET_ERROR_RETURN_VALUE) {
echo "Wanted: ";
var_dump(Memcached::GET_ERROR_RETURN_VALUE);
echo "Got: ";
var_dump($v);
}
echo "OK\n";
?>
--EXPECT--
OK memcached-3.3.0/tests/deletemulti.phpt 0000644 0000765 0000024 00000003140 14704245235 016613 0 ustar mike staff --TEST--
Delete multi
--SKIPIF--
--FILE--
'foo-data',
'bar' => 'bar-data',
'baz' => 'baz-data',
'lol' => 'lol-data',
'kek' => 'kek-data',
);
$keys = array_keys($data);
$null = null;
$m->setMulti($data, 3600);
/* Check that all keys were stored */
var_dump(has_all_keys($keys, $m->getMulti($keys)));
/* Check that all keys get deleted */
$deleted = $m->deleteMulti($keys);
var_dump(has_all_keys($keys, $deleted, true));
/* Try to get the deleted keys, should give empty array */
var_dump($m->getMulti($keys));
/* ---- same tests for byKey variants ---- */
$m->setMultiByKey("hi", $data, 3600);
var_dump(has_all_keys($keys, $m->getMultiByKey('hi', $keys)));
/* Check that all keys get deleted */
$deleted = $m->deleteMultiByKey('hi', $keys);
var_dump(has_all_keys($keys, $deleted, true));
/* Try to get the deleted keys, should give empty array */
var_dump($m->getMultiByKey('hi', $keys));
/* Test deleting non-existent keys */
$keys = array();
$keys[] = "nothere";
$keys[] = "nothere2";
$retval = $m->deleteMulti($keys);
foreach ($retval as $key => $value) {
if ($value === Memcached::RES_NOTFOUND) {
echo "$key NOT FOUND\n";
}
}
?>
--EXPECT--
bool(true)
bool(true)
array(0) {
}
bool(true)
bool(true)
array(0) {
}
nothere NOT FOUND
nothere2 NOT FOUND memcached-3.3.0/tests/deletemultitypes.phpt 0000644 0000765 0000024 00000000610 14704245235 017677 0 ustar mike staff --TEST--
Delete multi key types
--SKIPIF--
--FILE--
deleteMulti($keys);
array_walk($keys, 'dump_types');
?>
--EXPECT--
integer
string
integer
string memcached-3.3.0/tests/expire.phpt 0000644 0000765 0000024 00000002536 14704245235 015602 0 ustar mike staff --TEST--
Memcached store, fetch & touch expired key
--SKIPIF--
--FILE--
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 = memc_get_instance (array (
Memcached::OPT_BINARY_PROTOCOL => true
));
echo '-- binary protocol' . PHP_EOL;
run_expiry_test ($m);
$m = memc_get_instance ();
echo '-- text protocol' . PHP_EOL;
run_expiry_test ($m);
echo "DONE TEST\n";
?>
--EXPECT--
-- binary protocol
All OK
-- text protocol
All OK
DONE TEST
memcached-3.3.0/tests/flush_buffers.phpt 0000644 0000765 0000024 00000001041 14704245235 017131 0 ustar mike staff --TEST--
Test flushing buffers
--SKIPIF--
--FILE--
1,
Memcached::OPT_BUFFER_WRITES => 1,
));
$key = uniqid ('flush_key_');
var_dump ($m->set($key, 'test_val'));
$m2 = memc_get_instance ();
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 memcached-3.3.0/tests/getdelayed.phpt 0000644 0000765 0000024 00000002171 14704245235 016410 0 ustar mike staff --TEST--
Memcached getDelayed callback
--SKIPIF--
--FILE--
'foo-data',
'bar' => 'bar-data',
'baz' => 'baz-data',
'lol' => 'lol-data',
'kek' => 'kek-data',
);
foreach ($data as $k => $v) {
$m->set($k, $v, 3600);
}
function myfunc() {
$datas = func_get_args();
if (isset($datas[1])) {
var_dump($datas[1]);
}
}
$m->getDelayed(array_keys($data), true, 'myfunc');
?>
--EXPECTF--
array(4) {
["key"]=>
string(3) "foo"
["value"]=>
string(8) "foo-data"
["cas"]=>
int(%d)
["flags"]=>
int(0)
}
array(4) {
["key"]=>
string(3) "bar"
["value"]=>
string(8) "bar-data"
["cas"]=>
int(%d)
["flags"]=>
int(0)
}
array(4) {
["key"]=>
string(3) "baz"
["value"]=>
string(8) "baz-data"
["cas"]=>
int(%d)
["flags"]=>
int(0)
}
array(4) {
["key"]=>
string(3) "lol"
["value"]=>
string(8) "lol-data"
["cas"]=>
int(%d)
["flags"]=>
int(0)
}
array(4) {
["key"]=>
string(3) "kek"
["value"]=>
string(8) "kek-data"
["cas"]=>
int(%d)
["flags"]=>
int(0)
} memcached-3.3.0/tests/getserverlist.phpt 0000644 0000765 0000024 00000001764 14704245235 017212 0 ustar mike staff --TEST--
getServerList
--SKIPIF--
--FILE--
array ( 'KEYHERE' => 'localhost', 11211, 3 ), );
$m = new memcached();
var_dump($m->getServerList());
$m->addServers($servers);
var_dump($m->getServerList());
$m->addServers($servers);
var_dump($m->getServerList());
$m = new memcached();
$m->addServer('127.0.0.1', 11211);
var_dump($m->getServerList());
echo "OK";
?>
--EXPECT--
array(0) {
}
array(1) {
[0]=>
array(3) {
["host"]=>
string(9) "localhost"
["port"]=>
int(11211)
["type"]=>
string(3) "TCP"
}
}
array(2) {
[0]=>
array(3) {
["host"]=>
string(9) "localhost"
["port"]=>
int(11211)
["type"]=>
string(3) "TCP"
}
[1]=>
array(3) {
["host"]=>
string(9) "localhost"
["port"]=>
int(11211)
["type"]=>
string(3) "TCP"
}
}
array(1) {
[0]=>
array(3) {
["host"]=>
string(9) "127.0.0.1"
["port"]=>
int(11211)
["type"]=>
string(3) "TCP"
}
}
OK memcached-3.3.0/tests/gh_21.phpt 0000644 0000765 0000024 00000001202 14704245235 015173 0 ustar mike staff --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) memcached-3.3.0/tests/gh_77.phpt 0000644 0000765 0000024 00000001104 14704245235 015207 0 ustar mike staff --TEST--
Test for Github issue #77
--SKIPIF--
--FILE--
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
memcached-3.3.0/tests/gh_90.phpt 0000644 0000765 0000024 00000003442 14704245235 015211 0 ustar mike staff --TEST--
Test for GH #90
--SKIPIF--
--FILE--
true
));
// 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, mt_getrandmax()); //Random value 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)
}
memcached-3.3.0/tests/gh_500.phpt 0000644 0000765 0000024 00000000756 14704245235 015272 0 ustar mike staff --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)
memcached-3.3.0/tests/invoke_callback.phpt 0000644 0000765 0000024 00000001034 14704245235 017405 0 ustar mike staff --TEST--
Test that callback is invoked on new object
--SKIPIF--
--FILE--
addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT);
}
$m = new Memcached('hi', 'my_func');
$m = new Memcached('hi', 'my_func');
var_dump($m->getServerList());
echo "OK\n";
--EXPECTF--
array(1) {
[0]=>
array(3) {
["host"]=>
string(9) "%s"
["port"]=>
int(%d)
["type"]=>
string(3) "TCP"
}
}
OK
memcached-3.3.0/tests/invoke_callback_2.phpt 0000644 0000765 0000024 00000002755 14704245235 017641 0 ustar mike staff --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) {
var_dump(func_num_args());
var_dump($id);
}
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) {
var_dump(func_num_args());
var_dump($this->isPristine());
var_dump($this->isPersistent());
var_dump($id);
}
}
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 "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
int(2)
string(4) "foo3"
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"
cb second persistent in object
memcached-3.3.0/tests/invoke_callback_twice.phpt 0000644 0000765 0000024 00000000545 14704245235 020606 0 ustar mike staff --TEST--
Test that callback is invoked on new object only once
--SKIPIF--
--FILE--
--FILE--
set($key, array(
'foo' => 'bar'
), 360);
var_dump($m->get($key));
?>
--EXPECT--
array(1) {
["foo"]=>
string(3) "bar"
}
memcached-3.3.0/tests/multi_order.phpt 0000644 0000765 0000024 00000001256 14704245235 016631 0 ustar mike staff --TEST--
Memcached GET_PRESERVE_ORDER flag in getMulti
--SKIPIF--
--FILE--
addServer (MEMC_SERVER_HOST, MEMC_SERVER_PORT);
$data = array(
'foo' => 'foo-data',
'bar' => 'bar-data',
'baz' => 'baz-data',
'lol' => 'lol-data',
'kek' => 'kek-data',
);
//$m->setMulti($data, 3600);
foreach ($data as $k => $v) {
$m->set($k, $v, 3600);
}
$keys = array_keys($data);
$keys[] = 'zoo';
$got = $m->getMulti($keys, Memcached::GET_PRESERVE_ORDER);
foreach ($got as $k => $v) {
echo "$k $v\n";
}
?>
--EXPECT--
foo foo-data
bar bar-data
baz baz-data
lol lol-data
kek kek-data
zoo
memcached-3.3.0/tests/no-not-found.phpt 0000644 0000765 0000024 00000000726 14704245235 016630 0 ustar mike staff --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);
$result = $memcached->get('foo_not_exists');
var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE);
echo "OK\n";
?>
--EXPECT--
bool(true)
bool(true)
OK
memcached-3.3.0/tests/options.phpt 0000644 0000765 0000024 00000004432 14704245235 015776 0 ustar mike staff --TEST--
Memcached options
--SKIPIF--
--FILE--
setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP);
var_dump($m->getOption(Memcached::OPT_COMPRESSION));
var_dump($m->getOption(Memcached::OPT_SERIALIZER));
var_dump($m->getOption(Memcached::OPT_SOCKET_SEND_SIZE));
$m->setOption(Memcached::OPT_PREFIX_KEY, "\x01");
var_dump($m->getOption(Memcached::OPT_HASH) == Memcached::HASH_DEFAULT);
$m->setOption(Memcached::OPT_HASH, Memcached::HASH_MURMUR);
var_dump($m->getOption(Memcached::OPT_HASH) == Memcached::HASH_MURMUR);
$m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_ZLIB);
var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSION_ZLIB);
$m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ);
var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSION_FASTLZ);
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)
int(1)
Warning: Memcached::getOption(): no servers defined in %s on line %d
NULL
Warning: Memcached::setOption(): bad key provided in %s on line %d
bool(true)
bool(true)
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)
memcached-3.3.0/tests/pr_75.phpt 0000644 0000765 0000024 00000001204 14704245235 015231 0 ustar mike staff --TEST--
Wrong return values for binary protocol
--SKIPIF--
--FILE--
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";
var_dump ($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
bool(true)
add result code: 0
OK memcached-3.3.0/tests/rescode.phpt 0000644 0000765 0000024 00000003440 14704245235 015725 0 ustar mike staff --TEST--
Memcached result codes.
--SKIPIF--
--FILE--
getResultMessage(), "\n";
$m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT, 1);
echo $m->getResultCode(), "\n";
echo $m->getResultMessage(), "\n";
$m->set('bar_foo', 10);
echo $m->getResultMessage(), "\n";
$m->delete('bar_foo');
echo $m->getResultMessage(), "\n";
$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();
$m2 = new Memcached();
$m2->getMulti(array('asdf_a', 'jkhjkhjkb', 'nbahsdgc'));
echo $m2->getResultCode(), "\n";
echo $m2->getResultMessage(), "\n";
$m2->addServer('127.0.0.1', 7312, 1);
echo $m2->getResultCode(), "\n";
echo $m2->getResultMessage(), "\n";
$m2->delete('bar_foo');
echo $m2->getResultCode(), "\n";
echo $m2->getResultMessage(), "\n";
var_dump($m->getResultCode() == $code);
$m = memc_get_instance (array (), 'test1');
$m2 = new Memcached('test1');
$m->delete('moikkamitakuuluu');
echo $m->getResultMessage(), "\n";
$m2->set('minapaasetannih', 10, 1);
echo $m->getResultMessage(), "\n";
echo $m2->getResultMessage(), "\n";
$m->delete('bar_foo');
// clearly "NOT FOUND"
$m->delete('bar_foo');
$res_m = $m->getResultMessage();
echo $res_m, "\n";
$m2->set('bar_foo', 10);
echo $m->getResultMessage(), "\n";
echo $m2->getResultMessage(), "\n";
$m->delete('bar_foo');
echo $m->getResultMessage(), "\n";
?>
--EXPECTF--
SUCCESS
%d
SUCCESS
SUCCESS
SUCCESS
%d
NOT FOUND
SUCCESS
%d
NO SERVERS DEFINED
%d
SUCCESS
%d
%rSYSTEM ERROR|WRITE FAILURE|CONNECTION FAILURE%r
bool(true)
NOT FOUND
NOT FOUND
SUCCESS
NOT FOUND
NOT FOUND
SUCCESS
SUCCESS
memcached-3.3.0/tests/session_badconf_emptyprefix.phpt 0000644 0000765 0000024 00000001165 14704245235 022076 0 ustar mike staff --TEST--
Session bad configurations, prefix
--SKIPIF--
--INI--
memcached.sess_locking = on
memcached.sess_prefix = "memc.sess.key."
session.save_handler = "memcached"
--FILE--
--INI--
memcached.sess_locking = on
memcached.sess_lock_wait = -1
memcached.sess_prefix = "memc.sess.key."
session.save_path="127.0.0.1:51312"
session.save_handler = memcached
--FILE--
--INI--
session.save_handler = "memcached"
session.save_path = "PERSISTENT=1 hello:11211,world:11211"
--FILE--
--INI--
session.save_handler = memcached
--FILE--
70100) print "skip";
?>
--INI--
session.save_handler = memcached
--FILE--
--INI--
session.save_handler = memcached
--FILE--
--INI--
session.save_handler = memcached
memcached.sess_binary_protocol = Off
--FILE--
int(1)
}
array(0) {
}
memcached-3.3.0/tests/session_basic2.phpt 0000644 0000765 0000024 00000001326 14704245235 017210 0 ustar mike staff --TEST--
Session basic open, write, destroy
--SKIPIF--
--INI--
session.save_handler = memcached
memcached.sess_binary_protocol = Off
--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) {
}
memcached-3.3.0/tests/session_basic3.phpt 0000644 0000765 0000024 00000001337 14704245235 017213 0 ustar mike staff --TEST--
Session basic open, write, destroy
--SKIPIF--
--INI--
session.save_handler = memcached
memcached.sess_binary_protocol = Off
--FILE--
true
]);
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) {
}
memcached-3.3.0/tests/session_persistent.phpt 0000644 0000765 0000024 00000001166 14704245235 020247 0 ustar mike staff --TEST--
Session persistent
--SKIPIF--
--INI--
session.save_handler=memcached
memcached.sess_persistent=1
--FILE--
--EXPECT--
array(1) {
["test"]=>
bool(true)
}
memcached-3.3.0/tests/set_large.phpt 0000644 0000765 0000024 00000000576 14704245235 016255 0 ustar mike staff --TEST--
set large data
--SKIPIF--
--FILE--
0,
));
$key = 'foobarbazDEADC0DE';
$value = str_repeat("foo bar", 1024 * 1024);
var_dump($m->set($key, $value, 360));
var_dump($m->get($key) === $value);
?>
--EXPECT--
bool(true)
bool(true)
memcached-3.3.0/tests/setoptions.phpt 0000644 0000765 0000024 00000002262 14704245235 016511 0 ustar mike staff --TEST--
Set options using setOptions
--SKIPIF--
--FILE--
setOptions(array(
Memcached::OPT_PREFIX_KEY => 'a_prefix',
Memcached::OPT_SERIALIZER => Memcached::SERIALIZER_PHP,
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";
var_dump($m->setOptions(array(
"asdf" => 123
)));
var_dump($m->setOptions(array(
-1 => 123
)));
--EXPECTF--
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
test invalid options
Warning: Memcached::setOptions(): invalid configuration option in %s on line %d
bool(false)
Warning: Memcached::setOptions(): error setting memcached option: %s in %s on line %d
bool(false)
memcached-3.3.0/tests/touch_binary.phpt 0000644 0000765 0000024 00000003543 14704245235 016773 0 ustar mike staff --TEST--
Touch in binary mode
--SKIPIF--
--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 ($expected);
$code = resolve_to_constant ($code);
echo "{$op} status code mismatch, expected {$expected} but got {$code}" . PHP_EOL;
}
}
include dirname (__FILE__) . '/config.inc';
$mem = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true));
$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
memcached-3.3.0/tests/types.inc 0000644 0000765 0000024 00000005406 14704245235 015247 0 ustar mike staff "1","b" => "2","c" => "3")),
array('object_dummy', new testclass()),
);
foreach ($data as $key => $value) {
$m->delete($key);
}
foreach ($data as $types) {
$key = $types [0];
$value = $types [1];
$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 "=== {$key} ===\n";
echo "Expected: ";
var_dump($value);
echo "Actual: ";
var_dump($actual);
}
}
$m->flush();
if (($actual = $m->get(uniqid ('random_key_'))) !== false) {
echo "Expected: null";
echo "Actual: " . gettype($actual);
}
}
function memc_types_test_multi ($m, $options)
{
$data = array(
'boolean_true' => 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]);
}
}
}
memcached-3.3.0/tests/types_igbinary.phpt 0000644 0000765 0000024 00000000703 14704245235 017330 0 ustar mike staff --TEST--
Memcached store & fetch type and value correctness using igbinary serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_igbinary_multi.phpt 0000644 0000765 0000024 00000000725 14704245235 020546 0 ustar mike staff --TEST--
Memcached multi store & multi fetch type and value correctness using igbinary serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_json.phpt 0000644 0000765 0000024 00000000665 14704245235 016504 0 ustar mike staff --TEST--
Memcached store & fetch type and value correctness using JSON serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_json_multi.phpt 0000644 0000765 0000024 00000000707 14704245235 017713 0 ustar mike staff --TEST--
Memcached multi store & multi fetch type and value correctness using JSON serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_msgpack.phpt 0000644 0000765 0000024 00000000765 14704245235 017161 0 ustar mike staff --TEST--
Memcached store & fetch type and value correctness using msgpack serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_msgpack_multi.phpt 0000644 0000765 0000024 00000001001 14704245235 020353 0 ustar mike staff --TEST--
Memcached multi store & fetch type and value correctness using msgpack serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_php.phpt 0000644 0000765 0000024 00000000534 14704245235 016315 0 ustar mike staff --TEST--
Memcached store & fetch type and value correctness using PHP serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/types_php_multi.phpt 0000644 0000765 0000024 00000000550 14704245235 017525 0 ustar mike staff --TEST--
Memcached multi store & fetch type and value correctness using PHP serializer
--SKIPIF--
--FILE--
--EXPECT--
TEST DONE
memcached-3.3.0/tests/undefined_set.phpt 0000644 0000765 0000024 00000001171 14704245235 017114 0 ustar mike staff --TEST--
Set with undefined key and value
--SKIPIF--
--FILE--
'bar');
// 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);
var_dump($rv);
$rv = @$m->set($no_key, $no_value, 360);
var_dump($rv);
$rv = @$m->set($key, $value, $no_time);
var_dump($rv);
?>
--EXPECTF--
bool(false)
bool(true)
bool(false)
bool(true)
memcached-3.3.0/tests/vbucket.phpt 0000644 0000765 0000024 00000001163 14704245235 015744 0 ustar mike staff --TEST--
Memcached virtual buckets
--SKIPIF--
--FILE--
Memcached::DISTRIBUTION_VIRTUAL_BUCKET
));
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));
echo "OK\n";
?>
--EXPECTF--
bool(true)
bool(true)
bool(true)
OK
memcached-3.3.0/tests/vbucket_error_7.phpt 0000644 0000765 0000024 00000002037 14704245235 017404 0 ustar mike staff --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
memcached-3.3.0/tests/vbucket_error_8.phpt 0000644 0000765 0000024 00000002120 14704245235 017376 0 ustar mike staff --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
memcached-3.3.0/tests/user-flags.phpt 0000644 0000765 0000024 00000005024 14704245235 016351 0 ustar mike staff --TEST--
Memcached user flags
--SKIPIF--
--FILE--
get($key, null, Memcached::GET_EXTENDED)['flags'];
}
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));
include dirname (__FILE__) . '/config.inc';
$m = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true));
$key = uniqid ('udf_test_');
// Set with flags off
$m->set ($key, '1', 10);
$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(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(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(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64));
// 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->getMulti(array_keys($values), Memcached::GET_EXTENDED);
foreach (array_keys($values) as $key) {
check_flags($flags[$key]['flags'], 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, '1', 10);
$m->get($key);
check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4));
// Too large flags
$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE);
echo "DONE TEST\n";
?>
--EXPECTF--
array(3) {
["value"]=>
string(1) "1"
["cas"]=>
int(%d)
["flags"]=>
int(0)
}
Flags OK
Flags OK
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 memcached-3.3.0/tests/gh_93.phpt 0000644 0000765 0000024 00000001537 14704245235 015217 0 ustar mike staff --TEST--
Test for Github issue #93 (double and long overflow)
--SKIPIF--
--FILE--
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 memcached-3.3.0/tests/add.phpt 0000644 0000765 0000024 00000000525 14704245235 015032 0 ustar mike staff --TEST--
Memcached::add()
--SKIPIF--
--FILE--
delete('foo');
var_dump($m->add('foo', 1, 60));
var_dump($m->get('foo'));
var_dump($m->add('foo', 2, 60));
var_dump($m->get('foo'));
--EXPECT--
bool(true)
int(1)
bool(false)
int(1)
memcached-3.3.0/tests/bad_construct.phpt 0000644 0000765 0000024 00000001415 14704245235 017133 0 ustar mike staff --TEST--
Memcached construct with bad arguments
--SKIPIF--
= 80000) die("skip PHP 7 only");
?>
--FILE--
setOption (Memcached::OPT_BINARY_PROTOCOL, true));
echo "OK" . PHP_EOL;
--EXPECTF--
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 14
NULL
OK
memcached-3.3.0/tests/bad_construct_8.phpt 0000644 0000765 0000024 00000001275 14704245235 017366 0 ustar mike staff --TEST--
Memcached construct with bad arguments
--SKIPIF--
--FILE--
getMessage() . PHP_EOL;
}
class extended extends Memcached {
public function __construct () {
}
}
error_reporting(E_ALL);
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
Memcached constructor was not called
OK
memcached-3.3.0/tests/append.phpt 0000644 0000765 0000024 00000001213 14704245235 015544 0 ustar mike staff --TEST--
Memcached::append()
--SKIPIF--
--FILE--
delete('foo');
$m->setOption(Memcached::OPT_COMPRESSION, true);
var_dump($m->append('foo', 'a'));
echo error_get_last()["message"], "\n";
$m->setOption(Memcached::OPT_COMPRESSION, false);
$m->delete('foo');
var_dump($m->append('foo', 'a'));
var_dump($m->get('foo'));
$m->set('foo', 'a');
var_dump($m->append('foo', 'b'));
var_dump($m->get('foo'));
--EXPECTF--
NULL
%s: cannot append/prepend with compression turned on
bool(false)
bool(false)
bool(true)
string(2) "ab"
memcached-3.3.0/tests/prepend.phpt 0000644 0000765 0000024 00000001177 14704245235 015743 0 ustar mike staff --TEST--
Memcached::prepend()
--SKIPIF--
--FILE--
delete('foo');
$m->setOption(Memcached::OPT_COMPRESSION, true);
var_dump($m->prepend('foo', 'a'));
$m->setOption(Memcached::OPT_COMPRESSION, false);
$m->delete('foo');
var_dump($m->prepend('foo', 'a'));
var_dump($m->get('foo'));
$m->set('foo', 'a');
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
bool(false)
bool(false)
bool(true)
string(2) "ba"
memcached-3.3.0/tests/replace.phpt 0000644 0000765 0000024 00000000616 14704245235 015716 0 ustar mike staff --TEST--
Memcached::replace()
--SKIPIF--
--FILE--
delete('foo');
var_dump($m->replace('foo', 'bar', 60));
var_dump($m->get('foo'));
$m->set('foo', 'kef');
var_dump($m->replace('foo', 'bar', 60));
var_dump($m->get('foo'));
--EXPECT--
bool(false)
bool(false)
bool(true)
string(3) "bar"
memcached-3.3.0/tests/getmulti.phpt 0000644 0000765 0000024 00000001541 14704245235 016133 0 ustar mike staff --TEST--
Memcached::getMulti()
--SKIPIF--
--FILE--
setMulti($data));
$keys = array_keys($data);
$keys['last'] = new Foo();
$v = $m->getMulti($keys);
var_dump(is_array($v));
var_dump($m->getResultCode() == Memcached::RES_SUCCESS);
if (is_array($v)) {
foreach ($v as $key => $value) {
if (!isset($data[$key]) or $value !== $data[$key]) {
echo "mismatch \$data['$key'] = \n";
var_dump($data[$key]);
var_dump($value);
}
}
} else {
echo "Result not an array\n";
}
var_dump(is_object($keys['last']));
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
memcached-3.3.0/tests/setmulti.phpt 0000644 0000765 0000024 00000002220 14704245235 016142 0 ustar mike staff --TEST--
Memcached::setMulti()
--SKIPIF--
--FILE--
deleteMulti($keys);
echo "set keys: ";
var_dump($m->setMulti($data, 10));
echo "get: ";
$r = $m->getMulti($keys);
var_dump($r);
echo "Equal: ";
var_dump($r === $data);
--EXPECTF--
Data: array(%d) {
["foo"]=>
string(3) "bar"
[%i]=>
string(7) "int-max"
[%i]=>
string(7) "int-min"
[%i]=>
string(7) "int-min"
[0]=>
string(4) "zero"
[123]=>
string(11) "onetwothree"
[-123]=>
string(14) "negonetwothree"
}
set keys: bool(true)
get: array(%d) {
["foo"]=>
string(3) "bar"
[%i]=>
string(7) "int-max"
[%i]=>
string(7) "int-min"
[%i]=>
string(7) "int-min"
[0]=>
string(4) "zero"
[123]=>
string(11) "onetwothree"
[-123]=>
string(14) "negonetwothree"
}
Equal: bool(true)
memcached-3.3.0/tests/cachecallback.phpt 0000644 0000765 0000024 00000002267 14704245235 017027 0 ustar mike staff --TEST--
Memcached::get() with cache callback
--SKIPIF--
--FILE--
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";
$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 memcached-3.3.0/tests/incrdecr.phpt 0000644 0000765 0000024 00000002572 14704245235 016077 0 ustar mike staff --TEST--
Memcached::increment() Memcached::decrement()
--SKIPIF--
--FILE--
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);
var_dump($m->get('foo'));
$m->increment('foo');
var_dump($m->get('foo'));
$m->increment('foo', 2);
var_dump($m->get('foo'));
$m->decrement('foo');
var_dump($m->get('foo'));
$m->decrement('foo', 2);
var_dump($m->get('foo'));
error_reporting(0);
echo "Negative offset\n";
error_clear_last();
$m->increment('foo', -1);
echo error_get_last()["message"], "\n";
var_dump($m->get('foo'));
error_clear_last();
$m->decrement('foo', -1);
echo error_get_last()["message"], "\n";
var_dump($m->get('foo'));
echo "Enormous offset\n";
$m->increment('foo', 0x7f000000);
var_dump($m->get('foo'));
$m->decrement('foo', 0x7f000000);
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)
int(4)
int(3)
int(1)
Negative offset
Memcached::increment(): offset cannot be a negative value
int(1)
Memcached::decrement(): offset cannot be a negative value
int(1)
Enormous offset
int(2130706433)
int(1)
memcached-3.3.0/tests/incrdecr_64.phpt 0000644 0000765 0000024 00000001447 14704245235 016410 0 ustar mike staff --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)
memcached-3.3.0/tests/incrdecr_initial.phpt 0000644 0000765 0000024 00000002156 14704245235 017606 0 ustar mike staff --TEST--
Memcached::increment() Memcached::decrement() with initial support
--SKIPIF--
--FILE--
true
));
$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)
memcached-3.3.0/tests/incrdecr_invalid_key.phpt 0000644 0000765 0000024 00000000456 14704245235 020454 0 ustar mike staff --TEST--
Memcached::increment() Memcached::decrement() with invalid key
--SKIPIF--
--FILE--
increment('', 1));
var_dump($m->decrement('', 1));
?>
--EXPECT--
bool(false)
bool(false)
memcached-3.3.0/tests/incrdecr_bykey.phpt 0000644 0000765 0000024 00000002621 14704245235 017275 0 ustar mike staff --TEST--
Memcached::incrementByKey() Memcached::decrementByKey()
--SKIPIF--
--FILE--
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 "Negative offset\n";
error_clear_last();
$m->incrementByKey('foo', 'foo', -1);
echo error_get_last()["message"], "\n";
var_dump($m->get('foo'));
error_clear_last();
$m->decrementByKey('foo', 'foo', -1);
echo error_get_last()["message"], "\n";
var_dump($m->get('foo'));
echo "Enormous offset\n";
$m->incrementByKey('foo', 'foo', 0x7f000000);
var_dump($m->get('foo'));
$m->decrementByKey('foo', 'foo', 0x7f000000);
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)
Negative offset
Memcached::incrementByKey(): offset cannot be a negative value
int(1)
Memcached::decrementByKey(): offset cannot be a negative value
int(1)
Enormous offset
int(2130706433)
int(1)
memcached-3.3.0/tests/invalid_options.phpt 0000644 0000765 0000024 00000000544 14704245235 017504 0 ustar mike staff --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 memcached-3.3.0/tests/keys_ascii.phpt 0000644 0000765 0000024 00000006017 14704245235 016427 0 ustar mike staff --TEST--
Test valid and invalid keys - ascii
--SKIPIF--
--FILE--
false,
Memcached::OPT_VERIFY_KEY => true
));
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
memcached-3.3.0/tests/keys_binary.phpt 0000644 0000765 0000024 00000006410 14704245235 016620 0 ustar mike staff --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
memcached-3.3.0/tests/testdata.res 0000644 0000765 0000024 00000011415 14704245235 015731 0 ustar mike staff Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut malesuada purus vel diam congue condimentum. Vivamus diam erat, commodo eget lacinia venenatis, tempor at nulla. Praesent dapibus aliquam lectus. Aliquam erat volutpat. Praesent congue elementum ipsum, eu bibendum nisi ullamcorper nec. Aenean mattis metus quis libero hendrerit blandit accumsan nisi lacinia. Aenean varius sollicitudin nisl, tempor condimentum turpis congue id. Nunc vulputate purus non nunc dignissim tincidunt. Curabitur adipiscing est in ligula interdum a ultrices nibh ultricies. Aliquam a dapibus lectus.
Ut eleifend, dui nec aliquam lobortis, quam est luctus lectus, nec hendrerit augue quam ac odio. Nam condimentum, ligula et rhoncus vulputate, lorem urna adipiscing mauris, non mollis velit arcu non urna. Donec sodales ultrices risus, sed hendrerit libero fringilla vitae. Maecenas magna nisl, vehicula scelerisque hendrerit id, fermentum at lorem. Curabitur eu nisl tincidunt arcu venenatis ultricies. Vivamus velit lorem, hendrerit non imperdiet sit amet, eleifend nec mauris. Donec eget condimentum purus. Cras sed lorem sagittis augue faucibus tincidunt. Pellentesque vitae lorem ac orci dignissim tempor. Maecenas diam elit, pulvinar sed gravida rutrum, ultrices vel mauris. In adipiscing placerat eros imperdiet euismod. Nunc quis ante non lectus dictum porta. Nullam orci felis, tristique ut posuere at, tempor sed eros. Pellentesque accumsan posuere magna eu condimentum. Phasellus adipiscing cursus fringilla. Donec diam ipsum, pharetra quis tempus sit amet, mollis in dolor. Pellentesque volutpat vestibulum nulla quis ultricies. Pellentesque scelerisque erat eu nulla ullamcorper tincidunt.
Nullam commodo lobortis lacus, ac scelerisque diam dignissim eget. Cras eu metus sed tellus accumsan rutrum id ac nunc. Duis rutrum ipsum quis sapien dictum tincidunt. Duis gravida augue et sapien laoreet at pretium eros vulputate. Duis pulvinar lectus quis libero ultricies consequat a id felis. Morbi imperdiet venenatis ipsum eget ultricies. Vivamus fermentum urna sed massa tristique euismod. Pellentesque sed justo ut mi tincidunt luctus semper et elit. In hac habitasse platea dictumst. Praesent suscipit, elit quis fermentum luctus, magna dolor volutpat tellus, nec blandit nulla metus a lacus. Duis gravida, ipsum eu posuere congue, massa augue semper sapien, vel bibendum mi odio nec lectus. Vivamus lacinia urna vitae justo tincidunt dictum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc sed libero metus, in imperdiet nibh.
Integer sapien mauris, pretium sed sodales at, blandit in lacus. Etiam a nisl semper enim pellentesque posuere vitae quis lectus. Etiam ut libero at tortor molestie feugiat non ut ligula. Suspendisse fermentum ipsum vel mauris aliquet convallis. Fusce velit turpis, sollicitudin sit amet luctus id, porta nec ipsum. Fusce consequat, risus vel congue sollicitudin, orci sem auctor nisl, eu consectetur neque tortor id neque. Nunc in odio velit. Duis vitae lacus elit, eu fringilla nulla. Phasellus non mi tellus, volutpat commodo lorem. Pellentesque vel ligula enim. Morbi suscipit, orci sed gravida convallis, nunc leo eleifend lacus, quis elementum dui mi nec risus. Mauris faucibus arcu scelerisque tellus semper dictum. Suspendisse vel posuere turpis. Curabitur ipsum ligula, auctor ut dignissim vel, scelerisque vel mauris. Vivamus est dolor, bibendum ac vestibulum a, congue id felis. Mauris rutrum pharetra tempus. Sed ornare congue purus, id adipiscing mi tincidunt at. Maecenas blandit, lorem in malesuada adipiscing, dolor arcu suscipit magna, ut mollis leo nibh non orci. Sed non massa ipsum, et lobortis tortor. Aliquam et egestas velit.
Mauris ac sem eget elit imperdiet faucibus at non turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent vel dui vitae enim imperdiet sodales. Maecenas a tristique mauris. Praesent consectetur risus sit amet lacus dictum ut egestas nibh lacinia. Mauris quam augue, fringilla ac pretium a, consectetur sed risus. Sed ullamcorper eleifend dolor, id tempor arcu sodales at. Vestibulum eget sagittis libero. Cras ornare dui ac ante pretium fringilla. Morbi eu tincidunt felis. Vivamus ultrices diam in eros elementum luctus. Aenean eu neque nibh. Mauris neque est, euismod ut rutrum nec, vehicula at magna. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce sit amet neque ac justo pretium laoreet. Duis non sapien ut eros tristique porttitor vel et lacus. Donec molestie nunc malesuada ante porta ac pretium magna dictum. Nam dolor orci, lacinia egestas ornare eget, viverra et mi. Vivamus convallis lobortis dui, ac sagittis urna mattis sit amet. Duis interdum, est sed dignissim blandit, metus elit scelerisque mauris, sit amet egestas velit arcu quis nunc.
memcached-3.3.0/tests/config.inc 0000644 0000765 0000024 00000003646 14704245235 015354 0 ustar mike staff setOptions ($opts) == false)
echo "Failed to set options" . PHP_EOL;
$memcached->addServer($host, $port);
if ($memcached->flush() === false) {
return NULL;
}
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) {
$memc = memc_get_instance ($option_set ['options']);
$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_version($memc) {
$version = $memc->getVersion();
return array_pop($version);
}
memcached-3.3.0/tests/sasl_basic.phpt 0000644 0000765 0000024 00000001365 14704245235 016410 0 ustar mike staff --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
memcached-3.3.0/tests/set_encoding_key.phpt 0000644 0000765 0000024 00000002570 14704245235 017615 0 ustar mike staff --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
memcached-3.3.0/tests/set_encoding_key2.phpt 0000644 0000765 0000024 00000002004 14704245235 017667 0 ustar mike staff --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
memcached-3.3.0/tests/getserverbykey.phpt 0000644 0000765 0000024 00000001777 14704245235 017366 0 ustar mike staff --TEST--
Memcached::getServerByKey()
--SKIPIF--
--FILE--
getServerByKey("a"));
$m->addServer('localhost', 11211, 1);
$m->addServer('localhost', 11212, 1);
$m->addServer('localhost', 11213, 1);
$m->addServer('localhost', 11214, 1);
$m->addServer('localhost', 11215, 1);
var_dump($m->getServerByKey(""));
echo $m->getResultMessage(), "\n";
var_dump($m->getServerByKey("a"));
var_dump($m->getServerByKey("b"));
var_dump($m->getServerByKey("c"));
var_dump($m->getServerByKey("d"));
--EXPECTF--
bool(false)
bool(false)
A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE
array(%d) {
["host"]=>
string(%d) "%s"
["port"]=>
int(%d)
["weight"]=>
int(0)
}
array(%d) {
["host"]=>
string(%d) "%s"
["port"]=>
int(%d)
["weight"]=>
int(0)
}
array(%d) {
["host"]=>
string(%d) "%s"
["port"]=>
int(%d)
["weight"]=>
int(0)
}
array(%d) {
["host"]=>
string(%d) "%s"
["port"]=>
int(%d)
["weight"]=>
int(0)
}
memcached-3.3.0/tests/gh_155.phpt 0000644 0000765 0000024 00000002314 14704245235 015270 0 ustar mike staff --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
memcached-3.3.0/tests/get_flags.phpt 0000644 0000765 0000024 00000002201 14704245235 016226 0 ustar mike staff --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 memcached-3.3.0/tests/session_lock.phpt 0000644 0000765 0000024 00000002754 14704245235 017003 0 ustar mike staff --TEST--
Session lock
--SKIPIF--
= 70100) print "skip";
?>
--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."
# 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--
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
memcached-3.3.0/tests/session_lazy_warning.phpt 0000644 0000765 0000024 00000002004 14704245235 020543 0 ustar mike staff --TEST--
Session lazy binary warning old libmemcached
--SKIPIF--
= 0x01000018) die ('skip too recent 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) {
}
memcached-3.3.0/tests/session_regenerate.phpt 0000644 0000765 0000024 00000000745 14704245235 020172 0 ustar mike staff --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);
var_dump (is_int ($stats[$key]['cmd_get']));
echo "OK";
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
OK
memcached-3.3.0/tests/stats_hang.phpt 0000644 0000765 0000024 00000004255 14704245235 016441 0 ustar mike staff --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
memcached-3.3.0/tests/default_behavior.phpt 0000644 0000765 0000024 00000001472 14704245235 017607 0 ustar mike staff --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
memcached-3.3.0/tests/reset_keyprefix.phpt 0000644 0000765 0000024 00000001440 14704245235 017507 0 ustar mike staff --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" memcached-3.3.0/tests/session_lock-php71.phpt 0000644 0000765 0000024 00000003126 14704245235 017732 0 ustar mike staff --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."
# 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--
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
memcached-3.3.0/tests/server.inc 0000644 0000765 0000024 00000004412 14704245235 015405 0 ustar mike staff 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 < getenv("VALGRIND") ? 1000 : 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 {$status['command']}\n";
break;
}
// Success, Connected to servers
if ($fp) {
$error = '';
break;
}
}
if ($fp) {
fclose($fp);
}
if ($error) {
echo $error;
proc_terminate($handle);
proc_close($handle);
exit(1);
}
register_shutdown_function(
function($handle) {
if (is_resource($handle)) {
proc_terminate($handle);
proc_close($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);
}
proc_close($handle);
}
return $success;
}
memcached-3.3.0/tests/server.php 0000644 0000765 0000024 00000011274 14704245235 015427 0 ustar mike staff 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, 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"];
} elseif ($key === "empty") {
$values = [];
} else {
$values["key"] = $key;
$values["foo"] = "bar";
}
return Memcached::RESPONSE_SUCCESS;
});
$server->on (Memcached::ON_VERSION,
function ($client_id, &$value) {
echo "client_id=[$client_id]: Version" . PHP_EOL;
$value = "1.1.1";
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);
memcached-3.3.0/tests/memcachedserver.phpt 0000644 0000765 0000024 00000005530 14704245235 017440 0 ustar mike staff --TEST--
MemcachedServer
--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->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();
usleep(50000);
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]
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(2) {
["key"]=>
string(0) ""
["foo"]=>
string(3) "bar"
}
}
client_id=[%s]: Stat key=[empty]
array(0) {
}
client_id=[%s]: Stat key=[foobar]
array(1) {
["127.0.0.1:3434"]=>
array(2) {
["key"]=>
string(6) "foobar"
["foo"]=>
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
memcached-3.3.0/tests/memcachedserver6.phpt 0000644 0000765 0000024 00000005517 14704245235 017533 0 ustar mike staff --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();
usleep(50000);
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
memcached-3.3.0/README.markdown 0000644 0000765 0000024 00000003650 14704245235 014746 0 ustar mike staff Build Status
------------

Description
-----------
This is the [PECL memcached](https://pecl.php.net/package/memcached) extension,
using the libmemcached library to connect to memcached servers.
[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
--------
$ phpize
$ ./configure
$ make
$ make test
Dependencies
------------
php-memcached 3.x:
* 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.
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) 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
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.
memcached-3.3.0/CREDITS 0000644 0000765 0000024 00000000073 14704245235 013261 0 ustar mike staff memcached
Andrei Zmievski, Oleg Grenrus (igbinary support)
memcached-3.3.0/LICENSE 0000644 0000765 0000024 00000006222 14704245235 013250 0 ustar mike staff --------------------------------------------------------------------
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
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"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,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
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 .
PHP includes the Zend Engine, freely available at
.
memcached-3.3.0/ChangeLog 0000644 0000765 0000024 00000027417 14704245235 014026 0 ustar mike staff 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)
--------------------------
* 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)
--------------------------
* 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 (2018-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)
--------------------------
* 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)
--------------------------
* 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)
--------------------------
* 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)
* 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
* 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
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
* 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
* 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
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 (2012-03-03)
--------------------------
* Fix embedded version number to be not -dev
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 (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)
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
* 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
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 (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 (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.
* Add 'flags' parameter to getMulti() and getMultiByKey().
* Add GET_PRESERVE_ORDER class constant that can be used with
abovementioned flags parameter to make the order of the keys in the
response match the request.
* Fix an issue with retrieving 0-length payloads (FALSE boolean value).
* Refactor the way payload types are stored in memcached flags to optimize
the structure and allow for future expansion. WARNING! You have to flush
the cache when upgrading to this version.
* Add several tests.
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 (2009-02-13)
--------------------------
* Fix compilation against PHP 5.3.
* Add support for 'igbinary' serializer (Oleg Grenrus)
Version 0.1.3 (2009-02-06)
--------------------------
* Bludgeon bug #15896 (Memcached setMulti error) into submission.
Version 0.1.2 (2009-02-06)
--------------------------
* Fix bug #15896 (Memcached setMulti error).
* Check for empty key in getServerByKey().
* Allow passing 'null' for callbacks.
* get() with cas token fetching wasn't erroring out properly.
* Rename certain parameters in the API to be more clear.
* Allow only strings as the append/prepend value.
* Remove expiration parameter from append/prepend.
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 (2009-01-29)
--------------------------
* Initial release
memcached-3.3.0/memcached-api.php 0000644 0000765 0000024 00000016067 14704245235 015441 0 ustar mike staff comp_len * factor
;
; the default value is 1.3 (23% space saving)
;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
; Set the default serializer for new memcached objects.
; 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
; encoded data and does not fully implement
; serializing. See the JSON extension.
; 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, then msgpack if available, then php otherwise.
;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 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)
;
; 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
memcached-3.3.0/fastlz/LICENSE 0000644 0000765 0000024 00000002312 14704245235 014547 0 ustar mike staff FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
memcached-3.3.0/config.m4 0000644 0000765 0000024 00000036077 14704245235 013765 0 ustar mike staff dnl vim:se ts=2 sw=2 et:
PHP_ARG_ENABLE(memcached, whether to 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)
PHP_ARG_ENABLE(memcached-session, whether to enable memcached session handler support,
[ --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)
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 enable memcached sasl support,
[ --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)
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)
fi
if test -z "$PHP_DEBUG"; then
AC_ARG_ENABLE(debug,
[ --enable-debug Compile with debugging symbols],[
PHP_DEBUG=$enableval
],[ PHP_DEBUG=no
])
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
if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then
PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib"
elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then
PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include"
else
AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"])
fi
else
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"
elif test -f "$i/include/zlib.h"; then
PHP_ZLIB_DIR="$i"
PHP_ZLIB_INCDIR="$i/include"
fi
done
fi
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, 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])
fi
if test "$PHP_MEMCACHED_SESSION" != "no"; then
AC_MSG_CHECKING([for session includes])
session_inc_path=""
if test -f "$abs_srcdir/include/php/ext/session/php_session.h"; then
session_inc_path="$abs_srcdir/include/php"
elif test -f "$abs_srcdir/ext/session/php_session.h"; then
session_inc_path="$abs_srcdir"
elif test -f "$phpincludedir/ext/session/php_session.h"; then
session_inc_path="$phpincludedir"
else
for i in php php4 php5 php6; do
if test -f "$prefix/include/$i/ext/session/php_session.h"; then
session_inc_path="$prefix/include/$i"
fi
done
fi
if test "$session_inc_path" = ""; then
AC_MSG_ERROR([Cannot find php_session.h])
else
AC_MSG_RESULT([$session_inc_path])
fi
fi
if test "$PHP_MEMCACHED_JSON" != "no"; then
AC_MSG_CHECKING([for json includes])
json_inc_path=""
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
fi
if test "$PHP_MEMCACHED_IGBINARY" != "no"; then
AC_MSG_CHECKING([for igbinary includes])
igbinary_inc_path=""
if test -f "$abs_srcdir/include/php/ext/igbinary/igbinary.h"; then
igbinary_inc_path="$abs_srcdir/include/php"
elif test -f "$abs_srcdir/ext/igbinary/igbinary.h"; 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
igbinary_inc_path="$prefix/include/$i"
fi
done
fi
if test "$igbinary_inc_path" = ""; then
AC_MSG_ERROR([Cannot find igbinary.h])
else
AC_MSG_RESULT([$igbinary_inc_path])
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])
AC_DEFINE(HAVE_MEMCACHED_SESSION,1,[Whether memcache session handler is enabled])
SESSION_INCLUDES="-I$session_inc_path"
ifdef([PHP_ADD_EXTENSION_DEP],
[
PHP_ADD_EXTENSION_DEP(memcached, session)
])
else
SESSION_INCLUDES=""
AC_MSG_RESULT([disabled])
fi
AC_MSG_CHECKING([for memcached igbinary support])
if test "$PHP_MEMCACHED_IGBINARY" != "no"; then
AC_MSG_RESULT([enabled])
AC_DEFINE(HAVE_MEMCACHED_IGBINARY,1,[Whether memcache igbinary serializer is enabled])
IGBINARY_INCLUDES="-I$igbinary_inc_path"
ifdef([PHP_ADD_EXTENSION_DEP],
[
PHP_ADD_EXTENSION_DEP(memcached, igbinary)
])
else
IGBINARY_INCLUDES=""
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
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
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
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
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_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"
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_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"]
)
])
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)
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, libmemcached built with sasl disabled. Run configure with --disable-memcached-sasl or update libmemcached with sasl support])
fi
else
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_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"
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_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"
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
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_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
LIBEVENT_INCLUDES=""
AC_MSG_CHECKING([for memcached protocol support])
if test "$PHP_MEMCACHED_PROTOCOL" != "no"; then
AC_MSG_RESULT([enabled])
AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [
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"]
)
])
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_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`
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"
AC_DEFINE(HAVE_MEMCACHED_PROTOCOL,1,[Whether memcached protocol is enabled])
else
AC_MSG_RESULT([disabled])
fi
CFLAGS="$ORIG_CFLAGS"
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)
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)
])
fi
fi
memcached-3.3.0/config.w32 0000644 0000765 0000024 00000003556 14704245235 014054 0 ustar mike staff // vim:ft=javascript
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") {
if (!CHECK_LIB("memcached.lib;libmemcached.lib", "memcached", PHP_MEMCACHED)) {
ERROR("memcached: library 'memcached' not found");
}
if (!CHECK_HEADER_ADD_INCLUDE("libmemcached/memcached.h", "CFLAGS_MEMCACHED")) {
ERROR("memcached: header 'libmemcached/memcached.h' not found");
}
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");
}
}
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");
AC_DEFINE("MEMCACHED_EXPORTS", 1)
}
memcached-3.3.0/php_memcached.c 0000644 0000765 0000024 00000404772 14704245235 015200 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
*/
/* TODO
* - set LIBKETAMA_COMPATIBLE as the default?
* - fix unserialize(serialize($memc))
*/
#include "php_memcached.h"
#include "php_memcached_private.h"
#include "php_memcached_server.h"
#include "g_fmt.h"
#include
#include
#ifdef HAVE_MEMCACHED_SESSION
# include "php_memcached_session.h"
#endif
#ifdef HAVE_FASTLZ_H
#include
#else
#include "fastlz/fastlz.h"
#endif
#include
#ifdef HAVE_ZSTD_H
#include
#endif
#ifdef HAVE_JSON_API
# include "ext/json/php_json.h"
#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"
#endif
# include "ext/spl/spl_exceptions.h"
static int le_memc;
static int php_memc_list_entry(void) {
return le_memc;
}
/****************************************
Protocol parameters
****************************************/
#define MEMC_OBJECT_KEY_MAX_LENGTH 250
/****************************************
Custom options
****************************************/
#define MEMC_OPT_COMPRESSION -1001
#define MEMC_OPT_PREFIX_KEY -1002
#define MEMC_OPT_SERIALIZER -1003
#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
#define MEMC_OPT_ITEM_SIZE_LIMIT -1008
/****************************************
Custom result codes
****************************************/
#define MEMC_RES_PAYLOAD_FAILURE -1001
/****************************************
Payload value flags
****************************************/
#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)
#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
#define MEMC_VAL_IS_DOUBLE 2
#define MEMC_VAL_IS_BOOL 3
#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<<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))
#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_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 ((1 << 16) - 1)
/****************************************
"get" operation flags
****************************************/
#define MEMC_GET_PRESERVE_ORDER 1
#define MEMC_GET_EXTENDED 2
/****************************************
Helper macros
****************************************/
#define RETURN_FROM_GET RETURN_FALSE
/****************************************
Structures and definitions
****************************************/
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_enabled;
zend_bool encoding_enabled;
zend_long serializer;
zend_long compression_type;
zend_long compression_level;
zend_long store_retry_count;
zend_long set_udf_flags;
zend_long item_size_limit;
#ifdef HAVE_MEMCACHED_SASL
zend_bool has_sasl_data;
#endif
} php_memc_user_data_t;
typedef struct {
memcached_st *memc;
zend_bool is_pristine;
int rescode;
int memc_errno;
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));
}
#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;
#if PHP_VERSION_ID < 80000
#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); \
(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)
{
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;
}
}
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);
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;
}
#define MEMC_CHECK_KEY(intern, key) \
if (UNEXPECTED(ZSTR_LEN(key) == 0 || \
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, memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)) \
))) { \
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \
RETURN_FALSE; \
}
#ifdef HAVE_MEMCACHED_PROTOCOL
typedef struct {
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))
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;
ZEND_DECLARE_MODULE_GLOBALS(php_memcached)
#ifdef COMPILE_DL_MEMCACHED
ZEND_GET_MODULE(memcached)
#endif
static PHP_INI_MH(OnUpdateCompressionType)
{
if (!new_value) {
MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ;
} else if (!strcmp(ZSTR_VAL(new_value), "fastlz")) {
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;
}
return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
}
static PHP_INI_MH(OnUpdateSerializer)
{
if (!new_value) {
MEMC_G(serializer_type) = SERIALIZER_DEFAULT;
} else if (!strcmp(ZSTR_VAL(new_value), "php")) {
MEMC_G(serializer_type) = SERIALIZER_PHP;
#ifdef HAVE_MEMCACHED_IGBINARY
} else if (!strcmp(ZSTR_VAL(new_value), "igbinary")) {
MEMC_G(serializer_type) = SERIALIZER_IGBINARY;
#endif // IGBINARY
#ifdef HAVE_JSON_API
} else if (!strcmp(ZSTR_VAL(new_value), "json")) {
MEMC_G(serializer_type) = SERIALIZER_JSON;
} 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(ZSTR_VAL(new_value), "msgpack")) {
MEMC_G(serializer_type) = SERIALIZER_MSGPACK;
#endif // msgpack
} else {
return FAILURE;
}
return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
}
#ifdef HAVE_MEMCACHED_SESSION
static
PHP_INI_MH(OnUpdateDeprecatedLockValue)
{
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;
}
static
PHP_INI_MH(OnUpdateSessionPrefixString)
{
if (new_value && ZSTR_LEN(new_value) > 0) {
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(new_value, 1)) {
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);
}
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);
}
#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)
#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()
#ifdef HAVE_MEMCACHED_SESSION
MEMC_SESSION_INI_BOOL ("locking", "1", OnUpdateBool, lock_enabled)
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
MEMC_SESSION_INI_BOOL ("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled)
#else
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)
MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit)
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)
MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.key.", OnUpdateSessionPrefixString, prefix)
/* 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_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)
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)
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
/****************************************
Forward declarations
****************************************/
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_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);
/* Invoke PHP functions */
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);
static
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,
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
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);
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);
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(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);
/****************************************
Exported helper functions
****************************************/
zend_bool php_memc_init_sasl_if_needed()
{
#ifdef 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
}
char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
{
char *buffer = NULL;
if (fci->object) {
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));
}
else {
spprintf (&buffer, 0, "%s", Z_STRVAL(fci->function_name));
}
}
return buffer;
}
/****************************************
Handling error codes
****************************************/
static
zend_bool s_memcached_return_is_error(memcached_return status, zend_bool strict)
{
zend_bool result = 0;
switch (status) {
case MEMCACHED_SUCCESS:
case MEMCACHED_STORED:
case MEMCACHED_DELETED:
case MEMCACHED_STAT:
case MEMCACHED_END:
case MEMCACHED_BUFFERED:
result = 0;
break;
case MEMCACHED_SOME_ERRORS:
result = strict;
break;
default:
result = 1;
break;
}
return result;
}
static
int s_memc_status_handle_result_code(php_memc_object_t *intern, memcached_return status)
{
intern->rescode = status;
intern->memc_errno = 0;
if (s_memcached_return_is_error(status, 1)) {
intern->memc_errno = memcached_last_error_errno(intern->memc);
return FAILURE;
}
return SUCCESS;
}
static
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
zend_bool s_memc_status_has_error(php_memc_object_t *intern)
{
return s_memcached_return_is_error(intern->rescode, 1);
}
static
zend_bool s_memc_status_has_result_code(php_memc_object_t *intern, memcached_return status)
{
return intern->rescode == status;
}
/****************************************
Marshall cas tokens
****************************************/
static
void s_uint64_to_zval (zval *target, uint64_t value)
{
if (value >= ((uint64_t) LONG_MAX)) {
zend_string *buffer;
#ifdef PRIu64
buffer = strpprintf (0, "%" PRIu64, value);
#else
/* Best effort */
buffer = strpprintf (0, "%llu", value);
#endif
ZVAL_STR(target, buffer);
}
else {
ZVAL_LONG (target, (zend_long) 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;
}
/****************************************
Iterate over memcached results and mget
****************************************/
static
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;
memcached_result_create(intern->memc, &result);
do {
result_ptr = memcached_fetch_result(intern->memc, &result, &rc);
if (s_memcached_return_is_error(rc, 0)) {
status = rc;
}
/* nothing returned */
if (!result_ptr) {
break;
}
else {
zend_string *key;
zval val, zcas;
zend_bool retval;
uint64_t cas;
uint32_t flags;
const char *res_key;
size_t res_key_len;
if (!s_memcached_result_to_zval(intern->memc, &result, &val)) {
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);
s_uint64_to_zval(&zcas, cas);
key = zend_string_init (res_key, res_key_len, 0);
retval = result_apply_fn(intern, key, &val, &zcas, flags, context);
zend_string_release(key);
zval_ptr_dtor(&val);
zval_ptr_dtor(&zcas);
/* Stop iterating on false */
if (!retval) {
if (!fetch_delay) {
/* Make sure we clear our results */
while (memcached_fetch_result(intern->memc, &result, &rc)) {}
}
break;
}
}
} 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;
int mget_status;
uint64_t orig_cas_flag = 0;
// Reset status code
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
if (!keys->num_valid_keys) {
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED;
return 0;
}
if (with_cas) {
orig_cas_flag = memcached_behavior_get (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
if (!orig_cas_flag) {
memcached_behavior_set (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
}
}
if (server_key) {
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);
}
/* 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);
}
/* Return on failure codes */
if (mget_status == FAILURE) {
return 0;
}
if (!result_apply_fn) {
/* no callback, for example getDelayed */
return 1;
}
status = php_memc_result_apply(intern, result_apply_fn, 0, context);
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
return 0;
}
return 1;
}
/****************************************
Invoke callbacks
****************************************/
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;
zval params[2];
ZVAL_COPY(¶ms[0], object);
if (persistent_id) {
ZVAL_STR(¶ms[1], zend_string_copy(persistent_id));
} else {
ZVAL_NULL(¶ms[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);
php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf);
efree (buf);
ret = 0;
}
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
zval_ptr_dtor(&retval);
return ret;
}
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)
{
zend_bool status = 0;
zval params[4];
zval retval;
php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject);
/* Prepare params */
ZVAL_COPY(¶ms[0], zobject);
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;
if (zend_call_function(fci, fcc) == SUCCESS) {
if (zend_is_true(&retval)) {
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 {
s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0);
}
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
zval_ptr_dtor(¶ms[2]);
if (!with_cas) {
zval_ptr_dtor(¶ms[3]);
}
zval_ptr_dtor(&retval);
return status;
}
/****************************************
Wrapper for setting from zval
****************************************/
static
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;
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);
char *buffer = emalloc(buffer_size);
/* Store compressed size here */
size_t compressed_size = 0;
uint32_t original_size = ZSTR_LEN(payload);
switch (compression_type) {
case COMPRESSION_TYPE_FASTLZ:
{
compressed_size = fastlz_compress(ZSTR_VAL(payload), ZSTR_LEN(payload), buffer);
if (compressed_size > 0) {
compress_status = 1;
compression_type_flag = MEMC_VAL_COMPRESSION_FASTLZ;
}
}
break;
#ifdef HAVE_ZSTD_H
case COMPRESSION_TYPE_ZSTD:
{
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;
compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD;
}
}
break;
#endif
case COMPRESSION_TYPE_ZLIB:
{
unsigned long cs = compressed_size = buffer_size;
if (compression_level < 0) {
compression_level = 0;
} else if (compression_level > 9) {
compression_level = 9;
}
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;
}
}
break;
default:
compress_status = 0;
break;
}
/* This means the value was too small to be compressed and ended up larger */
if (ZSTR_LEN(payload) <= (compressed_size * MEMC_G(compression_factor))) {
compress_status = 0;
}
/* 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);
/* 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;
return 1;
}
/* Original payload was not modified */
efree(buffer);
return 0;
}
static
zend_bool s_serialize_value (php_memc_serializer_type serializer, zval *value, smart_str *buf, uint32_t *flags)
{
switch (serializer) {
/*
Igbinary serialization
*/
#ifdef HAVE_MEMCACHED_IGBINARY
case SERIALIZER_IGBINARY:
{
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, (char *)buffer, buffer_len);
efree(buffer);
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY);
}
break;
#endif
/*
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
/*
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;
}
/* Check for exceptions caused by serializers */
if (EG(exception) && buf->s->len) {
return 0;
}
return 1;
}
static
zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t *flags)
{
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;
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;
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;
case IS_TRUE:
payload = zend_string_init ("1", 1, 0);
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL);
should_compress = 0;
break;
case IS_FALSE:
payload = zend_string_alloc (0, 0);
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL);
should_compress = 0;
break;
default:
{
smart_str buffer = {0};
if (!s_serialize_value (memc_user_data->serializer, value, &buffer, flags)) {
smart_str_free(&buffer);
return NULL;
}
payload = buffer.s;
}
break;
}
/* turn off compression for values below the threshold */
if (ZSTR_LEN(payload) == 0 || ZSTR_LEN(payload) < MEMC_G(compression_threshold)) {
should_compress = 0;
}
/* If we have compression flag, compress the value */
if (should_compress) {
/* 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, memc_user_data->compression_level, &payload, flags);
}
if (memc_user_data->set_udf_flags >= 0) {
MEMC_VAL_SET_USER_FLAGS(*flags, ((uint32_t) memc_user_data->set_udf_flags));
}
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)
{
if (memcached_server_count (intern->memc) == 0) {
return 0;
}
return s_memcached_return_is_error (status, 1);
}
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)
{
uint32_t flags = 0;
zend_string *payload = NULL;
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;
if (value) {
payload = s_zval_to_payload(intern, value, &flags);
if (!payload) {
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;
#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) {
case MEMC_OP_SET:
status = memc_write_using_fn_by_key(memcached_set_by_key);
break;
case MEMC_OP_TOUCH:
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:
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;
case MEMC_OP_PREPEND:
status = memc_write_using_fn_by_key(memcached_prepend_by_key);
break;
}
if (status == MEMCACHED_END) {
status = MEMCACHED_SUCCESS;
}
}
else {
retry:
switch (op) {
case MEMC_OP_SET:
status = memc_write_using_fn(memcached_set);
break;
case MEMC_OP_TOUCH:
status = php_memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), 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;
case MEMC_OP_PREPEND:
status = memc_write_using_fn(memcached_prepend);
break;
}
if (status == MEMCACHED_END) {
status = MEMCACHED_SUCCESS;
}
}
if (s_should_retry_write (intern, status) && retries-- > 0) {
goto retry;
}
#undef memc_write_using_fn
#undef memc_write_using_fn_by_key
if (payload) {
zend_string_release(payload);
}
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
return 0;
}
return 1;
}
/****************************************
Methods
****************************************/
/* {{{ 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;
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;
/* "|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;
if (persistent_id && persistent_id->len) {
zend_resource *le;
plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0);
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()) {
intern->memc = le->ptr;
intern->is_pristine = 0;
zend_string_release (plist_key);
return;
}
}
is_persistent = 1;
}
if (conn_str && conn_str->len > 0) {
intern->memc = memcached (ZSTR_VAL(conn_str), ZSTR_LEN(conn_str));
}
else {
intern->memc = memcached (NULL, 0);
}
if (!intern->memc) {
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);
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);
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);
/* 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));
}
}
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));
}
/* 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)) {
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));
}
}
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;
}
}
if (plist_key) {
zend_resource le;
le.type = php_memc_list_entry();
le.ptr = intern->memc;
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) {
zend_string_release(plist_key);
php_error_docref(NULL, E_ERROR, "could not register persistent entry");
/* not reached */
}
zend_string_release(plist_key);
}
}
/* }}} */
static
void s_hash_to_keys(php_memc_keys_t *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 *));
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, ZSTR_VAL(key), ZSTR_LEN(key));
}
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++;
}
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;
}
static
void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key)
{
zval zv_keys;
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);
}
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]);
}
efree(keys->strings);
efree(keys->mkeys);
efree(keys->mkeys_len);
}
typedef struct {
zend_bool extended;
zval *return_value;
} php_memc_get_ctx_t;
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_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_COPY(context->return_value, value);
}
return 0; /* Stop after one */
}
static
void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
php_memc_get_ctx_t context = {0};
php_memc_keys_t keys = {0};
zend_long get_flags = 0;
zend_string *key;
zend_string *server_key = NULL;
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;
MEMC_METHOD_INIT_VARS;
if (by_key) {
/* "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 {
/* "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;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
MEMC_CHECK_KEY(intern, key);
context.extended = (get_flags & MEMC_GET_EXTENDED);
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, context.extended, 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::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);
}
/* }}} */
/* {{{ 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);
}
/* }}} */
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_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));
zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node);
}
else {
zend_symtable_update(Z_ARRVAL_P(context->return_value), key, value);
}
return 1;
}
/* {{{ -- php_memc_getMulti_impl */
static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
php_memc_get_ctx_t context;
php_memc_keys_t keys_out;
zval *keys = NULL;
zend_string *server_key = NULL;
zend_long flags = 0;
MEMC_METHOD_INIT_VARS;
zend_bool retval, preserve_order;
if (by_key) {
/* "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 {
/* "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;
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);
context.extended = (flags & MEMC_GET_EXTENDED);
context.return_value = return_value;
retval = php_memc_mget_apply(intern, server_key, &keys_out, s_get_multi_apply_fn, context.extended, &context);
s_clear_keys(&keys_out);
if (!retval && (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) || s_memc_status_has_result_code(intern, MEMCACHED_SOME_ERRORS))) {
return;
}
if (!retval || EG(exception)) {
zval_dtor(return_value);
RETURN_FROM_GET;
}
}
/* }}} */
/* {{{ 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)
{
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);
}
/* }}} */
static
void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t flags, zval *return_value)
{
Z_TRY_ADDREF_P(value);
Z_TRY_ADDREF_P(cas);
add_assoc_str_ex(return_value, ZEND_STRL("key"), zend_string_copy(key));
add_assoc_zval_ex(return_value, ZEND_STRL("value"), value);
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
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 params[2];
zval retval;
php_memc_result_callback_ctx_t *context = (php_memc_result_callback_ctx_t *) in_context;
ZVAL_COPY(¶ms[0], context->object);
array_init(¶ms[1]);
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) {
php_error_docref(NULL, E_WARNING, "could not invoke result callback");
status = 0;
}
zval_ptr_dtor(&retval);
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
return status;
}
/* {{{ -- php_memc_getDelayed_impl */
static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
php_memc_keys_t keys_out = {0};
zval *keys = NULL;
zend_string *server_key = NULL;
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) {
/* "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 {
/* "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;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL);
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 {
status = php_memc_mget_apply(intern, server_key, &keys_out, NULL, with_cas, NULL);
}
s_clear_keys(&keys_out);
RETURN_BOOL(status);
}
/* }}} */
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);
return 0; // stop iterating after one
}
/* {{{ Memcached::fetch()
Returns the next result from a previous delayed request */
PHP_METHOD(Memcached, fetch)
{
memcached_return status = MEMCACHED_SUCCESS;
MEMC_METHOD_INIT_VARS;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
MEMC_METHOD_FETCH_OBJECT;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
array_init(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);
RETURN_FROM_GET;
}
}
/* }}} */
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;
array_init (&zv);
s_create_result_array(key, value, cas, flags, &zv);
add_next_index_zval(return_value, &zv);
return 1;
}
/* {{{ Memcached::fetchAll()
Returns all the results from a previous delayed request */
PHP_METHOD(Memcached, fetchAll)
{
memcached_return status = MEMCACHED_SUCCESS;
MEMC_METHOD_INIT_VARS;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
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, 0, return_value);
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
zval_dtor(return_value);
RETURN_FALSE;
}
}
/* }}} */
/* {{{ 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);
}
/* }}} */
/* {{{ 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_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1);
}
/* }}} */
/* {{{ 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)
{
php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ 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_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
/* {{{ -- php_memc_setMulti_impl */
static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
zval *entries;
zend_string *server_key = NULL;
zend_long expiration = 0;
zval *value;
zend_string *skey;
zend_ulong num_key;
int tmp_len = 0;
MEMC_METHOD_INIT_VARS;
if (by_key) {
/* "Sa|ll" */
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STR(server_key)
Z_PARAM_ARRAY(entries)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(expiration)
ZEND_PARSE_PARAMETERS_END();
} else {
/* "a|ll" */
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_ARRAY(entries)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(expiration)
ZEND_PARSE_PARAMETERS_END();
}
MEMC_METHOD_FETCH_OBJECT;
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 = NULL;
if (skey) {
str_key = skey;
}
else {
char tmp_key[64];
tmp_len = snprintf(tmp_key, sizeof(tmp_key) - 1, "%ld", (long)num_key);
str_key = zend_string_init(tmp_key, tmp_len, 0);
}
/* 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);
}
} ZEND_HASH_FOREACH_END();
RETURN_BOOL(!s_memc_status_has_error(intern));
}
/* }}} */
/* {{{ 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)
{
php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 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)
{
php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1);
}
/* }}} */
/* {{{ 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);
}
/* }}} */
/* {{{ 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::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)
{
php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1);
}
/* }}} */
/* {{{ 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);
}
/* }}} */
/* {{{ 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_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1);
}
/* }}} */
/* {{{ -- php_memc_store_impl */
static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key)
{
zend_string *key;
zend_string *server_key = NULL;
zend_string *s_value;
zval s_zvalue;
zval *value = NULL;
zend_long expiration = 0;
MEMC_METHOD_INIT_VARS;
if (by_key) {
if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) {
/* "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) {
/* "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 {
/* "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) {
/* "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) {
/* "S|l */
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(key)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(expiration)
ZEND_PARSE_PARAMETERS_END();
} else {
/* "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();
}
}
MEMC_METHOD_FETCH_OBJECT;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
MEMC_CHECK_KEY(intern, key);
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();
}
}
if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
/* {{{ -- php_memc_cas_impl */
static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
zval *zv_cas;
uint64_t cas;
zend_string *key;
zend_string *server_key = NULL;
zval *value;
zend_long expiration = 0;
zend_string *payload;
uint32_t flags = 0;
memcached_return status;
MEMC_METHOD_INIT_VARS;
if (by_key) {
/* "zSSz|l" */
ZEND_PARSE_PARAMETERS_START(4, 5)
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)
ZEND_PARSE_PARAMETERS_END();
} else {
/* "zSz|l" */
ZEND_PARSE_PARAMETERS_START(3, 4)
Z_PARAM_ZVAL(zv_cas)
Z_PARAM_STR(key)
Z_PARAM_ZVAL(value)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(expiration)
ZEND_PARSE_PARAMETERS_END();
}
MEMC_METHOD_FETCH_OBJECT;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
MEMC_CHECK_KEY(intern, key);
cas = s_zval_to_uint64(zv_cas);
payload = s_zval_to_payload(intern, value, &flags);
if (payload == NULL) {
intern->rescode = MEMC_RES_PAYLOAD_FAILURE;
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 {
status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas);
}
zend_string_release(payload);
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
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)
{
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)
{
php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ Memcached::deleteMulti(array keys [, int time ])
Deletes the given keys */
PHP_METHOD(Memcached, deleteMulti)
{
php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ 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)
{
php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
/* {{{ Memcached::deleteMultiByKey(array keys [, int time ])
Deletes the given key from the server identified by the server key */
PHP_METHOD(Memcached, deleteMultiByKey)
{
php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
/* {{{ -- php_memc_delete_impl */
static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
zend_string *key, *server_key;
zend_long expiration = 0;
memcached_return status;
MEMC_METHOD_INIT_VARS;
if (by_key) {
/* "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 {
/* "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;
}
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),
ZSTR_LEN(key), expiration);
} else {
status = memcached_delete(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration);
}
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
/* {{{ -- php_memc_deleteMulti_impl */
static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
{
zval *entries, *zv, ret;
zend_string *server_key = NULL;
zend_long expiration = 0;
zend_string *entry;
memcached_return status;
MEMC_METHOD_INIT_VARS;
if (by_key) {
/* "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 {
/* "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;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
array_init(return_value);
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), zv) {
entry = zval_get_string(zv);
if (ZSTR_LEN(entry) == 0) {
zend_string_release(entry);
continue;
}
if (by_key) {
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, ZSTR_VAL(entry), ZSTR_LEN(entry), ZSTR_VAL(entry), ZSTR_LEN(entry), expiration);
}
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
ZVAL_LONG(&ret, status);
} else {
ZVAL_TRUE(&ret);
}
zend_symtable_update(Z_ARRVAL_P(return_value), entry, &ret);
zend_string_release(entry);
} ZEND_HASH_FOREACH_END();
return;
}
/* }}} */
/* {{{ -- 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;
zend_long offset = 1;
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) {
/* "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 {
/* "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;
s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
MEMC_CHECK_KEY(intern, key);
if (offset < 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), offset, &value);
} else {
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_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value);
} else {
status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value);
}
}
} else {
zend_long retries = memc_user_data->store_retry_count;
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, 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, (time_t)expiry, &value);
}
} else {
if (incr) {
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, (time_t)expiry, &value);
}
}
if (s_should_retry_write(intern, status) && retries-- > 0) {
goto retry_inc_dec;
}
}
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
RETURN_FALSE;
}
if (value == UINT64_MAX) {
RETURN_FALSE;
}
RETURN_LONG((long)value);
}
/* }}} */
/* {{{ 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)
{
zend_string *host;
zend_long port, weight = 0;
memcached_return status;
MEMC_METHOD_INIT_VARS;
/* "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);
status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight);
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;
HashPosition pos;
int entry_size, i = 0;
memcached_server_st *list = NULL;
memcached_return status;
MEMC_METHOD_INIT_VARS;
/* "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);
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_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 */
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;
}
host = zval_get_string(z_host);
port = zval_get_long(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);
}
weight = zval_get_long(z_weight);
}
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++;
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;
/* "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);
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;
}
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);
}
/* }}} */
/* {{{ 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));
}
/* }}} */
/* {{{ 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)
{
zend_string *server_key;
zend_long long_val;
double d_val;
char *buffer;
zval *return_value = (zval *) context;
zval *server_values;
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_add(Z_ARRVAL_P(return_value), server_key, &zv);
}
spprintf (&buffer, 0, "%.*s", (int)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, (char*)value, value_length);
}
efree (buffer);
zend_string_release(server_key);
return MEMCACHED_SUCCESS;
}
/* {{{ Memcached::getStats()
Returns statistics for the memcache servers */
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!" */
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;
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;
}
}
/* }}} */
/* {{{ 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);
/* 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;
}
}
/* }}} */
/* {{{ Memcached::flush([ int delay ])
Flushes the data on all the servers */
static PHP_METHOD(Memcached, flush)
{
zend_long delay = 0;
memcached_return status;
MEMC_METHOD_INIT_VARS;
/* "|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);
status = memcached_flush(intern->memc, delay);
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
/* {{{ Memcached::getOption(int option)
Returns the value for the given option constant */
static PHP_METHOD(Memcached, getOption)
{
zend_long option;
uint64_t result;
memcached_behavior flag;
MEMC_METHOD_INIT_VARS;
/* "l" */
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(option)
ZEND_PARSE_PARAMETERS_END();
MEMC_METHOD_FETCH_OBJECT;
switch (option) {
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);
case MEMC_OPT_ITEM_SIZE_LIMIT:
RETURN_LONG(memc_user_data->item_size_limit);
case MEMC_OPT_PREFIX_KEY:
{
memcached_return retval;
char *result;
result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval);
if (retval == MEMCACHED_SUCCESS && result) {
RETURN_STRING(result);
} else {
RETURN_EMPTY_STRING();
}
}
case MEMC_OPT_SERIALIZER:
RETURN_LONG((long)memc_user_data->serializer);
break;
case MEMC_OPT_USER_FLAGS:
RETURN_LONG(memc_user_data->set_udf_flags);
break;
case MEMC_OPT_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(intern->memc) == 0) {
php_error_docref(NULL, E_WARNING, "no servers defined");
return;
}
default:
/*
* Assume that it's a libmemcached behavior option.
*/
flag = (memcached_behavior) option;
result = memcached_behavior_get(intern->memc, flag);
RETURN_LONG((long)result);
}
}
/* }}} */
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:
memc_user_data->compression_enabled = zval_get_long(value) ? 1 : 0;
break;
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 {
/* invalid compression type */
intern->rescode = MEMCACHED_INVALID_ARGUMENTS;
return 0;
}
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) {
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;
char *key;
str = zval_get_string(value);
if (ZSTR_LEN(str) == 0) {
key = NULL;
} else {
key = ZSTR_VAL(str);
}
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;
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));
return 0;
}
/*
* This is necessary because libmemcached does not reset hash/distribution
* options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA
* (non-weighted) case. We have to clean up ourselves.
*/
if (!lval) {
(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;
case MEMC_OPT_SERIALIZER:
{
lval = zval_get_long(value);
/* igbinary serializer */
#ifdef HAVE_MEMCACHED_IGBINARY
if (lval == SERIALIZER_IGBINARY) {
memc_user_data->serializer = SERIALIZER_IGBINARY;
} else
#endif
#ifdef HAVE_JSON_API
if (lval == SERIALIZER_JSON) {
memc_user_data->serializer = SERIALIZER_JSON;
} else if (lval == SERIALIZER_JSON_ARRAY) {
memc_user_data->serializer = SERIALIZER_JSON_ARRAY;
} else
#endif
/* msgpack serializer */
#ifdef HAVE_MEMCACHED_MSGPACK
if (lval == SERIALIZER_MSGPACK) {
memc_user_data->serializer = SERIALIZER_MSGPACK;
} else
#endif
/* php serializer */
if (lval == SERIALIZER_PHP) {
memc_user_data->serializer = SERIALIZER_PHP;
} else {
memc_user_data->serializer = SERIALIZER_PHP;
intern->rescode = MEMCACHED_INVALID_ARGUMENTS;
php_error_docref(NULL, E_WARNING, "invalid serializer provided");
return 0;
}
break;
}
case MEMC_OPT_USER_FLAGS:
lval = zval_get_long(value);
if (lval < 0) {
memc_user_data->set_udf_flags = -1;
return 1;
}
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 = lval;
break;
case MEMC_OPT_STORE_RETRY_COUNT:
lval = zval_get_long(value);
memc_user_data->store_retry_count = lval;
break;
default:
/*
* Assume that it's a libmemcached behavior option.
*/
if (option < 0) {
rc = MEMCACHED_INVALID_ARGUMENTS;
}
else {
flag = (memcached_behavior) option;
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 {
rc = MEMCACHED_INVALID_ARGUMENTS;
}
}
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;
}
break;
}
return 1;
}
static
uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements)
{
zval *pzval;
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));
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), pzval) {
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);
*num_elements = 0;
return NULL;
}
retval [i] = (uint32_t) value;
i++;
} ZEND_HASH_FOREACH_END();
return retval;
}
/* {{{ Memcached::setBucket(array host_map, array forward_map, integer replicas)
Sets the memcached virtual buckets */
PHP_METHOD(Memcached, setBucket)
{
zval *zserver_map;
zval *zforward_map = NULL;
zend_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;
/* "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;
if (zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) == 0) {
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, E_WARNING, "forward_map length must match the server_map length");
RETURN_FALSE;
}
if (replicas < 0) {
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);
if (!server_map) {
RETURN_FALSE;
}
if (zforward_map) {
forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len);
if (!forward_map) {
efree (server_map);
RETURN_FALSE;
}
}
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;
}
efree(server_map);
if (forward_map) {
efree(forward_map);
}
RETURN_BOOL(retval);
}
/* }}} */
/* {{{ Memcached::setOptions(array options)
Sets the value for the given option constant */
static PHP_METHOD(Memcached, setOptions)
{
zval *options;
zend_bool ok = 1;
zend_string *key;
zend_ulong key_index;
zval *value;
MEMC_METHOD_INIT_VARS;
/* "a" */
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(options)
ZEND_PARSE_PARAMETERS_END();
MEMC_METHOD_FETCH_OBJECT;
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 {
if (!php_memc_set_option(intern, (long) key_index, value)) {
ok = 0;
}
}
} 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)
{
zend_long option;
zval *value;
MEMC_METHOD_INIT_VARS;
/* "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;
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;
/* "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;
}
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, ZSTR_VAL(user), ZSTR_VAL(pass));
if (s_memc_status_handle_result_code(intern, status) == FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
#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)
{
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);
}
/* }}} */
/* {{{ 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
****************************************/
/* {{{ constructor/destructor */
static
void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data)
{
#ifdef HAVE_MEMCACHED_SASL
if (memc_user_data->has_sasl_data) {
memcached_destroy_sasl_auth_data(memc);
}
#endif
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(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);
}
zend_object *php_memc_server_new(zend_class_entry *ce)
{
php_memc_server_t *intern;
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->zo.handlers = &memcached_server_object_handlers;
intern->handler = php_memc_proto_handler_new();
return &intern->zo;
}
#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", (char*)memcached_server_name(instance));
add_assoc_long(&array, "port", memcached_server_port(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);
*/
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)
{
zend_string *address, *version;
zval rv, *return_value = (zval *)in_context;
#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009
version = strpprintf(0, "%d.%d.%d",
memcached_server_major_version(instance),
memcached_server_minor_version(instance),
memcached_server_micro_version(instance));
#else
version = strpprintf(0, "%d.%d.%d",
instance->major_version,
instance->minor_version,
instance->micro_version);
#endif
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);
zend_string_release(address);
return MEMCACHED_SUCCESS;
}
static
zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32_t flags)
{
zend_string *buffer;
uint32_t stored_length;
unsigned long length;
zend_bool decompress_status = 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);
#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;
}
memcpy(&stored_length, payload, sizeof (uint32_t));
payload += sizeof (uint32_t);
payload_len -= sizeof (uint32_t);
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);
}
else if (is_zlib) {
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';
if (!decompress_status) {
php_error_docref(NULL, E_WARNING, "could not decompress value");
zend_string_release (buffer);
return NULL;
}
zend_string_forget_hash_val(buffer);
return buffer;
}
static
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:
{
php_unserialize_data_t var_hash;
const unsigned char *p, *max;
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)) {
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;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
}
break;
case MEMC_VAL_IS_IGBINARY:
#ifdef HAVE_MEMCACHED_IGBINARY
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;
}
#else
ZVAL_FALSE(return_value);
php_error_docref(NULL, E_WARNING, "could not unserialize value, no igbinary support");
return 0;
#endif
break;
case MEMC_VAL_IS_JSON:
#ifdef HAVE_JSON_API
{
php_memc_user_data_t *memc_user_data = memcached_get_user_data(memc);
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);
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(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");
return 0;
#endif
break;
}
return 1;
}
static
zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_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)) {
data = s_decompress_value (payload, payload_len, flags);
if (!data) {
return 0;
}
} else {
data = zend_string_init(payload, payload_len, 0);
}
switch (MEMC_VAL_GET_TYPE(flags)) {
case MEMC_VAL_IS_STRING:
ZVAL_STR_COPY(return_value, data);
break;
case MEMC_VAL_IS_LONG:
ZVAL_LONG(return_value, strtol(ZSTR_VAL(data), NULL, 10));
break;
case MEMC_VAL_IS_DOUBLE:
{
if (zend_string_equals_literal(data, "Infinity")) {
ZVAL_DOUBLE(return_value, php_get_inf());
}
else if (zend_string_equals_literal(data, "-Infinity")) {
ZVAL_DOUBLE(return_value, -php_get_inf());
}
else if (zend_string_equals_literal(data, "NaN")) {
ZVAL_DOUBLE(return_value, php_get_nan());
}
else {
ZVAL_DOUBLE(return_value, zend_strtod(ZSTR_VAL(data), NULL));
}
}
break;
case MEMC_VAL_IS_BOOL:
ZVAL_BOOL(return_value, payload_len > 0 && ZSTR_VAL(data)[0] == '1');
break;
case MEMC_VAL_IS_SERIALIZED:
case MEMC_VAL_IS_IGBINARY:
case MEMC_VAL_IS_JSON:
case MEMC_VAL_IS_MSGPACK:
retval = s_unserialize_value (memc, MEMC_VAL_GET_TYPE(flags), data, return_value);
break;
default:
php_error_docref(NULL, E_WARNING, "unknown payload type");
retval = 0;
break;
}
zend_string_release(data);
return retval;
}
PHP_MEMCACHED_API
zend_class_entry *php_memc_get_ce(void)
{
return memcached_ce;
}
PHP_MEMCACHED_API
zend_class_entry *php_memc_get_exception(void)
{
return memcached_exception_ce;
}
PHP_MEMCACHED_API
zend_class_entry *php_memc_get_exception_base(int root)
{
if (!root) {
if (!spl_ce_RuntimeException) {
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;
}
}
return zend_exception_get_default();
}
#ifdef HAVE_MEMCACHED_PROTOCOL
static
void s_destroy_cb (zend_fcall_info *fci)
{
if (fci->size > 0) {
zval_ptr_dtor(&fci->function_name);
if (fci->object) {
OBJ_RELEASE(fci->object);
}
}
}
static
PHP_METHOD(MemcachedServer, run)
{
int i;
zend_bool rc;
zend_string *address;
php_memc_server_t *intern;
intern = Z_MEMC_SERVER_P(getThis());
/* "S" */
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_STR(address)
ZEND_PARSE_PARAMETERS_END();
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_SERVER_G(callbacks) [i].fci);
}
RETURN_BOOL(rc);
}
static
PHP_METHOD(MemcachedServer, on)
{
zend_long event;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
zend_bool rc = 0;
/* "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;
}
if (fci.size > 0) {
s_destroy_cb (&MEMC_SERVER_G(callbacks) [event].fci);
MEMC_SERVER_G(callbacks) [event].fci = fci;
MEMC_SERVER_G(callbacks) [event].fci_cache = fci_cache;
Z_TRY_ADDREF(fci.function_name);
if (fci.object) {
GC_ADDREF(fci.object);
}
}
RETURN_BOOL(rc);
}
#endif
#if PHP_VERSION_ID < 80000
#include "php_memcached_legacy_arginfo.h"
#else
#include "zend_attributes.h"
#include "php_memcached_arginfo.h"
#endif
/* {{{ memcached_module_entry
*/
#if ZEND_MODULE_API_NO >= 20050922
static const zend_module_dep memcached_deps[] = {
#ifdef HAVE_MEMCACHED_SESSION
ZEND_MOD_REQUIRED("session")
#endif
#ifdef HAVE_MEMCACHED_IGBINARY
ZEND_MOD_REQUIRED("igbinary")
#endif
#ifdef HAVE_MEMCACHED_MSGPACK
ZEND_MOD_REQUIRED("msgpack")
#endif
ZEND_MOD_REQUIRED("spl")
ZEND_MOD_END
};
#endif
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;
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;
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;
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;
#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;
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 = 6;
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;
/* 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 = {
STANDARD_MODULE_HEADER_EX, NULL,
memcached_deps,
"memcached",
NULL,
PHP_MINIT(memcached),
PHP_MSHUTDOWN(memcached),
NULL,
NULL,
PHP_MINFO(memcached),
PHP_MEMCACHED_VERSION,
PHP_MODULE_GLOBALS(php_memcached),
PHP_GINIT(php_memcached),
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
/* {{{ 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)
#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
*/
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);
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);
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
*/
#ifdef HAVE_MEMCACHED_IGBINARY
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 1);
#else
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
*/
#ifdef HAVE_JSON_API
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 1);
#else
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 0);
#endif
/*
* Indicate whether msgpack serializer is available
*/
#ifdef HAVE_MEMCACHED_MSGPACK
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 1);
#else
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
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 0);
#endif
#ifdef HAVE_MEMCACHED_SASL
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 1);
#else
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 0);
#endif
/*
* libmemcached behavior options
*/
REGISTER_MEMC_CLASS_CONST_LONG(OPT_HASH, MEMCACHED_BEHAVIOR_HASH);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_DEFAULT, MEMCACHED_HASH_DEFAULT);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_MD5, MEMCACHED_HASH_MD5);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_CRC, MEMCACHED_HASH_CRC);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_64, MEMCACHED_HASH_FNV1_64);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_64, MEMCACHED_HASH_FNV1A_64);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_32, MEMCACHED_HASH_FNV1_32);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_32, MEMCACHED_HASH_FNV1A_32);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_HSIEH, MEMCACHED_HASH_HSIEH);
REGISTER_MEMC_CLASS_CONST_LONG(HASH_MURMUR, MEMCACHED_HASH_MURMUR);
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);
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);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_NODELAY, MEMCACHED_BEHAVIOR_TCP_NODELAY);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_SEND_SIZE, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE);
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);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_CACHE_LOOKUPS, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_FAILURE_LIMIT, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_AUTO_EJECT_HOSTS, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_HASH_WITH_PREFIX_KEY, MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_NOREPLY, MEMCACHED_BEHAVIOR_NOREPLY);
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);
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);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS);
#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018
REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_TIMEOUT_LIMIT, MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT);
#endif
/*
* 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_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);
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
#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);
#endif
/*
* Our result codes.
*/
REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE);
/*
* 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_JSON_ARRAY, SERIALIZER_JSON_ARRAY);
REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK);
/*
* Compression types
*/
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.
*/
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
/*
* 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);
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);
#endif
/*
* 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
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION */
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_object_t, zo);
memcached_object_handlers.clone_obj = NULL;
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);
memcached_ce = register_class_Memcached();
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));
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;
memcached_server_ce = register_class_MemcachedServer();
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));
/* TODO
* possibly declare custom exception property here
*/
php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU);
REGISTER_INI_ENTRIES();
#ifdef HAVE_MEMCACHED_SESSION
php_memc_session_minit(module_number);
#endif
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(memcached)
{
#ifdef HAVE_MEMCACHED_SASL
if (MEMC_G(sasl_initialised)) {
sasl_done();
}
#endif
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION */
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);
#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");
#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
php_info_print_table_row(2, "Session support ", "no");
#endif
#ifdef HAVE_MEMCACHED_IGBINARY
php_info_print_table_row(2, "igbinary support", "yes");
#else
php_info_print_table_row(2, "igbinary support", "no");
#endif
#ifdef HAVE_JSON_API
php_info_print_table_row(2, "json support", "yes");
#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
#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();
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim: noet sw=4 ts=4 fdm=marker:
*/
memcached-3.3.0/php_memcached.h 0000644 0000765 0000024 00000003526 14704245235 015175 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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_MEMCACHED_H
#define PHP_MEMCACHED_H
#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"
#endif
#define PHP_MEMCACHED_VERSION "3.3.0"
#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);
extern zend_module_entry memcached_module_entry;
#define phpext_memcached_ptr &memcached_module_entry
#endif /* PHP_MEMCACHED_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
*/
memcached-3.3.0/php_memcached.stub.php 0000644 0000765 0000024 00000011176 14704245235 016511 0 ustar mike staff = 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
memcached-3.3.0/php_memcached_legacy_arginfo.h 0000644 0000765 0000024 00000040143 14704245235 020222 0 ustar mike staff /* This is a generated file, edit the .stub.php file instead.
* Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0)
ZEND_ARG_INFO(0, persistent_id)
ZEND_ARG_INFO(0, callback)
ZEND_ARG_INFO(0, connection_str)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_getResultMessage arginfo_class_Memcached_getResultCode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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_class_Memcached_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_class_Memcached_getMulti, 0, 0, 1)
ZEND_ARG_INFO(0, keys)
ZEND_ARG_INFO(0, get_flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getMultiByKey, 0, 0, 2)
ZEND_ARG_INFO(0, server_key)
ZEND_ARG_INFO(0, keys)
ZEND_ARG_INFO(0, get_flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 0, 1)
ZEND_ARG_INFO(0, keys)
ZEND_ARG_INFO(0, with_cas)
ZEND_ARG_INFO(0, value_cb)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 0, 2)
ZEND_ARG_INFO(0, server_key)
ZEND_ARG_INFO(0, keys)
ZEND_ARG_INFO(0, with_cas)
ZEND_ARG_INFO(0, value_cb)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_fetch arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_fetchAll arginfo_class_Memcached_getResultCode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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_class_Memcached_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_class_Memcached_touch, 0, 0, 1)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, expiration)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_touchByKey, 0, 0, 2)
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_class_Memcached_setMulti, 0, 0, 1)
ZEND_ARG_INFO(0, items)
ZEND_ARG_INFO(0, expiration)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setMultiByKey, 0, 0, 2)
ZEND_ARG_INFO(0, server_key)
ZEND_ARG_INFO(0, items)
ZEND_ARG_INFO(0, expiration)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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_class_Memcached_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()
#define arginfo_class_Memcached_add arginfo_class_Memcached_set
#define arginfo_class_Memcached_addByKey arginfo_class_Memcached_setByKey
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_append, 0, 0, 2)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_appendByKey, 0, 0, 3)
ZEND_ARG_INFO(0, server_key)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_prepend arginfo_class_Memcached_append
#define arginfo_class_Memcached_prependByKey arginfo_class_Memcached_appendByKey
#define arginfo_class_Memcached_replace arginfo_class_Memcached_set
#define arginfo_class_Memcached_replaceByKey arginfo_class_Memcached_setByKey
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_delete, 0, 0, 1)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, time)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_deleteMulti, 0, 0, 1)
ZEND_ARG_INFO(0, keys)
ZEND_ARG_INFO(0, time)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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_class_Memcached_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_class_Memcached_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()
#define arginfo_class_Memcached_decrement arginfo_class_Memcached_increment
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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()
#define arginfo_class_Memcached_decrementByKey arginfo_class_Memcached_incrementByKey
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_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_class_Memcached_addServers, 0, 0, 1)
ZEND_ARG_INFO(0, servers)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_getServerList arginfo_class_Memcached_getResultCode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getServerByKey, 0, 0, 1)
ZEND_ARG_INFO(0, server_key)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_resetServerList arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_quit arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_flushBuffers arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_getLastErrorMessage arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_getLastErrorCode arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_getLastErrorErrno arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_getResultCode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getStats, 0, 0, 0)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_getVersion arginfo_class_Memcached_getResultCode
#define arginfo_class_Memcached_getAllKeys arginfo_class_Memcached_getResultCode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_flush, 0, 0, 0)
ZEND_ARG_INFO(0, delay)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_getOption, 0, 0, 1)
ZEND_ARG_INFO(0, option)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setOption, 0, 0, 2)
ZEND_ARG_INFO(0, option)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setOptions, 0, 0, 1)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setBucket, 0, 0, 3)
ZEND_ARG_INFO(0, host_map)
ZEND_ARG_INFO(0, forward_map)
ZEND_ARG_INFO(0, replicas)
ZEND_END_ARG_INFO()
#if defined(HAVE_MEMCACHED_SASL)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setSaslAuthData, 0, 0, 2)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
#endif
#if defined(HAVE_MEMCACHED_SET_ENCODING_KEY)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_setEncodingKey, 0, 0, 1)
ZEND_ARG_INFO(0, key)
ZEND_END_ARG_INFO()
#endif
#define arginfo_class_Memcached_isPersistent arginfo_class_Memcached_getResultCode
#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)
ZEND_END_ARG_INFO()
#endif
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MemcachedServer_on, 0, 0, 2)
ZEND_ARG_INFO(0, event)
ZEND_ARG_INFO(0, callback)
ZEND_END_ARG_INFO()
#endif
ZEND_METHOD(Memcached, __construct);
ZEND_METHOD(Memcached, getResultCode);
ZEND_METHOD(Memcached, getResultMessage);
ZEND_METHOD(Memcached, get);
ZEND_METHOD(Memcached, getByKey);
ZEND_METHOD(Memcached, getMulti);
ZEND_METHOD(Memcached, getMultiByKey);
ZEND_METHOD(Memcached, getDelayed);
ZEND_METHOD(Memcached, getDelayedByKey);
ZEND_METHOD(Memcached, fetch);
ZEND_METHOD(Memcached, fetchAll);
ZEND_METHOD(Memcached, set);
ZEND_METHOD(Memcached, setByKey);
ZEND_METHOD(Memcached, touch);
ZEND_METHOD(Memcached, touchByKey);
ZEND_METHOD(Memcached, setMulti);
ZEND_METHOD(Memcached, setMultiByKey);
ZEND_METHOD(Memcached, cas);
ZEND_METHOD(Memcached, casByKey);
ZEND_METHOD(Memcached, add);
ZEND_METHOD(Memcached, addByKey);
ZEND_METHOD(Memcached, append);
ZEND_METHOD(Memcached, appendByKey);
ZEND_METHOD(Memcached, prepend);
ZEND_METHOD(Memcached, prependByKey);
ZEND_METHOD(Memcached, replace);
ZEND_METHOD(Memcached, replaceByKey);
ZEND_METHOD(Memcached, delete);
ZEND_METHOD(Memcached, deleteMulti);
ZEND_METHOD(Memcached, deleteByKey);
ZEND_METHOD(Memcached, deleteMultiByKey);
ZEND_METHOD(Memcached, increment);
ZEND_METHOD(Memcached, decrement);
ZEND_METHOD(Memcached, incrementByKey);
ZEND_METHOD(Memcached, decrementByKey);
ZEND_METHOD(Memcached, addServer);
ZEND_METHOD(Memcached, addServers);
ZEND_METHOD(Memcached, getServerList);
ZEND_METHOD(Memcached, getServerByKey);
ZEND_METHOD(Memcached, resetServerList);
ZEND_METHOD(Memcached, quit);
ZEND_METHOD(Memcached, flushBuffers);
ZEND_METHOD(Memcached, getLastErrorMessage);
ZEND_METHOD(Memcached, getLastErrorCode);
ZEND_METHOD(Memcached, getLastErrorErrno);
ZEND_METHOD(Memcached, getLastDisconnectedServer);
ZEND_METHOD(Memcached, getStats);
ZEND_METHOD(Memcached, getVersion);
ZEND_METHOD(Memcached, getAllKeys);
ZEND_METHOD(Memcached, flush);
ZEND_METHOD(Memcached, getOption);
ZEND_METHOD(Memcached, setOption);
ZEND_METHOD(Memcached, setOptions);
ZEND_METHOD(Memcached, setBucket);
#if defined(HAVE_MEMCACHED_SASL)
ZEND_METHOD(Memcached, setSaslAuthData);
#endif
#if defined(HAVE_MEMCACHED_SET_ENCODING_KEY)
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
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_METHOD(MemcachedServer, on);
#endif
static const zend_function_entry class_Memcached_methods[] = {
ZEND_ME(Memcached, __construct, arginfo_class_Memcached___construct, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getResultCode, arginfo_class_Memcached_getResultCode, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getResultMessage, arginfo_class_Memcached_getResultMessage, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, get, arginfo_class_Memcached_get, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getByKey, arginfo_class_Memcached_getByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getMulti, arginfo_class_Memcached_getMulti, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getMultiByKey, arginfo_class_Memcached_getMultiByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getDelayed, arginfo_class_Memcached_getDelayed, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getDelayedByKey, arginfo_class_Memcached_getDelayedByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, fetch, arginfo_class_Memcached_fetch, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, fetchAll, arginfo_class_Memcached_fetchAll, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, set, arginfo_class_Memcached_set, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setByKey, arginfo_class_Memcached_setByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, touch, arginfo_class_Memcached_touch, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, touchByKey, arginfo_class_Memcached_touchByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setMulti, arginfo_class_Memcached_setMulti, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setMultiByKey, arginfo_class_Memcached_setMultiByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, cas, arginfo_class_Memcached_cas, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, casByKey, arginfo_class_Memcached_casByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, add, arginfo_class_Memcached_add, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, addByKey, arginfo_class_Memcached_addByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, append, arginfo_class_Memcached_append, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, appendByKey, arginfo_class_Memcached_appendByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, prepend, arginfo_class_Memcached_prepend, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, prependByKey, arginfo_class_Memcached_prependByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, replace, arginfo_class_Memcached_replace, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, replaceByKey, arginfo_class_Memcached_replaceByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, delete, arginfo_class_Memcached_delete, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, deleteMulti, arginfo_class_Memcached_deleteMulti, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, deleteByKey, arginfo_class_Memcached_deleteByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, deleteMultiByKey, arginfo_class_Memcached_deleteMultiByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, increment, arginfo_class_Memcached_increment, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, decrement, arginfo_class_Memcached_decrement, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, incrementByKey, arginfo_class_Memcached_incrementByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, decrementByKey, arginfo_class_Memcached_decrementByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, addServer, arginfo_class_Memcached_addServer, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, addServers, arginfo_class_Memcached_addServers, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getServerList, arginfo_class_Memcached_getServerList, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getServerByKey, arginfo_class_Memcached_getServerByKey, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, resetServerList, arginfo_class_Memcached_resetServerList, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, quit, arginfo_class_Memcached_quit, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, flushBuffers, arginfo_class_Memcached_flushBuffers, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getLastErrorMessage, arginfo_class_Memcached_getLastErrorMessage, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getLastErrorCode, arginfo_class_Memcached_getLastErrorCode, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getLastErrorErrno, arginfo_class_Memcached_getLastErrorErrno, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getLastDisconnectedServer, arginfo_class_Memcached_getLastDisconnectedServer, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getStats, arginfo_class_Memcached_getStats, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getVersion, arginfo_class_Memcached_getVersion, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getAllKeys, arginfo_class_Memcached_getAllKeys, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, flush, arginfo_class_Memcached_flush, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, getOption, arginfo_class_Memcached_getOption, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setOption, arginfo_class_Memcached_setOption, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setOptions, arginfo_class_Memcached_setOptions, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, setBucket, arginfo_class_Memcached_setBucket, ZEND_ACC_PUBLIC)
#if defined(HAVE_MEMCACHED_SASL)
ZEND_ME(Memcached, setSaslAuthData, arginfo_class_Memcached_setSaslAuthData, ZEND_ACC_PUBLIC)
#endif
#if defined(HAVE_MEMCACHED_SET_ENCODING_KEY)
ZEND_ME(Memcached, setEncodingKey, arginfo_class_Memcached_setEncodingKey, ZEND_ACC_PUBLIC)
#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
};
#if defined(HAVE_MEMCACHED_PROTOCOL)
static const zend_function_entry class_MemcachedServer_methods[] = {
ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC)
ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC)
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
memcached-3.3.0/php_memcached_private.h 0000644 0000765 0000024 00000015156 14704245235 016731 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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_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"
#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
# 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)
# 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
/* 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
****************************************/
typedef enum {
SERIALIZER_PHP = 1,
SERIALIZER_IGBINARY = 2,
SERIALIZER_JSON = 3,
SERIALIZER_JSON_ARRAY = 4,
SERIALIZER_MSGPACK = 5
} php_memc_serializer_type;
typedef enum {
COMPRESSION_TYPE_ZLIB = 1,
COMPRESSION_TYPE_FASTLZ = 2,
COMPRESSION_TYPE_ZSTD = 3
} php_memc_compression_type;
typedef struct {
const char *name;
php_memc_serializer_type type;
} php_memc_serializer;
#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"
#endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */
#ifdef HAVE_MEMCACHED_SASL
# include
#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
/* 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 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;
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;
#endif
struct {
char *serializer_name;
char *compression_name;
zend_long compression_threshold;
double compression_factor;
zend_long store_retry_count;
zend_long compression_level;
zend_long item_size_limit;
/* Converted values*/
php_memc_serializer_type serializer_type;
php_memc_compression_type compression_type;
/* 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 */
zend_long no_effect;
#ifdef HAVE_MEMCACHED_PROTOCOL
struct {
php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX];
} server;
#endif
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);
PHP_MSHUTDOWN_FUNCTION(memcached);
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 */
/*
* 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
*/
memcached-3.3.0/php_memcached_session.c 0000644 0000765 0000024 00000034204 14704245235 016730 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
*/
#include "php_memcached.h"
#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 REALTIME_MAXDELTA 60*60*24*30
ps_module ps_mod_memcached = {
PS_MOD_UPDATE_TIMESTAMP(memcached)
};
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
static
int le_memc_sess;
static
int s_memc_sess_list_entry(void)
{
return le_memc_sess;
}
static
void s_destroy_mod_data(memcached_st *memc)
{
php_memcached_user_data *user_data = memcached_get_user_data(memc);
#ifdef 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);
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;
}
}
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_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 s_adjust_expiration(MEMC_SESS_INI(lock_expiration));
}
else {
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);
}
}
return 0;
}
static
time_t s_session_expiration(zend_long maxlifetime)
{
if (maxlifetime > 0) {
return s_adjust_expiration(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;
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);
do {
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:
if (retries > 0) {
usleep(wait_time * 1000);
wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2);
}
break;
default:
php_error_docref(NULL, E_WARNING, "Failed to write session lock: %s", memcached_strerror (memc, rc));
break;
}
} while (!user_data->is_locked && retries-- > 0);
efree(lock_key);
return user_data->is_locked;
}
static
void s_unlock_session(memcached_st *memc)
{
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);
}
}
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)) { \
memcached_return rc; \
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)); \
} \
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)) {
check_set_behavior(MEMC_SESS_INI(consistent_hash_type), 1);
}
if (MEMC_SESS_INI(server_failure_limit)) {
check_set_behavior(MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, MEMC_SESS_INI(server_failure_limit));
}
if (MEMC_SESS_INI(number_of_replicas)) {
check_set_behavior(MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, MEMC_SESS_INI(number_of_replicas));
}
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_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) {
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;
}
#undef check_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);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1);
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;
// 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);
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, 1)) {
// 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);
memcached_server_list_free(servers);
return SUCCESS;
}
}
}
}
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);
}
s_destroy_mod_data(memc);
PS_SET_MOD_DATA(NULL);
return FAILURE;
}
if (plist_key) {
zend_resource le;
le.type = s_memc_sess_list_entry();
le.ptr = memc;
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) {
php_error_docref(NULL, E_ERROR, "Could not register persistent entry for the memcached session");
/* not reached */
}
efree(plist_key);
}
PS_SET_MOD_DATA(memc);
return SUCCESS;
}
PS_CLOSE_FUNC(memcached)
{
php_memcached_user_data *user_data;
memcached_st *memc = PS_GET_MOD_DATA();
if (!memc) {
php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value");
return FAILURE;
}
user_data = memcached_get_user_data(memc);
if (user_data->is_locked) {
s_unlock_session(memc);
}
if (!user_data->is_persistent) {
s_destroy_mod_data(memc);
}
PS_SET_MOD_DATA(NULL);
return SUCCESS;
}
PS_READ_FUNC(memcached)
{
char *payload = NULL;
size_t payload_len = 0;
uint32_t flags = 0;
memcached_return status;
memcached_st *memc = PS_GET_MOD_DATA();
if (!memc) {
php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value");
return FAILURE;
}
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, 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);
pefree(payload, *is_persistent);
return SUCCESS;
} else if (status == MEMCACHED_NOTFOUND) {
*val = ZSTR_EMPTY_ALLOC();
return SUCCESS;
} else {
php_error_docref(NULL, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc));
return FAILURE;
}
}
PS_WRITE_FUNC(memcached)
{
zend_long retries = 1;
memcached_st *memc = PS_GET_MOD_DATA();
time_t expiration = s_session_expiration(maxlifetime);
if (!memc) {
php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value");
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;
replicas = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
failure_limit = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT);
retries = 1 + replicas * (failure_limit + 1);
}
do {
if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) {
return SUCCESS;
} else {
php_error_docref(NULL, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc));
}
} while (--retries > 0);
return FAILURE;
}
PS_DESTROY_FUNC(memcached)
{
php_memcached_user_data *user_data;
memcached_st *memc = PS_GET_MOD_DATA();
if (!memc) {
php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value");
return FAILURE;
}
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;
}
PS_GC_FUNC(memcached)
{
return SUCCESS;
}
PS_CREATE_SID_FUNC(memcached)
{
zend_string *sid;
memcached_st *memc = PS_GET_MOD_DATA();
if (!memc) {
sid = php_session_create_id(NULL);
}
else {
int retries = 3;
while (retries-- > 0) {
sid = php_session_create_id((void **) &memc);
if (memcached_add (memc, sid->val, sid->len, NULL, 0, s_lock_expiration(), 0) == MEMCACHED_SUCCESS) {
break;
}
zend_string_release(sid);
sid = NULL;
}
}
return sid;
}
PS_VALIDATE_SID_FUNC(memcached)
{
memcached_st *memc = PS_GET_MOD_DATA();
if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) {
return SUCCESS;
} else {
return FAILURE;
}
}
PS_UPDATE_TIMESTAMP_FUNC(memcached)
{
memcached_st *memc = PS_GET_MOD_DATA();
time_t expiration = s_session_expiration(maxlifetime);
if (php_memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) {
return FAILURE;
}
return SUCCESS;
}
/* }}} */
memcached-3.3.0/php_memcached_session.h 0000644 0000765 0000024 00000003107 14704245235 016733 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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 */
#include "ext/session/php_session.h"
extern ps_module ps_mod_memcached;
#define ps_memcached_ptr &ps_mod_memcached
PS_FUNCS_UPDATE_TIMESTAMP(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);
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 */
memcached-3.3.0/php_libmemcached_compat.h 0000644 0000765 0000024 00000003253 14704245235 017224 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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);
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
typedef memcached_server_instance_st php_memcached_instance_st;
#endif
#endif
memcached-3.3.0/php_libmemcached_compat.c 0000644 0000765 0000024 00000005216 14704245235 017220 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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) {
zend_bool *is_persistent = memcached_get_user_data(memc);
pefree(value, *is_persistent);
}
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);
}
memcached-3.3.0/php_memcached_server.h 0000644 0000765 0000024 00000002701 14704245235 016555 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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_
#ifdef HAVE_MEMCACHED_PROTOCOL
#include
/*
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);
zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, zend_string *address);
#endif
#endif
memcached-3.3.0/php_memcached_server.c 0000644 0000765 0000024 00000061031 14704245235 016551 0 ustar mike staff /*
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
*/
#include "php_memcached.h"
#include "php_memcached_private.h"
#include "php_memcached_server.h"
#include "php_network.h"
#include
#include
#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) \
do { \
zend_string *cookie_buf; \
cookie_buf = 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; \
my_result_cas = zval_get_double(&my_zresult_cas); \
} while (0)
ZEND_EXTERN_MODULE_GLOBALS(php_memcached)
struct _php_memc_proto_handler_t {
memcached_binary_protocol_callback_st callbacks;
struct memcached_protocol_st *protocol_handle;
struct event_base *event_base;
};
typedef struct {
struct memcached_protocol_client_st *protocol_client;
struct event_base *event_base;
zend_bool on_connect_invoked;
} php_memc_client_t;
static
long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t param_count)
{
zval retval;
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));
php_error_docref(NULL, E_WARNING, "Failed to invoke callback %s()", buf);
efree (buf);
}
return Z_ISUNDEF(retval) ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(&retval);
}
// 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 *result_cas)
{
protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
zval zcookie, zkey, zvalue, zflags, zexptime, zresult_cas;
zval params[6];
if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
ZVAL_STRINGL(&zkey, key, key_len);
ZVAL_STRINGL(&zvalue, data, data_len);
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);
ZVAL_COPY(¶ms[2], &zvalue);
ZVAL_COPY(¶ms[3], &zflags);
ZVAL_COPY(¶ms[4], &zexptime);
ZVAL_COPY(¶ms[5], &zresult_cas);
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);
zval_ptr_dtor (&zflags);
zval_ptr_dtor (&zexptime);
zval_ptr_dtor (&zresult_cas);
return retval;
}
static
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 zcookie, zkey, zvalue, zcas, zresult_cas;
zval params[5];
if (!MEMC_HAS_CB(event)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
ZVAL_STRINGL(&zkey, key, key_len);
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);
ZVAL_COPY(¶ms[2], &zvalue);
ZVAL_COPY(¶ms[3], &zcas);
ZVAL_COPY(¶ms[4], &zresult_cas);
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);
zval_ptr_dtor (&zcas);
zval_ptr_dtor (&zresult_cas);
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)
{
protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
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);
ZVAL_STRINGL(&zkey, key, key_len);
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);
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);
retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7);
*result = (uint64_t)zval_get_long(&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);
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 zcookie, zkey, zcas;
zval params[3];
if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
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;
}
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];
if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
ZVAL_LONG(&zwhen, when);
ZVAL_COPY(¶ms[0], &zcookie);
ZVAL_COPY(¶ms[1], &zwhen);
retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2);
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
zval_ptr_dtor(&zcookie);
zval_ptr_dtor(&zwhen);
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 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);
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);
ZVAL_COPY(¶ms[2], &zvalue);
ZVAL_COPY(¶ms[3], &zflags);
ZVAL_COPY(¶ms[4], &zresult_cas);
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(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(zvalue) != IS_STRING) {
convert_to_string (&zvalue);
}
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(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);
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;
zval zcookie;
zval params[1];
if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
ZVAL_COPY(¶ms[0], &zcookie);
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;
}
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);
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;
}
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);
ZVAL_STRINGL(&zkey, key, key_len);
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);
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);
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);
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);
}
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, zstats;
if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) {
return retval;
}
MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie);
if (key && key_len) {
ZVAL_STRINGL(&zkey, key, key_len);
} else {
ZVAL_NULL(&zkey);
}
array_init(&zstats);
ZVAL_MAKE_REF(&zstats);
ZVAL_COPY(¶ms[0], &zcookie);
ZVAL_COPY(¶ms[1], &zkey);
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) {
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_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);
} 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();
}
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 (&zstats);
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);
ZVAL_NULL(&zversion);
ZVAL_MAKE_REF(&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);
if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
if (Z_TYPE(zversion) != IS_STRING) {
convert_to_string(&zversion);
}
retval = response_handler (cookie, Z_STRVAL(zversion), (uint32_t) Z_STRLEN(zversion));
}
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
zval_ptr_dtor (&zcookie);
zval_ptr_dtor (&zversion);
return retval;
}
// libevent callbacks
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;
if (!client->on_connect_invoked) {
if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) {
zend_string *zremoteaddr_str;
zval zremoteaddr;
zval params[1];
protocol_binary_response_status retval;
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], &zremoteaddr);
retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 1);
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(&zremoteaddr);
if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
memcached_protocol_client_destroy (client->protocol_client);
efree (client);
evutil_closesocket (fd);
return;
}
}
client->on_connect_invoked = 1;
}
events = memcached_protocol_client_work (client->protocol_client);
if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) {
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, 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, 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;
client->on_connect_invoked = 0;
if (!client->protocol_client) {
php_error_docref (NULL, 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, 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 zend_string *spec)
{
evutil_socket_t sock;
struct sockaddr_storage addr;
socklen_t addr_len;
int rc;
addr_len = sizeof (struct sockaddr);
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 (addr.ss_family, SOCK_STREAM, 0);
if (sock < 0) {
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, E_WARNING, "bind failed: %s", strerror (errno));
return -1;
}
rc = listen (sock, 1024);
if (rc < 0) {
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, 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, 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, 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, zend_string *address)
{
struct event *accept_event;
evutil_socket_t sock = s_create_listening_socket (address);
if (sock == -1) {
return 0;
}
handler->event_base = event_base_new();
if (!handler->event_base) {
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, 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, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno));
return 0;
break;
case 1:
php_error_docref(NULL, E_ERROR, "no events registered");
return 0;
break;
default:
return 1;
break;
}
}
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;
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim: noet sw=4 ts=4 fdm=marker:
*/
memcached-3.3.0/g_fmt.c 0000644 0000765 0000024 00000004447 14704245235 013512 0 ustar mike staff /****************************************************************
*
* 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;
#if PHP_VERSION_ID < 80100
int sign;
#else
bool sign;
#endif
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);
#ifdef IGNORE_ZERO_SIGN
done:
#endif
return b0;
}
memcached-3.3.0/g_fmt.h 0000644 0000765 0000024 00000002235 14704245235 013510 0 ustar mike staff /****************************************************************
*
* 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
memcached-3.3.0/fastlz/fastlz.c 0000644 0000765 0000024 00000032520 14704245235 015215 0 ustar mike staff /*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
/*
* Prevent accessing more than 8-bit at once, except on x86 architectures.
*/
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_STRICT_ALIGN
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
#undef FASTLZ_STRICT_ALIGN
#elif defined(_M_IX86) /* Intel, MSVC */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__386)
#undef FASTLZ_STRICT_ALIGN
#elif defined(_X86_) /* MinGW */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__I86__) /* Digital Mars */
#undef FASTLZ_STRICT_ALIGN
#endif
#endif
/*
* FIXME: use preprocessor magic to set this on different platforms!
*/
typedef unsigned char flzuint8;
typedef unsigned short flzuint16;
typedef unsigned int flzuint32;
/* prototypes */
int fastlz_compress(const void* input, int length, void* output);
int fastlz_compress_level(int level, const void* input, int length, void* output);
int fastlz_decompress(const void* input, int length, void* output, int maxout);
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_DISTANCE 8192
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_READU16(p) *((const flzuint16*)(p))
#else
#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
#endif
#define HASH_LOG 13
#define HASH_SIZE (1<< HASH_LOG)
#define HASH_MASK (HASH_SIZE-1)
#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
int fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if(length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if(level == 1)
return fastlz1_decompress(input, length, output, maxout);
if(level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output)
{
if(level == 1)
return fastlz1_compress(input, length, output);
if(level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_bound = ip + length - 2;
const flzuint8* ip_limit = ip + length - 12;
flzuint8* op = (flzuint8*) output;
const flzuint8* htab[HASH_SIZE];
const flzuint8** hslot;
flzuint32 hval;
flzuint32 copy;
/* sanity check */
if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
{
if(length)
{
/* create literal copy only */
*op++ = length-1;
ip_bound++;
while(ip <= ip_bound)
*op++ = *ip++;
return length+1;
}
else
return 0;
}
/* initializes hash table */
for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
*hslot = ip;
/* we start with literal copy */
copy = 2;
*op++ = MAX_COPY-1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
{
const flzuint8* ref;
flzuint32 distance;
/* minimum match length */
flzuint32 len = 3;
/* comparison starting-point */
const flzuint8* anchor = ip;
/* check for a run */
#if FASTLZ_LEVEL==2
if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
{
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
#endif
/* find potential match */
HASH_FUNCTION(hval,ip);
hslot = htab + hval;
ref = htab[hval];
/* calculate distance to the match */
distance = anchor - ref;
/* update hash table */
*hslot = anchor;
/* is this a match? check the first 3 bytes */
if(distance==0 ||
#if FASTLZ_LEVEL==1
(distance >= MAX_DISTANCE) ||
#else
(distance >= MAX_FARDISTANCE) ||
#endif
*ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
goto literal;
#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
if(distance >= MAX_DISTANCE)
{
if(*ip++ != *ref++ || *ip++!= *ref++)
goto literal;
len += 2;
}
match:
#endif
/* last matched byte */
ip = anchor + len;
/* distance is biased */
distance--;
if(!distance)
{
/* zero distance means a run */
flzuint8 x = ip[-1];
while(ip < ip_bound)
if(*ref++ != x) break; else ip++;
}
else
for(;;)
{
/* safe because the outer check against ip limit */
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
while(ip < ip_bound)
if(*ref++ != *ip++) break;
break;
}
/* if we have copied something, adjust the copy count */
if(copy)
/* copy is biased, '0' means 1 byte copy */
*(op-copy-1) = copy-1;
else
/* back, to overwrite the copy count */
op--;
/* reset literal counter */
copy = 0;
/* length is biased, '1' means a match of 3 bytes */
ip -= 3;
len = ip - anchor;
/* encode the match */
#if FASTLZ_LEVEL==2
if(distance < MAX_DISTANCE)
{
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
}
else
{
/* far away, but not yet in the another galaxy... */
if(len < 7)
{
distance -= MAX_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
else
{
distance -= MAX_DISTANCE;
*op++ = (7 << 5) + 31;
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
#else
if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
while(len > MAX_LEN-2)
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 -2;
*op++ = (distance & 255);
len -= MAX_LEN-2;
}
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
#endif
/* update the hash at match boundary */
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
/* assuming literal copy */
*op++ = MAX_COPY-1;
continue;
literal:
*op++ = *anchor++;
ip = anchor;
copy++;
if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* left-over as literal copy */
ip_bound++;
while(ip <= ip_bound)
{
*op++ = *ip++;
copy++;
if(copy == MAX_COPY)
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* if we have copied something, adjust the copy length */
if(copy)
*(op-copy-1) = copy-1;
else
op--;
#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
*(flzuint8*)output |= (1 << 5);
#endif
return op - (flzuint8*)output;
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
flzuint8* op_limit = op + maxout;
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;
do
{
const flzuint8* ref = op;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 8;
if(ctrl >= 32)
{
#if FASTLZ_LEVEL==2
flzuint8 code;
#endif
len--;
ref -= ofs;
if (len == 7-1)
#if FASTLZ_LEVEL==1
len += *ip++;
ref -= *ip++;
#else
do
{
code = *ip++;
len += code;
} while (code==255);
code = *ip++;
ref -= code;
/* match from 16-bit distance */
if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
{
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_DISTANCE;
}
#endif
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
return 0;
#endif
if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
ctrl = *ip++;
else
loop = 0;
if(ref == op)
{
/* optimize copy for a run */
flzuint8 b = ref[-1];
*op++ = b;
*op++ = b;
*op++ = b;
for(; len; --len)
*op++ = b;
}
else
{
#if !defined(FASTLZ_STRICT_ALIGN)
const flzuint16* p;
flzuint16* q;
#endif
/* copy from reference */
ref--;
*op++ = *ref++;
*op++ = *ref++;
*op++ = *ref++;
#if !defined(FASTLZ_STRICT_ALIGN)
/* copy a byte, so that now it's word aligned */
if(len & 1)
{
*op++ = *ref++;
len--;
}
/* copy 16-bit at once */
q = (flzuint16*) op;
op += len;
p = (const flzuint16*) ref;
for(len>>=1; len > 4; len-=4)
{
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
}
for(; len; --len)
*q++ = *p++;
#else
for(; len; --len)
*op++ = *ref++;
#endif
}
}
else
{
ctrl++;
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
return 0;
#endif
*op++ = *ip++;
for(--ctrl; ctrl; ctrl--)
*op++ = *ip++;
loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
if(loop)
ctrl = *ip++;
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
return op - (flzuint8*)output;
}
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
memcached-3.3.0/fastlz/fastlz.h 0000644 0000765 0000024 00000006756 14704245235 015236 0 ustar mike staff /*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
#if defined (__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
*/
int fastlz_compress(const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress above.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
#if defined (__cplusplus)
}
#endif
#endif /* FASTLZ_H */