Skip to content

Commit

Permalink
Merge pull request #38023 from nextcloud/backport/32877/stable26
Browse files Browse the repository at this point in the history
[stable26] allow storing multiple mounts for the same rootid in the mount cache
  • Loading branch information
blizzz authored Jun 15, 2023
2 parents 00afe49 + 7c85dfe commit 5f56610
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 18 deletions.
3 changes: 3 additions & 0 deletions core/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ function (GenericEvent $event) use ($container) {
if (!$table->hasIndex('mounts_class_index')) {
$subject->addHintForMissingSubject($table->getName(), 'mounts_class_index');
}
if (!$table->hasIndex('mounts_user_root_path_index')) {
$subject->addHintForMissingSubject($table->getName(), 'mounts_user_root_path_index');
}
}
}
);
Expand Down
8 changes: 8 additions & 0 deletions core/Command/Db/AddMissingIndices.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,14 @@ private function addCoreIndexes(OutputInterface $output, bool $dryRun): void {
$updated = true;
$output->writeln('<info>oc_mounts table updated successfully.</info>');
}
if (!$table->hasIndex('mounts_user_root_path_index')) {
$output->writeln('<info>Adding mounts_user_root_path_index index to the oc_mounts table, this can take some time...</info>');

$table->addIndex(['user_id', 'root_id', 'mount_point'], 'mounts_user_root_path_index', [], ['lengths' => [null, null, 128]]);
$this->connection->migrateToSchema($schema->getWrappedSchema());
$updated = true;
$output->writeln('<info>oc_mounts table updated successfully.</info>');
}
}

