Browse Source

Proposed mutex extension.

tags/2.0.0-beta
resurtm 12 years ago
parent
commit
7aef563dd5
  1. 76
      extensions/mutex/Mutex.php
  2. 29
      extensions/mutex/db/Mutex.php
  3. 28
      extensions/mutex/db/mssql/Mutex.php
  4. 38
      extensions/mutex/db/mysql/Mutex.php
  5. 59
      extensions/mutex/unix/Mutex.php

76
extensions/mutex/Mutex.php

@ -0,0 +1,76 @@
<?php
namespace yii\mutex;
use Yii;
use yii\base\Component;
abstract class Mutex extends Component
{
public $autoRelease = true;
private $_locks = array();
public function init()
{
if ($this->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();
}

29
extensions/mutex/db/Mutex.php

@ -0,0 +1,29 @@
<?php
namespace yii\mutex\db;
use Yii;
use yii\db\Connection;
use yii\base\InvalidConfigException;
abstract class Mutex extends \yii\mutex\Mutex
{
/**
* @var string|Connection
*/
public $db = 'db';
public function init()
{
parent::init();
$this->db = Yii::$app->getComponent($this->db);
if (!$this->db instanceof Connection) {
throw new InvalidConfigException('');
}
}
public function getIsDistributed()
{
return true;
}
}

28
extensions/mutex/db/mssql/Mutex.php

@ -0,0 +1,28 @@
<?php
namespace yii\mutex\db\mssql;
use Yii;
use yii\base\InvalidConfigException;
class Mutex extends \yii\mutex\db\Mutex
{
public function init()
{
parent::init();
$driverName = $this->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
}
}

38
extensions/mutex/db/mysql/Mutex.php

@ -0,0 +1,38 @@
<?php
namespace yii\mutex\db\mysql;
use Yii;
use yii\base\InvalidConfigException;
class Mutex extends \yii\mutex\db\Mutex
{
public function init()
{
parent::init();
if ($this->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();
}
}

59
extensions/mutex/unix/Mutex.php

@ -0,0 +1,59 @@
<?php
namespace yii\mutex\unix;
use Yii;
use yii\base\InvalidConfigException;
class Mutex extends \yii\mutex\Mutex
{
private $_files = array();
public function init()
{
// if (stripos(php_uname('s'), 'win') === 0) {
// throw new InvalidConfigException('');
// }
}
protected function acquire($name, $timeout = 0)
{
$file = fopen(Yii::$app->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;
}
}
Loading…
Cancel
Save