Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Filecache chunking #43576

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,7 @@
'OC\\Files\\Cache\\CacheDependencies' => $baseDir . '/lib/private/Files/Cache/CacheDependencies.php',
'OC\\Files\\Cache\\CacheEntry' => $baseDir . '/lib/private/Files/Cache/CacheEntry.php',
'OC\\Files\\Cache\\CacheQueryBuilder' => $baseDir . '/lib/private/Files/Cache/CacheQueryBuilder.php',
'OC\\Files\\Cache\\Database' => $baseDir . '/lib/private/Files/Cache/Database.php',
'OC\\Files\\Cache\\FailedCache' => $baseDir . '/lib/private/Files/Cache/FailedCache.php',
'OC\\Files\\Cache\\FileAccess' => $baseDir . '/lib/private/Files/Cache/FileAccess.php',
'OC\\Files\\Cache\\HomeCache' => $baseDir . '/lib/private/Files/Cache/HomeCache.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Files\\Cache\\CacheDependencies' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheDependencies.php',
'OC\\Files\\Cache\\CacheEntry' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheEntry.php',
'OC\\Files\\Cache\\CacheQueryBuilder' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheQueryBuilder.php',
'OC\\Files\\Cache\\Database' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Database.php',
'OC\\Files\\Cache\\FailedCache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/FailedCache.php',
'OC\\Files\\Cache\\FileAccess' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/FileAccess.php',
'OC\\Files\\Cache\\HomeCache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/HomeCache.php',
Expand Down
49 changes: 49 additions & 0 deletions lib/private/DB/QueryBuilder/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@
/** @var string */
protected $lastInsertedTable;

/**
* Tables that require special attention and thus can't be queried by default
*
* @var list<string>
*/
protected array $shardedTables = [
'filecache',
'filecache_extended',
'files_metadata'
];

protected bool $sharded = false;

/**
* Initializes a new QueryBuilder.
*
Expand Down Expand Up @@ -662,6 +675,17 @@
return $this;
}

/**
* @param string $table
* @return void
* @throws \Exception
*/
private function checkTableAccess(string $table) {
if (in_array($table, $this->shardedTables) !== $this->sharded) {
throw new \Exception("current query isn't allowed to access the $table table");
}
}

