From 7aef563dd530636abacedf84088231310c7c7cce Mon Sep 17 00:00:00 2001 From: resurtm Date: Mon, 24 Jun 2013 22:30:50 +0600 Subject: [PATCH 01/11] Proposed mutex extension. --- extensions/mutex/Mutex.php | 76 +++++++++++++++++++++++++++++ extensions/mutex/db/Mutex.php | 29 +++++++++++ extensions/mutex/db/mssql/Mutex.php | 28 +++++++++++ extensions/mutex/db/mysql/Mutex.php | 38 +++++++++++++++ extensions/mutex/unix/Mutex.php | 59 ++++++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 extensions/mutex/Mutex.php create mode 100644 extensions/mutex/db/Mutex.php create mode 100644 extensions/mutex/db/mssql/Mutex.php create mode 100644 extensions/mutex/db/mysql/Mutex.php create mode 100644 extensions/mutex/unix/Mutex.php diff --git a/extensions/mutex/Mutex.php b/extensions/mutex/Mutex.php new file mode 100644 index 0000000000..876bc2b1e2 --- /dev/null +++ b/extensions/mutex/Mutex.php @@ -0,0 +1,76 @@ +autoRelease) { + register_shutdown_function(array($this, 'shutdownFunction')); + } + } + + /** + * NEVER CALL THIS METHOD UNDER ANY CIRCUMSTANCES + */ + public function shutdownFunction() + { + foreach ($this->_locks as $lock) { + $this->release($lock); + } + } + + public function acquireLock($name, $timeout = 0) + { + if ($this->acquire($name, $timeout)) { + $this->_locks[] = $name; + return true; + } else { + return false; + } + } + + public function releaseLock($name) + { + if ($this->release($name)) { + unset($this->_locks[array_search($name, $this->_locks)]); + return true; + } else { + return false; + } + } + + public function getIsLockAcquired($name) + { + if (in_array($name, $this->_locks)) { + return true; + } else { + return $this->getIsAcquired($name); + } + } + + public function getIsLockLocal($name) + { + return in_array($name, $this->_locks); + } + + abstract protected function acquire($name, $timeout = 0); + + abstract protected function release($name); + + protected function getIsAcquired($name) + { + return null; + } + + abstract public function getIsDistributed(); +} diff --git a/extensions/mutex/db/Mutex.php b/extensions/mutex/db/Mutex.php new file mode 100644 index 0000000000..2fae64122b --- /dev/null +++ b/extensions/mutex/db/Mutex.php @@ -0,0 +1,29 @@ +db = Yii::$app->getComponent($this->db); + if (!$this->db instanceof Connection) { + throw new InvalidConfigException(''); + } + } + + public function getIsDistributed() + { + return true; + } +} diff --git a/extensions/mutex/db/mssql/Mutex.php b/extensions/mutex/db/mssql/Mutex.php new file mode 100644 index 0000000000..0b673053f3 --- /dev/null +++ b/extensions/mutex/db/mssql/Mutex.php @@ -0,0 +1,28 @@ +db->driverName; + if ($driverName !== 'sqlsrv' && $driverName !== 'dblib' && $driverName !== 'mssql') { + throw new InvalidConfigException(''); + } + } + + protected function acquire($name, $timeout = 0) + { + // http://msdn.microsoft.com/en-us/library/ms189823.aspx + } + + protected function release($name) + { + // http://msdn.microsoft.com/en-us/library/ms178602.aspx + } +} diff --git a/extensions/mutex/db/mysql/Mutex.php b/extensions/mutex/db/mysql/Mutex.php new file mode 100644 index 0000000000..07ab7e2cd5 --- /dev/null +++ b/extensions/mutex/db/mysql/Mutex.php @@ -0,0 +1,38 @@ +db->driverName !== 'mysql') { + throw new InvalidConfigException(''); + } + } + + protected function acquire($name, $timeout = 0) + { + return (boolean)$this->db + ->createCommand('SELECT GET_LOCK(:name, :timeout)', array(':name' => $name, ':timeout' => $timeout)) + ->queryScalar(); + } + + protected function release($name) + { + return (boolean)$this->db + ->createCommand('SELECT RELEASE_LOCK(:name)', array(':name' => $name)) + ->queryScalar(); + } + + protected function getIsAcquired($name) + { + return (boolean)$this->db + ->createCommand('SELECT IS_FREE_LOCK(:name)', array(':name' => $name)) + ->queryScalar(); + } +} diff --git a/extensions/mutex/unix/Mutex.php b/extensions/mutex/unix/Mutex.php new file mode 100644 index 0000000000..3e3d530d4a --- /dev/null +++ b/extensions/mutex/unix/Mutex.php @@ -0,0 +1,59 @@ +getRuntimePath() . '/mutex.' . md5($name) . '.lock', 'w+'); + if ($file === false) { + return false; + } + $waitTime = 0; + while (!flock($file, LOCK_EX | LOCK_NB)) { + $waitTime++; + if ($waitTime > $timeout) { + fclose($file); + return false; + } + sleep(1); + } + $this->_files[$name] = $file; + return true; + } + + protected function release($name) + { + if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) { + return false; + } else { + fclose($this->_files[$name]); + unset($this->_files[$name]); + return true; + } + } + + protected function getIsAcquired($name) + { + return false; + } + + public function getIsDistributed() + { + return false; + } +} From dd48e8a71b1f35f505c2876697f6893d7c27b3d8 Mon Sep 17 00:00:00 2001 From: resurtm Date: Mon, 24 Jun 2013 22:34:40 +0600 Subject: [PATCH 02/11] Uncomment UNIX Mutex. --- extensions/mutex/unix/Mutex.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/mutex/unix/Mutex.php b/extensions/mutex/unix/Mutex.php index 3e3d530d4a..c95baa8ff1 100644 --- a/extensions/mutex/unix/Mutex.php +++ b/extensions/mutex/unix/Mutex.php @@ -12,9 +12,9 @@ class Mutex extends \yii\mutex\Mutex public function init() { -// if (stripos(php_uname('s'), 'win') === 0) { -// throw new InvalidConfigException(''); -// } + if (stripos(php_uname('s'), 'win') === 0) { + throw new InvalidConfigException(''); + } } protected function acquire($name, $timeout = 0) From 421e2eb960a13cfb95fa70a1d2afc17a28e12749 Mon Sep 17 00:00:00 2001 From: resurtm Date: Mon, 24 Jun 2013 23:34:57 +0600 Subject: [PATCH 03/11] Mutex extension docblocks and several minor fixes. --- extensions/mutex/Mutex.php | 68 ++++++++++++++++++++++++++++- extensions/mutex/db/Mutex.php | 28 ++++++++++-- extensions/mutex/db/mssql/Mutex.php | 32 +++++++++++++- extensions/mutex/db/mysql/Mutex.php | 34 +++++++++++++++ extensions/mutex/unix/Mutex.php | 40 +++++++++++++++++ 5 files changed, 195 insertions(+), 7 deletions(-) diff --git a/extensions/mutex/Mutex.php b/extensions/mutex/Mutex.php index 876bc2b1e2..5268d866ca 100644 --- a/extensions/mutex/Mutex.php +++ b/extensions/mutex/Mutex.php @@ -1,17 +1,35 @@ + * @since 2.0 + */ abstract class Mutex extends Component { + /** + * @var boolean whether all locks acquired in this process (i.e. local locks) must be released automagically + * before finishing script execution. Defaults to true. Setting this property to true + */ public $autoRelease = true; - + /** + * @var string[] names of the locks acquired in the current PHP process. + */ private $_locks = array(); + /** + * Initializes the mutex component. + */ public function init() { if ($this->autoRelease) { @@ -20,7 +38,7 @@ abstract class Mutex extends Component } /** - * NEVER CALL THIS METHOD UNDER ANY CIRCUMSTANCES + * Never call this method directly under any circumstances. This method is intended for internal use only. */ public function shutdownFunction() { @@ -29,6 +47,12 @@ abstract class Mutex extends Component } } + /** + * @param string $name of the lock to be acquired. Must be unique. + * @param integer $timeout to wait for lock to be released. Defaults to zero meaning that method will return + * false immediately in case lock was already acquired. + * @return boolean lock acquiring result. + */ public function acquireLock($name, $timeout = 0) { if ($this->acquire($name, $timeout)) { @@ -39,6 +63,11 @@ abstract class Mutex extends Component } } + /** + * Release acquired lock. + * @param string $name of the lock to be released. This lock must be already created. + * @return boolean lock release result. + */ public function releaseLock($name) { if ($this->release($name)) { @@ -49,6 +78,12 @@ abstract class Mutex extends Component } } + /** + * Checks whether named lock was already opened. + * @param string $name of the lock to be checked. This lock must be already created. + * @return boolean|null whether named lock was already opened. Returns `null` value in case concrete + * mutex implementation does not support this operation. + */ public function getIsLockAcquired($name) { if (in_array($name, $this->_locks)) { @@ -58,19 +93,48 @@ abstract class Mutex extends Component } } + /** + * Checks whether given lock is local. In other words local lock means that it was opened in the current + * PHP process. + * @param string $name of the lock to be checked. This lock must be already created. + * @return boolean whether named lock was locally acquired. + */ public function getIsLockLocal($name) { return in_array($name, $this->_locks); } + /** + * This method should be extended by concrete mutex implementations. Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + */ abstract protected function acquire($name, $timeout = 0); + /** + * This method should be extended by concrete mutex implementations. Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + */ abstract protected function release($name); + /** + * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been + * already acquired by given name. + * @param string $name of the lock to be released. + * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature + * is not supported by concrete mutex implementation. + */ protected function getIsAcquired($name) { return null; } + /** + * This method should be extended by concrete mutex implementations. Returns whether current mutex + * implementation can be used in a distributed environment. + * @return boolean whether current mutex implementation can be used in a distributed environment. + */ abstract public function getIsDistributed(); } diff --git a/extensions/mutex/db/Mutex.php b/extensions/mutex/db/Mutex.php index 2fae64122b..17dd68a0dd 100644 --- a/extensions/mutex/db/Mutex.php +++ b/extensions/mutex/db/Mutex.php @@ -1,4 +1,9 @@ + * @since 2.0 + */ abstract class Mutex extends \yii\mutex\Mutex { /** - * @var string|Connection + * @var Connection|string the DB connection object or the application component ID of the DB connection. + * After the Mutex object is created, if you want to change this property, you should only assign + * it with a DB connection object. */ public $db = 'db'; + /** + * Initializes generic database table based mutex implementation. + * @throws InvalidConfigException if [[db]] is invalid. + */ public function init() { parent::init(); - $this->db = Yii::$app->getComponent($this->db); + if (is_string($this->db)) { + $this->db = Yii::$app->getComponent($this->db); + } if (!$this->db instanceof Connection) { - throw new InvalidConfigException(''); + throw new InvalidConfigException('Mutex::db must be either a DB connection instance or the application component ID of a DB connection.'); } } + /** + * This method should be extended by concrete mutex implementations. Returns whether current mutex + * implementation can be used in a distributed environment. + * @return boolean whether current mutex implementation can be used in a distributed environment. + */ public function getIsDistributed() { return true; diff --git a/extensions/mutex/db/mssql/Mutex.php b/extensions/mutex/db/mssql/Mutex.php index 0b673053f3..374100aed3 100644 --- a/extensions/mutex/db/mssql/Mutex.php +++ b/extensions/mutex/db/mssql/Mutex.php @@ -1,12 +1,25 @@ + * @since 2.0 + */ class Mutex extends \yii\mutex\db\Mutex { + /** + * Initializes Microsoft SQL Server specific mutex component implementation. + * @throws InvalidConfigException if [[db]] is not Microsoft SQL Server connection. + */ public function init() { parent::init(); @@ -16,13 +29,28 @@ class Mutex extends \yii\mutex\db\Mutex } } + /** + * This method should be extended by concrete mutex implementations. Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + * @throws \BadMethodCallException + * @see http://msdn.microsoft.com/en-us/library/ms189823.aspx + */ protected function acquire($name, $timeout = 0) { - // http://msdn.microsoft.com/en-us/library/ms189823.aspx + throw new \BadMethodCallException('Not implemented yet.'); } + /** + * This method should be extended by concrete mutex implementations. Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + * @throws \BadMethodCallException + * @see http://msdn.microsoft.com/en-us/library/ms178602.aspx + */ protected function release($name) { - // http://msdn.microsoft.com/en-us/library/ms178602.aspx + throw new \BadMethodCallException('Not implemented yet.'); } } diff --git a/extensions/mutex/db/mysql/Mutex.php b/extensions/mutex/db/mysql/Mutex.php index 07ab7e2cd5..7153d385f2 100644 --- a/extensions/mutex/db/mysql/Mutex.php +++ b/extensions/mutex/db/mysql/Mutex.php @@ -1,12 +1,25 @@ + * @since 2.0 + */ class Mutex extends \yii\mutex\db\Mutex { + /** + * Initializes MySQL specific mutex component implementation. + * @throws InvalidConfigException if [[db]] is not MySQL connection. + */ public function init() { parent::init(); @@ -15,6 +28,13 @@ class Mutex extends \yii\mutex\db\Mutex } } + /** + * This method should be extended by concrete mutex implementations. Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock + */ protected function acquire($name, $timeout = 0) { return (boolean)$this->db @@ -22,6 +42,12 @@ class Mutex extends \yii\mutex\db\Mutex ->queryScalar(); } + /** + * This method should be extended by concrete mutex implementations. Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock + */ protected function release($name) { return (boolean)$this->db @@ -29,6 +55,14 @@ class Mutex extends \yii\mutex\db\Mutex ->queryScalar(); } + /** + * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been + * already acquired by given name. + * @param string $name of the lock to be released. + * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature + * is not supported by concrete mutex implementation. + * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_is-free-lock + */ protected function getIsAcquired($name) { return (boolean)$this->db diff --git a/extensions/mutex/unix/Mutex.php b/extensions/mutex/unix/Mutex.php index c95baa8ff1..ca18a499c5 100644 --- a/extensions/mutex/unix/Mutex.php +++ b/extensions/mutex/unix/Mutex.php @@ -1,15 +1,32 @@ + * @since 2.0 + */ class Mutex extends \yii\mutex\Mutex { + /** + * @var resource[] stores all opened lock files. Keys are lock names and values are file handles. + */ private $_files = array(); + /** + * Initializes mutex component implementation dedicated for UNIX, GNU/Linux, Mac OS X, and other UNIX-like + * operating systems. + * @throws InvalidConfigException + */ public function init() { if (stripos(php_uname('s'), 'win') === 0) { @@ -17,6 +34,12 @@ class Mutex extends \yii\mutex\Mutex } } + /** + * This method should be extended by concrete mutex implementations. Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + */ protected function acquire($name, $timeout = 0) { $file = fopen(Yii::$app->getRuntimePath() . '/mutex.' . md5($name) . '.lock', 'w+'); @@ -36,6 +59,11 @@ class Mutex extends \yii\mutex\Mutex return true; } + /** + * This method should be extended by concrete mutex implementations. Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + */ protected function release($name) { if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) { @@ -47,11 +75,23 @@ class Mutex extends \yii\mutex\Mutex } } + /** + * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been + * already acquired by given name. + * @param string $name of the lock to be released. + * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature + * is not supported by concrete mutex implementation. + */ protected function getIsAcquired($name) { return false; } + /** + * This method should be extended by concrete mutex implementations. Returns whether current mutex + * implementation can be used in a distributed environment. + * @return boolean whether current mutex implementation can be used in a distributed environment. + */ public function getIsDistributed() { return false; From a15c70f414c67ca0bc46fc8148af988432d594ea Mon Sep 17 00:00:00 2001 From: resurtm Date: Mon, 24 Jun 2013 23:42:11 +0600 Subject: [PATCH 04/11] composer.json file and proper class files location. --- extensions/mutex/composer.json | 27 +++++++++++++++++++ extensions/mutex/{ => yii}/Mutex.php | 0 extensions/mutex/{ => yii}/db/Mutex.php | 0 extensions/mutex/{ => yii}/db/mssql/Mutex.php | 0 extensions/mutex/{ => yii}/db/mysql/Mutex.php | 0 extensions/mutex/{ => yii}/unix/Mutex.php | 0 6 files changed, 27 insertions(+) create mode 100644 extensions/mutex/composer.json rename extensions/mutex/{ => yii}/Mutex.php (100%) rename extensions/mutex/{ => yii}/db/Mutex.php (100%) rename extensions/mutex/{ => yii}/db/mssql/Mutex.php (100%) rename extensions/mutex/{ => yii}/db/mysql/Mutex.php (100%) rename extensions/mutex/{ => yii}/unix/Mutex.php (100%) diff --git a/extensions/mutex/composer.json b/extensions/mutex/composer.json new file mode 100644 index 0000000000..44995432f9 --- /dev/null +++ b/extensions/mutex/composer.json @@ -0,0 +1,27 @@ +{ + "name": "yiisoft/yii2-mutex", + "description": "Mutual exclusion extension for the Yii framework", + "keywords": ["yii", "mutex"], + "type": "library", + "license": "BSD-3-Clause", + "support": { + "issues": "https://github.com/yiisoft/yii2/issues?state=open", + "forum": "http://www.yiiframework.com/forum/", + "wiki": "http://www.yiiframework.com/wiki/", + "irc": "irc://irc.freenode.net/yii", + "source": "https://github.com/yiisoft/yii2" + }, + "authors": [ + { + "name": "resurtm", + "email": "resurtm@gmail.com" + } + ], + "minimum-stability": "dev", + "require": { + "yiisoft/yii2": "*" + }, + "autoload": { + "psr-0": { "yii\\smarty": "" } + } +} diff --git a/extensions/mutex/Mutex.php b/extensions/mutex/yii/Mutex.php similarity index 100% rename from extensions/mutex/Mutex.php rename to extensions/mutex/yii/Mutex.php diff --git a/extensions/mutex/db/Mutex.php b/extensions/mutex/yii/db/Mutex.php similarity index 100% rename from extensions/mutex/db/Mutex.php rename to extensions/mutex/yii/db/Mutex.php diff --git a/extensions/mutex/db/mssql/Mutex.php b/extensions/mutex/yii/db/mssql/Mutex.php similarity index 100% rename from extensions/mutex/db/mssql/Mutex.php rename to extensions/mutex/yii/db/mssql/Mutex.php diff --git a/extensions/mutex/db/mysql/Mutex.php b/extensions/mutex/yii/db/mysql/Mutex.php similarity index 100% rename from extensions/mutex/db/mysql/Mutex.php rename to extensions/mutex/yii/db/mysql/Mutex.php diff --git a/extensions/mutex/unix/Mutex.php b/extensions/mutex/yii/unix/Mutex.php similarity index 100% rename from extensions/mutex/unix/Mutex.php rename to extensions/mutex/yii/unix/Mutex.php From b8541df0882c208831aa2a03a56fe9e991e7c7fa Mon Sep 17 00:00:00 2001 From: resurtm Date: Mon, 24 Jun 2013 23:44:02 +0600 Subject: [PATCH 05/11] Proper files location. --- extensions/mutex/yii/{ => mutex}/Mutex.php | 0 extensions/mutex/yii/{ => mutex}/db/Mutex.php | 0 extensions/mutex/yii/{ => mutex}/db/mssql/Mutex.php | 0 extensions/mutex/yii/{ => mutex}/db/mysql/Mutex.php | 0 extensions/mutex/yii/{ => mutex}/unix/Mutex.php | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename extensions/mutex/yii/{ => mutex}/Mutex.php (100%) rename extensions/mutex/yii/{ => mutex}/db/Mutex.php (100%) rename extensions/mutex/yii/{ => mutex}/db/mssql/Mutex.php (100%) rename extensions/mutex/yii/{ => mutex}/db/mysql/Mutex.php (100%) rename extensions/mutex/yii/{ => mutex}/unix/Mutex.php (100%) diff --git a/extensions/mutex/yii/Mutex.php b/extensions/mutex/yii/mutex/Mutex.php similarity index 100% rename from extensions/mutex/yii/Mutex.php rename to extensions/mutex/yii/mutex/Mutex.php diff --git a/extensions/mutex/yii/db/Mutex.php b/extensions/mutex/yii/mutex/db/Mutex.php similarity index 100% rename from extensions/mutex/yii/db/Mutex.php rename to extensions/mutex/yii/mutex/db/Mutex.php diff --git a/extensions/mutex/yii/db/mssql/Mutex.php b/extensions/mutex/yii/mutex/db/mssql/Mutex.php similarity index 100% rename from extensions/mutex/yii/db/mssql/Mutex.php rename to extensions/mutex/yii/mutex/db/mssql/Mutex.php diff --git a/extensions/mutex/yii/db/mysql/Mutex.php b/extensions/mutex/yii/mutex/db/mysql/Mutex.php similarity index 100% rename from extensions/mutex/yii/db/mysql/Mutex.php rename to extensions/mutex/yii/mutex/db/mysql/Mutex.php diff --git a/extensions/mutex/yii/unix/Mutex.php b/extensions/mutex/yii/mutex/unix/Mutex.php similarity index 100% rename from extensions/mutex/yii/unix/Mutex.php rename to extensions/mutex/yii/mutex/unix/Mutex.php From 397004c8f6695cc8f041c570b2f0e212c790d727 Mon Sep 17 00:00:00 2001 From: resurtm Date: Tue, 25 Jun 2013 00:14:42 +0600 Subject: [PATCH 06/11] Mutex cache backend WIP. --- extensions/mutex/yii/mutex/cache/Mutex.php | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 extensions/mutex/yii/mutex/cache/Mutex.php diff --git a/extensions/mutex/yii/mutex/cache/Mutex.php b/extensions/mutex/yii/mutex/cache/Mutex.php new file mode 100644 index 0000000000..67b64458a9 --- /dev/null +++ b/extensions/mutex/yii/mutex/cache/Mutex.php @@ -0,0 +1,89 @@ + + * @since 2.0 + */ +class Mutex extends \yii\mutex\Mutex +{ + /** + * @var Cache|string the cache object or the application component ID of the cache object. + * The messages data will be cached using this cache object. Note, this property has meaning only + * in case [[cachingDuration]] set to non-zero value. + * After the Mutex object is created, if you want to change this property, you should only assign + * it with a cache object. + */ + public $cache = 'cache'; + + + /** + * Initializes the DbMessageSource component. Configured [[cache]] component will be initialized. + * @throws InvalidConfigException if [[cache]] is invalid. + */ + public function init() + { + parent::init(); + if (is_string($this->cache)) { + $this->cache = Yii::$app->getComponent($this->cache); + } + if (!$this->cache instanceof Cache) { + throw new InvalidConfigException('Mutex::cache must be either a cache object or the application component ID of the cache object.'); + } + } + + /** + * This method should be extended by concrete mutex implementations. Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + */ + protected function acquire($name, $timeout = 0) + { + + } + + /** + * This method should be extended by concrete mutex implementations. Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + */ + protected function release($name) + { + return $this->cache->delete("mutex.{$name}"); + } + + /** + * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been + * already acquired by given name. + * @param string $name of the lock to be released. + * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature + * is not supported by concrete mutex implementation. + */ + protected function getIsAcquired($name) + { + + } + + /** + * This method should be extended by concrete mutex implementations. Returns whether current mutex + * implementation can be used in a distributed environment. + * @return boolean whether current mutex implementation can be used in a distributed environment. + */ + public function getIsDistributed() + { + return $this->cache instanceof DbCache || $this->cache instanceof MemCache; + } +} From 90227bd3448f31d0b4e847236a6cc9740b6bc7d3 Mon Sep 17 00:00:00 2001 From: resurtm Date: Tue, 25 Jun 2013 07:22:06 +0600 Subject: [PATCH 07/11] Autorelease callback improved, composer.json typo. --- extensions/mutex/composer.json | 2 +- extensions/mutex/yii/mutex/Mutex.php | 12 ++++++++---- extensions/mutex/yii/mutex/cache/Mutex.php | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/extensions/mutex/composer.json b/extensions/mutex/composer.json index 44995432f9..db8cde3599 100644 --- a/extensions/mutex/composer.json +++ b/extensions/mutex/composer.json @@ -22,6 +22,6 @@ "yiisoft/yii2": "*" }, "autoload": { - "psr-0": { "yii\\smarty": "" } + "psr-0": { "yii\\mutex": "" } } } diff --git a/extensions/mutex/yii/mutex/Mutex.php b/extensions/mutex/yii/mutex/Mutex.php index 5268d866ca..14ebf8fe95 100644 --- a/extensions/mutex/yii/mutex/Mutex.php +++ b/extensions/mutex/yii/mutex/Mutex.php @@ -33,7 +33,13 @@ abstract class Mutex extends Component public function init() { if ($this->autoRelease) { - register_shutdown_function(array($this, 'shutdownFunction')); + $referenceHolder = new stdClass(); + $referenceHolder->locks = &$this->_locks; + register_shutdown_function(function ($ref) { + foreach ($ref->locks as $lock) { + $this->release($lock); + } + }, $referenceHolder); } } @@ -42,9 +48,7 @@ abstract class Mutex extends Component */ public function shutdownFunction() { - foreach ($this->_locks as $lock) { - $this->release($lock); - } + } /** diff --git a/extensions/mutex/yii/mutex/cache/Mutex.php b/extensions/mutex/yii/mutex/cache/Mutex.php index 67b64458a9..73e277bf13 100644 --- a/extensions/mutex/yii/mutex/cache/Mutex.php +++ b/extensions/mutex/yii/mutex/cache/Mutex.php @@ -74,7 +74,7 @@ class Mutex extends \yii\mutex\Mutex */ protected function getIsAcquired($name) { - + } /** From 33adfcea91b45a5287bacfdf26b4bf30e69acd6c Mon Sep 17 00:00:00 2001 From: resurtm Date: Tue, 25 Jun 2013 07:24:57 +0600 Subject: [PATCH 08/11] Autorelease callback. --- extensions/mutex/yii/mutex/Mutex.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/mutex/yii/mutex/Mutex.php b/extensions/mutex/yii/mutex/Mutex.php index 14ebf8fe95..c7413a1ce6 100644 --- a/extensions/mutex/yii/mutex/Mutex.php +++ b/extensions/mutex/yii/mutex/Mutex.php @@ -34,10 +34,11 @@ abstract class Mutex extends Component { if ($this->autoRelease) { $referenceHolder = new stdClass(); + $referenceHolder->mutex = &$this; $referenceHolder->locks = &$this->_locks; register_shutdown_function(function ($ref) { foreach ($ref->locks as $lock) { - $this->release($lock); + $ref->mutex->release($lock); } }, $referenceHolder); } From b98a1236bb829f10ae52966e924b54e3ad89fdbb Mon Sep 17 00:00:00 2001 From: resurtm Date: Tue, 25 Jun 2013 09:08:54 +0600 Subject: [PATCH 09/11] Fixes: 1. Proper auto release shutdown callback. 2. Proper Mutex::releaseLock() method. --- extensions/mutex/yii/mutex/Mutex.php | 31 ++++++++++++---------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/extensions/mutex/yii/mutex/Mutex.php b/extensions/mutex/yii/mutex/Mutex.php index c7413a1ce6..9f47501d79 100644 --- a/extensions/mutex/yii/mutex/Mutex.php +++ b/extensions/mutex/yii/mutex/Mutex.php @@ -33,25 +33,17 @@ abstract class Mutex extends Component public function init() { if ($this->autoRelease) { - $referenceHolder = new stdClass(); - $referenceHolder->mutex = &$this; - $referenceHolder->locks = &$this->_locks; - register_shutdown_function(function ($ref) { - foreach ($ref->locks as $lock) { - $ref->mutex->release($lock); + $references = new stdClass(); + $references->mutex = $this; + $references->locks = &$this->_locks; + register_shutdown_function(function ($refs) { + foreach ($refs->locks as $lock) { + $refs->mutex->release($lock); } - }, $referenceHolder); + }, $references); } } - /** - * Never call this method directly under any circumstances. This method is intended for internal use only. - */ - public function shutdownFunction() - { - - } - /** * @param string $name of the lock to be acquired. Must be unique. * @param integer $timeout to wait for lock to be released. Defaults to zero meaning that method will return @@ -69,14 +61,17 @@ abstract class Mutex extends Component } /** - * Release acquired lock. + * Release acquired lock. This method will return false in case named lock was not found. * @param string $name of the lock to be released. This lock must be already created. - * @return boolean lock release result. + * @return boolean lock release result: false in case named lock was not found.. */ public function releaseLock($name) { if ($this->release($name)) { - unset($this->_locks[array_search($name, $this->_locks)]); + $index = array_search($name, $this->_locks); + if ($index !== false) { + unset($this->_locks[$index]); + } return true; } else { return false; From 733dbbfb8b3a78b749f482005c48464e65d235e4 Mon Sep 17 00:00:00 2001 From: resurtm Date: Tue, 25 Jun 2013 09:54:07 +0600 Subject: [PATCH 10/11] Mutex WIP. --- .../yii/mutex/{db/Mutex.php => DbMutex.php} | 14 +-- .../mutex/{unix/Mutex.php => FileMutex.php} | 43 ++++----- .../{db/mssql/Mutex.php => MssqlMutex.php} | 14 +-- extensions/mutex/yii/mutex/Mutex.php | 73 +++------------ .../{db/mysql/Mutex.php => MysqlMutex.php} | 25 ++---- extensions/mutex/yii/mutex/cache/Mutex.php | 89 ------------------- 6 files changed, 43 insertions(+), 215 deletions(-) rename extensions/mutex/yii/mutex/{db/Mutex.php => DbMutex.php} (71%) rename extensions/mutex/yii/mutex/{unix/Mutex.php => FileMutex.php} (61%) rename extensions/mutex/yii/mutex/{db/mssql/Mutex.php => MssqlMutex.php} (77%) rename extensions/mutex/yii/mutex/{db/mysql/Mutex.php => MysqlMutex.php} (63%) delete mode 100644 extensions/mutex/yii/mutex/cache/Mutex.php diff --git a/extensions/mutex/yii/mutex/db/Mutex.php b/extensions/mutex/yii/mutex/DbMutex.php similarity index 71% rename from extensions/mutex/yii/mutex/db/Mutex.php rename to extensions/mutex/yii/mutex/DbMutex.php index 17dd68a0dd..3699c368f8 100644 --- a/extensions/mutex/yii/mutex/db/Mutex.php +++ b/extensions/mutex/yii/mutex/DbMutex.php @@ -5,7 +5,7 @@ * @license http://www.yiiframework.com/license/ */ -namespace yii\mutex\db; +namespace yii\mutex; use Yii; use yii\db\Connection; @@ -15,7 +15,7 @@ use yii\base\InvalidConfigException; * @author resurtm * @since 2.0 */ -abstract class Mutex extends \yii\mutex\Mutex +abstract class DbMutex extends Mutex { /** * @var Connection|string the DB connection object or the application component ID of the DB connection. @@ -38,14 +38,4 @@ abstract class Mutex extends \yii\mutex\Mutex throw new InvalidConfigException('Mutex::db must be either a DB connection instance or the application component ID of a DB connection.'); } } - - /** - * This method should be extended by concrete mutex implementations. Returns whether current mutex - * implementation can be used in a distributed environment. - * @return boolean whether current mutex implementation can be used in a distributed environment. - */ - public function getIsDistributed() - { - return true; - } } diff --git a/extensions/mutex/yii/mutex/unix/Mutex.php b/extensions/mutex/yii/mutex/FileMutex.php similarity index 61% rename from extensions/mutex/yii/mutex/unix/Mutex.php rename to extensions/mutex/yii/mutex/FileMutex.php index ca18a499c5..4a949d0526 100644 --- a/extensions/mutex/yii/mutex/unix/Mutex.php +++ b/extensions/mutex/yii/mutex/FileMutex.php @@ -5,7 +5,7 @@ * @license http://www.yiiframework.com/license/ */ -namespace yii\mutex\unix; +namespace yii\mutex; use Yii; use yii\base\InvalidConfigException; @@ -14,8 +14,13 @@ use yii\base\InvalidConfigException; * @author resurtm * @since 2.0 */ -class Mutex extends \yii\mutex\Mutex +class FileMutex extends Mutex { + /** + * @var string the directory to store mutex files. You may use path alias here. + * If not set, it will use the "mutex" subdirectory under the application runtime path. + */ + public $mutexPath = '@runtime/mutex'; /** * @var resource[] stores all opened lock files. Keys are lock names and values are file handles. */ @@ -30,7 +35,11 @@ class Mutex extends \yii\mutex\Mutex public function init() { if (stripos(php_uname('s'), 'win') === 0) { - throw new InvalidConfigException(''); + throw new InvalidConfigException('FileMutex does not have MS Windows operating system support.'); + } + $this->mutexPath = Yii::getAlias($this->mutexPath); + if (!is_dir($this->mutexPath)) { + mkdir($this->mutexPath, 0777, true); } } @@ -40,9 +49,9 @@ class Mutex extends \yii\mutex\Mutex * @param integer $timeout to wait for lock to become released. * @return boolean acquiring result. */ - protected function acquire($name, $timeout = 0) + protected function acquireLock($name, $timeout = 0) { - $file = fopen(Yii::$app->getRuntimePath() . '/mutex.' . md5($name) . '.lock', 'w+'); + $file = fopen($this->mutexPath . '/' . md5($name) . '.lock', 'w+'); if ($file === false) { return false; } @@ -64,7 +73,7 @@ class Mutex extends \yii\mutex\Mutex * @param string $name of the lock to be released. * @return boolean release result. */ - protected function release($name) + protected function releaseLock($name) { if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) { return false; @@ -74,26 +83,4 @@ class Mutex extends \yii\mutex\Mutex return true; } } - - /** - * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been - * already acquired by given name. - * @param string $name of the lock to be released. - * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature - * is not supported by concrete mutex implementation. - */ - protected function getIsAcquired($name) - { - return false; - } - - /** - * This method should be extended by concrete mutex implementations. Returns whether current mutex - * implementation can be used in a distributed environment. - * @return boolean whether current mutex implementation can be used in a distributed environment. - */ - public function getIsDistributed() - { - return false; - } } diff --git a/extensions/mutex/yii/mutex/db/mssql/Mutex.php b/extensions/mutex/yii/mutex/MssqlMutex.php similarity index 77% rename from extensions/mutex/yii/mutex/db/mssql/Mutex.php rename to extensions/mutex/yii/mutex/MssqlMutex.php index 374100aed3..d267699d6c 100644 --- a/extensions/mutex/yii/mutex/db/mssql/Mutex.php +++ b/extensions/mutex/yii/mutex/MssqlMutex.php @@ -5,7 +5,7 @@ * @license http://www.yiiframework.com/license/ */ -namespace yii\mutex\db\mssql; +namespace yii\mutex; use Yii; use yii\base\InvalidConfigException; @@ -14,7 +14,7 @@ use yii\base\InvalidConfigException; * @author resurtm * @since 2.0 */ -class Mutex extends \yii\mutex\db\Mutex +class MssqlMutex extends Mutex { /** * Initializes Microsoft SQL Server specific mutex component implementation. @@ -25,7 +25,7 @@ class Mutex extends \yii\mutex\db\Mutex parent::init(); $driverName = $this->db->driverName; if ($driverName !== 'sqlsrv' && $driverName !== 'dblib' && $driverName !== 'mssql') { - throw new InvalidConfigException(''); + throw new InvalidConfigException('In order to use MssqlMutex connection must be configured to use MS SQL Server database.'); } } @@ -34,10 +34,10 @@ class Mutex extends \yii\mutex\db\Mutex * @param string $name of the lock to be acquired. * @param integer $timeout to wait for lock to become released. * @return boolean acquiring result. - * @throws \BadMethodCallException + * @throws \BadMethodCallException not implemented yet. * @see http://msdn.microsoft.com/en-us/library/ms189823.aspx */ - protected function acquire($name, $timeout = 0) + protected function acquireLock($name, $timeout = 0) { throw new \BadMethodCallException('Not implemented yet.'); } @@ -46,10 +46,10 @@ class Mutex extends \yii\mutex\db\Mutex * This method should be extended by concrete mutex implementations. Releases lock by given name. * @param string $name of the lock to be released. * @return boolean release result. - * @throws \BadMethodCallException + * @throws \BadMethodCallException not implemented yet. * @see http://msdn.microsoft.com/en-us/library/ms178602.aspx */ - protected function release($name) + protected function releaseLock($name) { throw new \BadMethodCallException('Not implemented yet.'); } diff --git a/extensions/mutex/yii/mutex/Mutex.php b/extensions/mutex/yii/mutex/Mutex.php index 9f47501d79..297abafde8 100644 --- a/extensions/mutex/yii/mutex/Mutex.php +++ b/extensions/mutex/yii/mutex/Mutex.php @@ -18,7 +18,8 @@ abstract class Mutex extends Component { /** * @var boolean whether all locks acquired in this process (i.e. local locks) must be released automagically - * before finishing script execution. Defaults to true. Setting this property to true + * before finishing script execution. Defaults to true. Setting this property to true means that all locks + * acquire in this process must be released in any case (regardless any kind of errors or exceptions). */ public $autoRelease = true; /** @@ -33,14 +34,13 @@ abstract class Mutex extends Component public function init() { if ($this->autoRelease) { - $references = new stdClass(); - $references->mutex = $this; - $references->locks = &$this->_locks; - register_shutdown_function(function ($refs) { - foreach ($refs->locks as $lock) { - $refs->mutex->release($lock); + $mutex = $this; + $locks = &$this->_locks; + register_shutdown_function(function () use ($mutex, &$locks) { + foreach ($locks as $lock) { + $mutex->release($lock); } - }, $references); + }); } } @@ -50,9 +50,9 @@ abstract class Mutex extends Component * false immediately in case lock was already acquired. * @return boolean lock acquiring result. */ - public function acquireLock($name, $timeout = 0) + public function acquire($name, $timeout = 0) { - if ($this->acquire($name, $timeout)) { + if ($this->acquireLock($name, $timeout)) { $this->_locks[] = $name; return true; } else { @@ -65,9 +65,9 @@ abstract class Mutex extends Component * @param string $name of the lock to be released. This lock must be already created. * @return boolean lock release result: false in case named lock was not found.. */ - public function releaseLock($name) + public function release($name) { - if ($this->release($name)) { + if ($this->releaseLock($name)) { $index = array_search($name, $this->_locks); if ($index !== false) { unset($this->_locks[$index]); @@ -78,63 +78,18 @@ abstract class Mutex extends Component } } - /** - * Checks whether named lock was already opened. - * @param string $name of the lock to be checked. This lock must be already created. - * @return boolean|null whether named lock was already opened. Returns `null` value in case concrete - * mutex implementation does not support this operation. - */ - public function getIsLockAcquired($name) - { - if (in_array($name, $this->_locks)) { - return true; - } else { - return $this->getIsAcquired($name); - } - } - - /** - * Checks whether given lock is local. In other words local lock means that it was opened in the current - * PHP process. - * @param string $name of the lock to be checked. This lock must be already created. - * @return boolean whether named lock was locally acquired. - */ - public function getIsLockLocal($name) - { - return in_array($name, $this->_locks); - } - /** * This method should be extended by concrete mutex implementations. Acquires lock by given name. * @param string $name of the lock to be acquired. * @param integer $timeout to wait for lock to become released. * @return boolean acquiring result. */ - abstract protected function acquire($name, $timeout = 0); + abstract protected function acquireLock($name, $timeout = 0); /** * This method should be extended by concrete mutex implementations. Releases lock by given name. * @param string $name of the lock to be released. * @return boolean release result. */ - abstract protected function release($name); - - /** - * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been - * already acquired by given name. - * @param string $name of the lock to be released. - * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature - * is not supported by concrete mutex implementation. - */ - protected function getIsAcquired($name) - { - return null; - } - - /** - * This method should be extended by concrete mutex implementations. Returns whether current mutex - * implementation can be used in a distributed environment. - * @return boolean whether current mutex implementation can be used in a distributed environment. - */ - abstract public function getIsDistributed(); + abstract protected function releaseLock($name); } diff --git a/extensions/mutex/yii/mutex/db/mysql/Mutex.php b/extensions/mutex/yii/mutex/MysqlMutex.php similarity index 63% rename from extensions/mutex/yii/mutex/db/mysql/Mutex.php rename to extensions/mutex/yii/mutex/MysqlMutex.php index 7153d385f2..b04427a209 100644 --- a/extensions/mutex/yii/mutex/db/mysql/Mutex.php +++ b/extensions/mutex/yii/mutex/MysqlMutex.php @@ -5,7 +5,7 @@ * @license http://www.yiiframework.com/license/ */ -namespace yii\mutex\db\mysql; +namespace yii\mutex; use Yii; use yii\base\InvalidConfigException; @@ -14,7 +14,7 @@ use yii\base\InvalidConfigException; * @author resurtm * @since 2.0 */ -class Mutex extends \yii\mutex\db\Mutex +class MysqlMutex extends Mutex { /** * Initializes MySQL specific mutex component implementation. @@ -24,7 +24,7 @@ class Mutex extends \yii\mutex\db\Mutex { parent::init(); if ($this->db->driverName !== 'mysql') { - throw new InvalidConfigException(''); + throw new InvalidConfigException('In order to use MysqlMutex connection must be configured to use MySQL database.'); } } @@ -35,7 +35,7 @@ class Mutex extends \yii\mutex\db\Mutex * @return boolean acquiring result. * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock */ - protected function acquire($name, $timeout = 0) + protected function acquireLock($name, $timeout = 0) { return (boolean)$this->db ->createCommand('SELECT GET_LOCK(:name, :timeout)', array(':name' => $name, ':timeout' => $timeout)) @@ -48,25 +48,10 @@ class Mutex extends \yii\mutex\db\Mutex * @return boolean release result. * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock */ - protected function release($name) + protected function releaseLock($name) { return (boolean)$this->db ->createCommand('SELECT RELEASE_LOCK(:name)', array(':name' => $name)) ->queryScalar(); } - - /** - * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been - * already acquired by given name. - * @param string $name of the lock to be released. - * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature - * is not supported by concrete mutex implementation. - * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_is-free-lock - */ - protected function getIsAcquired($name) - { - return (boolean)$this->db - ->createCommand('SELECT IS_FREE_LOCK(:name)', array(':name' => $name)) - ->queryScalar(); - } } diff --git a/extensions/mutex/yii/mutex/cache/Mutex.php b/extensions/mutex/yii/mutex/cache/Mutex.php deleted file mode 100644 index 73e277bf13..0000000000 --- a/extensions/mutex/yii/mutex/cache/Mutex.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @since 2.0 - */ -class Mutex extends \yii\mutex\Mutex -{ - /** - * @var Cache|string the cache object or the application component ID of the cache object. - * The messages data will be cached using this cache object. Note, this property has meaning only - * in case [[cachingDuration]] set to non-zero value. - * After the Mutex object is created, if you want to change this property, you should only assign - * it with a cache object. - */ - public $cache = 'cache'; - - - /** - * Initializes the DbMessageSource component. Configured [[cache]] component will be initialized. - * @throws InvalidConfigException if [[cache]] is invalid. - */ - public function init() - { - parent::init(); - if (is_string($this->cache)) { - $this->cache = Yii::$app->getComponent($this->cache); - } - if (!$this->cache instanceof Cache) { - throw new InvalidConfigException('Mutex::cache must be either a cache object or the application component ID of the cache object.'); - } - } - - /** - * This method should be extended by concrete mutex implementations. Acquires lock by given name. - * @param string $name of the lock to be acquired. - * @param integer $timeout to wait for lock to become released. - * @return boolean acquiring result. - */ - protected function acquire($name, $timeout = 0) - { - - } - - /** - * This method should be extended by concrete mutex implementations. Releases lock by given name. - * @param string $name of the lock to be released. - * @return boolean release result. - */ - protected function release($name) - { - return $this->cache->delete("mutex.{$name}"); - } - - /** - * This method may optionally be extended by concrete mutex implementations. Checks whether lock has been - * already acquired by given name. - * @param string $name of the lock to be released. - * @return null|boolean whether lock has been already acquired. Returns `null` in case this feature - * is not supported by concrete mutex implementation. - */ - protected function getIsAcquired($name) - { - - } - - /** - * This method should be extended by concrete mutex implementations. Returns whether current mutex - * implementation can be used in a distributed environment. - * @return boolean whether current mutex implementation can be used in a distributed environment. - */ - public function getIsDistributed() - { - return $this->cache instanceof DbCache || $this->cache instanceof MemCache; - } -} From f6d0b4b2471e0f44cea59f8084d04c7bba9a4054 Mon Sep 17 00:00:00 2001 From: resurtm Date: Thu, 4 Jul 2013 21:01:06 +0600 Subject: [PATCH 11/11] Removed MSSQL mutex. --- extensions/mutex/yii/mutex/MssqlMutex.php | 56 ----------------------- 1 file changed, 56 deletions(-) delete mode 100644 extensions/mutex/yii/mutex/MssqlMutex.php diff --git a/extensions/mutex/yii/mutex/MssqlMutex.php b/extensions/mutex/yii/mutex/MssqlMutex.php deleted file mode 100644 index d267699d6c..0000000000 --- a/extensions/mutex/yii/mutex/MssqlMutex.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @since 2.0 - */ -class MssqlMutex extends Mutex -{ - /** - * Initializes Microsoft SQL Server specific mutex component implementation. - * @throws InvalidConfigException if [[db]] is not Microsoft SQL Server connection. - */ - public function init() - { - parent::init(); - $driverName = $this->db->driverName; - if ($driverName !== 'sqlsrv' && $driverName !== 'dblib' && $driverName !== 'mssql') { - throw new InvalidConfigException('In order to use MssqlMutex connection must be configured to use MS SQL Server database.'); - } - } - - /** - * This method should be extended by concrete mutex implementations. Acquires lock by given name. - * @param string $name of the lock to be acquired. - * @param integer $timeout to wait for lock to become released. - * @return boolean acquiring result. - * @throws \BadMethodCallException not implemented yet. - * @see http://msdn.microsoft.com/en-us/library/ms189823.aspx - */ - protected function acquireLock($name, $timeout = 0) - { - throw new \BadMethodCallException('Not implemented yet.'); - } - - /** - * This method should be extended by concrete mutex implementations. Releases lock by given name. - * @param string $name of the lock to be released. - * @return boolean release result. - * @throws \BadMethodCallException not implemented yet. - * @see http://msdn.microsoft.com/en-us/library/ms178602.aspx - */ - protected function releaseLock($name) - { - throw new \BadMethodCallException('Not implemented yet.'); - } -}