diff options
author | Robin Appelman <icewind@owncloud.com> | 2016-02-25 13:14:20 +0100 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2016-04-25 16:18:59 +0200 |
commit | dbfdc6282af2c00deece8196684b7c67a1064bb4 (patch) | |
tree | 3dacb071aa5f882d43222b49091bd60d879cf668 /lib/private/Files/Cache/Propagator.php | |
parent | 632159613447796b5bb7dbe3a17c194573b18b4a (diff) | |
download | nextcloud-server-dbfdc6282af2c00deece8196684b7c67a1064bb4.tar.gz nextcloud-server-dbfdc6282af2c00deece8196684b7c67a1064bb4.zip |
do propagation in a single query
Diffstat (limited to 'lib/private/Files/Cache/Propagator.php')
-rw-r--r-- | lib/private/Files/Cache/Propagator.php | 67 |
1 files changed, 47 insertions, 20 deletions
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; } } |