ObjectStorePreviewCacheMountProvider.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Files\Mount;
  8. use OC\Files\ObjectStore\AppdataPreviewObjectStoreStorage;
  9. use OC\Files\ObjectStore\ObjectStoreStorage;
  10. use OC\Files\Storage\Wrapper\Jail;
  11. use OCP\Files\Config\IRootMountProvider;
  12. use OCP\Files\Storage\IStorageFactory;
  13. use OCP\IConfig;
  14. use Psr\Log\LoggerInterface;
  15. /**
  16. * Mount provider for object store app data folder for previews
  17. */
  18. class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
  19. private LoggerInterface $logger;
  20. /** @var IConfig */
  21. private $config;
  22. public function __construct(LoggerInterface $logger, IConfig $config) {
  23. $this->logger = $logger;
  24. $this->config = $config;
  25. }
  26. /**
  27. * @return MountPoint[]
  28. * @throws \Exception
  29. */
  30. public function getRootMounts(IStorageFactory $loader): array {
  31. if (!is_array($this->config->getSystemValue('objectstore_multibucket'))) {
  32. return [];
  33. }
  34. if ($this->config->getSystemValue('objectstore.multibucket.preview-distribution', false) !== true) {
  35. return [];
  36. }
  37. $instanceId = $this->config->getSystemValueString('instanceid', '');
  38. $mountPoints = [];
  39. $directoryRange = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
  40. $i = 0;
  41. foreach ($directoryRange as $parent) {
  42. foreach ($directoryRange as $child) {
  43. $mountPoints[] = new MountPoint(
  44. AppdataPreviewObjectStoreStorage::class,
  45. '/appdata_' . $instanceId . '/preview/' . $parent . '/' . $child,
  46. $this->getMultiBucketObjectStore($i),
  47. $loader,
  48. null,
  49. null,
  50. self::class
  51. );
  52. $i++;
  53. }
  54. }
  55. $rootStorageArguments = $this->getMultiBucketObjectStoreForRoot();
  56. $fakeRootStorage = new ObjectStoreStorage($rootStorageArguments);
  57. $fakeRootStorageJail = new Jail([
  58. 'storage' => $fakeRootStorage,
  59. 'root' => '/appdata_' . $instanceId . '/preview',
  60. ]);
  61. // add a fallback location to be able to fetch existing previews from the old bucket
  62. $mountPoints[] = new MountPoint(
  63. $fakeRootStorageJail,
  64. '/appdata_' . $instanceId . '/preview/old-multibucket',
  65. null,
  66. $loader,
  67. null,
  68. null,
  69. self::class
  70. );
  71. return $mountPoints;
  72. }
  73. protected function getMultiBucketObjectStore(int $number): array {
  74. $config = $this->config->getSystemValue('objectstore_multibucket');
  75. // sanity checks
  76. if (empty($config['class'])) {
  77. $this->logger->error('No class given for objectstore', ['app' => 'files']);
  78. }
  79. if (!isset($config['arguments'])) {
  80. $config['arguments'] = [];
  81. }
  82. /*
  83. * Use any provided bucket argument as prefix
  84. * and add the mapping from parent/child => bucket
  85. */
  86. if (!isset($config['arguments']['bucket'])) {
  87. $config['arguments']['bucket'] = '';
  88. }
  89. $config['arguments']['bucket'] .= "-preview-$number";
  90. // instantiate object store implementation
  91. $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
  92. $config['arguments']['internal-id'] = $number;
  93. return $config['arguments'];
  94. }
  95. protected function getMultiBucketObjectStoreForRoot(): array {
  96. $config = $this->config->getSystemValue('objectstore_multibucket');
  97. // sanity checks
  98. if (empty($config['class'])) {
  99. $this->logger->error('No class given for objectstore', ['app' => 'files']);
  100. }
  101. if (!isset($config['arguments'])) {
  102. $config['arguments'] = [];
  103. }
  104. /*
  105. * Use any provided bucket argument as prefix
  106. * and add the mapping from parent/child => bucket
  107. */
  108. if (!isset($config['arguments']['bucket'])) {
  109. $config['arguments']['bucket'] = '';
  110. }
  111. $config['arguments']['bucket'] .= '0';
  112. // instantiate object store implementation
  113. $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
  114. return $config['arguments'];
  115. }
  116. }