123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- <?php
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\mutex;
- use PDO;
- use yii\base\InvalidConfigException;
- /**
- * OracleMutex implements mutex "lock" mechanism via Oracle locks.
- *
- * Application configuration example:
- *
- * ```
- * [
- * 'components' => [
- * 'db' => [
- * 'class' => 'yii\db\Connection',
- * 'dsn' => 'oci:dbname=LOCAL_XE',
- * ...
- * ]
- * 'mutex' => [
- * 'class' => 'yii\mutex\OracleMutex',
- * 'lockMode' => 'NL_MODE',
- * 'releaseOnCommit' => true,
- * ...
- * ],
- * ],
- * ]
- * ```
- *
- * @see http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm
- * @see Mutex
- *
- * @author Alexander Zlakomanov <zlakomanoff@gmail.com>
- * @since 2.0.10
- */
- class OracleMutex extends DbMutex
- {
- /** available lock modes */
- const MODE_X = 'X_MODE';
- const MODE_NL = 'NL_MODE';
- const MODE_S = 'S_MODE';
- const MODE_SX = 'SX_MODE';
- const MODE_SS = 'SS_MODE';
- const MODE_SSX = 'SSX_MODE';
- /**
- * @var string lock mode to be used.
- * @see http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm#CHDBCFDI
- */
- public $lockMode = self::MODE_X;
- /**
- * @var bool whether to release lock on commit.
- */
- public $releaseOnCommit = false;
- /**
- * Initializes Oracle specific mutex component implementation.
- * @throws InvalidConfigException if [[db]] is not Oracle connection.
- */
- public function init()
- {
- parent::init();
- if (strncmp($this->db->driverName, 'oci', 3) !== 0 && strncmp($this->db->driverName, 'odbc', 4) !== 0) {
- throw new InvalidConfigException('In order to use OracleMutex connection must be configured to use Oracle database.');
- }
- }
- /**
- * Acquires lock by given name.
- * @see http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm
- * @param string $name of the lock to be acquired.
- * @param int $timeout time (in seconds) to wait for lock to become released.
- * @return bool acquiring result.
- */
- protected function acquireLock($name, $timeout = 0)
- {
- $lockStatus = null;
- // clean vars before using
- $releaseOnCommit = $this->releaseOnCommit ? 'TRUE' : 'FALSE';
- $timeout = abs((int) $timeout);
- // inside pl/sql scopes pdo binding not working correctly :(
- $this->db->useMaster(function ($db) use ($name, $timeout, $releaseOnCommit, &$lockStatus) {
- /** @var \yii\db\Connection $db */
- $db->createCommand(
- 'DECLARE
- handle VARCHAR2(128);
- BEGIN
- DBMS_LOCK.ALLOCATE_UNIQUE(:name, handle);
- :lockStatus := DBMS_LOCK.REQUEST(handle, DBMS_LOCK.' . $this->lockMode . ', ' . $timeout . ', ' . $releaseOnCommit . ');
- END;',
- [':name' => $name]
- )
- ->bindParam(':lockStatus', $lockStatus, PDO::PARAM_INT, 1)
- ->execute();
- });
- return $lockStatus === 0 || $lockStatus === '0';
- }
- /**
- * Releases lock by given name.
- * @param string $name of the lock to be released.
- * @return bool release result.
- * @see http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm
- */
- protected function releaseLock($name)
- {
- $releaseStatus = null;
- $this->db->useMaster(function ($db) use ($name, &$releaseStatus) {
- /** @var \yii\db\Connection $db */
- $db->createCommand(
- 'DECLARE
- handle VARCHAR2(128);
- BEGIN
- DBMS_LOCK.ALLOCATE_UNIQUE(:name, handle);
- :result := DBMS_LOCK.RELEASE(handle);
- END;',
- [':name' => $name]
- )
- ->bindParam(':result', $releaseStatus, PDO::PARAM_INT, 1)
- ->execute();
- });
- return $releaseStatus === 0 || $releaseStatus === '0';
- }
- }
|