~xibo-maintainers/xibo/tempel

« back to all changes in this revision

Viewing changes to lib/Storage/PdoStorageService.php

  • Committer: Dan Garner
  • Date: 2016-06-28 15:02:11 UTC
  • mto: This revision was merged to the branch mainline in revision 528.
  • Revision ID: git-v1:51031805c36c1d366fa330b2c2320d1927c57003
Fixes for upgrade steps

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
namespace Xibo\Storage;
23
23
 
24
 
use Xibo\Exception\DeadlockException;
25
24
use Xibo\Service\ConfigService;
26
25
use Xibo\Service\LogService;
27
26
 
33
32
class PdoStorageService implements StorageServiceInterface
34
33
{
35
34
    /**
36
 
     * @var \PDO[] The connection
 
35
     * @var \PDO The connection
37
36
     */
38
 
        private $conn = [];
39
 
 
40
 
    /** @var array Statistics */
41
 
    private static $stats = [];
 
37
        private $conn = NULL;
42
38
 
43
39
    /**
44
40
     * Logger
47
43
    private $log;
48
44
 
49
45
    /**
 
46
     * Count of Connections
 
47
     * @var int
 
48
     */
 
49
    private static $countConnections = 0;
 
50
 
 
51
    /**
 
52
     * Count of Selects
 
53
     * @var int
 
54
     */
 
55
    private static $countSelects = 0;
 
56
 
 
57
    /**
 
58
     * Count of Inserts
 
59
     * @var int
 
60
     */
 
61
    private static $countInserts = 0;
 
62
 
 
63
    /**
 
64
     * Count of Updates
 
65
     * @var int
 
66
     */
 
67
    private static $countUpdates = 0;
 
68
 
 
69
    /**
50
70
     * PDOConnect constructor.
51
71
     * @param LogService $logger
52
72
     */
55
75
        $this->log = $logger;
56
76
    }
57
77
 
58
 
    /** @inheritdoc */
59
 
    public function setConnection($name = 'default')
 
78
    /**
 
79
     * Set Connection
 
80
     * @return $this
 
81
     */
 
82
    public function setConnection()
60
83
    {
61
84
        // Create a new connection
62
 
        $this->conn[$name] = PdoStorageService::newConnection();
 
85
        $this->conn = PdoStorageService::newConnection();
63
86
        return $this;
64
87
    }
65
88
 
66
 
    /** @inheritdoc */
67
 
    public function close($name = null)
 
89
    /**
 
90
     * Closes the stored connection
 
91
     */
 
92
    public function close()
68
93
    {
69
 
        if ($name === null && isset($this->conn[$name])) {
70
 
            $this->conn[$name] = null;
71
 
            unset($this->conn[$name]);
72
 
        } else {
73
 
            $this->conn = [];
 
94
        if ($this->conn) {
 
95
            $this->conn = null;
74
96
        }
75
97
    }
76
98
 
110
132
 
111
133
                $conn->query("SET NAMES 'utf8'");
112
134
 
 
135
        self::$countConnections++;
 
136
 
113
137
                return $conn;
114
138
        }
115
139
 
123
147
     */
124
148
        public function connect($host, $user, $pass, $name = null)
125
149
    {
126
 
        if (!isset($this->conn['default']))
127
 
                    $this->close('default');
 
150
                if (!$this->conn) {
 
151
                        $this->close();
 
152
                }
128
153
 
129
154
        $dsn = PdoStorageService::createDsn($host, $name);
130
155
 
131
156
        // Open the connection and set the error mode
132
 
                $this->conn['default'] = new \PDO($dsn, $user, $pass);
133
 
                $this->conn['default']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
134
 
                $this->conn['default']->query("SET NAMES 'utf8'");
135
 
 
136
 
                return $this->conn['default'];
 
157
                $this->conn = new \PDO($dsn, $user, $pass);
 
158
                $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
 
159
 
 
160
                $this->conn->query("SET NAMES 'utf8'");
 
161
                
 
162
 
 
163
                return $this->conn;
137
164
        }
138
165
 
139
 
    /** @inheritdoc */
140
 
    public function getConnection($name = 'default')
 
