/** * Static function that wipes document and words * @param int $id ID of document to wipe */ public function wipe_document($id) { global $DB; // Delete existing document and occurrences. $DB->delete_records($this->get_occurrences_table(), array('documentid' => $id)); $DB->delete_records($this->get_documents_table(), array('id' => $id)); // If the course is currently being transferred we should get rid of it // from the new table too. if (isset($this->courseid) && year_tables::currently_transferring_course($this->courseid)) { $course = get_course($this->courseid); $year = year_tables::get_year_for_course($course); $otherdoc = new local_ousearch_document(); $otherdoc->init_from_record($this); unset($otherdoc->id); if ($otherdoc->find('local_ousearch_docs_' . $year)) { $DB->delete_records($this->get_occurrences_table(), array('documentid' => $id)); $DB->delete_records($this->get_documents_table(), array('id' => $id)); } } }
/** * Does a chunk of work toward splitting the data into tables. * * @param bool $output If true, calls mtrace to display output * @param array $results Output array (number of documents moved per course) * @param int $chunksize Number of items to include in chunk (roughly) * @return bool True to stop processing for this cron, false to continue * @throws coding_exception If not currently doing the transfer */ public static function split_tables_chunk($output = true, $chunksize = self::SPLIT_TABLES_CHUNK_SIZE) { global $DB, $CFG; require_once $CFG->dirroot . '/local/ousearch/searchlib.php'; $enabled = get_config('local_ousearch', self::CONFIG_ENABLED); if ($enabled != self::ENABLED_TRANSFERRING) { throw new \coding_exception('Cannot call this except during transfer'); } // Get course being transferred and set up initial data. $transferringid = get_config('local_ousearch', self::CONFIG_TRANSFERRING_COURSE); $params = array(); if (!$transferringid) { // Do non-course stuff first. $where = 'courseid IS NULL'; $course = null; self::cron_log($output, ' [Non-course]'); $targetyear = self::NON_COURSE_YEAR; } else { $where = 'courseid = ?'; $params[] = $transferringid; $course = get_course($transferringid); self::cron_log($output, ' ' . $course->shortname); $targetyear = self::get_year_for_course($course); } // Work out table names. $targetdocs = 'local_ousearch_docs_' . $targetyear; $targetoccurs = 'local_ousearch_occurs_' . $targetyear; // Only get the records we haven't done yet. $doneupto = get_config('local_ousearch', self::CONFIG_TRANSFERRING_DONEUPTO); if ($doneupto) { $where .= ' AND timemodified > ?'; $params[] = $doneupto; } // Find all records that were added or modified since the last processed // time. Note we do not need to limit these results because it's a // recordset. $before = microtime(true); $transaction = $DB->start_delegated_transaction(); $rs = $DB->get_recordset_select('local_ousearch_documents', $where, $params, 'timemodified', '*'); self::cron_log($output, ' Select: ' . round(microtime(true) - $before, 1) . 's.'); $count = 0; $lasttime = 0; $complete = true; $updates = 0; $creates = 0; $before = microtime(true); foreach ($rs as $document) { // If we have already processed the requested amount, stop processing // as soon as the last time changes. (The reason to wait until then // is that we can record that we've done everything up until that // time, without missing anything.) if ($count >= $chunksize) { if ($document->timemodified != $lasttime) { $complete = false; break; } } // See if this document already exists. If so, delete and remake. $docobject = new \local_ousearch_document(); $docobject->init_from_record($document); unset($docobject->id); if ($docobject->find($targetdocs)) { $DB->delete_records($targetoccurs, array('documentid' => $docobject->id)); $DB->delete_records($targetdocs, array('id' => $docobject->id)); $updates++; } else { $creates++; } // Insert the document into the target table. $oldid = $document->id; unset($document->id); $newid = $DB->insert_record($targetdocs, $document); // Copy all the SQL occurrences from source table. $DB->execute('INSERT INTO {' . $targetoccurs . '} (wordid, documentid, score) SELECT wordid, ?, score FROM {local_ousearch_occurrences} WHERE documentid = ?', array($newid, $oldid)); $lasttime = $document->timemodified; $count++; } $rs->close(); self::cron_log($output, ' Copy: ' . $creates . ' creates, ' . $updates . ' updates, ' . round(microtime(true) - $before, 1) . 's.'); if ($complete) { // After completing a course, add it to the course years list. if ($course) { $DB->insert_record('local_ousearch_courseyears', array('courseid' => $course->id, 'year' => $targetyear)); } // Look for the next course. $nextparams = array(); if (!$transferringid) { $where = ''; } else { $where = 'WHERE id > ?'; $nextparams[] = $transferringid; } $nextcourseid = $DB->get_field_sql("SELECT MIN(id) FROM {course} {$where}", $nextparams, IGNORE_MISSING); if ($nextcourseid) { // Move to next course. unset_config(self::CONFIG_TRANSFERRING_DONEUPTO, 'local_ousearch'); set_config(self::CONFIG_TRANSFERRING_COURSE, $nextcourseid, 'local_ousearch'); $transaction->allow_commit(); self::cron_log($output, ' Complete, moving to next course.', true); return false; } else { // Finished all courses! unset_config(self::CONFIG_TRANSFERRING_DONEUPTO, 'local_ousearch'); unset_config(self::CONFIG_TRANSFERRING_COURSE, 'local_ousearch'); set_config(self::CONFIG_ENABLED, self::ENABLED_ON, 'local_ousearch'); $transaction->allow_commit(); // Delete all records from old tables. Doing this outside the // transaction allows it to use TRUNCATE to speed this up. $before = microtime(true); $DB->delete_records('local_ousearch_documents'); $DB->delete_records('local_ousearch_occurrences'); self::cron_log($output, ' All courses complete, tables deleted: ' . round(microtime(true) - $before, 1) . 's.', true); return true; } } else { // If not complete, update the time processed up to. set_config(self::CONFIG_TRANSFERRING_DONEUPTO, $lasttime, 'local_ousearch'); $transaction->allow_commit(); self::cron_log($output, ' Continuing...', true); return false; } }