[TASK] Improve Locker 59/28159/19
authorMarkus Klein <klein.t3@mfc-linz.at>
Fri, 7 Mar 2014 12:38:42 +0000 (13:38 +0100)
committerThomas Maroschik <tmaroschik@dfau.de>
Sat, 15 Mar 2014 11:11:34 +0000 (12:11 +0100)
Code cleanup for locker and fix of semaphore locking.
It is now possible to reuse a semaphore.

Resolves: #40420
Releases: 6.2
Change-Id: I843aca1f9fa3d070ce0a508a27d3c433725991fa
Reviewed-on: https://review.typo3.org/28159
Reviewed-by: Thomas Maroschik
Tested-by: Thomas Maroschik
typo3/sysext/core/Classes/Locking/Locker.php
typo3/sysext/core/Classes/Mail/MboxTransport.php
typo3/sysext/core/Tests/Unit/Locking/LockerTest.php

index bb02a40..74f304a 100644 (file)
@@ -5,6 +5,7 @@ namespace TYPO3\CMS\Core\Locking;
  *  Copyright notice
  *
  *  (c) 2008-2013 Michael Stucki (michael@typo3.org)
+ *  (c) 2014 Markus Klein <klein.t3@mfc-linz.at>
  *  All rights reserved
  *
  *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -26,6 +27,7 @@ namespace TYPO3\CMS\Core\Locking;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * TYPO3 locking class
@@ -35,13 +37,21 @@ namespace TYPO3\CMS\Core\Locking;
  * This is especially useful if two clients are requesting the same website short after each other. While the request of client 1 triggers building and caching of the website, client 2 will be waiting at this lock.
  *
  * @author Michael Stucki <michael@typo3.org>
