Added experimental switch to count external storage data in quota

This includes all mountpoints except the Shared one in
the used space calculation.

Added unit tests for ext storage inclusion in quota calculation
This commit is contained in:
Vincent Petry 2014-03-25 16:37:46 +01:00 committed by Robin Appelman
parent b5f0a17918
commit da889ff029
4 changed files with 183 additions and 27 deletions

View file

@ -291,6 +291,9 @@ $CONFIG = array(
*/
'cache_path' => '',
/* EXPERIMENTAL: option whether to include external storage in quota calculation, defaults to false */
'quota_include_external_storage' => false,
/*
* specifies how often the filesystem is checked for changes made outside owncloud
* 0 -> never check the filesystem for outside changes, provides a performance increase when it's certain that no changes are made directly to the filesystem
@ -301,5 +304,4 @@ $CONFIG = array(
/* If true, prevent owncloud from changing the cache due to changes in the filesystem for all storage */
'filesystem_cache_readonly' => false,
);

View file

@ -807,7 +807,8 @@ class View {
* get the filesystem info
*
* @param string $path
* @param boolean $includeMountPoints whether to add mountpoint sizes,
* @param boolean|string $includeMountPoints true to add mountpoint sizes,
* 'ext' to add only ext storage mount point sizes. Defaults to true.
* defaults to true
* @return \OC\Files\FileInfo|false
*/
@ -847,10 +848,15 @@ class View {
if ($data and isset($data['fileid'])) {
if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
//add the sizes of other mountpoints to the folder
$extOnly = ($includeMountPoints === 'ext');
$mountPoints = Filesystem::getMountPoints($path);
foreach ($mountPoints as $mountPoint) {
$subStorage = Filesystem::getStorage($mountPoint);
if ($subStorage) {
// exclude shared storage ?
if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
continue;
}
$subCache = $subStorage->getCache('');
$rootEntry = $subCache->get('');
$data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0;

View file

@ -936,6 +936,8 @@ class OC_Helper {
*/
public static function getStorageInfo($path, $rootInfo = null) {
// return storage info without adding mount points
$includeExtStorage = \OC_Config::getValue('quota_include_external_storage', false);
if (is_null($rootInfo)) {
$rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
}
@ -944,8 +946,20 @@ class OC_Helper {
$used = 0;
}
$quota = 0;
// TODO: need a better way to get total space from storage
$storage = $rootInfo->getStorage();
if ($includeExtStorage && $storage->instanceOfStorage('\OC\Files\Storage\Shared')) {
$includeExtStorage = false;
}
if ($includeExtStorage) {
$quota = OC_Util::getUserQuota(\OCP\User::getUser());
if ($quota !== \OC\Files\SPACE_UNLIMITED) {
// always get free space / total space from root + mount points
$path = '';
return self::getGlobalStorageInfo();
}
}
// TODO: need a better way to get total space from storage
if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
$quota = $storage->getQuota();
}
@ -967,4 +981,35 @@ class OC_Helper {
return array('free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative);
}
/**
* Get storage info including all mount points and quota
*
* @return array
*/
private static function getGlobalStorageInfo() {
$quota = OC_Util::getUserQuota(\OCP\User::getUser());
$rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
$used = $rootInfo['size'];
if ($used < 0) {
$used = 0;
}
$total = $quota;
$free = $quota - $used;
if ($total > 0) {
if ($quota > 0 && $total > $quota) {
$total = $quota;
}
// prevent division by zero or error codes (negative values)
$relative = round(($used / $total) * 10000) / 100;
} else {
$relative = 0;
}
return array('free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative);
}
}

View file

@ -15,35 +15,58 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase {
public function setUp() {
$this->user = 'user_' . uniqid();
\OC\Files\Filesystem::tearDown();
\OC\Files\Filesystem::init($this->user, '/' . $this->user . '/files');
\OC_User::createUser($this->user, $this->user);
\OC\Files\Filesystem::tearDown();
\OC_User::setUserId($this->user);
\OC\Files\Filesystem::init($this->user, '/' . $this->user . '/files');
\OC\Files\Filesystem::clearMounts();
$this->storageMock = null;
}
public function tearDown() {
$this->user = null;
if ($this->storageMock) {
$this->storageMock->getCache()->clear();
$this->storageMock = null;
}
\OC\Files\Filesystem::tearDown();
\OC_User::setUserId('');
\OC_User::deleteUser($this->user);
\OC_Preferences::deleteUser($this->user);
}
/**
* Returns a storage mock that returns the given value as
* free space
*
* @param int $freeSpace free space value
* @return \OC\Files\Storage\Storage
*/
private function getStorageMock($freeSpace = 12) {
$this->storageMock = $this->getMock(
'\OC\Files\Storage\Temporary',
array('free_space'),
array('')
);
\OC\Files\Filesystem::clearMounts();
$this->storageMock->expects($this->once())
->method('free_space')
->will($this->returnValue(12));
}
public function tearDown() {
$this->user = null;
$this->storageMock->getCache()->clear();
\OC\Files\Filesystem::tearDown();
return $this->storageMock;
}
/**
* Test getting the storage info
*/
function testGetStorageInfo() {
\OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files');
$this->storageMock->file_put_contents('test.txt', '01234');
$homeStorage = $this->getStorageMock(12);
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$homeStorage->file_put_contents('test.txt', '01234');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(12, $storageInfo['free']);
@ -51,18 +74,96 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase {
$this->assertEquals(17, $storageInfo['total']);
}
/**
* Test getting the storage info, ignoring extra mount points
*/
function testGetStorageInfoExcludingExtStorage() {
$homeStorage = $this->getStorageMock(12);
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$homeStorage->file_put_contents('test.txt', '01234');
$extStorage = new \OC\Files\Storage\Temporary(array());
$extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq');
$extStorage->getScanner()->scan(''); // update root size
\OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(12, $storageInfo['free']);
$this->assertEquals(5, $storageInfo['used']);
$this->assertEquals(17, $storageInfo['total']);
}
/**
* Test getting the storage info, including extra mount points
*/
function testGetStorageInfoIncludingExtStorage() {
$homeStorage = new \OC\Files\Storage\Temporary(array());
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$homeStorage->file_put_contents('test.txt', '01234');
$extStorage = new \OC\Files\Storage\Temporary(array());
$extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq');
$extStorage->getScanner()->scan(''); // update root size
\OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext');
$oldConfig = \OC_Config::getValue('quota_include_external_storage', false);
\OC_Config::setValue('quota_include_external_storage', 'true');
$config = \OC::$server->getConfig();
$userQuota = $config->setUserValue($this->user, 'files', 'quota', '25');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(3, $storageInfo['free']);
$this->assertEquals(22, $storageInfo['used']);
$this->assertEquals(25, $storageInfo['total']);
\OC_Config::setValue('quota_include_external_storage', $oldConfig);
$userQuota = $config->setUserValue($this->user, 'files', 'quota', 'default');
}
/**
* Test getting the storage info excluding extra mount points
* when user has no quota set, even when quota ext storage option
* was set
*/
function testGetStorageInfoIncludingExtStorageWithNoUserQuota() {
$homeStorage = $this->getStorageMock(12);
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$homeStorage->file_put_contents('test.txt', '01234');
$extStorage = new \OC\Files\Storage\Temporary(array());
$extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq');
$extStorage->getScanner()->scan(''); // update root size
\OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext');
$oldConfig = \OC_Config::getValue('quota_include_external_storage', false);
\OC_Config::setValue('quota_include_external_storage', 'true');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(12, $storageInfo['free']);
$this->assertEquals(5, $storageInfo['used']);
$this->assertEquals(17, $storageInfo['total']);
\OC_Config::setValue('quota_include_external_storage', $oldConfig);
}
/**
* Test getting the storage info with quota enabled
*/
function testGetStorageInfoWithQuota() {
$this->storageMock->file_put_contents('test.txt', '01234');
$this->storageMock = new \OC\Files\Storage\Wrapper\Quota(
$homeStorage = $this->getStorageMock(12);
$homeStorage->file_put_contents('test.txt', '01234');
$homeStorage = new \OC\Files\Storage\Wrapper\Quota(
array(
'storage' => $this->storageMock,
'storage' => $homeStorage,
'quota' => 7
)
);
\OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files');
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(2, $storageInfo['free']);
@ -74,14 +175,15 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase {
* Test getting the storage info when data exceeds quota
*/
function testGetStorageInfoWhenSizeExceedsQuota() {
$this->storageMock->file_put_contents('test.txt', '0123456789');
$this->storageMock = new \OC\Files\Storage\Wrapper\Quota(
$homeStorage = $this->getStorageMock(12);
$homeStorage->file_put_contents('test.txt', '0123456789');
$homeStorage = new \OC\Files\Storage\Wrapper\Quota(
array(
'storage' => $this->storageMock,
'storage' => $homeStorage,
'quota' => 7
)
);
\OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files');
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(0, $storageInfo['free']);
@ -95,14 +197,15 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase {
* free storage space is less than the quota
*/
function testGetStorageInfoWhenFreeSpaceLessThanQuota() {
$this->storageMock->file_put_contents('test.txt', '01234');
$this->storageMock = new \OC\Files\Storage\Wrapper\Quota(
$homeStorage = $this->getStorageMock(12);
$homeStorage->file_put_contents('test.txt', '01234');
$homeStorage = new \OC\Files\Storage\Wrapper\Quota(
array(
'storage' => $this->storageMock,
'storage' => $homeStorage,
'quota' => 18
)
);
\OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files');
\OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files');
$storageInfo = \OC_Helper::getStorageInfo('');
$this->assertEquals(12, $storageInfo['free']);