├── CREDITS ├── config.m4 ├── tests ├── 005.phpt ├── memcache.sh ├── 016.phpt ├── 008.phpt ├── 013.phpt ├── pecl16536.phpt ├── 015.phpt ├── 007.phpt ├── 028.phpt ├── 018.phpt ├── 014.phpt ├── 017.phpt ├── 006.phpt ├── 037.phpt ├── 012.phpt ├── 004.phpt ├── pecl11221.phpt ├── 009.phpt ├── 011.phpt ├── 001.phpt ├── 030.phpt ├── 051.phpt ├── 052.phpt ├── 010.phpt ├── 019a.phpt ├── 026.phpt ├── 022.phpt ├── 050.phpt ├── 045.phpt ├── 035.phpt ├── 019.phpt ├── pecl63272.phpt ├── 027.phpt ├── 036.phpt ├── 024.phpt ├── 053.phpt ├── 022a.phpt ├── 021.phpt ├── 100a.phpt ├── 024a.phpt ├── 003.phpt ├── 100.phpt ├── connect.inc ├── 025.phpt ├── 034.phpt ├── 002.phpt ├── 029.phpt ├── 020.phpt ├── 047.phpt ├── 046.phpt ├── 023.phpt ├── 027a.phpt ├── 032.phpt ├── 031.phpt └── 033.phpt ├── example.php ├── README ├── config.w32 ├── memcache_queue.h ├── LICENSE ├── memcache_queue.c ├── config9.m4 ├── memcache_standard_hash.c ├── memcache.dsp ├── memcache_consistent_hash.c ├── memcache_session.c ├── php_memcache.h ├── package2.xml └── memcache.php /CREDITS: -------------------------------------------------------------------------------- 1 | Antony Dovgal, Mikael Johansson 2 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl this file is required by phpize 3 | 4 | sinclude(config9.m4) 5 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-caching-memcache/master/tests/005.phpt -------------------------------------------------------------------------------- /tests/memcache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # basic script to launch memcached for testing 4 | memcached -p11211 -U11211 -d 5 | memcached -p11212 -U11212 -d 6 | 7 | # if this fails, make sure your user has permissions 8 | # to write to /var/run/memcached 9 | memcached -s /var/run/memcached/memcached.sock -d 10 | -------------------------------------------------------------------------------- /tests/016.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->delete() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('test', 'test'); 11 | 12 | $memcache->delete('test', 10); 13 | 14 | /* the item should be still there */ 15 | $memcache->delete('test'); 16 | 17 | echo "Done\n"; 18 | 19 | ?> 20 | --EXPECT-- 21 | Done 22 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_delete() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | Done 22 | -------------------------------------------------------------------------------- /tests/013.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set() & memcache->get() with strange keys 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set($key, $var, false, 10); 14 | $result = $memcache->get($key); 15 | 16 | var_dump($result); 17 | 18 | ?> 19 | --EXPECT-- 20 | string(4) "test" 21 | -------------------------------------------------------------------------------- /tests/pecl16536.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | PECL bug #16536 (Weight of 0 causes SegFault on memcache_add_server) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port, true, 0)); 12 | var_dump(@$mmc->set('TEST_KEY', 'test_value')); 13 | 14 | echo "Done\n"; 15 | ?> 16 | --EXPECTF-- 17 | bool(false) 18 | bool(false) 19 | Done 20 | -------------------------------------------------------------------------------- /tests/015.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->getVersion() & memcache->getStats() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getVersion(); 11 | 12 | $stats = $memcache->getStats(); 13 | 14 | if ($version) { 15 | echo "version ok\n"; 16 | } 17 | 18 | if ($stats) { 19 | echo "stats ok\n"; 20 | } 21 | 22 | ?> 23 | --EXPECT-- 24 | version ok 25 | stats ok 26 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_get_version() & memcache_get_stats() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 23 | --EXPECT-- 24 | version ok 25 | stats ok 26 | -------------------------------------------------------------------------------- /tests/028.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->addServer() and memcache->close() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port, true, 50); 15 | $result2 = $memcache2->close(); 16 | 17 | var_dump($result1); 18 | var_dump($result2); 19 | 20 | ?> 21 | --EXPECTF-- 22 | bool(true) 23 | bool(true) 24 | -------------------------------------------------------------------------------- /tests/018.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_set() & memcache_add() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | bool(true) 22 | bool(false) 23 | -------------------------------------------------------------------------------- /tests/014.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->increment() & memcache->decrement() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('new_test', 5); 11 | 12 | $result1 = $memcache->increment('new_test'); 13 | $result2 = $memcache->decrement('new_test'); 14 | $result3 = $memcache->get('new_test'); 15 | 16 | var_dump($result1); 17 | var_dump($result2); 18 | var_dump($result3); 19 | 20 | ?> 21 | --EXPECT-- 22 | int(6) 23 | int(5) 24 | string(1) "5" 25 | -------------------------------------------------------------------------------- /tests/017.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Memcache class should be inheritable 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect($host, $port); 18 | $t->foo(); 19 | 20 | var_dump($t); 21 | 22 | echo "Done\n"; 23 | ?> 24 | --EXPECTF-- 25 | foo 26 | object(test)%s%d) { 27 | ["connection"]=> 28 | resource(%d) of type (memcache connection) 29 | } 30 | Done 31 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_increment() & memcache_decrement() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 21 | --EXPECT-- 22 | int(6) 23 | int(5) 24 | string(1) "5" 25 | -------------------------------------------------------------------------------- /tests/037.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | ini_set('memcache.hash_strategy') 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECTF-- 21 | string(8) "standard" 22 | string(10) "consistent" 23 | string(10) "consistent" -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | set("str_key", "String to store in memcached"); 7 | $memcache->set("num_key", 123); 8 | 9 | $object = new StdClass; 10 | $object->attribute = 'test'; 11 | $memcache->set("obj_key", $object); 12 | 13 | $array = Array('assoc'=>123, 345, 567); 14 | $memcache->set("arr_key", $array); 15 | 16 | var_dump($memcache->get('str_key')); 17 | var_dump($memcache->get('num_key')); 18 | var_dump($memcache->get('obj_key')); 19 | } 20 | else { 21 | echo "Connection to memcached failed"; 22 | } 23 | ?> 24 | 25 | -------------------------------------------------------------------------------- /tests/012.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_add() & memcache_replace() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | $result1 = $memcache->add('non_existing_test_key2', $var, false, 1); 15 | $result2 = $memcache->replace('non_existing_test_key2', $var, false, 10); 16 | 17 | var_dump($result1); 18 | var_dump($result2); 19 | 20 | $memcache->delete('non_existing_test_key2'); 21 | 22 | ?> 23 | --EXPECT-- 24 | bool(true) 25 | bool(true) 26 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_add() & memcache_replace() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | $result1 = memcache_add($memcache, 'non_existing_test_key', $var, false, 1); 15 | $result2 = memcache_replace($memcache, 'non_existing_test_key', $var, false, 10); 16 | 17 | var_dump($result1); 18 | var_dump($result2); 19 | 20 | memcache_delete($memcache, 'non_existing_test_key'); 21 | 22 | ?> 23 | --EXPECT-- 24 | bool(true) 25 | bool(true) 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | memcached module for PHP 2 | ------------------------ 3 | This module requires zlib library, used for on-the-fly data (de)compression. 4 | Also, you'll need memcached to use it =) 5 | 6 | The memcached website is here: 7 | http://www.danga.com/memcached/ 8 | 9 | You will probably need libevent to install memcached: 10 | You can download it here: http://www.monkey.org/~provos/libevent/ 11 | 12 | How to run tests: 13 | 1. sh tests/memcache.sh 14 | 2. TEST_PHP_EXECUTABLE=/usr/local/bin/php php -dextension=modules/memcache.so run-tests.php -d extension=modules/memcache.so 15 | 16 | Maintainers: 17 | Herman J. Radtke III hradtke at php dot net 18 | -------------------------------------------------------------------------------- /tests/pecl11221.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | PECL bug #11221 (Double free when returning cached object with __sleep) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('block', $block)); 20 | 21 | return $block; 22 | } 23 | 24 | $cache = new memcache; 25 | $cache->connect($host, $port); 26 | 27 | cache_failure(); 28 | 29 | echo "Done\n"; 30 | ?> 31 | --EXPECTF-- 32 | bool(true) 33 | Done 34 | -------------------------------------------------------------------------------- /tests/009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set() method 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | $result = $memcache->set('test_key', $var, false, 10); 15 | var_dump($result); 16 | 17 | // Should generate a "SERVER_ERROR: out of memory" 18 | $var = str_repeat('a', 1500000); 19 | $memcache->setCompressThreshold(0); 20 | $result = $memcache->set('test_key', $var, false, 10); 21 | var_dump($result); 22 | 23 | echo "Done\n"; 24 | 25 | ?> 26 | --EXPECT-- 27 | bool(true) 28 | bool(false) 29 | Done 30 | -------------------------------------------------------------------------------- /tests/011.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set()/memcache->get() using compression 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | $memcache->set('test_key', $var, MEMCACHE_COMPRESSED, 10); 15 | 16 | $result = $memcache->get('test_key'); 17 | 18 | var_dump($result); 19 | 20 | ?> 21 | --EXPECTF-- 22 | object(stdClass)%s2) { 23 | ["plain_attribute"]=> 24 | string(5) "value" 25 | ["array_attribute"]=> 26 | array(2) { 27 | [0]=> 28 | string(5) "test1" 29 | [1]=> 30 | string(5) "test2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_set() function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $value->array_attribute = array('test1', 'test2'); 13 | memcache_set($memcache, 'test_key', $value, false, 10); 14 | 15 | $key = 123; 16 | $value = 123; 17 | memcache_set($memcache, $key, $value, false, 10); 18 | 19 | var_dump($key); 20 | var_dump($value); 21 | 22 | memcache_set($memcache, $key); 23 | $memcache->set($key); 24 | 25 | echo "Done\n"; 26 | 27 | ?> 28 | --EXPECTF-- 29 | int(123) 30 | int(123) 31 | 32 | Warning: %s parameter%s 33 | 34 | Warning: %s parameter%s 35 | Done -------------------------------------------------------------------------------- /tests/030.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | ini_set("memcache.chunk_size") 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 26 | --EXPECTF-- 27 | string(%d) "%d" 28 | string(5) "16384" 29 | string(5) "32768" 30 | string(5) "32768" 31 | string(5) "32768" 32 | -------------------------------------------------------------------------------- /tests/051.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set() with duplicate keys 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('test_key', array('test')); 11 | var_dump($result); 12 | 13 | $result = $memcache->set('test_key2', 'test2'); 14 | var_dump($result); 15 | 16 | $result = $memcache->get(array('test_key', 'test_key')); 17 | var_dump($result); 18 | 19 | $result = $memcache->get(array('test_key2', 'test_key2')); 20 | var_dump($result); 21 | 22 | ?> 23 | --EXPECT-- 24 | bool(true) 25 | bool(true) 26 | array(1) { 27 | ["test_key"]=> 28 | array(1) { 29 | [0]=> 30 | string(4) "test" 31 | } 32 | } 33 | array(1) { 34 | ["test_key2"]=> 35 | string(5) "test2" 36 | } 37 | -------------------------------------------------------------------------------- /tests/052.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->connect() and memcache->close() in loop 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect($host, $port, false); 15 | 16 | $key = 'test_key'; 17 | $memcache->set($key, 'test'); 18 | $memcache->close(); 19 | 20 | for ($i=0; $i<$count; $i++) { 21 | $memcache->connect($host, $port, false); 22 | $result = $memcache->get($key); 23 | 24 | if (!$result) { 25 | printf('Failed to fetch value for iteration %d', $i); 26 | } 27 | 28 | $memcache->close(); 29 | } 30 | 31 | $end = time(); 32 | printf("%d seconds", $end - $start); 33 | 34 | ?> 35 | --EXPECT-- 36 | 0 seconds -------------------------------------------------------------------------------- /tests/010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->get() function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $value->array_attribute = Array('test1', 'test2'); 13 | $memcache->set('test_key', $value); 14 | 15 | $result = $memcache->get('test_key'); 16 | var_dump($result); 17 | 18 | $result = $memcache->get(array('unset_test_key', 'unset_test_key1')); 19 | var_dump($result); 20 | 21 | ?> 22 | --EXPECTF-- 23 | object(stdClass)%s2) { 24 | ["plain_attribute"]=> 25 | string(5) "value" 26 | ["array_attribute"]=> 27 | array(2) { 28 | [0]=> 29 | string(5) "test1" 30 | [1]=> 31 | string(5) "test2" 32 | } 33 | } 34 | array(0) { 35 | } 36 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("memcache", "memcache support", "no"); 5 | 6 | if (PHP_MEMCACHE != "no") { 7 | if ( 8 | ((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "memcache", PHP_MEMCACHE) )) || 9 | (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "memcache", PHP_MEMCACHE)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)) 10 | ) { 11 | EXTENSION("memcache", "memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c"); 12 | AC_DEFINE('HAVE_MEMCACHE', 1, 'Have memcache support'); 13 | ADD_FLAG("CFLAGS_MEMCACHE", "/D HAVE_MEMCACHE_SESSION=1"); 14 | ADD_EXTENSION_DEP('memcache', 'session'); 15 | } else { 16 | WARNING("memcache not enabled; libraries and headers not found"); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tests/019a.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_add_server() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 18 | --EXPECTF-- 19 | bool(true) 20 | bool(true) 21 | 22 | Warning: memcache_add_server() expects parameter 1 to be Memcache, object given in %s on line %d 23 | NULL 24 | 25 | Warning: memcache_add_server() expects parameter 2 to be string, object given in %s on line %d 26 | NULL 27 | Done 28 | -------------------------------------------------------------------------------- /tests/026.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->delete() with load balancing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host2, $port2); 12 | 13 | $result1 = $memcache->set('delete_fail_key1', $var, false, 1); 14 | $result2 = $memcache->delete('delete_fail_key1'); 15 | $result3 = $memcache->delete('delete_fail_key2'); 16 | 17 | var_dump($result1); 18 | var_dump($result2); 19 | var_dump($result3); 20 | 21 | $memcache = new Memcache(); 22 | $memcache->addServer($nonExistingHost, $nonExistingPort); 23 | $result4 = @$memcache->delete('delete_fail_key1'); 24 | 25 | var_dump($result4); 26 | 27 | ?> 28 | --EXPECT-- 29 | bool(true) 30 | bool(true) 31 | bool(false) 32 | bool(false) 33 | -------------------------------------------------------------------------------- /tests/022.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->getExtendedStats() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($nonExistingHost, $nonExistingPort); 12 | $memcache->addServer($host, $port); 13 | $memcache->addServer($host2, $port2); 14 | 15 | $result1 = @$memcache->getStats(); 16 | $result2 = @$memcache->getExtendedStats(); 17 | 18 | var_dump($result1['pid']); 19 | 20 | var_dump(count($result2)); 21 | var_dump($result2["$host:$port"]['pid']); 22 | var_dump($result2["$host2:$port2"]['pid']); 23 | var_dump($result2["$nonExistingHost:$nonExistingPort"]); 24 | 25 | ?> 26 | --EXPECTF-- 27 | string(%d) "%d" 28 | int(3) 29 | string(%d) "%d" 30 | string(%d) "%d" 31 | bool(false) 32 | -------------------------------------------------------------------------------- /tests/050.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | failure callback throws exception 3 | --SKIPIF-- 4 | = 5.0.0'); ?> 5 | --FILE-- 6 | addServer($nonExistingHost, $nonExistingPort, false, 1, 1, 15, true, '_callback_server_failure'); 17 | $result = 'Test1'; 18 | 19 | try { 20 | $result = @$memcache->set('test_key', 'test-032-01'); 21 | } 22 | catch (Exception $e) { 23 | var_dump($e->getMessage()); 24 | } 25 | 26 | var_dump($result); 27 | 28 | ?> 29 | --EXPECTF-- 30 | string(%d) "%s" 31 | string(5) "Test2" 32 | string(5) "Test1" 33 | -------------------------------------------------------------------------------- /tests/045.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Nested get's in __wakeup() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | get('_test_key2'); 14 | var_dump($result); 15 | } 16 | } 17 | 18 | $a1 = new testclass(); 19 | 20 | $memcache->set('_test_key1', $a1); 21 | $memcache->set('_test_key2', 'Test2'); 22 | 23 | $a2 = $memcache->get('_test_key1'); 24 | var_dump($a2); 25 | 26 | $result = $memcache->get(array('_test_key1', '_test_key2')); 27 | ksort($result); 28 | var_dump($result); 29 | 30 | ?> 31 | --EXPECTF-- 32 | string(5) "Test2" 33 | object(testclass)%s { 34 | } 35 | string(5) "Test2" 36 | array(2) { 37 | ["_test_key1"]=> 38 | object(testclass)%s { 39 | } 40 | ["_test_key2"]=> 41 | string(5) "Test2" 42 | } -------------------------------------------------------------------------------- /tests/035.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache::connect() with unix domain socket 3 | --SKIPIF-- 4 | = 5.0.0'); if (!isset($domainsocket)) die('skip $domainsocket not set'); ?> 5 | --FILE-- 6 | addServer($domainsocket, 0); 12 | var_dump($result); 13 | 14 | $result1 = $memcache->set('test_key', 'abc'); 15 | $result2 = $memcache->get('test_key'); 16 | var_dump($result1); 17 | var_dump($result2); 18 | 19 | $memcache = new Memcache(); 20 | $result = $memcache->connect($domainsocket, 0); 21 | var_dump($result); 22 | 23 | $memcache = memcache_connect($domainsocket, null); 24 | var_dump($result); 25 | 26 | ?> 27 | --EXPECTF-- 28 | bool(true) 29 | bool(true) 30 | string(3) "abc" 31 | bool(true) 32 | bool(true) -------------------------------------------------------------------------------- /tests/019.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->addServer() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('test_key', 'test'); 14 | $result2 = @$memcache->get('test_key'); 15 | 16 | var_dump($result1); 17 | var_dump($result2); 18 | 19 | $result1 = $memcache->addServer($host, $port, true, 1, 1, 15); 20 | $result2 = $memcache->connect($host2, $port2); 21 | 22 | $result3 = $memcache->set('non_existing_test_key', $var, false, 1); 23 | $result4 = $memcache->get('non_existing_test_key'); 24 | $result5 = $memcache->getExtendedStats(); 25 | 26 | var_dump($result1); 27 | var_dump($result2); 28 | var_dump($result3); 29 | var_dump($result4); 30 | var_dump(count($result5)); 31 | 32 | ?> 33 | --EXPECT-- 34 | bool(false) 35 | bool(false) 36 | bool(true) 37 | bool(true) 38 | bool(true) 39 | string(4) "test" 40 | int(2) -------------------------------------------------------------------------------- /tests/pecl63272.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | PECL bug #63272 (Explicitly reserve range of flags in php_memcache.h so application code can use) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 19 | 20 | foreach ($user_flags as $user_flag) { 21 | $m->set("testkey", "testvalue", $user_flag); 22 | $m->set("testkey_compressed", "testvalue", $user_flag | MEMCACHE_COMPRESSED); 23 | 24 | $getflags = 0; 25 | var_dump($m->get("testkey", $getflags)); 26 | var_dump($m->get("testkey_compressed", $getflags)); 27 | } 28 | 29 | echo "Done\n"; 30 | ?> 31 | --EXPECT-- 32 | string(9) "testvalue" 33 | string(9) "testvalue" 34 | string(9) "testvalue" 35 | string(9) "testvalue" 36 | string(9) "testvalue" 37 | string(9) "testvalue" 38 | string(9) "testvalue" 39 | string(9) "testvalue" 40 | Done 41 | -------------------------------------------------------------------------------- /tests/027.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->setCompressThreshold() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setCompressThreshold(10000); 12 | 13 | $result1 = $memcache->set('non_existing_test_key', $var, 0, 1); 14 | $result2 = $memcache->get('non_existing_test_key'); 15 | 16 | var_dump($result1); 17 | var_dump(strlen($result2)); 18 | 19 | $memcache->setCompressThreshold(10000, 0); 20 | $result3 = $memcache->set('non_existing_test_key', $var, 0, 1); 21 | $memcache->setCompressThreshold(10000, 1); 22 | $result4 = $memcache->set('non_existing_test_key', $var, 0, 1); 23 | 24 | var_dump($result3); 25 | var_dump($result4); 26 | 27 | $result5 = $memcache->set('non_existing_test_key', 'abc', MEMCACHE_COMPRESSED, 1); 28 | $result6 = $memcache->get('non_existing_test_key'); 29 | 30 | var_dump($result5); 31 | var_dump($result6); 32 | 33 | ?> 34 | --EXPECT-- 35 | bool(true) 36 | int(15000) 37 | bool(true) 38 | bool(true) 39 | bool(true) 40 | string(3) "abc" 41 | -------------------------------------------------------------------------------- /tests/036.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | ini_set('session.save_handler') 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | get($id); 20 | session_write_close(); 21 | $result3 = $memcache->get($id); 22 | 23 | // Test destroy 24 | session_start(); 25 | $result4 = session_destroy(); 26 | $result5 = $memcache->get($id); 27 | 28 | var_dump($result1); 29 | var_dump($id); 30 | var_dump($result2); 31 | var_dump($result3); 32 | var_dump($result4); 33 | var_dump($result5); 34 | 35 | ?> 36 | --EXPECTF-- 37 | bool(true) 38 | string(%d) "%s" 39 | bool(false) 40 | string(%d) "%s" 41 | bool(true) 42 | bool(false) -------------------------------------------------------------------------------- /tests/024.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->close(), memcache->get() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host2, $port2); 11 | $memcache->addServer($nonExistingHost, $nonExistingPort); 12 | 13 | $result1 = $memcache->close(); 14 | var_dump($result1); 15 | 16 | $memcache = new Memcache(); 17 | $result2 = $memcache->connect($host, $port); 18 | $result3 = $memcache->set('test_key', 'test', false, 1); 19 | $result4 = $memcache->close(); 20 | 21 | // This will fail since all servers have been removed 22 | $result5 = $memcache->get('test_key'); 23 | 24 | // Reconnect server 25 | $result6 = $memcache->connect($host, $port); 26 | $result7 = $memcache->get('test_key'); 27 | 28 | var_dump($result2); 29 | var_dump($result3); 30 | var_dump($result4); 31 | var_dump($result5); 32 | var_dump($result6); 33 | var_dump($result7); 34 | 35 | ?> 36 | --EXPECT-- 37 | bool(true) 38 | bool(true) 39 | bool(true) 40 | bool(true) 41 | bool(false) 42 | bool(true) 43 | string(4) "test" 44 | -------------------------------------------------------------------------------- /tests/053.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | ini_set('session.save_handler') with unix domain socket 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect($domainsocket, 0); 12 | 13 | $session_save_path = ", $domainsocket:0?weight=1, "; 14 | ini_set('session.save_handler', 'memcache'); 15 | ini_set('session.save_path', $session_save_path); 16 | 17 | $result1 = session_start(); 18 | $id = session_id(); 19 | 20 | $_SESSION['_test_key'] = 'Test'; 21 | 22 | $result2 = $memcache->get($id); 23 | session_write_close(); 24 | $result3 = $memcache->get($id); 25 | 26 | // Test destroy 27 | session_start(); 28 | $result4 = session_destroy(); 29 | $result5 = $memcache->get($id); 30 | 31 | var_dump($result1); 32 | var_dump($id); 33 | var_dump($result2); 34 | var_dump($result3); 35 | var_dump($result4); 36 | var_dump($result5); 37 | 38 | ?> 39 | --EXPECTF-- 40 | bool(true) 41 | string(%d) "%s" 42 | bool(false) 43 | string(%d) "%s" 44 | bool(true) 45 | bool(false) -------------------------------------------------------------------------------- /tests/022a.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_get_extended_stats() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 28 | --EXPECTF-- 29 | Warning: memcache_get_extended_stats() expects parameter 1 to be Memcache, array given in %s on line %d 30 | NULL 31 | 32 | Warning: memcache_get_extended_stats() expects parameter 1 to be Memcache, object given in %s on line %d 33 | NULL 34 | string(%d) "%d" 35 | int(3) 36 | string(%d) "%d" 37 | string(%d) "%d" 38 | bool(false) 39 | -------------------------------------------------------------------------------- /tests/021.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set()/memcache->get() with failover 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 15 | $memcache->addServer($nonExistingHost, $nonExistingPort); 16 | 17 | $result1 = @$memcache->set($balanceKey1, $var1, false, 1); 18 | $result2 = $memcache->set($balanceKey2, $var2, false, 1); 19 | $result3 = $memcache->get($balanceKey1); 20 | $result4 = $memcache->get(array($balanceKey1,$balanceKey2)); 21 | 22 | var_dump($result1); 23 | var_dump($result2); 24 | var_dump($result3); 25 | 26 | if (is_array($result4)) 27 | sort($result4); 28 | var_dump($result4); 29 | 30 | $memcache = new Memcache(); 31 | $memcache->addServer($nonExistingHost, $nonExistingPort); 32 | 33 | $result5 = @$memcache->set($balanceKey1, $var1, false, 1); 34 | $result6 = @$memcache->get($balanceKey1); 35 | 36 | var_dump($result5); 37 | var_dump($result6); 38 | 39 | ?> 40 | --EXPECT-- 41 | bool(true) 42 | bool(true) 43 | string(5) "test1" 44 | array(2) { 45 | [0]=> 46 | string(5) "test1" 47 | [1]=> 48 | string(5) "test2" 49 | } 50 | bool(false) 51 | bool(false) 52 | -------------------------------------------------------------------------------- /tests/100a.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_flush() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($nonExistingHost, $nonExistingPort, false); 21 | 22 | $result2 = memcache_flush($memcache2); 23 | var_dump($result2); 24 | 25 | memcache_close($memcache); 26 | var_dump(memcache_flush($memcache)); 27 | var_dump(memcache_flush(new stdClass)); 28 | var_dump(memcache_flush('')); 29 | 30 | echo "Done\n"; 31 | 32 | ?> 33 | --EXPECTF-- 34 | Notice: memcache_flush(): Server %s failed with: Connection %s 35 | bool(true) 36 | 37 | Notice: memcache_flush(): Server %s failed with: Connection %s 38 | bool(false) 39 | bool(true) 40 | 41 | Warning: memcache_flush() expects parameter 1 to be Memcache, object given %s 42 | NULL 43 | 44 | Warning: memcache_flush() expects parameter 1 to be Memcache, string given %s 45 | NULL 46 | Done 47 | -------------------------------------------------------------------------------- /tests/024a.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_close(), memcache_get() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect($host, $port); 18 | $result3 = memcache_set($memcache, 'test_key', 'test', false, 1); 19 | $result4 = memcache_close($memcache); 20 | 21 | // This will fail since all servers have been removed 22 | $result5 = memcache_get($memcache, 'test_key'); 23 | 24 | var_dump($result2); 25 | var_dump($result3); 26 | var_dump($result4); 27 | var_dump($result5); 28 | 29 | 30 | var_dump(memcache_close($memcache)); 31 | var_dump(memcache_close($memcache)); 32 | var_dump(memcache_close(new stdClass)); 33 | var_dump(memcache_close("")); 34 | 35 | echo "Done\n"; 36 | 37 | ?> 38 | --EXPECTF-- 39 | bool(true) 40 | bool(true) 41 | bool(true) 42 | bool(true) 43 | bool(false) 44 | bool(true) 45 | bool(true) 46 | 47 | Warning: memcache_close() expects parameter 1 to be Memcache, object given in %s on line %d 48 | NULL 49 | 50 | Warning: memcache_close() expects parameter 1 to be Memcache, string given in %s on line %d 51 | NULL 52 | Done 53 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_set()/memcache_get() using compression 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | memcache_set($memcache, 'test_key', $var, MEMCACHE_COMPRESSED, 10); 15 | memcache_set($memcache, 'test_key1', $var, MEMCACHE_COMPRESSED, 10); 16 | 17 | $result = memcache_get($memcache, 'test_key'); 18 | 19 | var_dump($result); 20 | 21 | $result = memcache_get($memcache, Array('test_key', 'test_key1')); 22 | 23 | var_dump($result); 24 | 25 | ?> 26 | --EXPECTF-- 27 | object(stdClass)%s2) { 28 | ["plain_attribute"]=> 29 | string(5) "value" 30 | ["array_attribute"]=> 31 | array(2) { 32 | [0]=> 33 | string(5) "test1" 34 | [1]=> 35 | string(5) "test2" 36 | } 37 | } 38 | array(2) { 39 | ["test_key"]=> 40 | object(stdClass)%s2) { 41 | ["plain_attribute"]=> 42 | string(5) "value" 43 | ["array_attribute"]=> 44 | array(2) { 45 | [0]=> 46 | string(5) "test1" 47 | [1]=> 48 | string(5) "test2" 49 | } 50 | } 51 | ["test_key1"]=> 52 | object(stdClass)%s2) { 53 | ["plain_attribute"]=> 54 | string(5) "value" 55 | ["array_attribute"]=> 56 | array(2) { 57 | [0]=> 58 | string(5) "test1" 59 | [1]=> 60 | string(5) "test2" 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/100.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->flush() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 17 | 18 | $result1 = $memcache->set('test_key', 'abc'); 19 | $result2 = $memcache->get('test_key'); 20 | var_dump($result1); 21 | var_dump($result2); 22 | 23 | $result = $memcache->flush(time()+3); 24 | var_dump($result); 25 | 26 | sleep(1); 27 | 28 | $result = $memcache->get('test_key'); 29 | var_dump($result); 30 | 31 | sleep(2); 32 | 33 | $result = $memcache->get('test_key'); 34 | var_dump($result); 35 | 36 | // Test partly failing flush 37 | $memcache = new Memcache(); 38 | $memcache->addServer($host, $port); 39 | $memcache->addServer($nonExistingHost, $nonExistingPort); 40 | 41 | $result = @$memcache->flush(); 42 | var_dump($result); 43 | 44 | // Test failing flush 45 | $memcache = new Memcache(); 46 | $memcache->addServer($nonExistingHost, $nonExistingPort); 47 | 48 | $result = @$memcache->flush(); 49 | var_dump($result); 50 | 51 | ?> 52 | --EXPECT-- 53 | bool(true) 54 | string(3) "abc" 55 | bool(true) 56 | string(3) "abc" 57 | bool(false) 58 | bool(true) 59 | bool(false) 60 | -------------------------------------------------------------------------------- /tests/connect.inc: -------------------------------------------------------------------------------- 1 | array( 32 | 'crc32' => array('key1_abc', 'key2_abcde'), 33 | 'fnv' => array('key1_a', 'key2_2534534'), 34 | ), 35 | 'standard' => array( 36 | 'crc32' => array('load_test_key1', 'load_test_key2'), 37 | 'fnv' => array('key1_ab', 'key2_a'), 38 | ), 39 | ); 40 | 41 | $strat = strtolower(ini_get('memcache.hash_strategy')); 42 | $func = strtolower(ini_get('memcache.hash_function')); 43 | list ($balanceKey1, $balanceKey2) = $balanceKeys[$strat][$func]; 44 | 45 | $memcache = @memcache_connect($host, $port); 46 | 47 | if (!$memcache) { 48 | die('skip Connection to memcached failed'); 49 | } 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /tests/025.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->increment() with load balancing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 15 | $memcache->addServer($host2, $port2); 16 | 17 | $memcache1 = memcache_connect($host, $port); 18 | $memcache2 = memcache_connect($host2, $port2); 19 | 20 | $memcache1->set($balanceKey1, '', false, 2); 21 | $memcache1->set($balanceKey2, '', false, 2); 22 | $memcache2->set($balanceKey1, '', false, 2); 23 | $memcache2->set($balanceKey2, '', false, 2); 24 | 25 | $result1 = $memcache->set($balanceKey1, $var1, false, 2); // hashes to host2 26 | $result2 = $memcache->set($balanceKey2, $var2, false, 2); // hashes to host1 27 | $result3 = $memcache->increment($balanceKey1); 28 | $result4 = $memcache->increment($balanceKey2); 29 | 30 | var_dump($result1); 31 | var_dump($result2); 32 | var_dump($result3); 33 | var_dump($result4); 34 | 35 | $result5 = $memcache1->get($balanceKey1); 36 | $result6 = $memcache1->get($balanceKey2); 37 | $result7 = $memcache2->get($balanceKey1); 38 | $result8 = $memcache2->get($balanceKey2); 39 | 40 | var_dump($result5); 41 | var_dump($result6); 42 | var_dump($result7); 43 | var_dump($result8); 44 | 45 | ?> 46 | --EXPECT-- 47 | bool(true) 48 | bool(true) 49 | int(11) 50 | int(21) 51 | string(0) "" 52 | string(2) "21" 53 | string(2) "11" 54 | string(0) "" 55 | -------------------------------------------------------------------------------- /tests/034.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->getStats() with arguments 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('test_key', 'abc'); 11 | var_dump($result); 12 | 13 | $result = $memcache->getStats(); 14 | var_dump($result['pid']); 15 | 16 | $result = $memcache->getStats('abc'); 17 | var_dump($result); 18 | 19 | $result = $memcache->getStats('reset'); 20 | var_dump($result); 21 | 22 | $result = $memcache->getStats('malloc'); 23 | var_dump($result['arena_size']); 24 | 25 | $result = $memcache->getStats('slabs'); 26 | var_dump($result[key($result)]['chunk_size']); 27 | var_dump($result[key($result)]['free_chunks_end']); 28 | $slab = key($result); 29 | 30 | $result = $memcache->getStats('cachedump', $slab, 10); 31 | var_dump($result[key($result)][0]); 32 | var_dump($result[key($result)][1]); 33 | 34 | $result = $memcache->getStats('items'); 35 | var_dump($result['items'][$slab]['number']); 36 | 37 | //$result = $memcache->getStats('sizes'); 38 | //var_dump($result['64']); 39 | 40 | print "\n"; 41 | 42 | $result = $memcache->getExtendedStats('abc'); 43 | var_dump($result["$host:$port"]); 44 | 45 | $result = $memcache->getExtendedStats('items'); 46 | var_dump(isset($result["$host:$port"]['items'])); 47 | 48 | ?> 49 | --EXPECTF-- 50 | bool(true) 51 | string(%d) "%d" 52 | bool(false) 53 | bool(true) 54 | string(%d) "%d" 55 | string(%d) "%d" 56 | string(%d) "%d" 57 | string(%d) "%d" 58 | string(%d) "%d" 59 | string(%d) "%d" 60 | 61 | bool(false) 62 | bool(true) 63 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_get() function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | plain_attribute = 'value'; 12 | $var->array_attribute = Array('test1', 'test2'); 13 | 14 | $result = memcache_set($memcache, 'test_key', $var); 15 | var_dump($result); 16 | 17 | $result = memcache_set($memcache, 'test_key1', $var); 18 | var_dump($result); 19 | 20 | $result = memcache_get($memcache, 'test_key'); 21 | var_dump($result); 22 | 23 | $result = memcache_get($memcache, array('test_key', 'test_key1')); 24 | var_dump($result); 25 | 26 | $result = memcache_get($memcache, array('unset_test_key', 'unset_test_key1')); 27 | var_dump($result); 28 | 29 | ?> 30 | --EXPECTF-- 31 | bool(true) 32 | bool(true) 33 | object(stdClass)%s2) { 34 | ["plain_attribute"]=> 35 | string(5) "value" 36 | ["array_attribute"]=> 37 | array(2) { 38 | [0]=> 39 | string(5) "test1" 40 | [1]=> 41 | string(5) "test2" 42 | } 43 | } 44 | array(2) { 45 | ["test_key"]=> 46 | object(stdClass)%s2) { 47 | ["plain_attribute"]=> 48 | string(5) "value" 49 | ["array_attribute"]=> 50 | array(2) { 51 | [0]=> 52 | string(5) "test1" 53 | [1]=> 54 | string(5) "test2" 55 | } 56 | } 57 | ["test_key1"]=> 58 | object(stdClass)%s2) { 59 | ["plain_attribute"]=> 60 | string(5) "value" 61 | ["array_attribute"]=> 62 | array(2) { 63 | [0]=> 64 | string(5) "test1" 65 | [1]=> 66 | string(5) "test2" 67 | } 68 | } 69 | } 70 | array(0) { 71 | } -------------------------------------------------------------------------------- /tests/029.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | ini_set("memcache.allow_failover") 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 17 | $memcache->addServer($nonExistingHost, $nonExistingPort); 18 | 19 | $result1 = @$memcache->set($balanceKey1, $var1, false, 1); // hashes to $host2 20 | $result2 = $memcache->set($balanceKey2, $var2, false, 1); // hashes to $host1 21 | $result3 = $memcache->get($balanceKey1); 22 | $result4 = $memcache->get($balanceKey2); 23 | 24 | var_dump($result1); 25 | var_dump($result2); 26 | var_dump($result3); 27 | var_dump($result4); 28 | 29 | $result = $memcache->get(array($balanceKey1, $balanceKey2)); 30 | sort($result); 31 | var_dump($result); 32 | 33 | ini_set('memcache.allow_failover', 0); 34 | 35 | $result1 = $memcache->get($balanceKey1); 36 | $result2 = $memcache->get($balanceKey2); 37 | 38 | var_dump($result1); 39 | var_dump($result2); 40 | 41 | $result = $memcache->get(array($balanceKey1, $balanceKey2)); 42 | sort($result); 43 | var_dump($result); 44 | 45 | $result = ini_set('memcache.allow_failover', "abc"); 46 | var_dump($result); 47 | 48 | ?> 49 | --EXPECTF-- 50 | bool(true) 51 | bool(true) 52 | string(5) "test1" 53 | string(5) "test2" 54 | array(2) { 55 | [0]=> 56 | string(5) "test1" 57 | [1]=> 58 | string(5) "test2" 59 | } 60 | bool(false) 61 | string(5) "test2" 62 | array(1) { 63 | [0]=> 64 | string(5) "test2" 65 | } 66 | string(1) "0" 67 | -------------------------------------------------------------------------------- /tests/020.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->set()/memcache->get() with multiple keys and load balancing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 15 | $memcache->addServer($host2, $port2); 16 | 17 | $memcache1 = memcache_connect($host, $port); 18 | $memcache2 = memcache_pconnect($host2, $port2); 19 | 20 | $memcache1->set($balanceKey1, '', false, 2); 21 | $memcache1->set($balanceKey2, '', false, 2); 22 | $memcache2->set($balanceKey1, '', false, 2); 23 | $memcache2->set($balanceKey2, '', false, 2); 24 | 25 | $result1 = $memcache->set($balanceKey1, $var1, false, 2); // hashes to $host2 26 | $result2 = $memcache->set($balanceKey2, $var2, false, 2); // hashes to $host1 27 | $result3 = $memcache->get(array($balanceKey1, $balanceKey2)); 28 | sort($result3); 29 | 30 | var_dump($result1); 31 | var_dump($result2); 32 | var_dump($result3); 33 | 34 | $result4 = $memcache1->get($balanceKey1); // return false; key1 is at $host2 35 | $result5 = $memcache1->get($balanceKey2); 36 | $result6 = $memcache2->get($balanceKey1); 37 | $result7 = $memcache2->get($balanceKey2); // return false; key2 is at $host1 38 | 39 | var_dump($result4); 40 | var_dump($result5); 41 | var_dump($result6); 42 | var_dump($result7); 43 | 44 | ?> 45 | --EXPECT-- 46 | bool(true) 47 | bool(true) 48 | array(2) { 49 | [0]=> 50 | string(5) "test1" 51 | [1]=> 52 | string(5) "test2" 53 | } 54 | string(0) "" 55 | string(5) "test2" 56 | string(5) "test1" 57 | string(0) "" 58 | -------------------------------------------------------------------------------- /tests/047.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->get() with flags 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | set('test_key1', 'test1', $flag1); 14 | $memcache->set('test_key2', 'test2', $flag2); 15 | 16 | // Test OO 17 | $result1 = null; 18 | $result2 = $memcache->get('test_key1', $result1); 19 | 20 | var_dump($result1); 21 | var_dump($result2); 22 | 23 | $result3 = null; 24 | $result4 = $memcache->get(array('test_key1', 'test_key2'), $result3); 25 | 26 | if (is_array($result3)) 27 | ksort($result3); 28 | if (is_array($result4)) 29 | ksort($result4); 30 | 31 | var_dump($result3); 32 | var_dump($result4); 33 | 34 | // Test procedural 35 | $result1 = null; 36 | $result2 = memcache_get($memcache, 'test_key1', $result1); 37 | 38 | var_dump($result1); 39 | var_dump($result2); 40 | 41 | $result3 = null; 42 | $result4 = memcache_get($memcache, array('test_key1', 'test_key2'), $result3); 43 | 44 | if (is_array($result3)) 45 | ksort($result3); 46 | if (is_array($result4)) 47 | ksort($result4); 48 | 49 | var_dump($result3); 50 | var_dump($result4); 51 | 52 | ?> 53 | --EXPECT-- 54 | int(256) 55 | string(5) "test1" 56 | array(2) { 57 | ["test_key1"]=> 58 | int(256) 59 | ["test_key2"]=> 60 | int(512) 61 | } 62 | array(2) { 63 | ["test_key1"]=> 64 | string(5) "test1" 65 | ["test_key2"]=> 66 | string(5) "test2" 67 | } 68 | int(256) 69 | string(5) "test1" 70 | array(2) { 71 | ["test_key1"]=> 72 | int(256) 73 | ["test_key2"]=> 74 | int(512) 75 | } 76 | array(2) { 77 | ["test_key1"]=> 78 | string(5) "test1" 79 | ["test_key2"]=> 80 | string(5) "test2" 81 | } -------------------------------------------------------------------------------- /tests/046.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | hash strategies and functions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | $functions) { 17 | foreach ($functions as $function => $keys) { 18 | ini_set('memcache.hash_strategy', $strategy); 19 | ini_set('memcache.hash_function', $function); 20 | list ($balanceKey1, $balanceKey2) = $keys; 21 | 22 | print "\n$strategy:$function\n"; 23 | 24 | $memcache = new Memcache(); 25 | $memcache->addServer($host, $port); 26 | $memcache->addServer($host2, $port2); 27 | 28 | $memcache1->set($balanceKey1, '', false, 2); 29 | $memcache1->set($balanceKey2, '', false, 2); 30 | $memcache2->set($balanceKey1, '', false, 2); 31 | $memcache2->set($balanceKey2, '', false, 2); 32 | 33 | $memcache->set($balanceKey1, $var1, false, 2); // hashes to $host2 34 | $memcache->set($balanceKey2, $var2, false, 2); // hashes to $host1 35 | 36 | $result4 = $memcache1->get($balanceKey1); // return false; key1 is at $host2 37 | $result5 = $memcache1->get($balanceKey2); 38 | $result6 = $memcache2->get($balanceKey1); 39 | $result7 = $memcache2->get($balanceKey2); // return false; key2 is at $host1 40 | 41 | var_dump($result4); 42 | var_dump($result5); 43 | var_dump($result6); 44 | var_dump($result7); 45 | } 46 | } 47 | 48 | ?> 49 | --EXPECT-- 50 | 51 | consistent:crc32 52 | string(0) "" 53 | string(5) "test2" 54 | string(5) "test1" 55 | string(0) "" 56 | 57 | consistent:fnv 58 | string(0) "" 59 | string(5) "test2" 60 | string(5) "test1" 61 | string(0) "" 62 | 63 | standard:crc32 64 | string(0) "" 65 | string(5) "test2" 66 | string(5) "test1" 67 | string(0) "" 68 | 69 | standard:fnv 70 | string(0) "" 71 | string(5) "test2" 72 | string(5) "test1" 73 | string(0) "" 74 | -------------------------------------------------------------------------------- /tests/023.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->delete() with load balancing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port); 15 | $memcache->addServer($host2, $port2); 16 | 17 | $memcache1 = memcache_connect($host, $port); 18 | $memcache2 = memcache_connect($host2, $port2); 19 | 20 | $memcache1->set($balanceKey1, '', false, 2); 21 | $memcache1->set($balanceKey2, '', false, 2); 22 | $memcache2->set($balanceKey1, '', false, 2); 23 | $memcache2->set($balanceKey2, '', false, 2); 24 | 25 | $result1 = $memcache->set($balanceKey1, $var1, false, 2); // hashes to host2 26 | $result2 = $memcache->set($balanceKey2, $var2, false, 2); // hashes to host1 27 | $result3 = $memcache->get($balanceKey1); 28 | $result4 = $memcache->get($balanceKey2); 29 | 30 | var_dump($result1); 31 | var_dump($result2); 32 | var_dump($result3); 33 | var_dump($result4); 34 | print "\r\n"; 35 | 36 | $result5 = $memcache1->get($balanceKey1); 37 | $result6 = $memcache1->get($balanceKey2); 38 | $result7 = $memcache2->get($balanceKey1); 39 | $result8 = $memcache2->get($balanceKey2); 40 | 41 | var_dump($result5); 42 | var_dump($result6); 43 | var_dump($result7); 44 | var_dump($result8); 45 | print "\r\n"; 46 | 47 | $result9 = $memcache->delete($balanceKey1); 48 | $result10 = $memcache->get($balanceKey1); 49 | $result11 = $memcache2->get($balanceKey1); 50 | 51 | var_dump($result9); 52 | var_dump($result10); 53 | var_dump($result11); 54 | 55 | $result12 = $memcache->delete($balanceKey2); 56 | $result13 = $memcache->get($balanceKey2); 57 | $result14 = $memcache1->get($balanceKey2); 58 | 59 | var_dump($result12); 60 | var_dump($result13); 61 | var_dump($result14); 62 | 63 | ?> 64 | --EXPECT-- 65 | bool(true) 66 | bool(true) 67 | string(5) "test1" 68 | string(5) "test2" 69 | 70 | string(0) "" 71 | string(5) "test2" 72 | string(5) "test1" 73 | string(0) "" 74 | 75 | bool(true) 76 | bool(false) 77 | bool(false) 78 | bool(true) 79 | bool(false) 80 | bool(false) 81 | -------------------------------------------------------------------------------- /tests/027a.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache_set_compress_threshold() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 43 | --EXPECTF-- 44 | bool(true) 45 | int(15000) 46 | bool(true) 47 | bool(true) 48 | bool(true) 49 | string(3) "abc" 50 | 51 | Warning: memcache_set_compress_threshold() expects parameter 1 to be Memcache, array given in %s on line %d 52 | NULL 53 | 54 | Warning: memcache_set_compress_threshold()%s threshold must be a positive integer in %s on line %d 55 | bool(false) 56 | 57 | Warning: memcache_set_compress_threshold()%s min_savings must be a float in the 0..1 range in %s on line %d 58 | bool(false) 59 | 60 | Warning: memcache_set_compress_threshold()%s threshold must be a positive integer in %s on line %d 61 | bool(false) 62 | 63 | Warning: memcache_set_compress_threshold() expects parameter 1 to be Memcache, object given in %s on line %d 64 | NULL 65 | Done 66 | -------------------------------------------------------------------------------- /tests/032.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->getServerStatus(), memcache->setServerParams() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port, false); 13 | $memcache->addServer($host2, $port2, false); 14 | 15 | $memcache1 = memcache_connect($host, $port); 16 | $memcache2 = memcache_pconnect($host2, $port2); 17 | 18 | $memcache1->set($balanceKey1, '', false, 2); 19 | $memcache1->set($balanceKey2, '', false, 2); 20 | $memcache2->set($balanceKey1, '', false, 2); 21 | $memcache2->set($balanceKey2, '', false, 2); 22 | 23 | $result1 = $memcache->set($balanceKey1, 'test-030-01', false, 2); // hashes to $host2 24 | $result2 = $memcache->set($balanceKey2, 'test-030-02', false, 2); // hashes to $host1 25 | 26 | var_dump($result1); 27 | var_dump($result2); 28 | 29 | $result4 = $memcache1->get($balanceKey1); // return false; key1 is at $host2 30 | $result5 = $memcache1->get($balanceKey2); 31 | $result6 = $memcache2->get($balanceKey1); 32 | $result7 = $memcache2->get($balanceKey2); // return false; key2 is at $host1 33 | 34 | var_dump($result4); 35 | var_dump($result5); 36 | var_dump($result6); 37 | var_dump($result7); 38 | 39 | // Add server in failed mode 40 | $memcache = new Memcache(); 41 | $memcache->addServer($host, $port, false); 42 | $memcache->addServer($host2, $port2, false, 1, 1, -1, false); 43 | 44 | $result8 = $memcache->getServerStatus($host, $port); 45 | $result9 = $memcache->getServerStatus($host2, $port2); 46 | 47 | var_dump($result8); 48 | var_dump($result9); 49 | 50 | // Hot-add failed server 51 | $result10 = $memcache->setServerParams($host2, $port2, 1, 15, true); 52 | $result11 = $memcache->getServerStatus($host2, $port2); 53 | 54 | var_dump($result10); 55 | var_dump($result11); 56 | 57 | $result12 = $memcache->set($balanceKey1, 'test-030-03', false, 1); // hashes to $host2 58 | $result13 = $memcache2->get($balanceKey1); // key should be at $host2 (reconnected $host2) 59 | 60 | var_dump($result12); 61 | var_dump($result13); 62 | 63 | ?> 64 | --EXPECT-- 65 | bool(true) 66 | bool(true) 67 | string(0) "" 68 | string(11) "test-030-02" 69 | string(11) "test-030-01" 70 | string(0) "" 71 | int(1) 72 | int(0) 73 | bool(true) 74 | int(1) 75 | bool(true) 76 | string(11) "test-030-03" 77 | -------------------------------------------------------------------------------- /memcache_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifndef MEMCACHE_QUEUE_H_ 23 | #define MEMCACHE_QUEUE_H_ 24 | 25 | /* request / server stack */ 26 | #define MMC_QUEUE_PREALLOC 25 27 | 28 | typedef struct mmc_queue { 29 | void **items; /* items on queue */ 30 | int alloc; /* allocated size */ 31 | int head; /* head index in ring buffer */ 32 | int tail; /* tail index in ring buffer */ 33 | int len; 34 | } mmc_queue_t; 35 | 36 | #define mmc_queue_release(q) memset((q), 0, sizeof(*(q))) 37 | #define mmc_queue_reset(q) (q)->len = (q)->head = (q)->tail = 0 38 | #define mmc_queue_item(q, i) ((q)->tail + (i) < (q)->alloc ? (q)->items[(q)->tail + (i)] : (q)->items[(i) - ((q)->alloc - (q)->tail)]) 39 | 40 | void mmc_queue_push(mmc_queue_t *, void *); 41 | void *mmc_queue_pop(mmc_queue_t *); 42 | int mmc_queue_contains(mmc_queue_t *, void *); 43 | void mmc_queue_free(mmc_queue_t *); 44 | void mmc_queue_copy(mmc_queue_t *, mmc_queue_t *); 45 | void mmc_queue_remove(mmc_queue_t *, void *); 46 | 47 | #endif /*MEMCACHE_QUEUE_H_*/ 48 | 49 | /* 50 | * Local variables: 51 | * tab-width: 4 52 | * c-basic-offset: 4 53 | * End: 54 | * vim600: noet sw=4 ts=4 fdm=marker 55 | * vim<600: noet sw=4 ts=4 56 | */ 57 | -------------------------------------------------------------------------------- /tests/031.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->addServer() adding server in failed mode 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | addServer($host, $port, false); 13 | $memcache->addServer($host2, $port2, false); 14 | 15 | $memcache1 = memcache_connect($host, $port); 16 | $memcache2 = memcache_connect($host2, $port2); 17 | 18 | $memcache1->set($balanceKey1, '', false, 2); 19 | $memcache1->set($balanceKey1, '', false, 2); 20 | $memcache2->set($balanceKey1, '', false, 2); 21 | $memcache2->set($balanceKey2, '', false, 2); 22 | 23 | $result1 = $memcache->set($balanceKey1, 'test-030-01', false, 2); // hashes to $host2 24 | $result2 = $memcache->set($balanceKey2, 'test-030-02', false, 2); // hashes to $host1 25 | 26 | var_dump($result1); 27 | var_dump($result2); 28 | 29 | $result4 = $memcache1->get($balanceKey1); // return false; key1 is at $host2 30 | $result5 = $memcache1->get($balanceKey2); 31 | $result6 = $memcache2->get($balanceKey1); 32 | $result7 = $memcache2->get($balanceKey2); // return false; key2 is at $host1 33 | 34 | var_dump($result4); 35 | var_dump($result5); 36 | var_dump($result6); 37 | var_dump($result7); 38 | 39 | // Add server in failed mode 40 | $memcache = new Memcache(); 41 | $memcache->addServer($host, $port, false); 42 | $memcache->addServer($host2, $port2, false, 1, 1, -1, false); 43 | 44 | $result8 = $memcache->set($balanceKey1, 'test-030-03', false, 1); // hashes to $host2 45 | $result9 = $memcache->set($balanceKey2, 'test-030-04', false, 1); // hashes to $host1 46 | 47 | var_dump($result8); 48 | var_dump($result9); 49 | 50 | $result10 = $memcache1->get($balanceKey1); // key should be $host1 (failed over from $host2) 51 | $result11 = $memcache1->get($balanceKey2); // key should always be at $host1 52 | 53 | var_dump($result10); 54 | var_dump($result11); 55 | 56 | // Single server in failed mode 57 | function _callback_server_failure($host, $port) { 58 | print "_callback_server_failure()\n"; 59 | } 60 | 61 | $memcache = new Memcache(); 62 | $memcache->addServer($host, $port, true, 1, 1, -1, false, '_callback_server_failure'); 63 | $result13 = $memcache->add('test_key', 'Test'); 64 | $result14 = $memcache->get('test_key'); 65 | 66 | var_dump($result13); 67 | var_dump($result14); 68 | 69 | ?> 70 | --EXPECT-- 71 | bool(true) 72 | bool(true) 73 | string(0) "" 74 | string(11) "test-030-02" 75 | string(11) "test-030-01" 76 | string(0) "" 77 | bool(true) 78 | bool(true) 79 | string(11) "test-030-03" 80 | string(11) "test-030-04" 81 | bool(false) 82 | bool(false) 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------- 2 | The PHP License, Version 3.0 3 | Copyright (c) 1999 - 2005 The PHP Group. All rights reserved. 4 | -------------------------------------------------------------------- 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, is permitted provided that the following conditions 8 | are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | 3. The name "PHP" must not be used to endorse or promote products 19 | derived from this software without prior written permission. For 20 | written permission, please contact group@php.net. 21 | 22 | 4. Products derived from this software may not be called "PHP", nor 23 | may "PHP" appear in their name, without prior written permission 24 | from group@php.net. You may indicate that your software works in 25 | conjunction with PHP by saying "Foo for PHP" instead of calling 26 | it "PHP Foo" or "phpfoo" 27 | 28 | 5. The PHP Group may publish revised and/or new versions of the 29 | license from time to time. Each version will be given a 30 | distinguishing version number. 31 | Once covered code has been published under a particular version 32 | of the license, you may always continue to use it under the terms 33 | of that version. You may also choose to use such covered code 34 | under the terms of any subsequent version of the license 35 | published by the PHP Group. No one other than the PHP Group has 36 | the right to modify the terms applicable to covered code created 37 | under this License. 38 | 39 | 6. Redistributions of any form whatsoever must retain the following 40 | acknowledgment: 41 | "This product includes PHP, freely available from 42 | ". 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP 48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 | OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | -------------------------------------------------------------------- 58 | 59 | This software consists of voluntary contributions made by many 60 | individuals on behalf of the PHP Group. 61 | 62 | The PHP Group can be contacted via Email at group@php.net. 63 | 64 | For more information on the PHP Group and the PHP project, 65 | please see . 66 | 67 | This product includes the Zend Engine, freely available at 68 | . 69 | -------------------------------------------------------------------------------- /tests/033.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | memcache->addServer() with server failure callback 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setServerParams($host, $tcp_port, 1, -1, false, '_callback_server_failure'); 19 | } 20 | 21 | // Test function callback using addServer() 22 | $memcache = new Memcache(); 23 | $memcache->addServer($nonExistingHost, $nonExistingPort, false, 1, 1, 15, true, '_callback_server_failure'); 24 | 25 | $result1 = $memcache->set('test_key', 'test-032-01'); 26 | var_dump($result1); 27 | 28 | class MemcachedFailureHandler { 29 | function _callback_server_failure($host, $tcp_port, $udp_port, $error, $errnum) { 30 | var_dump($host); 31 | var_dump($tcp_port); 32 | var_dump($udp_port); 33 | var_dump($error); 34 | var_dump($errnum); 35 | } 36 | } 37 | 38 | // Test OO callback using setServerParams() 39 | $memcache = new Memcache(); 40 | $memcache->addServer($nonExistingHost, $nonExistingPort, false); 41 | $result2 = $memcache->setServerParams($nonExistingHost, $nonExistingPort, 1, 15, true, 42 | array(new MemcachedFailureHandler(), '_callback_server_failure')); 43 | var_dump($result2); 44 | 45 | $result3 = $memcache->set('test_key', 'test-032-01'); 46 | var_dump($result3); 47 | 48 | // Test giving non-existing callback to addServer() 49 | $memcache = new Memcache(); 50 | $result4 = @$memcache->addServer($nonExistingHost, $nonExistingPort, false, 1, 1, 15, true, 'non_existing_user_function'); 51 | var_dump($result4); 52 | 53 | // Test giving non-existing callback to setServerParams() 54 | $memcache = new Memcache(); 55 | $memcache->addServer($nonExistingHost, $nonExistingPort, false); 56 | $result5 = @$memcache->setServerParams($nonExistingHost, $nonExistingPort, 1, 15, true, 'non_existing_user_function'); 57 | var_dump($result5); 58 | 59 | // Test resetting callback to null 60 | $memcache = new Memcache(); 61 | $memcache->addServer($nonExistingHost, $nonExistingPort, false, 1, 1, 15, true, '_callback_server_failure'); 62 | $result6 = $memcache->setServerParams($nonExistingHost, $nonExistingPort, 1, 15, true, null); 63 | $result7 = @$memcache->set('test_key', 'test-032-01'); 64 | 65 | var_dump($result6); 66 | var_dump($result7); 67 | 68 | // Test refcount 69 | function _callback_server_failure2($host, $tcp_port, $udp_port, $error, $errnum) { 70 | var_dump($error); 71 | } 72 | 73 | function test_connect() { 74 | global $mc, $nonExistingHost, $nonExistingPort; 75 | $mc = new Memcache(); 76 | $mc->addServer($nonExistingHost, $nonExistingPort, false, 1, 1, 15, true, '_callback_server_failure2'); 77 | } 78 | 79 | test_connect(); 80 | $result10 = $mc->set('test_key', 'test-032-02'); 81 | var_dump($result10); 82 | 83 | ?> 84 | --EXPECTF-- 85 | string(%d) "%s" 86 | int(%d) 87 | int(%d) 88 | string(%d) "Connection %s" 89 | int(%d) 90 | bool(false) 91 | bool(true) 92 | string(%d) "%s" 93 | int(%d) 94 | int(%d) 95 | string(%d) "Connection %s" 96 | int(%d) 97 | bool(false) 98 | bool(false) 99 | bool(false) 100 | bool(true) 101 | bool(false) 102 | string(%d) "Connection %s" 103 | bool(false) 104 | -------------------------------------------------------------------------------- /memcache_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2004 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "memcache_queue.h" 28 | 29 | void mmc_queue_push(mmc_queue_t *queue, void *ptr) { 30 | if (mmc_queue_contains(queue, ptr)) return; 31 | 32 | if (queue->len >= queue->alloc) { 33 | int increase = 1 + MMC_QUEUE_PREALLOC; 34 | queue->alloc += increase; 35 | queue->items = erealloc(queue->items, sizeof(*queue->items) * queue->alloc); 36 | 37 | /* move tail segment downwards */ 38 | if (queue->head < queue->tail) { 39 | memmove(queue->items + queue->tail + increase, queue->items + queue->tail, (queue->alloc - queue->tail - increase) * sizeof(*queue->items)); 40 | queue->tail += increase; 41 | } 42 | } 43 | 44 | if (queue->len) { 45 | queue->head++; 46 | 47 | if (queue->head >= queue->alloc) { 48 | queue->head = 0; 49 | } 50 | } 51 | 52 | queue->items[queue->head] = ptr; 53 | queue->len++; 54 | } 55 | 56 | void *mmc_queue_pop(mmc_queue_t *queue) { 57 | if (queue->len) { 58 | void *ptr; 59 | 60 | ptr = queue->items[queue->tail]; 61 | queue->len--; 62 | 63 | if (queue->len) { 64 | queue->tail++; 65 | 66 | if (queue->tail >= queue->alloc) { 67 | queue->tail = 0; 68 | } 69 | } 70 | 71 | return ptr; 72 | } 73 | return NULL; 74 | } 75 | 76 | int mmc_queue_contains(mmc_queue_t *queue, void *ptr) { 77 | if (queue != NULL) { 78 | int i; 79 | 80 | for (i=0; i < queue->len; i++) { 81 | if (mmc_queue_item(queue, i) == ptr) { 82 | return 1; 83 | } 84 | } 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | void mmc_queue_free(mmc_queue_t *queue) { 91 | if (queue->items != NULL) { 92 | efree(queue->items); 93 | } 94 | memset(queue, 0, sizeof(*queue)); 95 | } 96 | 97 | void mmc_queue_copy(mmc_queue_t *source, mmc_queue_t *target) { 98 | if (target->alloc != source->alloc) { 99 | target->alloc = source->alloc; 100 | erealloc(target->items, sizeof(*target->items) * target->alloc); 101 | } 102 | 103 | memcpy(target->items, source->items, sizeof(*source->items) * source->alloc); 104 | target->head = source->head; 105 | target->tail = source->tail; 106 | target->len = source->len; 107 | } 108 | 109 | void mmc_queue_remove(mmc_queue_t *queue, void *ptr) { 110 | void *item; 111 | mmc_queue_t original = *queue; 112 | mmc_queue_release(queue); 113 | 114 | while ((item = mmc_queue_pop(&original)) != NULL) { 115 | if (item != ptr) { 116 | mmc_queue_push(queue, item); 117 | } 118 | } 119 | 120 | mmc_queue_free(&original); 121 | } 122 | 123 | /* 124 | * Local variables: 125 | * tab-width: 4 126 | * c-basic-offset: 4 127 | * End: 128 | * vim600: noet sw=4 ts=4 fdm=marker 129 | * vim<600: noet sw=4 ts=4 130 | */ 131 | -------------------------------------------------------------------------------- /config9.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl $Id$ 3 | dnl 4 | 5 | PHP_ARG_ENABLE(memcache, whether to enable memcache support, 6 | [ --enable-memcache Enable memcache support]) 7 | 8 | PHP_ARG_ENABLE(memcache-session, whether to enable memcache session handler support, 9 | [ --disable-memcache-session Disable memcache session handler support], yes, no) 10 | 11 | if test -z "$PHP_ZLIB_DIR"; then 12 | PHP_ARG_WITH(zlib-dir, for the location of ZLIB, 13 | [ --with-zlib-dir[=DIR] memcache: Set the path to ZLIB install prefix.], no, no) 14 | fi 15 | 16 | if test -z "$PHP_DEBUG"; then 17 | AC_ARG_ENABLE(debug, 18 | [ --enable-debug compile with debugging symbols],[ 19 | PHP_DEBUG=$enableval 20 | ],[ 21 | PHP_DEBUG=no 22 | ]) 23 | fi 24 | 25 | if test "$PHP_MEMCACHE" != "no"; then 26 | 27 | if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then 28 | if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then 29 | PHP_ZLIB_DIR="$PHP_ZLIB_DIR" 30 | PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib" 31 | elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then 32 | PHP_ZLIB_DIR="$PHP_ZLIB_DIR" 33 | PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include" 34 | else 35 | AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"]) 36 | fi 37 | else 38 | for i in /usr/local /usr; do 39 | if test -f "$i/include/zlib/zlib.h"; then 40 | PHP_ZLIB_DIR="$i" 41 | PHP_ZLIB_INCDIR="$i/include/zlib" 42 | elif test -f "$i/include/zlib.h"; then 43 | PHP_ZLIB_DIR="$i" 44 | PHP_ZLIB_INCDIR="$i/include" 45 | fi 46 | done 47 | fi 48 | 49 | dnl # zlib 50 | AC_MSG_CHECKING([for the location of zlib]) 51 | if test "$PHP_ZLIB_DIR" = "no"; then 52 | AC_MSG_ERROR([memcache support requires ZLIB. Use --with-zlib-dir= to specify prefix where ZLIB include and library are located]) 53 | else 54 | AC_MSG_RESULT([$PHP_ZLIB_DIR]) 55 | if test "z$PHP_LIBDIR" != "z"; then 56 | dnl PHP5+ 57 | PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHE_SHARED_LIBADD) 58 | else 59 | dnl PHP4 60 | PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/lib, MEMCACHE_SHARED_LIBADD) 61 | fi 62 | PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) 63 | fi 64 | 65 | if test "$PHP_MEMCACHE_SESSION" != "no"; then 66 | AC_MSG_CHECKING([for session includes]) 67 | session_inc_path="" 68 | 69 | if test -f "$abs_srcdir/include/php/ext/session/php_session.h"; then 70 | session_inc_path="$abs_srcdir/include/php" 71 | elif test -f "$abs_srcdir/ext/session/php_session.h"; then 72 | session_inc_path="$abs_srcdir" 73 | elif test -f "$phpincludedir/ext/session/php_session.h"; then 74 | session_inc_path="$phpincludedir" 75 | else 76 | for i in php php4 php5 php6; do 77 | if test -f "$prefix/include/$i/ext/session/php_session.h"; then 78 | session_inc_path="$prefix/include/$i" 79 | fi 80 | done 81 | fi 82 | 83 | if test "$session_inc_path" = ""; then 84 | AC_MSG_ERROR([Cannot find php_session.h]) 85 | else 86 | AC_MSG_RESULT([$session_inc_path]) 87 | fi 88 | fi 89 | 90 | AC_MSG_CHECKING([for memcache session support]) 91 | if test "$PHP_MEMCACHE_SESSION" != "no"; then 92 | AC_MSG_RESULT([enabled]) 93 | AC_DEFINE(HAVE_MEMCACHE_SESSION,1,[Whether memcache session handler is enabled]) 94 | AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support]) 95 | PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c, $ext_shared,,-I$session_inc_path) 96 | ifdef([PHP_ADD_EXTENSION_DEP], 97 | [ 98 | PHP_ADD_EXTENSION_DEP(memcache, session) 99 | ]) 100 | else 101 | AC_MSG_RESULT([disabled]) 102 | AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support]) 103 | PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c, $ext_shared) 104 | fi 105 | 106 | dnl this is needed to build the extension with phpize and -Wall 107 | 108 | if test "$PHP_DEBUG" = "yes"; then 109 | CFLAGS="$CFLAGS -Wall" 110 | fi 111 | 112 | fi 113 | -------------------------------------------------------------------------------- /memcache_standard_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_memcache.h" 28 | 29 | ZEND_EXTERN_MODULE_GLOBALS(memcache) 30 | 31 | typedef struct mmc_standard_state { 32 | int num_servers; 33 | mmc_t **buckets; 34 | int num_buckets; 35 | mmc_hash_function hash; 36 | } mmc_standard_state_t; 37 | 38 | void *mmc_standard_create_state(mmc_hash_function hash) /* {{{ */ 39 | { 40 | mmc_standard_state_t *state = emalloc(sizeof(mmc_standard_state_t)); 41 | memset(state, 0, sizeof(mmc_standard_state_t)); 42 | state->hash = hash; 43 | return state; 44 | } 45 | /* }}} */ 46 | 47 | void mmc_standard_free_state(void *s) /* {{{ */ 48 | { 49 | mmc_standard_state_t *state = s; 50 | if (state != NULL) { 51 | if (state->buckets != NULL) { 52 | efree(state->buckets); 53 | } 54 | efree(state); 55 | } 56 | } 57 | /* }}} */ 58 | 59 | static unsigned int mmc_hash(mmc_standard_state_t *state, const char *key, int key_len) /* {{{ */ 60 | { 61 | unsigned int hash = (state->hash(key, key_len) >> 16) & 0x7fff; 62 | return hash ? hash : 1; 63 | } 64 | /* }}} */ 65 | 66 | mmc_t *mmc_standard_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */ 67 | { 68 | mmc_standard_state_t *state = s; 69 | mmc_t *mmc; 70 | 71 | if (state->num_servers > 1) { 72 | unsigned int hash = mmc_hash(state, key, key_len), i; 73 | mmc = state->buckets[hash % state->num_buckets]; 74 | 75 | /* perform failover if needed */ 76 | for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && ihost, mmc->port, mmc->status)); 80 | 81 | hash += mmc_hash(state, next_key, next_len); 82 | mmc = state->buckets[hash % state->num_buckets]; 83 | 84 | efree(next_key); 85 | } 86 | } 87 | else { 88 | mmc = state->buckets[0]; 89 | mmc_open(mmc, 0, NULL, NULL TSRMLS_CC); 90 | } 91 | 92 | return mmc->status != MMC_STATUS_FAILED ? mmc : NULL; 93 | } 94 | /* }}} */ 95 | 96 | void mmc_standard_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */ 97 | { 98 | mmc_standard_state_t *state = s; 99 | int i; 100 | 101 | /* add weight number of buckets for this server */ 102 | if (state->num_buckets) { 103 | state->buckets = erealloc(state->buckets, sizeof(mmc_t *) * (state->num_buckets + weight)); 104 | } 105 | else { 106 | state->buckets = emalloc(sizeof(mmc_t *) * (weight)); 107 | } 108 | 109 | for (i=0; ibuckets[state->num_buckets + i] = mmc; 111 | } 112 | 113 | state->num_buckets += weight; 114 | state->num_servers++; 115 | } 116 | /* }}} */ 117 | 118 | mmc_hash_t mmc_standard_hash = { 119 | mmc_standard_create_state, 120 | mmc_standard_free_state, 121 | mmc_standard_find_server, 122 | mmc_standard_add_server 123 | }; 124 | 125 | /* 126 | * Local variables: 127 | * tab-width: 4 128 | * c-basic-offset: 4 129 | * End: 130 | * vim600: noet sw=4 ts=4 fdm=marker 131 | * vim<600: noet sw=4 ts=4 132 | */ 133 | -------------------------------------------------------------------------------- /memcache.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="memcache" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 6 | 7 | CFG=memcache - Win32 Debug_TS 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "memcache.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "memcache.mak" CFG="memcache - Win32 Debug_TS" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "memcache - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") 21 | !MESSAGE "memcache - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | MTL=midl.exe 30 | RSC=rc.exe 31 | 32 | !IF "$(CFG)" == "memcache - Win32 Release_TS" 33 | 34 | # PROP BASE Use_MFC 0 35 | # PROP BASE Use_Debug_Libraries 0 36 | # PROP BASE Output_Dir "Release_TS" 37 | # PROP BASE Intermediate_Dir "Release_TS" 38 | # PROP BASE Ignore_Export_Lib 0 39 | # PROP BASE Target_Dir "" 40 | # PROP Use_MFC 0 41 | # PROP Use_Debug_Libraries 0 42 | # PROP Output_Dir "Release_TS" 43 | # PROP Intermediate_Dir "Release_TS" 44 | # PROP Ignore_Export_Lib 0 45 | # PROP Target_Dir "" 46 | # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MEMCACHE_EXPORTS" /YX /FD /c 47 | # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "PHP_EXPORTS" /D "COMPILE_DL_MEMCACHE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MEMCACHE=1 /YX /FD /c 48 | # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 49 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 50 | # ADD BASE RSC /l 0x407 /d "NDEBUG" 51 | # ADD RSC /l 0x407 /d "NDEBUG" 52 | BSC32=bscmake.exe 53 | # ADD BASE BSC32 /nologo 54 | # ADD BSC32 /nologo 55 | LINK32=link.exe 56 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 57 | # ADD LINK32 php4ts.lib zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS\php_memcache.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline" 58 | 59 | !ELSEIF "$(CFG)" == "memcache - Win32 Debug_TS" 60 | 61 | # PROP BASE Use_MFC 0 62 | # PROP BASE Use_Debug_Libraries 1 63 | # PROP BASE Output_Dir "Debug_TS" 64 | # PROP BASE Intermediate_Dir "Debug_TS" 65 | # PROP BASE Target_Dir "" 66 | # PROP Use_MFC 0 67 | # PROP Use_Debug_Libraries 1 68 | # PROP Output_Dir "Debug_TS" 69 | # PROP Intermediate_Dir "Debug_TS" 70 | # PROP Ignore_Export_Lib 0 71 | # PROP Target_Dir "" 72 | # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MEMCACHE_EXPORTS" /YX /FD /GZ /c 73 | # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "PHP_EXPORTS" /D "COMPILE_DL_MEMCACHE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MEMCACHE=1 /FR /YX /FD /GZ /c 74 | # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 75 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 76 | # ADD BASE RSC /l 0x407 /d "_DEBUG" 77 | # ADD RSC /l 0x407 /d "_DEBUG" 78 | BSC32=bscmake.exe 79 | # ADD BASE BSC32 /nologo 80 | # ADD BSC32 /nologo 81 | LINK32=link.exe 82 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept 83 | # ADD LINK32 php4ts_debug.lib zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS\php_memcache.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS" 84 | 85 | !ENDIF 86 | 87 | # Begin Target 88 | 89 | # Name "memcache - Win32 Release_TS" 90 | # Name "memcache - Win32 Debug_TS" 91 | # Begin Group "Source Files" 92 | 93 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 94 | # Begin Source File 95 | 96 | SOURCE=.\memcache.c 97 | # End Source File 98 | # End Group 99 | # Begin Group "Header Files" 100 | 101 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 102 | # Begin Source File 103 | 104 | SOURCE=.\php_memcache.h 105 | # End Source File 106 | # End Group 107 | # End Target 108 | # End Project 109 | -------------------------------------------------------------------------------- /memcache_consistent_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include 27 | 28 | #include "php.h" 29 | #include "php_memcache.h" 30 | 31 | ZEND_EXTERN_MODULE_GLOBALS(memcache) 32 | 33 | typedef struct mmc_consistent_point { 34 | mmc_t *server; 35 | unsigned int point; 36 | } mmc_consistent_point_t; 37 | 38 | typedef struct mmc_consistent_state { 39 | int num_servers; 40 | mmc_consistent_point_t *points; 41 | int num_points; 42 | mmc_t *buckets[MMC_CONSISTENT_BUCKETS]; 43 | int buckets_populated; 44 | mmc_hash_function hash; 45 | } mmc_consistent_state_t; 46 | 47 | void *mmc_consistent_create_state(mmc_hash_function hash) /* {{{ */ 48 | { 49 | mmc_consistent_state_t *state = emalloc(sizeof(mmc_consistent_state_t)); 50 | memset(state, 0, sizeof(mmc_consistent_state_t)); 51 | state->hash = hash; 52 | return state; 53 | } 54 | /* }}} */ 55 | 56 | void mmc_consistent_free_state(void *s) /* {{{ */ 57 | { 58 | mmc_consistent_state_t *state = s; 59 | if (state != NULL) { 60 | if (state->points != NULL) { 61 | efree(state->points); 62 | } 63 | efree(state); 64 | } 65 | } 66 | /* }}} */ 67 | 68 | static int mmc_consistent_compare(const void *a, const void *b) /* {{{ */ 69 | { 70 | if (((mmc_consistent_point_t *)a)->point < ((mmc_consistent_point_t *)b)->point) { 71 | return -1; 72 | } 73 | if (((mmc_consistent_point_t *)a)->point > ((mmc_consistent_point_t *)b)->point) { 74 | return 1; 75 | } 76 | return 0; 77 | } 78 | /* }}} */ 79 | 80 | static mmc_t *mmc_consistent_find(mmc_consistent_state_t *state, unsigned int point) /* {{{ */ 81 | { 82 | int lo = 0, hi = state->num_points - 1, mid; 83 | 84 | while (1) { 85 | /* point is outside interval or lo >= hi, wrap-around */ 86 | if (point <= state->points[lo].point || point > state->points[hi].point) { 87 | return state->points[lo].server; 88 | } 89 | 90 | /* test middle point */ 91 | mid = lo + (hi - lo) / 2; 92 | MMC_DEBUG(("mmc_consistent_find: lo %d, hi %d, mid %d, point %u, midpoint %u", lo, hi, mid, point, state->points[mid].point)); 93 | 94 | /* perfect match */ 95 | if (point <= state->points[mid].point && point > (mid ? state->points[mid-1].point : 0)) { 96 | return state->points[mid].server; 97 | } 98 | 99 | /* too low, go up */ 100 | if (state->points[mid].point < point) { 101 | lo = mid + 1; 102 | } 103 | else { 104 | hi = mid - 1; 105 | } 106 | } 107 | } 108 | /* }}} */ 109 | 110 | static void mmc_consistent_populate_buckets(mmc_consistent_state_t *state) /* {{{ */ 111 | { 112 | unsigned int i, step = 0xffffffff / MMC_CONSISTENT_BUCKETS; 113 | 114 | qsort((void *)state->points, state->num_points, sizeof(mmc_consistent_point_t), mmc_consistent_compare); 115 | for (i=0; ibuckets[i] = mmc_consistent_find(state, step * i); 117 | } 118 | 119 | state->buckets_populated = 1; 120 | } 121 | /* }}} */ 122 | 123 | mmc_t *mmc_consistent_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */ 124 | { 125 | mmc_consistent_state_t *state = s; 126 | mmc_t *mmc; 127 | 128 | if (state->num_servers > 1) { 129 | unsigned int i, hash = state->hash(key, key_len); 130 | 131 | if (!state->buckets_populated) { 132 | mmc_consistent_populate_buckets(state); 133 | } 134 | 135 | mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS]; 136 | 137 | /* perform failover if needed */ 138 | for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && ihost, mmc->port, mmc->status)); 142 | 143 | hash = state->hash(next_key, next_len); 144 | mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS]; 145 | 146 | efree(next_key); 147 | } 148 | } 149 | else { 150 | mmc = state->points[0].server; 151 | mmc_open(mmc, 0, NULL, NULL TSRMLS_CC); 152 | } 153 | 154 | return mmc->status != MMC_STATUS_FAILED ? mmc : NULL; 155 | } 156 | /* }}} */ 157 | 158 | void mmc_consistent_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */ 159 | { 160 | mmc_consistent_state_t *state = s; 161 | int i, key_len, points = weight * MMC_CONSISTENT_POINTS; 162 | 163 | /* buffer for "host:port-i\0" */ 164 | char *key = emalloc(strlen(mmc->host) + MAX_LENGTH_OF_LONG * 2 + 3); 165 | 166 | /* add weight * MMC_CONSISTENT_POINTS number of points for this server */ 167 | state->points = erealloc(state->points, sizeof(mmc_consistent_point_t) * (state->num_points + points)); 168 | 169 | for (i=0; ihost, mmc->port, i); 171 | state->points[state->num_points + i].server = mmc; 172 | state->points[state->num_points + i].point = state->hash(key, key_len); 173 | MMC_DEBUG(("mmc_consistent_add_server: key %s, point %lu", key, state->points[state->num_points + i].point)); 174 | } 175 | 176 | state->num_points += points; 177 | state->num_servers++; 178 | state->buckets_populated = 0; 179 | 180 | efree(key); 181 | } 182 | /* }}} */ 183 | 184 | mmc_hash_t mmc_consistent_hash = { 185 | mmc_consistent_create_state, 186 | mmc_consistent_free_state, 187 | mmc_consistent_find_server, 188 | mmc_consistent_add_server 189 | }; 190 | 191 | /* 192 | * Local variables: 193 | * tab-width: 4 194 | * c-basic-offset: 4 195 | * End: 196 | * vim600: noet sw=4 ts=4 fdm=marker 197 | * vim<600: noet sw=4 ts=4 198 | */ 199 | -------------------------------------------------------------------------------- /memcache_session.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2004 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include 27 | #include "php.h" 28 | #include "php_ini.h" 29 | #include "php_variables.h" 30 | 31 | #include "SAPI.h" 32 | #include "ext/standard/url.h" 33 | #include "php_memcache.h" 34 | 35 | #if HAVE_MEMCACHE_SESSION 36 | #include "ext/session/php_session.h" 37 | #endif 38 | 39 | ps_module ps_mod_memcache = { 40 | PS_MOD(memcache) 41 | }; 42 | 43 | /* {{{ PS_OPEN_FUNC 44 | */ 45 | PS_OPEN_FUNC(memcache) 46 | { 47 | mmc_pool_t *pool; 48 | mmc_t *mmc; 49 | 50 | php_url *url; 51 | zval *params, **param; 52 | int i, j, path_len; 53 | 54 | pool = mmc_pool_new(TSRMLS_C); 55 | 56 | for (i=0,j=0,path_len=strlen(save_path); iquery != NULL) { 94 | MAKE_STD_ZVAL(params); 95 | array_init(params); 96 | 97 | sapi_module.treat_data(PARSE_STRING, estrdup(url->query), params TSRMLS_CC); 98 | 99 | if (zend_hash_find(Z_ARRVAL_P(params), "persistent", sizeof("persistent"), (void **) ¶m) != FAILURE) { 100 | convert_to_boolean_ex(param); 101 | persistent = Z_BVAL_PP(param); 102 | } 103 | 104 | if (zend_hash_find(Z_ARRVAL_P(params), "weight", sizeof("weight"), (void **) ¶m) != FAILURE) { 105 | convert_to_long_ex(param); 106 | weight = Z_LVAL_PP(param); 107 | } 108 | 109 | if (zend_hash_find(Z_ARRVAL_P(params), "timeout", sizeof("timeout"), (void **) ¶m) != FAILURE) { 110 | convert_to_long_ex(param); 111 | timeout = Z_LVAL_PP(param); 112 | } 113 | 114 | if (zend_hash_find(Z_ARRVAL_P(params), "retry_interval", sizeof("retry_interval"), (void **) ¶m) != FAILURE) { 115 | convert_to_long_ex(param); 116 | retry_interval = Z_LVAL_PP(param); 117 | } 118 | 119 | zval_ptr_dtor(¶ms); 120 | } 121 | 122 | if (url->scheme && url->path && !strcmp(url->scheme, "file")) { 123 | char *host; 124 | int host_len = spprintf(&host, 0, "unix://%s", url->path); 125 | 126 | /* chop off trailing :0 port specifier */ 127 | if (!strcmp(host + host_len - 2, ":0")) { 128 | host_len -= 2; 129 | } 130 | 131 | if (persistent) { 132 | mmc = mmc_find_persistent(host, host_len, 0, timeout, retry_interval TSRMLS_CC); 133 | } 134 | else { 135 | mmc = mmc_server_new(host, host_len, 0, 0, timeout, retry_interval TSRMLS_CC); 136 | } 137 | 138 | efree(host); 139 | } 140 | else { 141 | if (url->host == NULL || weight <= 0 || timeout <= 0) { 142 | php_url_free(url); 143 | mmc_pool_free(pool TSRMLS_CC); 144 | PS_SET_MOD_DATA(NULL); 145 | return FAILURE; 146 | } 147 | 148 | if (persistent) { 149 | mmc = mmc_find_persistent(url->host, strlen(url->host), url->port, timeout, retry_interval TSRMLS_CC); 150 | } 151 | else { 152 | mmc = mmc_server_new(url->host, strlen(url->host), url->port, 0, timeout, retry_interval TSRMLS_CC); 153 | } 154 | } 155 | 156 | mmc_pool_add(pool, mmc, weight); 157 | php_url_free(url); 158 | } 159 | } 160 | 161 | if (pool->num_servers) { 162 | PS_SET_MOD_DATA(pool); 163 | return SUCCESS; 164 | } 165 | 166 | mmc_pool_free(pool TSRMLS_CC); 167 | PS_SET_MOD_DATA(NULL); 168 | return FAILURE; 169 | } 170 | /* }}} */ 171 | 172 | /* {{{ PS_CLOSE_FUNC 173 | */ 174 | PS_CLOSE_FUNC(memcache) 175 | { 176 | mmc_pool_t *pool = PS_GET_MOD_DATA(); 177 | 178 | if (pool) { 179 | mmc_pool_free(pool TSRMLS_CC); 180 | PS_SET_MOD_DATA(NULL); 181 | } 182 | 183 | return SUCCESS; 184 | } 185 | /* }}} */ 186 | 187 | /* {{{ PS_READ_FUNC 188 | */ 189 | PS_READ_FUNC(memcache) 190 | { 191 | mmc_pool_t *pool = PS_GET_MOD_DATA(); 192 | zval *result; 193 | 194 | if (pool) { 195 | char key_tmp[MMC_KEY_MAX_SIZE]; 196 | unsigned int key_tmp_len; 197 | 198 | if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) { 199 | return FAILURE; 200 | } 201 | 202 | MAKE_STD_ZVAL(result); 203 | ZVAL_NULL(result); 204 | 205 | if (mmc_exec_retrieval_cmd(pool, key_tmp, key_tmp_len, &result, NULL TSRMLS_CC) <= 0 || Z_TYPE_P(result) != IS_STRING) { 206 | zval_ptr_dtor(&result); 207 | return FAILURE; 208 | } 209 | 210 | *val = Z_STRVAL_P(result); 211 | *vallen = Z_STRLEN_P(result); 212 | FREE_ZVAL(result); 213 | return SUCCESS; 214 | } 215 | 216 | return FAILURE; 217 | } 218 | /* }}} */ 219 | 220 | /* {{{ PS_WRITE_FUNC 221 | */ 222 | PS_WRITE_FUNC(memcache) 223 | { 224 | mmc_pool_t *pool = PS_GET_MOD_DATA(); 225 | 226 | if (pool) { 227 | char key_tmp[MMC_KEY_MAX_SIZE]; 228 | unsigned int key_tmp_len; 229 | 230 | if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) { 231 | return FAILURE; 232 | } 233 | 234 | if (mmc_pool_store(pool, "set", sizeof("set")-1, key_tmp, key_tmp_len, 0, INI_INT("session.gc_maxlifetime"), val, vallen TSRMLS_CC)) { 235 | return SUCCESS; 236 | } 237 | } 238 | 239 | return FAILURE; 240 | } 241 | /* }}} */ 242 | 243 | /* {{{ PS_DESTROY_FUNC 244 | */ 245 | PS_DESTROY_FUNC(memcache) 246 | { 247 | mmc_pool_t *pool = PS_GET_MOD_DATA(); 248 | mmc_t *mmc; 249 | 250 | int result = -1; 251 | 252 | if (pool) { 253 | char key_tmp[MMC_KEY_MAX_SIZE]; 254 | unsigned int key_tmp_len; 255 | 256 | if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) { 257 | return FAILURE; 258 | } 259 | 260 | while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) { 261 | if ((result = mmc_delete(mmc, key_tmp, key_tmp_len, 0 TSRMLS_CC)) < 0) { 262 | mmc_server_failure(mmc TSRMLS_CC); 263 | } 264 | } 265 | 266 | if (result >= 0) { 267 | return SUCCESS; 268 | } 269 | } 270 | 271 | return FAILURE; 272 | } 273 | /* }}} */ 274 | 275 | /* {{{ PS_GC_FUNC 276 | */ 277 | PS_GC_FUNC(memcache) 278 | { 279 | return SUCCESS; 280 | } 281 | /* }}} */ 282 | 283 | /* 284 | * Local variables: 285 | * tab-width: 4 286 | * c-basic-offset: 4 287 | * End: 288 | * vim600: noet sw=4 ts=4 fdm=marker 289 | * vim<600: noet sw=4 ts=4 290 | */ 291 | -------------------------------------------------------------------------------- /php_memcache.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Antony Dovgal | 16 | | Mikael Johansson | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifndef PHP_MEMCACHE_H 23 | #define PHP_MEMCACHE_H 24 | 25 | extern zend_module_entry memcache_module_entry; 26 | #define phpext_memcache_ptr &memcache_module_entry 27 | 28 | #ifdef PHP_WIN32 29 | #define PHP_MEMCACHE_API __declspec(dllexport) 30 | #else 31 | #define PHP_MEMCACHE_API 32 | #endif 33 | 34 | #ifdef ZTS 35 | #include "TSRM.h" 36 | #endif 37 | 38 | #include "ext/standard/php_smart_str_public.h" 39 | 40 | PHP_MINIT_FUNCTION(memcache); 41 | PHP_MSHUTDOWN_FUNCTION(memcache); 42 | PHP_RINIT_FUNCTION(memcache); 43 | PHP_MINFO_FUNCTION(memcache); 44 | 45 | PHP_FUNCTION(memcache_connect); 46 | PHP_FUNCTION(memcache_pconnect); 47 | PHP_FUNCTION(memcache_add_server); 48 | PHP_FUNCTION(memcache_set_server_params); 49 | PHP_FUNCTION(memcache_get_server_status); 50 | PHP_FUNCTION(memcache_get_version); 51 | PHP_FUNCTION(memcache_add); 52 | PHP_FUNCTION(memcache_set); 53 | PHP_FUNCTION(memcache_replace); 54 | PHP_FUNCTION(memcache_get); 55 | PHP_FUNCTION(memcache_delete); 56 | PHP_FUNCTION(memcache_debug); 57 | PHP_FUNCTION(memcache_get_stats); 58 | PHP_FUNCTION(memcache_get_extended_stats); 59 | PHP_FUNCTION(memcache_set_compress_threshold); 60 | PHP_FUNCTION(memcache_increment); 61 | PHP_FUNCTION(memcache_decrement); 62 | PHP_FUNCTION(memcache_close); 63 | PHP_FUNCTION(memcache_flush); 64 | PHP_FUNCTION(memcache_setoptimeout); 65 | 66 | #define PHP_MEMCACHE_VERSION "2.2.7" 67 | 68 | #define MMC_BUF_SIZE 4096 69 | #define MMC_SERIALIZED 1 70 | #define MMC_COMPRESSED 2 71 | /* These flags are set here to reserve the for use by users of the pecl-memcache in set and get */ 72 | #define MMC_RESERVED_APPLICATIONDEFINEDFLAG_12 4096 /* not used in pecl-memcache code */ 73 | #define MMC_RESERVED_APPLICATIONDEFINEDFLAG_13 8192 /* not used in pecl-memcache code */ 74 | #define MMC_RESERVED_APPLICATIONDEFINEDFLAG_14 16384 /* not used in pecl-memcache code */ 75 | #define MMC_RESERVED_APPLICATIONDEFINEDFLAG_15 32768 /* not used in pecl-memcache code */ 76 | 77 | #define MMC_DEFAULT_TIMEOUT 1 /* seconds */ 78 | #define MMC_KEY_MAX_SIZE 250 /* stoled from memcached sources =) */ 79 | #define MMC_DEFAULT_RETRY 15 /* retry failed server after x seconds */ 80 | #define MMC_DEFAULT_SAVINGS 0.2 /* minimum 20% savings for compression to be used */ 81 | #define MMC_DEFAULT_CACHEDUMP_LIMIT 100 /* number of entries */ 82 | 83 | #define MMC_STATUS_FAILED 0 84 | #define MMC_STATUS_DISCONNECTED 1 85 | #define MMC_STATUS_UNKNOWN 2 86 | #define MMC_STATUS_CONNECTED 3 87 | 88 | #define MMC_OK 0 89 | #define MMC_REQUEST_FAILURE -1 90 | 91 | #define MMC_STANDARD_HASH 1 92 | #define MMC_CONSISTENT_HASH 2 93 | #define MMC_HASH_CRC32 1 /* CRC32 hash function */ 94 | #define MMC_HASH_FNV1A 2 /* FNV-1a hash function */ 95 | 96 | #define MMC_CONSISTENT_POINTS 160 /* points per server */ 97 | #define MMC_CONSISTENT_BUCKETS 1024 /* number of precomputed buckets, should be power of 2 */ 98 | 99 | typedef struct mmc { 100 | php_stream *stream; 101 | char inbuf[MMC_BUF_SIZE]; 102 | smart_str outbuf; 103 | char *host; 104 | unsigned short port; 105 | long timeout; 106 | long timeoutms; /* takes precedence over timeout */ 107 | long connect_timeoutms; /* takes precedence over timeout */ 108 | long failed; 109 | long retry_interval; 110 | int persistent; 111 | int status; 112 | char *error; /* last error message */ 113 | int errnum; /* last error code */ 114 | zval *failure_callback; 115 | zend_bool in_free; 116 | } mmc_t; 117 | 118 | /* hashing strategy */ 119 | typedef unsigned int (*mmc_hash_function)(const char *, int); 120 | typedef void * (*mmc_hash_create_state)(mmc_hash_function); 121 | typedef void (*mmc_hash_free_state)(void *); 122 | typedef mmc_t * (*mmc_hash_find_server)(void *, const char *, int TSRMLS_DC); 123 | typedef void (*mmc_hash_add_server)(void *, mmc_t *, unsigned int); 124 | 125 | #define mmc_pool_find(pool, key, key_len) \ 126 | pool->hash->find_server(pool->hash_state, key, key_len) 127 | 128 | typedef struct mmc_hash { 129 | mmc_hash_create_state create_state; 130 | mmc_hash_free_state free_state; 131 | mmc_hash_find_server find_server; 132 | mmc_hash_add_server add_server; 133 | } mmc_hash_t; 134 | 135 | /* 32 bit magic FNV-1a prime and init */ 136 | #define FNV_32_PRIME 0x01000193 137 | #define FNV_32_INIT 0x811c9dc5 138 | 139 | typedef struct mmc_pool { 140 | mmc_t **servers; 141 | int num_servers; 142 | mmc_t **requests; 143 | int compress_threshold; 144 | double min_compress_savings; 145 | zend_bool in_free; 146 | mmc_hash_t *hash; 147 | void *hash_state; 148 | } mmc_pool_t; 149 | 150 | /* our globals */ 151 | ZEND_BEGIN_MODULE_GLOBALS(memcache) 152 | long debug_mode; 153 | long default_port; 154 | long num_persistent; 155 | long compression_level; 156 | long allow_failover; 157 | long chunk_size; 158 | long max_failover_attempts; 159 | long hash_strategy; 160 | long hash_function; 161 | long default_timeout_ms; 162 | ZEND_END_MODULE_GLOBALS(memcache) 163 | 164 | #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3) 165 | # define MEMCACHE_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC) 166 | #else 167 | # define MEMCACHE_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp)) 168 | #endif 169 | 170 | #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 4) 171 | # define MEMCACHE_LIST_INSERT(item, list) zend_list_insert(item, list TSRMLS_CC); 172 | #else 173 | # define MEMCACHE_LIST_INSERT(item, list) zend_list_insert(item, list); 174 | #endif 175 | 176 | /* internal functions */ 177 | mmc_t *mmc_server_new(char *, int, unsigned short, int, int, int TSRMLS_DC); 178 | mmc_t *mmc_find_persistent(char *, int, int, int, int TSRMLS_DC); 179 | int mmc_server_failure(mmc_t * TSRMLS_DC); 180 | void mmc_server_deactivate(mmc_t * TSRMLS_DC); 181 | 182 | int mmc_prepare_key(zval *, char *, unsigned int * TSRMLS_DC); 183 | int mmc_prepare_key_ex(const char *, unsigned int, char *, unsigned int * TSRMLS_DC); 184 | 185 | mmc_pool_t *mmc_pool_new(TSRMLS_D); 186 | void mmc_pool_free(mmc_pool_t * TSRMLS_DC); 187 | void mmc_pool_add(mmc_pool_t *, mmc_t *, unsigned int); 188 | int mmc_pool_store(mmc_pool_t *, const char *, int, const char *, int, int, int, const char *, int TSRMLS_DC); 189 | int mmc_open(mmc_t *, int, char **, int * TSRMLS_DC); 190 | int mmc_exec_retrieval_cmd(mmc_pool_t *, const char *, int, zval **, zval * TSRMLS_DC); 191 | int mmc_delete(mmc_t *, const char *, int, int TSRMLS_DC); 192 | 193 | /* session handler struct */ 194 | #if HAVE_MEMCACHE_SESSION 195 | #include "ext/session/php_session.h" 196 | 197 | extern ps_module ps_mod_memcache; 198 | #define ps_memcache_ptr &ps_mod_memcache 199 | 200 | PS_FUNCS(memcache); 201 | #endif 202 | 203 | /* {{{ macros */ 204 | #if ZEND_DEBUG 205 | 206 | void mmc_debug(const char *format, ...); 207 | 208 | #define MMC_DEBUG(info) \ 209 | {\ 210 | mmc_debug info; \ 211 | }\ 212 | 213 | #else 214 | 215 | #define MMC_DEBUG(info) \ 216 | {\ 217 | }\ 218 | 219 | #endif 220 | /* }}} */ 221 | 222 | #ifdef ZTS 223 | #define MEMCACHE_G(v) TSRMG(memcache_globals_id, zend_memcache_globals *, v) 224 | #else 225 | #define MEMCACHE_G(v) (memcache_globals.v) 226 | #endif 227 | 228 | #ifndef ZSTR 229 | #define ZSTR 230 | #endif 231 | 232 | #endif /* PHP_MEMCACHE_H */ 233 | 234 | /* 235 | * Local variables: 236 | * tab-width: 4 237 | * c-basic-offset: 4 238 | * End: 239 | * vim600: noet sw=4 ts=4 fdm=marker 240 | * vim<600: noet sw=4 ts=4 241 | */ 242 | -------------------------------------------------------------------------------- /package2.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | memcache 7 | pecl.php.net 8 | memcached extension 9 | 10 | Memcached is a caching daemon designed especially for 11 | dynamic web applications to decrease database load by 12 | storing objects in memory. 13 | This extension allows you to work with memcached through 14 | handy OO and procedural interfaces. 15 | 16 | 17 | Antony Dovgal 18 | tony2001 19 | tony@daylessday.org 20 | no 21 | 22 | 23 | Mikael Johansson 24 | mikl 25 | mikael@synd.info 26 | yes 27 | 28 | 29 | Herman Radtke 30 | hradtke 31 | hradtke@php.net 32 | yes 33 | 34 | 2012-09-22 35 | 36 | 2.2.7 37 | 2.2.7 38 | 39 | 40 | stable 41 | stable 42 | 43 | PHP License 44 | 45 | - PHP 5.4 compatibility 46 | - Fixed return value error get_host_port_from_server(). 47 | - Fixed PECL Bug #16672 (memcache.php doesn't support unix socket) 48 | - Fixed pecl bug #19374 (memcache.php throws Notice: Undefined index: VALUE when viewing expired items) 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 4.3.11 126 | 127 | 128 | 1.4.0b1 129 | 130 | 131 | 132 | memcache 133 | 134 | 135 | 136 | 137 | 138 | 2010-10-03 139 | 140 | 2.2.6 141 | 2.2.6 142 | 143 | 144 | stable 145 | stable 146 | 147 | PHP License 148 | 149 | - Fixed pecl bug #16536 (Weight of 0 causes SegFault on memcache_add_server) 150 | - Fixed pecl bug #17130 (Uninitialized tv.tv_usec causing PHP to loop endlessly) 151 | - Fixed pecl bug #13623 (Memcache-client makes php segfault in semi-related code) 152 | 153 | 154 | 155 | 2009-02-27 156 | 157 | 2.2.5 158 | 2.2.5 159 | 160 | 161 | stable 162 | stable 163 | 164 | PHP License 165 | 166 | - Improved performance of consistent hash strategy 167 | - Fixed PECL request #13758 (Failed to extract 'connection' variable from object) 168 | 169 | 170 | 171 | 2008-09-11 172 | 173 | 2.2.4 174 | 2.2.4 175 | 176 | 177 | stable 178 | stable 179 | 180 | PHP License 181 | 182 | - Added memcached stats script from Harun Yayli (http://livebookmark.net/memcachephp) 183 | - Fixed server weight not being used in the session handler 184 | - Fixed PECL bug #13343 (compilation breaks with CodeWarrior compiler) 185 | - Fixed PECL bug #13546 (Session handler through unix socket) 186 | - Fixed PECL bug #14239 (Memcache::set() modifies value parameter) 187 | - Fixed PECL request #13725 (unnecessary allocations in mmc_consistent_add_server) 188 | - Changed behaviour when unserialize/uncompress fail to return false instead of failing the server 189 | 190 | 191 | 192 | 2008-02-05 193 | 194 | 2.2.3 195 | 2.2.3 196 | 197 | 198 | stable 199 | stable 200 | 201 | PHP License 202 | 203 | - Fixed PECL bug #12883 (Breaks UTF-8 in keys) 204 | - Fixed PECL bug #13060 (make problems, due to role="doc" instead of role="src") 205 | - Added package version to phpinfo() 206 | 207 | 208 | 209 | 2008-01-10 210 | 211 | 2.2.2 212 | 2.2.2 213 | 214 | 215 | stable 216 | stable 217 | 218 | PHP License 219 | 220 | - Fixed PECL bug 12494 (Segmentation fault when Exception thrown in the callback function) 221 | - Fixed PECL bug #12834 (segfault when getting duplicate array values on 64-bit system) 222 | - Changed behaviour of close() to actually remove all servers from pool (PECL bug #12555) 223 | - Added configure option for PEAR installer to disable session handler support 224 | 225 | 226 | 227 | 2007-11-01 228 | 229 | 2.2.1 230 | 2.2.1 231 | 232 | 233 | stable 234 | stable 235 | 236 | PHP License 237 | 238 | - Added argument to Memcache::get() that receives the flags for retrieved value(s) 239 | - Fixed PECL bug 11369 ("nested" get calls in __wakeup() functions breaks) 240 | - Fixed problem with keys being modified in-place and empty keys (PECL Bug #11236) 241 | - Fixed incompatibility with standard hash strategy in previous versions 242 | 243 | 244 | 245 | 2007-09-21 246 | 247 | 2.2.0 248 | 2.2.0 249 | 250 | 251 | stable 252 | stable 253 | 254 | PHP License 255 | 256 | - Added support for consistent hash strategy 257 | - New INI directives 258 | "memcache.hash_strategy" = {standard, consistent} 259 | "memcache.hash_function" = {crc32, fnv} 260 | - PHP6 support 261 | - Fixed PECL bug #11221 (Double free when returning cached object with __sleep) 262 | - Fixed PECL bug #10607 (Segfault on array key retrieval when array key is not IS_STRING) 263 | - Don't failover on "object to large" errors 264 | - Use $phpincludedir for finding php_session.h 265 | 266 | 267 | 268 | 2007-03-27 269 | 270 | 2.1.2 271 | 2.1.2 272 | 273 | 274 | stable 275 | stable 276 | 277 | PHP License 278 | 279 | - Added missing files to the package. 280 | 281 | 282 | 283 | 2007-03-27 284 | 285 | 2.1.1 286 | 2.1.1 287 | 288 | 289 | stable 290 | stable 291 | 292 | PHP License 293 | 294 | - Added experimental session storage support. You can use memcached as session storage. 295 | - Fixed PECL bug #9486 (empty keys should not be allowed in memcache_set/add()) 296 | - Fixed PECL bug #9854 (get() changes the datatype of variable of given as key) 297 | 298 | 299 | 300 | 2006-10-09 301 | 302 | 2.1.0 303 | 2.1.0 304 | 305 | 306 | stable 307 | stable 308 | 309 | PHP License 310 | 311 | - Servers may be flagged up/down and the user may specify a error callback 312 | - Individual server params and up/down status may be changed at runtime 313 | - New methods: setServerParams(), getServerStatus() 314 | - Statistics methods support fetching other kinds of stats (slabs, items, cachedump, ...) 315 | - Fixed PECL bugs #7631, #8117 (erroneous line feeds in config.m4) 316 | - Added memcache.max_failover_attempts ini directive, which can be used to configure max number of 317 | servers to try when setting and getting data. 318 | 319 | 320 | 321 | 322 | 2.0.4 323 | 2.0.4 324 | 325 | 326 | stable 327 | stable 328 | 329 | 2006-05-16 330 | PHP License 331 | - Redefined retry_interval as long to fix no-automatic-reconnect behaviour 332 | - Fixed PECL bugs #7635, #7637 (OnUpdateInt: referenced symbol not found) 333 | 334 | 335 | 336 | 337 | 2.0.3 338 | 2.0.3 339 | 340 | 341 | stable 342 | stable 343 | 344 | 2006-05-15 345 | PHP License 346 | - Display ini entries in phpinfo() output 347 | - Fixed Zend2 compat 348 | 349 | 350 | 351 | 352 | 2.0.2 353 | 2.0.2 354 | 355 | 356 | stable 357 | stable 358 | 359 | 2006-05-14 360 | PHP License 361 | 362 | - Added "memcache.default_port" ini directive (default 11211) 363 | - Added "memcache.allow_failover" ini directive (default On) 364 | - Added "memcache.chunk_size" ini directive (default 8192 bytes) 365 | - Setting retry_interval parameter to -1 disables automatic reconnect 366 | - Fixed PECL bug #7331 (NULL pointer freeing causes memcache to segfault) 367 | 368 | 369 | 370 | 371 | 2.0.1 372 | 2.0.1 373 | 374 | 375 | stable 376 | stable 377 | 378 | 2006-02-01 379 | PHP License 380 | 381 | - Fixed PECL bug #6595 (segfault in addServer()) 382 | - Fixed PECL bug #6512 (buffer overrun in getVersion()) 383 | - Fixed PECL bug #6460 (lacking include of php_smart_str_public.h) 384 | - Fixed PECL bug #6370 (incorrect failover on out-of-memory server errors) 385 | - Improved zlib detection 386 | 387 | 388 | 389 | 390 | 2.0.0 391 | 2.0.0 392 | 393 | 394 | stable 395 | stable 396 | 397 | 2005-12-21 398 | PHP License 399 | 400 | - Multiple servers with loadbalancing and failover 401 | - Automatic compress threshold setting 402 | - New methods: addServer(), getExtendedStats(), setCompressThreshold() 403 | 404 | 405 | 406 | 407 | 1.6 408 | 1.6 409 | 410 | 411 | stable 412 | stable 413 | 414 | 2005-10-12 415 | PHP License 416 | 417 | - Fixed minor leak appeared when connect fails. 418 | - Fixed PECL bug #5626 (segfault when trying to use previously closed connection). 419 | 420 | 421 | 422 | 423 | 1.5 424 | 1.5 425 | 426 | 427 | stable 428 | stable 429 | 430 | 2005-08-05 431 | PHP License 432 | 433 | 1) Fixed minor leak. 434 | 2) Class Memcache made inheritable. 435 | 436 | 437 | 438 | 439 | 1.4 440 | 1.4 441 | 442 | 443 | stable 444 | stable 445 | 446 | 2004-12-02 447 | PHP License 448 | 449 | 1) Added multi get support (i.e. you're now able to get multiple items with one get() call, 450 | just pass array of keys to get() and it will return associative array of found items). 451 | 452 | 453 | 454 | 455 | 1.3 456 | 1.3 457 | 458 | 459 | stable 460 | stable 461 | 462 | 2004-08-29 463 | PHP License 464 | 465 | 1) Fixed potential problem with empty datasets (yet another patch from Andrey Nigmatulin [anight at monamour dot ru]). 466 | 2) Fixed bug #2167 (thanks to [pbnadeau at gmail dot com] for noticing, testing and patching). 467 | 468 | 469 | 470 | 471 | 1.2 472 | 1.2 473 | 474 | 475 | stable 476 | stable 477 | 478 | 2004-07-20 479 | PHP License 480 | 481 | 1) Fixed typo, preventing to use set() with flags and expire in the same time (thanks to Troy Hakala [troy at recipezaar dot com] for noticing). 482 | 2) Added possibility to store objects and arrays compressed. 483 | 3) Hopefully fixed all possible problems with persistent connections (thanks to [anight at monamour dot ru]). 484 | 4) Some uncritical impovements. 485 | 486 | 487 | 488 | 489 | 1.1 490 | 1.1 491 | 492 | 493 | stable 494 | stable 495 | 496 | 2004-06-08 497 | PHP License 498 | 499 | 1) Fixed couple of possible segfaults and one error (many thanks to Anight). 500 | 2) Minor improvements. 501 | 502 | 503 | 504 | 505 | 1.0 506 | 1.0 507 | 508 | 509 | beta 510 | beta 511 | 512 | 2004-05-21 513 | PHP License 514 | 515 | 1) Ifdef'ed debug routines, so they are available only in debug mode. 516 | This should add more speed to extension. 517 | 2) Minor code decorations. 518 | 519 | 520 | 521 | 522 | 0.4 523 | 0.4 524 | 525 | 526 | beta 527 | beta 528 | 529 | 2004-xx-xx 530 | PHP License 531 | 532 | 1) Added on-the-fly data (de)compression support. 533 | 2) Added procedural API. 534 | 3) Extension was fairly refactored and accelerated. 535 | 536 | 537 | 538 | 539 | 0.2 540 | 0.2 541 | 542 | 543 | beta 544 | beta 545 | 546 | 2004-02-26 547 | PHP License 548 | 549 | New methods: getStats(), increment(), decrement(). 550 | Extension should be rather stable. 551 | 552 | 553 | 554 | 555 | 0.1 556 | 0.1 557 | 558 | 559 | alpha 560 | alpha 561 | 562 | 2004-02-08 563 | PHP License 564 | Initial release in PECL 565 | 566 | 567 | 568 | -------------------------------------------------------------------------------- /memcache.php: -------------------------------------------------------------------------------- 1 | | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | $VERSION='$Id$'; 21 | 22 | define('ADMIN_USERNAME','memcache'); // Admin Username 23 | define('ADMIN_PASSWORD','password'); // Admin Password 24 | define('DATE_FORMAT','Y/m/d H:i:s'); 25 | define('GRAPH_SIZE',200); 26 | define('MAX_ITEM_DUMP',50); 27 | 28 | $MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array 29 | $MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array 30 | 31 | 32 | ////////// END OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////// 33 | 34 | ///////////////// Password protect //////////////////////////////////////////////////////////////// 35 | if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || 36 | $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { 37 | Header("WWW-Authenticate: Basic realm=\"Memcache Login\""); 38 | Header("HTTP/1.0 401 Unauthorized"); 39 | 40 | echo << 42 |

