diff options
Diffstat (limited to 'lib/private/Files/Cache')
-rw-r--r-- | lib/private/Files/Cache/HomePropagator.php | 9 | ||||
-rw-r--r-- | lib/private/Files/Cache/Propagator.php | 67 |
2 files changed, 52 insertions, 24 deletions
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; } } |