memcache.install 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. /**
  3. * @file
  4. * Install, update and uninstall functions for the memcache module.
  5. */
  6. define('MEMCACHE_PECL_RECOMMENDED', '3.0.6');
  7. define('MEMCACHED_PECL_RECOMMENDED', '2.0.1');
  8. /**
  9. * Implements hook_enable().
  10. */
  11. function memcache_enable() {
  12. $error = FALSE;
  13. $warning = FALSE;
  14. $severity = 'status';
  15. $memcache = extension_loaded('memcache');
  16. $memcached = extension_loaded('memcached');
  17. if (!$memcache && !$memcached) {
  18. $error = TRUE;
  19. }
  20. if (!function_exists('dmemcache_object')) {
  21. // dmemcache.inc isn't loaded.
  22. $error = TRUE;
  23. }
  24. else {
  25. if (!_memcache_version_valid()) {
  26. $warning = TRUE;
  27. }
  28. // Make a test connection to all configured memcache servers.
  29. $memcache_servers = variable_get('memcache_servers', array('127.0.0.1:11211' => 'default'));
  30. foreach ($memcache_servers as $server => $bin) {
  31. if ($cluster = dmemcache_object_cluster($bin)) {
  32. $memcache = dmemcache_instance($cluster['cluster']);
  33. if (dmemcache_connect($memcache, $server, $cluster['weight']) === FALSE) {
  34. $error = TRUE;
  35. }
  36. else {
  37. if (!variable_get('memcache_persistent', TRUE)) {
  38. dmemcache_close($memcache);
  39. }
  40. }
  41. }
  42. }
  43. }
  44. if ($error) {
  45. $severity = 'error';
  46. }
  47. elseif ($warning) {
  48. $severity = 'warning';
  49. }
  50. if ($error || $warning) {
  51. 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);
  52. }
  53. }
  54. /**
  55. * Implements hook_requirements().
  56. */
  57. function memcache_requirements($phase) {
  58. $requirements = array();
  59. $t = get_t();
  60. $memcache = extension_loaded('memcache');
  61. $memcached = extension_loaded('memcached');
  62. if ($phase == 'install' || $phase == 'runtime') {
  63. $requirements['memcache_extension']['title'] = $t('Memcache');
  64. if (!$memcache && !$memcached) {
  65. $requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
  66. $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.');
  67. }
  68. else {
  69. $requirements['memcache_extension']['value'] = $t('PHP %extension Extension', array('%extension' => $memcache ? $t('Memcache') : $t('Memcached')));
  70. }
  71. }
  72. if ($phase == 'runtime') {
  73. $errors = array();
  74. $warnings = array();
  75. if (!$memcache && !$memcached) {
  76. $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.');
  77. }
  78. if (!function_exists('dmemcache_set')) {
  79. // dmemcache.inc isn't loaded.
  80. $errors[] = $t('Failed to load required file %dmemcache.', array('%dmemcache' => drupal_get_path('module', 'memcache') . '/' . 'dmemcache.inc'));
  81. $requirements['memcache_extension']['value'] = $t('Unknown');
  82. }
  83. else {
  84. $extension = dmemcache_extension();
  85. if ($extension == 'Memcache') {
  86. $version = phpversion('memcache');
  87. $recommended = MEMCACHE_PECL_RECOMMENDED;
  88. }
  89. elseif ($extension == 'Memcached') {
  90. $version = phpversion('memcached');
  91. $recommended = MEMCACHED_PECL_RECOMMENDED;
  92. }
  93. if (!$version) {
  94. $version = $t('Unknown');
  95. }
  96. $requirements['memcache_extension']['value'] = $version . _memcache_statistics_link();
  97. if (!_memcache_version_valid()) {
  98. $warnings[] = $t('PECL !extension version %version is unsupported. Please update to %recommended or newer.', array(
  99. '!extension' => $extension,
  100. '%version' => $version,
  101. '%recommended' => $recommended,
  102. ));
  103. }
  104. // Make a test connection to all configured memcache servers.
  105. $memcache_servers = variable_get('memcache_servers', array('127.0.0.1:11211' => 'default'));
  106. foreach ($memcache_servers as $server => $bin) {
  107. if ($cluster = dmemcache_object_cluster($bin)) {
  108. $memcache = dmemcache_instance($cluster['cluster']);
  109. if (dmemcache_connect($memcache, $server, $cluster['weight']) === FALSE) {
  110. $errors[] = $t('Failed to connect to memcached server instance at %server.', array('%server' => $server));
  111. }
  112. else {
  113. if (!variable_get('memcache_persistent', TRUE)) {
  114. dmemcache_close($memcache);
  115. }
  116. }
  117. }
  118. }
  119. // Set up a temporary bin to see if we can store a value and then
  120. // successfully retreive it.
  121. try {
  122. $cid = 'memcache_requirements_test';
  123. $value = 'OK';
  124. // Temporarily store a test value in memcache.
  125. cache_set($cid, $value);
  126. // Retreive the test value from memcache.
  127. $data = cache_get($cid);
  128. if (!isset($data->data) || $data->data !== $value) {
  129. $errors[] = $t('Failed to store to then retrieve data from memcache.');
  130. }
  131. else {
  132. // Test a delete as well.
  133. cache_clear_all($cid, 'cache');
  134. }
  135. }
  136. catch (Exception $e) {
  137. // An unexpected exception occurred.
  138. $errors[] = $t('Unexpected failure when testing memcache configuration.');
  139. }
  140. // Core's lock implementation can cause worse performance together with
  141. // stampede protection. Plus, long keys will be truncated resulting in
  142. // dropped locks.
  143. if (variable_get('memcache_stampede_protection', FALSE) && strpos(variable_get('lock_inc', 'includes/lock.inc'), 'includes/lock.inc') !== FALSE) {
  144. $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"));
  145. }
  146. }
  147. if (!empty($errors)) {
  148. // Error takes precedence over warning, stack together errors and
  149. // warnings and display as error messages.
  150. $errors = array_merge($errors, $warnings);
  151. unset($warnings);
  152. $requirements['memcache_extension']['severity'] = REQUIREMENT_ERROR;
  153. $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)));
  154. }
  155. elseif (!empty($warnings)) {
  156. $requirements['memcache_extension']['severity'] = REQUIREMENT_WARNING;
  157. $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)));
  158. }
  159. else {
  160. $requirements['memcache_extension']['severity'] = REQUIREMENT_OK;
  161. }
  162. }
  163. return $requirements;
  164. }
  165. /**
  166. * Add "(more information)" link after memcache version if memcache_admin
  167. * module is enabled and user has access to memcache statistics.
  168. */
  169. function _memcache_statistics_link() {
  170. $t = get_t();
  171. if (module_exists('memcache_admin') && user_access('access memcache statistics')) {
  172. return ' (' . l($t('more information'), 'admin/reports/memcache') . ')';
  173. }
  174. else {
  175. return '';
  176. }
  177. }
  178. /**
  179. * Validate whether the current PECL version is supported.
  180. */
  181. function _memcache_version_valid() {
  182. $extension = dmemcache_extension();
  183. if ($extension == 'Memcache') {
  184. return version_compare(phpversion('memcache'), MEMCACHE_PECL_RECOMMENDED, '>=');
  185. }
  186. elseif ($extension == 'Memcached') {
  187. return version_compare(phpversion('memcached'), MEMCACHED_PECL_RECOMMENDED, '>=');
  188. }
  189. }
  190. /**
  191. * Remove the memcache_widlcard_flushes variable since its structure has changed.
  192. */
  193. function memcache_update_7000() {
  194. variable_del('memcache_wildcard_flushes');
  195. }