diff options
Diffstat (limited to 'phpBB/includes/lock/db.php')
-rw-r--r-- | phpBB/includes/lock/db.php | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/phpBB/includes/lock/db.php b/phpBB/includes/lock/db.php new file mode 100644 index 0000000000..20dbb63e0c --- /dev/null +++ b/phpBB/includes/lock/db.php @@ -0,0 +1,138 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Database locking class +* @package phpBB3 +*/ +class phpbb_lock_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 + */ + private $config; + + /** + * A database connection + * @var dbal + */ + 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 array $config The phpBB configuration + * @param dbal $db A database connection + */ + public function __construct($config_name, phpbb_config $config, dbal $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; + } + + /** + * 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 void + */ + public function release() + { + if ($this->locked) + { + $this->config->set_atomic($this->config_name, $this->unique_id, '0', false); + $this->locked = false; + } + } +} |