Merge pull request #22648 from owncloud/propagate-single

do propagation in a single query
This commit is contained in:
Thomas Müller 2016-04-25 23:01:45 +02:00
commit f6e1b43a38
8 changed files with 57 additions and 30 deletions

View File

@ -33,7 +33,6 @@ class SharedPropagator extends Propagator {
* @param string $internalPath
* @param int $time
* @param int $sizeDifference
* @return \array[] all propagated entries
*/
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
/** @var \OC\Files\Storage\Storage $storage */

View File

@ -332,7 +332,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage {
if (!$storage) {
$storage = $this;
}
return new \OCA\Files_Sharing\SharedPropagator($storage);
return new \OCA\Files_Sharing\SharedPropagator($storage, \OC::$server->getDatabaseConnection());
}
public function getOwner($path) {

View File

@ -32,6 +32,7 @@ class AdapterSqlite extends Adapter {
$statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
$statement = str_replace( '`', '"', $statement );
$statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement );
$statement = str_ireplace('GREATEST(', 'MAX(', $statement);
$statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement );
return $statement;
}

View File

@ -21,14 +21,16 @@
namespace OC\Files\Cache;
use OCP\IDBConnection;
class HomePropagator extends Propagator {
private $ignoredBaseFolders;
/**
* @param \OC\Files\Storage\Storage $storage
*/
public function __construct(\OC\Files\Storage\Storage $storage) {
parent::__construct($storage);
public function __construct(\OC\Files\Storage\Storage $storage, IDBConnection $connection) {
parent::__construct($storage, $connection);
$this->ignoredBaseFolders = ['files_encryption'];
}
@ -37,14 +39,13 @@ class HomePropagator extends Propagator {
* @param string $internalPath
* @param int $time
* @param int $sizeDifference number of bytes the file has grown
* @return array[] all propagated entries
*/
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
list($baseFolder) = explode('/', $internalPath, 2);
if (in_array($baseFolder, $this->ignoredBaseFolders)) {
return [];
} else {
return parent::propagateChange($internalPath, $time, $sizeDifference);
parent::propagateChange($internalPath, $time, $sizeDifference);
}
}
}

View File

@ -21,7 +21,9 @@
namespace OC\Files\Cache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\IPropagator;
use OCP\IDBConnection;
/**
* Propagate etags and mtimes within the storage
@ -33,10 +35,17 @@ class Propagator implements IPropagator {
protected $storage;
/**
* @param \OC\Files\Storage\Storage $storage
* @var IDBConnection
*/
public function __construct(\OC\Files\Storage\Storage $storage) {
private $connection;
/**
* @param \OC\Files\Storage\Storage $storage
* @param IDBConnection $connection
*/
public function __construct(\OC\Files\Storage\Storage $storage, IDBConnection $connection) {
$this->storage = $storage;
$this->connection = $connection;
}
@ -44,31 +53,49 @@ class Propagator implements IPropagator {
* @param string $internalPath
* @param int $time
* @param int $sizeDifference number of bytes the file has grown
* @return array[] all propagated entries
*/
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
$cache = $this->storage->getCache($internalPath);
$storageId = (int)$this->storage->getStorageCache()->getNumericId();
$parentId = $cache->getParentId($internalPath);
$propagatedEntries = [];
while ($parentId !== -1) {
$entry = $cache->get($parentId);
$propagatedEntries[] = $entry;
if (!$entry) {
return $propagatedEntries;
}
$mtime = max($time, $entry['mtime']);
$parents = $this->getParents($internalPath);
if ($entry['size'] === -1) {
$newSize = -1;
} else {
$newSize = $entry['size'] + $sizeDifference;
}
$cache->update($parentId, ['mtime' => $mtime, 'etag' => $this->storage->getETag($entry['path']), 'size' => $newSize]);
$parentHashes = array_map('md5', $parents);
$etag = uniqid(); // since we give all folders the same etag we don't ask the storage for the etag
$parentId = $entry['parent'];
$builder = $this->connection->getQueryBuilder();
$hashParams = array_map(function ($hash) use ($builder) {
return $builder->expr()->literal($hash);
}, $parentHashes);
$builder->update('filecache')
->set('mtime', $builder->createFunction('GREATEST(`mtime`, ' . $builder->createNamedParameter($time) . ')'))
->set('etag', $builder->createNamedParameter($etag, IQueryBuilder::PARAM_STR))
->where($builder->expr()->eq('storage', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)))
->andWhere($builder->expr()->in('path_hash', $hashParams));
$builder->execute();
if ($sizeDifference !== 0) {
// we need to do size separably so we can ignore entries with uncalculated size
$builder = $this->connection->getQueryBuilder();
$builder->update('filecache')
->set('size', $builder->createFunction('`size` + ' . $builder->createNamedParameter($sizeDifference)))
->where($builder->expr()->eq('storage', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)))
->andWhere($builder->expr()->in('path_hash', $hashParams))
->andWhere($builder->expr()->gt('size', $builder->expr()->literal(-1, IQueryBuilder::PARAM_INT)));
}
return $propagatedEntries;
$builder->execute();
}
protected function getParents($path) {
$parts = explode('/', $path);
$parent = '';
$parents = [];
foreach ($parts as $part) {
$parents[] = $parent;
$parent = trim($parent . '/' . $part, '/');
}
return $parents;
}
}

View File

@ -352,7 +352,7 @@ abstract class Common implements Storage, ILockingStorage {
$storage = $this;
}
if (!isset($storage->propagator)) {
$storage->propagator = new Propagator($storage);
$storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection());
}
return $storage->propagator;
}

View File

@ -88,7 +88,7 @@ class Home extends Local implements \OCP\Files\IHomeStorage {
$storage = $this;
}
if (!isset($this->propagator)) {
$this->propagator = new HomePropagator($storage);
$this->propagator = new HomePropagator($storage, \OC::$server->getDatabaseConnection());
}
return $this->propagator;
}

View File

@ -30,7 +30,6 @@ interface IPropagator {
/**
* @param string $internalPath
* @param int $time
* @return array[] all propagated cache entries
* @since 9.0.0
*/
public function propagateChange($internalPath, $time);