Merge "Reduced some master queries by adding flags to Revision functions."

This commit is contained in:
Tim Starling 2012-06-28 05:11:04 +00:00 committed by Gerrit Code Review
commit fcd74e5dd3
7 changed files with 99 additions and 36 deletions

View file

@ -435,6 +435,9 @@ $wgAutoloadLocalClasses = array(
'IContextSource' => 'includes/context/IContextSource.php',
'RequestContext' => 'includes/context/RequestContext.php',
# includes/dao
'IDBAccessObject' => 'includes/dao/IDBAccessObject.php',
# includes/db
'Blob' => 'includes/db/DatabaseUtility.php',
'ChronologyProtector' => 'includes/db/LBFactory.php',

View file

@ -23,7 +23,7 @@
/**
* @todo document
*/
class Revision {
class Revision implements IDBAccessObject {
protected $mId;
protected $mPage;
protected $mUserText;
@ -47,7 +47,7 @@ class Revision {
const DELETED_RESTRICTED = 8;
// Convenience field
const SUPPRESSED_USER = 12;
// Audience options for Revision::getText()
// Audience options for accessors
const FOR_PUBLIC = 1;
const FOR_THIS_USER = 2;
const RAW = 3;
@ -56,11 +56,17 @@ class Revision {
* Load a page revision from a given revision ID number.
* Returns null if no such revision can be found.
*
* $flags include:
* IDBAccessObject::LATEST_READ : Select the data from the master
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
*
* @param $id Integer
* @param $flags Integer (optional)
* @return Revision or null
*/
public static function newFromId( $id ) {
return Revision::newFromConds( array( 'rev_id' => intval( $id ) ) );
public static function newFromId( $id, $flags = 0 ) {
return self::newFromConds( array( 'rev_id' => intval( $id ) ), $flags );
}
/**
@ -68,11 +74,17 @@ class Revision {
* that's attached to a given title. If not attached
* to that title, will return null.
*
* $flags include:
* IDBAccessObject::LATEST_READ : Select the data from the master
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
*
* @param $title Title
* @param $id Integer (optional)
* @param $flags Integer Bitfield (optional)
* @return Revision or null
*/
public static function newFromTitle( $title, $id = 0 ) {
public static function newFromTitle( $title, $id = 0, $flags = 0 ) {
$conds = array(
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey()
@ -80,7 +92,7 @@ class Revision {
if ( $id ) {
// Use the specified ID
$conds['rev_id'] = $id;
} elseif ( wfGetLB()->getServerCount() > 1 ) {
} elseif ( !( $flags & self::AVOID_MASTER ) && wfGetLB()->getServerCount() > 1 ) {
// Get the latest revision ID from the master
$dbw = wfGetDB( DB_MASTER );
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
@ -92,7 +104,7 @@ class Revision {
// Use a join to get the latest revision
$conds[] = 'rev_id=page_latest';
}
return Revision::newFromConds( $conds );
return self::newFromConds( $conds, $flags );
}
/**
@ -100,15 +112,21 @@ class Revision {
* that's attached to a given page ID.
* Returns null if no such revision can be found.
*
* $flags include:
* IDBAccessObject::LATEST_READ : Select the data from the master
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
*
* @param $revId Integer
* @param $pageId Integer (optional)
* @param $flags Integer Bitfield (optional)
* @return Revision or null
*/
public static function newFromPageId( $pageId, $revId = 0 ) {
public static function newFromPageId( $pageId, $revId = 0, $flags = 0 ) {
$conds = array( 'page_id' => $pageId );
if ( $revId ) {
$conds['rev_id'] = $revId;
} elseif ( wfGetLB()->getServerCount() > 1 ) {
} elseif ( !( $flags & self::AVOID_MASTER ) && wfGetLB()->getServerCount() > 1 ) {
// Get the latest revision ID from the master
$dbw = wfGetDB( DB_MASTER );
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
@ -119,7 +137,7 @@ class Revision {
} else {
$conds[] = 'rev_id = page_latest';
}
return Revision::newFromConds( $conds );
return self::newFromConds( $conds, $flags );
}
/**
@ -175,7 +193,7 @@ class Revision {
* @return Revision or null
*/
public static function loadFromId( $db, $id ) {
return Revision::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) );
return self::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) );
}
/**
@ -195,7 +213,7 @@ class Revision {
} else {
$conds[] = 'rev_id=page_latest';
}
return Revision::loadFromConds( $db, $conds );
return self::loadFromConds( $db, $conds );
}
/**
@ -214,7 +232,7 @@ class Revision {
} else {
$matchId = 'page_latest';
}
return Revision::loadFromConds( $db,
return self::loadFromConds( $db,
array( "rev_id=$matchId",
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey() )
@ -232,7 +250,7 @@ class Revision {
* @return Revision or null
*/
public static function loadFromTimestamp( $db, $title, $timestamp ) {
return Revision::loadFromConds( $db,
return self::loadFromConds( $db,
array( 'rev_timestamp' => $db->timestamp( $timestamp ),
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey() )
@ -243,14 +261,17 @@ class Revision {
* Given a set of conditions, fetch a revision.
*
* @param $conditions Array
* @param $flags integer (optional)
* @return Revision or null
*/
public static function newFromConds( $conditions ) {
$db = wfGetDB( DB_SLAVE );
$rev = Revision::loadFromConds( $db, $conditions );
if( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) {
$dbw = wfGetDB( DB_MASTER );
$rev = Revision::loadFromConds( $dbw, $conditions );
private static function newFromConds( $conditions, $flags = 0 ) {
$db = wfGetDB( ( $flags & self::LATEST_READ ) ? DB_MASTER : DB_SLAVE );
$rev = self::loadFromConds( $db, $conditions, $flags );
if ( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) {
if ( !( $flags & self::LATEST_READ ) && !( $flags & self::AVOID_MASTER ) ) {
$dbw = wfGetDB( DB_MASTER );
$rev = self::loadFromConds( $dbw, $conditions, $flags );
}
}
return $rev;
}
@ -261,10 +282,11 @@ class Revision {
*
* @param $db DatabaseBase
* @param $conditions Array
* @param $flags integer (optional)
* @return Revision or null
*/
private static function loadFromConds( $db, $conditions ) {
$res = Revision::fetchFromConds( $db, $conditions );
private static function loadFromConds( $db, $conditions, $flags = 0 ) {
$res = self::fetchFromConds( $db, $conditions, $flags );
if( $res ) {
$row = $res->fetchObject();
if( $row ) {
@ -285,7 +307,7 @@ class Revision {
* @return ResultWrapper
*/
public static function fetchRevision( $title ) {
return Revision::fetchFromConds(
return self::fetchFromConds(
wfGetDB( DB_SLAVE ),
array( 'rev_id=page_latest',
'page_namespace' => $title->getNamespace(),
@ -300,20 +322,25 @@ class Revision {
*
* @param $db DatabaseBase
* @param $conditions Array
* @param $flags integer (optional)
* @return ResultWrapper
*/
private static function fetchFromConds( $db, $conditions ) {
private static function fetchFromConds( $db, $conditions, $flags = 0 ) {
$fields = array_merge(
self::selectFields(),
self::selectPageFields(),
self::selectUserFields()
);
$options = array( 'LIMIT' => 1 );
if ( $flags & self::FOR_UPDATE ) {
$options[] = 'FOR UPDATE';
}
return $db->select(
array( 'revision', 'page', 'user' ),
$fields,
$conditions,
__METHOD__,
array( 'LIMIT' => 1 ),
$options,
array( 'page' => self::pageJoinCond(), 'user' => self::userJoinCond() )
);
}
@ -834,7 +861,7 @@ class Revision {
if( $this->getTitle() ) {
$prev = $this->getTitle()->getPreviousRevisionID( $this->getId() );
if( $prev ) {
return Revision::newFromTitle( $this->getTitle(), $prev );
return self::newFromTitle( $this->getTitle(), $prev );
}
}
return null;
@ -849,7 +876,7 @@ class Revision {
if( $this->getTitle() ) {
$next = $this->getTitle()->getNextRevisionID( $this->getId() );
if ( $next ) {
return Revision::newFromTitle( $this->getTitle(), $next );
return self::newFromTitle( $this->getTitle(), $next );
}
}
return null;
@ -979,7 +1006,7 @@ class Revision {
$text = gzdeflate( $text );
$flags[] = 'gzip';
} else {
wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" );
wfDebug( __METHOD__ . " -- no zlib support, not compressing\n" );
}
}
return implode( ',', $flags );
@ -998,7 +1025,7 @@ class Revision {
wfProfileIn( __METHOD__ );
$data = $this->mText;
$flags = Revision::compressRevisionText( $data );
$flags = self::compressRevisionText( $data );
# Write to external storage if required
if( $wgDefaultExternalStore ) {
@ -1048,7 +1075,7 @@ class Revision {
? $this->getPreviousRevisionId( $dbw )
: $this->mParentId,
'rev_sha1' => is_null( $this->mSha1 )
? Revision::base36Sha1( $this->mText )
? self::base36Sha1( $this->mText )
: $this->mSha1
), __METHOD__
);
@ -1272,7 +1299,7 @@ class Revision {
static function countByTitle( $db, $title ) {
$id = $title->getArticleID();
if( $id ) {
return Revision::countByPageId( $db, $id );
return self::countByPageId( $db, $id );
}
return 0;
}

View file

@ -0,0 +1,32 @@
<?php
/**
* This file contains database access object related constants.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Database
*/
/**
* Interface for database access objects
*/
interface IDBAccessObject {
const LATEST_READ = 1; // read from the master
const FOR_UPDATE = 2; // lock the rows read
const LOCKING_READ = 3; // LATEST_READ | FOR_UPDATE
const AVOID_MASTER = 4; // avoiding checking the master
}

View file

@ -612,7 +612,7 @@ class DifferenceEngine extends ContextSource {
return false;
}
// Short-circuit
// If mOldRev is false, it means that the
// If mOldRev is false, it means that the
if ( $this->mOldRev === false || ( $this->mOldRev && $this->mNewRev
&& $this->mOldRev->getID() == $this->mNewRev->getID() ) )
{
@ -1019,7 +1019,7 @@ class DifferenceEngine extends ContextSource {
// Load the new revision object
$this->mNewRev = $this->mNewid
? Revision::newFromId( $this->mNewid )
: Revision::newFromTitle( $this->getTitle() );
: Revision::newFromTitle( $this->getTitle(), false, Revision::AVOID_MASTER );
if ( !$this->mNewRev instanceof Revision ) {
return false;

View file

@ -1456,7 +1456,7 @@ class LocalFile extends File {
*/
function getDescriptionText() {
global $wgParser;
$revision = Revision::newFromTitle( $this->title );
$revision = Revision::newFromTitle( $this->title, false, Revision::AVOID_MASTER );
if ( !$revision ) return false;
$text = $revision->getText();
if ( !$text ) return false;

View file

@ -756,7 +756,8 @@ class SearchResult {
protected function initFromTitle( $title ) {
$this->mTitle = $title;
if ( !is_null( $this->mTitle ) ) {
$this->mRevision = Revision::newFromTitle( $this->mTitle );
$this->mRevision = Revision::newFromTitle(
$this->mTitle, false, Revision::AVOID_MASTER );
if ( $this->mTitle->getNamespace() === NS_FILE )
$this->mImage = wfFindFile( $this->mTitle );
}

View file

@ -143,7 +143,7 @@ class SpecialBookSources extends SpecialPage {
$page = $this->msg( 'booksources' )->inContentLanguage()->text();
$title = Title::makeTitleSafe( NS_PROJECT, $page ); # Show list in content language
if( is_object( $title ) && $title->exists() ) {
$rev = Revision::newFromTitle( $title );
$rev = Revision::newFromTitle( $title, false, Revision::AVOID_MASTER );
$this->getOutput()->addWikiText( str_replace( 'MAGICNUMBER', $this->isbn, $rev->getText() ) );
return true;
}