MDL-56675 cachestore_memcached: Disable store if not purgeable

If the store is shared and the getAllKeys function is broken due to an
incompatability between libmemcached and memcached >= 1.4.23, then it is
not possible to purge the cache, and we cannot support the plugin.

This patch adjusts the isready check to additionally check if the
combination of libmemcached and memcached is affected by this issue.
This commit is contained in:
Andrew Nicols 2016-11-02 09:41:14 +08:00
parent 06e3b6d8ba
commit 77f1729eec
2 changed files with 54 additions and 2 deletions

View File

@ -229,8 +229,56 @@ class cachestore_memcached extends cache_store implements cache_is_configurable
$version = phpversion('memcached');
$this->candeletemulti = ($version && version_compare($version, self::REQUIRED_VERSION, '>='));
// Test the connection to the main connection.
$this->isready = @$this->connection->set("ping", 'ping', 1);
$this->isready = $this->is_connection_ready();
}
/**
* Confirm whether the connection is ready and usable.
*
* @return boolean
*/
public function is_connection_ready() {
if (!@$this->connection->set("ping", 'ping', 1)) {
// Test the connection to the server.
return false;
}
if ($this->isshared) {
// There is a bug in libmemcached which means that it is not possible to purge the cache in a shared cache
// configuration.
// This issue currently affects:
// - memcached 1.4.23+ with php-memcached <= 2.2.0
// The following combinations are not affected:
// - memcached <= 1.4.22 with any version of php-memcached
// - any version of memcached with php-memcached >= 3.0.1
// This check is cheapest as it does not involve connecting to the server at all.
$safecombination = false;
$extension = new ReflectionExtension('memcached');
if ((version_compare($extension->getVersion(), '3.0.1') >= 0)) {
// This is php-memcached version >= 3.0.1 which is a safe combination.
$safecombination = true;
}
if (!$safecombination && (version_compare($this->connection->getVersion(), '1.4.22') <= 0)) {
// This is memcached server version <= 1.4.22 which is a safe combination.
$safecombination = true;
}
if (!$safecombination) {
// This is memcached 1.4.23+ and php-memcached < 3.0.1.
// The issue may have been resolved in a subsequent update to any of the three libraries.
// The only way to safely determine if the combination is safe is to call getAllKeys.
// A safe combination will return an array, whilst an affected combination will return false.
// This is the most expensive check.
if (!is_array($this->connection->getAllKeys())) {
return false;
}
}
}
return true;
}
/**

View File

@ -288,6 +288,10 @@ class cachestore_memcached_test extends cachestore_tests {
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
$cachestore = $this->create_test_cache_with_config($definition, array('isshared' => true));
if (!$cachestore->is_connection_ready()) {
$this->markTestSkipped('Could not test cachestore_memcached. Connection is not ready.');
}
$connection = new Memcached(crc32(__METHOD__));
$connection->addServers($this->get_servers(TEST_CACHESTORE_MEMCACHED_TESTSERVERS));
$connection->setOptions(array(