[TASK] Optimize clearing file backend caches 33/16833/3
authorOliver Hader <oliver@typo3.org>
Wed, 28 Nov 2012 10:49:36 +0000 (11:49 +0100)
committerGeorg Ringer <georg.ringer@gmail.com>
Thu, 28 Mar 2013 09:38:46 +0000 (10:38 +0100)
During concurrent requests it might happen that one request
flushes a cache that is stored in the filesystem and another
different request tries to recreate the data. This will lead
to race conditions if the cached contents are large.

The idea is to move the current cache to a temporary location
and then remove it.

Change-Id: I242fdbc6ab28008363747a8076d021ebce127e17
Resolves: #43382
Releases: 6.0, 6.1
Reviewed-on: https://review.typo3.org/16833
Reviewed-by: Mattias Nilsson
Tested-by: Mattias Nilsson
Reviewed-by: Philipp Gampe
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
Reviewed-by: Georg Ringer
Tested-by: Georg Ringer
typo3/sysext/core/Classes/Cache/Backend/FileBackend.php
typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php

index 72e97f0..2f0b9d0 100644 (file)
@@ -288,8 +288,7 @@ class FileBackend extends \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend implem
         * @api
         */
        public function flush() {
-               \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($this->cacheDirectory, TRUE);
-               $this->createFinalCacheDirectory($this->cacheDirectory);
+               parent::flush();
                if ($this->frozen === TRUE) {
                        $this->frozen = FALSE;
                }
@@ -399,4 +398,4 @@ class FileBackend extends \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend implem
 }
 
 
-?>
\ No newline at end of file
+?>
index 6c7cb67..9ca7fda 100644 (file)
@@ -309,7 +309,7 @@ class SimpleFileBackend extends \TYPO3\CMS\Core\Cache\Backend\AbstractBackend im
         * @api
         */
        public function flush() {
-               \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($this->cacheDirectory, TRUE);
+               \TYPO3\CMS\Core\Utility\GeneralUtility::flushDirectory($this->cacheDirectory);
                $this->createFinalCacheDirectory($this->cacheDirectory);
        }
 
index 0ed1b0f..2eae6c9 100644 (file)
@@ -2693,6 +2693,28 @@ Connection: close
        }
 
        /**
+        * Flushes a directory by first moving to a temporary resource, and then
+        * triggering the remove process. This way directories can be flushed faster
+        * to prevent race conditions on concurrent processes accessing the same directory.
+        *
+        * @param string $directory The directory to be renamed and flushed
+        * @return boolean Whether the action was successful
+        */
+       static public function flushDirectory($directory) {
+               $result = FALSE;
+
+               if (is_dir($directory)) {
+                       $temporaryDirectory = rtrim($directory, '/') . '.' . uniqid('remove') . '/';
+                       if (rename($directory, $temporaryDirectory)) {
+                               clearstatcache();
+                               $result = self::rmdir($temporaryDirectory, TRUE);
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
         * Returns an array with the names of folders in a specific path
         * Will return 'error' (string) if there were an error with reading directory content.
         *
@@ -4929,4 +4951,4 @@ Connection: close
                echo $obContent;
        }
 }
-?>
\ No newline at end of file
+?>