/**
  * @param array $updates Array of arrays each containing two keys, 'primaryKey'
  *  and 'changes'. primaryKey must contain a map of column names to values
  *  sufficient to uniquely identify the row changes must contain a map of column
  *  names to update values to apply to the row.
  */
 public function write(array $updates)
 {
     $this->db->begin();
     foreach ($updates as $update) {
         $this->db->update($this->table, $update['changes'], $update['primaryKey'], __METHOD__);
     }
     $this->db->commit();
     wfWaitForSlaves(false, false, $this->clusterName);
 }
示例#2
0
 /**
  * Do all the updates
  *
  * @param array $what what updates to perform
  */
 public function doUpdates($what = array('core', 'extensions', 'stats'))
 {
     global $wgVersion, $wgLocalisationCacheConf;
     $this->db->begin(__METHOD__);
     $what = array_flip($what);
     $this->skipSchema = isset($what['noschema']) || $this->fileHandle !== null;
     if (isset($what['core'])) {
         $this->runUpdates($this->getCoreUpdateList(), false);
     }
     if (isset($what['extensions'])) {
         $this->runUpdates($this->getOldGlobalUpdates(), false);
         $this->runUpdates($this->getExtensionUpdates(), true);
     }
     if (isset($what['stats'])) {
         $this->checkStats();
     }
     if (isset($what['purge'])) {
         $this->purgeCache();
         if ($wgLocalisationCacheConf['manualRecache']) {
             $this->rebuildLocalisationCache();
         }
     }
     $this->setAppliedUpdates($wgVersion, $this->updates);
     if ($this->fileHandle) {
         $this->skipSchema = false;
         $this->writeSchemaUpdateFile();
         $this->setAppliedUpdates("{$wgVersion}-schema", $this->updatesSkipped);
     }
     $this->db->commit(__METHOD__);
 }
 /**
  * Create database tables from scratch.
  *
  * @return Status
  */
 public function createTables()
 {
     $status = $this->getConnection();
     if (!$status->isOK()) {
         return $status;
     }
     $this->db->selectDB($this->getVar('wgDBname'));
     if ($this->db->tableExists('archive', __METHOD__)) {
         $status->warning('config-install-tables-exist');
         $this->enableLB();
         return $status;
     }
     $this->db->setFlag(DBO_DDLMODE);
     // For Oracle's handling of schema files
     $this->db->begin(__METHOD__);
     $error = $this->db->sourceFile($this->db->getSchemaPath());
     if ($error !== true) {
         $this->db->reportQueryError($error, 0, '', __METHOD__);
         $this->db->rollback(__METHOD__);
         $status->fatal('config-install-tables-failed', $error);
     } else {
         $this->db->commit(__METHOD__);
     }
     // Resume normal operations
     if ($status->isOk()) {
         $this->enableLB();
     }
     return $status;
 }
示例#4
0
 /**
  * Create the tables for each extension the user enabled
  * @return Status
  */
 public function createExtensionTables()
 {
     $status = $this->getConnection();
     if (!$status->isOK()) {
         return $status;
     }
     $updater = DatabaseUpdater::newForDB($this->db);
     $extensionUpdates = $updater->getNewExtensions();
     $ourExtensions = array_map('strtolower', $this->getVar('_Extensions'));
     foreach ($ourExtensions as $ext) {
         if (isset($extensionUpdates[$ext])) {
             $this->db->begin(__METHOD__);
             $error = $this->db->sourceFile($extensionUpdates[$ext]);
             if ($error !== true) {
                 $this->db->rollback(__METHOD__);
                 $status->warning('config-install-tables-failed', $error);
             } else {
                 $this->db->commit(__METHOD__);
             }
         }
     }
     // Now run updates to create tables for old extensions
     $updater->doUpdates(array('extensions'));
     return $status;
 }
示例#5
0
 /**
  * Merge page histories
  *
  * @param integer $id The page_id
  * @param Title $newTitle The new title
  */
 private function mergePage($row, Title $newTitle)
 {
     $id = $row->page_id;
     // Construct the WikiPage object we will need later, while the
     // page_id still exists. Note that this cannot use makeTitleSafe(),
     // we are deliberately constructing an invalid title.
     $sourceTitle = Title::makeTitle($row->page_namespace, $row->page_title);
     $sourceTitle->resetArticleID($id);
     $wikiPage = new WikiPage($sourceTitle);
     $wikiPage->loadPageData('fromdbmaster');
     $destId = $newTitle->getArticleId();
     $this->db->begin(__METHOD__);
     $this->db->update('revision', array('rev_page' => $destId), array('rev_page' => $id), __METHOD__);
     $this->db->delete('page', array('page_id' => $id), __METHOD__);
     /* Call LinksDeletionUpdate to delete outgoing links from the old title,
      * and update category counts.
      *
      * Calling external code with a fake broken Title is a fairly dubious
      * idea. It's necessary because it's quite a lot of code to duplicate,
      * but that also makes it fragile since it would be easy for someone to
      * accidentally introduce an assumption of title validity to the code we
      * are calling.
      */
     $update = new LinksDeletionUpdate($wikiPage);
     $update->doUpdate();
     $this->db->commit(__METHOD__);
     return true;
 }
 /**
  * Apply a SQL source file to the database as part of running an installation step.
  *
  * @param string $sourceFileMethod
  * @param string $stepName
  * @param string $archiveTableMustNotExist
  * @return Status
  */
 private function stepApplySourceFile($sourceFileMethod, $stepName, $archiveTableMustNotExist = false)
 {
     $status = $this->getConnection();
     if (!$status->isOK()) {
         return $status;
     }
     $this->db->selectDB($this->getVar('wgDBname'));
     if ($archiveTableMustNotExist && $this->db->tableExists('archive', __METHOD__)) {
         $status->warning("config-{$stepName}-tables-exist");
         $this->enableLB();
         return $status;
     }
     $this->db->setFlag(DBO_DDLMODE);
     // For Oracle's handling of schema files
     $this->db->begin(__METHOD__);
     $error = $this->db->sourceFile(call_user_func(array($this->db, $sourceFileMethod)));
     if ($error !== true) {
         $this->db->reportQueryError($error, 0, '', __METHOD__);
         $this->db->rollback(__METHOD__);
         $status->fatal("config-{$stepName}-tables-failed", $error);
     } else {
         $this->db->commit(__METHOD__);
     }
     // Resume normal operations
     if ($status->isOk()) {
         $this->enableLB();
     }
     return $status;
 }
 /**
  * Merge page histories
  *
  * @param integer $id The page_id
  * @param Title $newTitle The new title
  */
 private function mergePage($id, Title $newTitle)
 {
     $destId = $newTitle->getArticleId();
     $this->db->begin(__METHOD__);
     $this->db->update('revision', array('rev_page' => $destId), array('rev_page' => $id), __METHOD__);
     $this->db->delete('page', array('page_id' => $id), __METHOD__);
     // @fixme Need WikiPage::doDeleteUpdates() or similar to avoid orphan
     // rows in the links tables.
     $this->db->commit(__METHOD__);
     return true;
 }
 /**
  * Remove a batch of users
  *
  * @param DatabaseBase $dbw
  * @param int[] $batch list of user IDs to remove
  */
 private function removeBatch(DatabaseBase $dbw, array $batch)
 {
     $rows = 0;
     $dbw->begin(__METHOD__);
     // remove entries from user table
     $dbw->delete(self::USER_TABLE, ['user_id' => $batch], __METHOD__);
     $rows += $dbw->affectedRows();
     // remove entries from user_properties table
     $dbw->delete('user_properties', ['up_user' => $batch], __METHOD__);
     $rows += $dbw->affectedRows();
     $dbw->commit(__METHOD__);
     $this->info('Batch removed', ['batch' => count($batch), 'rows' => $rows]);
 }