166
    /**
 
167
     * Get the Raw Connection
 
168
     * @return \PDO
 
169
     */
 
170
    public function getConnection()
141
171
    {
142
 
        if (!isset($this->conn[$name]))
143
 
            $this->conn[$name] = PdoStorageService::newConnection();
144
 
 
145
 
        return $this->conn[$name];
 
172
        return $this->conn;
146
173
    }
147
174
 
148
175
    /**
156
183
        if ($this->log != null)
157
184
            $this->log->sql($sql, $params);
158
185
 
159
 
        $sth = $this->getConnection()->prepare($sql);
 
186
        $sth = $this->conn->prepare($sql);
160
187
        $sth->execute($params);
161
188
 
162
 
        $this->incrementStat('default', 'exists');
 
189
        self::$countSelects++;
163
190
 
164
191
        if ($sth->fetch())
165
192
            return true;
180
207
        if ($this->log != null)
181
208
            $this->log->sql($sql, $params);
182
209
 
183
 
        if (!$this->getConnection()->inTransaction())
184
 
            $this->getConnection()->beginTransaction();
 
210
        if (!$this->conn->inTransaction())
 
211
            $this->conn->beginTransaction();
185
212
 
186
 
        $sth = $this->getConnection()->prepare($sql);
 
213
        $sth = $this->conn->prepare($sql);
187
214
 
188
215
        $sth->execute($params);
189
216
 
190
 
        $this->incrementStat('default', 'insert');
 
217
        self::$countInserts++;
191
218
 
192
 
        return intval($this->getConnection()->lastInsertId());
 
219
        return intval($this->conn->lastInsertId());
193
220
    }
194
221
 
195
 
        /** @inheritdoc */
 
222
        /**
 
223
         * Run Update SQL
 
224
         * @param string $sql
 
225
         * @param array $params
 
226
     * @param \PDO[Optional] $dbh
 
227
         * @throws \PDOException
 
228
         */
196
229
        public function update($sql, $params)
197
230
        {
198
231
        if ($this->log != null)
199
232
            $this->log->sql($sql, $params);
200
233
 
201
 
        if (!$this->getConnection()->inTransaction())
202
 
            $this->getConnection()->beginTransaction();
 
234
        if (!$this->conn->inTransaction())
 
235
            $this->conn->beginTransaction();
203
236
 
204
 
        $sth = $this->getConnection()->prepare($sql);
 
237
        $sth = $this->conn->prepare($sql);
205
238
 
206
239
        $sth->execute($params);
207
240
 
208
 
        $this->incrementStat('default', 'update');
 
241
        self::$countUpdates++;
209
242
        }
210
243
 
211
244
        /**
220
253
        if ($this->log != null)
221
254
            $this->log->sql($sql, $params);
222
255
 
223
 
        $sth = $this->getConnection()->prepare($sql);
 
256
        $sth = $this->conn->prepare($sql);
224
257
 
225
258
        $sth->execute($params);
226
259
 
227
 
        $this->incrementStat('default', 'select');
 
260
        self::$countSelects++;
228
261
 
229
262
        return $sth->fetchAll(\PDO::FETCH_ASSOC);
230
263
        }
231
264
 
232
 
        /** @inheritdoc */
233
 
        public function isolated($sql, $params)
234
 
    {
235
 
        // Should we log?
236
 
        if ($this->log != null)
237
 
            $this->log->sql($sql, $params);
238
 
 
239
 
        $sth = $this->getConnection('isolated')->prepare($sql);
240
 
 
241
 
        $sth->execute($params);
242
 
 
243
 
        $this->incrementStat('isolated', 'update');
244
 
    }
245
 
 
246
 
    /** @inheritdoc */
247
 
    public function updateWithDeadlockLoop($sql, $params, $connection = null)
