Merge pull request #52441 from nextcloud/scan-locked-error

pull/52543/head
Kate 5 months ago committed by GitHub
commit c1a9dfd993
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      apps/files/lib/Command/Scan.php
  2. 15
      apps/files_external/lib/Command/Scan.php
  3. 10
      lib/private/Files/Cache/Scanner.php
  4. 11
      lib/private/Files/Utils/Scanner.php
  5. 12
      lib/public/Lock/LockedException.php

@ -24,6 +24,7 @@ use OCP\Files\NotFoundException;
use OCP\Files\StorageNotAvailableException;
use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IUserManager;
use OCP\Lock\LockedException;
use OCP\Server;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Helper\Table;
@ -165,6 +166,12 @@ class Scan extends Base {
} catch (NotFoundException $e) {
$output->writeln('<error>Path not found: ' . $e->getMessage() . '</error>');
++$this->errorsCounter;
} catch (LockedException $e) {
if (str_starts_with($e->getPath(), 'scanner::')) {
$output->writeln('<error>Another process is already scanning \'' . substr($e->getPath(), strlen('scanner::')) . '\'</error>');
} else {
throw $e;
}
} catch (\Exception $e) {
$output->writeln('<error>Exception during scan: ' . $e->getMessage() . '</error>');
$output->writeln('<error>' . $e->getTraceAsString() . '</error>');

@ -11,6 +11,7 @@ namespace OCA\Files_External\Command;
use OC\Files\Cache\Scanner;
use OCA\Files_External\Service\GlobalStoragesService;
use OCP\IUserManager;
use OCP\Lock\LockedException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -82,7 +83,19 @@ class Scan extends StorageAuthBase {
$this->abortIfInterrupted();
});
$scanner->scan($path);
try {
$scanner->scan($path);
} catch (LockedException $e) {
if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) {
if ($e->getReadablePath() === 'scanner::') {
$output->writeln('<error>Another process is already scanning this storage</error>');
} else {
$output->writeln('<error>Another process is already scanning \'' . substr($e->getReadablePath(), strlen('scanner::')) . '\' in this storage</error>');
}
} else {
throw $e;
}
}
$this->presentStats($output);

@ -210,7 +210,7 @@ class Scanner extends BasicEmitter implements IScanner {
* @var \OC\Files\Cache\CacheEntry $cacheData
*/
$newData = $this->array_diff_assoc_multi($data, $cacheData->getData());
// make it known to the caller that etag has been changed and needs propagation
if (isset($newData['etag'])) {
$data['etag_changed'] = true;
@ -351,23 +351,23 @@ class Scanner extends BasicEmitter implements IScanner {
*
*/
protected function array_diff_assoc_multi(array $array1, array $array2) {
$result = [];
foreach ($array1 as $key => $value) {
// if $array2 doesn't have the same key, that's a result
if (!array_key_exists($key, $array2)) {
$result[$key] = $value;
continue;
}
// if $array2's value for the same key is different, that's a result
if ($array2[$key] !== $value && !is_array($value)) {
$result[$key] = $value;
continue;
}
if (is_array($value)) {
$nestedDiff = $this->array_diff_assoc_multi($value, $array2[$key]);
if (!empty($nestedDiff)) {

@ -29,6 +29,7 @@ use OCP\Files\Storage\IStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
use Psr\Log\LoggerInterface;
/**
@ -260,7 +261,15 @@ class Scanner extends PublicEmitter {
try {
$propagator = $storage->getPropagator();
$propagator->beginBatch();
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
try {
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
} catch (LockedException $e) {
if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) {
throw new LockedException("scanner::$dir", $e, $e->getExistingLock());
} else {
throw $e;
}
}
$cache = $storage->getCache();
if ($cache instanceof Cache) {
// only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner

@ -24,6 +24,8 @@ class LockedException extends \Exception {
/** @var string|null */
private $existingLock;
private ?string $readablePath;
/**
* LockedException constructor.
*
@ -34,6 +36,7 @@ class LockedException extends \Exception {
* @since 8.1.0
*/
public function __construct(string $path, ?\Exception $previous = null, ?string $existingLock = null, ?string $readablePath = null) {
$this->readablePath = $readablePath;
if ($readablePath) {
$message = "\"$path\"(\"$readablePath\") is locked";
} else {
@ -62,4 +65,13 @@ class LockedException extends \Exception {
public function getExistingLock(): ?string {
return $this->existingLock;
}
/**
* @return ?string
* @since 32.0.0
*/
public function getReadablePath(): ?string {
return $this->readablePath;
}
}

Loading…
Cancel
Save