PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/core/lib/Drupal/Core/Cache/ApcuBackend.php

https://gitlab.com/reasonat/test8
PHP | 271 lines | 106 code | 32 blank | 133 comment | 8 complexity | 5c397eaaf339ec53479c65453707f7d0 MD5 | raw file
  1. <?php
  2. namespace Drupal\Core\Cache;
  3. /**
  4. * Stores cache items in the Alternative PHP Cache User Cache (APCu).
  5. */
  6. class ApcuBackend implements CacheBackendInterface {
  7. /**
  8. * The name of the cache bin to use.
  9. *
  10. * @var string
  11. */
  12. protected $bin;
  13. /**
  14. * Prefix for all keys in the storage that belong to this site.
  15. *
  16. * @var string
  17. */
  18. protected $sitePrefix;
  19. /**
  20. * Prefix for all keys in this cache bin.
  21. *
  22. * Includes the site-specific prefix in $sitePrefix.
  23. *
  24. * @var string
  25. */
  26. protected $binPrefix;
  27. /**
  28. * The cache tags checksum provider.
  29. *
  30. * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
  31. */
  32. protected $checksumProvider;
  33. /**
  34. * Constructs a new ApcuBackend instance.
  35. *
  36. * @param string $bin
  37. * The name of the cache bin.
  38. * @param string $site_prefix
  39. * The prefix to use for all keys in the storage that belong to this site.
  40. * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
  41. * The cache tags checksum provider.
  42. */
  43. public function __construct($bin, $site_prefix, CacheTagsChecksumInterface $checksum_provider) {
  44. $this->bin = $bin;
  45. $this->sitePrefix = $site_prefix;
  46. $this->checksumProvider = $checksum_provider;
  47. $this->binPrefix = $this->sitePrefix . '::' . $this->bin . '::';
  48. }
  49. /**
  50. * Prepends the APCu user variable prefix for this bin to a cache item ID.
  51. *
  52. * @param string $cid
  53. * The cache item ID to prefix.
  54. *
  55. * @return string
  56. * The APCu key for the cache item ID.
  57. */
  58. public function getApcuKey($cid) {
  59. return $this->binPrefix . $cid;
  60. }
  61. /**
  62. * {@inheritdoc}
  63. */
  64. public function get($cid, $allow_invalid = FALSE) {
  65. $cache = apcu_fetch($this->getApcuKey($cid));
  66. return $this->prepareItem($cache, $allow_invalid);
  67. }
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public function getMultiple(&$cids, $allow_invalid = FALSE) {
  72. // Translate the requested cache item IDs to APCu keys.
  73. $map = array();
  74. foreach ($cids as $cid) {
  75. $map[$this->getApcuKey($cid)] = $cid;
  76. }
  77. $result = apcu_fetch(array_keys($map));
  78. $cache = array();
  79. if ($result) {
  80. foreach ($result as $key => $item) {
  81. $item = $this->prepareItem($item, $allow_invalid);
  82. if ($item) {
  83. $cache[$map[$key]] = $item;
  84. }
  85. }
  86. }
  87. unset($result);
  88. $cids = array_diff($cids, array_keys($cache));
  89. return $cache;
  90. }
  91. /**
  92. * Returns all cached items, optionally limited by a cache ID prefix.
  93. *
  94. * APCu is a memory cache, shared across all server processes. To prevent
  95. * cache item clashes with other applications/installations, every cache item
  96. * is prefixed with a unique string for this site. Therefore, functions like
  97. * apcu_clear_cache() cannot be used, and instead, a list of all cache items
  98. * belonging to this application need to be retrieved through this method
  99. * instead.
  100. *
  101. * @param string $prefix
  102. * (optional) A cache ID prefix to limit the result to.
  103. *
  104. * @return \APCUIterator
  105. * An APCUIterator containing matched items.
  106. */
  107. protected function getAll($prefix = '') {
  108. return $this->getIterator('/^' . preg_quote($this->getApcuKey($prefix), '/') . '/');
  109. }
  110. /**
  111. * Prepares a cached item.
  112. *
  113. * Checks that the item is either permanent or did not expire.
  114. *
  115. * @param \stdClass $cache
  116. * An item loaded from cache_get() or cache_get_multiple().
  117. * @param bool $allow_invalid
  118. * If TRUE, a cache item may be returned even if it is expired or has been
  119. * invalidated. See ::get().
  120. *
  121. * @return mixed
  122. * The cache item or FALSE if the item expired.
  123. */
  124. protected function prepareItem($cache, $allow_invalid) {
  125. if (!isset($cache->data)) {
  126. return FALSE;
  127. }
  128. $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
  129. // Check expire time.
  130. $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
  131. // Check if invalidateTags() has been called with any of the entry's tags.
  132. if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
  133. $cache->valid = FALSE;
  134. }
  135. if (!$allow_invalid && !$cache->valid) {
  136. return FALSE;
  137. }
  138. return $cache;
  139. }
  140. /**
  141. * {@inheritdoc}
  142. */
  143. public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
  144. assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache tags must be strings.');
  145. $tags = array_unique($tags);
  146. $cache = new \stdClass();
  147. $cache->cid = $cid;
  148. $cache->created = round(microtime(TRUE), 3);
  149. $cache->expire = $expire;
  150. $cache->tags = implode(' ', $tags);
  151. $cache->checksum = $this->checksumProvider->getCurrentChecksum($tags);
  152. // APCu serializes/unserializes any structure itself.
  153. $cache->serialized = 0;
  154. $cache->data = $data;
  155. // Expiration is handled by our own prepareItem(), not APCu.
  156. apcu_store($this->getApcuKey($cid), $cache);
  157. }
  158. /**
  159. * {@inheritdoc}
  160. */
  161. public function setMultiple(array $items = array()) {
  162. foreach ($items as $cid => $item) {
  163. $this->set($cid, $item['data'], isset($item['expire']) ? $item['expire'] : CacheBackendInterface::CACHE_PERMANENT, isset($item['tags']) ? $item['tags'] : array());
  164. }
  165. }
  166. /**
  167. * {@inheritdoc}
  168. */
  169. public function delete($cid) {
  170. apcu_delete($this->getApcuKey($cid));
  171. }
  172. /**
  173. * {@inheritdoc}
  174. */
  175. public function deleteMultiple(array $cids) {
  176. apcu_delete(array_map(array($this, 'getApcuKey'), $cids));
  177. }
  178. /**
  179. * {@inheritdoc}
  180. */
  181. public function deleteAll() {
  182. apcu_delete($this->getIterator('/^' . preg_quote($this->binPrefix, '/') . '/'));
  183. }
  184. /**
  185. * {@inheritdoc}
  186. */
  187. public function garbageCollection() {
  188. // APCu performs garbage collection automatically.
  189. }
  190. /**
  191. * {@inheritdoc}
  192. */
  193. public function removeBin() {
  194. apcu_delete($this->getIterator('/^' . preg_quote($this->binPrefix, '/') . '/'));
  195. }
  196. /**
  197. * {@inheritdoc}
  198. */
  199. public function invalidate($cid) {
  200. $this->invalidateMultiple(array($cid));
  201. }
  202. /**
  203. * {@inheritdoc}
  204. */
  205. public function invalidateMultiple(array $cids) {
  206. foreach ($this->getMultiple($cids) as $cache) {
  207. $this->set($cache->cid, $cache, REQUEST_TIME - 1);
  208. }
  209. }
  210. /**
  211. * {@inheritdoc}
  212. */
  213. public function invalidateAll() {
  214. foreach ($this->getAll() as $data) {
  215. $cid = str_replace($this->binPrefix, '', $data['key']);
  216. $this->set($cid, $data['value'], REQUEST_TIME - 1);
  217. }
  218. }
  219. /**
  220. * Instantiates and returns the APCUIterator class.
  221. *
  222. * @param mixed $search
  223. * A PCRE regular expression that matches against APC key names, either as a
  224. * string for a single regular expression, or as an array of regular
  225. * expressions. Or, optionally pass in NULL to skip the search.
  226. * @param int $format
  227. * The desired format, as configured with one or more of the APC_ITER_*
  228. * constants.
  229. * @param int $chunk_size
  230. * The chunk size. Must be a value greater than 0. The default value is 100.
  231. * @param int $list
  232. * The type to list. Either pass in APC_LIST_ACTIVE or APC_LIST_DELETED.
  233. *
  234. * @return \APCUIterator
  235. */
  236. protected function getIterator($search = NULL, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) {
  237. return new \APCUIterator($search, $format, $chunk_size, $list);
  238. }
  239. }