Skip to content
Snippets Groups Projects
Commit c05fd1af authored by Alberto Paderno's avatar Alberto Paderno
Browse files

Issue #2846622: Change the module to require only the APCu extension

parent 3e2efcfb
No related branches found
No related tags found
1 merge request!17Issue #2846622: Change the module to require only the APCu extension
Pipeline #230248 passed
......@@ -9,7 +9,7 @@
* Implements hook_drush_exit().
*/
function apc_drush_exit() {
if (class_exists('DrupalAPCCache')) {
DrupalAPCCache::remoteFlush();
if (class_exists('DrupalApcCache')) {
DrupalApcCache::remoteFlush();
}
}
......@@ -11,60 +11,57 @@
* Implements hook_requirements().
*/
function apc_requirements($phase) {
$requirements = array();
// Ensure translations don't break at install time.
$t = get_t();
// Test APC.
$apc_enabled = (function_exists('apc_cache_info') && ($cache = @apc_cache_info('user', TRUE)));
$requirements['apc'] = array(
'title' => $t('APCu extension'),
);
if (extension_loaded('apcu')) {
$version = phpversion('apcu');
$name = $t('APCu');
$description = $t('APC needs APCu version >=4.0.2.');
$apcu_version = phpversion('apcu');
$required_version_installed = version_compare($apcu_version, '5.0.0') >= 0;
$meets_version = version_compare($version, '4.0.2') >= 0;
if (!$required_version_installed) {
$requirements['apc']['description'] = $t(
'The Alternative PHP Cache module needs the APCu extension version 5.0.0 or higher; version %apcu_version is currently installed.',
array('%apcu_version' => $apcu_version)
);
$requirements['apc']['severity'] = REQUIREMENT_ERROR;
// APCu reports cache info with keys that differ from APC.
// This has been fixed upstream, but has not made it into a release.
// @see https://github.com/krakjoe/apcu/issues/41
// @see https://github.com/krakjoe/apcu/pull/42
$cache['num_entries'] = isset($cache['num_entries']) ? $cache['num_entries'] : $cache['nentries'];
$cache['start_time'] = isset($cache['start_time']) ? $cache['start_time'] : $cache['stime'];
return $requirements;
}
}
else {
$version = phpversion('apc');
$name = $t('APC');
$description = $t('APC needs version >=3.1.1.');
if (apcu_enabled() && $phase == 'runtime') {
$cache = apcu_cache_info(TRUE);
$num_entries = isset($cache['num_entries']) ? $cache['num_entries'] : 0;
$start_time = isset($cache['start_time']) ? $cache['start_time'] : time();
$mem_size = isset($cache['mem_size']) ? $cache['mem_size'] : 0;
$meets_version = version_compare($version, '3.1.1') >= 0;
}
$requirements['apc'] = array(
'title' => $name,
'value' => $apc_enabled ? ($meets_version ? $version : $description) : $t('Not available'),
'severity' => $apc_enabled && $meets_version ? ($cache['num_entries'] ? REQUIREMENT_OK : REQUIREMENT_WARNING) : REQUIREMENT_ERROR,
);
if ($apc_enabled) {
$requirements['apc']['description'] = $t('!name has been running for !duration. Currently caching !num_entries entries (!memory_size).',
array(
'!name' => $name,
'!duration' => format_interval(time() - $cache['start_time']),
'!num_entries' => $cache['num_entries'],
'!memory_size' => format_size($cache['mem_size']),
)
);
$requirements['apc']['description'] = $t(
'The APCu extension has been running for !duration. It contains !num_entries entries and uses !memory_size of memory.',
array(
'!duration' => format_interval(time() - $start_time),
'!num_entries' => $num_entries,
'!memory_size' => format_size($mem_size),
)
);
$requirements['apc']['severity'] = REQUIREMENT_INFO;
}
elseif (!apcu_enabled()) {
$severity = drupal_is_cli() ? REQUIREMENT_INFO : REQUIREMENT_ERROR;
$requirements['apc']['description'] = $t(
'The Alternative PHP Cache module needs the APCu extension to be enabled.'
);
$requirements['apc']['severity'] = $severity;
}
}
else {
$requirements['apc']['description'] = $t('The APC module needs the <a href="!apc_link">APC</a> or the <a href="!apcu_link">APCu</a> extension.',
array(
'!apc_link' => 'http://www.php.net/apc',
'!apcu_link' => 'https://github.com/krakjoe/apcu',
)
$requirements['apc']['description'] = $t(
'The Alternative PHP Cache module needs the <a href="!apcu_link">APCu</a> extension.',
array('!apcu_link' => 'https://www.php.net/apcu')
);
$requirements['apc']['severity'] = REQUIREMENT_ERROR;
}
return $requirements;
......
......@@ -2,52 +2,9 @@
/**
* @file
* Functions and classes for the APC cache backend.
* Contains DrupalApcCache.
*/
/**
* Dummy functions to prevent errors if APC is not installed.
*/
if (!function_exists('apc_fetch')) {
/**
* Replacement for apc_fetch() which always return FALSE.
*
* @param string $key
* The key used to store the value.
* @param bool &$success
* A variable set to FALSE.
*
* @return false
* The value has not been fetched.
*/
function apc_fetch($key, &$success = NULL) {
if ($success) {
$success = FALSE;
}
return FALSE;
}
/**
* Replacement for apc_store() which always return FALSE.
*
* @param string $key
* The key used to store the value.
* @param mixed $var
* The value to store.
* @param int $ttl
* The time to live in seconds.
*
* @return false
* The value has not been stored.
*/
function apc_store($key, $var, $ttl = 0) {
return FALSE;
}
}
/**
* Statistics about the APC cache.
*/
......@@ -59,7 +16,7 @@ function apc_store($key, $var, $ttl = 0) {
* This is a Drupal cache implementation which uses the APC extension to store
* cached data.
*/
class DrupalAPCCache implements DrupalCacheInterface {
class DrupalApcCache implements DrupalCacheInterface {
/**
* The cache bin.
......@@ -196,7 +153,8 @@ public function get($cid) {
$GLOBALS['_apc_statistics'][] = array('get', $this->bin, array($cid));
// Fetch the data.
$cache = apc_fetch($this->key($cid));
$cache = apcu_fetch($this->key($cid));
return $this->prepareItem($cache);
}
......@@ -208,7 +166,7 @@ public function get($cid) {
* @param object $cache
* An item loaded from cache_get() or cache_get_multiple().
*
* @return mixed
* @return false|object
* The item with unserialized data, or FALSE if there is no valid item to
* load.
*/
......@@ -236,31 +194,23 @@ protected function prepareItem($cache) {
* {@inheritdoc}
*/
public function getMultiple(&$cids) {
$cache = array();
$keys = array();
// Add a get to our statistics.
$GLOBALS['_apc_statistics'][] = array('get', $this->bin, $cids);
if (!$cids) {
return $keys;
return $cache;
}
// We need to search the cache with the proper keys and be able to get the
// original $cid back.
foreach ($cids as $cid) {
$keys[$this->key($cid)] = $cid;
}
$data = apcu_fetch($this->key($cid), $success);
$fetch = apc_fetch(array_keys($keys));
$cache = array();
if (!empty($fetch)) {
foreach ($fetch as $key => $data) {
$cache[$keys[$key]] = $this->prepareItem($data);
if ($success) {
$cache[$cid] = $this->prepareItem($data);
}
}
unset($fetch);
// Add a get to our statistics.
$GLOBALS['_apc_statistics'][] = array('get', $this->bin, $cids);
$cids = array_diff($cids, array_keys($cache));
return $cache;
}
......@@ -279,28 +229,28 @@ public function set($cid, $data, $expire = CACHE_PERMANENT) {
$cache->expire = $expire;
$cache->data = $data;
// APCu will serialize any structure we give itself.
// Cache values stored in APCu do not need to be serialized, as APCu does
// that.
$cache->serialized = 0;
// What kind of expiration is being used.
switch ($expire) {
case CACHE_PERMANENT:
$set_result = apc_store($this->key($cid), $cache);
$ttl = 0;
break;
case CACHE_TEMPORARY:
if (variable_get('cache_lifetime', 0) > 0) {
$set_result = apc_store($this->key($cid), $cache, variable_get('cache_lifetime', 0));
}
else {
$set_result = apc_store($this->key($cid), $cache);
}
// For apcu_store(), using 0 as TTL means the stored data will never
// expire. The minimum lifetime is one second.
$cache_lifetime = variable_get('cache_lifetime', 0);
$ttl = $cache_lifetime > 0 ? $cache_lifetime : 1;
break;
default:
$set_result = apc_store($this->key($cid), $cache, $expire - time());
$ttl = $expire - time();
break;
}
apcu_store($this->key($cid), $cache, $ttl);
}
/**
......@@ -310,13 +260,10 @@ public function set($cid, $data, $expire = CACHE_PERMANENT) {
* The prefix for the cache IDs to delete.
*/
protected function deletePrefix($prefix) {
if (class_exists('APCIterator')) {
$escapedKey = preg_quote($this->binKey() . $prefix, '/');
$iterator = new APCIterator('user', '/^' . $escapedKey . '/', APC_ITER_KEY);
foreach ($iterator as $key => $data) {
apc_delete($key);
}
if (class_exists('APCUIterator')) {
$escaped_key = preg_quote($this->binKey() . $prefix, '/');
$iterator = new APCUIterator("/^$escaped_key/", APC_ITER_KEY);
apcu_delete($iterator);
}
}
......@@ -355,11 +302,11 @@ public function clear($cid = NULL, $wildcard = FALSE) {
}
elseif (is_array($cid)) {
foreach ($cid as $entry) {
apc_delete($this->key($entry));
apcu_delete($this->key($entry));
}
}
else {
apc_delete($this->key($cid));
apcu_delete($this->key($cid));
}
}
}
......@@ -368,11 +315,13 @@ public function clear($cid = NULL, $wildcard = FALSE) {
* {@inheritdoc}
*/
public function isEmpty() {
if (class_exists('APCIterator')) {
$escapedKey = preg_quote($this->binKey(), '/');
$iterator = new APCIterator('user', '/^' . $escapedKey . '/', APC_ITER_KEY);
return 0 === $iterator->getTotalCount();
if (class_exists('APCUIterator')) {
$escaped_key = preg_quote($this->binKey(), '/');
$iterator = new APCUIterator('/^' . $escaped_key . '/', APC_ITER_KEY);
return $iterator->getTotalCount() === 0;
}
return TRUE;
}
......@@ -384,7 +333,7 @@ public static function remoteFlush() {
if (!module_exists('apc')) {
drush_log(
dt('You need to enable the APC module for remote cache clearing to work. Run drush pm-enable apc.'),
dt('You need to enable the Alternative PHP Cache module for remote cache clearing to work. Run drush pm-enable apc.'),
'error'
);
return;
......
......@@ -38,7 +38,7 @@ class ApcCacheTestCase extends DrupalWebTestCase {
parent::setUp(func_get_args());
variable_set("cache_flush_{$this->defaultBin}", 0);
variable_set("cache_class_{$this->defaultBin}", 'DrupalAPCCache');
variable_set("cache_class_{$this->defaultBin}", 'DrupalApcCache');
}
/**
......@@ -281,7 +281,7 @@ class ApcCacheClearCase extends ApcCacheTestCase {
/**
* {@inheritdoc}
*/
protected protected function setUp() {
protected function setUp() {
$this->defaultValue = $this->randomName(10);
parent::setUp();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment