/** * Open a connection to the master server with the admin rights. * @return Database * @access private */ function newConnection() { $lb = wfGetLBFactory()->newMainLB(); $db = $lb->getConnection(DB_MASTER); $this->loadBalancers[] = $lb; return $db; }
public function process() { // Erweiterung der Elternfunktion process() $post = $this->request->data('post'); $get = $this->request->data('get'); unset($get['title']); // dirty MediaWiki fix: /wiki/foo -> /w/index.php?title=foo if (isset($get['allowed_filetarpathes'])) { $this->echoJson(self::$allowed_filetarpathes); exit; } if (!empty($this->request->file())) { $this->handleChunk(); if (isset($this->returnData)) { $this->echoJson($this->returnData); } // Fehlermeldung "Uncommitted DB writes": MediaWiki mag es wahrscheinlich nicht, // wenn man exit() aufruft. vgl. http://stackoverflow.com/a/22695318 $lb = wfGetLBFactory(); $lb->shutdown(); exit; # prevent MediaWiki to output something } elseif (!empty($get)) { $this->handleTestChunk(); if (isset($this->returnData)) { $this->echoJson($this->returnData); } exit; # prevent MediaWiki to output something } $this->pruneChunks(true); # [true=always|false=random base]. Other option is to implement a cron script }
/** * @return \LoadBalancer */ public function getLB() { if ($this->cluster !== false) { return wfGetLBFactory()->getExternalLB($this->cluster, $this->wiki); } else { return wfGetLB($this->wiki); } }
/** * @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(); wfGetLBFactory()->waitForReplication(); }
/** * Wrapper function for wfGetDB * * @param $db int Index of the connection to get * @param $groups mixed Query groups. * @param $wiki string|bool The wiki ID, or false for the current wiki * @return DatabaseBase */ public static function getDB($db, $groups = array(), $wiki = false) { global $wgEchoCluster; // Use the external db defined for Echo if ($wgEchoCluster) { $lb = wfGetLBFactory()->getExternalLB($wgEchoCluster, $wiki); } else { $lb = wfGetLB($wiki); } return $lb->getConnection($db, $groups, $wiki); }
function run() { if (!empty($this->params['mainDbMasterPos'])) { wfGetLB()->waitFor($this->params['mainDbMasterPos']); } if (!empty($this->params['echoDbMasterPos'])) { global $wgEchoCluster; wfGetLBFactory()->getExternalLB($wgEchoCluster)->waitFor($this->params['echoDbMasterPos']); } EchoNotificationController::notify($this->event, false); return true; }
public function execute() { wfProfileIn(__METHOD__); //run the download: Http::doSessionIdDownload($this->getOption('sid'), $this->getOption('usk')); // close up shop: // Execute any deferred updates wfDoUpdates(); // Log what the user did, for book-keeping purposes. wfLogProfilingData(); // Shut down the database before exit wfGetLBFactory()->shutdown(); wfProfileOut(__METHOD__); }
function getOpenIDStore( $storeType, $prefix, $options ) { global $wgOut, $wgMemc, $wgDBtype; switch ( $storeType ) { case 'file': # Auto-create path if it doesn't exist if ( !is_dir( $options['path'] ) ) { if ( !mkdir( $options['path'], 0770, true ) ) { $wgOut->showErrorPage( 'openidconfigerror', 'openidconfigerrortext' ); return null; } } return new Auth_OpenID_FileStore( $options['path'] ); case 'db': if ( $wgDBtype == 'sqlite' ) { $db = new MediaWikiOpenIDDatabaseConnection( wfGetDB( DB_MASTER ) ); require_once( 'Auth/OpenID/SQLiteStore.php' ); return new Auth_OpenID_SQLiteStore( $db ); } else { $lb = wfGetLBFactory()->newMainLB(); $db = new MediaWikiOpenIDDatabaseConnection( $lb->getConnection( DB_MASTER ) ); switch( $wgDBtype ) { case 'mysql': require_once( 'Auth/OpenID/MySQLStore.php' ); return new Auth_OpenID_MySQLStore( $db ); case 'postgres': require_once( 'Auth/OpenID/PostgreSQLStore.php' ); return new Auth_OpenID_PostgreSQLStore( $db ); default: $wgOut->showErrorPage( 'openidconfigerror', 'openidconfigerrortext' ); return null; } } case 'memcached': return new MediaWikiOpenIDMemcachedStore( $wgMemc ); default: $wgOut->showErrorPage( 'openidconfigerror', 'openidconfigerrortext' ); } }
/** * @return DatabaseBase */ protected function getDB() { if (!isset($this->db)) { # If server connection info was given, use that if ($this->serverInfo) { $this->lb = new LoadBalancer(array('servers' => array($this->serverInfo))); $this->db = $this->lb->getConnection(DB_MASTER); $this->db->clearFlag(DBO_TRX); } else { # We must keep a separate connection to MySQL in order to avoid deadlocks # However, SQLite has an opposite behaviour. # @todo Investigate behaviour for other databases if (wfGetDB(DB_MASTER)->getType() == 'sqlite') { $this->db = wfGetDB(DB_MASTER); } else { $this->lb = wfGetLBFactory()->newMainLB(); $this->db = $this->lb->getConnection(DB_MASTER); $this->db->clearFlag(DBO_TRX); } } } return $this->db; }
public function testDoUpdatesCLI() { $this->setMwGlobals('wgCommandLineMode', true); $updates = ['1' => "deferred update 1;\n", '2' => "deferred update 2;\n", '2-1' => "deferred update 1 within deferred update 2;\n", '2-2' => "deferred update 2 within deferred update 2;\n", '3' => "deferred update 3;\n", '3-1' => "deferred update 1 within deferred update 3;\n", '3-2' => "deferred update 2 within deferred update 3;\n", '3-1-1' => "deferred update 1 within deferred update 1 within deferred update 3;\n", '3-2-1' => "deferred update 1 within deferred update 2 with deferred update 3;\n"]; wfGetLBFactory()->commitMasterChanges(__METHOD__); // clear anything DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['1']; }); DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['2']; DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['2-1']; }); DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['2-2']; }); }); DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['3']; DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['3-1']; DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['3-1-1']; }); }); DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['3-2']; DeferredUpdates::addCallableUpdate(function () use($updates) { echo $updates['3-2-1']; }); }); }); $this->expectOutputString(implode('', $updates)); DeferredUpdates::doUpdates(); }
public function execute() { $wiki = $this->getOption('wikidb') ?: false; // Get the appropriate load balancer (for this wiki) if ($this->hasOption('cluster')) { $lb = wfGetLBFactory()->getExternalLB($this->getOption('cluster'), $wiki); } else { $lb = wfGetLB($wiki); } // Figure out which server to use if ($this->hasOption('slave')) { $server = $this->getOption('slave'); if ($server === 'any') { $index = DB_SLAVE; } else { $index = null; for ($i = 0; $i < $lb->getServerCount(); ++$i) { if ($lb->getServerName($i) === $server) { $index = $i; break; } } if ($index === null) { $this->error("No slave server configured with the name '{$server}'.", 1); } } } else { $index = DB_MASTER; } // Get a DB handle (with this wiki's DB selected) from the appropriate load balancer $db = $lb->getConnection($index, array(), $wiki); if ($this->hasOption('slave') && $db->getLBInfo('master') !== null) { $this->error("The server selected ({$db->getServer()}) is not a slave.", 1); } if ($this->hasArg(0)) { $file = fopen($this->getArg(0), 'r'); if (!$file) { $this->error("Unable to open input file", true); } $error = $db->sourceStream($file, false, array($this, 'sqlPrintResult')); if ($error !== true) { $this->error($error, true); } else { exit(0); } } $useReadline = function_exists('readline_add_history') && Maintenance::posix_isatty(0); if ($useReadline) { global $IP; $historyFile = isset($_ENV['HOME']) ? "{$_ENV['HOME']}/.mwsql_history" : "{$IP}/maintenance/.mwsql_history"; readline_read_history($historyFile); } $wholeLine = ''; $newPrompt = '> '; $prompt = $newPrompt; while (($line = Maintenance::readconsole($prompt)) !== false) { if (!$line) { # User simply pressed return key continue; } $done = $db->streamStatementEnd($wholeLine, $line); $wholeLine .= $line; if (!$done) { $wholeLine .= ' '; $prompt = ' -> '; continue; } if ($useReadline) { # Delimiter is eated by streamStatementEnd, we add it # up in the history (bug 37020) readline_add_history($wholeLine . $db->getDelimiter()); readline_write_history($historyFile); } try { $res = $db->query($wholeLine); $this->sqlPrintResult($res, $db); $prompt = $newPrompt; $wholeLine = ''; } catch (DBQueryError $e) { $doDie = !Maintenance::posix_isatty(0); $this->error($e, $doDie); } } wfWaitForSlaves(); }
/** * Ends this task peacefully */ public function restInPeace() { // Do any deferred jobs DeferredUpdates::doUpdates('commit'); // Execute a job from the queue $this->doJobs(); // Log profiling data, e.g. in the database or UDP wfLogProfilingData(); // Commit and close up! $factory = wfGetLBFactory(); $factory->commitMasterChanges(); $factory->shutdown(); wfDebug("Request ended normally\n"); }
/** * setWFVariables * * add all default variables into city_variables table * * @author Krzysztof Krzyzaniak <*****@*****.**> * @author Piotr Molski <*****@*****.**> * @access private * */ private function setWFVariables() { // WF Variables containter $this->mWFSettingVars = array(); $this->mWFSettingVars['wgSitename'] = $this->mNewWiki->sitename; $this->mWFSettingVars['wgLogo'] = self::DEFAULT_WIKI_LOGO; $this->mWFSettingVars['wgUploadPath'] = $this->mNewWiki->images_url; $this->mWFSettingVars['wgUploadDirectory'] = $this->mNewWiki->images_dir; $this->mWFSettingVars['wgDBname'] = $this->mNewWiki->dbname; $this->mWFSettingVars['wgLocalInterwiki'] = $this->mNewWiki->sitename; $this->mWFSettingVars['wgLanguageCode'] = $this->mNewWiki->language; $this->mWFSettingVars['wgServer'] = rtrim($this->mNewWiki->url, "/"); $this->mWFSettingVars['wgEnableSectionEdit'] = true; $this->mWFSettingVars['wgEnableSwiftFileBackend'] = true; $this->mWFSettingVars['wgOasisLoadCommonCSS'] = true; if ($this->getInitialNjordExtValue()) { $this->mWFSettingVars['wgEnableNjordExt'] = true; } // rt#60223: colon allowed in sitename, breaks project namespace if (mb_strpos($this->mWFSettingVars['wgSitename'], ':') !== false) { $this->mWFSettingVars['wgMetaNamespace'] = str_replace(array(':', ' '), array('', '_'), $this->mWFSettingVars['wgSitename']); } if (self::ACTIVE_CLUSTER) { wfGetLBFactory()->sectionsByDB[$this->mNewWiki->dbname] = $this->mWFSettingVars['wgDBcluster'] = self::ACTIVE_CLUSTER; } $oRes = $this->mDBw->select("city_variables_pool", array("cv_id, cv_name"), array("cv_name in ('" . implode("', '", array_keys($this->mWFSettingVars)) . "')"), __METHOD__); $this->mWFVars = array(); while ($oRow = $this->mDBw->fetchObject($oRes)) { $this->mWFVars[$oRow->cv_name] = $oRow->cv_id; } $this->mDBw->freeResult($oRes); foreach ($this->mWFSettingVars as $variable => $value) { /** * first, get id of variable */ $cv_id = 0; if (isset($this->mWFVars[$variable])) { $cv_id = $this->mWFVars[$variable]; } /** * then, insert value for wikia */ if (!empty($cv_id)) { $this->mDBw->insert("city_variables", array("cv_value" => serialize($value), "cv_city_id" => $this->mNewWiki->city_id, "cv_variable_id" => $cv_id), __METHOD__); } } }
/** * If there are any open database transactions, roll them back and log * the stack trace of the exception that should have been caught so the * transaction could be aborted properly. * * @since 1.23 * @param Exception|Throwable $e */ public static function rollbackMasterChangesAndLog($e) { $factory = wfGetLBFactory(); if ($factory->hasMasterChanges()) { $logger = LoggerFactory::getInstance('Bug56269'); $logger->warning('Exception thrown with an uncommited database transaction: ' . self::getLogMessage($e), self::getLogContext($e)); $factory->rollbackMasterChanges(__METHOD__); } }
/** * If there are any open database transactions, roll them back and log * the stack trace of the exception that should have been caught so the * transaction could be aborted properly. * * @since 1.23 * @param Exception $e */ public static function rollbackMasterChangesAndLog(Exception $e) { $factory = wfGetLBFactory(); if ($factory->hasMasterChanges()) { wfDebugLog('Bug56269', 'Exception thrown with an uncommited database transaction: ' . MWExceptionHandler::getLogMessage($e) . "\n" . $e->getTraceAsString()); $factory->rollbackMasterChanges(); } }
public function execute() { // Get a DB handle (with this wiki's DB select) from the appropriate load balancer if ($this->hasOption('cluster')) { $lb = wfGetLBFactory()->getExternalLB($this->getOption('cluster')); $dbw = $lb->getConnection(DB_MASTER); // master for external LB } else { $dbw = wfGetDB(DB_MASTER); // master for primary LB for this wiki } if ($this->hasArg(0)) { $file = fopen($this->getArg(0), 'r'); if (!$file) { $this->error("Unable to open input file", true); } $error = $dbw->sourceStream($file, false, array($this, 'sqlPrintResult')); if ($error !== true) { $this->error($error, true); } else { exit(0); } } $useReadline = function_exists('readline_add_history') && Maintenance::posix_isatty(0); if ($useReadline) { global $IP; $historyFile = isset($_ENV['HOME']) ? "{$_ENV['HOME']}/.mwsql_history" : "{$IP}/maintenance/.mwsql_history"; readline_read_history($historyFile); } $wholeLine = ''; $newPrompt = '> '; $prompt = $newPrompt; while (($line = Maintenance::readconsole($prompt)) !== false) { if (!$line) { # User simply pressed return key continue; } $done = $dbw->streamStatementEnd($wholeLine, $line); $wholeLine .= $line; if (!$done) { $wholeLine .= ' '; $prompt = ' -> '; continue; } if ($useReadline) { # Delimiter is eated by streamStatementEnd, we add it # up in the history (bug 37020) readline_add_history($wholeLine . $dbw->getDelimiter()); readline_write_history($historyFile); } try { $res = $dbw->query($wholeLine); $this->sqlPrintResult($res, $dbw); $prompt = $newPrompt; $wholeLine = ''; } catch (DBQueryError $e) { $doDie = !Maintenance::posix_isatty(0); $this->error($e, $doDie); } } wfWaitForSlaves(); }
} if (strcmp("{$wgScriptPath}/api{$wgScriptExtension}", $url)) { wfHttpError(403, 'Forbidden', 'API must be accessed through the primary script entry point.'); return; } // Verify that the API has not been disabled if (!$wgEnableAPI) { echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php'; echo '<pre><b>$wgEnableAPI=true;</b></pre>'; die(1); } // So extensions can check whether they're running in API mode define('MW_API', true); // Set a dummy $wgTitle, because $wgTitle == null breaks various things // In a perfect world this wouldn't be necessary $wgTitle = Title::newFromText('API'); /* Construct an ApiMain with the arguments passed via the URL. What we get back * is some form of an ApiMain, possibly even one that produces an error message, * but we don't care here, as that is handled by the ctor. */ $processor = new ApiMain($wgRequest, $wgEnableWriteAPI); // Process data & print results $processor->execute(); // Execute any deferred updates wfDoUpdates(); // Log what the user did, for book-keeping purposes. wfProfileOut('api.php'); wfLogProfilingData(); // Shut down the database wfGetLBFactory()->shutdown();
/** * @param int $index (DB_SLAVE/DB_MASTER) * @return DBConnRef */ protected function getDB($index) { $lb = $this->cluster !== false ? wfGetLBFactory()->getExternalLB($this->cluster, $this->wiki) : wfGetLB($this->wiki); return $lb->getConnectionRef($index, array(), $this->wiki); }
/** * Ends this task peacefully */ function restInPeace() { wfLogProfilingData(); // Commit and close up! $factory = wfGetLBFactory(); $factory->commitMasterChanges(); $factory->shutdown(); wfDebug("Request ended normally\n"); }
/** * Get a master connection to the logging DB * * @return DatabaseBase * @throws DBError */ protected function getMasterDB() { if (!$this->dbw) { // Get a separate connection in autocommit mode $lb = wfGetLBFactory()->newMainLB(); $this->dbw = $lb->getConnection(DB_MASTER, array(), $this->wiki); $this->dbw->clearFlag(DBO_TRX); } return $this->dbw; }
protected function prepareEnvironment() { global $wgCaches, $wgMemc; // Don't share DB or memcached connections wfGetLBFactory()->destroyInstance(); $wgCaches = array(); unset($wgMemc); }
/** * Issue a commit on all masters who are currently in a transaction and have * made changes to the database. It also supports sometimes waiting for the * local wiki's slaves to catch up. See the documentation for * $wgJobSerialCommitThreshold for more. * * @param Job $job * @throws DBError */ private function commitMasterChanges(Job $job) { global $wgJobSerialCommitThreshold; $lb = wfGetLB(wfWikiID()); if ($wgJobSerialCommitThreshold !== false) { // Generally, there is one master connection to the local DB $dbwSerial = $lb->getAnyOpenConnection($lb->getWriterIndex()); } else { $dbwSerial = false; } if (!$dbwSerial || !$dbwSerial->namedLocksEnqueue() || $dbwSerial->pendingWriteQueryDuration() < $wgJobSerialCommitThreshold) { // Writes are all to foreign DBs, named locks don't form queues, // or $wgJobSerialCommitThreshold is not reached; commit changes now wfGetLBFactory()->commitMasterChanges(); return; } $ms = intval(1000 * $dbwSerial->pendingWriteQueryDuration()); $msg = $job->toString() . " COMMIT ENQUEUED [{$ms}ms of writes]"; $this->logger->warning($msg); $this->debugCallback($msg); // Wait for an exclusive lock to commit if (!$dbwSerial->lock('jobrunner-serial-commit', __METHOD__, 30)) { // This will trigger a rollback in the main loop throw new DBError($dbwSerial, "Timed out waiting on commit queue."); } // Wait for the generic slave to catch up $pos = $lb->getMasterPos(); if ($pos) { $lb->waitForOne($pos); } $fname = __METHOD__; // Re-ping all masters with transactions. This throws DBError if some // connection died while waiting on locks/slaves, triggering a rollback. wfGetLBFactory()->forEachLB(function (LoadBalancer $lb) use($fname) { $lb->forEachOpenConnection(function (IDatabase $conn) use($fname) { if ($conn->writesOrCallbacksPending()) { $conn->query("SELECT 1", $fname); } }); }); // Actually commit the DB master changes wfGetLBFactory()->commitMasterChanges(); // Release the lock $dbwSerial->unlock('jobrunner-serial-commit', __METHOD__); }
/** * */ function wfSpecialExport($page = '') { global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors; global $wgExportAllowHistory, $wgExportMaxHistory; $curonly = true; $doexport = false; if ($wgRequest->getCheck('addcat')) { $page = $wgRequest->getText('pages'); $catname = $wgRequest->getText('catname'); if ($catname !== '' && $catname !== NULL && $catname !== false) { $t = Title::makeTitleSafe(NS_MAIN, $catname); if ($t) { /** * @fixme This can lead to hitting memory limit for very large * categories. Ideally we would do the lookup synchronously * during the export in a single query. */ $catpages = wfExportGetPagesFromCategory($t); if ($catpages) { $page .= "\n" . implode("\n", $catpages); } } } } else { if ($wgRequest->wasPosted() && $page == '') { $page = $wgRequest->getText('pages'); $curonly = $wgRequest->getCheck('curonly'); $rawOffset = $wgRequest->getVal('offset'); if ($rawOffset) { $offset = wfTimestamp(TS_MW, $rawOffset); } else { $offset = null; } $limit = $wgRequest->getInt('limit'); $dir = $wgRequest->getVal('dir'); $history = array('dir' => 'asc', 'offset' => false, 'limit' => $wgExportMaxHistory); $historyCheck = $wgRequest->getCheck('history'); if ($curonly) { $history = WikiExporter::CURRENT; } elseif (!$historyCheck) { if ($limit > 0 && $limit < $wgExportMaxHistory) { $history['limit'] = $limit; } if (!is_null($offset)) { $history['offset'] = $offset; } if (strtolower($dir) == 'desc') { $history['dir'] = 'desc'; } } if ($page != '') { $doexport = true; } } else { // Default to current-only for GET requests $page = $wgRequest->getText('pages', $page); $historyCheck = $wgRequest->getCheck('history'); if ($historyCheck) { $history = WikiExporter::FULL; } else { $history = WikiExporter::CURRENT; } if ($page != '') { $doexport = true; } } } if (!$wgExportAllowHistory) { // Override $history = WikiExporter::CURRENT; } $list_authors = $wgRequest->getCheck('listauthors'); if (!$curonly || !$wgExportAllowListContributors) { $list_authors = false; } if ($doexport) { $wgOut->disable(); // Cancel output buffering and gzipping if set // This should provide safer streaming for pages with history wfResetOutputBuffers(); header("Content-type: application/xml; charset=utf-8"); if ($wgRequest->getCheck('wpDownload')) { // Provide a sane filename suggestion $filename = urlencode($wgSitename . '-' . wfTimestampNow() . '.xml'); $wgRequest->response()->header("Content-disposition: attachment;filename={$filename}"); } /* Split up the input and look up linked pages */ $inputPages = array_filter(explode("\n", $page), 'wfFilterPage'); $pageSet = array_flip($inputPages); if ($wgRequest->getCheck('templates')) { $pageSet = wfExportGetTemplates($inputPages, $pageSet); } /* // Enable this when we can do something useful exporting/importing image information. :) if( $wgRequest->getCheck( 'images' ) ) { $pageSet = wfExportGetImages( $inputPages, $pageSet ); } */ $pages = array_keys($pageSet); /* Ok, let's get to it... */ if ($history == WikiExporter::CURRENT) { $lb = false; $db = wfGetDB(DB_SLAVE); $buffer = WikiExporter::BUFFER; } else { // Use an unbuffered query; histories may be very long! $lb = wfGetLBFactory()->newMainLB(); $db = $lb->getConnection(DB_SLAVE); $buffer = WikiExporter::STREAM; // This might take a while... :D wfSuppressWarnings(); set_time_limit(0); wfRestoreWarnings(); } $exporter = new WikiExporter($db, $history, $buffer); $exporter->list_authors = $list_authors; $exporter->openStream(); foreach ($pages as $page) { /* if( $wgExportMaxHistory && !$curonly ) { $title = Title::newFromText( $page ); if( $title ) { $count = Revision::countByTitle( $db, $title ); if( $count > $wgExportMaxHistory ) { wfDebug( __FUNCTION__ . ": Skipped $page, $count revisions too big\n" ); continue; } } }*/ #Bug 8824: Only export pages the user can read $title = Title::newFromText($page); if (is_null($title)) { continue; } #TODO: perhaps output an <error> tag or something. if (!$title->userCanRead()) { continue; } #TODO: perhaps output an <error> tag or something. $exporter->pageByTitle($title); } $exporter->closeStream(); if ($lb) { $lb->closeAll(); } return; } $self = SpecialPage::getTitleFor('Export'); $wgOut->addHTML(wfMsgExt('exporttext', 'parse')); $form = Xml::openElement('form', array('method' => 'post', 'action' => $self->getLocalUrl('action=submit'))); $form .= Xml::inputLabel(wfMsg('export-addcattext'), 'catname', 'catname', 40) . ' '; $form .= Xml::submitButton(wfMsg('export-addcat'), array('name' => 'addcat')) . '<br />'; $form .= Xml::openElement('textarea', array('name' => 'pages', 'cols' => 40, 'rows' => 10)); $form .= htmlspecialchars($page); $form .= Xml::closeElement('textarea'); $form .= '<br />'; if ($wgExportAllowHistory) { $form .= Xml::checkLabel(wfMsg('exportcuronly'), 'curonly', 'curonly', true) . '<br />'; } else { $wgOut->addHTML(wfMsgExt('exportnohistory', 'parse')); } $form .= Xml::checkLabel(wfMsg('export-templates'), 'templates', 'wpExportTemplates', false) . '<br />'; // Enable this when we can do something useful exporting/importing image information. :) //$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />'; $form .= Xml::checkLabel(wfMsg('export-download'), 'wpDownload', 'wpDownload', true) . '<br />'; $form .= Xml::submitButton(wfMsg('export-submit'), array('accesskey' => 's')); $form .= Xml::closeElement('form'); $wgOut->addHTML($form); }
DeferredUpdates::doUpdates(); // Log what the user did, for book-keeping purposes. $endtime = microtime(true); wfProfileOut('api.php'); wfLogProfilingData(); // Log the request if ($wgAPIRequestLog) { $items = array(wfTimestamp(TS_MW), $endtime - $starttime, $wgRequest->getIP(), $wgRequest->getHeader('User-agent')); $items[] = $wgRequest->wasPosted() ? 'POST' : 'GET'; if ($processor) { try { $manager = $processor->getModuleManager(); $module = $manager->getModule($wgRequest->getVal('action'), 'action'); } catch (Exception $ex) { $module = null; } if (!$module || $module->mustBePosted()) { $items[] = "action=" . $wgRequest->getVal('action'); } else { $items[] = wfArrayToCgi($wgRequest->getValues()); } } else { $items[] = "failed in ApiBeforeMain"; } wfErrorLog(implode(',', $items) . "\n", $wgAPIRequestLog); wfDebug("Logged API request to {$wgAPIRequestLog}\n"); } // Shut down the database. foo()->bar() syntax is not supported in PHP4: we won't ever actually // get here to worry about whether this should be = or =&, but the file has to parse properly. $lb = wfGetLBFactory(); $lb->shutdown();
/** * Gets a DB master connection for the given external cluster name * @param $cluster string * @return DatabaseBase */ function getExtDB($cluster) { $lb = wfGetLBFactory()->getExternalLB($cluster); return $lb->getConnection(DB_MASTER); }
/** * Waits for the slaves to catch up to the master position * * Use this when updating very large numbers of rows, as in maintenance scripts, * to avoid causing too much lag. Of course, this is a no-op if there are no slaves. * * By default this waits on the main DB cluster of the current wiki. * If $cluster is set to "*" it will wait on all DB clusters, including * external ones. If the lag being waiting on is caused by the code that * does this check, it makes since to use $ifWritesSince, particularly if * cluster is "*", to avoid excess overhead. * * Never call this function after a big DB write that is still in a transaction. * This only makes sense after the possible lag inducing changes were committed. * * @param float|null $ifWritesSince Only wait if writes were done since this UNIX timestamp * @param string|bool $wiki Wiki identifier accepted by wfGetLB * @param string|bool $cluster Cluster name accepted by LBFactory. Default: false. * @param int|null $timeout Max wait time. Default: 1 day (cli), ~10 seconds (web) * @return bool Success (able to connect and no timeouts reached) */ function wfWaitForSlaves($ifWritesSince = null, $wiki = false, $cluster = false, $timeout = null) { // B/C: first argument used to be "max seconds of lag"; ignore such values $ifWritesSince = $ifWritesSince > 1000000000.0 ? $ifWritesSince : null; if ($timeout === null) { $timeout = PHP_SAPI === 'cli' ? 86400 : 10; } // Figure out which clusters need to be checked /** @var LoadBalancer[] $lbs */ $lbs = array(); if ($cluster === '*') { wfGetLBFactory()->forEachLB(function (LoadBalancer $lb) use(&$lbs) { $lbs[] = $lb; }); } elseif ($cluster !== false) { $lbs[] = wfGetLBFactory()->getExternalLB($cluster); } else { $lbs[] = wfGetLB($wiki); } // Get all the master positions of applicable DBs right now. // This can be faster since waiting on one cluster reduces the // time needed to wait on the next clusters. $masterPositions = array_fill(0, count($lbs), false); foreach ($lbs as $i => $lb) { if ($lb->getServerCount() <= 1) { // Bug 27975 - Don't try to wait for slaves if there are none // Prevents permission error when getting master position continue; } elseif ($ifWritesSince && $lb->lastMasterChangeTimestamp() < $ifWritesSince) { continue; // no writes since the last wait } $masterPositions[$i] = $lb->getMasterPos(); } $ok = true; foreach ($lbs as $i => $lb) { if ($masterPositions[$i]) { // The DBMS may not support getMasterPos() or the whole // load balancer might be fake (e.g. $wgAllDBsAreLocalhost). $ok = $lb->waitForAll($masterPositions[$i], $timeout) && $ok; } } return $ok; }
/** * @param WikiPage $page * @param Revision $newRev * @throws MWException */ protected function notifyUpdatesForRevision(WikiPage $page, Revision $newRev) { $config = RequestContext::getMain()->getConfig(); $title = $page->getTitle(); // Get the new revision if (!$newRev->getContent()) { return; // deleted? } // Get the prior revision (the same for null edits) if ($newRev->getParentId()) { $oldRev = Revision::newFromId($newRev->getParentId(), Revision::READ_LATEST); if (!$oldRev->getContent()) { return; // deleted? } } else { $oldRev = null; } // Parse the new revision and get the categories $categoryChanges = $this->getExplicitCategoriesChanges($title, $newRev, $oldRev); list($categoryInserts, $categoryDeletes) = $categoryChanges; if (!$categoryInserts && !$categoryDeletes) { return; // nothing to do } $dbw = wfGetDB(DB_MASTER); $catMembChange = new CategoryMembershipChange($title, $newRev); $catMembChange->checkTemplateLinks(); $batchSize = $config->get('UpdateRowsPerQuery'); $insertCount = 0; foreach ($categoryInserts as $categoryName) { $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName); $catMembChange->triggerCategoryAddedNotification($categoryTitle); if ($insertCount++ && $insertCount % $batchSize == 0) { $dbw->commit(__METHOD__, 'flush'); wfGetLBFactory()->waitForReplication(); } } foreach ($categoryDeletes as $categoryName) { $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName); $catMembChange->triggerCategoryRemovedNotification($categoryTitle); if ($insertCount++ && $insertCount++ % $batchSize == 0) { $dbw->commit(__METHOD__, 'flush'); wfGetLBFactory()->waitForReplication(); } } }
require_once "{$IP}/vendor/autoload.php"; } if (defined('MW_CONFIG_CALLBACK')) { # Use a callback function to configure MediaWiki call_user_func(MW_CONFIG_CALLBACK); } else { // Require the configuration (probably LocalSettings.php) require $maintenance->loadSettings(); } if ($maintenance->getDbType() === Maintenance::DB_NONE) { if ($wgLocalisationCacheConf['storeClass'] === false && ($wgLocalisationCacheConf['store'] == 'db' || $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory)) { $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull'; } } $maintenance->finalSetup(); // Some last includes require_once "{$IP}/includes/Setup.php"; // Initialize main config instance $maintenance->setConfig(ConfigFactory::getDefaultInstance()->makeConfig('main')); // Do the work $maintenance->execute(); // Potentially debug globals $maintenance->globals(); // Perform deferred updates. DeferredUpdates::doUpdates(); // log profiling info wfLogProfilingData(); // Commit and close up! $factory = wfGetLBFactory(); $factory->commitMasterChanges('doMaintenance'); $factory->shutdown();
/** * Removes non-existing links from pages from pagelinks, imagelinks, * categorylinks, templatelinks and externallinks tables. * * @param $maxLag * @param $batchSize The size of deletion batches * * @author Merlijn van Deen <*****@*****.**> */ private function deleteLinksFromNonexistent( $maxLag = 0, $batchSize = 100 ) { wfWaitForSlaves( $maxLag ); $dbw = wfGetDB( DB_MASTER ); $lb = wfGetLBFactory()->newMainLB(); $dbr = $lb->getConnection( DB_SLAVE ); $dbr->bufferResults( false ); $linksTables = array( // table name => page_id field 'pagelinks' => 'pl_from', 'imagelinks' => 'il_from', 'categorylinks' => 'cl_from', 'templatelinks' => 'tl_from', 'externallinks' => 'el_from', ); foreach ( $linksTables as $table => $field ) { $this->output( "Retrieving illegal entries from $table... " ); // SELECT DISTINCT( $field ) FROM $table LEFT JOIN page ON $field=page_id WHERE page_id IS NULL; $results = $dbr->select( array( $table, 'page' ), $field, array('page_id' => null ), __METHOD__, 'DISTINCT', array( 'page' => array( 'LEFT JOIN', "$field=page_id")) ); $counter = 0; $list = array(); $this->output( "0.." ); foreach( $results as $row ) { $counter++; $list[] = $row->$field; if ( ( $counter % $batchSize ) == 0 ) { wfWaitForSlaves(5); $dbw->delete( $table, array( $field => $list ), __METHOD__ ); $this->output( $counter . ".." ); $list = array(); } } $this->output( $counter ); if (count($list) > 0) { $dbw->delete( $table, array( $field => $list ), __METHOD__ ); } $this->output( "\n" ); } $lb->closeAll(); }
protected function &getDB($cluster, $groups = [], $wiki = false) { $lb = wfGetLBFactory()->getExternalLB($cluster); return $lb->getConnection(DB_REPLICA); }