Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
TwoLevels.php
Go to the documentation of this file.
1 <?php
27 #require_once 'Zend/Cache/Backend/ExtendedInterface.php';
28 
32 #require_once 'Zend/Cache/Backend.php';
33 
34 
43 {
85  protected $_options = array(
86  'slow_backend' => 'File',
87  'fast_backend' => 'Apc',
88  'slow_backend_options' => array(),
89  'fast_backend_options' => array(),
90  'stats_update_factor' => 10,
91  'slow_backend_custom_naming' => false,
92  'fast_backend_custom_naming' => false,
93  'slow_backend_autoload' => false,
94  'fast_backend_autoload' => false,
95  'auto_fill_fast_cache' => true,
96  'auto_refresh_fast_cache' => true
97  );
98 
104  protected $_slowBackend;
105 
111  protected $_fastBackend;
112 
119 
127  public function __construct(array $options = array())
128  {
129  parent::__construct($options);
130 
131  if ($this->_options['slow_backend'] === null) {
132  Zend_Cache::throwException('slow_backend option has to set');
133  } elseif ($this->_options['slow_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
134  $this->_slowBackend = $this->_options['slow_backend'];
135  } else {
136  $this->_slowBackend = Zend_Cache::_makeBackend(
137  $this->_options['slow_backend'],
138  $this->_options['slow_backend_options'],
139  $this->_options['slow_backend_custom_naming'],
140  $this->_options['slow_backend_autoload']
141  );
142  if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) {
143  Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
144  }
145  }
146 
147  if ($this->_options['fast_backend'] === null) {
148  Zend_Cache::throwException('fast_backend option has to set');
149  } elseif ($this->_options['fast_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
150  $this->_fastBackend = $this->_options['fast_backend'];
151  } else {
152  $this->_fastBackend = Zend_Cache::_makeBackend(
153  $this->_options['fast_backend'],
154  $this->_options['fast_backend_options'],
155  $this->_options['fast_backend_custom_naming'],
156  $this->_options['fast_backend_autoload']
157  );
158  if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) {
159  Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
160  }
161  }
162 
163  $this->_slowBackend->setDirectives($this->_directives);
164  $this->_fastBackend->setDirectives($this->_directives);
165  }
166 
173  public function test($id)
174  {
175  $fastTest = $this->_fastBackend->test($id);
176  if ($fastTest) {
177  return $fastTest;
178  } else {
179  return $this->_slowBackend->test($id);
180  }
181  }
182 
196  public function save($data, $id, $tags = array(), $specificLifetime = false, $priority = 8)
197  {
198  $usage = $this->_getFastFillingPercentage('saving');
199  $boolFast = true;
200  $lifetime = $this->getLifetime($specificLifetime);
201  $preparedData = $this->_prepareData($data, $lifetime, $priority);
202  if (($priority > 0) && (10 * $priority >= $usage)) {
203  $fastLifetime = $this->_getFastLifetime($lifetime, $priority);
204  $boolFast = $this->_fastBackend->save($preparedData, $id, array(), $fastLifetime);
205  $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
206  } else {
207  $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
208  if ($boolSlow === true) {
209  $boolFast = $this->_fastBackend->remove($id);
210  if (!$boolFast && !$this->_fastBackend->test($id)) {
211  // some backends return false on remove() even if the key never existed. (and it won't if fast is full)
212  // all we care about is that the key doesn't exist now
213  $boolFast = true;
214  }
215  }
216  }
217 
218  return ($boolFast && $boolSlow);
219  }
220 
230  public function load($id, $doNotTestCacheValidity = false)
231  {
232  $resultFast = $this->_fastBackend->load($id, $doNotTestCacheValidity);
233  if ($resultFast === false) {
234  $resultSlow = $this->_slowBackend->load($id, $doNotTestCacheValidity);
235  if ($resultSlow === false) {
236  // there is no cache at all for this id
237  return false;
238  }
239  }
240  $array = $resultFast !== false ? unserialize($resultFast) : unserialize($resultSlow);
241 
242  //In case no cache entry was found in the FastCache and auto-filling is enabled, copy data to FastCache
243  if ($resultFast === false && $this->_options['auto_fill_fast_cache']) {
244  $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
245  $this->_fastBackend->save($preparedData, $id, array(), $array['lifetime']);
246  }
247  // maybe, we have to refresh the fast cache ?
248  elseif ($this->_options['auto_refresh_fast_cache']) {
249  if ($array['priority'] == 10) {
250  // no need to refresh the fast cache with priority = 10
251  return $array['data'];
252  }
253  $newFastLifetime = $this->_getFastLifetime($array['lifetime'], $array['priority'], time() - $array['expire']);
254  // we have the time to refresh the fast cache
255  $usage = $this->_getFastFillingPercentage('loading');
256  if (($array['priority'] > 0) && (10 * $array['priority'] >= $usage)) {
257  // we can refresh the fast cache
258  $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
259  $this->_fastBackend->save($preparedData, $id, array(), $newFastLifetime);
260  }
261  }
262  return $array['data'];
263  }
264 
271  public function remove($id)
272  {
273  $boolFast = $this->_fastBackend->remove($id);
274  $boolSlow = $this->_slowBackend->remove($id);
275  return $boolFast && $boolSlow;
276  }
277 
296  public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
297  {
298  switch($mode) {
300  $boolFast = $this->_fastBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
301  $boolSlow = $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
302  return $boolFast && $boolSlow;
303  break;
305  return $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_OLD);
307  $ids = $this->_slowBackend->getIdsMatchingTags($tags);
308  $res = true;
309  foreach ($ids as $id) {
310  $bool = $this->remove($id);
311  $res = $res && $bool;
312  }
313  return $res;
314  break;
316  $ids = $this->_slowBackend->getIdsNotMatchingTags($tags);
317  $res = true;
318  foreach ($ids as $id) {
319  $bool = $this->remove($id);
320  $res = $res && $bool;
321  }
322  return $res;
323  break;
325  $ids = $this->_slowBackend->getIdsMatchingAnyTags($tags);
326  $res = true;
327  foreach ($ids as $id) {
328  $bool = $this->remove($id);
329  $res = $res && $bool;
330  }
331  return $res;
332  break;
333  default:
334  Zend_Cache::throwException('Invalid mode for clean() method');
335  break;
336  }
337  }
338 
344  public function getIds()
345  {
346  return $this->_slowBackend->getIds();
347  }
348 
354  public function getTags()
355  {
356  return $this->_slowBackend->getTags();
357  }
358 
367  public function getIdsMatchingTags($tags = array())
368  {
369  return $this->_slowBackend->getIdsMatchingTags($tags);
370  }
371 
380  public function getIdsNotMatchingTags($tags = array())
381  {
382  return $this->_slowBackend->getIdsNotMatchingTags($tags);
383  }
384 
393  public function getIdsMatchingAnyTags($tags = array())
394  {
395  return $this->_slowBackend->getIdsMatchingAnyTags($tags);
396  }
397 
403  public function getFillingPercentage()
404  {
405  return $this->_slowBackend->getFillingPercentage();
406  }
407 
419  public function getMetadatas($id)
420  {
421  return $this->_slowBackend->getMetadatas($id);
422  }
423 
431  public function touch($id, $extraLifetime)
432  {
433  return $this->_slowBackend->touch($id, $extraLifetime);
434  }
435 
450  public function getCapabilities()
451  {
452  $slowBackendCapabilities = $this->_slowBackend->getCapabilities();
453  return array(
454  'automatic_cleaning' => $slowBackendCapabilities['automatic_cleaning'],
455  'tags' => $slowBackendCapabilities['tags'],
456  'expired_read' => $slowBackendCapabilities['expired_read'],
457  'priority' => $slowBackendCapabilities['priority'],
458  'infinite_lifetime' => $slowBackendCapabilities['infinite_lifetime'],
459  'get_list' => $slowBackendCapabilities['get_list']
460  );
461  }
462 
471  private function _prepareData($data, $lifetime, $priority)
472  {
473  $lt = $lifetime;
474  if ($lt === null) {
475  $lt = 9999999999;
476  }
477  return serialize(array(
478  'data' => $data,
479  'lifetime' => $lifetime,
480  'expire' => time() + $lt,
481  'priority' => $priority
482  ));
483  }
484 
493  private function _getFastLifetime($lifetime, $priority, $maxLifetime = null)
494  {
495  if ($lifetime <= 0) {
496  // if no lifetime, we have an infinite lifetime
497  // we need to use arbitrary lifetimes
498  $fastLifetime = (int) (2592000 / (11 - $priority));
499  } else {
500  // prevent computed infinite lifetime (0) by ceil
501  $fastLifetime = (int) ceil($lifetime / (11 - $priority));
502  }
503 
504  if ($maxLifetime >= 0 && $fastLifetime > $maxLifetime) {
505  return $maxLifetime;
506  }
507 
508  return $fastLifetime;
509  }
510 
518  public function ___expire($id)
519  {
520  $this->_fastBackend->remove($id);
521  $this->_slowBackend->___expire($id);
522  }
523 
524  private function _getFastFillingPercentage($mode)
525  {
526 
527  if ($mode == 'saving') {
528  // mode saving
529  if ($this->_fastBackendFillingPercentage === null) {
530  $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
531  } else {
532  $rand = rand(1, $this->_options['stats_update_factor']);
533  if ($rand == 1) {
534  // we force a refresh
535  $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
536  }
537  }
538  } else {
539  // mode loading
540  // we compute the percentage only if it's not available in cache
541  if ($this->_fastBackendFillingPercentage === null) {
542  $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
543  }
544  }
546  }
547 
548 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
getIdsMatchingAnyTags($tags=array())
Definition: TwoLevels.php:393
$id
Definition: fieldset.phtml:14
clean($mode=Zend_Cache::CLEANING_MODE_ALL, $tags=array())
Definition: TwoLevels.php:296
const CLEANING_MODE_OLD
Definition: Cache.php:73
const CLEANING_MODE_NOT_MATCHING_TAG
Definition: Cache.php:75
__construct(array $options=array())
Definition: TwoLevels.php:127
load($id, $doNotTestCacheValidity=false)
Definition: TwoLevels.php:230
if($exist=($block->getProductCollection() && $block->getProductCollection() ->getSize())) $mode
Definition: grid.phtml:15
const CLEANING_MODE_ALL
Definition: Cache.php:72
static throwException($msg, Exception $e=null)
Definition: Cache.php:205
getIdsMatchingTags($tags=array())
Definition: TwoLevels.php:367
const CLEANING_MODE_MATCHING_ANY_TAG
Definition: Cache.php:76
touch($id, $extraLifetime)
Definition: TwoLevels.php:431
const CLEANING_MODE_MATCHING_TAG
Definition: Cache.php:74
getLifetime($specificLifetime)
Definition: Backend.php:143
save($data, $id, $tags=array(), $specificLifetime=false, $priority=8)
Definition: TwoLevels.php:196
getIdsNotMatchingTags($tags=array())
Definition: TwoLevels.php:380
static _makeBackend($backend, $backendOptions, $customBackendNaming=false, $autoload=false)
Definition: Cache.php:124