memcache.install 7.96 KB
Newer Older
1 2
<?php

3 4 5 6 7
/**
 * @file
 * Install, update and uninstall functions for the memcache module.
 */

8 9 10
define('MEMCACHE_PECL_RECOMMENDED', '3.0.6');
define('MEMCACHED_PECL_RECOMMENDED', '2.0.1');

11 12 13 14 15
/**
 * Implements hook_enable().
 */
function memcache_enable() {
  $error = FALSE;
16 17
  $warning = FALSE;
  $severity = 'status';
18 19 20 21 22 23 24 25 26 27
  $memcache = extension_loaded('memcache');
  $memcached = extension_loaded('memcached');
  if (!$memcache && !$memcached) {
    $error = TRUE;
  }
  if (!function_exists('dmemcache_object')) {
    // dmemcache.inc isn't loaded.
    $error = TRUE;
  }
  else {
28
    if (!_memcache_version_valid()) {
29
      $warning = TRUE;
30
    }
31 32 33 34 35 36 37 38 39 40 41 42
    // Make a test connection to all configured memcache servers.
    $memcache_servers = variable_get('memcache_servers', array('127.0.0.1:11211' => 'default'));
    $memcache = dmemcache_instance();
    foreach ($memcache_servers as $server => $bin) {
      if (dmemcache_connect($memcache, $server, FALSE) === FALSE) {
        $error = TRUE;
      }
      else {
        dmemcache_close($memcache);
      }
    }
  }
43

44
  if ($error) {
45 46 47 48 49 50 51
    $severity = 'error';
  }
  elseif ($warning) {
    $severity = 'warning';
  }

  if ($error || $warning) {
52
    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);
53
  }
54

55 56
}

57 58 59 60 61 62 63 64
/**
 * Implements hook_requirements().
 */
function memcache_requirements($phase) {
  $requirements = array();
  $t = get_t();
  $memcache = extension_loaded('memcache');
  $memcached = extension_loaded('memcached');
65

66
  if ($phase == 'install' || $phase == 'runtime') {
67
    $requirements['memcache_extension']['title'] = $t('Memcache');
68 69
    if (!$memcache && !$memcached) {
      $requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
70
      $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.');
71
    }
72 73 74
    else {
      $requirements['memcache_extension']['value'] = $t('PHP %extension Extension', array('%extension' => $memcache ? $t('Memcache') : $t('Memcached')));
    }
75 76
  }
  if ($phase == 'runtime') {
77
    $errors = array();
78 79
    $warnings = array();

80 81 82 83 84 85 86
    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')) {
      // dmemcache.inc isn't loaded.
      $errors[] = $t('Failed to load required file %dmemcache.', array('%dmemcache' => drupal_get_path('module', 'memcache') . '/' . 'dmemcache.inc'));
87
      $requirements['memcache_extension']['value'] = $t('Unknown');
88
    }
89 90 91
    else {
      $extension = dmemcache_extension();
      if ($extension == 'Memcache') {
92 93
        $version = phpversion('memcache');
        $recommended = MEMCACHE_PECL_RECOMMENDED;
94
      }
95
      elseif ($extension == 'Memcached') {
96 97
        $version = phpversion('memcached');
        $recommended = MEMCACHED_PECL_RECOMMENDED;
98
      }
99 100
      if (!$version) {
        $version = $t('Unknown');
101
      }
102
      $requirements['memcache_extension']['value'] = $version . _memcache_statistics_link();
103

104
      if (!_memcache_version_valid()) {
105
        $warnings[] = $t('PECL !extension version %version is unsupported. Please update to %recommended or newer.', array(
106 107 108 109
          '!extension' => $extension,
          '%version' => $version,
          '%recommended' => $recommended,
        ));
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
      }

      // Make a test connection to all configured memcache servers.
      $memcache_servers = variable_get('memcache_servers', array('127.0.0.1:11211' => 'default'));
      $memcache = dmemcache_instance();
      foreach ($memcache_servers as $server => $bin) {
        if (dmemcache_connect($memcache, $server, FALSE) === FALSE) {
          $errors[] = $t('Failed to connect to memcached server instance at %server.', array('%server' => $server));
        }
        else {
          dmemcache_close($memcache);
        }
      }

      // Set up a temporary bin to see if we can store a value and then
      // successfully retreive it.
      try {
127
        $cid = 'memcache_requirements_test';
128
        $value = 'OK';
129
        // Temporarily store a test value in memcache.
130
        cache_set($cid, $value);
131
        // Retreive the test value from memcache.
132
        $data = cache_get($cid);
133
        if (!isset($data->data) || $data->data !== $value) {
134 135 136 137 138
          $errors[] = $t('Failed to store to then retrieve data from memcache.');
        }
        else {
          // Test a delete as well.
          cache_clear_all($cid, 'cache');
139 140 141 142
        }
      }
      catch (Exception $e) {
        // An unexpected exception occurred.
143
        $errors[] = $t('Unexpected failure when testing memcache configuration.');
144
      }
145 146 147 148 149 150
      // Core's lock implementation can cause worse performance together with
      // stampede protection. Plus, long keys will be truncated resulting in
      // dropped locks.
      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"));
      }
151
    }
152

153 154 155 156 157
    if (!empty($errors)) {
      // Error takes precedence over warning, stack together errors and
      // warnings and display as error messages.
      $errors = array_merge($errors, $warnings);
      unset($warnings);
158
      $requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
159
      $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)));
160
    }
161 162
    elseif (!empty($warnings)) {
      $requirements['memcache_extension']['severity'] = REQUIREMENT_WARNING;
163
      $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)));
164 165 166 167
    }
    else {
      $requirements['memcache_extension']['severity'] = REQUIREMENT_OK;
    }
168 169 170
  }
  return $requirements;
}
171

172 173 174 175 176 177 178 179 180 181 182 183 184 185
/**
 * Add "(more information)" link after memcache version if memcache_admin
 * module is enabled and user has access to memcache statistics.
 */
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 '';
  }
}

186 187 188 189 190 191 192 193 194 195 196 197 198
/**
 * Validate whether the current PECL version is supported.
 */
function _memcache_version_valid() {
  $extension = dmemcache_extension();
  if ($extension == 'Memcache') {
    return version_compare(phpversion('memcache'), MEMCACHE_PECL_RECOMMENDED, '>=');
  }
  elseif ($extension == 'Memcached') {
    return version_compare(phpversion('memcached'), MEMCACHED_PECL_RECOMMENDED, '>=');
  }
}

199 200 201 202 203
/**
 * Remove the memcache_widlcard_flushes variable since its structure has changed.
 */
function memcache_update_7000() {
  variable_del('memcache_wildcard_flushes');
204
}