public function getMountsForUser(IUser $user, IStorageFactory $loader) {
$this->migrator->migrateUser($user);
- $mounts = [];
-
$this->userStoragesService->setUser($user);
$this->userGlobalStoragesService->setUser($user);
- foreach ($this->userGlobalStoragesService->getAllStoragesForUser() as $storage) {
+ $storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUser();
+
+ $storages = array_map(function(StorageConfig $storageConfig) use ($user) {
try {
- $this->prepareStorageConfig($storage, $user);
- $impl = $this->constructStorage($storage);
+ $this->prepareStorageConfig($storageConfig, $user);
+ return $this->constructStorage($storageConfig);
} catch (\Exception $e) {
// propagate exception into filesystem
- $impl = new FailedStorage(['exception' => $e]);
+ return new FailedStorage(['exception' => $e]);
}
+ }, $storageConfigs);
+
+ \OC\Files\Cache\Storage::getGlobalCache()->loadForStorageIds(array_map(function(Storage\IStorage $storage) {
+ return $storage->getId();
+ }, $storages));
+
+ $availableStorages = array_map(function (Storage\IStorage $storage, StorageConfig $storageConfig) {
try {
- $availability = $impl->getAvailability();
+ $availability = $storage->getAvailability();
if (!$availability['available'] && !Availability::shouldRecheck($availability)) {
- $impl = new FailedStorage([
- 'exception' => new StorageNotAvailableException('Storage with mount id ' . $storage->getId() . ' is not available')
+ $storage = new FailedStorage([
+ 'exception' => new StorageNotAvailableException('Storage with mount id ' . $storageConfig->getId() . ' is not available')
]);
}
} catch (\Exception $e) {
// propagate exception into filesystem
- $impl = new FailedStorage(['exception' => $e]);
+ $storage = new FailedStorage(['exception' => $e]);
}
+ return $storage;
+ }, $storages, $storageConfigs);
- if ($storage->getType() === StorageConfig::MOUNT_TYPE_PERSONAl) {
- $mount = new PersonalMount(
+ $mounts = array_map(function(StorageConfig $storageConfig, Storage\IStorage $storage) use ($user, $loader) {
+ if ($storageConfig->getType() === StorageConfig::MOUNT_TYPE_PERSONAl) {
+ return new PersonalMount(
$this->userStoragesService,
- $storage->getId(),
- $impl,
- '/' . $user->getUID() . '/files' . $storage->getMountPoint(),
+ $storageConfig->getId(),
+ $storage,
+ '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
null,
$loader,
- $storage->getMountOptions()
+ $storageConfig->getMountOptions()
);
} else {
- $mount = new MountPoint(
- $impl,
- '/' . $user->getUID() . '/files' . $storage->getMountPoint(),
+ return new MountPoint(
+ $storage,
+ '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
null,
$loader,
- $storage->getMountOptions(),
- $storage->getId()
+ $storageConfig->getMountOptions(),
+ $storageConfig->getId()
);
}
- $mounts[$storage->getMountPoint()] = $mount;
- }
+ }, $storageConfigs, $availableStorages);
$this->userStoragesService->resetUser();
$this->userGlobalStoragesService->resetUser();
self::resetStorage();
\OC_Util::tearDownFS();
+ \OC\Files\Cache\Storage::getGlobalCache()->clearCache();
\OC::$server->getUserSession()->setUser(null);
\OC\Files\Filesystem::tearDown();
\OC::$server->getUserSession()->login($user, $password);
'OC\\Files\\Cache\\Propagator' => $baseDir . '/lib/private/Files/Cache/Propagator.php',
'OC\\Files\\Cache\\Scanner' => $baseDir . '/lib/private/Files/Cache/Scanner.php',
'OC\\Files\\Cache\\Storage' => $baseDir . '/lib/private/Files/Cache/Storage.php',
+ 'OC\\Files\\Cache\\StorageGlobal' => $baseDir . '/lib/private/Files/Cache/StorageGlobal.php',
'OC\\Files\\Cache\\Updater' => $baseDir . '/lib/private/Files/Cache/Updater.php',
'OC\\Files\\Cache\\Watcher' => $baseDir . '/lib/private/Files/Cache/Watcher.php',
'OC\\Files\\Cache\\Wrapper\\CacheJail' => $baseDir . '/lib/private/Files/Cache/Wrapper/CacheJail.php',
'OC\\Files\\Cache\\Propagator' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Propagator.php',
'OC\\Files\\Cache\\Scanner' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Scanner.php',
'OC\\Files\\Cache\\Storage' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Storage.php',
+ 'OC\\Files\\Cache\\StorageGlobal' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/StorageGlobal.php',
'OC\\Files\\Cache\\Updater' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Updater.php',
'OC\\Files\\Cache\\Watcher' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Watcher.php',
'OC\\Files\\Cache\\Wrapper\\CacheJail' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Wrapper/CacheJail.php',
* @package OC\Files\Cache
*/
class Storage {
+ /** @var StorageGlobal|null */
+ private static $globalCache = null;
private $storageId;
private $numericId;
+ /**
+ * @return StorageGlobal
+ */
+ public static function getGlobalCache() {
+ if (is_null(self::$globalCache)) {
+ self::$globalCache = new StorageGlobal(\OC::$server->getDatabaseConnection());
+ }
+ return self::$globalCache;
+ }
+
/**
* @param \OC\Files\Storage\Storage|string $storage
* @param bool $isAvailable
/**
* @param string $storageId
- * @return array|null
+ * @return array
*/
public static function getStorageById($storageId) {
- $sql = 'SELECT * FROM `*PREFIX*storages` WHERE `id` = ?';
- $result = \OC_DB::executeAudited($sql, array($storageId));
- return $result->fetchRow();
+ return self::getGlobalCache()->getStorageInfo($storageId);
}
/**
--- /dev/null
+<?php
+/**
+ * @copyright Robin Appelman <robin@icewind.nl>
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Cache;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\Mount\IMountPoint;
+use OCP\IDBConnection;
+
+/**
+ * Handle the mapping between the string and numeric storage ids
+ *
+ * Each storage has 2 different ids
+ * a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share')
+ * and a numeric storage id which is referenced in the file cache
+ *
+ * A mapping between the two storage ids is stored in the database and accessible trough this class
+ *
+ * @package OC\Files\Cache
+ */
+class StorageGlobal {
+ /** @var IDBConnection */
+ private $connection;
+
+ /** @var array[] */
+ private $cache = [];
+
+ public function __construct(IDBConnection $connection) {
+ $this->connection = $connection;
+ }
+
+ /**
+ * @param string[] $storageIds
+ */
+ public function loadForStorageIds(array $storageIds) {
+ $builder = $this->connection->getQueryBuilder();
+ $query = $builder->select(['id', 'numeric_id', 'available', 'last_checked'])
+ ->from('storages')
+ ->where($builder->expr()->in('id', $builder->createNamedParameter(array_values($storageIds), IQueryBuilder::PARAM_STR_ARRAY)));
+
+ $result = $query->execute();
+ while ($row = $result->fetch()) {
+ $this->cache[$row['id']] = $row;
+ }
+ }
+
+ /**
+ * @param string $storageId
+ * @return array|null
+ */
+ public function getStorageInfo($storageId) {
+ if (!isset($this->cache[$storageId])) {
+ $this->loadForStorageIds([$storageId]);
+ }
+ return isset($this->cache[$storageId]) ? $this->cache[$storageId] : null;
+ }
+
+ public function clearCache() {
+ $this->cache = [];
+ }
+}
$this->connection->commit();
+ Storage::getGlobalCache()->clearCache();
+
if ($hasWarnings) {
$out->warning('Some legacy storages could not be repaired. Please manually fix them then re-run ./occ maintenance:repair');
} else {
libxml_clear_errors();
$this->assertEquals([], $errors);
+ \OC\Files\Cache\Storage::getGlobalCache()->clearCache();
+
// tearDown the traits
$traits = $this->getTestTraits();
foreach ($traits as $trait) {