ObjectStorePreviewCacheMountProvider.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2020, Morris Jobke <hey@morrisjobke.de>
  5. *
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OC\Files\Mount;
  25. use OC\Files\ObjectStore\AppdataPreviewObjectStoreStorage;
  26. use OC\Files\ObjectStore\ObjectStoreStorage;
  27. use OC\Files\Storage\Wrapper\Jail;
  28. use OCP\Files\Config\IRootMountProvider;
  29. use OCP\Files\Storage\IStorageFactory;
  30. use OCP\IConfig;
  31. use Psr\Log\LoggerInterface;
  32. /**
  33. * Mount provider for object store app data folder for previews
  34. */
  35. class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
  36. private LoggerInterface $logger;
  37. /** @var IConfig */
  38. private $config;
  39. public function __construct(LoggerInterface $logger, IConfig $config) {
  40. $this->logger = $logger;
  41. $this->config = $config;
  42. }
  43. /**
  44. * @return MountPoint[]
  45. * @throws \Exception
  46. */
  47. public function getRootMounts(IStorageFactory $loader): array {
  48. if (!is_array($this->config->getSystemValue('objectstore_multibucket'))) {
  49. return [];
  50. }
  51. if ($this->config->getSystemValue('objectstore.multibucket.preview-distribution', false) !== true) {
  52. return [];
  53. }
  54. $instanceId = $this->config->getSystemValueString('instanceid', '');
  55. $mountPoints = [];
  56. $directoryRange = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
  57. $i = 0;
  58. foreach ($directoryRange as $parent) {
  59. foreach ($directoryRange as $child) {
  60. $mountPoints[] = new MountPoint(
  61. AppdataPreviewObjectStoreStorage::class,
  62. '/appdata_' . $instanceId . '/preview/' . $parent . '/' . $child,
  63. $this->getMultiBucketObjectStore($i),
  64. $loader,
  65. null,
  66. null,
  67. self::class
  68. );
  69. $i++;
  70. }
  71. }
  72. $rootStorageArguments = $this->getMultiBucketObjectStoreForRoot();
  73. $fakeRootStorage = new ObjectStoreStorage($rootStorageArguments);
  74. $fakeRootStorageJail = new Jail([
  75. 'storage' => $fakeRootStorage,
  76. 'root' => '/appdata_' . $instanceId . '/preview',
  77. ]);
  78. // add a fallback location to be able to fetch existing previews from the old bucket
  79. $mountPoints[] = new MountPoint(
  80. $fakeRootStorageJail,
  81. '/appdata_' . $instanceId . '/preview/old-multibucket',
  82. null,
  83. $loader,
  84. null,
  85. null,
  86. self::class
  87. );
  88. return $mountPoints;
  89. }
  90. protected function getMultiBucketObjectStore(int $number): array {
  91. $config = $this->config->getSystemValue('objectstore_multibucket');
  92. // sanity checks
  93. if (empty($config['class'])) {
  94. $this->logger->error('No class given for objectstore', ['app' => 'files']);
  95. }
  96. if (!isset($config['arguments'])) {
  97. $config['arguments'] = [];
  98. }
  99. /*
  100. * Use any provided bucket argument as prefix
  101. * and add the mapping from parent/child => bucket
  102. */
  103. if (!isset($config['arguments']['bucket'])) {
  104. $config['arguments']['bucket'] = '';
  105. }
  106. $config['arguments']['bucket'] .= "-preview-$number";
  107. // instantiate object store implementation
  108. $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
  109. $config['arguments']['internal-id'] = $number;
  110. return $config['arguments'];
  111. }
  112. protected function getMultiBucketObjectStoreForRoot(): array {
  113. $config = $this->config->getSystemValue('objectstore_multibucket');
  114. // sanity checks
  115. if (empty($config['class'])) {
  116. $this->logger->error('No class given for objectstore', ['app' => 'files']);
  117. }
  118. if (!isset($config['arguments'])) {
  119. $config['arguments'] = [];
  120. }
  121. /*
  122. * Use any provided bucket argument as prefix
  123. * and add the mapping from parent/child => bucket
  124. */
  125. if (!isset($config['arguments']['bucket'])) {
  126. $config['arguments']['bucket'] = '';
  127. }
  128. $config['arguments']['bucket'] .= '0';
  129. // instantiate object store implementation
  130. $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
  131. return $config['arguments'];
  132. }
  133. }