summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2015-03-16 10:04:05 +0100
committerThomas Müller <thomas.mueller@tmit.eu>2015-03-16 10:04:05 +0100
commitbbaf97ca43e9a9a95f924b0bdf15e975bc0b0eb0 (patch)
tree0eed1794b5db8270b59126e930d06ab967986811
parent69277736483ad3352f82ba882977e3767884ac49 (diff)
parent4ffca58bc4d10ce2d7b63790813ab448c198c23f (diff)
downloadnextcloud-server-bbaf97ca43e9a9a95f924b0bdf15e975bc0b0eb0.tar.gz
nextcloud-server-bbaf97ca43e9a9a95f924b0bdf15e975bc0b0eb0.zip
Merge pull request #14644 from owncloud/trash-expire-command
Expire files from the trash in the background
-rw-r--r--apps/files_trashbin/command/expire.php56
-rw-r--r--apps/files_trashbin/lib/trashbin.php51
-rw-r--r--apps/files_trashbin/tests/trashbin.php2
-rw-r--r--lib/private/command/queuebus.php53
-rw-r--r--tests/lib/testcase.php37
5 files changed, 167 insertions, 32 deletions
diff --git a/apps/files_trashbin/command/expire.php b/apps/files_trashbin/command/expire.php
new file mode 100644
index 00000000000..968608a31cb
--- /dev/null
+++ b/apps/files_trashbin/command/expire.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * ownCloud - trash bin
+ *
+ * @author Robin Appelman
+ * @copyright 2015 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Trashbin\Command;
+
+use OC\Command\FileAccess;
+use OCA\Files_Trashbin\Trashbin;
+use OCP\Command\ICommand;
+
+class Expire implements ICommand {
+ use FileAccess;
+
+ /**
+ * @var string
+ */
+ private $user;
+
+ /**
+ * @var int
+ */
+ private $trashBinSize;
+
+ /**
+ * @param string $user
+ * @param int $trashBinSize
+ */
+ function __construct($user, $trashBinSize) {
+ $this->user = $user;
+ $this->trashBinSize = $trashBinSize;
+ }
+
+ public function handle() {
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($this->user);
+ Trashbin::expire($this->trashBinSize, $this->user);
+ }
+}
diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php
index f30d61542fa..6a7636a46f2 100644
--- a/apps/files_trashbin/lib/trashbin.php
+++ b/apps/files_trashbin/lib/trashbin.php
@@ -23,6 +23,7 @@
namespace OCA\Files_Trashbin;
use OC\Files\Filesystem;
+use OCA\Files_Trashbin\Command\Expire;
class Trashbin {
// how long do we keep files in the trash bin if no other value is defined in the config file (unit: days)
@@ -211,13 +212,13 @@ class Trashbin {
}
$userTrashSize += $size;
- $userTrashSize -= self::expire($userTrashSize, $user);
+ self::scheduleExpire($userTrashSize, $user);
// if owner !== user we also need to update the owners trash size
if ($owner !== $user) {
$ownerTrashSize = self::getTrashbinSize($owner);
$ownerTrashSize += $size;
- $ownerTrashSize -= self::expire($ownerTrashSize, $owner);
+ self::scheduleExpire($ownerTrashSize, $owner);
}
return ($sizeOfAddedFiles === false) ? false : true;
@@ -429,7 +430,7 @@ class Trashbin {
if ($view->is_dir('/files_trashbin/versions/' . $file)) {
$rootView->rename(\OC\Files\Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath));
- } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp)) {
+ } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp, $user)) {
foreach ($versions as $v) {
if ($timestamp) {
$rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
@@ -533,8 +534,8 @@ class Trashbin {
$file = $filename;
}
- $size += self::deleteVersions($view, $file, $filename, $timestamp);
- $size += self::deleteEncryptionKeys($view, $file, $filename, $timestamp);
+ $size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
+ $size += self::deleteEncryptionKeys($view, $file, $filename, $timestamp, $user);
if ($view->is_dir('/files_trashbin/files/' . $file)) {
$size += self::calculateSize(new \OC\Files\View('/' . $user . '/files_trashbin/files/' . $file));
@@ -555,14 +556,13 @@ class Trashbin {
* @param $timestamp
* @return int
*/
- private static function deleteVersions(\OC\Files\View $view, $file, $filename, $timestamp) {
+ private static function deleteVersions(\OC\Files\View $view, $file, $filename, $timestamp, $user) {
$size = 0;
if (\OCP\App::isEnabled('files_versions')) {
- $user = \OCP\User::getUser();
if ($view->is_dir('files_trashbin/versions/' . $file)) {
$size += self::calculateSize(new \OC\Files\view('/' . $user . '/files_trashbin/versions/' . $file));
$view->unlink('files_trashbin/versions/' . $file);
- } else if ($versions = self::getVersionsFromTrash($filename, $timestamp)) {
+ } else if ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
foreach ($versions as $v) {
if ($timestamp) {
$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
@@ -584,10 +584,9 @@ class Trashbin {
* @param $timestamp
* @return int
*/
- private static function deleteEncryptionKeys(\OC\Files\View $view, $file, $filename, $timestamp) {
+ private static function deleteEncryptionKeys(\OC\Files\View $view, $file, $filename, $timestamp, $user) {
$size = 0;
if (\OCP\App::isEnabled('files_encryption')) {
- $user = \OCP\User::getUser();
$keyfiles = \OC\Files\Filesystem::normalizePath('files_trashbin/keys/' . $filename);
@@ -689,26 +688,18 @@ class Trashbin {
$freeSpace = self::calculateFreeSpace($size, $user);
if ($freeSpace < 0) {
- self::expire($size, $user);
+ self::scheduleExpire($size, $user);
}
}
/**
* clean up the trash bin
*
- * @param int $trashbinSize current size of the trash bin
+ * @param int $trashBinSize current size of the trash bin
* @param string $user
- * @return int size of expired files
*/
- private static function expire($trashbinSize, $user) {
-
- // let the admin disable auto expire
- $autoExpire = \OC_Config::getValue('trashbin_auto_expire', true);
- if ($autoExpire === false) {
- return 0;
- }
-
- $availableSpace = self::calculateFreeSpace($trashbinSize, $user);
+ public static function expire($trashBinSize, $user) {
+ $availableSpace = self::calculateFreeSpace($trashBinSize, $user);
$size = 0;
$retention_obligation = \OC_Config::getValue('trashbin_retention_obligation', self::DEFAULT_RETENTION_OBLIGATION);
@@ -725,8 +716,18 @@ class Trashbin {
// delete files from trash until we meet the trash bin size limit again
$size += self::deleteFiles(array_slice($dirContent, $count), $user, $availableSpace);
+ }
- return $size;
+ /**@param int $trashBinSize current size of the trash bin
+ * @param string $user
+ */
+ private static function scheduleExpire($trashBinSize, $user) {
+ // let the admin disable auto expire
+ $autoExpire = \OC_Config::getValue('trashbin_auto_expire', true);
+ if ($autoExpire === false) {
+ return;
+ }
+ \OC::$server->getCommandBus()->push(new Expire($user, $trashBinSize));
}
/**
@@ -827,8 +828,8 @@ class Trashbin {
* @param int $timestamp timestamp when the file was deleted
* @return array
*/
- private static function getVersionsFromTrash($filename, $timestamp) {
- $view = new \OC\Files\View('/' . \OCP\User::getUser() . '/files_trashbin/versions');
+ private static function getVersionsFromTrash($filename, $timestamp, $user) {
+ $view = new \OC\Files\View('/' . $user . '/files_trashbin/versions');
$versions = array();
//force rescan of versions, local storage may not have updated the cache
diff --git a/apps/files_trashbin/tests/trashbin.php b/apps/files_trashbin/tests/trashbin.php
index 17e38015868..8bc52cc9192 100644
--- a/apps/files_trashbin/tests/trashbin.php
+++ b/apps/files_trashbin/tests/trashbin.php
@@ -210,6 +210,8 @@ class Test_Trashbin extends \Test\TestCase {
\OC\Files\Filesystem::unlink($folder . 'user1-4.txt');
+ $this->runCommands();
+
$filesInTrashUser2AfterDelete = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2);
// user2-1.txt should have been expired
diff --git a/lib/private/command/queuebus.php b/lib/private/command/queuebus.php
new file mode 100644
index 00000000000..29c769e0107
--- /dev/null
+++ b/lib/private/command/queuebus.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Command;
+
+use OCP\Command\IBus;
+use OCP\Command\ICommand;
+
+class QueueBus implements IBus {
+ /**
+ * @var (ICommand|callable)[]
+ */
+ private $queue;
+
+ /**
+ * Schedule a command to be fired
+ *
+ * @param \OCP\Command\ICommand | callable $command
+ */
+ public function push($command) {
+ $this->queue[] = $command;
+ }
+
+ /**
+ * Require all commands using a trait to be run synchronous
+ *
+ * @param string $trait
+ */
+ public function requireSync($trait) {
+ }
+
+ /**
+ * @param \OCP\Command\ICommand | callable $command
+ */
+ private function runCommand($command) {
+ if ($command instanceof ICommand) {
+ $command->handle();
+ } else {
+ $command();
+ }
+ }
+
+ public function run() {
+ while ($command = array_shift($this->queue)) {
+ $this->runCommand($command);
+ }
+ }
+}
diff --git a/tests/lib/testcase.php b/tests/lib/testcase.php
index 1ea3aa13547..2b4540120d2 100644
--- a/tests/lib/testcase.php
+++ b/tests/lib/testcase.php
@@ -22,10 +22,24 @@
namespace Test;
+use OC\Command\QueueBus;
use OCP\Security\ISecureRandom;
abstract class TestCase extends \PHPUnit_Framework_TestCase {
/**
+ * @var \OC\Command\QueueBus
+ */
+ private $commandBus;
+
+ protected function setUp() {
+ // overwrite the command bus with one we can run ourselves
+ $this->commandBus = new QueueBus();
+ \OC::$server->registerService('AsyncCommandBus', function(){
+ return $this->commandBus;
+ });
+ }
+
+ /**
* Returns a unique identifier as uniqid() is not reliable sometimes
*
* @param string $prefix
@@ -55,6 +69,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
/**
* Remove all entries from the files map table
+ *
* @param string $dataDir
*/
static protected function tearDownAfterClassCleanFileMapper($dataDir) {
@@ -66,6 +81,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
/**
* Remove all entries from the storages table
+ *
* @throws \OC\DatabaseException
*/
static protected function tearDownAfterClassCleanStorages() {
@@ -76,6 +92,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
/**
* Remove all entries from the filecache table
+ *
* @throws \OC\DatabaseException
*/
static protected function tearDownAfterClassCleanFileCache() {
@@ -91,11 +108,11 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
*/
static protected function tearDownAfterClassCleanStrayDataFiles($dataDir) {
$knownEntries = array(
- 'owncloud.log' => true,
- 'owncloud.db' => true,
- '.ocdata' => true,
- '..' => true,
- '.' => true,
+ 'owncloud.log' => true,
+ 'owncloud.db' => true,
+ '.ocdata' => true,
+ '..' => true,
+ '.' => true,
);
if ($dh = opendir($dataDir)) {
@@ -122,8 +139,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
$path = $dir . '/' . $file;
if (is_dir($path)) {
self::tearDownAfterClassCleanStrayDataUnlinkDir($path);
- }
- else {
+ } else {
@unlink($path);
}
}
@@ -169,4 +185,11 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
\OC_Util::tearDownFS();
\OC_User::setUserId('');
}
+
+ /**
+ * Run all commands pushed to the bus
+ */
+ protected function runCommands() {
+ $this->commandBus->run();
+ }
}