+ * @author Markus Klein <klein.t3@mfc-linz.at>
  */
 class Locker {
 
+       const LOCKING_METHOD_SIMPLE = 'simple';
+       const LOCKING_METHOD_FLOCK = 'flock';
+       const LOCKING_METHOD_SEMAPHORE = 'semaphore';
+       const LOCKING_METHOD_DISABLED = 'disable';
+
+       const FILE_LOCK_FOLDER = 'typo3temp/locks/';
+
        /**
-        * @var string Locking method: One of 'simple', 'flock', 'semaphore' or 'disable'
+        * @var string Locking method: One of the constants above
         */
-       protected $method;
+       protected $method = '';
 
        /**
         * @var mixed Identifier used for this lock
@@ -56,7 +66,7 @@ class Locker {
        /**
         * @var resource File pointer if using flock method
         */
-       protected $filepointer;
+       protected $filePointer;
 
        /**
         * @var boolean True if lock is acquired
@@ -87,84 +97,120 @@ class Locker {
         * Constructor:
         * initializes locking, check input parameters and set variables accordingly.
         *
+        * Parameters $loops and $step only apply to the locking method LOCKING_METHOD_SIMPLE.
+        *
         * @param string $id ID to identify this lock in the system
-        * @param string $method Define which locking method to use. Defaults to "simple".
-        * @param integer $loops Number of times a locked resource is tried to be acquired. Only used in manual locks method "simple".
-        * @param integer step Milliseconds after lock acquire is retried. $loops * $step results in the maximum delay of a lock. Only used in manual lock method "simple".
+        * @param string $method Define which locking method to use. Use one of the LOCKING_METHOD_* constants. Defaults to LOCKING_METHOD_SIMPLE. Use '' to use setting from Install Tool.
+        * @param int $loops Number of times a locked resource is tried to be acquired.
+        * @param int $step Milliseconds after lock acquire is retried. $loops * $step results in the maximum delay of a lock.
+        * @throws \RuntimeException
+        * @throws \InvalidArgumentException
         */
-       public function __construct($id, $method = 'simple', $loops = 0, $step = 0) {
+       public function __construct($id, $method = self::LOCKING_METHOD_SIMPLE, $loops = 0, $step = 0) {
                // Force ID to be string
-               $id = (string) $id;
+               $id = (string)$id;
                if ((int)$loops) {
                        $this->loops = (int)$loops;
                }
                if ((int)$step) {
                        $this->step = (int)$step;
                }
-               $this->method = $method;
-               switch ($this->method) {
-                       case 'simple':
+               if ($method === '' && isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'])) {
+                       $method = (string)$GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'];
+               }
 
-                       case 'flock':
-                               $path = PATH_site . 'typo3temp/locks/';
+               switch ($method) {
+                       case self::LOCKING_METHOD_SIMPLE:
+                               // intended fall through
+                       case self::LOCKING_METHOD_FLOCK:
+                               $path = PATH_site . self::FILE_LOCK_FOLDER;
                                if (!is_dir($path)) {
-                                       \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($path);
+                                       GeneralUtility::mkdir($path);
                                }
                                $this->id = md5($id);
                                $this->resource = $path . $this->id;
                                break;
-                       case 'semaphore':
+                       case self::LOCKING_METHOD_SEMAPHORE:
                                $this->id = abs(crc32($id));
-                               if (($this->resource = sem_get($this->id, 1)) === FALSE) {
-                                       throw new \RuntimeException('Unable to get semaphore', 1313828196);
-                               }
                                break;
-                       case 'disable':
+                       case self::LOCKING_METHOD_DISABLED:
                                break;
                        default:
-                               throw new \InvalidArgumentException('No such method "' . $method . '"', 1294586097);
+                               throw new \InvalidArgumentException('No such locking method "' . $method . '"', 1294586097);
                }
+               $this->method = $method;
        }
 
        /**
         * Destructor:
-        * Releases lock automatically when instance is destroyed.
-        *
-        * @return      void
-        * @todo Define visibility
+        * Releases lock automatically when instance is destroyed and release resources
         */
        public function __destruct() {
                $this->release();
+               switch ($this->method) {
+                       case self::LOCKING_METHOD_FLOCK:
+                               if (
+                                       GeneralUtility::isAllowedAbsPath($this->resource)
+                                       && GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . self::FILE_LOCK_FOLDER)
+                               ) {
+                                       @unlink($this->resource);
+                               }
+                               break;
+                       case self::LOCKING_METHOD_SEMAPHORE:
+                               @sem_remove($this->resource);
+                               break;
+                       default:
+                               // do nothing
+               }
        }
 
        /**
-        * Acquire a lock and return when successful. If the lock is already open, the client will be
+        * Tries to allocate the semaphore
         *
-        * It is important to know that the lock will be acquired in any case, even if the request was blocked first. Therefore, the lock needs to be released in every situation.
+        * @return void
+        * @throws \RuntimeException
+        */
+       protected function getSemaphore() {
+               $this->resource = sem_get($this->id, 1);
+               if ($this->resource === FALSE) {
+                       throw new \RuntimeException('Unable to get semaphore with id ' . $this->id, 1313828196);
+               }
+       }
+
+       /**
+        * Acquire a lock and return when successful.
+        *
+        * It is important to know that the lock will be acquired in any case, even if the request was blocked first.
+        * Therefore, the lock needs to be released in every situation.
         *
         * @return boolean Returns TRUE if lock could be acquired without waiting, FALSE otherwise.
         * @throws \RuntimeException
+        * @deprecated since 6.2 - will be removed two versions later; use new API instead
         */
        public function acquire() {
-               // Default is TRUE, which means continue without caring for other clients. In the case of TYPO3s cache management, this has no negative effect except some resource overhead.
-               $noWait = TRUE;
-               $isAcquired = TRUE;
+               // TODO refactor locking in TSFE to use the new API, then this call can be logged
+               // GeneralUtility::logDeprecatedFunction();
+
+               // Default is TRUE, which means continue without caring for other clients.
+               // In the case of TYPO3s cache management, this has no negative effect except some resource overhead.
+               $noWait = FALSE;
+               $isAcquired = FALSE;
                switch ($this->method) {
-                       case 'simple':
-                               if (is_file($this->resource)) {
+                       case self::LOCKING_METHOD_SIMPLE:
+                               if (file_exists($this->resource)) {
                                        $this->sysLog('Waiting for a different process to release the lock');
-                                       $maxExecutionTime = ini_get('max_execution_time');
-                                       $maxAge = time() - ($maxExecutionTime ? $maxExecutionTime : 120);
+                                       $maxExecutionTime = (int)ini_get('max_execution_time');
+                                       $maxAge = time() - ($maxExecutionTime ?: 120);
                                        if (@filectime($this->resource) < $maxAge) {
                                                @unlink($this->resource);
-                                               $this->sysLog('Unlink stale lockfile');
+                                               $this->sysLog('Unlinking stale lockfile');
                                        }
                                }
-                               $isAcquired = FALSE;
                                for ($i = 0; $i < $this->loops; $i++) {
-                                       $filepointer = @fopen($this->resource, 'x');
-                                       if ($filepointer !== FALSE) {
-                                               fclose($filepointer);
+                                       $filePointer = @fopen($this->resource, 'x');
+                                       if ($filePointer !== FALSE) {
+                                               fclose($filePointer);
+                                               GeneralUtility::fixPermissions($this->resource);
                                                $this->sysLog('Lock acquired');
                                                $noWait = $i === 0;
                                                $isAcquired = TRUE;
@@ -175,42 +221,126 @@ class Locker {
                                if (!$isAcquired) {
                                        throw new \RuntimeException('Lock file could not be created', 1294586098);
                                }
-                               \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($this->resource);
                                break;
-                       case 'flock':
-                               if (($this->filepointer = fopen($this->resource, 'w+')) == FALSE) {
+                       case self::LOCKING_METHOD_FLOCK:
+                               $this->filePointer = fopen($this->resource, 'c');
+                               if ($this->filePointer === FALSE) {
                                        throw new \RuntimeException('Lock file could not be opened', 1294586099);
                                }
                                // Lock without blocking
-                               if (flock($this->filepointer, (LOCK_EX | LOCK_NB)) == TRUE) {
+                               if (flock($this->filePointer, LOCK_EX | LOCK_NB)) {
                                        $noWait = TRUE;
-                               } elseif (flock($this->filepointer, LOCK_EX) == TRUE) {
+                               } elseif (flock($this->filePointer, LOCK_EX)) {
                                        // Lock with blocking (waiting for similar locks to become released)
                                        $noWait = FALSE;
                                } else {
                                        throw new \RuntimeException('Could not lock file "' . $this->resource . '"', 1294586100);
                                }
+                               $isAcquired = TRUE;
                                break;
-                       case 'semaphore':
-                               if (sem_acquire($this->resource)) {
-                                       // Unfortunately it is not possible to find out if the request has blocked,
-                                       // as sem_acquire will block until we get the resource.
-                                       // So we return FALSE in any case.
-                                       $noWait = FALSE;
-                               } else {
-                                       throw new \RuntimeException('Could not get lock on semaphore "' . $this->resource . '"', 1379502242);
+                       case self::LOCKING_METHOD_SEMAPHORE:
+                               $this->getSemaphore();
+                               while (!$isAcquired) {
+                                       if (@sem_acquire($this->resource)) {
+                                               // Unfortunately it is not possible to find out if the request has blocked,
+                                               // as sem_acquire will block until we get the resource.
+                                               // So we do not set $noWait here at all
+                                               $isAcquired = TRUE;
+                                       }
                                }
                                break;
-                       case 'disable':
-                               $noWait = FALSE;
-                               $isAcquired = FALSE;
+                       case self::LOCKING_METHOD_DISABLED:
                                break;
+                       default:
+                               // will never be reached
                }
                $this->isAcquired = $isAcquired;
                return $noWait;
        }
 
        /**
+        * Try to acquire an exclusive lock
+        *
+        * @throws \RuntimeException
+        * @return bool Returns TRUE if the lock was acquired successfully
+        */
+       public function acquireExclusiveLock() {
+               if ($this->isAcquired) {
+                       return TRUE;
+               }
+               $this->isAcquired = FALSE;
+               switch ($this->method) {
+                       case self::LOCKING_METHOD_SIMPLE:
+                               if (file_exists($this->resource)) {
+                                       $this->sysLog('Waiting for a different process to release the lock');
+                                       $maxExecutionTime = (int)ini_get('max_execution_time');
+                                       $maxAge = time() - ($maxExecutionTime ?: 120);
+                                       if (@filectime($this->resource) < $maxAge) {
+                                               @unlink($this->resource);
+                                               $this->sysLog('Unlinking stale lockfile');
+                                       }
+                               }
+                               for ($i = 0; $i < $this->loops; $i++) {
+                                       $filePointer = @fopen($this->resource, 'x');
+                                       if ($filePointer !== FALSE) {
+                                               fclose($filePointer);
+                                               GeneralUtility::fixPermissions($this->resource);
+                                               $this->sysLog('Lock acquired');
+                                               $this->isAcquired = TRUE;
+                                               break;
+                                       }
+                                       usleep($this->step * 1000);
+                               }
+                               break;
+                       case self::LOCKING_METHOD_FLOCK:
+                               $this->filePointer = fopen($this->resource, 'c');
+                               if ($this->filePointer === FALSE) {
+                                       throw new \RuntimeException('Lock file could not be opened', 1294586099);
+                               }
+                               if (flock($this->filePointer, LOCK_EX)) {
+                                   $this->isAcquired = TRUE;
+                               }
+                               break;
+                       case self::LOCKING_METHOD_SEMAPHORE:
+                               $this->getSemaphore();
+                               if (@sem_acquire($this->resource)) {
+                                       $this->isAcquired = TRUE;
+                               }
+                               break;
+                       case self::LOCKING_METHOD_DISABLED:
+                               break;
+                       default:
+                               // will never be reached
+               }
+               return $this->isAcquired;
+       }
+
+       /**
+        * Try to acquire a shared lock
+        *
+        * (Only works for the flock() locking method currently)
+        *
+        * @return bool Returns TRUE if the lock was acquired successfully
+        * @throws \RuntimeException
+        */
+       public function acquireSharedLock() {
+               if ($this->isAcquired) {
+                       return TRUE;
+               }
+               $isAcquired = FALSE;
+               if ($this->method === self::LOCKING_METHOD_FLOCK) {
+                       $this->filePointer = fopen($this->resource, 'c');
+                       if ($this->filePointer === FALSE) {
+                               throw new \RuntimeException('Lock file could not be opened', 1294586099);
+                       }
+                       if (flock($this->filePointer, LOCK_SH)) {
+                               $isAcquired = TRUE;
+                       }
+               }
+               return $isAcquired;
+       }
+
+       /**
         * Release the lock
         *
         * @return boolean Returns TRUE on success or FALSE on failure
@@ -221,34 +351,33 @@ class Locker {
                }
                $success = TRUE;
                switch ($this->method) {
-                       case 'simple':
-                               if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($this->resource) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . 'typo3temp/locks/')) {
-                                       if (@unlink($this->resource) == FALSE) {
+                       case self::LOCKING_METHOD_SIMPLE:
+                               if (
+                                       GeneralUtility::isAllowedAbsPath($this->resource)
+                                       && GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . self::FILE_LOCK_FOLDER)
+                               ) {
+                                       if (@unlink($this->resource) === FALSE) {
                                                $success = FALSE;
                                        }
                                }
                                break;
-                       case 'flock':
-                               if (is_resource($this->filepointer)) {
-                                       if (flock($this->filepointer, LOCK_UN) == FALSE) {
+                       case self::LOCKING_METHOD_FLOCK:
+                               if (is_resource($this->filePointer)) {
+                                       if (flock($this->filePointer, LOCK_UN) === FALSE) {
                                                $success = FALSE;
                                        }
-                                       fclose($this->filepointer);
-                               }
-                               if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($this->resource) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . 'typo3temp/locks/')) {
-                                       @unlink($this->resource);
+                                       fclose($this->filePointer);
                                }
                                break;
-                       case 'semaphore':
-                               if (@sem_release($this->resource)) {
-                                       sem_remove($this->resource);
-                               } else {
+                       case self::LOCKING_METHOD_SEMAPHORE:
+                               if (!@sem_release($this->resource)) {
                                        $success = FALSE;
                                }
                                break;
-                       case 'disable':
-                               $success = FALSE;
+                       case self::LOCKING_METHOD_DISABLED:
                                break;
+                       default:
+                               // will never be reached
                }
                $this->isAcquired = FALSE;
                return $success;
@@ -283,15 +412,49 @@ class Locker {
        }
 
        /**
-        * Return the status of a lock
+        * Return the local status of a lock
         *
-        * @return string Returns TRUE if lock is acquired, FALSE otherwise
+        * @return bool Returns TRUE if lock is acquired by this process, FALSE otherwise
         */
        public function getLockStatus() {
                return $this->isAcquired;
        }
 
        /**
+        * Return the global status of the lock
+        *
+        * @return bool Returns TRUE if the lock is locked by either this or another process, FALSE otherwise
+        */
+       public function isLocked() {
+               $result = FALSE;
+               switch ($this->method) {
+                       case self::LOCKING_METHOD_SIMPLE:
+                               if (file_exists($this->resource)) {
+                                       $maxExecutionTime = (int)ini_get('max_execution_time');
+                                       $maxAge = time() - ($maxExecutionTime ?: 120);
+                                       if (@filectime($this->resource) < $maxAge) {
+                                               @unlink($this->resource);
+                                               $this->sysLog('Unlinking stale lockfile');
+                                       } else {
+                                               $result = TRUE;
+                                       }
+                               }
+                               break;
+                       case self::LOCKING_METHOD_FLOCK:
+                               // we can't detect this reliably here, since the third parameter of flock() does not work on windows
+                               break;
+                       case self::LOCKING_METHOD_SEMAPHORE:
+                               // no way to detect this at all, no PHP API for that
+                               break;
+                       case self::LOCKING_METHOD_DISABLED:
+                               break;
+                       default:
+                               // will never be reached
+               }
+               return $result;
+       }
+
+       /**
         * Sets the facility (extension name) for the syslog entry.
         *
         * @param string $syslogFacility
@@ -319,7 +482,7 @@ class Locker {
         */
        public function sysLog($message, $severity = 0) {
                if ($this->isLoggingEnabled) {
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('Locking [' . $this->method . '::' . $this->id . ']: ' . trim($message), $this->syslogFacility, $severity);
+                       GeneralUtility::sysLog('Locking [' . $this->method . '::' . $this->id . ']: ' . trim($message), $this->syslogFacility, $severity);
                }
        }
 
index 7929455..8133d7a 100644 (file)
@@ -74,7 +74,7 @@ class MboxTransport implements \Swift_Transport {
        /**
         * Outputs the mail to a text file according to RFC 4155.
         *
-        * @param Swift_Mime_Message $message The message to send
+        * @param \Swift_Mime_Message $message The message to send
         * @param string[] &$failedRecipients To collect failures by-reference, nothing will fail in our debugging case
         * @return int
         * @throws \RuntimeException
@@ -88,9 +88,9 @@ class MboxTransport implements \Swift_Transport {
                // Add the complete mail inclusive headers
                $messageStr .= $message->toString();
                $messageStr .= LF . LF;
-               $lockObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Locking\\Locker', $this->debugFile, $GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode']);
+               $lockObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Locking\\Locker', $this->debugFile);
                /** @var \TYPO3\CMS\Core\Locking\Locker $lockObject */
-               $lockObject->acquire();
+               $lockObject->acquireExclusiveLock();
                // Write the mbox file
                $file = @fopen($this->debugFile, 'a');
                if (!$file) {
@@ -109,7 +109,7 @@ class MboxTransport implements \Swift_Transport {
        /**
         * Determine the best-use reverse path for this message
         *
-        * @param Swift_Mime_Message $message
+        * @param \Swift_Mime_Message $message
         * @return mixed|NULL
         */
        private function getReversePath(\Swift_Mime_Message $message) {
@@ -132,7 +132,8 @@ class MboxTransport implements \Swift_Transport {
        /**
         * Register a plugin in the Transport.
         *
-        * @param Swift_Events_EventListener $plugin
+        * @param \Swift_Events_EventListener $plugin
+        * @return bool
         */
        public function registerPlugin(\Swift_Events_EventListener $plugin) {
                return TRUE;
index 87c6318..56faefa 100644 (file)
@@ -23,6 +23,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Locking;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Core\Locking\Locker;
 
 /**
  * Testcase for \TYPO3\CMS\Core\Locking\Locker
@@ -38,95 +39,81 @@ class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function constructorUsesDefaultLockingMethodSimple() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
-               $this->assertSame('simple', $instance->getMethod());
+               $instance = new Locker('999999999');
+               $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod());
        }
 
        /**
         * @test
         */
        public function constructorSetsMethodToGivenParameter() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'flock');
-               $this->assertSame('flock', $instance->getMethod());
+               $instance = new Locker('999999999', Locker::LOCKING_METHOD_FLOCK);
+               $this->assertSame(Locker::LOCKING_METHOD_FLOCK, $instance->getMethod());
        }
 
        /**
         * @test
+        * @expectedException \InvalidArgumentException
         */
-       public function constructorDoesNotThrowExceptionIfUsingDisableMethod() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'disable');
+       public function constructorThrowsExceptionForNotExistingLockingMethod() {
+               new Locker('999999999', 'foo');
        }
 
        /**
         * @test
-        * @expectedException \InvalidArgumentException
         */
-       public function constructorThrowsExceptionForNotExistingLockingMethod() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'foo');
+       public function constructorFetchesInstallToolConfigurationIfEmptyMethod() {
+               $GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'] = Locker::LOCKING_METHOD_SIMPLE;
+               $instance = new Locker('999999999', '');
+               $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod());
        }
 
        /**
         * @test
         */
        public function constructorUsesDefaultValueForLoops() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
-               $instance->setEnableLogging(FALSE);
-               $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
-               $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('loops');
-               $t3libLockReflectionResourceProperty->setAccessible(TRUE);
-               $this->assertSame(150, $t3libLockReflectionResourceProperty->getValue($instance));
+               $instance = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Locking\\Locker', array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED));
+               $this->assertSame(150, $instance->_get('loops'));
        }
 
        /**
         * @test
         */
        public function constructorSetsLoopsToGivenNumberOfLoops() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple', 10);
-               $instance->setEnableLogging(FALSE);
-               $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
-               $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('loops');
-               $t3libLockReflectionResourceProperty->setAccessible(TRUE);
-               $this->assertSame(10, $t3libLockReflectionResourceProperty->getValue($instance));
+               $instance = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Locking\\Locker', array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 10));
+               $this->assertSame(10, $instance->_get('loops'));
        }
 
        /**
         * @test
         */
        public function constructorUsesDefaultValueForSteps() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
-               $instance->setEnableLogging(FALSE);
-               $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
-               $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('step');
-               $t3libLockReflectionResourceProperty->setAccessible(TRUE);
-               $this->assertSame(200, $t3libLockReflectionResourceProperty->getValue($instance));
+               $instance = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Locking\\Locker', array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED));
+               $this->assertSame(200, $instance->_get('step'));
        }
 
        /**
         * @test
         */
        public function constructorSetsStepToGivenNumberOfStep() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple', 0, 10);
-               $instance->setEnableLogging(FALSE);
-               $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
-               $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('step');
-               $t3libLockReflectionResourceProperty->setAccessible(TRUE);
-               $this->assertSame(10, $t3libLockReflectionResourceProperty->getValue($instance));
+               $instance = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Locking\\Locker', array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 0, 10));
+               $this->assertSame(10, $instance->_get('step'));
        }
 
        /**
         * @test
         */
        public function constructorCreatesLockDirectoryIfNotExisting() {
-               \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . 'typo3temp/locks/', TRUE);
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
-               $this->assertTrue(is_dir(PATH_site . 'typo3temp/locks/'));
+               \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . Locker::FILE_LOCK_FOLDER, TRUE);
+               new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
+               $this->assertTrue(is_dir(PATH_site . Locker::FILE_LOCK_FOLDER));
        }
 
        /**
         * @test
         */
-       public function constructorSetsIdToMd5OfStringIfUsingSimleLocking() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
+       public function constructorSetsIdToMd5OfStringIfUsingSimpleLocking() {
+               $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
                $this->assertSame(md5('999999999'), $instance->getId());
        }
 
@@ -134,8 +121,8 @@ class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function constructorSetsResourceToPathWithIdIfUsingSimpleLocking() {
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
-               $this->assertSame(PATH_site . 'typo3temp/locks/' . md5('999999999'), $instance->getResource());
+               $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
+               $this->assertSame(PATH_site . Locker::FILE_LOCK_FOLDER . md5('999999999'), $instance->getResource());
        }
 
        /**
@@ -145,21 +132,10 @@ class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                if (!function_exists('sem_get')) {
                        $this->markTestSkipped('The system does not support semaphore base locking.');
                }
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'semaphore');
+               $instance = new Locker('999999999', Locker::LOCKING_METHOD_SEMAPHORE);
                $this->assertSame(abs(crc32('999999999')), $instance->getId());
        }
 
-       /**
-        * @test
-        */
-       public function constructorSetsResourceToSemaphoreResourceIfUsingSemaphoreLocking() {
-               if (!function_exists('sem_get')) {
-                       $this->markTestSkipped('The system does not support semaphore base locking.');
-               }
-               $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'semaphore');
-               $this->assertTrue(is_resource($instance->getResource()));
-       }
-
        ///////////////////////////////
        // tests concerning acquire
        ///////////////////////////////
@@ -171,42 +147,33 @@ class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        $this->markTestSkipped('acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() test not available on Windows.');
                }
                // Use a very high id to be unique
-               $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, 'simple');
+               $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE);
+               $instance->setEnableLogging(FALSE);
                $pathOfLockFile = $instance->getResource();
                $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
                // Acquire lock, get actual file permissions and clean up
-               $instance->acquire();
+               $instance->acquireExclusiveLock();
                clearstatcache();
                $resultFilePermissions = substr(decoct(fileperms($pathOfLockFile)), 2);
-               $instance->__destruct();
+               $instance->release();
                $this->assertEquals($resultFilePermissions, '0777');
        }
 
        ///////////////////////////////
        // tests concerning release
        ///////////////////////////////
-       /**
-        * Dataprovider for releaseRemovesLockfileInTypo3TempLocks
-        */
-       public function fileBasedLockMethods() {
-               return array(
-                       'simple' => array('simple'),
-                       'flock' => array('flock')
-               );
-       }
 
        /**
         * @test
-        * @dataProvider fileBasedLockMethods
         */
-       public function releaseRemovesLockfileInTypo3TempLocks($lockMethod) {
+       public function releaseRemovesLockfileInTypo3TempLocks() {
                // Use a very high id to be unique
-               $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, $lockMethod);
+               $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE);
                // Disable logging
                $instance->setEnableLogging(FALSE);
                // File pointer to current lock file
                $lockFile = $instance->getResource();
-               $instance->acquire();
+               $instance->acquireExclusiveLock();
                $instance->release();
                $this->assertFalse(is_file($lockFile));
        }
@@ -241,7 +208,7 @@ class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() skipped: Test file could not be created');
                }
                // Create instance, set lockfile to invalid path
-               $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, $lockMethod);
+               $instance = new Locker(999999999, $lockMethod);
                $instance->setEnableLogging(FALSE);
                $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
                $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('resource');