Rejected!

43 | Wrong Username or Password! 44 | 45 | EOB; 46 | exit; 47 | } 48 | 49 | ///////////MEMCACHE FUNCTIONS ///////////////////////////////////////////////////////////////////// 50 | 51 | function get_host_port_from_server($server){ 52 | $values = explode(':', $server); 53 | if (($values[0] == 'unix') && (!is_numeric( $values[1]))) { 54 | return array($server, 0); 55 | } 56 | else { 57 | return $values; 58 | } 59 | } 60 | 61 | function sendMemcacheCommands($command){ 62 | global $MEMCACHE_SERVERS; 63 | $result = array(); 64 | 65 | foreach($MEMCACHE_SERVERS as $server){ 66 | $strs = get_host_port_from_server($server); 67 | $host = $strs[0]; 68 | $port = $strs[1]; 69 | $result[$server] = sendMemcacheCommand($host,$port,$command); 70 | } 71 | return $result; 72 | } 73 | function sendMemcacheCommand($server,$port,$command){ 74 | 75 | $s = @fsockopen($server,$port); 76 | if (!$s){ 77 | die("Cant connect to:".$server.':'.$port); 78 | } 79 | 80 | fwrite($s, $command."\r\n"); 81 | 82 | $buf=''; 83 | while ((!feof($s))) { 84 | $buf .= fgets($s, 256); 85 | if (strpos($buf,"END\r\n")!==false){ // stat says end 86 | break; 87 | } 88 | if (strpos($buf,"DELETED\r\n")!==false || strpos($buf,"NOT_FOUND\r\n")!==false){ // delete says these 89 | break; 90 | } 91 | if (strpos($buf,"OK\r\n")!==false){ // flush_all says ok 92 | break; 93 | } 94 | } 95 | fclose($s); 96 | return parseMemcacheResults($buf); 97 | } 98 | function parseMemcacheResults($str){ 99 | 100 | $res = array(); 101 | $lines = explode("\r\n",$str); 102 | $cnt = count($lines); 103 | for($i=0; $i< $cnt; $i++){ 104 | $line = $lines[$i]; 105 | $l = explode(' ',$line,3); 106 | if (count($l)==3){ 107 | $res[$l[0]][$l[1]]=$l[2]; 108 | if ($l[0]=='VALUE'){ // next line is the value 109 | $res[$l[0]][$l[1]] = array(); 110 | list ($flag,$size)=explode(' ',$l[2]); 111 | $res[$l[0]][$l[1]]['stat']=array('flag'=>$flag,'size'=>$size); 112 | $res[$l[0]][$l[1]]['value']=$lines[++$i]; 113 | } 114 | }elseif($line=='DELETED' || $line=='NOT_FOUND' || $line=='OK'){ 115 | return $line; 116 | } 117 | } 118 | return $res; 119 | 120 | } 121 | 122 | function dumpCacheSlab($server,$slabId,$limit){ 123 | list($host,$port) = get_host_port_from_server($server); 124 | $resp = sendMemcacheCommand($host,$port,'stats cachedump '.$slabId.' '.$limit); 125 | 126 | return $resp; 127 | 128 | } 129 | 130 | function flushServer($server){ 131 | list($host,$port) = get_host_port_from_server($server); 132 | $resp = sendMemcacheCommand($host,$port,'flush_all'); 133 | return $resp; 134 | } 135 | function getCacheItems(){ 136 | $items = sendMemcacheCommands('stats items'); 137 | $serverItems = array(); 138 | $totalItems = array(); 139 | foreach ($items as $server=>$itemlist){ 140 | $serverItems[$server] = array(); 141 | $totalItems[$server]=0; 142 | if (!isset($itemlist['STAT'])){ 143 | continue; 144 | } 145 | 146 | $iteminfo = $itemlist['STAT']; 147 | 148 | foreach($iteminfo as $keyinfo=>$value){ 149 | if (preg_match('/items\:(\d+?)\:(.+?)$/',$keyinfo,$matches)){ 150 | $serverItems[$server][$matches[1]][$matches[2]] = $value; 151 | if ($matches[2]=='number'){ 152 | $totalItems[$server] +=$value; 153 | } 154 | } 155 | } 156 | } 157 | return array('items'=>$serverItems,'counts'=>$totalItems); 158 | } 159 | function getMemcacheStats($total=true){ 160 | $resp = sendMemcacheCommands('stats'); 161 | if ($total){ 162 | $res = array(); 163 | foreach($resp as $server=>$r){ 164 | foreach($r['STAT'] as $key=>$row){ 165 | if (!isset($res[$key])){ 166 | $res[$key]=null; 167 | } 168 | switch ($key){ 169 | case 'pid': 170 | $res['pid'][$server]=$row; 171 | break; 172 | case 'uptime': 173 | $res['uptime'][$server]=$row; 174 | break; 175 | case 'time': 176 | $res['time'][$server]=$row; 177 | break; 178 | case 'version': 179 | $res['version'][$server]=$row; 180 | break; 181 | case 'pointer_size': 182 | $res['pointer_size'][$server]=$row; 183 | break; 184 | case 'rusage_user': 185 | $res['rusage_user'][$server]=$row; 186 | break; 187 | case 'rusage_system': 188 | $res['rusage_system'][$server]=$row; 189 | break; 190 | case 'curr_items': 191 | $res['curr_items']+=$row; 192 | break; 193 | case 'total_items': 194 | $res['total_items']+=$row; 195 | break; 196 | case 'bytes': 197 | $res['bytes']+=$row; 198 | break; 199 | case 'curr_connections': 200 | $res['curr_connections']+=$row; 201 | break; 202 | case 'total_connections': 203 | $res['total_connections']+=$row; 204 | break; 205 | case 'connection_structures': 206 | $res['connection_structures']+=$row; 207 | break; 208 | case 'cmd_get': 209 | $res['cmd_get']+=$row; 210 | break; 211 | case 'cmd_set': 212 | $res['cmd_set']+=$row; 213 | break; 214 | case 'get_hits': 215 | $res['get_hits']+=$row; 216 | break; 217 | case 'get_misses': 218 | $res['get_misses']+=$row; 219 | break; 220 | case 'evictions': 221 | $res['evictions']+=$row; 222 | break; 223 | case 'bytes_read': 224 | $res['bytes_read']+=$row; 225 | break; 226 | case 'bytes_written': 227 | $res['bytes_written']+=$row; 228 | break; 229 | case 'limit_maxbytes': 230 | $res['limit_maxbytes']+=$row; 231 | break; 232 | case 'threads': 233 | $res['rusage_system'][$server]=$row; 234 | break; 235 | } 236 | } 237 | } 238 | return $res; 239 | } 240 | return $resp; 241 | } 242 | 243 | ////////////////////////////////////////////////////// 244 | 245 | // 246 | // don't cache this page 247 | // 248 | header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 249 | header("Cache-Control: post-check=0, pre-check=0", false); 250 | header("Pragma: no-cache"); // HTTP/1.0 251 | 252 | function duration($ts) { 253 | global $time; 254 | $years = (int)((($time - $ts)/(7*86400))/52.177457); 255 | $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); 256 | $weeks = (int)(($rem)/(7*86400)); 257 | $days = (int)(($rem)/86400) - $weeks*7; 258 | $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; 259 | $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; 260 | $str = ''; 261 | if($years==1) $str .= "$years year, "; 262 | if($years>1) $str .= "$years years, "; 263 | if($weeks==1) $str .= "$weeks week, "; 264 | if($weeks>1) $str .= "$weeks weeks, "; 265 | if($days==1) $str .= "$days day,"; 266 | if($days>1) $str .= "$days days,"; 267 | if($hours == 1) $str .= " $hours hour and"; 268 | if($hours>1) $str .= " $hours hours and"; 269 | if($mins == 1) $str .= " 1 minute"; 270 | else $str .= " $mins minutes"; 271 | return $str; 272 | } 273 | 274 | // create graphics 275 | // 276 | function graphics_avail() { 277 | return extension_loaded('gd'); 278 | } 279 | 280 | function bsize($s) { 281 | foreach (array('','K','M','G') as $i => $k) { 282 | if ($s < 1024) break; 283 | $s/=1024; 284 | } 285 | return sprintf("%5.1f %sBytes",$s,$k); 286 | } 287 | 288 | // create menu entry 289 | function menu_entry($ob,$title) { 290 | global $PHP_SELF; 291 | if ($ob==$_GET['op']){ 292 | return "
  • $title
  • "; 293 | } 294 | return "
  • $title
  • "; 295 | } 296 | 297 | function getHeader(){ 298 | $header = << 300 | 301 | MEMCACHE INFO 302 | 480 | 481 | 482 |
    483 |

    484 | 485 | memcache.php by Harun Yayli 486 |

    487 |
    488 |
    489 |
    490 | EOB; 491 | 492 | return $header; 493 | } 494 | function getFooter(){ 495 | global $VERSION; 496 | $footer = '
    497 | 498 | '; 499 | 500 | return $footer; 501 | 502 | } 503 | function getMenu(){ 504 | global $PHP_SELF; 505 | echo "