Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
occ files:scan --all --repair repairs all storages at once
This instead of iterating over all storages which is way less efficient
due to the 1-N nature of potential failed cross-storage moves that we
are repairing.

If singleuser mode is enabled and "--all --repair" is passed, all
storages will be repaired in bulk (no repair filter). If not, it will
fall back to iterating over each storage which is slower.
  • Loading branch information
Vincent Petry authored and tomneedham committed Sep 17, 2017
commit dfaece327469a29cf49ef39562be4e2160cff6fd
43 changes: 40 additions & 3 deletions apps/files/lib/Command/Scan.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
use OCP\Files\IMimeTypeLoader;
use OCP\IConfig;

class Scan extends Base {

Expand All @@ -53,6 +54,8 @@ class Scan extends Base {
private $lockingProvider;
/** @var IMimeTypeLoader */
private $mimeTypeLoader;
/** @var IConfig */
private $config;
/** @var float */
protected $execTime = 0;
/** @var int */
Expand All @@ -63,11 +66,13 @@ class Scan extends Base {
public function __construct(
IUserManager $userManager,
ILockingProvider $lockingProvider,
IMimeTypeLoader $mimeTypeLoader
IMimeTypeLoader $mimeTypeLoader,
IConfig $config
) {
$this->userManager = $userManager;
$this->lockingProvider = $lockingProvider;
$this->mimeTypeLoader = $mimeTypeLoader;
$this->config = $config;
parent::__construct();
}

Expand Down Expand Up @@ -128,6 +133,22 @@ public function checkScanWarning($fullPath, OutputInterface $output) {
}
}

/**
* Repair all storages at once
*
* @param OutputInterface $output
*/
protected function repairAll(OutputInterface $output) {
$connection = $this->reconnectToDatabase($output);
$repairStep = new RepairMismatchFileCachePath(
$connection,
$this->mimeTypeLoader
);
$repairStep->setStorageNumericId(null);
$repairStep->setCountOnly(false);
$repairStep->run(new ConsoleOutput($output));
}

protected function scanFiles($user, $path, $verbose, OutputInterface $output, $backgroundScan = false, $shouldRepair = false) {
$connection = $this->reconnectToDatabase($output);
$scanner = new \OC\Files\Utils\Scanner($user, $connection, \OC::$server->getLogger());
Expand All @@ -143,7 +164,7 @@ protected function scanFiles($user, $path, $verbose, OutputInterface $output, $b
try {
$repairStep = new RepairMismatchFileCachePath(
$connection,
$mimeTypeLoader
$this->mimeTypeLoader
);
$repairStep->setStorageNumericId($storage->getCache()->getNumericStorageId());
$repairStep->setCountOnly(false);
Expand Down Expand Up @@ -217,11 +238,27 @@ protected function scanFiles($user, $path, $verbose, OutputInterface $output, $b

protected function execute(InputInterface $input, OutputInterface $output) {
$inputPath = $input->getOption('path');
if ($input->getOption('repair')) {
$shouldRepairStoragesIndividually = true;
}

if ($inputPath) {
$inputPath = '/' . trim($inputPath, '/');
list (, $user,) = explode('/', $inputPath, 3);
$users = [$user];
} else if ($input->getOption('all')) {
// we can only repair all storages in bulk (more efficient) if singleuser or maintenance mode
// is enabled to prevent concurrent user access
if ($input->getOption('repair') &&
($this->config->getSystemValue('singleuser', false) || $this->config->getSystemValue('maintenance', false))) {
// repair all storages at once
$this->repairAll($output);
// don't fix individually
$shouldRepairStoragesIndividually = false;
} else {
$output->writeln("<error>Repairing every storage individually is slower than repairing in bulk</error>");
$output->writeln("<error>To repair in bulk, please switch to single user mode first: occ maintenance:singleuser --on</error>");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<comment>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about that one

}
$users = $this->userManager->search('');
} else {
$users = $input->getArgument('user_id');
Expand Down Expand Up @@ -269,7 +306,7 @@ protected function execute(InputInterface $input, OutputInterface $output) {
if ($verbose) {$output->writeln(""); }
$output->writeln("Starting scan for user $user_count out of $users_total ($user)");
# full: printout data if $verbose was set
$this->scanFiles($user, $path, $verbose, $output, $input->getOption('unscanned'), $input->getOption('repair'));
$this->scanFiles($user, $path, $verbose, $output, $input->getOption('unscanned'), $shouldRepairStoragesIndividually);
} else {
$output->writeln("<error>Unknown user $user_count $user</error>");
}
Expand Down