Completed
Pull Request — master (#32)
by Guillaume
31:29 queued 25:35
created

MySqlLock::setupPDO()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.9102

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 19
ccs 8
cts 13
cp 0.6153
rs 9.2
cc 4
eloc 12
nc 4
nop 1
crap 4.9102
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
35
    /**
36
     * Provide data for PDO connection
37
     *
38
     * @param string $user
39
     * @param string $password
40
     * @param string $host
41
     * @param int $port
42
     * @param string $classname class name to create as PDO connection
43
     * @param string $ssl_ca_cert Path to a file containing the SSL CA certificate(s), if you'd like to connect using SSL
44
     */
45
    public function __construct($user, $password, $host, $port = 3306, $classname = 'PDO', $ssl_ca_cert = NULL)
46
    {
47
        parent::__construct();
48
49
        $this->user = $user;
50
        $this->password = $password;
51
        $this->host = $host;
52
        $this->port = $port;
53
        $this->classname = $classname;
54
        $this->ssl_ca_cert = $ssl_ca_cert;
55
    }
56
57 10
    public function __clone()
58
    {
59 10
        parent::__clone();
60 10
        $this->pdo = array();
61 10
    }
62
63
    /**
64
     * Acquire lock
65
     *
66
     * @param  string   $name    name of lock
67
     * @param  null|int $timeout 1. null if you want blocking lock
68
     *                           2. 0 if you want just lock and go
69
     *                           3. $timeout > 0 if you want to wait for lock some time (in milliseconds)
70
     * @return bool
71
     */
72 32
    public function acquireLock($name, $timeout = null)
73
    {
74 32
        if (!$this->setupPDO($name)) {
75
            return false;
76
        }
77
78 32
        return parent::acquireLock($name, $timeout);
79
    }
80
81
    /**
82
     * @param  string $name
83
     * @param  bool   $blocking
84
     * @return bool
85
     */
86 32
    protected function getLock($name, $blocking)
87
    {
88 32
        return !$this->isLocked($name) && $this->pdo[$name]->query(
89 32
            sprintf(
90 32
                'SELECT GET_LOCK("%s", %d)',
91 32
                $name,
92
                0
93 32
            ),
94 32
            PDO::FETCH_COLUMN,
95
            0
96 32
        )->fetch();
97
    }
98
99
    /**
100
     * Release lock
101
     *
102
     * @param  string $name name of lock
103
     * @return bool
104
     */
105 32
    public function releaseLock($name)
106
    {
107 32
        if (!$this->setupPDO($name)) {
108
            return false;
109
        }
110
111 32
        $released = (bool) $this->pdo[$name]->query(
112 32
            sprintf(
113 32
                'SELECT RELEASE_LOCK("%s")',
114
                $name
115 32
            ),
116 32
            PDO::FETCH_COLUMN,
117
            0
118 32
        )->fetch();
119
120 32
        if (!$released) {
121 4
            return false;
122
        }
123
124 32
        unset($this->pdo[$name]);
125 32
        unset($this->locks[$name]);
126
127 32
        return true;
128
    }
129
130
    /**
131
     * Check if lock is locked
132
     *
133
     * @param  string $name name of lock
134
     * @return bool
135
     */
136 32
    public function isLocked($name)
137
    {
138 32
        if (empty($this->pdo) && !$this->setupPDO($name)) {
139
            return false;
140
        }
141
142 32
        return !current($this->pdo)->query(
143 32
            sprintf(
144 32
                'SELECT IS_FREE_LOCK("%s")',
145
                $name
146 32
            ),
147 32
            PDO::FETCH_COLUMN,
148
            0
149 32
        )->fetch();
150
    }
151
152
    /**
153
     * @param  string $name
154
     * @return bool
155
     */
156 32
    protected function setupPDO($name)
157
    {
158 32
        if (isset($this->pdo[$name])) {
159 32
            return true;
160
        }
161
162 32
        $dsn = sprintf('mysql:host=%s;port=%d', $this->host, $this->port);
163 32
        $opts = array();
164 32
        if (!empty($this->ssl_ca_cert)) {
165
            if (file_exists($this->ssl_ca_cert)) {
166
                $opts[\PDO::MYSQL_ATTR_SSL_CA] = $this->ssl_ca_cert;
167
            } else {
168
                error_log("Warning: specified SSL CA Certificate file doesn't exist.");
169
            }
170
        }
171 32
        $this->pdo[$name] = new $this->classname($dsn, $this->user, $this->password, $opts);
172
173 32
        return true;
174
    }
175
176 10
    public function __destruct()
177
    {
178 10
        parent::__destruct();
179
180 10
        foreach($this->pdo as $name => $pdo) {
181 6
            unset($this->pdo[$name]);
182 10
        }
183 10
    }
184
}
185