示例#9
0
 /**
  * Perform a cleanup for a set of wikis
  *
  * @param DatabaseBase $db database handler
  * @param string $table name of table to clean up
  * @param string $wiki_id_column table column name to use when querying for wiki ID
  * @param Array $city_ids IDs of wikis to remove from the table
  */
 private function doTableCleanup(DatabaseBase $db, $table, array $city_ids, $wiki_id_column = 'wiki_id')
 {
     $start = microtime(true);
     $db->delete($table, [$wiki_id_column => $city_ids], __METHOD__);
     $rows = $db->affectedRows();
     // just in case MW decides to start a transaction automagically
     $db->commit(__METHOD__);
     Wikia\Logger\WikiaLogger::instance()->info(__METHOD__, ['table' => $table, 'cities' => join(', ', $city_ids), 'count' => count($city_ids), 'took' => round(microtime(true) - $start, 4), 'rows' => $rows]);
     $this->output(sprintf("%s: %s - removed %d rows\n", date('Y-m-d H:i:s'), $table, $rows));
     // throttle delete queries
     if ($rows > 0) {
         sleep(5);
     }
 }
 /**
  * Do all the updates
  *
  * @param $what Array: what updates to perform
  */
 public function doUpdates($what = array('core', 'extensions', 'stats'))
 {
     global $wgVersion;
     $this->db->begin(__METHOD__);
     $what = array_flip($what);
     if (isset($what['core'])) {
         $this->runUpdates($this->getCoreUpdateList(), false);
     }
     if (isset($what['extensions'])) {
         $this->runUpdates($this->getOldGlobalUpdates(), false);
         $this->runUpdates($this->getExtensionUpdates(), true);
     }
     $this->setAppliedUpdates($wgVersion, $this->updates);
     if (isset($what['stats'])) {
         $this->checkStats();
     }
     $this->db->commit(__METHOD__);
 }
示例#11
0
 /**
  * Do all the updates
  *
  * @param $what Array: what updates to perform
  */
 public function doUpdates($what = array('core', 'extensions', 'purge', 'stats'))
 {
     global $wgLocalisationCacheConf, $wgVersion;
     $this->db->begin(__METHOD__);
     $what = array_flip($what);
     if (isset($what['core'])) {
         $this->runUpdates($this->getCoreUpdateList(), false);
     }
     if (isset($what['extensions'])) {
         $this->runUpdates($this->getOldGlobalUpdates(), false);
         $this->runUpdates($this->getExtensionUpdates(), true);
     }
     $this->setAppliedUpdates($wgVersion, $this->updates);
     if (isset($what['stats'])) {
         $this->checkStats();
     }
     if (isset($what['purge'])) {
         $this->purgeCache();
         if ($wgLocalisationCacheConf['manualRecache']) {
             $this->rebuildLocalisationCache();
         }
     }
     $this->db->commit(__METHOD__);
 }
 public function finishWrite()
 {
     if ($this->readOnly) {
         return;
     }
     if ($this->batch) {
         $this->dbw->insert('l10n_cache', $this->batch, __METHOD__);
     }
     $this->dbw->commit(__METHOD__);
     $this->currentLang = null;
     $this->dbw = null;
     $this->batch = array();
     $this->writesDone = true;
 }
 public function finishWrite()
 {
     if ($this->readOnly) {
         return;
     } elseif (is_null($this->currentLang)) {
         throw new MWException(__CLASS__ . ': must call startWrite() before finishWrite()');
     }
     $this->dbw->begin(__METHOD__);
     try {
         $this->dbw->delete('l10n_cache', array('lc_lang' => $this->currentLang), __METHOD__);
         foreach (array_chunk($this->batch, 500) as $rows) {
             $this->dbw->insert('l10n_cache', $rows, __METHOD__);
         }
         $this->writesDone = true;
     } catch (DBQueryError $e) {
         if ($this->dbw->wasReadOnlyError()) {
             $this->readOnly = true;
             // just avoid site down time
         } else {
             throw $e;
         }
     }
     $this->dbw->commit(__METHOD__);
     $this->currentLang = null;
     $this->batch = array();
 }
 /**
  * Write (insert) the properties into the DB.
  *
  * @since 1.2
  *
  * @param Database $dbw
  *
  * @return boolean Success indicator
  */
 protected function writePropsToDB(DatabaseBase $dbw)
 {
     $success = true;
     if (array_key_exists('defaultOwnWorkLicence', $this->config) && array_key_exists('licensesOwnWork', $this->config) && !in_array($this->config['defaultOwnWorkLicence'], $this->config['licensesOwnWork'])) {
         $this->config['licensesOwnWork'][] = $this->config['defaultOwnWorkLicence'];
     }
     $dbw->begin();
     // TODO: it'd be better to serialize() arrays
     foreach ($this->config as $prop => $value) {
         $success &= $dbw->insert('uw_campaign_conf', array('cc_campaign_id' => $this->id, 'cc_property' => $prop, 'cc_value' => is_array($value) ? implode('|', $value) : $value), __METHOD__);
     }
     $dbw->commit();
     return $success;
 }
