[FOLLOWUP][TASK] Add meaningful exceptions to new locking API 83/38683/9
authorMathias Brodala <mbrodala@pagemachine.de>
Tue, 14 Apr 2015 07:57:41 +0000 (09:57 +0200)
committerJigal van Hemert <jigal.van.hemert@typo3.org>
Mon, 20 Apr 2015 21:17:04 +0000 (23:17 +0200)
This adds dedicated exceptions to the new locking API which
vastly simplifies usage workflows.

Since the new API was not yet released, this is a non-breaking
change.

Resolves: #66411
Related: #47712
Releases: master
Change-Id: Iae44eaa121562469b64222f5837f7a48e6d9fc14
Reviewed-on: http://review.typo3.org/38683
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
Reviewed-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
12 files changed:
typo3/sysext/core/Classes/Core/ClassLoader.php
typo3/sysext/core/Classes/Locking/Exception.php [new file with mode: 0644]
typo3/sysext/core/Classes/Locking/Exception/LockAcquireException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Locking/Exception/LockAcquireWouldBlockException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Locking/Exception/LockCreateException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Locking/FileLockStrategy.php
typo3/sysext/core/Classes/Locking/LockFactory.php
typo3/sysext/core/Classes/Locking/LockingStrategyInterface.php
typo3/sysext/core/Classes/Locking/SemaphoreLockStrategy.php
typo3/sysext/core/Classes/Locking/SimpleLockStrategy.php
typo3/sysext/core/Documentation/Changelog/master/Feature-47712-NewLockingAPI.rst
typo3/sysext/core/Tests/Unit/Locking/LockFactoryTest.php

index 096ed54..1a4f4eb 100644 (file)
@@ -14,11 +14,12 @@ namespace TYPO3\CMS\Core\Core;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Locking\LockingStrategyInterface;
+use TYPO3\CMS\Core\Cache;
+use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
 use TYPO3\CMS\Core\Locking\LockFactory;
