diff options
author | Thomas Müller <DeepDiver1975@users.noreply.github.com> | 2016-04-25 23:01:45 +0200 |
---|---|---|
committer | Thomas Müller <DeepDiver1975@users.noreply.github.com> | 2016-04-25 23:01:45 +0200 |
commit | f6e1b43a38823b53b3fb80ec78fe6faddb367312 (patch) | |
tree | 84ce88cdcd402ae56122c3b3758455a3a516a9ac /lib/private | |
parent | 9c6ba6b123d28078ae914dd0a8add55361141aba (diff) | |
parent | dbfdc6282af2c00deece8196684b7c67a1064bb4 (diff) | |
download | nextcloud-server-f6e1b43a38823b53b3fb80ec78fe6faddb367312.tar.gz nextcloud-server-f6e1b43a38823b53b3fb80ec78fe6faddb367312.zip |
Merge pull request #22648 from owncloud/propagate-single
do propagation in a single query
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/DB/AdapterSqlite.php | 1 | ||||
-rw-r--r-- | lib/private/Files/Cache/HomePropagator.php | 9 | ||||
-rw-r--r-- | lib/private/Files/Cache/Propagator.php | 67 | ||||
-rw-r--r-- | lib/private/Files/Storage/Common.php | 2 | ||||
-rw-r--r-- | lib/private/Files/Storage/Home.php | 2 |
5 files changed, 55 insertions, 26 deletions
diff --git a/lib/private/DB/AdapterSqlite.php b/lib/private/DB/AdapterSqlite.php index d7769238abc..3466e0e1aac 100644 --- a/lib/private/DB/AdapterSqlite.php +++ b/lib/private/DB/AdapterSqlite.php @@ -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; } diff --git a/lib/private/Files/Cache/HomePropagator.php b/lib/private/Files/Cache/HomePropagator.php index 8edca9c0c87..db9e30ae0fc 100644 --- a/lib/private/Files/Cache/HomePropagator.php +++ b/lib/private/Files/Cache/HomePropagator.php @@ -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); } } } diff --git a/lib/private/Files/Cache/Propagator.php b/lib/private/Files/Cache/Propagator.php index 50264e54d44..b998c6bcfae 100644 --- a/lib/private/Files/Cache/Propagator.php +++ b/lib/private/Files/Cache/Propagator.php @@ -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; /** + * @var IDBConnection + */ + private $connection; + + /** * @param \OC\Files\Storage\Storage $storage + * @param IDBConnection $connection */ - public function __construct(\OC\Files\Storage\Storage $storage) { + 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(); + + $parents = $this->getParents($internalPath); + + $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 = $cache->getParentId($internalPath); - $propagatedEntries = []; - while ($parentId !== -1) { - $entry = $cache->get($parentId); - $propagatedEntries[] = $entry; - if (!$entry) { - return $propagatedEntries; - } - $mtime = max($time, $entry['mtime']); + $builder = $this->connection->getQueryBuilder(); + $hashParams = array_map(function ($hash) use ($builder) { + return $builder->expr()->literal($hash); + }, $parentHashes); - if ($entry['size'] === -1) { - $newSize = -1; - } else { - $newSize = $entry['size'] + $sizeDifference; - } - $cache->update($parentId, ['mtime' => $mtime, 'etag' => $this->storage->getETag($entry['path']), 'size' => $newSize]); + $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)); - $parentId = $entry['parent']; + $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; } } diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index 3a811b312c6..6382dbd26b1 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -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; } diff --git a/lib/private/Files/Storage/Home.php b/lib/private/Files/Storage/Home.php index 9b98f2f7e12..19ba217fa42 100644 --- a/lib/private/Files/Storage/Home.php +++ b/lib/private/Files/Storage/Home.php @@ -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; } |