# Try to open, return false on failure
$params = $wgKnownDBServers[$machineId];
$db = Database::newFromParams( $params['server'], $params['user'], $params['password'],
- $dbName, 1, false, true, true );
+ $dbName, 1, DBO_IGNORE );
}
}
if ( $db->isOpen() ) {
$pcache = false;
}
- $wgLinkCache->preFill( $this->mTitle );
-
# wrap user css and user js in pre and don't parse
# XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found
if (
/* private */ function insertNewArticle( $text, $summary, $isminor, $watchthis )
{
- global $wgOut, $wgUser, $wgLinkCache, $wgMwRedir;
+ global $wgOut, $wgUser, $wgMwRedir;
global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
$fname = 'Article::insertNewArticle';
function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = '' )
{
- global $wgOut, $wgUser, $wgLinkCache;
+ global $wgOut, $wgUser;
global $wgDBtransactions, $wgMwRedir;
global $wgUseSquid, $wgInternalServer;
# Get old version of link table to allow incremental link updates
$wgLinkCache->preFill( $this->mTitle );
$wgLinkCache->clear();
-
+
+ # Switch on use of link cache in the skin
+ $sk =& $wgUser->getSkin();
+ $sk->postParseLinkColour( false );
+
# Now update the link cache by parsing the text
$wgOut = new OutputPage();
$wgOut->addWikiText( $text );
$linkID = $titleObj->getArticleID();
$brokenLinks[] = array( 'bl_from' => $linkID, 'bl_to' => $t );
}
- $dbw->insertArray( 'brokenlinks', $brokenLinks, $fname );
+ $dbw->insert( 'brokenlinks', $brokenLinks, $fname, 'IGNORE' );
# Delete live links
$dbw->delete( 'links', array( 'l_to' => $id ) );
# Variables
#------------------------------------------------------------------------------
/* private */ var $mLastQuery = "";
- /* private */ var $mBufferResults = true;
- /* private */ var $mIgnoreErrors = false;
/* private */ var $mServer, $mUser, $mPassword, $mConn, $mDBname;
- /* private */ var $mOut, $mDebug, $mOpened = false;
+ /* private */ var $mOut, $mOpened = false;
/* private */ var $mFailFunction;
/* private */ var $mTablePrefix;
+ /* private */ var $mFlags;
+ /* private */ var $mTrxLevel = 0;
#------------------------------------------------------------------------------
# Accessors
#------------------------------------------------------------------------------
- # Set functions
- # These set a variable and return the previous state
+ # These optionally set a variable and return the previous state
# Fail function, takes a Database as a parameter
# Set to false for default, 1 for ignore errors
- function setFailFunction( $function ) { return wfSetVar( $this->mFailFunction, $function ); }
+ function failFunction( $function = NULL ) {
+ return wfSetVar( $this->mFailFunction, $function );
+ }
# Output page, used for reporting errors
# FALSE means discard output
- function &setOutputPage( &$out ) { $this->mOut =& $out; }
+ function &setOutputPage( &$out ) {
+ $this->mOut =& $out;
+ }
# Boolean, controls output of large amounts of debug information
- function setDebug( $debug ) { return wfSetVar( $this->mDebug, $debug ); }
+ function debug( $debug = NULL ) {
+ return wfSetBit( $this->mFlags, DBO_DEBUG, $debug );
+ }
# Turns buffering of SQL result sets on (true) or off (false). Default is
# "on" and it should not be changed without good reasons.
- function setBufferResults( $buffer ) { return wfSetVar( $this->mBufferResults, $buffer ); }
+ function bufferResults( $buffer = NULL ) {
+ if ( is_null( $buffer ) ) {
+ return !(bool)( $this->mFlags & DBO_NOBUFFER );
+ } else {
+ return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer );
+ }
+ }
# Turns on (false) or off (true) the automatic generation and sending
# of a "we're sorry, but there has been a database error" page on
# database errors. Default is on (false). When turned off, the
# code should use wfLastErrno() and wfLastError() to handle the
# situation as appropriate.
- function setIgnoreErrors( $ignoreErrors ) { return wfSetVar( $this->mIgnoreErrors, $ignoreErrors ); }
+ function ignoreErrors( $ignoreErrors = NULL ) {
+ return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors );
+ }
+ # The current depth of nested transactions
+ function trxLevel( $level = NULL ) {
+ return wfSetVar( $this->mTrxLevel, $level );
+ }
+
# Get functions
function lastQuery() { return $this->mLastQuery; }
#------------------------------------------------------------------------------
function Database( $server = false, $user = false, $password = false, $dbName = false,
- $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false,
- $tablePrefix = 'get from global' )
+ $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
{
- global $wgOut, $wgDBprefix;
+ global $wgOut, $wgDBprefix, $wgCommandLineMode;
# Can't get a reference if it hasn't been set yet
if ( !isset( $wgOut ) ) {
$wgOut = NULL;
$this->mOut =& $wgOut;
$this->mFailFunction = $failFunction;
- $this->mIgnoreErrors = $ignoreErrors;
- $this->mDebug = $debug;
- $this->mBufferResults = $bufferResults;
+ $this->mFlags = $flags;
+
+ if ( $this->mFlags & DBO_DEFAULT ) {
+ if ( $wgCommandLineMode ) {
+ $this->mFlags &= ~DBO_TRX;
+ } else {
+ $this->mFlags |= DBO_TRX;
+ }
+ }
+
if ( $tablePrefix == 'get from global' ) {
$this->mTablePrefix = $wgDBprefix;
} else {
}
/* static */ function newFromParams( $server, $user, $password, $dbName,
- $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false )
+ $failFunction = false, $flags = 0 )
{
- return new Database( $server, $user, $password, $dbName, $failFunction, $debug,
- $bufferResults, $ignoreErrors );
+ return new Database( $server, $user, $password, $dbName, $failFunction, $flags );
}
# Usually aborts on failure
}
# Closes a database connection, if it is open
+ # Commits any open transactions
# Returns success, true if already closed
function close()
{
$this->mOpened = false;
if ( $this->mConn ) {
+ if ( $this->trxLevel() ) {
+ $this->immediateCommit();
+ }
return mysql_close( $this->mConn );
} else {
return true;
$this->mLastQuery = $sql;
- if ( $this->mDebug ) {
+ if ( $this->debug() ) {
$sqlx = substr( $sql, 0, 500 );
$sqlx = wordwrap(strtr($sqlx,"\t\n"," "));
wfDebug( "SQL: $sqlx\n" );
$commentedSql = $sql;
}
- if( $this->mBufferResults ) {
- $ret = mysql_query( $commentedSql, $this->mConn );
- } else {
- $ret = mysql_unbuffered_query( $commentedSql, $this->mConn );
+ # If DBO_TRX is set, start a transaction
+ if ( ( $this->mFlags & DBO_TRX ) && !$this->trxLevel() && $sql != 'BEGIN' ) {
+ $this->begin();
}
-
+
+ # Do the query and handle errors
+ $ret = $this->doQuery( $commentedSql );
if ( false === $ret ) {
- $this->reportQueryError( mysql_error(), mysql_errno(), $sql, $fname, $tempIgnore );
+ $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
}
-
+
if ( $wgProfiling ) {
wfProfileOut( $profName );
}
return $ret;
}
+ # The DBMS-dependent part of query()
+ function doQuery( $sql ) {
+ if( $this->bufferResults() ) {
+ $ret = mysql_query( $sql, $this->mConn );
+ } else {
+ $ret = mysql_unbuffered_query( $sql, $this->mConn );
+ }
+ return $ret;
+ }
+
function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
global $wgCommandLineMode, $wgFullyInitialised;
# Ignore errors during error handling to avoid infinite recursion
- $ignore = $this->setIgnoreErrors( true );
+ $ignore = $this->ignoreErrors( true );
if( $ignore || $tempIgnore ) {
wfDebug("SQL ERROR (ignored): " . $error . "\n");
$this->mOut->databaseError( $fname, $sql, $error, $errno );
}
}
- $this->setIgnoreErrors( $ignore );
+ $this->ignoreErrors( $ignore );
}
function freeResult( $res ) {
function tableExists( $table )
{
$table = $this->tableName( $table );
- $old = $this->mIgnoreErrors;
- $this->mIgnoreErrors = true;
+ $old = $this->ignoreErrors( true );
$res = $this->query( "SELECT 1 FROM $table LIMIT 1" );
- $this->mIgnoreErrors = $old;
+ $this->ignoreErrors( $old );
if( $res ) {
$this->freeResult( $res );
return true;
# If errors are explicitly ignored, returns success
function insert( $table, $a, $fname = "Database::insert", $options = array() )
{
+ # No rows to insert, easy just return now
+ if ( !count( $a ) ) {
+ return true;
+ }
+
$table = $this->tableName( $table );
if ( !is_array( $options ) ) {
$options = array( $options );
$multi = false;
$keys = array_keys( $a );
}
-
+
$sql = 'INSERT ' . implode( ' ', $options ) .
" INTO $table (" . implode( ',', $keys ) . ') VALUES ';
$this->query( "BEGIN", $myFname );
$args = func_get_args();
$function = array_shift( $args );
- $oldIgnore = $dbw->setIgnoreErrors( true );
+ $oldIgnore = $dbw->ignoreErrors( true );
$tries = DEADLOCK_TRIES;
if ( is_array( $function ) ) {
$fname = $function[0];
}
}
} while( $dbw->wasDeadlock && --$tries > 0 );
- $this->setIgnoreErrors( $oldIgnore );
+ $this->ignoreErrors( $oldIgnore );
if ( $tries <= 0 ) {
$this->query( "ROLLBACK", $myFname );
$this->reportQueryError( $error, $errno, $sql, $fname );
return array( false, false );
}
}
+
+ # Begin a transaction, or if a transaction has already started, continue it
+ function begin( $fname = 'Database::begin' ) {
+ if ( !$this->mTrxLevel ) {
+ $this->immediateBegin( $fname );
+ } else {
+ $this->mTrxLevel++;
+ }
+ }
+
+ # End a transaction, or decrement the nest level if transactions are nested
+ function commit( $fname = 'Database::commit' ) {
+ if ( $this->mTrxLevel ) {
+ $this->mTrxLevel--;
+ }
+ if ( !$this->mTrxLevel ) {
+ $this->immediateCommit( $fname );
+ }
+ }
+
+ # Rollback a transaction
+ function rollback( $fname = 'Database::rollback' ) {
+ $this->query( 'ROLLBACK', $fname );
+ $this->mTrxLevel = 0;
+ }
+
+ # Begin a transaction, committing any previously open transaction
+ function immediateBegin( $fname = 'Database::immediateBegin' ) {
+ $this->query( 'BEGIN', $fname );
+ $this->mTrxLevel = 1;
+ }
+
+ # Commit transaction, if one is open
+ function immediateCommit( $fname = 'Database::immediateCommit' ) {
+ $this->query( 'COMMIT', $fname );
+ $this->mTrxLevel = 0;
+ }
}
class DatabaseMysql extends Database {
$search = $_REQUEST['search'];
echo wfMsgNoDB( "searchdisabled" );
echo wfMsgNoDB( "googlesearch", htmlspecialchars( $search ), $wgInputEncoding );
- wfAbruptExit();
+ wfErrorExit();
} else {
$t = Title::newFromText( wfMsgNoDB( "mainpage" ) );
}
}
echo $text;
- wfAbruptExit();
+ wfErrorExit();
}
function wfLimitResult( $limit, $offset ) {
var $mInsertId = NULL;
function DatabasePgsql($server = false, $user = false, $password = false, $dbName = false,
- $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false)
+ $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
{
- Database::Database( $server, $user, $password, $dbName, $failFunction, $debug,
- $bufferResults, $ignoreErrors );
+ Database::Database( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
}
- /* static */ function newFromParams( $server, $user, $password, $dbName,
- $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false )
+ /* static */ function newFromParams( $server = false, $user = false, $password = false, $dbName = false,
+ $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
{
- return new DatabasePgsql( $server, $user, $password, $dbName, $failFunction, $debug,
- $bufferResults, $ignoreErrors );
+ return new DatabasePgsql( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
}
# Usually aborts on failure
}
}
- # Usually aborts on failure
- # If errors are explicitly ignored, returns success
- function query( $sql, $fname = "", $tempIgnore = false )
- {
- global $wgProfiling;
-
- if ( $wgProfiling ) {
- # generalizeSQL will probably cut down the query to reasonable
- # logging size most of the time. The substr is really just a sanity check.
- $profName = "query: " . substr( Database::generalizeSQL( $sql ), 0, 255 );
- wfProfileIn( $profName );
- }
-
- $this->mLastQuery = $sql;
-
- if ( $this->mDebug ) {
- $sqlx = substr( $sql, 0, 500 );
- $sqlx = wordwrap(strtr($sqlx,"\t\n"," "));
- wfDebug( "SQL: $sqlx\n" );
- }
-
- $ret = pg_query( $this->mConn , $sql);
- $this->mLastResult = $ret;
- if ( false == $ret ) {
- // Ignore errors during error handling to prevent infinite recursion
- $ignore = $this->setIgnoreErrors( true );
- $error = pg_last_error( $this->mConn );
- // TODO FIXME : no error number function in postgre
- // $errno = mysql_errno( $this->mConn );
- if( $ignore || $tempIgnore ) {
- wfDebug("SQL ERROR (ignored): " . $error . "\n");
- } else {
- wfDebug("SQL ERROR: " . $error . "\n");
- if ( $this->mOut ) {
- // this calls wfAbruptExit()
- $this->mOut->databaseError( $fname, $sql, $error, 0 );
- }
- }
- $this->setIgnoreErrors( $ignore );
- }
-
- if ( $wgProfiling ) {
- wfProfileOut( $profName );
- }
- return $ret;
+ function doQuery( $sql ) {
+ return pg_query( $this->mConn , $sql);
}
-
+
function queryIgnore( $sql, $fname = "" ) {
return $this->query( $sql, $fname, true );
}
function dataSeek( $res, $row ) { return pg_result_seek( $res, $row ); }
function lastError() { return pg_last_error(); }
+ function lastErrno() { return 1; }
+
function affectedRows() {
return pg_affected_rows( $this->mLastResult );
}
# IGNORE is performed using single-row inserts, ignoring errors in each
if ( in_array( 'IGNORE', $options ) ) {
# FIXME: need some way to distiguish between key collision and other types of error
- $oldIgnore = $this->setIgnoreErrors( true );
+ $oldIgnore = $this->ignoreErrors( true );
if ( !is_array( reset( $a ) ) ) {
$a = array( $a );
}
foreach ( $a as $row ) {
parent::insertArray( $table, $row, $fname, array() );
}
- $this->setIgnoreErrors( $oldIgnore );
+ $this->ignoreErrors( $oldIgnore );
$retVal = true;
} else {
$retVal = parent::insertArray( $table, $a, $fname, array() );
# password: DB password
# type: "mysql" or "pgsql"
# load: ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0
+# flags: bit field
+# DBO_DEFAULT -- turns on DBO_TRX only if !$wgCommandLineMode (recommended)
+# DBO_DEBUG -- equivalent of $wgDebugDumpSql
+# DBO_TRX -- wrap entire request in a transaction
+# DBO_IGNORE -- ignore errors (not useful in LocalSettings.php)
+# DBO_NOBUFFER -- turn off buffering (not useful in LocalSettings.php)
+#
# Leave at false to use the single-server variables above
$wgDBservers = false;
# used, as it may contain private data.
$wgDebugLogFile = '';
$wgDebugRedirects = false;
+$wgDebugRawPage = false; # Avoid overlapping debug entries by leaving out CSS
$wgDebugComments = false;
$wgReadOnly = false;
# FIXME: need fixing
$wgUseCategoryBrowser = false;
-$wgEnablePersistentLC = false; # Persistent link cache in linkscc table; FAILS on MySQL 3.x
+$wgEnablePersistentLC = false; # Obsolete, do not use
$wgCompressedPersistentLC = true; # use gzcompressed blobs
$wgEnableParserCache = false; # requires that php was compiled --with-zlib
# Maximum indent level of toc.
$wgMaxTocLevel = 999;
+
+# Recognise longitude/latitude coordinates
+$wgUseGeoMode = false;
+
?>
function wfDebug( $text, $logonly = false )
{
- global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly;
+ global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage;
+ # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
+ if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) {
+ return;
+ }
+
if ( isset( $wgOut ) && $wgDebugComments && !$logonly ) {
$wgOut->debug( $text );
}
function logProfilingData()
{
- global $wgRequestTime, $wgDebugLogFile;
+ global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
global $wgProfiling, $wgProfileStack, $wgProfileLimit, $wgUser;
$now = wfTime();
$log = sprintf( "%s\t%04.3f\t%s\n",
gmdate( 'YmdHis' ), $elapsed,
urldecode( $_SERVER['REQUEST_URI'] . $forward ) );
- if ( '' != $wgDebugLogFile ) {
+ if ( '' != $wgDebugLogFile && ( $wgRequest->getVal('action') != 'raw' || $wgDebugRawPage ) ) {
error_log( $log . $prof, 3, $wgDebugLogFile );
}
}
}
# Just like exit() but makes a note of it.
-function wfAbruptExit(){
+# Commits open transactions except if the error parameter is set
+function wfAbruptExit( $error = false ){
+ global $wgLoadBalancer;
static $called = false;
if ( $called ){
exit();
} else {
wfDebug('WARNING: Abrupt exit\n');
}
+ if ( !$error ) {
+ $wgLoadBalancer->closeAll();
+ }
exit();
}
+function wfErrorExit() {
+ wfAbruptExit( true );
+}
+
function wfDebugDieBacktrace( $msg = '' ) {
global $wgCommandLineMode;
return $temp;
}
-# Sets dest to a reference to source and returns the original dest
-# Pity that doesn't work in PHP
-function &wfSetRef( &$dest, &$source )
-{
- die( "You can't rebind a variable in the caller's scope" );
+# As for wfSetVar except setting a bit
+function wfSetBit( &$dest, $bit, $state = true ) {
+ $temp = (bool)($dest & $bit );
+ if ( !is_null( $state ) ) {
+ if ( $state ) {
+ $dest |= $bit;
+ } else {
+ $dest &= ~$bit;
+ }
+ }
+ return $temp;
}
# This function takes two arrays as input, and returns a CGI-style string, e.g.
}
$sql .= $dbw->addQuotes( $badTitle );
}
+ $sql .= ")";
$dbw->query( $sql, $fname );
}
} else {
class LoadBalancer {
/* private */ var $mServers, $mConnections, $mLoads;
/* private */ var $mFailFunction;
- /* private */ var $mForce, $mReadIndex, $mLastConn;
+ /* private */ var $mForce, $mReadIndex, $mLastIndex;
/* private */ var $mWaitForFile, $mWaitForPos;
function LoadBalancer()
$this->mFailFunction = false;
$this->mReadIndex = -1;
$this->mForce = -1;
- $this->mLastConn = false;
+ $this->mLastIndex = -1;
}
function newFromParams( $servers, $failFunction = false )
$this->mWriteIndex = -1;
$this->mForce = -1;
$this->mConnections = array();
- $this->mLastConn = false;
+ $this->mLastIndex = 1;
$this->mLoads = array();
$this->mWaitForFile = false;
$this->mWaitForPos = false;
return $i;
}
- function &getReader()
+ function getReaderIndex()
{
+ $i = false;
if ( $this->mForce >= 0 ) {
- $conn =& $this->getConnection( $this->mForce );
+ $i = $this->mForce;
} else {
if ( $this->mReadIndex >= 0 ) {
- $conn =& $this->getConnection( $this->mReadIndex );
+ $i = $this->mReadIndex;
} else {
# $loads is $this->mLoads except with elements knocked out if they
# don't work
wfDebug( "Using reader #$i: {$this->mServers[$i]['host']}\n" );
$conn =& $this->getConnection( $i );
+ $this->mConnections[$i] =& $conn;
+
if ( !$conn->isOpen() ) {
unset( $loads[$i] );
}
} while ( $i !== false && !$conn->isOpen() );
if ( $conn->isOpen() ) {
$this->mReadIndex = $i;
+ } else {
+ $i = false;
}
}
}
- if ( $conn === false || !$conn->isOpen() ) {
- $this->reportConnectionError( $conn );
- $conn = false;
- }
- return $conn;
+ return $i;
}
# Set the master wait position
$this->mWaitForPos = $pos;
if ( $this->mReadIndex > 0 ) {
- $this->doWait( $this->mReadIndex );
+ if ( !$this->doWait( $this->mReadIndex ) ) {
+ # Use master instead
+ $this->mReadIndex = 0;
+ }
}
}
list( $file, $pos ) = explode( ' ', $memcPos );
# If the saved position is later than the requested position, return now
if ( $file == $this->mWaitForFile && $this->mWaitForPos <= $pos ) {
- return;
+ return true;
}
}
if ( $result == -1 || is_null( $result ) ) {
# Timed out waiting for slave, use master instead
- # This is not the ideal solution. If there are a large number of slaves, a slow
- # replicated write query will cause the master to be swamped with reads. However
- # that's a relatively graceful failure mode, so it will do for now.
wfDebug( "Timed out waiting for slave #$index pos {$this->mWaitForFile} {$this->mWaitForPos}\n" );
- $this->mReadIndex = 0;
+ $retVal = false;
} else {
+ $retVal = true;
wfDebug( "Done\n" );
}
+ return $retVal;
}
+ # Get a connection by index
function &getConnection( $i, $fail = false )
{
/*
}*/
# Operation-based index
- # Note, getReader() and getWriter() will re-enter this function
- if ( $i == DB_SLAVE ) {
- $this->mLastConn =& $this->getReader();
+ if ( $i == DB_SLAVE ) {
+ # Note: re-entrant
+ $i = $this->getReaderIndex();
} elseif ( $i == DB_MASTER ) {
- $this->mLastConn =& $this->getWriter();
+ $i = $this->getWriterIndex();
} elseif ( $i == DB_LAST ) {
- # Just use $this->mLastConn, which should already be set
- if ( $this->mLastConn === false ) {
+ # Just use $this->mLastIndex, which should already be set
+ $i = $this->mLastIndex;
+ if ( $i === -1 ) {
# Oh dear, not set, best to use the writer for safety
- $this->mLastConn =& $this->getWriter();
+ $i = $this->getWriterIndex();
}
- } else {
- # Explicit index
- if ( !array_key_exists( $i, $this->mConnections ) || !$this->mConnections[$i]->isOpen() ) {
- $this->mConnections[$i] = $this->makeConnection( $this->mServers[$i] );
- if ( $i != 0 && $this->mWaitForFile ) {
- $this->doWait( $i );
+ }
+ # Now we have an explicit index into the servers array
+ if ( !$this->isOpen( $i ) ) {
+ $this->mConnections[$i] = $this->makeConnection( $this->mServers[$i] );
+
+ if ( $i != 0 && $this->mWaitForFile ) {
+ if ( !$this->doWait( $i ) ) {
+ # Error waiting for this slave, use master instead
+ $this->mReadIndex = 0;
+ $i = 0;
+ if ( !$this->isOpen( 0 ) ) {
+ $this->mConnections[0] = $this->makeConnection( $this->mServers[0] );
+ }
+ wfDebug( "Failed over to {$this->mConnections[0]->mServer}\n" );
}
}
- if ( !$this->mConnections[$i]->isOpen() ) {
- wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );
- if ( $fail ) {
- $this->reportConnectionError( $this->mConnections[$i] );
- }
- $this->mConnections[$i] = false;
+ }
+ if ( !$this->isOpen( $i ) ) {
+ wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );
+ if ( $fail ) {
+ $this->reportConnectionError( $this->mConnections[$i] );
}
- $this->mLastConn =& $this->mConnections[$i];
+ $this->mConnections[$i] = false;
}
- return $this->mLastConn;
+ $this->mLastIndex = $i;
+
+ return $this->mConnections[$i];
}
+ /* private */ function isOpen( $index ) {
+ if ( array_key_exists( $index, $this->mConnections ) && $this->mConnections[$index]->isOpen() ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
/* private */ function makeConnection( &$server ) {
extract( $server );
# Get class for this database type
}
# Create object
- return new $class( $host, $user, $password, $dbname, 1 );
+ return new $class( $host, $user, $password, $dbname, 1, $flags );
}
function reportConnectionError( &$conn )
$conn->reportConnectionError();
}
- function &getWriter()
+ function getWriterIndex()
{
- $c =& $this->getConnection( 0 );
- if ( $c === false || !$c->isOpen() ) {
- $this->reportConnectionError( $c );
- $c = false;
- }
- return $c;
+ return 0;
}
function force( $i )
$this->waitFor( $_SESSION['master_log_file'], $_SESSION['master_pos'] );
}
}
+
+ # Close all open connections
+ function closeAll() {
+ foreach( $this->mConnections as $i => $conn ) {
+ if ( $this->isOpen( $i ) ) {
+ $conn->close();
+ }
+ }
+ }
+
+ function commitAll() {
+ foreach( $this->mConnections as $i => $conn ) {
+ if ( $this->isOpen( $i ) ) {
+ $conn->immediateCommit();
+ }
+ }
+ }
}
# "magic" behaviors of them based on index. The textual
# names of the namespaces are handled by Language.php.
-# Virtual namespaces; these don't appear in the page database:
-define("NS_MEDIA", -2);
-define("NS_SPECIAL", -1);
-
-# Real namespaces:
-define("NS_MAIN", 0);
-define("NS_TALK", 1);
-define("NS_USER", 2);
-define("NS_USER_TALK", 3);
-define("NS_WP", 4);
-define("NS_WIKIPEDIA", 4);
-define("NS_WP_TALK", 5);
-define("NS_WIKIPEDIA_TALK", 5);
-define("NS_IMAGE", 6);
-define("NS_IMAGE_TALK", 7);
-define("NS_MEDIAWIKI", 8);
-define("NS_MEDIAWIKI_TALK", 9);
-define("NS_TEMPLATE", 10);
-define("NS_TEMPLATE_TALK", 11);
-define("NS_HELP", 12);
-define("NS_HELP_TALK", 13);
-define("NS_CATEGORY", 14);
-define("NS_CATEGORY_TALK", 15);
+# Definitions of the NS_ constants are in Defines.php
# These are synonyms for the names given in the language file
# Users and translators should not change them
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
$this->mBodytext = "";
$this->addHTML( "<p>" . wfMsg( $msg ) . "</p>\n" );
$this->returnToMain( false );
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function sysopRequired()
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
if ( $wgCommandLineMode ) {
$msg = wfMsgNoDB( "dberrortextcl" );
if ( $wgCommandLineMode || !is_object( $wgUser )) {
print "$msg\n";
- wfAbruptExit();
+ wfErrorExit();
}
$sk = $wgUser->getSkin();
$shlink = $sk->makeKnownLink( wfMsgNoDB( "searchhelppage" ),
$msg = str_replace( "$5", $shlink, $msg );
$this->mBodytext = $msg;
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function readOnlyPage( $source = null, $protected = false )
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
$this->mBodytext = $message;
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function unexpectedValueError( $name, $val )
global $wgMessageCache, $wgUseMemCached, $wgUseDatabaseMessages;
global $wgMsgCacheExpiry, $wgCommandLineMode;
global $wgBlockCache, $wgParserCache, $wgParser, $wgDBConnections;
-global $wgLoadBalancer, $wgDBservers;
+global $wgLoadBalancer, $wgDBservers, $wgDebugDumpSql;
global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype;
global $wgFullyInitialised;
'password' => $wgDBpassword,
'dbname' => $wgDBname,
'type' => $wgDBtype,
- 'load' => 1
+ 'load' => 1,
+ 'flags' => ($wgDebugDumpSql ? DBO_DEBUG : 0) | DBO_DEFAULT
));
}
$wgLoadBalancer = LoadBalancer::newFromParams( $wgDBservers );
"Recentchangeslinked" => new UnlistedSpecialPage( "Recentchangeslinked" ),
"Movepage" => new UnlistedSpecialPage( "Movepage" ),
"Blockme" => new UnlistedSpecialPage( "Blockme" ),
- "Geo" => new SpecialPage( "Geo" ),
- "Validate" => new SpecialPage( "Validate" ),
+ "Geo" => new UnlistedSpecialPage( "Geo" ),
+ "Validate" => new UnlistedSpecialPage( "Validate" ),
"Booksources" => new SpecialPage( "Booksources" ),
"Categories" => new SpecialPage( "Categories" ),
"Export" => new SpecialPage( "Export" ),
"Asksql" => new SpecialPage( "Asksql", "sysop" ),
"Undelete" => new SpecialPage( "Undelete", "sysop" ),
"Makesysop" => new SpecialPage( "Makesysop", "sysop" ),
- "Import" => new SpecialPage( "Import", "sysop" ),
+# "Import" => new SpecialPage( "Import", "sysop" ),
"Lockdb" => new SpecialPage( "Lockdb", "developer" ),
"Unlockdb" => new SpecialPage( "Unlockdb", "developer" )
));
}
define( "MEDIAWIKI", true );
+require_once( "./includes/Defines.php" );
require_once( "./LocalSettings.php" );
require_once( "includes/Setup.php" );
exit;
}
-$db =& wfGetDB( DB_MASTER );
-
if ( $search = $wgRequest->getText( 'search' ) ) {
$wgTitle = Title::makeTitle( NS_SPECIAL, "Search" );
if( $wgRequest->getVal( 'fulltext' ) || !is_null( $wgRequest->getVal( 'offset' ) ) ) {
$wgArticle = new Article( $wgTitle );
}
- $db->query("BEGIN");
switch( $action ) {
case "view":
$wgOut->setSquidMaxage( $wgSquidMaxage );
default:
$wgOut->errorpage( "nosuchaction", "nosuchactiontext" );
}
- $db->query("COMMIT");
}
-$wgLoadBalancer->saveMasterPos();
-$wgOut->output();
-
+# Deferred updates aren't really deferred anymore. It's important to report errors to the
+# user, and that means doing this before OutputPage::output(). Note that for page saves,
+# the client will wait until the script exits anyway before following the redirect.
foreach ( $wgDeferredUpdateList as $up ) {
- $db->query("BEGIN");
$up->doUpdate();
- $db->query("COMMIT");
}
+
+$wgLoadBalancer->saveMasterPos();
+
+# Now commit any transactions, so that unreported errors after output() don't roll back the whole thing
+$wgLoadBalancer->commitAll();
+
+$wgOut->output();
+
logProfilingData();
+$wgLoadBalancer->closeAll();
wfDebug( "Request ended normally\n" );
?>
# Don't generate TeX PNGs (lack of a sensible current directory causes errors anyway)
$wgUser->setOption("math", 3);
+
+ # Turn on link cache in skin
+ $sk =& $wgUser->getSkin();
+ $sk->postParseLinkColour( false );
for ($id = $start; $id <= $end; $id++) {
if ( !($id % REPORTING_INTERVAL) ) {
#
print "Checking database for necessary updates...\n";
-$wgDatabase = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname,
- 1, false, true, false);
+$wgDatabase = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname, 1 );
if ( !$wgDatabase->isOpen() ) {
print "Unable to connect to database: " . $wgDatabase->lastError() . "\n";
exit();