Merge pull request #14207 from owncloud/propfind-optimize
Optimize quota calculation for propfind
This commit is contained in:
commit
5d7d2adcbf
2 changed files with 57 additions and 18 deletions
|
@ -20,7 +20,6 @@
|
|||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
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,17 @@ 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(
|
||||
$storageInfo = OC_Helper::getStorageInfo($this->info->getPath(), $this->info);
|
||||
$this->quotaInfo = array(
|
||||
$storageInfo['used'],
|
||||
$storageInfo['free']
|
||||
);
|
||||
}
|
||||
catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
return $this->quotaInfo;
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
return array(0, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue