mirror of
https://github.com/moodle/moodle.git
synced 2025-03-22 00:20:37 +01:00
Merge branch 'MDL-61305-master' of https://github.com/sammarshallou/moodle
This commit is contained in:
commit
af5f446fa8
@ -54,6 +54,12 @@ if (!defined('MAX_MODINFO_CACHE_SIZE')) {
|
||||
* Is an array of grouping id => array of group id => group id. Includes grouping id 0 for 'all groups'
|
||||
*/
|
||||
class course_modinfo {
|
||||
/** @var int Maximum time the course cache building lock can be held */
|
||||
const COURSE_CACHE_LOCK_EXPIRY = 180;
|
||||
|
||||
/** @var int Time to wait for the course cache building lock before throwing an exception */
|
||||
const COURSE_CACHE_LOCK_WAIT = 60;
|
||||
|
||||
/**
|
||||
* List of fields from DB table 'course' that are cached in MUC and are always present in course_modinfo::$course
|
||||
* @var array
|
||||
@ -448,7 +454,17 @@ class course_modinfo {
|
||||
// Retrieve modinfo from cache. If not present or cacherev mismatches, call rebuild and retrieve again.
|
||||
$coursemodinfo = $cachecoursemodinfo->get($course->id);
|
||||
if ($coursemodinfo === false || ($course->cacherev != $coursemodinfo->cacherev)) {
|
||||
$coursemodinfo = self::build_course_cache($course);
|
||||
$lock = self::get_course_cache_lock($course->id);
|
||||
try {
|
||||
// Only actually do the build if it's still needed after getting the lock (not if
|
||||
// somebody else, who might have been holding the lock, built it already).
|
||||
$coursemodinfo = $cachecoursemodinfo->get($course->id);
|
||||
if ($coursemodinfo === false || ($course->cacherev != $coursemodinfo->cacherev)) {
|
||||
$coursemodinfo = self::inner_build_course_cache($course, $lock);
|
||||
}
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
|
||||
// Set initial values
|
||||
@ -577,6 +593,34 @@ class course_modinfo {
|
||||
return $compressedsections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a lock for rebuilding the cache of a single course.
|
||||
*
|
||||
* Caller must release the returned lock.
|
||||
*
|
||||
* This is used to ensure that the cache rebuild doesn't happen multiple times in parallel.
|
||||
* This function will wait up to 1 minute for the lock to be obtained. If the lock cannot
|
||||
* be obtained, it throws an exception.
|
||||
*
|
||||
* @param int $courseid Course id
|
||||
* @return \core\lock\lock Lock (must be released!)
|
||||
* @throws moodle_exception If the lock cannot be obtained
|
||||
*/
|
||||
protected static function get_course_cache_lock($courseid) {
|
||||
// Get database lock to ensure this doesn't happen multiple times in parallel. Wait a
|
||||
// reasonable time for the lock to be released, so we can give a suitable error message.
|
||||
// In case the system crashes while building the course cache, the lock will automatically
|
||||
// expire after a (slightly longer) period.
|
||||
$lockfactory = \core\lock\lock_config::get_lock_factory('core_modinfo');
|
||||
$lock = $lockfactory->get_lock('build_course_cache_' . $courseid,
|
||||
self::COURSE_CACHE_LOCK_WAIT, self::COURSE_CACHE_LOCK_EXPIRY);
|
||||
if (!$lock) {
|
||||
throw new moodle_exception('locktimeout', '', '', null,
|
||||
'core_modinfo/build_course_cache_' . $courseid);
|
||||
}
|
||||
return $lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and stores in MUC object containing information about course
|
||||
* modules and sections together with cached fields from table course.
|
||||
@ -589,11 +633,28 @@ class course_modinfo {
|
||||
* necessary fields it is re-requested from database)
|
||||
*/
|
||||
public static function build_course_cache($course) {
|
||||
global $DB, $CFG;
|
||||
require_once("$CFG->dirroot/course/lib.php");
|
||||
if (empty($course->id)) {
|
||||
throw new coding_exception('Object $course is missing required property \id\'');
|
||||
}
|
||||
|
||||
$lock = self::get_course_cache_lock($course->id);
|
||||
try {
|
||||
return self::inner_build_course_cache($course, $lock);
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to build course cache when there is already a lock obtained.
|
||||
*
|
||||
* @param stdClass $course object from DB table course
|
||||
* @param \core\lock\lock $lock Lock object - not actually used, just there to indicate you have a lock
|
||||
* @return stdClass Course object that has been stored in MUC
|
||||
*/
|
||||
protected static function inner_build_course_cache($course, \core\lock\lock $lock) {
|
||||
global $DB;
|
||||
|
||||
// Ensure object has all necessary fields.
|
||||
foreach (self::$cachedfields as $key) {
|
||||
if (!isset($course->$key)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user