From 5bc4c797a75e4f2cd09b671cad648736ee5d8671 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 12 Jul 2017 12:39:26 +0800 Subject: [PATCH] MDL-59506 core_lock: use a null lock during install Use a different lock factory during installation which does not actually lock at all. --- .../lock/installation_lock_factory.php | 127 ++++++++++++++++++ lib/classes/lock/lock_config.php | 4 +- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 lib/classes/lock/installation_lock_factory.php diff --git a/lib/classes/lock/installation_lock_factory.php b/lib/classes/lock/installation_lock_factory.php new file mode 100644 index 00000000000..5200cab858a --- /dev/null +++ b/lib/classes/lock/installation_lock_factory.php @@ -0,0 +1,127 @@ +. + +/** + * Lock factory for use during installation. + * + * @package core + * @category lock + * @copyright Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core\lock; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Lock factory for use during installation. + * + * @package core + * @category lock + * @copyright Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class installation_lock_factory implements lock_factory { + + /** + * Create this lock factory. + * + * @param string $type - The type, e.g. cron, cache, session + */ + public function __construct($type) { + } + + /** + * Return information about the blocking behaviour of the lock type on this platform. + * + * @return boolean - False if attempting to get a lock will block indefinitely. + */ + public function supports_timeout() { + return true; + } + + /** + * This lock type will be automatically released when a process ends. + * + * @return boolean - True + */ + public function supports_auto_release() { + return true; + } + + /** + * This lock factory is only available during the initial installation. + * To use it at any other time would be potentially dangerous. + * + * @return boolean + */ + public function is_available() { + return during_initial_install(); + } + + /** + * Multiple locks for the same resource cannot be held from a single process. + * + * @return boolean - False + */ + public function supports_recursion() { + return false; + } + + /** + * Get some info that might be useful for debugging. + * @return boolean - string + */ + protected function get_debug_info() { + return 'host:' . php_uname('n') . ', pid:' . getmypid() . ', time:' . time(); + } + + /** + * Get a lock within the specified timeout or return false. + * + * @param string $resource - The identifier for the lock. Should use frankenstyle prefix. + * @param int $timeout - The number of seconds to wait for a lock before giving up. + * @param int $maxlifetime - Unused by this lock type. + * @return boolean - true if a lock was obtained. + */ + public function get_lock($resource, $timeout, $maxlifetime = 86400) { + return new lock($resource, $this); + } + + /** + * Release a lock that was previously obtained with @lock. + * + * @param lock $lock - A lock obtained from this factory. + * @return boolean - true if the lock is no longer held (including if it was never held). + */ + public function release_lock(lock $lock) { + return true; + } + + /** + * Extend a lock that was previously obtained with @lock. + * + * @param lock $lock - not used + * @param int $maxlifetime - not used + * @return boolean - true if the lock was extended. + */ + public function extend_lock(lock $lock, $maxlifetime = 86400) { + // Not supported by this factory. + return false; + } + +} diff --git a/lib/classes/lock/lock_config.php b/lib/classes/lock/lock_config.php index 43541a65b8b..06fddf40386 100644 --- a/lib/classes/lock/lock_config.php +++ b/lib/classes/lock/lock_config.php @@ -48,7 +48,9 @@ class lock_config { global $CFG, $DB; $lockfactory = null; - if (isset($CFG->lock_factory) && $CFG->lock_factory != 'auto') { + if (during_initial_install()) { + $lockfactory = new \core\lock\installation_lock_factory($type); + } else if (isset($CFG->lock_factory) && $CFG->lock_factory != 'auto') { if (!class_exists($CFG->lock_factory)) { // In this case I guess it is not safe to continue. Different cluster nodes could end up using different locking // types because of an installation error.