Manager.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2016, ownCloud, Inc.
  5. *
  6. * @author Björn Schießle <bjoern@schiessle.org>
  7. * @author Morris Jobke <hey@morrisjobke.de>
  8. * @author Robin Appelman <robin@icewind.nl>
  9. * @author Robin McCorkell <robin@mccorkell.me.uk>
  10. * @author Roeland Jago Douma <roeland@famdouma.nl>
  11. *
  12. * @license AGPL-3.0
  13. *
  14. * This code is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License, version 3,
  16. * as published by the Free Software Foundation.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License, version 3,
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>
  25. *
  26. */
  27. namespace OC\Files\Mount;
  28. use OCP\Cache\CappedMemoryCache;
  29. use OC\Files\Filesystem;
  30. use OC\Files\SetupManager;
  31. use OC\Files\SetupManagerFactory;
  32. use OCP\Files\Mount\IMountManager;
  33. use OCP\Files\Mount\IMountPoint;
  34. use OCP\Files\NotFoundException;
  35. class Manager implements IMountManager {
  36. /** @var MountPoint[] */
  37. private array $mounts = [];
  38. /** @var CappedMemoryCache<IMountPoint> */
  39. private CappedMemoryCache $pathCache;
  40. /** @var CappedMemoryCache<IMountPoint[]> */
  41. private CappedMemoryCache $inPathCache;
  42. private SetupManager $setupManager;
  43. public function __construct(SetupManagerFactory $setupManagerFactory) {
  44. $this->pathCache = new CappedMemoryCache();
  45. $this->inPathCache = new CappedMemoryCache();
  46. $this->setupManager = $setupManagerFactory->create($this);
  47. }
  48. /**
  49. * @param IMountPoint $mount
  50. */
  51. public function addMount(IMountPoint $mount) {
  52. $this->mounts[$mount->getMountPoint()] = $mount;
  53. $this->pathCache->clear();
  54. $this->inPathCache->clear();
  55. }
  56. /**
  57. * @param string $mountPoint
  58. */
  59. public function removeMount(string $mountPoint) {
  60. $mountPoint = Filesystem::normalizePath($mountPoint);
  61. if (\strlen($mountPoint) > 1) {
  62. $mountPoint .= '/';
  63. }
  64. unset($this->mounts[$mountPoint]);
  65. $this->pathCache->clear();
  66. $this->inPathCache->clear();
  67. }
  68. /**
  69. * @param string $mountPoint
  70. * @param string $target
  71. */
  72. public function moveMount(string $mountPoint, string $target) {
  73. $this->mounts[$target] = $this->mounts[$mountPoint];
  74. unset($this->mounts[$mountPoint]);
  75. $this->pathCache->clear();
  76. $this->inPathCache->clear();
  77. }
  78. /**
  79. * Find the mount for $path
  80. *
  81. * @param string $path
  82. * @return IMountPoint
  83. */
  84. public function find(string $path): IMountPoint {
  85. $this->setupManager->setupForPath($path);
  86. $path = Filesystem::normalizePath($path);
  87. if (isset($this->pathCache[$path])) {
  88. return $this->pathCache[$path];
  89. }
  90. $current = $path;
  91. while (true) {
  92. $mountPoint = $current . '/';
  93. if (isset($this->mounts[$mountPoint])) {
  94. $this->pathCache[$path] = $this->mounts[$mountPoint];
  95. return $this->mounts[$mountPoint];
  96. } elseif ($current === '') {
  97. break;
  98. }
  99. $current = dirname($current);
  100. if ($current === '.' || $current === '/') {
  101. $current = '';
  102. }
  103. }
  104. throw new NotFoundException("No mount for path " . $path . " existing mounts: " . implode(",", array_keys($this->mounts)));
  105. }
  106. /**
  107. * Find all mounts in $path
  108. *
  109. * @param string $path
  110. * @return IMountPoint[]
  111. */
  112. public function findIn(string $path): array {
  113. $this->setupManager->setupForPath($path, true);
  114. $path = $this->formatPath($path);
  115. if (isset($this->inPathCache[$path])) {
  116. return $this->inPathCache[$path];
  117. }
  118. $result = [];
  119. $pathLength = \strlen($path);
  120. $mountPoints = array_keys($this->mounts);
  121. foreach ($mountPoints as $mountPoint) {
  122. if (substr($mountPoint, 0, $pathLength) === $path && \strlen($mountPoint) > $pathLength) {
  123. $result[] = $this->mounts[$mountPoint];
  124. }
  125. }
  126. $this->inPathCache[$path] = $result;
  127. return $result;
  128. }
  129. public function clear() {
  130. $this->mounts = [];
  131. $this->pathCache->clear();
  132. $this->inPathCache->clear();
  133. }
  134. /**
  135. * Find mounts by storage id
  136. *
  137. * @param string $id
  138. * @return IMountPoint[]
  139. */
  140. public function findByStorageId(string $id): array {
  141. if (\strlen($id) > 64) {
  142. $id = md5($id);
  143. }
  144. $result = [];
  145. foreach ($this->mounts as $mount) {
  146. if ($mount->getStorageId() === $id) {
  147. $result[] = $mount;
  148. }
  149. }
  150. return $result;
  151. }
  152. /**
  153. * @return IMountPoint[]
  154. */
  155. public function getAll(): array {
  156. return $this->mounts;
  157. }
  158. /**
  159. * Find mounts by numeric storage id
  160. *
  161. * @param int $id
  162. * @return IMountPoint[]
  163. */
  164. public function findByNumericId(int $id): array {
  165. $result = [];
  166. foreach ($this->mounts as $mount) {
  167. if ($mount->getNumericStorageId() === $id) {
  168. $result[] = $mount;
  169. }
  170. }
  171. return $result;
  172. }
  173. /**
  174. * @param string $path
  175. * @return string
  176. */
  177. private function formatPath(string $path): string {
  178. $path = Filesystem::normalizePath($path);
  179. if (\strlen($path) > 1) {
  180. $path .= '/';
  181. }
  182. return $path;
  183. }
  184. public function getSetupManager(): SetupManager {
  185. return $this->setupManager;
  186. }
  187. /**
  188. * Return all mounts in a path from a specific mount provider
  189. *
  190. * @param string $path
  191. * @param string[] $mountProviders
  192. * @return MountPoint[]
  193. */
  194. public function getMountsByMountProvider(string $path, array $mountProviders) {
  195. $this->getSetupManager()->setupForProvider($path, $mountProviders);
  196. if (in_array('', $mountProviders)) {
  197. return $this->mounts;
  198. } else {
  199. return array_filter($this->mounts, function ($mount) use ($mountProviders) {
  200. return in_array($mount->getMountProvider(), $mountProviders);
  201. });
  202. }
  203. }
  204. }