diff options
Diffstat (limited to 'lib/private/Files/Cache')
-rw-r--r-- | lib/private/Files/Cache/Cache.php | 43 | ||||
-rw-r--r-- | lib/private/Files/Cache/CacheEntry.php | 8 | ||||
-rw-r--r-- | lib/private/Files/Cache/CacheQueryBuilder.php | 12 | ||||
-rw-r--r-- | lib/private/Files/Cache/Propagator.php | 17 | ||||
-rw-r--r-- | lib/private/Files/Cache/QuerySearchHelper.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Cache/Storage.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Cache/StorageGlobal.php | 2 | ||||
-rw-r--r-- | lib/private/Files/Cache/Updater.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Cache/Wrapper/CacheJail.php | 2 | ||||
-rw-r--r-- | lib/private/Files/Cache/Wrapper/CacheWrapper.php | 2 |
10 files changed, 75 insertions, 23 deletions
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 949079dfa22..f23635aa01b 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -37,6 +37,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> * */ + namespace OC\Files\Cache; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; @@ -63,7 +64,7 @@ use Psr\Log\LoggerInterface; /** * Metadata cache for a storage * - * The cache stores the metadata for all files and folders in a storage and is kept up to date trough the following mechanisms: + * The cache stores the metadata for all files and folders in a storage and is kept up to date through the following mechanisms: * * - Scanner: scans the storage and updates the cache where needed * - Watcher: checks for changes made to the filesystem outside of the Nextcloud instance and rescans files and folder when a change is detected @@ -188,6 +189,7 @@ class Cache implements ICache { $data['fileid'] = (int)$data['fileid']; $data['parent'] = (int)$data['parent']; $data['size'] = 0 + $data['size']; + $data['unencrypted_size'] = 0 + ($data['unencrypted_size'] ?? 0); $data['mtime'] = (int)$data['mtime']; $data['storage_mtime'] = (int)$data['storage_mtime']; $data['encryptedVersion'] = (int)$data['encrypted']; @@ -428,7 +430,7 @@ class Cache implements ICache { protected function normalizeData(array $data): array { $fields = [ 'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted', - 'etag', 'permissions', 'checksum', 'storage']; + 'etag', 'permissions', 'checksum', 'storage', 'unencrypted_size']; $extensionFields = ['metadata_etag', 'creation_time', 'upload_time']; $doNotCopyStorageMTime = false; @@ -538,7 +540,7 @@ class Cache implements ICache { public function remove($file) { $entry = $this->get($file); - if ($entry) { + if ($entry instanceof ICacheEntry) { $query = $this->getQueryBuilder(); $query->delete('filecache') ->whereFileId($entry->getId()); @@ -580,7 +582,7 @@ class Cache implements ICache { $parentIds = [$entry->getId()]; $queue = [$entry->getId()]; - // we walk depth first trough the file tree, removing all filecache_extended attributes while we walk + // we walk depth first through 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); @@ -873,8 +875,16 @@ class Cache implements ICache { $id = $entry['fileid']; $query = $this->getQueryBuilder(); - $query->selectAlias($query->func()->sum('size'), 'f1') - ->selectAlias($query->func()->min('size'), 'f2') + $query->selectAlias($query->func()->sum('size'), 'size_sum') + ->selectAlias($query->func()->min('size'), 'size_min') + // in case of encryption being enabled after some files are already uploaded, some entries will have an unencrypted_size of 0 and a non-zero size + ->selectAlias($query->func()->sum( + $query->func()->case([ + ['when' => $query->expr()->eq('unencrypted_size', $query->expr()->literal(0, IQueryBuilder::PARAM_INT)), 'then' => 'size'], + ], 'unencrypted_size') + ), 'unencrypted_sum') + ->selectAlias($query->func()->min('unencrypted_size'), 'unencrypted_min') + ->selectAlias($query->func()->max('unencrypted_size'), 'unencrypted_max') ->from('filecache') ->whereStorageId($this->getNumericStorageId()) ->whereParent($id); @@ -884,7 +894,7 @@ class Cache implements ICache { $result->closeCursor(); if ($row) { - [$sum, $min] = array_values($row); + ['size_sum' => $sum, 'size_min' => $min, 'unencrypted_sum' => $unencryptedSum, 'unencrypted_min' => $unencryptedMin, 'unencrypted_max' => $unencryptedMax] = $row; $sum = 0 + $sum; $min = 0 + $min; if ($min === -1) { @@ -892,8 +902,23 @@ class Cache implements ICache { } else { $totalSize = $sum; } + if ($unencryptedMin === -1 || $min === -1) { + $unencryptedTotal = $unencryptedMin; + } else { + $unencryptedTotal = $unencryptedSum; + } if ($entry['size'] !== $totalSize) { - $this->update($id, ['size' => $totalSize]); + // only set unencrypted size for a folder if any child entries have it set + if ($unencryptedMax > 0) { + $this->update($id, [ + 'size' => $totalSize, + 'unencrypted_size' => $unencryptedTotal, + ]); + } else { + $this->update($id, [ + 'size' => $totalSize, + ]); + } } } } @@ -927,7 +952,7 @@ class Cache implements ICache { * use the one with the highest id gives the best result with the background scanner, since that is most * likely the folder where we stopped scanning previously * - * @return string|bool the path of the folder or false when no folder matched + * @return string|false the path of the folder or false when no folder matched */ public function getIncomplete() { $query = $this->getQueryBuilder(); diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php index 12f0273fb6e..8ac76acf6d1 100644 --- a/lib/private/Files/Cache/CacheEntry.php +++ b/lib/private/Files/Cache/CacheEntry.php @@ -132,4 +132,12 @@ class CacheEntry implements ICacheEntry { public function __clone() { $this->data = array_merge([], $this->data); } + + public function getUnencryptedSize(): int { + if (isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) { + return $this->data['unencrypted_size']; + } else { + return $this->data['size']; + } + } } diff --git a/lib/private/Files/Cache/CacheQueryBuilder.php b/lib/private/Files/Cache/CacheQueryBuilder.php index b448424c1a8..496a8361d77 100644 --- a/lib/private/Files/Cache/CacheQueryBuilder.php +++ b/lib/private/Files/Cache/CacheQueryBuilder.php @@ -41,12 +41,16 @@ class CacheQueryBuilder extends QueryBuilder { parent::__construct($connection, $systemConfig, $logger); } - public function selectFileCache(string $alias = null) { + public function selectFileCache(string $alias = null, bool $joinExtendedCache = true) { $name = $alias ? $alias : 'filecache'; $this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", "$name.name", 'mimetype', 'mimepart', 'size', 'mtime', - 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time') - ->from('filecache', $name) - ->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid')); + 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'unencrypted_size') + ->from('filecache', $name); + + if ($joinExtendedCache) { + $this->addSelect('metadata_etag', 'creation_time', 'upload_time'); + $this->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid')); + } $this->alias = $name; diff --git a/lib/private/Files/Cache/Propagator.php b/lib/private/Files/Cache/Propagator.php index 270b2b013f5..a0953baa785 100644 --- a/lib/private/Files/Cache/Propagator.php +++ b/lib/private/Files/Cache/Propagator.php @@ -24,6 +24,7 @@ namespace OC\Files\Cache; +use OC\Files\Storage\Wrapper\Encryption; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Cache\IPropagator; use OCP\Files\Storage\IReliableEtagStorage; @@ -65,7 +66,7 @@ class Propagator implements IPropagator { * @param int $sizeDifference number of bytes the file has grown */ public function propagateChange($internalPath, $time, $sizeDifference = 0) { - // Do not propogate changes in ignored paths + // Do not propagate changes in ignored paths foreach ($this->ignore as $ignore) { if (strpos($internalPath, $ignore) === 0) { return; @@ -113,6 +114,20 @@ class Propagator implements IPropagator { ->andWhere($builder->expr()->in('path_hash', $hashParams)) ->andWhere($builder->expr()->gt('size', $builder->expr()->literal(-1, IQueryBuilder::PARAM_INT))); + if ($this->storage->instanceOfStorage(Encryption::class)) { + // in case of encryption being enabled after some files are already uploaded, some entries will have an unencrypted_size of 0 and a non-zero size + $builder->set('unencrypted_size', $builder->func()->greatest( + $builder->func()->add( + $builder->func()->case([ + ['when' => $builder->expr()->eq('unencrypted_size', $builder->expr()->literal(0, IQueryBuilder::PARAM_INT)), 'then' => 'size'] + ], 'unencrypted_size'), + $builder->createNamedParameter($sizeDifference) + ), + $builder->createNamedParameter(-1, IQueryBuilder::PARAM_INT) + )); + } + + $a = $builder->getSQL(); $builder->execute(); } } diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php index e7bccbf521c..3529ede9746 100644 --- a/lib/private/Files/Cache/QuerySearchHelper.php +++ b/lib/private/Files/Cache/QuerySearchHelper.php @@ -103,7 +103,7 @@ class QuerySearchHelper { $builder = $this->getQueryBuilder(); - $query = $builder->selectFileCache('file'); + $query = $builder->selectFileCache('file', false); if ($this->searchBuilder->shouldJoinTags($searchQuery->getSearchOperation())) { $user = $searchQuery->getUser(); @@ -158,7 +158,7 @@ class QuerySearchHelper { $result->closeCursor(); - // loop trough all caches for each result to see if the result matches that storage + // loop through all caches for each result to see if the result matches that storage // results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results $results = array_fill_keys(array_keys($caches), []); foreach ($rawEntries as $rawEntry) { diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php index fb9e5500658..f77c9b71dd7 100644 --- a/lib/private/Files/Cache/Storage.php +++ b/lib/private/Files/Cache/Storage.php @@ -40,7 +40,7 @@ use Psr\Log\LoggerInterface; * a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share') * and a numeric storage id which is referenced in the file cache * - * A mapping between the two storage ids is stored in the database and accessible trough this class + * A mapping between the two storage ids is stored in the database and accessible through this class * * @package OC\Files\Cache */ @@ -135,7 +135,7 @@ class Storage { * Get the numeric of the storage with the provided string id * * @param $storageId - * @return int|null either the numeric storage id or null if the storage id is not knwon + * @return int|null either the numeric storage id or null if the storage id is not known */ public static function getNumericStorageId($storageId) { $storageId = self::adjustStorageId($storageId); diff --git a/lib/private/Files/Cache/StorageGlobal.php b/lib/private/Files/Cache/StorageGlobal.php index a898c435415..74cbd5abdb2 100644 --- a/lib/private/Files/Cache/StorageGlobal.php +++ b/lib/private/Files/Cache/StorageGlobal.php @@ -33,7 +33,7 @@ use OCP\IDBConnection; * a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share') * and a numeric storage id which is referenced in the file cache * - * A mapping between the two storage ids is stored in the database and accessible trough this class + * A mapping between the two storage ids is stored in the database and accessible through this class * * @package OC\Files\Cache */ diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php index 98fb51fe264..f8c187996e6 100644 --- a/lib/private/Files/Cache/Updater.php +++ b/lib/private/Files/Cache/Updater.php @@ -73,14 +73,14 @@ class Updater implements IUpdater { } /** - * Disable updating the cache trough this updater + * Disable updating the cache through this updater */ public function disable() { $this->enabled = false; } /** - * Re-enable the updating of the cache trough this updater + * Re-enable the updating of the cache through this updater */ public function enable() { $this->enabled = true; diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php index 7183a6c0d2a..4053042edd9 100644 --- a/lib/private/Files/Cache/Wrapper/CacheJail.php +++ b/lib/private/Files/Cache/Wrapper/CacheJail.php @@ -267,7 +267,7 @@ class CacheJail extends CacheWrapper { * use the one with the highest id gives the best result with the background scanner, since that is most * likely the folder where we stopped scanning previously * - * @return string|bool the path of the folder or false when no folder matched + * @return string|false the path of the folder or false when no folder matched */ public function getIncomplete() { // not supported diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index e5300dc75f5..66ae83fd144 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -267,7 +267,7 @@ class CacheWrapper extends Cache { * use the one with the highest id gives the best result with the background scanner, since that is most * likely the folder where we stopped scanning previously * - * @return string|bool the path of the folder or false when no folder matched + * @return string|false the path of the folder or false when no folder matched */ public function getIncomplete() { return $this->getCache()->getIncomplete(); |