MemcachedCache.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. namespace Doctrine\Common\Cache;
  3. use Memcached;
  4. use function array_keys;
  5. use function preg_match;
  6. use function strlen;
  7. use function strpos;
  8. use function time;
  9. /**
  10. * Memcached cache provider.
  11. *
  12. * @deprecated Deprecated without replacement in doctrine/cache 1.11. This class will be dropped in 2.0
  13. *
  14. * @link www.doctrine-project.org
  15. */
  16. class MemcachedCache extends CacheProvider
  17. {
  18. public const CACHE_ID_MAX_LENGTH = 250;
  19. /** @var Memcached|null */
  20. private $memcached;
  21. /**
  22. * Sets the memcache instance to use.
  23. *
  24. * @return void
  25. */
  26. public function setMemcached(Memcached $memcached)
  27. {
  28. $this->memcached = $memcached;
  29. }
  30. /**
  31. * Gets the memcached instance used by the cache.
  32. *
  33. * @return Memcached|null
  34. */
  35. public function getMemcached()
  36. {
  37. return $this->memcached;
  38. }
  39. /**
  40. * {@inheritdoc}
  41. */
  42. protected function doFetch($id)
  43. {
  44. return $this->memcached->get($id);
  45. }
  46. /**
  47. * {@inheritdoc}
  48. */
  49. protected function doFetchMultiple(array $keys)
  50. {
  51. return $this->memcached->getMulti($keys) ?: [];
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)
  57. {
  58. foreach (array_keys($keysAndValues) as $id) {
  59. $this->validateCacheId($id);
  60. }
  61. if ($lifetime > 30 * 24 * 3600) {
  62. $lifetime = time() + $lifetime;
  63. }
  64. return $this->memcached->setMulti($keysAndValues, $lifetime);
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. protected function doContains($id)
  70. {
  71. $this->memcached->get($id);
  72. return $this->memcached->getResultCode() === Memcached::RES_SUCCESS;
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. protected function doSave($id, $data, $lifeTime = 0)
  78. {
  79. $this->validateCacheId($id);
  80. if ($lifeTime > 30 * 24 * 3600) {
  81. $lifeTime = time() + $lifeTime;
  82. }
  83. return $this->memcached->set($id, $data, (int) $lifeTime);
  84. }
  85. /**
  86. * {@inheritdoc}
  87. */
  88. protected function doDeleteMultiple(array $keys)
  89. {
  90. return $this->memcached->deleteMulti($keys)
  91. || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
  92. }
  93. /**
  94. * {@inheritdoc}
  95. */
  96. protected function doDelete($id)
  97. {
  98. return $this->memcached->delete($id)
  99. || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. protected function doFlush()
  105. {
  106. return $this->memcached->flush();
  107. }
  108. /**
  109. * {@inheritdoc}
  110. */
  111. protected function doGetStats()
  112. {
  113. $stats = $this->memcached->getStats();
  114. $servers = $this->memcached->getServerList();
  115. $key = $servers[0]['host'] . ':' . $servers[0]['port'];
  116. $stats = $stats[$key];
  117. return [
  118. Cache::STATS_HITS => $stats['get_hits'],
  119. Cache::STATS_MISSES => $stats['get_misses'],
  120. Cache::STATS_UPTIME => $stats['uptime'],
  121. Cache::STATS_MEMORY_USAGE => $stats['bytes'],
  122. Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'],
  123. ];
  124. }
  125. /**
  126. * Validate the cache id
  127. *
  128. * @see https://github.com/memcached/memcached/blob/1.5.12/doc/protocol.txt#L41-L49
  129. *
  130. * @param string $id
  131. *
  132. * @return void
  133. *
  134. * @throws InvalidCacheId
  135. */
  136. private function validateCacheId($id)
  137. {
  138. if (strlen($id) > self::CACHE_ID_MAX_LENGTH) {
  139. throw InvalidCacheId::exceedsMaxLength($id, self::CACHE_ID_MAX_LENGTH);
  140. }
  141. if (strpos($id, ' ') !== false) {
  142. throw InvalidCacheId::containsUnauthorizedCharacter($id, ' ');
  143. }
  144. if (preg_match('/[\t\r\n]/', $id) === 1) {
  145. throw InvalidCacheId::containsControlCharacter($id);
  146. }
  147. }
  148. }