aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Files
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Files')
-rw-r--r--lib/private/Files/ObjectStore/Azure.php14
-rw-r--r--lib/private/Files/ObjectStore/HomeObjectStoreStorage.php5
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php68
-rw-r--r--lib/private/Files/ObjectStore/S3.php13
-rw-r--r--lib/private/Files/ObjectStore/StorageObjectStore.php9
-rw-r--r--lib/private/Files/ObjectStore/Swift.php9
6 files changed, 116 insertions, 2 deletions
diff --git a/lib/private/Files/ObjectStore/Azure.php b/lib/private/Files/ObjectStore/Azure.php
index 553f593b299..24362647619 100644
--- a/lib/private/Files/ObjectStore/Azure.php
+++ b/lib/private/Files/ObjectStore/Azure.php
@@ -25,6 +25,7 @@ namespace OC\Files\ObjectStore;
use MicrosoftAzure\Storage\Blob\BlobRestProxy;
use MicrosoftAzure\Storage\Blob\Models\CreateBlockBlobOptions;
use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
+use OCP\Files\FileInfo;
use OCP\Files\ObjectStore\IObjectStore;
class Azure implements IObjectStore {
@@ -133,4 +134,17 @@ class Azure implements IObjectStore {
public function copyObject($from, $to) {
$this->getBlobClient()->copyBlob($this->containerName, $to, $this->containerName, $from);
}
+
+ public function bytesUsed(): int {
+ // The only way to get the bytes used is by listing every object
+ // in the blob and sum their size
+ return FileInfo::SPACE_UNKNOWN;
+ }
+
+ public function bytesQuota(): int {
+ // Azure doesn't have a way to set a quota on a specific blob container,
+ // only on a storage account
+ // https://learn.microsoft.com/en-us/answers/questions/627442/blob-general-v2-container-quota.html
+ return FileInfo::SPACE_UNLIMITED;
+ }
}
diff --git a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
index b361249ff47..4e1f49a351c 100644
--- a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php
@@ -27,8 +27,9 @@ namespace OC\Files\ObjectStore;
use OC\User\User;
use OCP\IUser;
+use OCP\Files\IHomeStorage;
-class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IHomeStorage {
+class HomeObjectStoreStorage extends ObjectStoreStorage implements IHomeStorage {
/**
* The home user storage requires a user object to create a unique storage id
* @param array $params
@@ -60,7 +61,7 @@ class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IH
/**
* @param string $path, optional
- * @return \OC\User\User
+ * @return User
*/
public function getUser($path = null): IUser {
return $this->user;
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index eb8aaffe1e0..48ca9486090 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -47,6 +47,10 @@ use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
use OCP\Files\Storage\IChunkedFileWrite;
use OCP\Files\Storage\IStorage;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Server;
class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFileWrite {
use CopyDirectory;
@@ -738,4 +742,68 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
$urn = $this->getURN($cacheEntry->getId());
$this->objectStore->abortMultipartUpload($urn, $writeToken);
}
+
+ /**
+ * In case the admin has overwritten the global instance quota,
+ * default to the quota minus the used object storage size known by Nextcloud
+ * instead of unknown
+ *
+ * @param $path
+ */
+ public function free_space($path) {
+ $cacheFactory = Server::get(ICacheFactory::class);
+ $memcache = $cacheFactory->createLocal('object_storage_info');
+ $cacheKey = 'object_store_used_size';
+ $size = $memcache->get($cacheKey);
+ if ($size) {
+ return $size;
+ }
+
+ // Ask for the object store backend
+ $quota = $this->objectStore->bytesQuota();
+
+ // If not given, by the object store backend, check if we have an override
+ if ($quota < 0) {
+ /** @var IConfig $config */
+ $config = Server::get(IConfig::class);
+ $quota = (int) $config->getAppValue('core', 'quota_instance_global', '0');
+ }
+
+ // If there's a quota in place
+ if ($quota > 0) {
+ // The used size, directly given by the object store backend
+ $size = $this->objectStore->bytesUsed();
+ if ($size < 0) {
+ // Otherwise we just make the sum of all of the storages sizes currently in Nextcloud
+ // Note: This will not take into account object versioning handled
+ // on the object store backend's side such as when using files_versions_s3
+ $size = $this->getUsedObjectStorageSizeInNextcloud();
+ }
+ $freeSpace = $quota - $size;
+ $memcache->set($cacheKey, $freeSpace, 5 * 60);
+ return $freeSpace;
+ }
+ // Otherwise default to unknown
+ return parent::free_space($path);
+ }
+
+ /**
+ * Returns the sum of file sizes from all of the users storages using object storage,
+ * as well as the global object store storage.
+ */
+ public function getUsedObjectStorageSizeInNextcloud(): ?int {
+ $qb = Server::get(IDBConnection::class)->getQueryBuilder();
+ $result = $qb->select($qb->func()->sum('size'))
+ ->from('filecache', 'fc')
+ ->join('fc', 'storages', 's', $qb->expr()->eq('fc.storage', 's.numeric_id'))
+ ->where($qb->expr()->like('s.id', $qb->createNamedParameter('object::%')))
+ ->andWhere($qb->expr()->eq('fc.path', $qb->createNamedParameter('')))
+ ->executeQuery();
+
+ $row = $result->fetchOne();
+ if ($row) {
+ return (int) $row;
+ }
+ return null;
+ }
}
diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php
index b1cd89388ae..d4e207f9002 100644
--- a/lib/private/Files/ObjectStore/S3.php
+++ b/lib/private/Files/ObjectStore/S3.php
@@ -25,6 +25,7 @@ namespace OC\Files\ObjectStore;
use Aws\Result;
use Exception;
+use OCP\Files\FileInfo;
use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
@@ -110,4 +111,16 @@ class S3 implements IObjectStore, IObjectStoreMultiPartUpload {
'UploadId' => $uploadId
]);
}
+
+ public function bytesUsed(): int {
+ // The only way to get the bytes used is by listing every object
+ // in the bucket and sum their size
+ return FileInfo::SPACE_UNKNOWN;
+ }
+
+ public function bytesQuota(): int {
+ // The quota is not obtainable through the S3 API, only through the
+ // specific Amazon Service Quotas API
+ return FileInfo::SPACE_UNLIMITED;
+ }
}
diff --git a/lib/private/Files/ObjectStore/StorageObjectStore.php b/lib/private/Files/ObjectStore/StorageObjectStore.php
index 85926be897e..260238c106c 100644
--- a/lib/private/Files/ObjectStore/StorageObjectStore.php
+++ b/lib/private/Files/ObjectStore/StorageObjectStore.php
@@ -23,6 +23,7 @@
*/
namespace OC\Files\ObjectStore;
+use OCP\Files\FileInfo;
use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\Storage\IStorage;
use function is_resource;
@@ -91,4 +92,12 @@ class StorageObjectStore implements IObjectStore {
public function copyObject($from, $to) {
$this->storage->copy($from, $to);
}
+
+ public function bytesUsed(): int {
+ return FileInfo::SPACE_UNKNOWN;
+ }
+
+ public function bytesQuota(): int {
+ return FileInfo::SPACE_UNLIMITED;
+ }
}
diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php
index b463cb9d44d..5a8860a6d51 100644
--- a/lib/private/Files/ObjectStore/Swift.php
+++ b/lib/private/Files/ObjectStore/Swift.php
@@ -29,6 +29,7 @@ use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Psr7\Utils;
use Icewind\Streams\RetryWrapper;
+use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\StorageAuthException;
@@ -152,4 +153,12 @@ class Swift implements IObjectStore {
'destination' => $this->getContainer()->name . '/' . $to
]);
}
+
+ public function bytesUsed(): int {
+ return $this->getContainer()->bytesUsed;
+ }
+
+ public function bytesQuota(): int {
+ return $this->getContainer()->getMetadata()['Quota-Bytes'] ?? FileInfo::SPACE_UNLIMITED;
+ }
}