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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota {
|
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota {
|
||||||
|
|
||||||
|
@ -31,6 +30,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
*/
|
*/
|
||||||
private $dirContent;
|
private $dirContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached quota info
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $quotaInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new file in the directory
|
* 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
|
// exit if we can't create a new file and we don't updatable existing file
|
||||||
$info = OC_FileChunking::decodeName($name);
|
$info = OC_FileChunking::decodeName($name);
|
||||||
if (!$this->fileView->isCreatable($this->path) &&
|
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();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +108,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPath = $this->path . '/' . $name;
|
$newPath = $this->path . '/' . $name;
|
||||||
if(!$this->fileView->mkdir($newPath)) {
|
if (!$this->fileView->mkdir($newPath)) {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath);
|
throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
|
||||||
}
|
}
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||||
|
@ -152,14 +159,14 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
|
|
||||||
$properties = array();
|
$properties = array();
|
||||||
$paths = array();
|
$paths = array();
|
||||||
foreach($folderContent as $info) {
|
foreach ($folderContent as $info) {
|
||||||
$name = $info->getName();
|
$name = $info->getName();
|
||||||
$paths[] = $this->path . '/' . $name;
|
$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: move this to a beforeGetPropertiesForPath event to pre-cache properties
|
||||||
// TODO: only fetch the requested 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
|
// 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
|
// 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);
|
$chunks = array_chunk($paths, 200, false);
|
||||||
foreach ($chunks as $pack) {
|
foreach ($chunks as $pack) {
|
||||||
$placeholders = join(',', array_fill(0, count($pack), '?'));
|
$placeholders = join(',', array_fill(0, count($pack), '?'));
|
||||||
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`'
|
$query = OC_DB::prepare('SELECT * FROM `*PREFIX*properties`'
|
||||||
.' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
|
. ' WHERE `userid` = ?' . ' AND `propertypath` IN (' . $placeholders . ')');
|
||||||
array_unshift($pack, OC_User::getUser()); // prepend userid
|
array_unshift($pack, OC_User::getUser()); // prepend userid
|
||||||
$result = $query->execute( $pack );
|
$result = $query->execute($pack);
|
||||||
while($row = $result->fetchRow()) {
|
while ($row = $result->fetchRow()) {
|
||||||
$propertypath = $row['propertypath'];
|
$propertypath = $row['propertypath'];
|
||||||
$propertyname = $row['propertyname'];
|
$propertyname = $row['propertyname'];
|
||||||
$propertyvalue = $row['propertyvalue'];
|
$propertyvalue = $row['propertyvalue'];
|
||||||
if($propertyname !== self::GETETAG_PROPERTYNAME) {
|
if ($propertyname !== self::GETETAG_PROPERTYNAME) {
|
||||||
$properties[$propertypath][$propertyname] = $propertyvalue;
|
$properties[$propertypath][$propertyname] = $propertyvalue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +190,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
}
|
}
|
||||||
|
|
||||||
$nodes = array();
|
$nodes = array();
|
||||||
foreach($folderContent as $info) {
|
foreach ($folderContent as $info) {
|
||||||
$node = $this->getChild($info->getName(), $info);
|
$node = $this->getChild($info->getName(), $info);
|
||||||
$node->setPropertyCache($properties[$this->path . '/' . $info->getName()]);
|
$node->setPropertyCache($properties[$this->path . '/' . $info->getName()]);
|
||||||
$nodes[] = $node;
|
$nodes[] = $node;
|
||||||
|
@ -230,15 +237,17 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getQuotaInfo() {
|
public function getQuotaInfo() {
|
||||||
|
if ($this->quotaInfo) {
|
||||||
|
return $this->quotaInfo;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$path = \OC\Files\Filesystem::getView()->getRelativePath($this->info->getPath());
|
$storageInfo = OC_Helper::getStorageInfo($this->info->getPath(), $this->info);
|
||||||
$storageInfo = OC_Helper::getStorageInfo($path);
|
$this->quotaInfo = array(
|
||||||
return array(
|
|
||||||
$storageInfo['used'],
|
$storageInfo['used'],
|
||||||
$storageInfo['free']
|
$storageInfo['free']
|
||||||
);
|
);
|
||||||
}
|
return $this->quotaInfo;
|
||||||
catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||||
return array(0, 0);
|
return array(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,4 +155,34 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase {
|
||||||
$nodes[1]->getProperties($properties)
|
$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