do propagation in a single query
This commit is contained in:
parent
6321596134
commit
dbfdc6282a
|
@ -33,7 +33,6 @@ class SharedPropagator extends Propagator {
|
||||||
* @param string $internalPath
|
* @param string $internalPath
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @param int $sizeDifference
|
* @param int $sizeDifference
|
||||||
* @return \array[] all propagated entries
|
|
||||||
*/
|
*/
|
||||||
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
||||||
/** @var \OC\Files\Storage\Storage $storage */
|
/** @var \OC\Files\Storage\Storage $storage */
|
||||||
|
|
|
@ -332,7 +332,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage {
|
||||||
if (!$storage) {
|
if (!$storage) {
|
||||||
$storage = $this;
|
$storage = $this;
|
||||||
}
|
}
|
||||||
return new \OCA\Files_Sharing\SharedPropagator($storage);
|
return new \OCA\Files_Sharing\SharedPropagator($storage, \OC::$server->getDatabaseConnection());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOwner($path) {
|
public function getOwner($path) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ class AdapterSqlite extends Adapter {
|
||||||
$statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
|
$statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
|
||||||
$statement = str_replace( '`', '"', $statement );
|
$statement = str_replace( '`', '"', $statement );
|
||||||
$statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement );
|
$statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement );
|
||||||
|
$statement = str_ireplace('GREATEST(', 'MAX(', $statement);
|
||||||
$statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement );
|
$statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement );
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,16 @@
|
||||||
|
|
||||||
namespace OC\Files\Cache;
|
namespace OC\Files\Cache;
|
||||||
|
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
class HomePropagator extends Propagator {
|
class HomePropagator extends Propagator {
|
||||||
private $ignoredBaseFolders;
|
private $ignoredBaseFolders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \OC\Files\Storage\Storage $storage
|
* @param \OC\Files\Storage\Storage $storage
|
||||||
*/
|
*/
|
||||||
public function __construct(\OC\Files\Storage\Storage $storage) {
|
public function __construct(\OC\Files\Storage\Storage $storage, IDBConnection $connection) {
|
||||||
parent::__construct($storage);
|
parent::__construct($storage, $connection);
|
||||||
$this->ignoredBaseFolders = ['files_encryption'];
|
$this->ignoredBaseFolders = ['files_encryption'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +39,13 @@ class HomePropagator extends Propagator {
|
||||||
* @param string $internalPath
|
* @param string $internalPath
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @param int $sizeDifference number of bytes the file has grown
|
* @param int $sizeDifference number of bytes the file has grown
|
||||||
* @return array[] all propagated entries
|
|
||||||
*/
|
*/
|
||||||
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
||||||
list($baseFolder) = explode('/', $internalPath, 2);
|
list($baseFolder) = explode('/', $internalPath, 2);
|
||||||
if (in_array($baseFolder, $this->ignoredBaseFolders)) {
|
if (in_array($baseFolder, $this->ignoredBaseFolders)) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
return parent::propagateChange($internalPath, $time, $sizeDifference);
|
parent::propagateChange($internalPath, $time, $sizeDifference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
|
|
||||||
namespace OC\Files\Cache;
|
namespace OC\Files\Cache;
|
||||||
|
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\Cache\IPropagator;
|
use OCP\Files\Cache\IPropagator;
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Propagate etags and mtimes within the storage
|
* Propagate etags and mtimes within the storage
|
||||||
|
@ -33,10 +35,17 @@ class Propagator implements IPropagator {
|
||||||
protected $storage;
|
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->storage = $storage;
|
||||||
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,31 +53,49 @@ class Propagator implements IPropagator {
|
||||||
* @param string $internalPath
|
* @param string $internalPath
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @param int $sizeDifference number of bytes the file has grown
|
* @param int $sizeDifference number of bytes the file has grown
|
||||||
* @return array[] all propagated entries
|
|
||||||
*/
|
*/
|
||||||
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
public function propagateChange($internalPath, $time, $sizeDifference = 0) {
|
||||||
$cache = $this->storage->getCache($internalPath);
|
$storageId = (int)$this->storage->getStorageCache()->getNumericId();
|
||||||
|
|
||||||
$parentId = $cache->getParentId($internalPath);
|
$parents = $this->getParents($internalPath);
|
||||||
$propagatedEntries = [];
|
|
||||||
while ($parentId !== -1) {
|
|
||||||
$entry = $cache->get($parentId);
|
|
||||||
$propagatedEntries[] = $entry;
|
|
||||||
if (!$entry) {
|
|
||||||
return $propagatedEntries;
|
|
||||||
}
|
|
||||||
$mtime = max($time, $entry['mtime']);
|
|
||||||
|
|
||||||
if ($entry['size'] === -1) {
|
$parentHashes = array_map('md5', $parents);
|
||||||
$newSize = -1;
|
$etag = uniqid(); // since we give all folders the same etag we don't ask the storage for the etag
|
||||||
} else {
|
|
||||||
$newSize = $entry['size'] + $sizeDifference;
|
|
||||||
}
|
|
||||||
$cache->update($parentId, ['mtime' => $mtime, 'etag' => $this->storage->getETag($entry['path']), 'size' => $newSize]);
|
|
||||||
|
|
||||||
$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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,7 +352,7 @@ abstract class Common implements Storage, ILockingStorage {
|
||||||
$storage = $this;
|
$storage = $this;
|
||||||
}
|
}
|
||||||
if (!isset($storage->propagator)) {
|
if (!isset($storage->propagator)) {
|
||||||
$storage->propagator = new Propagator($storage);
|
$storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection());
|
||||||
}
|
}
|
||||||
return $storage->propagator;
|
return $storage->propagator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ class Home extends Local implements \OCP\Files\IHomeStorage {
|
||||||
$storage = $this;
|
$storage = $this;
|
||||||
}
|
}
|
||||||
if (!isset($this->propagator)) {
|
if (!isset($this->propagator)) {
|
||||||
$this->propagator = new HomePropagator($storage);
|
$this->propagator = new HomePropagator($storage, \OC::$server->getDatabaseConnection());
|
||||||
}
|
}
|
||||||
return $this->propagator;
|
return $this->propagator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ interface IPropagator {
|
||||||
/**
|
/**
|
||||||
* @param string $internalPath
|
* @param string $internalPath
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @return array[] all propagated cache entries
|
|
||||||
* @since 9.0.0
|
* @since 9.0.0
|
||||||
*/
|
*/
|
||||||
public function propagateChange($internalPath, $time);
|
public function propagateChange($internalPath, $time);
|
||||||
|
|
Loading…
Reference in New Issue