View source
<?php
define('MEMCACHE_PECL_RECOMMENDED', '3.0.6');
define('MEMCACHE_PECL_PHP7_RECOMMENDED', '4.0.5');
define('MEMCACHED_PECL_RECOMMENDED', '2.0.1');
define('MEMCACHED_ASCII_AUTH_MINIMUM', '1.5.15');
define('MEMCACHED_ASCII_AUTH_RECOMMENDED', '1.6.4');
function memcache_enable() {
$error = FALSE;
$warning = FALSE;
$severity = 'status';
$memcache = extension_loaded('memcache');
$memcached = extension_loaded('memcached');
if (!$memcache && !$memcached) {
$error = TRUE;
}
if (!function_exists('dmemcache_object')) {
$error = TRUE;
}
else {
if (!_memcache_pecl_version_valid()) {
$warning = TRUE;
}
if (_dmemcache_use_ascii_auth()) {
$version = _memcached_ascii_auth_version_valid(MEMCACHED_ASCII_AUTH_MINIMUM);
if ($version !== TRUE && $version !== FALSE) {
$error = TRUE;
}
else {
$version = _memcached_ascii_auth_version_valid(MEMCACHED_ASCII_AUTH_RECOMMENDED);
if ($version !== TRUE && $version !== FALSE) {
$warning = TRUE;
}
}
}
$memcache_servers = variable_get('memcache_servers', array(
'127.0.0.1:11211' => 'default',
));
foreach ($memcache_servers as $server => $bin) {
if ($cluster = dmemcache_object_cluster($bin)) {
$memcache = dmemcache_instance($cluster['cluster']);
if (dmemcache_connect($memcache, $server, $cluster['weight']) === FALSE) {
$error = TRUE;
}
else {
if (!variable_get('memcache_persistent', TRUE)) {
dmemcache_close($memcache);
}
}
}
}
}
if ($error) {
$severity = 'error';
}
elseif ($warning) {
$severity = 'warning';
}
if ($error || $warning) {
drupal_set_message(t('There are problems with your Memcache configuration. Please review %readme and visit the Drupal admin !status page for more information.', array(
'%readme' => 'README.txt',
'!status' => l(t('status report'), 'admin/reports/status'),
)), $severity);
}
}
function memcache_requirements($phase) {
$requirements = array();
$t = get_t();
$memcache = extension_loaded('memcache');
$memcached = extension_loaded('memcached');
if ($phase == 'install' || $phase == 'runtime') {
$requirements['memcache_extension']['title'] = $t('Memcache');
if (!$memcache && !$memcached) {
$requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
$requirements['memcache_extension']['value'] = $t('Required PHP extension not found. Install the <a href="http://php.net/manual/en/book.memcache.php">memcache</a> (recommended) or <a href="http://php.net/manual/en/book.memcached.php">memcached</a> extension.');
}
else {
$requirements['memcache_extension']['value'] = $t('PHP %extension Extension', array(
'%extension' => $memcache ? $t('Memcache') : $t('Memcached'),
));
}
}
if ($phase == 'runtime') {
$errors = array();
$warnings = array();
if (!$memcache && !$memcached) {
$errors[] = $t('Required PHP extension not found. Install the <a href="http://php.net/manual/en/book.memcache.php">memcache</a> (recommended) or <a href="http://php.net/manual/en/book.memcached.php">memcached</a> extension.');
}
if (!function_exists('dmemcache_set')) {
$errors[] = $t('Failed to load required file %dmemcache.', array(
'%dmemcache' => drupal_get_path('module', 'memcache') . '/' . 'dmemcache.inc',
));
$requirements['memcache_extension']['value'] = $t('Unknown');
}
else {
$extension = dmemcache_extension();
if ($extension == 'Memcache') {
$version = phpversion('memcache');
if (version_compare(phpversion(), '7', '>=')) {
$recommended = MEMCACHE_PECL_PHP7_RECOMMENDED;
}
else {
$recommended = MEMCACHE_PECL_RECOMMENDED;
}
}
elseif ($extension == 'Memcached') {
$version = phpversion('memcached');
$recommended = MEMCACHED_PECL_RECOMMENDED;
}
if (!$version) {
$version = $t('Unknown');
}
$requirements['memcache_extension']['value'] = $version . _memcache_statistics_link();
if (!_memcache_pecl_version_valid()) {
$warnings[] = $t('PECL !extension version %version is unsupported. Please update to %recommended or newer.', array(
'!extension' => $extension,
'%version' => $version,
'%recommended' => $recommended,
));
}
if (_dmemcache_use_ascii_auth()) {
$version = _memcached_ascii_auth_version_valid(MEMCACHED_ASCII_AUTH_MINIMUM);
if ($version !== TRUE && $version !== FALSE) {
$errors[] = $t('ASCII protocol authentication is enabled but requires memcached v%minimum or greater. One or more memcached instances detected running memcache v%version.' . _memcache_statistics_link(), array(
'%version' => $version,
'%minimum' => MEMCACHED_ASCII_AUTH_MINIMUM,
));
}
else {
$version = _memcached_ascii_auth_version_valid(MEMCACHED_ASCII_AUTH_RECOMMENDED);
if ($version !== TRUE && $version !== FALSE) {
$warnings[] = $t('Memcached v%recommended is recommended when using ASCII protocol authentication, to avoid a CPU race. One or more memcached instances detected are running memcache v%version.' . _memcache_statistics_link(), array(
'%version' => $version,
'%recommended' => MEMCACHED_ASCII_AUTH_RECOMMENDED,
));
}
}
$memcache_bins = variable_get('memcache_bins', array(
'cache' => 'default',
));
foreach ($memcache_bins as $bin => $_) {
if ($mc = dmemcache_object($bin)) {
$ascii_auth = _check_ascii_auth($mc);
if ($ascii_auth !== TRUE) {
$s = $ascii_auth[0];
$message = $ascii_auth[1];
$errors[] = $t('ASCII protocol authentication failed: %message (%host:%port).' . _memcache_statistics_link(), array(
'%host' => $s['host'],
'%port' => $s['port'],
'%message' => $message,
));
}
}
}
}
$memcache_servers = variable_get('memcache_servers', array(
'127.0.0.1:11211' => 'default',
));
foreach ($memcache_servers as $server => $bin) {
if ($cluster = dmemcache_object_cluster($bin)) {
$memcache = dmemcache_instance($cluster['cluster']);
if (dmemcache_connect($memcache, $server, $cluster['weight']) === FALSE) {
$errors[] = $t('Failed to connect to memcached server instance at %server.', array(
'%server' => $server,
));
}
else {
if (!variable_get('memcache_persistent', TRUE)) {
dmemcache_close($memcache);
}
}
}
}
try {
$cid = 'memcache_requirements_test';
$value = 'OK';
cache_set($cid, $value);
$data = cache_get($cid);
if (!isset($data->data) || $data->data !== $value) {
$errors[] = $t('Failed to store to then retrieve data from memcache.');
}
else {
cache_clear_all($cid, 'cache');
}
} catch (Exception $e) {
$errors[] = $t('Unexpected failure when testing memcache configuration.');
}
if (variable_get('memcache_stampede_protection', FALSE) && strpos(variable_get('lock_inc', 'includes/lock.inc'), 'includes/lock.inc') !== FALSE) {
$warnings[] = $t('Drupal\'s core lock implementation (%core) is not supported by memcache stampede protection. Enable the memcache lock implementation (%memcache) or disable memcache stampede protection.', array(
'%core' => 'includes/lock.inc',
'%memcache' => drupal_get_path('module', 'memcache') . "/memcache-lock.inc",
));
}
}
if (!empty($errors)) {
$errors = array_merge($errors, $warnings);
unset($warnings);
$requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
$requirements['memcache_extension']['description'] = $t('There is a problem with your memcache configuration, check the Drupal logs for additional errors. Please review %readme for help resolving the following !issue: !errors', array(
'%readme' => drupal_get_path('module', 'memcache') . '/' . 'README.txt',
'!issue' => format_plural(count($errors), 'issue', 'issues'),
'!errors' => '<ul><li>' . implode('<li>', $errors),
));
}
elseif (!empty($warnings)) {
$requirements['memcache_extension']['severity'] = REQUIREMENT_WARNING;
$requirements['memcache_extension']['description'] = $t('There is a problem with your memcache configuration. Please review %readme for help resolving the following !issue: !warnings', array(
'%readme' => drupal_get_path('module', 'memcache') . '/' . 'README.txt',
'!issue' => format_plural(count($warnings), 'issue', 'issues'),
'!warnings' => '<ul><li>' . implode('<li>', $warnings),
));
}
else {
$requirements['memcache_extension']['severity'] = REQUIREMENT_OK;
}
}
return $requirements;
}
function _memcache_statistics_link() {
$t = get_t();
if (module_exists('memcache_admin') && user_access('access memcache statistics')) {
return ' (' . l($t('more information'), 'admin/reports/memcache') . ')';
}
else {
return '';
}
}
function _memcache_pecl_version_valid() {
$extension = dmemcache_extension();
if ($extension == 'Memcache') {
$full_version = phpversion('memcache');
$version = implode('.', array_slice(explode('.', $full_version), 0, 3));
if (version_compare(phpversion(), '7' . '>=')) {
return version_compare($version, MEMCACHE_PECL_PHP7_RECOMMENDED, '>=');
}
else {
return version_compare($version, MEMCACHE_PECL_RECOMMENDED, '>=');
}
}
elseif ($extension == 'Memcached') {
return version_compare(phpversion('memcached'), MEMCACHED_PECL_RECOMMENDED, '>=');
}
}
function _memcached_ascii_auth_version_valid($version) {
if (_dmemcache_use_ascii_auth()) {
$stats = dmemcache_stats();
foreach ($stats as $bin => $servers) {
if (!empty($servers)) {
foreach ($servers as $server => $value) {
$installed_version = $value['version'];
if (version_compare($installed_version, $version, '<')) {
return $installed_version;
}
}
}
else {
return FALSE;
}
}
}
return TRUE;
}
function _check_ascii_auth($memcache_original) {
$servers = $memcache_original
->getServerList();
foreach ($servers as $s) {
$mc = new Memcached();
$mc
->addServer($s['host'], $s['port']);
$mc
->set(DRUPAL_MEMCACHE_ASCII_AUTH_LIFETIME_KEY, TRUE);
$rc = $mc
->get(DRUPAL_MEMCACHE_ASCII_AUTH_LIFETIME_KEY);
if ($rc) {
return [
$s,
t('ASCII authentication not enabled on server'),
];
}
$rc = _dmemcache_ensure_ascii_auth("0", $mc);
if (!$rc) {
return [
$s,
t('ASCII authentication failed'),
];
}
}
return TRUE;
}
function memcache_update_7000() {
variable_del('memcache_wildcard_flushes');
}