aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb/lock
diff options
context:
space:
mode:
authorJoas Schilling <nickvergessen@gmx.de>2013-07-14 11:57:53 -0400
committerJoas Schilling <nickvergessen@gmx.de>2013-07-14 11:57:53 -0400
commitd7a85ebc245e76038b8ccd56524f045cc92a6c13 (patch)
tree66aa645c4d86636f0bce04a7125a7757a466b224 /phpBB/phpbb/lock
parentfa3cdb6bf2cfdca9c26168bd258752718bc8a43f (diff)
parentf6865dc33a8cedb7d21a64401ed80d2edbac36bd (diff)
downloadforums-d7a85ebc245e76038b8ccd56524f045cc92a6c13.tar
forums-d7a85ebc245e76038b8ccd56524f045cc92a6c13.tar.gz
forums-d7a85ebc245e76038b8ccd56524f045cc92a6c13.tar.bz2
forums-d7a85ebc245e76038b8ccd56524f045cc92a6c13.tar.xz
forums-d7a85ebc245e76038b8ccd56524f045cc92a6c13.zip
Merge remote-tracking branch 'igorw/ticket/11574' into ticket/11574
* igorw/ticket/11574: (575 commits) [ticket/11702] Fix forum_posts left over for link-click counts in viewforum.php [ticket/11696] Move file to new directory [ticket/11696] Rename constructor to __construct() [ticket/11696] Remove manual loading of db_tools in extension controller test [ticket/11696] Rename db_tools.php so it can be autoloaded [ticket/11698] Moving all autoloadable files to phpbb/ [ticket/11694] Do not locate assets with root path [ticket/11692] Don't update search_type in dev migration if already appended [ticket/11675] Fix template loop [ticket/11690] Old module class names may get autoloaded by class_exists [ticket/9649] Display information on index for moderators on unapproved posts [ticket/10999] Fix assets_version in ACP [prep-release-3.0.12] More changelog items for the 3.0.12 release. [ticket/11687] Add assets_version to phpbb_config [ticket/11686] Not checking for phpBB Debug errors on functional tests [ticket/11670] Consistency with logo: Replace "phpBB(tm)" with "phpBB(R)". [ticket/11674] Do not include vendor folder if there are no dependencies. [ticket/11685] Remove logout confirmation page [ticket/11684] Remove useless confirmation page after login and admin login [ticket/9657] Define user before injecting ...
Diffstat (limited to 'phpBB/phpbb/lock')
-rw-r--r--phpBB/phpbb/lock/db.php149
-rw-r--r--phpBB/phpbb/lock/flock.php144
2 files changed, 293 insertions, 0 deletions
diff --git a/phpBB/phpbb/lock/db.php b/phpBB/phpbb/lock/db.php
new file mode 100644
index 0000000000..5cc0821aa0
--- /dev/null
+++ b/phpBB/phpbb/lock/db.php
@@ -0,0 +1,149 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2010 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @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 phpbb_db_driver
+ */
+ 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 phpbb_db_driver $db A database connection
+ */
+ public function __construct($config_name, phpbb_config $config, phpbb_db_driver $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;
+ }
+ }
+}
diff --git a/phpBB/phpbb/lock/flock.php b/phpBB/phpbb/lock/flock.php
new file mode 100644
index 0000000000..17de0847c0
--- /dev/null
+++ b/phpBB/phpbb/lock/flock.php
@@ -0,0 +1,144 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* File locking class
+* @package phpBB3
+*/
+class phpbb_lock_flock
+{
+ /**
+ * Path to the file to which access is controlled
+ *
+ * @var string
+ */
+ private $path;
+
+ /**
+ * File pointer for the lock file
+ * @var string
+ */
+ private $lock_fp;
+
+ /**
+ * Constructor.
+ *
+ * You have to call acquire() to actually acquire the lock.
+ *
+ * @param string $path Path to the file to which access is controlled
+ */
+ public function __construct($path)
+ {
+ $this->path = $path;
+ $this->lock_fp = null;
+ }
+
+ /**
+ * Tries to acquire the lock.
+ *
+ * If the lock is already held by another process, this call will block
+ * until the other process releases the lock. If a lock is acquired and
+ * is not released before script finishes but the process continues to
+ * live (apache/fastcgi) then subsequent processes trying to acquire
+ * the same lock will be blocked forever.
+ *
+ * If the lock is already held by the same process via another instance
+ * of this class, this call will block forever.
+ *
+ * If flock function is disabled in php or fails to work, lock
+ * acquisition will fail and false will be returned.
+ *
+ * @return bool true if lock was acquired
+ * false otherwise
+ */
+ public function acquire()
+ {
+ if ($this->lock_fp)
+ {
+ return false;
+ }
+
+ // For systems that can't have two processes opening
+ // one file for writing simultaneously
+ if (file_exists($this->path . '.lock'))
+ {
+ $mode = 'rb';
+ }
+ else
+ {
+ $mode = 'wb';
+ }
+
+ $this->lock_fp = @fopen($this->path . '.lock', $mode);
+
+ if ($mode == 'wb')
+ {
+ if (!$this->lock_fp)
+ {
+ // Two processes may attempt to create lock file at the same time.
+ // Have the losing process try opening the lock file again for reading
+ // on the assumption that the winning process created it
+ $mode = 'rb';
+ $this->lock_fp = @fopen($this->path . '.lock', $mode);
+ }
+ else
+ {
+ // Only need to set mode when the lock file is written
+ @chmod($this->path . '.lock', 0666);
+ }
+ }
+
+ if ($this->lock_fp)
+ {
+ @flock($this->lock_fp, LOCK_EX);
+ }
+
+ return (bool) $this->lock_fp;
+ }
+
+ /**
+ * Does this process own the lock?
+ *
+ * @return bool true if lock is owned
+ * false otherwise
+ */
+ public function owns_lock()
+ {
+ return (bool) $this->lock_fp;
+ }
+
+ /**
+ * 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->lock_fp)
+ {
+ @flock($this->lock_fp, LOCK_UN);
+ fclose($this->lock_fp);
+ $this->lock_fp = null;
+ }
+ }
+}