+use TYPO3\CMS\Core\Locking\LockingStrategyInterface;
 use TYPO3\CMS\Core\Package\PackageInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Cache;
 
 /**
  * Class Loader implementation which loads .php files found in the classes
@@ -805,8 +806,8 @@ class ClassLoader {
 
                        try {
                                $this->lockObject = (new LockFactory())->createLocker('ClassLoader-cache-classes');
-                       } catch (\RuntimeException $e) {
-                               // The RuntimeException in constructor happens if directory typo3temp/locks could not be created.
+                       } catch (LockCreateException $e) {
+                               // The LockCreateException in constructor happens if directory typo3temp/locks could not be created.
                                // This usually happens during installation step 1 where typo3temp itself does not exist yet. In
                                // this case we proceed without locking, otherwise a missing typo3temp directory indicates a
                                // hard problem of the instance and we throw up.
diff --git a/typo3/sysext/core/Classes/Locking/Exception.php b/typo3/sysext/core/Classes/Locking/Exception.php
new file mode 100644 (file)
index 0000000..6799cc9
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace TYPO3\CMS\Core\Locking;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * A locking exception
+ */
+class Exception extends \TYPO3\CMS\Core\Exception {
+
+
+}
diff --git a/typo3/sysext/core/Classes/Locking/Exception/LockAcquireException.php b/typo3/sysext/core/Classes/Locking/Exception/LockAcquireException.php
new file mode 100644 (file)
index 0000000..f1d98af
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace TYPO3\CMS\Core\Locking\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * An exception indicating a lock acquisition error
+ */
+class LockAcquireException extends \TYPO3\CMS\Core\Locking\Exception {
+
+
+}
diff --git a/typo3/sysext/core/Classes/Locking/Exception/LockAcquireWouldBlockException.php b/typo3/sysext/core/Classes/Locking/Exception/LockAcquireWouldBlockException.php
new file mode 100644 (file)
index 0000000..349b79c
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace TYPO3\CMS\Core\Locking\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * An exception indicating that acquiring a lock would have blocked
+ */
+class LockAcquireWouldBlockException extends LockAcquireException {
+
+
+}
diff --git a/typo3/sysext/core/Classes/Locking/Exception/LockCreateException.php b/typo3/sysext/core/Classes/Locking/Exception/LockCreateException.php
new file mode 100644 (file)
index 0000000..b52203a
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace TYPO3\CMS\Core\Locking\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * An exception indicating a lock creation error
+ */
+class LockCreateException extends \TYPO3\CMS\Core\Locking\Exception {
+
+
+}
index 5640773..14c9c01 100644 (file)
@@ -14,6 +14,9 @@ namespace TYPO3\CMS\Core\Locking;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireException;
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException;
+use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -42,7 +45,7 @@ class FileLockStrategy implements LockingStrategyInterface {
 
        /**
         * @param string $subject ID to identify this lock in the system
-        * @throws \RuntimeException
+        * @throws LockCreateException if the lock could not be created
         */
        public function __construct($subject) {
                /*
@@ -56,11 +59,11 @@ class FileLockStrategy implements LockingStrategyInterface {
                        // does not exist, this issue should be solved on a different
                        // level of the application.
                        if (!GeneralUtility::mkdir($path)) {
-                               throw new \RuntimeException('Cannot create directory ' . $path, 1395140007);
+                               throw new LockCreateException('Cannot create directory ' . $path, 1395140007);
                        }
                }
                if (!is_writable($path)) {
-                       throw new \RuntimeException('Cannot write to directory ' . $path, 1396278700);
+                       throw new LockCreateException('Cannot write to directory ' . $path, 1396278700);
                }
                $this->filePath = $path . md5((string)$subject);
        }
@@ -78,7 +81,8 @@ class FileLockStrategy implements LockingStrategyInterface {
         *
         * @param int $mode LOCK_CAPABILITY_EXCLUSIVE or LOCK_CAPABILITY_SHARED or self::LOCK_CAPABILITY_NOBLOCK
         * @return bool Returns TRUE if the lock was acquired successfully
-        * @throws \RuntimeException with code 1428700748 if the acquire would have blocked and NOBLOCK was set
+        * @throws LockAcquireException if the lock could not be acquired
+        * @throws LockAcquireWouldBlockException if the acquire would have blocked and NOBLOCK was set
         */
        public function acquire($mode = self::LOCK_CAPABILITY_EXCLUSIVE) {
                if ($this->isAcquired) {
@@ -87,7 +91,7 @@ class FileLockStrategy implements LockingStrategyInterface {
 
                $this->filePointer = fopen($this->filePath, 'c');
                if ($this->filePointer === FALSE) {
-                       throw new \RuntimeException('Lock file could not be opened', 1294586099);
+                       throw new LockAcquireException('Lock file could not be opened', 1294586099);
                }
 
                $operation = $mode & self::LOCK_CAPABILITY_EXCLUSIVE ? LOCK_EX : LOCK_SH;
@@ -99,7 +103,7 @@ class FileLockStrategy implements LockingStrategyInterface {
                $this->isAcquired = flock($this->filePointer, $operation, $wouldBlock);
 
                if ($mode & self::LOCK_CAPABILITY_NOBLOCK && !$this->isAcquired && $wouldBlock) {
-                       throw new \RuntimeException('Failed to acquire lock because the request would block.', 1428700748);
+                       throw new LockAcquireWouldBlockException('Failed to acquire lock because the request would block.', 1428700748);
                }
 
                return $this->isAcquired;
index 8f5c62a..4d699e3 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Locking;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
 use TYPO3\CMS\Core\SingletonInterface;
 
 /**
@@ -62,7 +63,7 @@ class LockFactory implements SingletonInterface {
         * @param string $id ID to identify this lock in the system
         * @param int $capabilities LockingStrategyInterface::LOCK_CAPABILITY_* elements combined with bit-wise OR
         * @return LockingStrategyInterface Class name for a locking method
-        * @throws \InvalidArgumentException
+        * @throws LockCreateException if no locker could be created with the requested capabilities
         */
        public function createLocker($id, $capabilities = LockingStrategyInterface::LOCK_CAPABILITY_EXCLUSIVE) {
                $queue = new \SplPriorityQueue();
@@ -79,7 +80,7 @@ class LockFactory implements SingletonInterface {
                        // Locking might be used very early in the bootstrap process, where makeInstance() does not work
                        return new $className($id);
                }
-               throw new \InvalidArgumentException('Could not find a matching locking method with requested capabilities.', 1425990190);
+               throw new LockCreateException('Could not find a matching locking method with requested capabilities.', 1425990190);
        }
 
 }
index 38733d0..c0bbd9f 100644 (file)
@@ -14,6 +14,10 @@ namespace TYPO3\CMS\Core\Locking;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireException;
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException;
+use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
+
 /**
  * Interface for locking methods
  *
@@ -48,6 +52,7 @@ interface LockingStrategyInterface {
 
        /**
         * @param string $subject ID to identify this lock in the system
+        * @throws LockCreateException if the lock could not be created
         */
        public function __construct($subject);
 
@@ -56,7 +61,8 @@ interface LockingStrategyInterface {
         *
         * @param int $mode LOCK_CAPABILITY_EXCLUSIVE or LOCK_CAPABILITY_SHARED
         * @return bool Returns TRUE if the lock was acquired successfully
-        * @throws \RuntimeException with code 1428700748 if the acquire would have blocked and NOBLOCK was set
+        * @throws LockAcquireException if the lock could not be acquired
+        * @throws LockAcquireWouldBlockException if the acquire would have blocked and NOBLOCK was set
         */
        public function acquire($mode = self::LOCK_CAPABILITY_EXCLUSIVE);
 
index 0b0d02c..9229865 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Core\Locking;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireException;
+
 /**
  * Semaphore locking
  *
@@ -90,7 +92,7 @@ class SemaphoreLockStrategy implements LockingStrategyInterface {
         *
         * @param int $mode LOCK_CAPABILITY_EXCLUSIVE
         * @return bool Returns TRUE if the lock was acquired successfully
-        * @throws \RuntimeException
+        * @throws LockAcquireException if a semaphore could not be retrieved
         */
        public function acquire($mode = self::LOCK_CAPABILITY_EXCLUSIVE) {
                if ($this->isAcquired) {
@@ -99,7 +101,7 @@ class SemaphoreLockStrategy implements LockingStrategyInterface {
 
                $this->resource = sem_get($this->id, 1);
                if ($this->resource === FALSE) {
-                       throw new \RuntimeException('Unable to get semaphore with id ' . $this->id, 1313828196);
+                       throw new LockAcquireException('Unable to get semaphore with id ' . $this->id, 1313828196);
                }
 
                $this->isAcquired = (bool)sem_acquire($this->resource);
index 5a355d2..d108e77 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Core\Locking;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException;
+use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -47,7 +49,7 @@ class SimpleLockStrategy implements LockingStrategyInterface {
 
        /**
         * @param string $subject ID to identify this lock in the system
-        * @throws \RuntimeException
+        * @throws LockCreateException if the lock could not be created
         */
        public function __construct($subject) {
                // Tests if the directory for simple locks is available.
@@ -59,11 +61,11 @@ class SimpleLockStrategy implements LockingStrategyInterface {
                        // does not exist, this issue should be solved on a different
                        // level of the application.
                        if (!GeneralUtility::mkdir($path)) {
-                               throw new \RuntimeException('Cannot create directory ' . $path, 1395140007);
+                               throw new LockCreateException('Cannot create directory ' . $path, 1395140007);
                        }
                }
                if (!is_writable($path)) {
-                       throw new \RuntimeException('Cannot write to directory ' . $path, 1396278700);
+                       throw new LockCreateException('Cannot write to directory ' . $path, 1396278700);
                }
                $this->filePath = $path . md5((string)$subject);
        }
@@ -165,7 +167,7 @@ class SimpleLockStrategy implements LockingStrategyInterface {
                }
 
                if ($mode & self::LOCK_CAPABILITY_NOBLOCK && !$this->isAcquired && $wouldBlock) {
-                       throw new \RuntimeException('Failed to acquire lock because the request would block.', 1428700748);
+                       throw new LockAcquireWouldBlockException('Failed to acquire lock because the request would block.', 1428700748);
                }
 
                return $this->isAcquired;
index 0b91480..1e50b60 100644 (file)
@@ -42,10 +42,8 @@ Some methods also support non-blocking locks:
        );
        try {
                $result = $locker->acquire(LockingStrategyInterface::LOCK_CAPABILITY_SHARED | LockingStrategyInterface::LOCK_CAPABILITY_NOBLOCK);
-       catch (\RuntimeException $e) {
-               if ($e->getCode() === 1428700748) {
-                       // some process owns the lock, let's do something else meanwhile
-               }
+       catch (LockAcquireWouldBlockException $e) {
+               // some process owns the lock, let's do something else meanwhile
        }
        if ($result) {
                $locker->release();
index 96c66c3..c42f1bc 100644 (file)
@@ -77,8 +77,7 @@ class LockFactoryTest extends UnitTestCase {
 
        /**
         * @test
-        * @expectedException \InvalidArgumentException
-        * @expectedExceptionCode 1425990190
+        * @expectedException \TYPO3\CMS\Core\Locking\Exception\LockCreateException
         */
        public function getLockerThrowsExceptionIfNoMatchFound() {
                $this->mockFactory->createLocker('id', 32);