BackendChain.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. namespace Drupal\Core\Cache;
  3. /**
  4. * Defines a chained cache implementation for combining multiple cache backends.
  5. *
  6. * Can be used to combine two or more backends together to behave as if they
  7. * were a single backend.
  8. *
  9. * For example a slower, persistent storage engine could be combined with a
  10. * faster, volatile storage engine. When retrieving items from cache, they will
  11. * be fetched from the volatile backend first, only falling back to the
  12. * persistent backend if an item is not available. An item not present in the
  13. * volatile backend but found in the persistent one will be propagated back up
  14. * to ensure fast retrieval on the next request. On cache sets and deletes, both
  15. * backends will be invoked to ensure consistency.
  16. *
  17. * @see \Drupal\Core\Cache\ChainedFastBackend
  18. *
  19. * @ingroup cache
  20. */
  21. class BackendChain implements CacheBackendInterface, CacheTagsInvalidatorInterface {
  22. /**
  23. * Ordered list of CacheBackendInterface instances.
  24. *
  25. * @var array
  26. */
  27. protected $backends = [];
  28. /**
  29. * Constructs a DatabaseBackend object.
  30. *
  31. * @param string $bin
  32. * The cache bin for which the object is created.
  33. */
  34. public function __construct($bin) {
  35. }
  36. /**
  37. * Appends a cache backend to the cache chain.
  38. *
  39. * @param CacheBackendInterface $backend
  40. * The cache backend to be appended to the cache chain.
  41. *
  42. * @return \Drupal\Core\Cache\BackendChain
  43. * The called object.
  44. */
  45. public function appendBackend(CacheBackendInterface $backend) {
  46. $this->backends[] = $backend;
  47. return $this;
  48. }
  49. /**
  50. * Prepends a cache backend to the cache chain.
  51. *
  52. * @param CacheBackendInterface $backend
  53. * The backend to be prepended to the cache chain.
  54. *
  55. * @return \Drupal\Core\Cache\BackendChain
  56. * The called object.
  57. */
  58. public function prependBackend(CacheBackendInterface $backend) {
  59. array_unshift($this->backends, $backend);
  60. return $this;
  61. }
  62. /**
  63. * {@inheritdoc}
  64. */
  65. public function get($cid, $allow_invalid = FALSE) {
  66. foreach ($this->backends as $index => $backend) {
  67. if (($return = $backend->get($cid, $allow_invalid)) !== FALSE) {
  68. // We found a result, propagate it to all missed backends.
  69. if ($index > 0) {
  70. for ($i = ($index - 1); 0 <= $i; --$i) {
  71. $this->backends[$i]->set($cid, $return->data, $return->expire, $return->tags);
  72. }
  73. }
  74. return $return;
  75. }
  76. }
  77. return FALSE;
  78. }
  79. /**
  80. * {@inheritdoc}
  81. */
  82. public function getMultiple(&$cids, $allow_invalid = FALSE) {
  83. $return = [];
  84. foreach ($this->backends as $index => $backend) {
  85. $items = $backend->getMultiple($cids, $allow_invalid);
  86. // Propagate the values that could be retrieved from the current cache
  87. // backend to all missed backends.
  88. if ($index > 0 && !empty($items)) {
  89. for ($i = ($index - 1); 0 <= $i; --$i) {
  90. foreach ($items as $cached) {
  91. $this->backends[$i]->set($cached->cid, $cached->data, $cached->expire, $cached->tags);
  92. }
  93. }
  94. }
  95. // Append the values to the previously retrieved ones.
  96. $return += $items;
  97. if (empty($cids)) {
  98. // No need to go further if we don't have any cid to fetch left.
  99. break;
  100. }
  101. }
  102. return $return;
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
  108. foreach ($this->backends as $backend) {
  109. $backend->set($cid, $data, $expire, $tags);
  110. }
  111. }
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function setMultiple(array $items) {
  116. foreach ($this->backends as $backend) {
  117. $backend->setMultiple($items);
  118. }
  119. }
  120. /**
  121. * {@inheritdoc}
  122. */
  123. public function delete($cid) {
  124. foreach ($this->backends as $backend) {
  125. $backend->delete($cid);
  126. }
  127. }
  128. /**
  129. * {@inheritdoc}
  130. */
  131. public function deleteMultiple(array $cids) {
  132. foreach ($this->backends as $backend) {
  133. $backend->deleteMultiple($cids);
  134. }
  135. }
  136. /**
  137. * {@inheritdoc}
  138. */
  139. public function deleteAll() {
  140. foreach ($this->backends as $backend) {
  141. $backend->deleteAll();
  142. }
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function invalidate($cid) {
  148. foreach ($this->backends as $backend) {
  149. $backend->invalidate($cid);
  150. }
  151. }
  152. /**
  153. * {@inheritdoc}
  154. */
  155. public function invalidateMultiple(array $cids) {
  156. foreach ($this->backends as $backend) {
  157. $backend->invalidateMultiple($cids);
  158. }
  159. }
  160. /**
  161. * {@inheritdoc}
  162. */
  163. public function invalidateTags(array $tags) {
  164. foreach ($this->backends as $backend) {
  165. if ($backend instanceof CacheTagsInvalidatorInterface) {
  166. $backend->invalidateTags($tags);
  167. }
  168. }
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function invalidateAll() {
  174. foreach ($this->backends as $backend) {
  175. $backend->invalidateAll();
  176. }
  177. }
  178. /**
  179. * {@inheritdoc}
  180. */
  181. public function garbageCollection() {
  182. foreach ($this->backends as $backend) {
  183. $backend->garbageCollection();
  184. }
  185. }
  186. /**
  187. * {@inheritdoc}
  188. */
  189. public function removeBin() {
  190. foreach ($this->backends as $backend) {
  191. $backend->removeBin();
  192. }
  193. }
  194. }