Completed
Pull Request — master (#32)
by Guillaume
04:48
created

MySqlLock::releaseLock()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3.0026

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 24
ccs 14
cts 15
cp 0.9333
rs 8.9713
cc 3
eloc 15
nc 3
nop 1
crap 3.0026
1
<?php
2
/**
3
 * This file is part of ninja-mutex.
4
 *
5
 * (C) Kamil Dziedzic <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace NinjaMutex\Lock;
11
12
use PDO;
13
14
/**
15
 * Lock implementor using MySql
16
 *
17
 * @author Kamil Dziedzic <[email protected]>
18
 */
19
class MySqlLock extends LockAbstract
20
{
21
    /**
22
     * MySql connections
23
     *
24
     * @var PDO[]
25
     */
26
    protected $pdo = array();
27
28
    protected $user;
29
    protected $password;
30
    protected $host;
31
    protected $port;
32
    protected $classname;
33
    protected $ssl_ca_cert;
34
    protected $ssl_verify_server_cert = true;
35
36
    /**
37
     * Provide data for PDO connection
38
     *
39
     * @param string $user
40
     * @param string $password
41
     * @param string $host
42
     * @param int $port
43
     * @param string $classname class name to create as PDO connection
44
     * @param string $ssl_ca_cert Path to a file containing the SSL CA certificate(s), if you'd like to connect using SSL
45
     * @param bool $ssl_verify_server_cert Indicate if you want to verify that the server certificate is valid.
46
     */
47
    public function __construct($user, $password, $host, $port = 3306, $classname = 'PDO', $ssl_ca_cert = NULL, $ssl_verify_server_cert = true)
48
    {
49
        parent::__construct();
50
51
        $this->user = $user;
52
        $this->password = $password;
53
        $this->host = $host;
54
        $this->port = $port;
55
        $this->classname = $classname;
56
        $this->ssl_ca_cert = $ssl_ca_cert;
57
        $this->ssl_verify_server_cert = $ssl_verify_server_cert;
58
    }
59
60 5
    public function __clone()
61
    {
62 5
        parent::__clone();
63 5
        $this->pdo = array();
64 5
    }
65
66
    /**
67
     * Acquire lock
68
     *
69
     * @param  string   $name    name of lock
70
     * @param  null|int $timeout 1. null if you want blocking lock
71
     *                           2. 0 if you want just lock and go
72
     *                           3. $timeout > 0 if you want to wait for lock some time (in milliseconds)
73
     * @return bool
74
     */
75 16
    public function acquireLock($name, $timeout = null)
76
    {
77 16
        if (!$this->setupPDO($name)) {
78
            return false;
79
        }
80
81 16
        return parent::acquireLock($name, $timeout);
82
    }
83
84
    /**
85
     * @param  string $name
86
     * @param  bool   $blocking
87
     * @return bool
88
     */
89 16
    protected function getLock($name, $blocking)
90
    {
91 16
        return !$this->isLocked($name) && $this->pdo[$name]->query(
92 16
            sprintf(
93 16
                'SELECT GET_LOCK(%s, %d)',
94 16
                $this->pdo[$name]->quote($name),
95
                0
96 16
            ),
97 16
            PDO::FETCH_COLUMN,
98
            0
99 16
        )->fetch();
100
    }
101
102
    /**
103
     * Release lock
104
     *
105
     * @param  string $name name of lock
106
     * @return bool
107
     */
108 16
    public function releaseLock($name)
109
    {
110 16
        if (!$this->setupPDO($name)) {
111
            return false;
112
        }
113
114 16
        $released = (bool) $this->pdo[$name]->query(
115 16
            sprintf(
116 16
                'SELECT RELEASE_LOCK(%s)',
117 16
                $this->pdo[$name]->quote($name)
118 16
            ),
119 16
            PDO::FETCH_COLUMN,
120
            0
121 16
        )->fetch();
122
123 16
        if (!$released) {
124 2
            return false;
125
        }
126
127 16
        unset($this->pdo[$name]);
128 16
        unset($this->locks[$name]);
129
130 16
        return true;
131
    }
132
133
    /**
134
     * Check if lock is locked
135
     *
136
     * @param  string $name name of lock
137
     * @return bool
138
     */
139 16
    public function isLocked($name)
140
    {
141 16
        if (empty($this->pdo) && !$this->setupPDO($name)) {
142
            return false;
143
        }
144
145 16
        return !current($this->pdo)->query(
146 16
            sprintf(
147 16
                'SELECT IS_FREE_LOCK(%s)',
148 16
                current($this->pdo)->quote($name)
149 16
            ),
150 16
            PDO::FETCH_COLUMN,
151
            0
152 16
        )->fetch();
153
    }
154
155
    /**
156
     * @param  string $name
157
     * @return bool
158
     */
159 16
    protected function setupPDO($name)
160
    {
161 16
        if (isset($this->pdo[$name])) {
162 16
            return true;
163
        }
164
165 16
        $dsn = sprintf('mysql:host=%s;port=%d', $this->host, $this->port);
166 16
        $opts = array();
167 16
        if (!empty($this->ssl_ca_cert)) {
168
            if (file_exists($this->ssl_ca_cert)) {
169
                $opts[\PDO::MYSQL_ATTR_SSL_CA] = $this->ssl_ca_cert;
170
                if (!$this->ssl_verify_server_cert && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')) {
171
                    $opts[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
172
                }
173
            } else {
174
                error_log("Warning: specified SSL CA Certificate file doesn't exist.");
175
            }
176
        }
177 16
        $this->pdo[$name] = new $this->classname($dsn, $this->user, $this->password, $opts);
178
179 16
        return true;
180
    }
181
182 5
    public function __destruct()
183
    {
184 5
        parent::__destruct();
185
186 5
        foreach($this->pdo as $name => $pdo) {
187 3
            unset($this->pdo[$name]);
188 5
        }
189 5
    }
190
}
191