Skip to content

Commit 4271753

Browse files
authored
Merge pull request #52790 from nextcloud/backport/52441/stable31
[stable31] fix: better error message when trying to scan a folder that is already being scanned
2 parents aec2c56 + a4a5bca commit 4271753

5 files changed

Lines changed: 48 additions & 7 deletions

File tree

apps/files/lib/Command/Scan.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use OCP\Files\StorageNotAvailableException;
2525
use OCP\FilesMetadata\IFilesMetadataManager;
2626
use OCP\IUserManager;
27+
use OCP\Lock\LockedException;
2728
use Psr\Log\LoggerInterface;
2829
use Symfony\Component\Console\Helper\Table;
2930
use Symfony\Component\Console\Input\InputArgument;
@@ -164,6 +165,12 @@ protected function scanFiles(string $user, string $path, ?string $scanMetadata,
164165
} catch (NotFoundException $e) {
165166
$output->writeln('<error>Path not found: ' . $e->getMessage() . '</error>');
166167
++$this->errorsCounter;
168+
} catch (LockedException $e) {
169+
if (str_starts_with($e->getPath(), 'scanner::')) {
170+
$output->writeln('<error>Another process is already scanning \'' . substr($e->getPath(), strlen('scanner::')) . '\'</error>');
171+
} else {
172+
throw $e;
173+
}
167174
} catch (\Exception $e) {
168175
$output->writeln('<error>Exception during scan: ' . $e->getMessage() . '</error>');
169176
$output->writeln('<error>' . $e->getTraceAsString() . '</error>');

apps/files_external/lib/Command/Scan.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use OC\Files\Cache\Scanner;
1212
use OCA\Files_External\Service\GlobalStoragesService;
1313
use OCP\IUserManager;
14+
use OCP\Lock\LockedException;
1415
use Symfony\Component\Console\Helper\Table;
1516
use Symfony\Component\Console\Input\InputArgument;
1617
use Symfony\Component\Console\Input\InputInterface;
@@ -82,7 +83,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8283
$this->abortIfInterrupted();
8384
});
8485

85-
$scanner->scan($path);
86+
try {
87+
$scanner->scan($path);
88+
} catch (LockedException $e) {
89+
if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) {
90+
if ($e->getReadablePath() === 'scanner::') {
91+
$output->writeln('<error>Another process is already scanning this storage</error>');
92+
} else {
93+
$output->writeln('<error>Another process is already scanning \'' . substr($e->getReadablePath(), strlen('scanner::')) . '\' in this storage</error>');
94+
}
95+
} else {
96+
throw $e;
97+
}
98+
}
8699

87100
$this->presentStats($output);
88101

lib/private/Files/Cache/Scanner.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
210210
* @var \OC\Files\Cache\CacheEntry $cacheData
211211
*/
212212
$newData = $this->array_diff_assoc_multi($data, $cacheData->getData());
213-
213+
214214
// make it known to the caller that etag has been changed and needs propagation
215215
if (isset($newData['etag'])) {
216216
$data['etag_changed'] = true;
@@ -351,23 +351,23 @@ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $loc
351351
*
352352
*/
353353
protected function array_diff_assoc_multi(array $array1, array $array2) {
354-
354+
355355
$result = [];
356356

357357
foreach ($array1 as $key => $value) {
358-
358+
359359
// if $array2 doesn't have the same key, that's a result
360360
if (!array_key_exists($key, $array2)) {
361361
$result[$key] = $value;
362362
continue;
363363
}
364-
364+
365365
// if $array2's value for the same key is different, that's a result
366366
if ($array2[$key] !== $value && !is_array($value)) {
367367
$result[$key] = $value;
368368
continue;
369369
}
370-
370+
371371
if (is_array($value)) {
372372
$nestedDiff = $this->array_diff_assoc_multi($value, $array2[$key]);
373373
if (!empty($nestedDiff)) {

lib/private/Files/Utils/Scanner.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use OCP\Files\StorageNotAvailableException;
3030
use OCP\IDBConnection;
3131
use OCP\Lock\ILockingProvider;
32+
use OCP\Lock\LockedException;
3233
use Psr\Log\LoggerInterface;
3334

3435
/**
@@ -260,7 +261,15 @@ public function scan($dir = '', $recursive = \OC\Files\Cache\Scanner::SCAN_RECUR
260261
try {
261262
$propagator = $storage->getPropagator();
262263
$propagator->beginBatch();
263-
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
264+
try {
265+
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
266+
} catch (LockedException $e) {
267+
if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) {
268+
throw new LockedException("scanner::$dir", $e, $e->getExistingLock());
269+
} else {
270+
throw $e;
271+
}
272+
}
264273
$cache = $storage->getCache();
265274
if ($cache instanceof Cache) {
266275
// only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner

lib/public/Lock/LockedException.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class LockedException extends \Exception {
2424
/** @var string|null */
2525
private $existingLock;
2626

27+
private ?string $readablePath;
28+
2729
/**
2830
* LockedException constructor.
2931
*
@@ -34,6 +36,7 @@ class LockedException extends \Exception {
3436
* @since 8.1.0
3537
*/
3638
public function __construct(string $path, ?\Exception $previous = null, ?string $existingLock = null, ?string $readablePath = null) {
39+
$this->readablePath = $readablePath;
3740
if ($readablePath) {
3841
$message = "\"$path\"(\"$readablePath\") is locked";
3942
} else {
@@ -62,4 +65,13 @@ public function getPath(): string {
6265
public function getExistingLock(): ?string {
6366
return $this->existingLock;
6467
}
68+
69+
/**
70+
* @return ?string
71+
* @since 32.0.0
72+
*/
73+
public function getReadablePath(): ?string {
74+
return $this->readablePath;
75+
}
76+
6577
}

0 commit comments

Comments
 (0)