/**
* Creates and adds a query root corresponding to the table identified by the
* given alias, forming a cartesian product with any existing query roots.
Expand All @@ -678,6 +702,7 @@
* @return $this This QueryBuilder instance.
*/
public function from($from, $alias = null) {
$this->checkTableAccess($from);

Check failure on line 705 in lib/private/DB/QueryBuilder/QueryBuilder.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

ImplicitToStringCast

lib/private/DB/QueryBuilder/QueryBuilder.php:705:27: ImplicitToStringCast: Argument 1 of OC\DB\QueryBuilder\QueryBuilder::checkTableAccess expects string, but OCP\DB\QueryBuilder\IQueryFunction|string provided with a __toString method (see https://psalm.dev/060)

Check failure

Code scanning / Psalm

ImplicitToStringCast Error

Argument 1 of OC\DB\QueryBuilder\QueryBuilder::checkTableAccess expects string, but OCP\DB\QueryBuilder\IQueryFunction|string provided with a __toString method
$this->queryBuilder->from(
$this->getTableName($from),
$this->quoteAlias($alias)
Expand All @@ -704,6 +729,8 @@
* @return $this This QueryBuilder instance.
*/
public function join($fromAlias, $join, $alias, $condition = null) {
$this->checkTableAccess($join);

$this->queryBuilder->join(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
Expand Down Expand Up @@ -732,6 +759,8 @@
* @return $this This QueryBuilder instance.
*/
public function innerJoin($fromAlias, $join, $alias, $condition = null) {
$this->checkTableAccess($join);

$this->queryBuilder->innerJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
Expand Down Expand Up @@ -760,6 +789,8 @@
* @return $this This QueryBuilder instance.
*/
public function leftJoin($fromAlias, $join, $alias, $condition = null) {
$this->checkTableAccess($join);

$this->queryBuilder->leftJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
Expand Down Expand Up @@ -788,6 +819,8 @@
* @return $this This QueryBuilder instance.
*/
public function rightJoin($fromAlias, $join, $alias, $condition = null) {
$this->checkTableAccess($join);

$this->queryBuilder->rightJoin(
$this->quoteAlias($fromAlias),
$this->getTableName($join),
Expand Down Expand Up @@ -1337,4 +1370,20 @@

return $this->helper->quoteColumnName($alias);
}

public function escapeLikeParameter(string $parameter): string {
return $this->connection->escapeLikeParameter($parameter);
}

/**
* Mark the query as accessing the sharded tables
*
* Proper attention needs to be given to ensure that all requirements for accessing the sharded tables
*
* @param bool $sharded
* @return void
*/
public function setSharded(bool $sharded): void {
$this->sharded = $sharded;
}
}
71 changes: 23 additions & 48 deletions lib/private/Files/Cache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
use OCP\Files\Search\ISearchQuery;
use OCP\Files\Storage\IStorage;
use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IDBConnection;
use OCP\Server;
use OCP\Util;
use Psr\Log\LoggerInterface;

Expand All @@ -88,7 +88,7 @@
protected string $storageId;
protected Storage $storageCache;
protected IMimeTypeLoader$mimetypeLoader;
protected IDBConnection $connection;
protected CacheDatabase $cacheDb;
protected SystemConfig $systemConfig;
protected LoggerInterface $logger;
protected QuerySearchHelper $querySearchHelper;
Expand All @@ -106,25 +106,20 @@
$this->storageId = md5($this->storageId);
}
if (!$dependencies) {
$dependencies = \OC::$server->get(CacheDependencies::class);
$dependencies = Server::get(CacheDependencies::class);
}
$this->storageCache = new Storage($this->storage, true, $dependencies->getConnection());
$this->mimetypeLoader = $dependencies->getMimeTypeLoader();
$this->connection = $dependencies->getConnection();
$this->cacheDb = $dependencies->getCacheDb();
$this->systemConfig = $dependencies->getSystemConfig();
$this->logger = $dependencies->getLogger();
$this->querySearchHelper = $dependencies->getQuerySearchHelper();
$this->eventDispatcher = $dependencies->getEventDispatcher();
$this->metadataManager = $dependencies->getMetadataManager();
}

protected function getQueryBuilder() {
return new CacheQueryBuilder(
$this->connection,
$this->systemConfig,
$this->logger,
$this->metadataManager,
);
public function getQueryBuilder() {
return $this->cacheDb->queryForStorageId($this->getNumericStorageId());
}

public function getStorageCache(): Storage {
Expand All @@ -149,7 +144,7 @@
public function get($file) {
$query = $this->getQueryBuilder();
$query->selectFileCache();
$metadataQuery = $query->selectMetadata();
$metadataQuery = $query->selectMetadata($this->metadataManager);

if (is_string($file) || $file == '') {
// normalize file
Expand Down Expand Up @@ -236,7 +231,7 @@
->whereParent($fileId)
->orderBy('name', 'ASC');

$metadataQuery = $query->selectMetadata();
$metadataQuery = $query->selectMetadata($this->metadataManager);

$result = $query->execute();
$files = $result->fetchAll();
Expand Down Expand Up @@ -305,7 +300,7 @@
$values['storage'] = $storageId;

try {
$builder = $this->connection->getQueryBuilder();
$builder = $this->getQueryBuilder();
$builder->insert('filecache');

foreach ($values as $column => $value) {
Expand Down Expand Up @@ -333,9 +328,9 @@
}
} catch (UniqueConstraintViolationException $e) {
// entry exists already
if ($this->connection->inTransaction()) {
$this->connection->commit();
$this->connection->beginTransaction();
if ($this->cacheDb->inTransaction($this->getNumericStorageId())) {
$this->cacheDb->commit($this->getNumericStorageId());
$this->cacheDb->beginTransaction($this->getNumericStorageId());
}
}

Expand Down Expand Up @@ -699,7 +694,7 @@
if ($sourceData['mimetype'] === 'httpd/unix-directory') {
//update all child entries
$sourceLength = mb_strlen($sourcePath);
$query = $this->connection->getQueryBuilder();
$query = $this->getQueryBuilder();

$fun = $query->func();
$newPathFunction = $fun->concat(
Expand All @@ -711,7 +706,7 @@
->set('path_hash', $fun->md5($newPathFunction))
->set('path', $newPathFunction)
->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%')));
->andWhere($query->expr()->like('path', $query->createNamedParameter($query->escapeLikeParameter($sourcePath) . '/%')));

// when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark
if ($sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) {
Expand All @@ -723,26 +718,26 @@
$retryLimit = 4;
for ($i = 1; $i <= $retryLimit; $i++) {
try {
$this->connection->beginTransaction();
$this->cacheDb->beginTransaction();

Check failure on line 721 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:721:23: TooFewArguments: Too few arguments for OC\Files\Cache\CacheDatabase::beginTransaction - expecting storageId to be passed (see https://psalm.dev/025)

Check failure on line 721 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:721:23: TooFewArguments: Too few arguments for method OC\Files\Cache\CacheDatabase::begintransaction saw 0 (see https://psalm.dev/025)

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for OC\Files\Cache\CacheDatabase::beginTransaction - expecting storageId to be passed

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for method OC\Files\Cache\CacheDatabase::begintransaction saw 0
$query->executeStatement();
break;
} catch (\OC\DatabaseException $e) {
$this->connection->rollBack();
$this->cacheDb->rollBack($this->getNumericStorageId());
throw $e;
} catch (RetryableException $e) {
// Simply throw if we already retried 4 times.
if ($i === $retryLimit) {
throw $e;
}

$this->connection->rollBack();
$this->cacheDb->rollBack();

Check failure on line 733 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:733:23: TooFewArguments: Too few arguments for OC\Files\Cache\CacheDatabase::rollBack - expecting storageId to be passed (see https://psalm.dev/025)

Check failure on line 733 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:733:23: TooFewArguments: Too few arguments for method OC\Files\Cache\CacheDatabase::rollback saw 0 (see https://psalm.dev/025)

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for OC\Files\Cache\CacheDatabase::rollBack - expecting storageId to be passed

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for method OC\Files\Cache\CacheDatabase::rollback saw 0

// Sleep a bit to give some time to the other transaction to finish.
usleep(100 * 1000 * $i);
}
}
} else {
$this->connection->beginTransaction();
$this->cacheDb->beginTransaction();

Check failure on line 740 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:740:21: TooFewArguments: Too few arguments for OC\Files\Cache\CacheDatabase::beginTransaction - expecting storageId to be passed (see https://psalm.dev/025)

Check failure on line 740 in lib/private/Files/Cache/Cache.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

TooFewArguments

lib/private/Files/Cache/Cache.php:740:21: TooFewArguments: Too few arguments for method OC\Files\Cache\CacheDatabase::begintransaction saw 0 (see https://psalm.dev/025)

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for OC\Files\Cache\CacheDatabase::beginTransaction - expecting storageId to be passed

Check failure

Code scanning / Psalm

TooFewArguments Error

Too few arguments for method OC\Files\Cache\CacheDatabase::begintransaction saw 0
}

$query = $this->getQueryBuilder();
Expand All @@ -761,7 +756,7 @@

$query->execute();

$this->connection->commit();
$this->cacheDb->commit($this->getNumericStorageId());

if ($sourceCache->getNumericStorageId() !== $this->getNumericStorageId()) {
$this->eventDispatcher->dispatchTyped(new CacheEntryRemovedEvent($this->storage, $sourcePath, $sourceId, $sourceCache->getNumericStorageId()));
Expand All @@ -787,7 +782,7 @@
->whereStorageId($this->getNumericStorageId());
$query->execute();

$query = $this->connection->getQueryBuilder();
$query = $this->getQueryBuilder();
$query->delete('storages')
->where($query->expr()->eq('id', $query->createNamedParameter($this->storageId)));
$query->execute();
Expand Down Expand Up @@ -861,8 +856,8 @@
return $this->searchQuery(new SearchQuery($operator, 0, 0, [], null));
}

public function searchQuery(ISearchQuery $searchQuery) {
return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
public function searchQuery(ISearchQuery $query) {
return current($this->querySearchHelper->searchInCaches($query, [$this]));
}

/**
Expand Down Expand Up @@ -1099,27 +1094,7 @@
* @deprecated use getPathById() instead
*/
public static function getById($id) {
$query = \OC::$server->getDatabaseConnection()->getQueryBuilder();
$query->select('path', 'storage')
->from('filecache')
->where($query->expr()->eq('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));

$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();

if ($row) {
$numericId = $row['storage'];
$path = $row['path'];
} else {
return null;
}

if ($id = Storage::getStorageId($numericId)) {
return [$id, $path];
} else {
return null;
}
throw new \Exception("Cache::getById has been removed");
}

/**
Expand Down
Loading
Loading