Skip to content
Snippets Groups Projects
Commit f0caf412 authored by Vincent Petry's avatar Vincent Petry Committed by Joas Schilling
Browse files

Cleanup job for system and user tag orphaned when file was deleted

Whenever a file was deleted (also from trash), the tag mapping is
pointing at a fileid that doesn't exist any more.

This cleanup job will delete such orphaned mapping entries.
parent 1765e11f
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<author>Robin Appelman, Vincent Petry</author> <author>Robin Appelman, Vincent Petry</author>
<standalone/> <standalone/>
<default_enable/> <default_enable/>
<version>1.4.1</version> <version>1.4.2</version>
<types> <types>
<filesystem/> <filesystem/>
</types> </types>
......
...@@ -20,7 +20,5 @@ ...@@ -20,7 +20,5 @@
*/ */
// Cron job for scanning user storages // Cron job for scanning user storages
$jobList = \OC::$server->getJobList(); \OC::$server->getJobList()->add('OCA\Files\BackgroundJob\ScanFiles');
$job = 'OCA\Files\BackgroundJob\ScanFiles'; \OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedTagsJob');
\OC::$server->getJobList()->add($job);
...@@ -98,15 +98,5 @@ if ($installedVersion === '1.1.9' && ( ...@@ -98,15 +98,5 @@ if ($installedVersion === '1.1.9' && (
} }
// Add cron job for scanning user storages // Add cron job for scanning user storages
$jobList = \OC::$server->getJobList(); \OC::$server->getJobList()->add('OCA\Files\BackgroundJob\ScanFiles');
$job = 'OCA\Files\BackgroundJob\ScanFiles'; \OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedTagsJob');
\OC::$server->getJobList()->add($job);
/**
* migrate old constant DEBUG to new config value 'debug'
*
* TODO: remove this in ownCloud 8.3
*/
if(defined('DEBUG') && DEBUG === true) {
\OC::$server->getConfig()->setSystemValue('debug', true);
}
<?php
/**
* @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files\BackgroundJob;
use OC\BackgroundJob\TimedJob;
/**
* Delete all share entries that have no matching entries in the file cache table.
*/
class DeleteOrphanedTagsJob extends TimedJob {
/** @var \OCP\IDBConnection */
protected $connection;
/** @var \OCP\ILogger */
protected $logger;
/**
* Default interval in minutes
*
* @var int $defaultIntervalMin
**/
protected $defaultIntervalMin = 60;
/**
* sets the correct interval for this timed job
*/
public function __construct() {
$this->interval = $this->defaultIntervalMin * 60;
$this->connection = \OC::$server->getDatabaseConnection();
$this->logger = \OC::$server->getLogger();
}
/**
* Makes the background job do its work
*
* @param array $argument unused argument
*/
public function run($argument) {
$this->cleanSystemTags();
$this->cleanUserTags();
}
/**
* Deleting orphaned system tag mappings
*
* @return int Number of deleted entries
*/
protected function cleanSystemTags() {
$subQuery = $this->connection->getQueryBuilder();
$subQuery->select($subQuery->expr()->literal('1'))
->from('filecache', 'f')
->where($subQuery->expr()->eq('objectid', 'f.fileid'));
$query = $this->connection->getQueryBuilder();
$deletedEntries = $query->delete('systemtag_object_mapping')
->where($query->expr()->eq('objecttype', $query->expr()->literal('files')))
->andWhere($query->expr()->isNull($query->createFunction('(' . $subQuery->getSql() . ')')))
->execute();
$this->logger->debug("$deletedEntries orphaned system tag relations deleted", ['app' => 'DeleteOrphanedTagsJob']);
return $deletedEntries;
}
/**
* Deleting orphaned user tag mappings
*
* @return int Number of deleted entries
*/
protected function cleanUserTags() {
$subQuery = $this->connection->getQueryBuilder();
$subQuery->select($subQuery->expr()->literal('1'))
->from('filecache', 'f')
->where($subQuery->expr()->eq('objid', 'f.fileid'));
$query = $this->connection->getQueryBuilder();
$deletedEntries = $query->delete('vcategory_to_object')
->where($query->expr()->eq('type', $query->expr()->literal('files')))
->andWhere($query->expr()->isNull($query->createFunction('(' . $subQuery->getSql() . ')')))
->execute();
$this->logger->debug("$deletedEntries orphaned user tag relations deleted", ['app' => 'DeleteOrphanedTagsJob']);
return $deletedEntries;
}
}
<?php
/**
* @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files\Tests\BackgroundJob;
use OCA\Files\BackgroundJob\DeleteOrphanedTagsJob;
use OCP\DB\QueryBuilder\IQueryBuilder;
/**
* Class DeleteOrphanedTagsJobTest
*
* @group DB
*
* @package Test\BackgroundJob
*/
class DeleteOrphanedTagsJobTest extends \Test\TestCase {
/** @var \OCP\IDBConnection */
protected $connection;
protected function setup() {
parent::setUp();
$this->connection = \OC::$server->getDatabaseConnection();
}
protected function cleanMapping($table) {
$query = $this->connection->getQueryBuilder();
$query->delete($table)->execute();
}
protected function getMappings($table) {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from($table);
$result = $query->execute();
$mapping = $result->fetchAll();
$result->closeCursor();
return $mapping;
}
/**
* Test clearing orphaned system tag mappings
*/
public function testClearSystemTagMappings() {
$this->cleanMapping('systemtag_object_mapping');
$query = $this->connection->getQueryBuilder();
$query->insert('filecache')
->values([
'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'),
'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')),
])->execute();
$fileId = $query->getLastInsertId();
// Existing file
$query = $this->connection->getQueryBuilder();
$query->insert('systemtag_object_mapping')
->values([
'objectid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
'objecttype' => $query->createNamedParameter('files'),
'systemtagid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
])->execute();
// Non-existing file
$query = $this->connection->getQueryBuilder();
$query->insert('systemtag_object_mapping')
->values([
'objectid' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT),
'objecttype' => $query->createNamedParameter('files'),
'systemtagid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
])->execute();
$mapping = $this->getMappings('systemtag_object_mapping');
$this->assertCount(2, $mapping);
$job = new DeleteOrphanedTagsJob();
$this->invokePrivate($job, 'cleanSystemTags');
$mapping = $this->getMappings('systemtag_object_mapping');
$this->assertCount(1, $mapping);
$query = $this->connection->getQueryBuilder();
$query->delete('filecache')
->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
->execute();
$this->cleanMapping('systemtag_object_mapping');
}
/**
* Test clearing orphaned system tag mappings
*/
public function testClearUserTagMappings() {
$this->cleanMapping('vcategory_to_object');
$query = $this->connection->getQueryBuilder();
$query->insert('filecache')
->values([
'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'),
'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')),
])->execute();
$fileId = $query->getLastInsertId();
// Existing file
$query = $this->connection->getQueryBuilder();
$query->insert('vcategory_to_object')
->values([
'objid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
'type' => $query->createNamedParameter('files'),
'categoryid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
])->execute();
// Non-existing file
$query = $this->connection->getQueryBuilder();
$query->insert('vcategory_to_object')
->values([
'objid' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT),
'type' => $query->createNamedParameter('files'),
'categoryid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
])->execute();
$mapping = $this->getMappings('vcategory_to_object');
$this->assertCount(2, $mapping);
$job = new DeleteOrphanedTagsJob();
$this->invokePrivate($job, 'cleanUserTags');
$mapping = $this->getMappings('vcategory_to_object');
$this->assertCount(1, $mapping);
$query = $this->connection->getQueryBuilder();
$query->delete('filecache')
->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
->execute();
$this->cleanMapping('vcategory_to_object');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment