defined('MOODLE_INTERNAL') || die();
+// Cache for storing link encoders, so that we don't need to call
+// register_link_encoders each time backup_xml_transformer is constructed
+// TODO MDL-25290 replace global with MUC code.
+global $LINKS_ENCODERS_CACHE;
+
+$LINKS_ENCODERS_CACHE = array();
+
/**
* Class implementing the @xml_contenttrasnformed logic to be applied in moodle2 backups
*
* TODO: Finish phpdocs
*/
-
-// cache for storing link encoders, so that we don't need to call
-// register_link_encoders each time backup_xml_transformer is constructed
-global $LINKS_ENCODERS_CACHE;
-$LINKS_ENCODERS_CACHE = array();
-
class backup_xml_transformer extends xml_contenttransformer {
private $absolute_links_encoders; // array of static methods to be called in order to
private $unicoderegexp; // to know if the site supports unicode regexp
public function __construct($courseid) {
- global $LINKS_ENCODERS_CACHE;
-
$this->absolute_links_encoders = array();
$this->courseid = $courseid;
// Check if we support unicode modifiers in regular expressions
$this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false,
// if regexp libraries don't support unicode
// Register all the available content link encoders
- if (empty($LINKS_ENCODERS_CACHE)) {
- $LINKS_ENCODERS_CACHE = $this->register_link_encoders();
- }
- $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE;
+ $this->absolute_links_encoders = $this->register_link_encoders();
}
public function process($content) {
return $result;
}
+ /**
+ * Register all available content link encoders
+ *
+ * @return array encoder
+ * @todo MDL-25290 replace LINKS_ENCODERS_CACHE global with MUC code
+ */
private function register_link_encoders() {
+ global $LINKS_ENCODERS_CACHE;
+ // If encoder is linked, then return cached encoder.
+ if (!empty($LINKS_ENCODERS_CACHE)) {
+ return $LINKS_ENCODERS_CACHE;
+ }
+
$encoders = array();
// Add the course encoder
// Add local encodes
// TODO: Any interest? 1.9 never had that.
+ $LINKS_ENCODERS_CACHE = $encoders;
return $encoders;
}
}
* TODO: Finish phpdocs
*/
abstract class restore_dbops {
- static $BACKUP_IDS_CACHE = array();
- static $BACKUP_IDS_EXIST = array();
+ /**
+ * Keep cache of backup records.
+ * @var array
+ * @todo MDL-25290 static should be replaced with MUC code.
+ */
+ private static $backupidscache = array();
+ /**
+ * Keep track of backup ids which are cached.
+ * @var array
+ * @todo MDL-25290 static should be replaced with MUC code.
+ */
+ private static $backupidsexist = array();
+ /**
+ * Count is expensive, so manually keeping track of
+ * backupidscache, to avoid memory issues.
+ * @var int
+ * @todo MDL-25290 static should be replaced with MUC code.
+ */
+ private static $backupidscachesize = 2048;
+ /**
+ * Count is expensive, so manually keeping track of
+ * backupidsexist, to avoid memory issues.
+ * @var int
+ * @todo MDL-25290 static should be replaced with MUC code.
+ */
+ private static $backupidsexistsize = 10240;
+ /**
+ * Slice backupids cache to add more data.
+ * @var int
+ * @todo MDL-25290 static should be replaced with MUC code.
+ */
+ private static $backupidsslice = 512;
/**
* Return one array containing all the tasks that have been included
return $problems;
}
+ /**
+ * Return cached backup id's
+ *
+ * @param int $restoreid id of backup
+ * @param string $itemname name of the item
+ * @param int $itemid id of item
+ * @return array backup id's
+ * @todo MDL-25290 replace static backupids* with MUC code
+ */
protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) {
global $DB;
$key = "$itemid $itemname $restoreid";
- if (!isset(self::$BACKUP_IDS_EXIST[$key])) {
- return false;
+ // If record exists in cache then return.
+ if (isset(self::$backupidsexist[$key]) && isset(self::$backupidscache[$key])) {
+ // Return a copy of cached data, to avoid any alterations in cached data.
+ return clone self::$backupidscache[$key];
}
- if (isset(self::$BACKUP_IDS_CACHE[$key])) {
- return self::$BACKUP_IDS_CACHE[$key];
+ // Clean cache, if it's full.
+ if (self::$backupidscachesize <= 0) {
+ // Remove some records, to keep memory in limit.
+ self::$backupidscache = array_slice(self::$backupidscache, self::$backupidsslice, null, true);
+ self::$backupidscachesize = self::$backupidscachesize + self::$backupidsslice;
+ }
+ if (self::$backupidsexistsize <= 0) {
+ self::$backupidsexist = array_slice(self::$backupidsexist, self::$backupidsslice, null, true);
+ self::$backupidsexistsize = self::$backupidsexistsize + self::$backupidsslice;
}
+ // Retrive record from database.
$record = array(
'backupid' => $restoreid,
'itemname' => $itemname,
'itemid' => $itemid
);
-
- if (count(self::$BACKUP_IDS_CACHE) > 2048) {
- $BACKUP_IDS_CACHE = array();
+ if ($dbrec = $DB->get_record('backup_ids_temp', $record)) {
+ self::$backupidsexist[$key] = $dbrec->id;
+ self::$backupidscache[$key] = $dbrec;
+ self::$backupidscachesize--;
+ self::$backupidsexistsize--;
+ return $dbrec;
+ } else {
+ return false;
}
-
- return self::$BACKUP_IDS_CACHE[$key] = $DB->get_record('backup_ids_temp', $record);
}
+ /**
+ * Cache backup ids'
+ *
+ * @param int $restoreid id of backup
+ * @param string $itemname name of the item
+ * @param int $itemid id of item
+ * @param array $extrarecord extra record which needs to be updated
+ * @return void
+ * @todo MDL-25290 replace static BACKUP_IDS_* with MUC code
+ */
protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) {
global $DB;
$key = "$itemid $itemname $restoreid";
- if (!isset(self::$BACKUP_IDS_EXIST[$key])) {
- $record = array(
- 'backupid' => $restoreid,
- 'itemname' => $itemname,
- 'itemid' => $itemid,
- 'newitemid' => 0,
- 'parentitemid' => null,
- 'info' => null
- );
- $record = array_merge($record, $extrarecord);
- $record['id'] = $DB->insert_record_raw('backup_ids_temp', $record);
- self::$BACKUP_IDS_EXIST[$key] = $record['id'];
- if (count(self::$BACKUP_IDS_CACHE) < 2048) {
- // cache new records if we haven't got many yet
- self::$BACKUP_IDS_CACHE[$key] = (object) $record;
+ $record = array(
+ 'backupid' => $restoreid,
+ 'itemname' => $itemname,
+ 'itemid' => $itemid,
+ );
+
+ // If record is not cached then add one.
+ if (!isset(self::$backupidsexist[$key])) {
+ // If we have this record in db, then just update this.
+ if ($existingrecord = $DB->get_record('backup_ids_temp', $record)) {
+ self::$backupidsexist[$key] = $existingrecord->id;
+ self::$backupidsexistsize--;
+ self::update_backup_cached_record($record, $extrarecord, $key, $existingrecord);
+ } else {
+ // Add new record to cache and db.
+ $recorddefault = array (
+ 'newitemid' => 0,
+ 'parentitemid' => null,
+ 'info' => null);
+ $record = array_merge($record, $recorddefault, $extrarecord);
+ $record['id'] = $DB->insert_record('backup_ids_temp', $record);
+ self::$backupidsexist[$key] = $record['id'];
+ self::$backupidsexistsize--;
+ if (self::$backupidscachesize > 0) {
+ // Cache new records if we haven't got many yet.
+ self::$backupidscache[$key] = (object) $record;
+ self::$backupidscachesize--;
+ }
}
} else {
- if (!empty($extrarecord)) {
- $extrarecord['id'] = self::$BACKUP_IDS_EXIST[$key];
- $DB->update_record('backup_ids_temp', $extrarecord);
- if (isset(self::$BACKUP_IDS_CACHE[$key])) {
- $record = array_merge((array)self::$BACKUP_IDS_CACHE[$key], $extrarecord);
- self::$BACKUP_IDS_CACHE[$key] = (object) $record;
+ self::update_backup_cached_record($record, $extrarecord, $key);
+ }
+ }
+
+ /**
+ * Updates existing backup record
+ *
+ * @param array $record record which needs to be updated
+ * @param array $extrarecord extra record which needs to be updated
+ * @param string $key unique key which is used to identify cached record
+ * @param stdClass $existingrecord (optional) existing record
+ */
+ protected static function update_backup_cached_record($record, $extrarecord, $key, $existingrecord = null) {
+ global $DB;
+ // Update only if extrarecord is not empty.
+ if (!empty($extrarecord)) {
+ $extrarecord['id'] = self::$backupidsexist[$key];
+ $DB->update_record('backup_ids_temp', $extrarecord);
+ // Update existing cache or add new record to cache.
+ if (isset(self::$backupidscache[$key])) {
+ $record = array_merge((array)self::$backupidscache[$key], $extrarecord);
+ self::$backupidscache[$key] = (object) $record;
+ } else if (self::$backupidscachesize > 0) {
+ if ($existingrecord) {
+ self::$backupidscache[$key] = $existingrecord;
+ } else {
+ // Retrive record from database and cache updated records.
+ self::$backupidscache[$key] = $DB->get_record('backup_ids_temp', $record);
}
+ $record = array_merge((array)self::$backupidscache[$key], $extrarecord);
+ self::$backupidscache[$key] = (object) $record;
+ self::$backupidscachesize--;
}
}
}