From 7b938088b54a55943ad064c4829857bfd421e2ca Mon Sep 17 00:00:00 2001 From: Brendan Heywood Date: Tue, 27 Jul 2021 17:59:14 +1000 Subject: [PATCH] MDL-71014 core: Cache immutable bootstrap config locally --- lib/accesslib.php | 3 ++- lib/moodlelib.php | 17 ++++++----------- lib/setup.php | 17 +++++++++++++++-- lib/setuplib.php | 24 ++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/accesslib.php b/lib/accesslib.php index 2bedd6aa96f..a79f7bb005a 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -6291,7 +6291,8 @@ class context_system extends context { debugging('context_system::instance(): invalid $id parameter detected, should be 0'); } - if (defined('SYSCONTEXTID') and $cache) { // dangerous: define this in config.php to eliminate 1 query/page + // SYSCONTEXTID is cached in local cache to eliminate 1 query per page. + if (defined('SYSCONTEXTID') and $cache) { if (!isset(context::$systemcontext)) { $record = new stdClass(); $record->id = SYSCONTEXTID; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index bd3d2ef0fc0..47e4ef34b69 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -1457,8 +1457,6 @@ function set_config($name, $value, $plugin=null) { * * NOTE: this function is called from lib/db/upgrade.php * - * @static string|false $siteidentifier The site identifier is not cached. We use this static cache so - * that we need only fetch it once per request. * @param string $plugin full component name * @param string $name default null * @return mixed hash-like object or single value, return false no config found @@ -1467,8 +1465,6 @@ function set_config($name, $value, $plugin=null) { function get_config($plugin, $name = null) { global $CFG, $DB; - static $siteidentifier = null; - if ($plugin === 'moodle' || $plugin === 'core' || empty($plugin)) { $forced =& $CFG->config_php_settings; $iscore = true; @@ -1482,12 +1478,11 @@ function get_config($plugin, $name = null) { $iscore = false; } - if ($siteidentifier === null) { + if (!isset($CFG->siteidentifier)) { try { - // This may fail during installation. - // If you have a look at {@link initialise_cfg()} you will see that this is how we detect the need to - // install the database. - $siteidentifier = $DB->get_field('config', 'value', array('name' => 'siteidentifier')); + // This may throw an exception during installation, which is how we detect the + // need to install the database. For more details see {@see initialise_cfg()}. + $CFG->siteidentifier = $DB->get_field('config', 'value', array('name' => 'siteidentifier')); } catch (dml_exception $ex) { // Set siteidentifier to false. We don't want to trip this continually. $siteidentifier = false; @@ -1499,7 +1494,7 @@ function get_config($plugin, $name = null) { if (array_key_exists($name, $forced)) { return (string)$forced[$name]; } else if ($name === 'siteidentifier' && $plugin == 'core') { - return $siteidentifier; + return $CFG->siteidentifier; } } @@ -1524,7 +1519,7 @@ function get_config($plugin, $name = null) { } if ($plugin === 'core') { - $result['siteidentifier'] = $siteidentifier; + $result['siteidentifier'] = $CFG->siteidentifier; } foreach ($forced as $key => $value) { diff --git a/lib/setup.php b/lib/setup.php index b6f82c7f9bd..dc9d1970a4a 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -651,6 +651,17 @@ if (PHPUNIT_TEST and !PHPUNIT_UTIL) { unset($dbhash); } +// Load any immutable bootstrap config from local cache. +$bootstrapcachefile = $CFG->localcachedir . '/bootstrap.php'; +if (is_readable($bootstrapcachefile)) { + try { + require_once($bootstrapcachefile); + } catch (Throwable $e) { + // If it is corrupted then attempt to delete it and it will be rebuilt. + @unlink($bootstrapcachefile); + } +} + // Load up any configuration from the config table or MUC cache. if (PHPUNIT_TEST) { phpunit_util::initialise_cfg(); @@ -752,8 +763,7 @@ if (isset($_SERVER['PHP_SELF'])) { // initialise ME's - this must be done BEFORE starting of session! initialise_fullme(); -// define SYSCONTEXTID in config.php if you want to save some queries, -// after install it must match the system context record id. +// SYSCONTEXTID is cached in local cache to eliminate 1 query per page. if (!defined('SYSCONTEXTID')) { context_system::instance(); } @@ -1056,6 +1066,9 @@ if (false) { $PAGE = new moodle_page(); } +// Cache any immutable config locally to avoid constant DB lookups. +initialise_local_config_cache(); + // Allow plugins to callback as soon possible after setup.php is loaded. $pluginswithfunction = get_plugins_with_function('after_config', 'lib.php'); foreach ($pluginswithfunction as $plugins) { diff --git a/lib/setuplib.php b/lib/setuplib.php index 734cb4eec66..0a33f0941fb 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -795,6 +795,30 @@ function initialise_cfg() { } } +/** + * Cache any immutable config locally to avoid constant DB lookups. + * + * Only to be used only from lib/setup.php + */ +function initialise_local_config_cache() { + global $CFG; + + $bootstrapcachefile = $CFG->localcachedir . '/bootstrap.php'; + + if (!empty($CFG->siteidentifier) && !file_exists($bootstrapcachefile)) { + $contents = "siteidentifier = '" . addslashes($CFG->siteidentifier) . "'; +define('SYSCONTEXTID', ".SYSCONTEXTID."); +"; + + $temp = $bootstrapcachefile . '.tmp' . uniqid(); + file_put_contents($temp, $contents); + @chmod($temp, $CFG->filepermissions); + rename($temp, $bootstrapcachefile); + } +} + /** * Initialises $FULLME and friends. Private function. Should only be called from * setup.php.