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.

194 lines
5.4 KiB

3 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Lukas Reschke <lukas@statuscode.ch>
  8. * @author Markus Goetz <markus@woboq.com>
  9. * @author Morris Jobke <hey@morrisjobke.de>
  10. * @author Robin Appelman <robin@icewind.nl>
  11. * @author Robin McCorkell <robin@mccorkell.me.uk>
  12. * @author Roeland Jago Douma <roeland@famdouma.nl>
  13. * @author Stefan Weil <sw@weilnetz.de>
  14. * @author Vincent Petry <pvince81@owncloud.com>
  15. *
  16. * @license AGPL-3.0
  17. *
  18. * This code is free software: you can redistribute it and/or modify
  19. * it under the terms of the GNU Affero General Public License, version 3,
  20. * as published by the Free Software Foundation.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU Affero General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU Affero General Public License, version 3,
  28. * along with this program. If not, see <http://www.gnu.org/licenses/>
  29. *
  30. */
  31. namespace OC\Memcache;
  32. use OCP\ICache;
  33. use OCP\ICacheFactory;
  34. use OCP\ILogger;
  35. use OCP\IMemcache;
  36. class Factory implements ICacheFactory {
  37. public const NULL_CACHE = NullCache::class;
  38. /**
  39. * @var string $globalPrefix
  40. */
  41. private $globalPrefix;
  42. /**
  43. * @var ILogger $logger
  44. */
  45. private $logger;
  46. /**
  47. * @var string $localCacheClass
  48. */
  49. private $localCacheClass;
  50. /**
  51. * @var string $distributedCacheClass
  52. */
  53. private $distributedCacheClass;
  54. /**
  55. * @var string $lockingCacheClass
  56. */
  57. private $lockingCacheClass;
  58. /**
  59. * @param string $globalPrefix
  60. * @param ILogger $logger
  61. * @param string|null $localCacheClass
  62. * @param string|null $distributedCacheClass
  63. * @param string|null $lockingCacheClass
  64. */
  65. public function __construct(string $globalPrefix, ILogger $logger,
  66. $localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null) {
  67. $this->logger = $logger;
  68. $this->globalPrefix = $globalPrefix;
  69. if (!$localCacheClass) {
  70. $localCacheClass = self::NULL_CACHE;
  71. }
  72. if (!$distributedCacheClass) {
  73. $distributedCacheClass = $localCacheClass;
  74. }
  75. $missingCacheMessage = 'Memcache {class} not available for {use} cache';
  76. $missingCacheHint = 'Is the matching PHP module installed and enabled?';
  77. if (!class_exists($localCacheClass) || !$localCacheClass::isAvailable()) {
  78. if (\OC::$CLI && !defined('PHPUNIT_RUN')) {
  79. // CLI should not hard-fail on broken memcache
  80. $this->logger->info($missingCacheMessage, [
  81. 'class' => $localCacheClass,
  82. 'use' => 'local',
  83. 'app' => 'cli'
  84. ]);
  85. $localCacheClass = self::NULL_CACHE;
  86. } else {
  87. throw new \OC\HintException(strtr($missingCacheMessage, [
  88. '{class}' => $localCacheClass, '{use}' => 'local'
  89. ]), $missingCacheHint);
  90. }
  91. }
  92. if (!class_exists($distributedCacheClass) || !$distributedCacheClass::isAvailable()) {
  93. if (\OC::$CLI && !defined('PHPUNIT_RUN')) {
  94. // CLI should not hard-fail on broken memcache
  95. $this->logger->info($missingCacheMessage, [
  96. 'class' => $distributedCacheClass,
  97. 'use' => 'distributed',
  98. 'app' => 'cli'
  99. ]);
  100. $distributedCacheClass = self::NULL_CACHE;
  101. } else {
  102. throw new \OC\HintException(strtr($missingCacheMessage, [
  103. '{class}' => $distributedCacheClass, '{use}' => 'distributed'
  104. ]), $missingCacheHint);
  105. }
  106. }
  107. if (!($lockingCacheClass && class_exists($distributedCacheClass) && $lockingCacheClass::isAvailable())) {
  108. // don't fallback since the fallback might not be suitable for storing lock
  109. $lockingCacheClass = self::NULL_CACHE;
  110. }
  111. $this->localCacheClass = $localCacheClass;
  112. $this->distributedCacheClass = $distributedCacheClass;
  113. $this->lockingCacheClass = $lockingCacheClass;
  114. }
  115. /**
  116. * create a cache instance for storing locks
  117. *
  118. * @param string $prefix
  119. * @return IMemcache
  120. */
  121. public function createLocking(string $prefix = ''): IMemcache {
  122. return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix);
  123. }
  124. /**
  125. * create a distributed cache instance
  126. *
  127. * @param string $prefix
  128. * @return ICache
  129. */
  130. public function createDistributed(string $prefix = ''): ICache {
  131. return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix);
  132. }
  133. /**
  134. * create a local cache instance
  135. *
  136. * @param string $prefix
  137. * @return ICache
  138. */
  139. public function createLocal(string $prefix = ''): ICache {
  140. return new $this->localCacheClass($this->globalPrefix . '/' . $prefix);
  141. }
  142. /**
  143. * @see \OC\Memcache\Factory::createDistributed()
  144. * @param string $prefix
  145. * @return ICache
  146. * @deprecated 13.0.0 Use either createLocking, createDistributed or createLocal
  147. */
  148. public function create(string $prefix = ''): ICache {
  149. return $this->createDistributed($prefix);
  150. }
  151. /**
  152. * check memcache availability
  153. *
  154. * @return bool
  155. */
  156. public function isAvailable(): bool {
  157. return ($this->distributedCacheClass !== self::NULL_CACHE);
  158. }
  159. /**
  160. * @see \OC\Memcache\Factory::createLocal()
  161. * @param string $prefix
  162. * @return ICache
  163. */
  164. public function createLowLatency(string $prefix = ''): ICache {
  165. return $this->createLocal($prefix);
  166. }
  167. /**
  168. * Check if a local memory cache backend is available
  169. *
  170. * @return bool
  171. */
  172. public function isLocalCacheAvailable(): bool {
  173. return ($this->localCacheClass !== self::NULL_CACHE);
  174. }
  175. }