yii2

Форк
1
/
OracleMutex.php 
135 строк · 3.9 Кб
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7

8
namespace yii\mutex;
9

10
use PDO;
11
use yii\base\InvalidConfigException;
12

13
/**
14
 * OracleMutex implements mutex "lock" mechanism via Oracle locks.
15
 *
16
 * Application configuration example:
17
 *
18
 * ```
19
 * [
20
 *     'components' => [
21
 *         'db' => [
22
 *             'class' => 'yii\db\Connection',
23
 *             'dsn' => 'oci:dbname=LOCAL_XE',
24
 *              ...
25
 *         ]
26
 *         'mutex' => [
27
 *             'class' => 'yii\mutex\OracleMutex',
28
 *             'lockMode' => 'NL_MODE',
29
 *             'releaseOnCommit' => true,
30
 *              ...
31
 *         ],
32
 *     ],
33
 * ]
34
 * ```
35
 *
36
 * @see https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm#ARPLS021
37
 * @see Mutex
38
 *
39
 * @author Alexander Zlakomanov <zlakomanoff@gmail.com>
40
 * @since 2.0.10
41
 */
42
class OracleMutex extends DbMutex
43
{
44
    /** available lock modes */
45
    const MODE_X = 'X_MODE';
46
    const MODE_NL = 'NL_MODE';
47
    const MODE_S = 'S_MODE';
48
    const MODE_SX = 'SX_MODE';
49
    const MODE_SS = 'SS_MODE';
50
    const MODE_SSX = 'SSX_MODE';
51

52
    /**
53
     * @var string lock mode to be used.
54
     * @see https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm#ARPLS021#CHDBCFDI
55
     */
56
    public $lockMode = self::MODE_X;
57
    /**
58
     * @var bool whether to release lock on commit.
59
     */
60
    public $releaseOnCommit = false;
61

62

63
    /**
64
     * Initializes Oracle specific mutex component implementation.
65
     * @throws InvalidConfigException if [[db]] is not Oracle connection.
66
     */
67
    public function init()
68
    {
69
        parent::init();
70
        if (strncmp($this->db->driverName, 'oci', 3) !== 0 && strncmp($this->db->driverName, 'odbc', 4) !== 0) {
71
            throw new InvalidConfigException('In order to use OracleMutex connection must be configured to use Oracle database.');
72
        }
73
    }
74

75
    /**
76
     * Acquires lock by given name.
77
     * @see https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm#ARPLS021
78
     * @param string $name of the lock to be acquired.
79
     * @param int $timeout time (in seconds) to wait for lock to become released.
80
     * @return bool acquiring result.
81
     */
82
    protected function acquireLock($name, $timeout = 0)
83
    {
84
        $lockStatus = null;
85

86
        // clean vars before using
87
        $releaseOnCommit = $this->releaseOnCommit ? 'TRUE' : 'FALSE';
88
        $timeout = abs((int) $timeout);
89

90
        // inside pl/sql scopes pdo binding not working correctly :(
91
        $this->db->useMaster(function ($db) use ($name, $timeout, $releaseOnCommit, &$lockStatus) {
92
            /** @var \yii\db\Connection $db */
93
            $db->createCommand(
94
                'DECLARE
95
    handle VARCHAR2(128);
96
BEGIN
97
    DBMS_LOCK.ALLOCATE_UNIQUE(:name, handle);
98
    :lockStatus := DBMS_LOCK.REQUEST(handle, DBMS_LOCK.' . $this->lockMode . ', ' . $timeout . ', ' . $releaseOnCommit . ');
99
END;',
100
                [':name' => $name]
101
            )
102
            ->bindParam(':lockStatus', $lockStatus, PDO::PARAM_INT, 1)
103
            ->execute();
104
        });
105

106
        return $lockStatus === 0 || $lockStatus === '0';
107
    }
108

109
    /**
110
     * Releases lock by given name.
111
     * @param string $name of the lock to be released.
112
     * @return bool release result.
113
     * @see https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lock.htm#ARPLS021
114
     */
115
    protected function releaseLock($name)
116
    {
117
        $releaseStatus = null;
118
        $this->db->useMaster(function ($db) use ($name, &$releaseStatus) {
119
            /** @var \yii\db\Connection $db */
120
            $db->createCommand(
121
                'DECLARE
122
    handle VARCHAR2(128);
123
BEGIN
124
    DBMS_LOCK.ALLOCATE_UNIQUE(:name, handle);
125
    :result := DBMS_LOCK.RELEASE(handle);
126
END;',
127
                [':name' => $name]
128
            )
129
            ->bindParam(':result', $releaseStatus, PDO::PARAM_INT, 1)
130
            ->execute();
131
        });
132

133
        return $releaseStatus === 0 || $releaseStatus === '0';
134
    }
135
}
136

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.