248
 
    {
249
 
        // Should we log?
250
 
        if ($this->log != null)
251
 
            $this->log->sql($sql, $params);
252
 
 
253
 
        if ($connection === null)
254
 
            $connection = 'isolated';
255
 
 
256
 
        // Prepare the statement
257
 
        $statement = $this->getConnection($connection)->prepare($sql);
258
 
 
259
 
        // Deadlock protect this statement
260
 
        $success = false;
261
 
        $retries = 2;
262
 
        do {
263
 
            try {
264
 
                $this->incrementStat($connection, 'update');
265
 
                $statement->execute($params);
266
 
                // Successful
267
 
                $success = true;
268
 
 
269
 
            } catch (\PDOException $PDOException) {
270
 
                $errorCode = isset($PDOException->errorInfo[1]) ? $PDOException->errorInfo[1] : $PDOException->getCode();
271
 
 
272
 
                if ($errorCode != 1213 && $errorCode != 1205)
273
 
                    throw $PDOException;
274
 
            }
275
 
 
276
 
            if ($success)
277
 
                break;
278
 
 
279
 
            // Sleep a bit, give the DB time to breathe
280
 
            $queryHash = substr($sql, 0, 15) . '... [' . md5($sql . json_encode($params)) . ']';
281
 
            $this->log->debug('Retrying query after a short nap, try: ' . (3 - $retries) . '. Query Hash: ' . $queryHash);
282
 
            usleep(10000);
283
 
 
284
 
        } while ($retries--);
285
 
 
286
 
        if (!$success)
287
 
            throw new DeadlockException(__('Failed to write to database after %d retries. Please try again later.', $retries));
288
 
    }
289
 
 
290
 
    /** @inheritdoc */
291
 
    public function commitIfNecessary($name = 'default')
292
 
    {
293
 
        if ($this->getConnection($name)->inTransaction()) {
294
 
            $this->incrementStat($name, 'commit');
295
 
            $this->getConnection()->commit();
296
 
        }
297
 
    }
298
 
 
299
265
    /**
 
266
     * Commit if necessary
 
267
     */
 
268
    public function commitIfNecessary()
 
269
    {
 
270
        if ($this->conn->inTransaction())
 
271
            $this->conn->commit();
 
272
    }
 
273
 
 
274
        /**
300
275
     * Set the TimeZone for this connection
301
 
     * @param string $timeZone e.g. -8:00
302
 
     * @param string $connection
303
 
     */
304
 
    public function setTimeZone($timeZone, $connection = 'default')
305
 
    {
306
 
        $this->getConnection($connection)->query('SET time_zone = \'' . $timeZone . '\';');
307
 
 
308
 
        $this->incrementStat($connection, 'utility');
 
276
         * @param \PDO $connection
 
277
         * @param string $timeZone e.g. -8:00
 
278
         */
 
279
        public function setTimeZone($timeZone, $connection = null)
 
280
        {
 
281
        if ($connection == null)
 
282
            $connection = $this->conn;
 
283
 
 
284
        $connection->query('SET time_zone = \'' . $timeZone . '\';');
 
285
 
 
286
        self::$countSelects++;
309
287
        }
310
288
 
311
289
    /**
312
290
     * PDO stats
313
291
     * @return array
314
292
     */
315
 
    public function stats()
316
 
    {
317
 
        return self::$stats;
318
 
    }
319
 
 
320
 
    /** @inheritdoc */
321
 
    public function incrementStat($connection, $key)
322
 
    {
323
 
        $currentCount = (isset(self::$stats[$connection][$key])) ? self::$stats[$connection][$key] : 0;
324
 
        self::$stats[$connection][$key] = $currentCount + 1;
325
 
    }
326
 
 
327
 
    /**
328
 
     * Statically increment stats
329
 
     * @param $connection
330
 
     * @param $key
331
 
     */
332
 
    public static function incrementStatStatic($connection, $key)
333
 
    {
334
 
        $currentCount = (isset(self::$stats[$connection][$key])) ? self::$stats[$connection][$key] : 0;
335
 
        self::$stats[$connection][$key] = $currentCount + 1;
 
293
    public static function stats()
 
294
    {
 
295
        return [
 
296
            'connections' => self::$countConnections,
 
297
            'selects' => self::$countSelects,
 
298
            'inserts' => self::$countInserts,
 
299
            'updates' => self::$countUpdates
 
300
        ];
336
301
    }
337
302
}
 
 
b'\\ No newline at end of file'