Make Cache::removeChildren non recursive
Currently the "add new files during scanning" call stack is smaller than the "remove deleted files during scanning" call stack. This can lead to the scanner adding folders in the folder tree that are to deep to be removed. This changes the `removeChildren` logic to be non recursive so there is no limit to the depth of the folder tree during removal Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
03603db486
commit
5af7d921a9
|
@ -553,25 +553,35 @@ class Cache implements ICache {
|
|||
* @throws \OC\DatabaseException
|
||||
*/
|
||||
private function removeChildren(ICacheEntry $entry) {
|
||||
$children = $this->getFolderContentsById($entry->getId());
|
||||
$childIds = array_map(function (ICacheEntry $cacheEntry) {
|
||||
return $cacheEntry->getId();
|
||||
}, $children);
|
||||
$childFolders = array_filter($children, function ($child) {
|
||||
return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
|
||||
});
|
||||
foreach ($childFolders as $folder) {
|
||||
$this->removeChildren($folder);
|
||||
$parentIds = [$entry->getId()];
|
||||
$queue = [$entry->getId()];
|
||||
|
||||
// we walk depth first trough the file tree, removing all filecache_extended attributes while we walk
|
||||
// and collecting all folder ids to later use to delete the filecache entries
|
||||
while ($entryId = array_pop($queue)) {
|
||||
$children = $this->getFolderContentsById($entryId);
|
||||
$childIds = array_map(function (ICacheEntry $cacheEntry) {
|
||||
return $cacheEntry->getId();
|
||||
}, $children);
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache_extended')
|
||||
->where($query->expr()->in('fileid', $query->createNamedParameter($childIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
$query->execute();
|
||||
|
||||
/** @var ICacheEntry[] $childFolders */
|
||||
$childFolders = array_filter($children, function ($child) {
|
||||
return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
|
||||
});
|
||||
foreach ($childFolders as $folder) {
|
||||
$parentIds[] = $folder->getId();
|
||||
$queue[] = $folder->getId();
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache')
|
||||
->whereParent($entry->getId());
|
||||
$query->execute();
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache_extended')
|
||||
->where($query->expr()->in('fileid', $query->createNamedParameter($childIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
->whereParentIn($parentIds);
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,4 +94,17 @@ class CacheQueryBuilder extends QueryBuilder {
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereParentIn(array $parents) {
|
||||
$alias = $this->alias;
|
||||
if ($alias) {
|
||||
$alias .= '.';
|
||||
} else {
|
||||
$alias = '';
|
||||
}
|
||||
|
||||
$this->andWhere($this->expr()->in("{$alias}parent", $this->createNamedParameter($parents, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue