You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.4 KiB

3 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Andreas Fischer <bantu@owncloud.com>
  6. * @author Bart Visscher <bartv@thisnet.nl>
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Joas Schilling <coding@schilljs.com>
  9. * @author Lukas Reschke <lukas@statuscode.ch>
  10. * @author Morris Jobke <hey@morrisjobke.de>
  11. * @author Robin Appelman <robin@icewind.nl>
  12. *
  13. * @license AGPL-3.0
  14. *
  15. * This code is free software: you can redistribute it and/or modify
  16. * it under the terms of the GNU Affero General Public License, version 3,
  17. * as published by the Free Software Foundation.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU Affero General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Affero General Public License, version 3,
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>
  26. *
  27. */
  28. namespace OC\Memcache;
  29. use bantu\IniGetWrapper\IniGetWrapper;
  30. use OCP\IMemcache;
  31. class APCu extends Cache implements IMemcache {
  32. use CASTrait {
  33. cas as casEmulated;
  34. }
  35. use CADTrait;
  36. public function get($key) {
  37. $result = apcu_fetch($this->getPrefix() . $key, $success);
  38. if (!$success) {
  39. return null;
  40. }
  41. return $result;
  42. }
  43. public function set($key, $value, $ttl = 0) {
  44. return apcu_store($this->getPrefix() . $key, $value, $ttl);
  45. }
  46. public function hasKey($key) {
  47. return apcu_exists($this->getPrefix() . $key);
  48. }
  49. public function remove($key) {
  50. return apcu_delete($this->getPrefix() . $key);
  51. }
  52. public function clear($prefix = '') {
  53. $ns = $this->getPrefix() . $prefix;
  54. $ns = preg_quote($ns, '/');
  55. if (class_exists('\APCIterator')) {
  56. $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY);
  57. } else {
  58. $iter = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY);
  59. }
  60. return apcu_delete($iter);
  61. }
  62. /**
  63. * Set a value in the cache if it's not already stored
  64. *
  65. * @param string $key
  66. * @param mixed $value
  67. * @param int $ttl Time To Live in seconds. Defaults to 60*60*24
  68. * @return bool
  69. */
  70. public function add($key, $value, $ttl = 0) {
  71. return apcu_add($this->getPrefix() . $key, $value, $ttl);
  72. }
  73. /**
  74. * Increase a stored number
  75. *
  76. * @param string $key
  77. * @param int $step
  78. * @return int | bool
  79. */
  80. public function inc($key, $step = 1) {
  81. $this->add($key, 0);
  82. /**
  83. * TODO - hack around a PHP 7 specific issue in APCu
  84. *
  85. * on PHP 7 the apcu_inc method on a non-existing object will increment
  86. * "0" and result in "1" as value - therefore we check for existence
  87. * first
  88. *
  89. * on PHP 5.6 this is not the case
  90. *
  91. * see https://github.com/krakjoe/apcu/issues/183#issuecomment-244038221
  92. * for details
  93. */
  94. return apcu_exists($this->getPrefix() . $key)
  95. ? apcu_inc($this->getPrefix() . $key, $step)
  96. : false;
  97. }
  98. /**
  99. * Decrease a stored number
  100. *
  101. * @param string $key
  102. * @param int $step
  103. * @return int | bool
  104. */
  105. public function dec($key, $step = 1) {
  106. /**
  107. * TODO - hack around a PHP 7 specific issue in APCu
  108. *
  109. * on PHP 7 the apcu_dec method on a non-existing object will decrement
  110. * "0" and result in "-1" as value - therefore we check for existence
  111. * first
  112. *
  113. * on PHP 5.6 this is not the case
  114. *
  115. * see https://github.com/krakjoe/apcu/issues/183#issuecomment-244038221
  116. * for details
  117. */
  118. return apcu_exists($this->getPrefix() . $key)
  119. ? apcu_dec($this->getPrefix() . $key, $step)
  120. : false;
  121. }
  122. /**
  123. * Compare and set
  124. *
  125. * @param string $key
  126. * @param mixed $old
  127. * @param mixed $new
  128. * @return bool
  129. */
  130. public function cas($key, $old, $new) {
  131. // apc only does cas for ints
  132. if (is_int($old) and is_int($new)) {
  133. return apcu_cas($this->getPrefix() . $key, $old, $new);
  134. } else {
  135. return $this->casEmulated($key, $old, $new);
  136. }
  137. }
  138. /**
  139. * @return bool
  140. */
  141. public static function isAvailable() {
  142. if (!extension_loaded('apcu')) {
  143. return false;
  144. } elseif (!\OC::$server->get(IniGetWrapper::class)->getBool('apc.enabled')) {
  145. return false;
  146. } elseif (!\OC::$server->get(IniGetWrapper::class)->getBool('apc.enable_cli') && \OC::$CLI) {
  147. return false;
  148. } elseif (
  149. version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 &&
  150. version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1
  151. ) {
  152. return false;
  153. } else {
  154. return true;
  155. }
  156. }
  157. }