aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2022-08-18 11:43:18 +0200
committerRobin Appelman <robin@icewind.nl>2022-09-01 19:32:24 +0200
commitbd91c56539ba23bed3bff5dbc594950ef93799e0 (patch)
treedbdafa886aae1980ae9bbbcc720628d2863a3992
parent634ee18d03fd36369d22a9eca2d88d66a8975c3a (diff)
downloadnextcloud-server-bd91c56539ba23bed3bff5dbc594950ef93799e0.tar.gz
nextcloud-server-bd91c56539ba23bed3bff5dbc594950ef93799e0.zip
get quota for user only when needed
always apply the wrapper but have the wrapper get the quota lazily only when an operation where quota is applied is performed Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r--lib/private/Files/SetupManager.php8
-rw-r--r--lib/private/Files/Storage/Wrapper/Quota.php71
-rw-r--r--tests/lib/Files/Storage/HomeStorageQuotaTest.php84
3 files changed, 55 insertions, 108 deletions
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 5782a5a72a6..d52a291cd99 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -172,10 +172,10 @@ class SetupManager {
*/
if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
if (is_object($storage->getUser())) {
- $quota = OC_Util::getUserQuota($storage->getUser());
- if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
- return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
- }
+ $user = $storage->getUser();
+ return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) {
+ return OC_Util::getUserQuota($user);
+ }, 'root' => 'files']);
}
}
diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php
index 4cd0a5e0b4a..8b129472eb0 100644
--- a/lib/private/Files/Storage/Wrapper/Quota.php
+++ b/lib/private/Files/Storage/Wrapper/Quota.php
@@ -33,40 +33,47 @@
namespace OC\Files\Storage\Wrapper;
use OC\Files\Filesystem;
+use OC\SystemConfig;
use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\FileInfo;
use OCP\Files\Storage\IStorage;
class Quota extends Wrapper {
-
- /**
- * @var int $quota
- */
- protected $quota;
-
- /**
- * @var string $sizeRoot
- */
- protected $sizeRoot;
-
- private $config;
+ /** @var callable|null */
+ protected $quotaCallback;
+ protected ?int $quota;
+ protected string $sizeRoot;
+ private SystemConfig $config;
/**
* @param array $parameters
*/
public function __construct($parameters) {
parent::__construct($parameters);
- $this->quota = $parameters['quota'];
- $this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : '';
- $this->config = \OC::$server->getSystemConfig();
+ $this->quota = $parameters['quota'] ?? null;
+ $this->quotaCallback = $parameters['quotaCallback'] ?? null;
+ $this->sizeRoot = $parameters['root'] ?? '';
+ $this->config = \OC::$server->get(SystemConfig::class);
}
/**
* @return int quota value
*/
- public function getQuota() {
+ public function getQuota(): int {
+ if ($this->quota === null) {
+ $quotaCallback = $this->quotaCallback;
+ if ($quotaCallback === null) {
+ throw new \Exception("No quota or quota callback provider");
+ }
+ $this->quota = $quotaCallback();
+ }
return $this->quota;
}
+ private function hasQuota(): bool {
+ return $this->getQuota() !== FileInfo::SPACE_UNLIMITED;
+ }
+
/**
* @param string $path
* @param \OC\Files\Storage\Storage $storage
@@ -100,7 +107,10 @@ class Quota extends Wrapper {
* @return int|bool
*/
public function free_space($path) {
- if ($this->quota < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) {
+ if (!$this->hasQuota()) {
+ return $this->storage->free_space($path);
+ }
+ if ($this->getQuota() < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) {
return $this->storage->free_space($path);
} else {
$used = $this->getSize($this->sizeRoot);
@@ -108,7 +118,7 @@ class Quota extends Wrapper {
return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
} else {
$free = $this->storage->free_space($path);
- $quotaFree = max($this->quota - $used, 0);
+ $quotaFree = max($this->getQuota() - $used, 0);
// if free space is known
if ($free >= 0) {
$free = min($free, $quotaFree);
@@ -128,6 +138,9 @@ class Quota extends Wrapper {
* @return int|false
*/
public function file_put_contents($path, $data) {
+ if (!$this->hasQuota()) {
+ return $this->storage->file_put_contents($path, $data);
+ }
$free = $this->free_space($path);
if ($free < 0 or strlen($data) < $free) {
return $this->storage->file_put_contents($path, $data);
@@ -144,6 +157,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function copy($source, $target) {
+ if (!$this->hasQuota()) {
+ return $this->storage->copy($source, $target);
+ }
$free = $this->free_space($target);
if ($free < 0 or $this->getSize($source) < $free) {
return $this->storage->copy($source, $target);
@@ -160,6 +176,9 @@ class Quota extends Wrapper {
* @return resource|bool
*/
public function fopen($path, $mode) {
+ if (!$this->hasQuota()) {
+ return $this->storage->fopen($path, $mode);
+ }
$source = $this->storage->fopen($path, $mode);
// don't apply quota for part files
@@ -202,6 +221,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ if (!$this->hasQuota()) {
+ return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ }
$free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
@@ -217,6 +239,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ if (!$this->hasQuota()) {
+ return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ }
$free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
@@ -226,8 +251,11 @@ class Quota extends Wrapper {
}
public function mkdir($path) {
+ if (!$this->hasQuota()) {
+ return $this->storage->mkdir($path);
+ }
$free = $this->free_space($path);
- if ($this->shouldApplyQuota($path) && $free === 0.0) {
+ if ($this->shouldApplyQuota($path) && $free == 0) {
return false;
}
@@ -235,8 +263,11 @@ class Quota extends Wrapper {
}
public function touch($path, $mtime = null) {
+ if (!$this->hasQuota()) {
+ return $this->storage->touch($path, $mtime);
+ }
$free = $this->free_space($path);
- if ($free === 0.0) {
+ if ($free == 0) {
return false;
}
diff --git a/tests/lib/Files/Storage/HomeStorageQuotaTest.php b/tests/lib/Files/Storage/HomeStorageQuotaTest.php
deleted file mode 100644
index 177fe1b4f6c..00000000000
--- a/tests/lib/Files/Storage/HomeStorageQuotaTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace Test\Files\Storage;
-
-/**
- * Class HomeStorageQuotaTest
- *
- * @group DB
- */
-class HomeStorageQuotaTest extends \Test\TestCase {
- /**
- * Tests that the home storage is not wrapped when no quota exists.
- */
- public function testHomeStorageWrapperWithoutQuota() {
- $user1 = $this->getUniqueID();
- \OC::$server->getUserManager()->createUser($user1, 'test');
- \OC::$server->getConfig()->setUserValue($user1, 'files', 'quota', 'none');
- \OC_User::setUserId($user1);
-
- \OC_Util::setupFS($user1);
-
- $userMount = \OC\Files\Filesystem::getMountManager()->find('/' . $user1 . '/');
- $this->assertNotNull($userMount);
- $this->assertNotInstanceOf('\OC\Files\Storage\Wrapper\Quota', $userMount->getStorage());
-
- // clean up
- \OC_User::setUserId('');
- $user = \OC::$server->getUserManager()->get($user1);
- if ($user !== null) {
- $user->delete();
- }
- \OC::$server->getConfig()->deleteAllUserValues($user1);
- \OC_Util::tearDownFS();
- }
-
- /**
- * Tests that the home storage is not wrapped when no quota exists.
- */
- public function testHomeStorageWrapperWithQuota() {
- $user1 = $this->getUniqueID();
- \OC::$server->getUserManager()->createUser($user1, 'test');
- \OC::$server->getConfig()->setUserValue($user1, 'files', 'quota', '1024');
- \OC_User::setUserId($user1);
-
- \OC_Util::setupFS($user1);
-
- $userMount = \OC\Files\Filesystem::getMountManager()->find('/' . $user1 . '/');
- $this->assertNotNull($userMount);
- $this->assertTrue($userMount->getStorage()->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota'));
-
- // ensure that root wasn't wrapped
- $rootMount = \OC\Files\Filesystem::getMountManager()->find('/');
- $this->assertNotNull($rootMount);
- $this->assertNotInstanceOf('\OC\Files\Storage\Wrapper\Quota', $rootMount->getStorage());
-
- // clean up
- \OC_User::setUserId('');
- $user = \OC::$server->getUserManager()->get($user1);
- if ($user !== null) {
- $user->delete();
- }
- \OC::$server->getConfig()->deleteAllUserValues($user1);
- \OC_Util::tearDownFS();
- }
-}