From bdead76ea4e31dc4c3e742d60ad6d48eeb9a2471 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Tue, 18 Nov 2014 13:56:11 +0800 Subject: [PATCH 1/3] MDL-48252 scheduled tasks: file_temp_cleanup_task does full delete. This scheduled task was previously only doing a partial delete due to the fact that the directory modification time would be updated when a child file was deleted. It would then have to wait another week before that directory could be deleted. --- lib/classes/task/file_temp_cleanup_task.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/classes/task/file_temp_cleanup_task.php b/lib/classes/task/file_temp_cleanup_task.php index 01a7fbf9fcd..b5aeea8d0b0 100644 --- a/lib/classes/task/file_temp_cleanup_task.php +++ b/lib/classes/task/file_temp_cleanup_task.php @@ -52,13 +52,28 @@ class file_temp_cleanup_task extends scheduled_task { // Show all child nodes prior to their parent. $iter = new \RecursiveIteratorIterator($dir, \RecursiveIteratorIterator::CHILD_FIRST); + // An array of the full path (key) and date last modified. + $modifieddateobject = array(); + + // Get the time modified for each directory node. Nodes will be updated + // once a file is deleted, so we need a list of the original values. for ($iter->rewind(); $iter->valid(); $iter->next()) { $node = $iter->getRealPath(); if (!is_readable($node)) { continue; } + $modifieddateobject[$node] = $iter->getMTime(); + } + + // Now loop through again and remove old files and directories. + for ($iter->rewind(); $iter->valid(); $iter->next()) { + $node = $iter->getRealPath(); + if (!is_readable($node)) { + continue; + } + // Check if file or directory is older than the given time. - if ($iter->getMTime() < $time) { + if ($modifieddateobject[$node] < $time) { if ($iter->isDir() && !$iter->isDot()) { // Don't attempt to delete the directory if it isn't empty. if (!glob($node. DIRECTORY_SEPARATOR . '*')) { @@ -72,9 +87,11 @@ class file_temp_cleanup_task extends scheduled_task { mtrace("Failed removing file '$node'."); } } + } else { + // Return the time modified to the original date. + touch($node, $modifieddateobject[$node]); } } - } } From 67eb7d7804b85af3f8e0cd204ef45bcd8ae8013b Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Tue, 18 Nov 2014 13:58:33 +0800 Subject: [PATCH 2/3] MDL-48252 scheduled tasks: Unit test for file_temp_cleanup_task. --- lib/tests/scheduled_task_test.php | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/lib/tests/scheduled_task_test.php b/lib/tests/scheduled_task_test.php index 27b401a37bb..e05edd61357 100644 --- a/lib/tests/scheduled_task_test.php +++ b/lib/tests/scheduled_task_test.php @@ -312,4 +312,61 @@ class core_scheduled_task_testcase extends advanced_testcase { $this->assertGreaterThanOrEqual(0, $hour); $this->assertLessThanOrEqual(23, $hour); } + + /** + * Test that the file_temp_cleanup_task removes directories and + * files as expected. + */ + public function test_file_temp_cleanup_task() { + global $CFG; + + // Create directories. + $dir = $CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . 'courses'; + mkdir($dir, 0777, true); + + // Create files to be checked and then deleted. + $file01 = $dir . DIRECTORY_SEPARATOR . 'sections.xml'; + file_put_contents($file01, 'test data 001'); + $file02 = $dir . DIRECTORY_SEPARATOR . 'modules.xml'; + file_put_contents($file02, 'test data 002'); + // Change the time modified for the first file, to a time that will be deleted by the task (greater than seven days). + touch($file01, time() - (8 * 24 * 3600)); + + $task = \core\task\manager::get_scheduled_task('\\core\\task\\file_temp_cleanup_task'); + $this->assertInstanceOf('\core\task\file_temp_cleanup_task', $task); + $task->execute(); + + // Scan the directory. Only modules.xml should be left. + $filesarray = scandir($dir); + $this->assertEquals('modules.xml', $filesarray[2]); + $this->assertEquals(3, count($filesarray)); + + // Change the time modified on modules.xml. + touch($file02, time() - (8 * 24 * 3600)); + // Change the time modified on the courses directory. + touch($CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . + 'courses', time() - (8 * 24 * 3600)); + // Run the scheduled task to remove the file and directory. + $task->execute(); + $filesarray = scandir($CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01'); + // There should only be two items in the array, '.' and '..'. + $this->assertEquals(2, count($filesarray)); + + // Change the time modified on all of the files and directories. + $dir = new \RecursiveDirectoryIterator($CFG->tempdir); + // Show all child nodes prior to their parent. + $iter = new \RecursiveIteratorIterator($dir, \RecursiveIteratorIterator::CHILD_FIRST); + + for ($iter->rewind(); $iter->valid(); $iter->next()) { + $node = $iter->getRealPath(); + touch($node, time() - (8 * 24 * 3600)); + } + + // Run the scheduled task again to remove all of the files and directories. + $task->execute(); + $filesarray = scandir($CFG->tempdir); + // All of the files and directories should be deleted. + // There should only be two items in the array, '.' and '..'. + $this->assertEquals(2, count($filesarray)); + } } From c35d736a443d6bc89a7c42b7f01cd73ffb75960e Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Mon, 24 Nov 2014 09:45:27 +0800 Subject: [PATCH 3/3] MDL-32547 backup: Add setting for backup folder tidy up. --- admin/settings/server.php | 13 +++++++++++++ lang/en/admin.php | 2 ++ lib/classes/task/file_temp_cleanup_task.php | 2 +- version.php | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/admin/settings/server.php b/admin/settings/server.php index 29a5966906e..4b3b11e85e9 100644 --- a/admin/settings/server.php +++ b/admin/settings/server.php @@ -153,6 +153,19 @@ $temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_strin 60 => new lang_string('numdays', '', 60), 30 => new lang_string('numdays', '', 30)))); +$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'), + new lang_string('configtempdatafoldercleanup', 'admin'), 168, array( + 1 => new lang_string('numhours', '', 1), + 3 => new lang_string('numhours', '', 3), + 6 => new lang_string('numhours', '', 6), + 9 => new lang_string('numhours', '', 9), + 12 => new lang_string('numhours', '', 12), + 18 => new lang_string('numhours', '', 18), + 24 => new lang_string('numhours', '', 24), + 48 => new lang_string('numdays', '', 2), + 168 => new lang_string('numdays', '', 7), +))); + $ADMIN->add('server', $temp); diff --git a/lang/en/admin.php b/lang/en/admin.php index 63e1d819d62..03e6231b8cf 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -342,6 +342,7 @@ $string['configstripalltitletags'] = 'Uncheck this setting to allow HTML tags in $string['configsupportemail'] = 'This email address will be published to users of this site as the one to email when they need general help (for example, when new users create their own accounts). If this email is left blank then no such helpful email address is supplied.'; $string['configsupportname'] = 'This is the name of a person or other entity offering general help via the support email or web address.'; $string['configsupportpage'] = 'This web address will be published to users of this site as the one to go to when they need general help (for example, when new users create their own accounts). If this address is left blank then no link will be supplied.'; +$string['configtempdatafoldercleanup'] = 'Remove temporary data files from the data folder that are older than the selected time.'; $string['configthemedesignermode'] = 'Normally all theme images and style sheets are cached in browsers and on the server for a very long time, for performance. If you are designing themes or developing code then you probably want to turn this mode on so that you are not served cached versions. Warning: this will make your site slower for all users! Alternatively, you can also reset the theme caches manually from the Theme selection page.'; $string['configthemelist'] = 'Leave this blank to allow any valid theme to be used. If you want to shorten the theme menu, you can specify a comma-separated list of names here (Don\'t use spaces!). For example: standard,orangewhite.'; @@ -1037,6 +1038,7 @@ $string['tasksessioncleanup'] = 'Cleanup old sessions'; $string['taskstatscron'] = 'Background processing for statistics'; $string['tasktagcron'] = 'Background processing for tags'; $string['tasktempfilecleanup'] = 'Delete stale temp files'; +$string['tempdatafoldercleanup'] = 'Clean up temporary data files older than'; $string['themedesignermode'] = 'Theme designer mode'; $string['themelist'] = 'Theme list'; $string['themenoselected'] = 'No theme selected'; diff --git a/lib/classes/task/file_temp_cleanup_task.php b/lib/classes/task/file_temp_cleanup_task.php index b5aeea8d0b0..516e3c516cc 100644 --- a/lib/classes/task/file_temp_cleanup_task.php +++ b/lib/classes/task/file_temp_cleanup_task.php @@ -46,7 +46,7 @@ class file_temp_cleanup_task extends scheduled_task { $tmpdir = $CFG->tempdir; // Default to last weeks time. - $time = strtotime('-1 week'); + $time = time() - ($CFG->tempdatafoldercleanup * 3600); $dir = new \RecursiveDirectoryIterator($tmpdir); // Show all child nodes prior to their parent. diff --git a/version.php b/version.php index bc99b638e3b..5cc5a7347ab 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2014112000.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2014112000.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.