diff --git a/src/NinjaMutex/Lock/DirectoryLock.php b/src/NinjaMutex/Lock/DirectoryLock.php new file mode 100644 index 0000000..f3c9a9c --- /dev/null +++ b/src/NinjaMutex/Lock/DirectoryLock.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace NinjaMutex\Lock; + +/** + * Lock implementor using mkdir + * + * @author Jan Voracek + */ +class DirectoryLock extends LockAbstract +{ + protected $dirname; + + /** + * @param string $dirname + */ + public function __construct($dirname) + { + parent::__construct(); + + $this->dirname = $dirname; + } + + /** + * @param string $name + * @param bool $blocking + * @return bool + */ + protected function getLock($name, $blocking) + { + while (!@mkdir($this->getDirectoryPath($name))) { + if (!$blocking) { + return false; + } + + usleep(rand(5000, 20000)); + } + + return true; + } + + /** + * Release lock + * + * @param string $name name of lock + * @return bool + */ + public function releaseLock($name) + { + if (isset($this->locks[$name])) { + rmdir($this->getDirectoryPath($name)); + unset($this->locks[$name]); + + return true; + } + + return false; + } + + /** + * @param string $name + * @return string + */ + protected function getDirectoryPath($name) + { + return $this->dirname . DIRECTORY_SEPARATOR . $name . '.lock'; + } + + /** + * Check if lock is locked + * + * @param string $name name of lock + * @return bool + */ + public function isLocked($name) + { + if ($this->acquireLock($name, false)) { + return !$this->releaseLock($name); + } + + return true; + } +} diff --git a/tests/NinjaMutex/AbstractTest.php b/tests/NinjaMutex/AbstractTest.php index 25b1476..e618591 100644 --- a/tests/NinjaMutex/AbstractTest.php +++ b/tests/NinjaMutex/AbstractTest.php @@ -9,6 +9,7 @@ */ namespace NinjaMutex; +use NinjaMutex\Lock\DirectoryLock; use NinjaMutex\Lock\FlockLock; use NinjaMutex\Lock\MemcacheLock; use NinjaMutex\Lock\MemcachedLock; @@ -62,6 +63,7 @@ public function lockImplementorProvider() $data = array( // Just mocks $this->provideFlockMockLock(), + $this->provideDirectoryMockLock(), $this->provideMemcacheMockLock(), $this->provideMemcachedMockLock(), $this->provideMysqlMockLock(), @@ -69,6 +71,7 @@ public function lockImplementorProvider() $this->providePhpRedisMockLock(), // Real locks $this->provideFlockLock(), + $this->provideDirectoryLock(), array($memcacheLockFabric->create()), array($memcachedLockFabric->create()), $this->provideMysqlLock(), @@ -139,6 +142,14 @@ protected function provideFlockMockLock() return array(new FlockLock(vfs\vfsStream::url('nfs/'))); } + /** + * @return array + */ + protected function provideDirectoryMockLock() + { + return array(new DirectoryLock(vfs\vfsStream::url('nfs/'))); + } + /** * @return array */ @@ -175,6 +186,14 @@ protected function provideFlockLock() return array(new FlockLock('/tmp/mutex/')); } + /** + * @return array + */ + protected function provideDirectoryLock() + { + return array(new DirectoryLock('/tmp/mutex/')); + } + /** * @return array */