PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/tedivm/stash/src/Stash/Driver/Sub/Memcached.php

https://gitlab.com/fabiorf/chat
PHP | 231 lines | 138 code | 28 blank | 65 comment | 19 complexity | cebdc8014eaf88c91d08fc38ba8021de MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Stash package.
  4. *
  5. * (c) Robert Hafner <tedivm@tedivm.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Stash\Driver\Sub;
  11. use Stash\Exception\RuntimeException;
  12. /**
  13. * @internal
  14. * @package Stash
  15. * @author Robert Hafner <tedivm@tedivm.com>
  16. */
  17. class Memcached
  18. {
  19. /**
  20. * @var \Memcached
  21. */
  22. protected $memcached;
  23. /**
  24. * Constructs the Memcached subdriver.
  25. *
  26. * Takes an array of servers, with array containing another array with the server, port and weight.
  27. * array(array( '127.0.0.1', 11211, 20), array( '192.168.10.12', 11213, 80), array( '192.168.10.12', 11211, 80));
  28. *
  29. * Takes an array of options which map to the "\Memcached::OPT_" settings (\Memcached::OPT_COMPRESSION => "compression").
  30. *
  31. * @param array $servers
  32. * @param array $options
  33. * @throws \Stash\Exception\RuntimeException
  34. */
  35. public function __construct($servers = array(), $options = array())
  36. {
  37. // build this array here instead of as a class variable since the constants are only defined if the extension
  38. // exists
  39. $memOptions = array('COMPRESSION',
  40. 'SERIALIZER',
  41. 'PREFIX_KEY',
  42. 'HASH',
  43. 'DISTRIBUTION',
  44. 'LIBKETAMA_COMPATIBLE',
  45. 'BUFFER_WRITES',
  46. 'BINARY_PROTOCOL',
  47. 'NO_BLOCK',
  48. 'TCP_NODELAY',
  49. 'SOCKET_SEND_SIZE',
  50. 'SOCKET_RECV_SIZE',
  51. 'CONNECT_TIMEOUT',
  52. 'RETRY_TIMEOUT',
  53. 'SEND_TIMEOUT',
  54. 'RECV_TIMEOUT',
  55. 'POLL_TIMEOUT',
  56. 'CACHE_LOOKUPS',
  57. 'SERVER_FAILURE_LIMIT',
  58. 'CLIENT_MODE'
  59. );
  60. $memcached = new \Memcached();
  61. $serverList = $memcached->getServerList();
  62. if (empty($serverList)) {
  63. $memcached->addServers($servers);
  64. }
  65. foreach ($options as $name => $value) {
  66. $name = strtoupper($name);
  67. if (!in_array($name, $memOptions) || !defined('\Memcached::OPT_' . $name)) {
  68. continue;
  69. }
  70. switch ($name) {
  71. case 'HASH':
  72. $value = strtoupper($value);
  73. if (!defined('\Memcached::HASH_' . $value)) {
  74. throw new RuntimeException('Memcached option ' . $name . ' requires valid memcache hash option value');
  75. }
  76. $value = constant('\Memcached::HASH_' . $value);
  77. break;
  78. case 'DISTRIBUTION':
  79. $value = strtoupper($value);
  80. if (!defined('\Memcached::DISTRIBUTION_' . $value)) {
  81. throw new RuntimeException('Memcached option ' . $name . ' requires valid memcache distribution option value');
  82. }
  83. $value = constant('\Memcached::DISTRIBUTION_' . $value);
  84. break;
  85. case 'SERIALIZER':
  86. $value = strtoupper($value);
  87. if (!defined('\Memcached::SERIALIZER_' . $value)) {
  88. throw new RuntimeException('Memcached option ' . $name . ' requires valid memcache serializer option value');
  89. }
  90. $value = constant('\Memcached::SERIALIZER_' . $value);
  91. break;
  92. case 'SOCKET_SEND_SIZE':
  93. case 'SOCKET_RECV_SIZE':
  94. case 'CONNECT_TIMEOUT':
  95. case 'RETRY_TIMEOUT':
  96. case 'SEND_TIMEOUT':
  97. case 'RECV_TIMEOUT':
  98. case 'POLL_TIMEOUT':
  99. case 'SERVER_FAILURE_LIMIT':
  100. if (!is_numeric($value)) {
  101. throw new RuntimeException('Memcached option ' . $name . ' requires numeric value');
  102. }
  103. break;
  104. case 'PREFIX_KEY':
  105. if (!is_string($value)) {
  106. throw new RuntimeException('Memcached option ' . $name . ' requires string value');
  107. }
  108. break;
  109. case 'COMPRESSION':
  110. case 'LIBKETAMA_COMPATIBLE':
  111. case 'BUFFER_WRITES':
  112. case 'BINARY_PROTOCOL':
  113. case 'NO_BLOCK':
  114. case 'TCP_NODELAY':
  115. case 'CACHE_LOOKUPS':
  116. if (!is_bool($value)) {
  117. throw new RuntimeException('Memcached option ' . $name . ' requires boolean value');
  118. }
  119. break;
  120. }
  121. if (!@$memcached->setOption(constant('\Memcached::OPT_' . $name), $value)) {
  122. throw new RuntimeException('Memcached option Memcached::OPT_' . $name . ' not accepted by memcached extension.');
  123. }
  124. }
  125. $this->memcached = $memcached;
  126. }
  127. /**
  128. * Stores the data in memcached.
  129. *
  130. * @param string $key
  131. * @param mixed $value
  132. * @param null|int $expire
  133. * @return bool
  134. */
  135. public function set($key, $value, $expire = null)
  136. {
  137. if (isset($expire) && $expire < time()) {
  138. return true;
  139. }
  140. return $this->memcached->set($key, array('data' => $value, 'expiration' => $expire), $expire);
  141. }
  142. /**
  143. * Retrieves the data from memcached.
  144. *
  145. * @param string $key
  146. * @return mixed
  147. */
  148. public function get($key)
  149. {
  150. $value = $this->memcached->get($key);
  151. if ($value === false && $this->memcached->getResultCode() == \Memcached::RES_NOTFOUND) {
  152. return false;
  153. }
  154. return $value;
  155. }
  156. /**
  157. * This function emulates runs the cas memcache functionlity.
  158. *
  159. * @param string $key
  160. * @param mixed $value
  161. * @return mixed
  162. */
  163. public function cas($key, $value)
  164. {
  165. $token = null;
  166. if (($rValue = $this->memcached->get($key, null, $token)) !== false) {
  167. return $rValue;
  168. }
  169. if ($this->memcached->getResultCode() === \Memcached::RES_NOTFOUND) {
  170. $this->memcached->add($key, $value);
  171. } else {
  172. $this->memcached->cas($token, $key, $value);
  173. }
  174. return $value;
  175. }
  176. /**
  177. * Increments the key and returns the new value.
  178. *
  179. * @param $key
  180. * @return int
  181. */
  182. public function inc($key)
  183. {
  184. $this->cas($key, 0);
  185. return $this->memcached->increment($key);
  186. }
  187. /**
  188. * Flushes memcached.
  189. */
  190. public function flush()
  191. {
  192. $this->memcached->flush();
  193. }
  194. /**
  195. * Returns true if the Memcached extension is installed.
  196. *
  197. * @return bool
  198. */
  199. public static function isAvailable()
  200. {
  201. return class_exists('Memcached', false);
  202. }
  203. }