if (!$updated) {
Expand Down
2 changes: 1 addition & 1 deletion core/Migrations/Version13000Date20170718121200.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op
$table->addIndex(['storage_id'], 'mounts_storage_index');
$table->addIndex(['root_id'], 'mounts_root_index');
$table->addIndex(['mount_id'], 'mounts_mount_id_index');
$table->addUniqueIndex(['user_id', 'root_id'], 'mounts_user_root_index');
$table->addIndex(['user_id', 'root_id', 'mount_point'], 'mounts_user_root_path_index', [], ['lengths' => [null, null, 128]]);
} else {
$table = $schema->getTable('mounts');
$table->addColumn('mount_id', Types::BIGINT, [
Expand Down
51 changes: 51 additions & 0 deletions core/Migrations/Version27000Date20220613163520.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2022 Your name <[email protected]>
*
* @author Your name <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OC\Core\Migrations;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version27000Date20220613163520 extends SimpleMigrationStep {
public function name(): string {
return "Add mountpoint path to mounts table unique index";
}

public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

$table = $schema->getTable('mounts');
if ($table->hasIndex('mounts_user_root_index')) {
$table->dropIndex('mounts_user_root_index');
// new index gets added with "add missing indexes"
}

return $schema;
}
}
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@
'OC\\Core\\Migrations\\Version25000Date20220602190540' => $baseDir . '/core/Migrations/Version25000Date20220602190540.php',
'OC\\Core\\Migrations\\Version25000Date20220905140840' => $baseDir . '/core/Migrations/Version25000Date20220905140840.php',
'OC\\Core\\Migrations\\Version25000Date20221007010957' => $baseDir . '/core/Migrations/Version25000Date20221007010957.php',
'OC\\Core\\Migrations\\Version27000Date20220613163520' => $baseDir . '/core/Migrations/Version27000Date20220613163520.php',
'OC\\Core\\Migrations\\Version27000Date20230309104325' => $baseDir . '/core/Migrations/Version27000Date20230309104325.php',
'OC\\Core\\Migrations\\Version27000Date20230309104802' => $baseDir . '/core/Migrations/Version27000Date20230309104802.php',
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Migrations\\Version25000Date20220602190540' => __DIR__ . '/../../..' . '/core/Migrations/Version25000Date20220602190540.php',
'OC\\Core\\Migrations\\Version25000Date20220905140840' => __DIR__ . '/../../..' . '/core/Migrations/Version25000Date20220905140840.php',
'OC\\Core\\Migrations\\Version25000Date20221007010957' => __DIR__ . '/../../..' . '/core/Migrations/Version25000Date20221007010957.php',
'OC\\Core\\Migrations\\Version27000Date20220613163520' => __DIR__ . '/../../..' . '/core/Migrations/Version27000Date20220613163520.php',
'OC\\Core\\Migrations\\Version27000Date20230309104325' => __DIR__ . '/../../..' . '/core/Migrations/Version27000Date20230309104325.php',
'OC\\Core\\Migrations\\Version27000Date20230309104802' => __DIR__ . '/../../..' . '/core/Migrations/Version27000Date20230309104802.php',
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
Expand Down
36 changes: 19 additions & 17 deletions lib/private/Files/Config/UserMountCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,38 +92,39 @@ public function registerMounts(IUser $user, array $mounts, array $mountProviderC
}
}, $mounts);
$newMounts = array_values(array_filter($newMounts));
$newMountRootIds = array_map(function (ICachedMountInfo $mount) {
return $mount->getRootId();
$newMountKeys = array_map(function (ICachedMountInfo $mount) {
return $mount->getRootId() . '::' . $mount->getMountPoint();
}, $newMounts);
$newMounts = array_combine($newMountRootIds, $newMounts);
$newMounts = array_combine($newMountKeys, $newMounts);

$cachedMounts = $this->getMountsForUser($user);
if (is_array($mountProviderClasses)) {
$cachedMounts = array_filter($cachedMounts, function (ICachedMountInfo $mountInfo) use ($mountProviderClasses, $newMounts) {
// for existing mounts that didn't have a mount provider set
// we still want the ones that map to new mounts
if ($mountInfo->getMountProvider() === '' && isset($newMounts[$mountInfo->getRootId()])) {
$mountKey = $mountInfo->getRootId() . '::' . $mountInfo->getMountPoint();
if ($mountInfo->getMountProvider() === '' && isset($newMounts[$mountKey])) {
return true;
}
return in_array($mountInfo->getMountProvider(), $mountProviderClasses);
});
}
$cachedMountRootIds = array_map(function (ICachedMountInfo $mount) {
return $mount->getRootId();
$cachedRootKeys = array_map(function (ICachedMountInfo $mount) {
return $mount->getRootId() . '::' . $mount->getMountPoint();
}, $cachedMounts);
$cachedMounts = array_combine($cachedMountRootIds, $cachedMounts);
$cachedMounts = array_combine($cachedRootKeys, $cachedMounts);

$addedMounts = [];
$removedMounts = [];

foreach ($newMounts as $rootId => $newMount) {
if (!isset($cachedMounts[$rootId])) {
foreach ($newMounts as $mountKey => $newMount) {
if (!isset($cachedMounts[$mountKey])) {
$addedMounts[] = $newMount;
}
}

foreach ($cachedMounts as $rootId => $cachedMount) {
if (!isset($newMounts[$rootId])) {
foreach ($cachedMounts as $mountKey => $cachedMount) {
if (!isset($newMounts[$mountKey])) {
$removedMounts[] = $cachedMount;
}
}
Expand Down Expand Up @@ -154,13 +155,13 @@ public function registerMounts(IUser $user, array $mounts, array $mountProviderC
private function findChangedMounts(array $newMounts, array $cachedMounts) {
$new = [];
foreach ($newMounts as $mount) {
$new[$mount->getRootId()] = $mount;
$new[$mount->getRootId() . '::' . $mount->getMountPoint()] = $mount;
}
$changed = [];
foreach ($cachedMounts as $cachedMount) {
$rootId = $cachedMount->getRootId();
if (isset($new[$rootId])) {
$newMount = $new[$rootId];
$key = $cachedMount->getRootId() . '::' . $cachedMount->getMountPoint();
if (isset($new[$key])) {
$newMount = $new[$key];
if (
$newMount->getMountPoint() !== $cachedMount->getMountPoint() ||
$newMount->getStorageId() !== $cachedMount->getStorageId() ||
Expand All @@ -183,7 +184,7 @@ private function addToCache(ICachedMountInfo $mount) {
'mount_point' => $mount->getMountPoint(),
'mount_id' => $mount->getMountId(),
'mount_provider_class' => $mount->getMountProvider(),
], ['root_id', 'user_id']);
], ['root_id', 'user_id', 'mount_point']);
} else {
// in some cases this is legitimate, like orphaned shares
$this->logger->debug('Could not get storage info for mount at ' . $mount->getMountPoint());
Expand All @@ -209,7 +210,8 @@ private function removeFromCache(ICachedMountInfo $mount) {

$query = $builder->delete('mounts')
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)))
->andWhere($builder->expr()->eq('mount_point', $builder->createNamedParameter($mount->getMountPoint())));
$query->execute();
}

Expand Down

0 comments on commit 5f56610

Please sign in to comment.