Skip to content

Commit

Permalink
store unencrypted size in the unencrypted_size column
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Appelman <robin@icewind.nl>
  • Loading branch information
icewind1991 committed Apr 28, 2022
1 parent e5166ca commit 44a1b35
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 52 deletions.
35 changes: 30 additions & 5 deletions lib/private/Files/Cache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -188,6 +189,7 @@ public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader
$data['fileid'] = (int)$data['fileid'];
$data['parent'] = (int)$data['parent'];
$data['size'] = 0 + $data['size'];
$data['unencrypted_size'] = 0 + $data['unencrypted_size'];
$data['mtime'] = (int)$data['mtime'];
$data['storage_mtime'] = (int)$data['storage_mtime'];
$data['encryptedVersion'] = (int)$data['encrypted'];
Expand Down Expand Up @@ -428,7 +430,7 @@ public function update($id, array $data) {
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;
Expand Down Expand Up @@ -873,8 +875,16 @@ public function calculateFolderSize($path, $entry = null) {
$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);
Expand All @@ -884,16 +894,31 @@ public function calculateFolderSize($path, $entry = null) {
$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) {
$totalSize = $min;
} 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,
]);
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions lib/private/Files/Cache/CacheEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,12 @@ public function getData() {
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'];
}
}
}
2 changes: 1 addition & 1 deletion lib/private/Files/Cache/CacheQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function __construct(IDBConnection $connection, SystemConfig $systemConfi
public function selectFileCache(string $alias = null) {
$name = $alias ? $alias : 'filecache';
$this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", 'name', 'mimetype', 'mimepart', 'size', 'mtime',
'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time')
'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time', 'unencrypted_size')
->from('filecache', $name)
->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));

Expand Down
15 changes: 15 additions & 0 deletions lib/private/Files/Cache/Propagator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -113,6 +114,20 @@ public function propagateChange($internalPath, $time, $sizeDifference = 0) {
->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->expr()->castColumn(
$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();
}
}
Expand Down
27 changes: 24 additions & 3 deletions lib/private/Files/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ public function __construct($path, $storage, $internalPath, $data, $mount, $owne
$this->data = $data;
$this->mount = $mount;
$this->owner = $owner;
$this->rawSize = $this->data['size'] ?? 0;
if (isset($this->data['unencrypted_size'])) {
$this->rawSize = $this->data['unencrypted_size'];
} else {
$this->rawSize = $this->data['size'] ?? 0;
}
}

public function offsetSet($offset, $value): void {
Expand Down Expand Up @@ -208,7 +212,12 @@ public function getEtag() {
public function getSize($includeMounts = true) {
if ($includeMounts) {
$this->updateEntryfromSubMounts();
return isset($this->data['size']) ? 0 + $this->data['size'] : 0;

if (isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
return $this->data['unencrypted_size'];
} else {
return isset($this->data['size']) ? 0 + $this->data['size'] : 0;
}
} else {
return $this->rawSize;
}
Expand Down Expand Up @@ -386,7 +395,19 @@ private function updateEntryfromSubMounts() {
* @param string $entryPath full path of the child entry
*/
public function addSubEntry($data, $entryPath) {
$this->data['size'] += isset($data['size']) ? $data['size'] : 0;
if (!$data) {
return;
}
$hasUnencryptedSize = isset($data['unencrypted_size']) && $data['unencrypted_size'] > 0;
if ($hasUnencryptedSize) {
$subSize = $data['unencrypted_size'];
} else {
$subSize = $data['size'] ?: 0;
}
$this->data['size'] += $subSize;
if ($hasUnencryptedSize) {
$this->data['unencrypted_size'] += $subSize;
}
if (isset($data['mtime'])) {
$this->data['mtime'] = max($this->data['mtime'], $data['mtime']);
}
Expand Down
Loading

0 comments on commit 44a1b35

Please sign in to comment.