From fb2a3284dfff5c52ba603d672fbb11cd88942bc6 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 13 Feb 2015 16:01:16 +0100 Subject: [PATCH 1/3] Cache quota info for directories --- lib/private/connector/sabre/directory.php | 42 ++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index c878e5ee4b..702addfe52 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -20,7 +20,6 @@ * License along with this library. If not, see . * */ - class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota { @@ -31,6 +30,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node */ private $dirContent; + /** + * Cached quota info + * + * @var array + */ + private $quotaInfo; + /** * Creates a new file in the directory * @@ -66,7 +72,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node // exit if we can't create a new file and we don't updatable existing file $info = OC_FileChunking::decodeName($name); if (!$this->fileView->isCreatable($this->path) && - !$this->fileView->isUpdatable($this->path . '/' . $info['name'])) { + !$this->fileView->isUpdatable($this->path . '/' . $info['name']) + ) { throw new \Sabre\DAV\Exception\Forbidden(); } @@ -101,8 +108,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node } $newPath = $this->path . '/' . $name; - if(!$this->fileView->mkdir($newPath)) { - throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath); + if (!$this->fileView->mkdir($newPath)) { + throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath); } } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); @@ -152,14 +159,14 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node $properties = array(); $paths = array(); - foreach($folderContent as $info) { + foreach ($folderContent as $info) { $name = $info->getName(); $paths[] = $this->path . '/' . $name; - $properties[$this->path.'/' . $name][self::GETETAG_PROPERTYNAME] = '"' . $info->getEtag() . '"'; + $properties[$this->path . '/' . $name][self::GETETAG_PROPERTYNAME] = '"' . $info->getEtag() . '"'; } // TODO: move this to a beforeGetPropertiesForPath event to pre-cache properties // TODO: only fetch the requested properties - if(count($paths)>0) { + if (count($paths) > 0) { // // the number of arguments within IN conditions are limited in most databases // we chunk $paths into arrays of 200 items each to meet this criteria @@ -167,15 +174,15 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node $chunks = array_chunk($paths, 200, false); foreach ($chunks as $pack) { $placeholders = join(',', array_fill(0, count($pack), '?')); - $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`' - .' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' ); + $query = OC_DB::prepare('SELECT * FROM `*PREFIX*properties`' + . ' WHERE `userid` = ?' . ' AND `propertypath` IN (' . $placeholders . ')'); array_unshift($pack, OC_User::getUser()); // prepend userid - $result = $query->execute( $pack ); - while($row = $result->fetchRow()) { + $result = $query->execute($pack); + while ($row = $result->fetchRow()) { $propertypath = $row['propertypath']; $propertyname = $row['propertyname']; $propertyvalue = $row['propertyvalue']; - if($propertyname !== self::GETETAG_PROPERTYNAME) { + if ($propertyname !== self::GETETAG_PROPERTYNAME) { $properties[$propertypath][$propertyname] = $propertyvalue; } } @@ -183,7 +190,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node } $nodes = array(); - foreach($folderContent as $info) { + foreach ($folderContent as $info) { $node = $this->getChild($info->getName(), $info); $node->setPropertyCache($properties[$this->path . '/' . $info->getName()]); $nodes[] = $node; @@ -230,15 +237,18 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node * @return array */ public function getQuotaInfo() { + if ($this->quotaInfo) { + return $this->quotaInfo; + } try { $path = \OC\Files\Filesystem::getView()->getRelativePath($this->info->getPath()); $storageInfo = OC_Helper::getStorageInfo($path); - return array( + $this->quotaInfo = array( $storageInfo['used'], $storageInfo['free'] ); - } - catch (\OCP\Files\StorageNotAvailableException $e) { + return $this->quotaInfo; + } catch (\OCP\Files\StorageNotAvailableException $e) { return array(0, 0); } } From 9abaa0cc615ba5326a3990ad79b94e46db423cf2 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 13 Feb 2015 16:01:28 +0100 Subject: [PATCH 2/3] pass fileinfo to getStorageInfo --- lib/private/connector/sabre/directory.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 702addfe52..7c35bfa179 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -241,8 +241,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node return $this->quotaInfo; } try { - $path = \OC\Files\Filesystem::getView()->getRelativePath($this->info->getPath()); - $storageInfo = OC_Helper::getStorageInfo($path); + $storageInfo = OC_Helper::getStorageInfo($this->info->getPath(), $this->info); $this->quotaInfo = array( $storageInfo['used'], $storageInfo['free'] From 7bfe476030764f851d92f5c80ae8b798d074210b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 13 Feb 2015 17:59:47 +0100 Subject: [PATCH 3/3] add unit test for webdav quota --- tests/lib/connector/sabre/directory.php | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/lib/connector/sabre/directory.php b/tests/lib/connector/sabre/directory.php index e9bfea81b7..599a6ca3f7 100644 --- a/tests/lib/connector/sabre/directory.php +++ b/tests/lib/connector/sabre/directory.php @@ -155,4 +155,34 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { $nodes[1]->getProperties($properties) ); } + + public function testGetQuotaInfo() { + $storage = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Quota') + ->disableOriginalConstructor() + ->getMock(); + + $storage->expects($this->once()) + ->method('instanceOfStorage') + ->with('\OC\Files\Storage\Wrapper\Quota') + ->will($this->returnValue(true)); + + $storage->expects($this->once()) + ->method('getQuota') + ->will($this->returnValue(1000)); + + $storage->expects($this->once()) + ->method('free_space') + ->will($this->returnValue(800)); + + $this->info->expects($this->once()) + ->method('getSize') + ->will($this->returnValue(200)); + + $this->info->expects($this->once()) + ->method('getStorage') + ->will($this->returnValue($storage)); + + $dir = new OC_Connector_Sabre_Directory($this->view, $this->info); + $this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free + } }