Skip to content

Commit

Permalink
Merge pull request #33600 from nextcloud/lazy-quota
Browse files Browse the repository at this point in the history
get quota for user only when needed
  • Loading branch information
blizzz authored Sep 7, 2022
2 parents 54f3661 + bd91c56 commit 417f46e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 108 deletions.
8 changes: 4 additions & 4 deletions lib/private/Files/SetupManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ private function setupBuiltinWrappers() {
*/
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']);
}
}

Expand Down
71 changes: 51 additions & 20 deletions lib/private/Files/Storage/Wrapper/Quota.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -100,15 +107,18 @@ protected function getSize($path, $storage = null) {
* @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);
if ($used < 0) {
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);
Expand All @@ -128,6 +138,9 @@ public function free_space($path) {
* @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);
Expand All @@ -144,6 +157,9 @@ public function file_put_contents($path, $data) {
* @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);
Expand All @@ -160,6 +176,9 @@ public function copy($source, $target) {
* @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
Expand Down Expand Up @@ -202,6 +221,9 @@ private function shouldApplyQuota(string $path): bool {
* @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);
Expand All @@ -217,6 +239,9 @@ public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $t
* @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);
Expand All @@ -226,17 +251,23 @@ public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $t
}

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;
}

return parent::mkdir($path);
}

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;
}

Expand Down
84 changes: 0 additions & 84 deletions tests/lib/Files/Storage/HomeStorageQuotaTest.php

This file was deleted.

0 comments on commit 417f46e

Please sign in to comment.