Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
75.00% covered (warning)
75.00%
3 / 4
CRAP
96.55% covered (success)
96.55%
28 / 29
db
0.00% covered (danger)
0.00%
0 / 1
75.00% covered (warning)
75.00%
3 / 4
9
96.55% covered (success)
96.55%
28 / 29
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 acquire
0.00% covered (danger)
0.00%
0 / 1
5.00
94.44% covered (success)
94.44%
17 / 18
 owns_lock
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 release
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\lock;
/**
* Database locking class
*/
class db
{
    /**
    * Name of the config variable this lock uses
    * @var string
    */
    private $config_name;
    /**
    * Unique identifier for this lock.
    *
    * @var string
    */
    private $unique_id;
    /**
    * Stores the state of this lock
    * @var bool
    */
    private $locked;
    /**
    * The phpBB configuration
    * @var \phpbb\config\config
    */
    private $config;
    /**
    * A database connection
    * @var \phpbb\db\driver\driver_interface
    */
    private $db;
    /**
    * Creates a named released instance of the lock.
    *
    * You have to call acquire() to actually create the lock.
    *
    * @param    string                                $config_name    A config variable to be used for locking
    * @param    \phpbb\config\config                $config            The phpBB configuration
    * @param    \phpbb\db\driver\driver_interface    $db                A database connection
    */
    public function __construct($config_name, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
    {
        $this->config_name = $config_name;
        $this->config = $config;
        $this->db = $db;
    }
    /**
    * Tries to acquire the lock by updating
    * the configuration variable in the database.
    *
    * As a lock may only be held by one process at a time, lock
    * acquisition may fail if another process is holding the lock
    * or if another process obtained the lock but never released it.
    * Locks are forcibly released after a timeout of 1 hour.
    *
    * @return    bool            true if lock was acquired
    *                            false otherwise
    */
    public function acquire()
    {
        if ($this->locked)
        {
            return false;
        }
        if (!isset($this->config[$this->config_name]))
        {
            $this->config->set($this->config_name, '0', false);
        }
        $lock_value = $this->config[$this->config_name];
        // make sure lock cannot be acquired by multiple processes
        if ($lock_value)
        {
            // if the other process is running more than an hour already we have to assume it
            // aborted without cleaning the lock
            $time = explode(' ', $lock_value);
            $time = $time[0];
            if ($time + 3600 >= time())
            {
                return false;
            }
        }
        $this->unique_id = time() . ' ' . unique_id();
        // try to update the config value, if it was already modified by another
        // process we failed to acquire the lock.
        $this->locked = $this->config->set_atomic($this->config_name, $lock_value, $this->unique_id, false);
        return $this->locked;
    }
    /**
    * Does this process own the lock?
    *
    * @return    bool            true if lock is owned
    *                            false otherwise
    */
    public function owns_lock()
    {
        return (bool) $this->locked;
    }
    /**
    * Releases the lock.
    *
    * The lock must have been previously obtained, that is, acquire() call
    * was issued and returned true.
    *
    * Note: Attempting to release a lock that is already released,
    * that is, calling release() multiple times, is harmless.
    *
    * @return null
    */
    public function release()
    {
        if ($this->locked)
        {
            $this->config->set_atomic($this->config_name, $this->unique_id, '0', false);
            $this->locked = false;
        }
    }
}