Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

MDL-40893 backup: cache question answers for performance

To constrain memory we only cache a single question's answers.
A quiz must display this many answers, so it will not result
in undue memory pressure.

We now match on the full answer text rather than the first 255
characters.  This removes the risk of matching questions with the
same start.
  • Loading branch information...
commit 5821a7c5f121bbc6b7dfd09640b917bd41e99217 1 parent 14e8af6
mr-russ mr-russ authored

Showing 1 changed file with 24 additions and 18 deletions. Show diff stats Hide diff stats

  1. +24 18 backup/moodle2/restore_qtype_plugin.class.php
42 backup/moodle2/restore_qtype_plugin.class.php
@@ -35,6 +35,18 @@
35 35 */
36 36 abstract class restore_qtype_plugin extends restore_plugin {
37 37
  38 + /*
  39 + * A simple answer to id cache for a single questions answers.
  40 + * @var array
  41 + */
  42 + private $questionanswercache = array();
  43 +
  44 + /*
  45 + * The id of the current question in the questionanswercache.
  46 + * @var int
  47 + */
  48 + private $questionanswercacheid = null;
  49 +
38 50 /**
39 51 * Add to $paths the restore_path_elements needed
40 52 * to handle question_answers for a given question
@@ -147,38 +159,32 @@ public function process_question_answer($data) {
147 159
148 160 // The question existed, we need to map the existing question_answers
149 161 } else {
150   - // Look in question_answers by answertext matching
151   - $sql = 'SELECT id
152   - FROM {question_answers}
153   - WHERE question = ?
154   - AND ' . $DB->sql_compare_text('answer', 255) . ' = ' . $DB->sql_compare_text('?', 255);
155   - $params = array($newquestionid, $data->answertext);
156   - $newitemid = $DB->get_field_sql($sql, $params);
157   -
158   - // Not able to find the answer, let's try cleaning the answertext
159   - // of all the question answers in DB as slower fallback. MDL-30018.
160   - if (!$newitemid) {
  162 + // Have we cached the current question?
  163 + if ($this->questionanswercacheid !== $newquestionid) {
  164 + // The question changed, purge and start again!
  165 + $this->questionanswercache = array();
161 166 $params = array('question' => $newquestionid);
162 167 $answers = $DB->get_records('question_answers', $params, '', 'id, answer');
  168 + $this->questionanswercacheid = $newquestionid;
  169 + // Cache all cleaned answers for a simple text match.
163 170 foreach ($answers as $answer) {
164   - // Clean in the same way than {@link xml_writer::xml_safe_utf8()}.
  171 + // MDL-30018: Clean in the same way as {@link xml_writer::xml_safe_utf8()}.
165 172 $clean = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is','', $answer->answer); // Clean CTRL chars.
166 173 $clean = preg_replace("/\r\n|\r/", "\n", $clean); // Normalize line ending.
167   - if ($clean === $data->answertext) {
168   - $newitemid = $data->id;
169   - }
  174 + $this->questionanswercache[$clean] = $answer->id;
170 175 }
171 176 }
172 177
173   - // If we haven't found the newitemid, something has gone really wrong, question in DB
174   - // is missing answers, exception
175   - if (!$newitemid) {
  178 + if (!isset($this->questionanswercache[$data->answertext])) {
  179 + // If we haven't found the matching answer, something has gone really wrong, the question in the DB
  180 + // is missing answers, throw an exception.
176 181 $info = new stdClass();
177 182 $info->filequestionid = $oldquestionid;
178 183 $info->dbquestionid = $newquestionid;
179 184 $info->answer = $data->answertext;
180 185 throw new restore_step_exception('error_question_answers_missing_in_db', $info);
181 186 }
  187 + $newitemid = $this->questionanswercache[$data->answertext];
182 188 }
183 189 // Create mapping (we'll use this intensively when restoring question_states. And also answerfeedback files)
184 190 $this->set_mapping('question_answer', $oldid, $newitemid);

0 comments on commit 5821a7c

Please sign in to comment.
Something went wrong with that request. Please try again.