diff --git a/extensions/mutex/Mutex.php b/extensions/mutex/Mutex.php new file mode 100644 index 0000000..876bc2b --- /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 0000000..2fae641 --- /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 0000000..0b67305 --- /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 0000000..07ab7e2 --- /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 0000000..3e3d530 --- /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; + } +}