PageRenderTime 64ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Varien/Cache/Backend/Memcached.php

https://bitbucket.org/sevenly/magento-ce
PHP | 159 lines | 67 code | 22 blank | 70 comment | 17 complexity | 9de5a66839dbd79d7c365b58514777fe MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Varien
  22. * @package Varien_Cache
  23. * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. class Varien_Cache_Backend_Memcached
  27. extends Zend_Cache_Backend_Memcached
  28. implements Zend_Cache_Backend_ExtendedInterface
  29. {
  30. /**
  31. * Maximum chunk of data that could be saved in one memcache cell (1 MiB)
  32. */
  33. const DEFAULT_SLAB_SIZE = 1048576;
  34. /**
  35. * Used to tell chunked data from ordinary
  36. */
  37. const CODE_WORD = '{splitted}';
  38. /**
  39. * Constructor
  40. *
  41. * @throws Varien_Exception
  42. * @param array $options @see Zend_Cache_Backend_Memcached::__construct()
  43. */
  44. public function __construct(array $options = array())
  45. {
  46. parent::__construct($options);
  47. if (!isset($options['slab_size']) || !is_numeric($options['slab_size'])) {
  48. if (isset($options['slab_size'])) {
  49. throw new Varien_Exception("Invalid value for the node <slab_size>. Expected to be positive integer.");
  50. }
  51. $this->_options['slab_size'] = self::DEFAULT_SLAB_SIZE;
  52. } else {
  53. $this->_options['slab_size'] = $options['slab_size'];
  54. }
  55. }
  56. /**
  57. * Returns ID of a specific chunk on the basis of data's ID
  58. *
  59. * @param string $id Main data's ID
  60. * @param int $index Particular chunk number to return ID for
  61. * @return string
  62. */
  63. protected function _getChunkId($id, $index)
  64. {
  65. return "{$id}[{$index}]";
  66. }
  67. /**
  68. * Remove saved chunks in case something gone wrong (e.g. some chunk from the chain can not be found)
  69. *
  70. * @param string $id ID of data's info cell
  71. * @param int $chunks Number of chunks to remove (basically, the number after '{splitted}|')
  72. * @return null
  73. */
  74. protected function _cleanTheMess($id, $chunks)
  75. {
  76. for ($i = 0; $i < $chunks; $i++) {
  77. $this->remove($this->_getChunkId($id, $i));
  78. }
  79. $this->remove($id);
  80. }
  81. /**
  82. * Save data to memcached, split it into chunks if data size is bigger than memcached slab size.
  83. *
  84. * @param string $data @see Zend_Cache_Backend_Memcached::save()
  85. * @param string $id @see Zend_Cache_Backend_Memcached::save()
  86. * @param array $tags @see Zend_Cache_Backend_Memcached::save()
  87. * @param bool $specificLifetime @see Zend_Cache_Backend_Memcached::save()
  88. * @return bool
  89. */
  90. public function save($data, $id, $tags = array(), $specificLifetime = false)
  91. {
  92. if (is_string($data) && (strlen($data) > $this->_options['slab_size'])) {
  93. $dataChunks = str_split($data, $this->_options['slab_size']);
  94. for ($i = 0, $cnt = count($dataChunks); $i < $cnt; $i++) {
  95. $chunkId = $this->_getChunkId($id, $i);
  96. if (!parent::save($dataChunks[$i], $chunkId, $tags, $specificLifetime)) {
  97. $this->_cleanTheMess($id, $i + 1);
  98. return false;
  99. }
  100. }
  101. $data = self::CODE_WORD . '|' . $i;
  102. }
  103. return parent::save($data, $id, $tags, $specificLifetime);
  104. }
  105. /**
  106. * Load data from memcached, glue from several chunks if it was splitted upon save.
  107. *
  108. * @param string $id @see Zend_Cache_Backend_Memcached::load()
  109. * @param bool $doNotTestCacheValidity @see Zend_Cache_Backend_Memcached::load()
  110. * @return bool|false|string
  111. */
  112. public function load($id, $doNotTestCacheValidity = false)
  113. {
  114. $data = parent::load($id, $doNotTestCacheValidity);
  115. if (is_string($data) && (substr($data, 0, strlen(self::CODE_WORD)) == self::CODE_WORD)) {
  116. // Seems we've got chunked data
  117. $arr = explode('|', $data);
  118. $chunks = isset($arr[1]) ? $arr[1] : false;
  119. $chunkData = array();
  120. if ($chunks && is_numeric($chunks)) {
  121. for ($i = 0; $i < $chunks; $i++) {
  122. $chunk = parent::load($this->_getChunkId($id, $i), $doNotTestCacheValidity);
  123. if (false === $chunk) {
  124. // Some chunk in chain was not found, we can not glue-up the data:
  125. // clean the mess and return nothing
  126. $this->_cleanTheMess($id, $chunks);
  127. return false;
  128. }
  129. $chunkData[] = $chunk;
  130. }
  131. return implode('', $chunkData);
  132. }
  133. }
  134. // Data has not been splitted to chunks on save
  135. return $data;
  136. }
  137. }