Skip to content

Commit

Permalink
Merge pull request #30683 from nextcloud/backport/30531/stable22
Browse files Browse the repository at this point in the history
[stable22] Optimize FileSystemTags workflow for groupfolder
  • Loading branch information
CarlSchwan authored Jan 14, 2022
2 parents fbc1007 + 5c155d1 commit 5881082
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
32 changes: 22 additions & 10 deletions apps/workflowengine/lib/Check/FileSystemTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use OCP\SystemTag\TagNotFoundException;
use OCP\WorkflowEngine\ICheck;
use OCP\WorkflowEngine\IFileCheck;
use OC\Files\Storage\Wrapper\Wrapper;

class FileSystemTags implements ICheck, IFileCheck {
use TFileCheck;
Expand Down Expand Up @@ -132,13 +133,26 @@ protected function getSystemTags() {
* @return int[]
*/
protected function getFileIds(ICache $cache, $path, $isExternalStorage) {
// TODO: Fix caching inside group folders
// Do not cache file ids inside group folders because multiple file ids might be mapped to
// the same combination of cache id + path.
/** @psalm-suppress InvalidArgument */
$shouldCacheFileIds = !$this->storage->instanceOfStorage(\OCA\GroupFolders\Mount\GroupFolderStorage::class);
$cacheId = $cache->getNumericStorageId();
if ($shouldCacheFileIds && isset($this->fileIds[$cacheId][$path])) {
if ($this->storage->instanceOfStorage(\OCA\GroupFolders\Mount\GroupFolderStorage::class)) {
// Special implementation for groupfolder since all groupfolders share the same storage
// id so add the group folder id in the cache key too.
$groupFolderStorage = $this->storage;
if ($this->storage instanceof Wrapper) {
$groupFolderStorage = $this->storage->getInstanceOfStorage(\OCA\GroupFolders\Mount\GroupFolderStorage::class);
}
if ($groupFolderStorage === null) {
throw new \LogicException('Should not happen: Storage is instance of GroupFolderStorage but no group folder storage found while unwrapping.');
}
/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedInterfaceMethod
*/
$cacheId = $cache->getNumericStorageId() . '/' . $groupFolderStorage->getFolderId();
} else {
$cacheId = $cache->getNumericStorageId();
}
if (isset($this->fileIds[$cacheId][$path])) {
return $this->fileIds[$cacheId][$path];
}

Expand All @@ -151,12 +165,10 @@ protected function getFileIds(ICache $cache, $path, $isExternalStorage) {

$fileId = $cache->getId($path);
if ($fileId !== -1) {
$parentIds[] = $cache->getId($path);
$parentIds[] = $fileId;
}

if ($shouldCacheFileIds) {
$this->fileIds[$cacheId][$path] = $parentIds;
}
$this->fileIds[$cacheId][$path] = $parentIds;

return $parentIds;
}
Expand Down
21 changes: 20 additions & 1 deletion lib/private/Files/Storage/Wrapper/Wrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ public function isLocal() {
/**
* Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
*
* @param string $class
* @param class-string<IStorage> $class
* @return bool
*/
public function instanceOfStorage($class) {
Expand All @@ -497,6 +497,25 @@ public function instanceOfStorage($class) {
return is_a($this, $class) or $this->getWrapperStorage()->instanceOfStorage($class);
}

/**
* @psalm-template T of IStorage
* @psalm-param class-string<T> $class
* @psalm-return T|null
*/
public function getInstanceOfStorage(string $class) {
$storage = $this;
while ($storage instanceof Wrapper) {
if ($storage instanceof $class) {
break;
}
$storage = $storage->getWrapperStorage();
}
if (!($storage instanceof $class)) {
return null;
}
return $storage;
}

/**
* Pass any methods custom to specific storage implementations to the wrapped storage
*
Expand Down

0 comments on commit 5881082

Please sign in to comment.