diff --git a/extensions/mutex/Mutex.php b/extensions/mutex/Mutex.php index 876bc2b..5268d86 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 2fae641..17dd68a 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 0b67305..374100a 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 07ab7e2..7153d38 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 c95baa8..ca18a49 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;