示例#15
0
 /**
  * This function should *not* be called outside of JobQueueDB
  *
  * @param DatabaseBase $dbw
  * @param array $jobs
  * @param int $flags
  * @param string $method
  * @return boolean
  * @throws type
  */
 public function doBatchPushInternal(DatabaseBase $dbw, array $jobs, $flags, $method)
 {
     if (!count($jobs)) {
         return true;
     }
     $rowSet = array();
     // (sha1 => job) map for jobs that are de-duplicated
     $rowList = array();
     // list of jobs for jobs that are are not de-duplicated
     foreach ($jobs as $job) {
         $row = $this->insertFields($job);
         if ($job->ignoreDuplicates()) {
             $rowSet[$row['job_sha1']] = $row;
         } else {
             $rowList[] = $row;
         }
     }
     if ($flags & self::QOS_ATOMIC) {
         $dbw->begin($method);
         // wrap all the job additions in one transaction
     }
     try {
         // Strip out any duplicate jobs that are already in the queue...
         if (count($rowSet)) {
             $res = $dbw->select('job', 'job_sha1', array('job_sha1' => array_keys($rowSet), 'job_token' => ''), $method);
             foreach ($res as $row) {
                 wfDebug("Job with hash '{$row->job_sha1}' is a duplicate.\n");
                 unset($rowSet[$row->job_sha1]);
                 // already enqueued
             }
         }
         // Build the full list of job rows to insert
         $rows = array_merge($rowList, array_values($rowSet));
         // Insert the job rows in chunks to avoid slave lag...
         foreach (array_chunk($rows, 50) as $rowBatch) {
             $dbw->insert('job', $rowBatch, $method);
         }
         JobQueue::incrStats('job-insert', $this->type, count($rows));
         JobQueue::incrStats('job-insert-duplicate', $this->type, count($rowSet) + count($rowList) - count($rows));
     } catch (DBError $e) {
         if ($flags & self::QOS_ATOMIC) {
             $dbw->rollback($method);
         }
         throw $e;
     }
     if ($flags & self::QOS_ATOMIC) {
         $dbw->commit($method);
     }
     $this->cache->set($this->getCacheKey('empty'), 'false', JobQueueDB::CACHE_TTL_LONG);
     return true;
 }
 protected function acceptRequest_rollback(DatabaseBase $dbw, $user_id, $acd_id)
 {
     $dbw->begin();
     # DELETE the user in case something caused a COMMIT already somewhere.
     if ($user_id) {
         $dbw->delete('user', array('user_id' => $user_id), __METHOD__);
         $dbw->delete('user_groups', array('ug_user' => $user_id), __METHOD__);
     }
     # DELETE the new account_credentials row likewise.
     if ($acd_id) {
         $dbw->delete('account_credentials', array('acd_id' => $acd_id), __METHOD__);
     }
     $dbw->commit();
 }
示例#17
0
 /**
  * @param array $updates Array of arrays each containing two keys, 'primaryKey' and 'changes'.
  *   primaryKey must contain a map of column names to values sufficient to uniquely identify the row
  *   changes must contain a map of column names to update values to apply to the row
  */
 public function write(array $updates)
 {
     $this->db->begin();
     foreach ($updates as $id => $update) {
         //echo "Updating: ";var_dump( $update['primaryKey'] );
         //echo "With values: ";var_dump( $update['changes'] );
         $this->db->update($this->table, $update['changes'], $update['primaryKey'], __METHOD__);
     }
     $this->db->commit();
     wfWaitForSlaves(false, false, $this->clusterName);
 }