use WANObjectCache;
use Exception;
use RuntimeException;
- use IDatabase;
use DBTransactionError;
use DBReplicationWaitError;
'errorLogger' => $this->errorLogger,
'hostname' => $this->hostname,
'cliMode' => $this->cliMode,
- 'agent' => $this->agent
+ 'agent' => $this->agent,
+ 'chronologyProtector' => $this->getChronologyProtector()
];
}
namespace Wikimedia\Rdbms;
- use IDatabase;
use InvalidArgumentException;
/**
public function getMainLB( $domain = false ) {
$section = $this->getSectionForDomain( $domain );
if ( !isset( $this->mainLBs[$section] ) ) {
- $lb = $this->newMainLB( $domain );
- $this->getChronologyProtector()->initLB( $lb );
- $this->mainLBs[$section] = $lb;
+ $this->mainLBs[$section] = $this->newMainLB( $domain );
}
return $this->mainLBs[$section];
public function getExternalLB( $cluster ) {
if ( !isset( $this->extLBs[$cluster] ) ) {
$this->extLBs[$cluster] = $this->newExternalLB( $cluster );
- $this->getChronologyProtector()->initLB( $this->extLBs[$cluster] );
}
return $this->extLBs[$cluster];
*/
namespace Wikimedia\Rdbms;
- use IDatabase;
use Database;
use DBConnRef;
use MaintainableDBConnRef;
* - srvCache : BagOStuff object for server cache [optional]
* - memCache : BagOStuff object for cluster memory cache [optional]
* - wanCache : WANObjectCache object [optional]
+ * - chronologyProtector: ChronologyProtector object [optional]
* - hostname : The name of the current server [optional]
* - cliMode: Whether the execution context is a CLI script. [optional]
* - profiler : Class name or instance with profileIn()/profileOut() methods. [optional]
* If a DB_REPLICA connection has been opened already, then wait immediately.
* Otherwise sets a variable telling it to wait if such a connection is opened.
*
- * @param DBMasterPos $pos
+ * @param DBMasterPos|bool $pos Master position or false
*/
public function waitFor( $pos );
*
* This can be used a faster proxy for waitForAll()
*
- * @param DBMasterPos $pos
+ * @param DBMasterPos|bool $pos Master position or false
* @param int $timeout Max seconds to wait; default is mWaitTimeout
* @return bool Success (able to connect and no timeouts reached)
*/
/**
* Set the master wait position and wait for ALL replica DBs to catch up to it
*
- * @param DBMasterPos $pos
+ * @param DBMasterPos|bool $pos Master position or false
* @param int $timeout Max seconds to wait; default is mWaitTimeout
* @return bool Success (able to connect and no timeouts reached)
*/
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Wikimedia\ScopedCallback;
- use IDatabase;
use Database;
use DBConnRef;
use MaintainableDBConnRef;
/** @var ILoadMonitor */
private $loadMonitor;
+ /** @var ChronologyProtector|null */
+ private $chronProt;
/** @var BagOStuff */
private $srvCache;
/** @var BagOStuff */
/** @var boolean */
private $disabled = false;
+ /** @var boolean */
+ private $chronProtInitialized = false;
/** @var integer Warn when this many connection are held */
const CONN_HELD_WARN_THRESHOLD = 10;
: ( gethostname() ?: 'unknown' );
$this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
$this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
+
+ if ( isset( $params['chronologyProtector'] ) ) {
+ $this->chronProt = $params['chronologyProtector'];
+ }
}
/**
return $i;
}
- /**
- * @param DBMasterPos|false $pos
- */
public function waitFor( $pos ) {
+ $oldPos = $this->mWaitForPos;
$this->mWaitForPos = $pos;
- $i = $this->mReadIndex;
+ // If a generic reader connection was already established, then wait now
+ $i = $this->mReadIndex;
if ( $i > 0 ) {
if ( !$this->doWait( $i ) ) {
$this->laggedReplicaMode = true;
}
}
+
+ // Restore the older position if it was higher
+ $this->setWaitForPositionIfHigher( $oldPos );
}
public function waitForOne( $pos, $timeout = null ) {
+ $oldPos = $this->mWaitForPos;
$this->mWaitForPos = $pos;
$i = $this->mReadIndex;
$ok = true; // no applicable loads
}
+ // Restore the older position if it was higher
+ $this->setWaitForPositionIfHigher( $oldPos );
+
return $ok;
}
public function waitForAll( $pos, $timeout = null ) {
+ $oldPos = $this->mWaitForPos;
$this->mWaitForPos = $pos;
$serverCount = count( $this->mServers );
}
}
+ // Restore the older position if it was higher
+ $this->setWaitForPositionIfHigher( $oldPos );
+
return $ok;
}
+ /**
+ * @param DBMasterPos|bool $pos
+ */
+ private function setWaitForPositionIfHigher( $pos ) {
+ if ( !$pos ) {
+ return;
+ }
+
+ if ( !$this->mWaitForPos || $pos->hasReached( $this->mWaitForPos ) ) {
+ $this->mWaitForPos = $pos;
+ }
+ }
+
/**
* @param int $i
* @return IDatabase|bool
$domain = false; // local connection requested
}
+ if ( !$this->chronProtInitialized && $this->chronProt ) {
+ $this->connLogger->debug( __METHOD__ . ': calling initLB() before first connection.' );
+ // Load CP positions before connecting so that doWait() triggers later if needed
+ $this->chronProtInitialized = true;
+ $this->chronProt->initLB( $this );
+ }
+
if ( $domain !== false ) {
$conn = $this->openForeignConnection( $i, $domain );
} elseif ( isset( $this->mConns['local'][$i][0] ) ) {
use \MediaWiki\Logger\LoggerFactory;
use \MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\FakeResultWrapper;
+ use Wikimedia\Rdbms\IDatabase;
/**
* Class representing a MediaWiki article and history.
*/
protected $mLinksUpdated = '19700101000000';
- const PURGE_CDN_CACHE = 1; // purge CDN cache for page variant URLs
- const PURGE_CLUSTER_PCACHE = 2; // purge parser cache in the local datacenter
- const PURGE_GLOBAL_PCACHE = 4; // set page_touched to clear parser cache in all datacenters
+ /** @deprecated since 1.29. Added in 1.28 for partial purging, no longer used. */
+ const PURGE_CDN_CACHE = 1;
+ const PURGE_CLUSTER_PCACHE = 2;
+ const PURGE_GLOBAL_PCACHE = 4;
const PURGE_ALL = 7;
/**
/**
* Perform the actions of a page purging
- * @param integer $flags Bitfield of WikiPage::PURGE_* constants
* @return bool
+ * @note In 1.28 (and only 1.28), this took a $flags parameter that
+ * controlled how much purging was done.
*/
- public function doPurge( $flags = self::PURGE_ALL ) {
+ public function doPurge() {
// Avoid PHP 7.1 warning of passing $this by reference
$wikiPage = $this;
return false;
}
- if ( ( $flags & self::PURGE_GLOBAL_PCACHE ) == self::PURGE_GLOBAL_PCACHE ) {
- // Set page_touched in the database to invalidate all DC caches
- $this->mTitle->invalidateCache();
- } elseif ( ( $flags & self::PURGE_CLUSTER_PCACHE ) == self::PURGE_CLUSTER_PCACHE ) {
- // Delete the parser options key in the local cluster to invalidate the DC cache
- ParserCache::singleton()->deleteOptionsKey( $this );
- // Avoid sending HTTP 304s in ViewAction to the client who just issued the purge
- $cache = ObjectCache::getLocalClusterInstance();
- $cache->set(
- $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ),
- wfTimestamp( TS_MW ),
- $cache::TTL_HOUR
- );
- }
+ $this->mTitle->invalidateCache();
- if ( ( $flags & self::PURGE_CDN_CACHE ) == self::PURGE_CDN_CACHE ) {
- // Clear any HTML file cache
- HTMLFileCache::clearFileCache( $this->getTitle() );
- // Send purge after any page_touched above update was committed
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
- DeferredUpdates::PRESEND
- );
- }
+ // Clear file cache
+ HTMLFileCache::clearFileCache( $this->getTitle() );
+ // Send purge after above page_touched update was committed
+ DeferredUpdates::addUpdate(
+ new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
+ DeferredUpdates::PRESEND
+ );
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
$messageCache = MessageCache::singleton();
*
* @return string|bool TS_MW timestamp or false
* @since 1.28
+ * @deprecated since 1.29. It will always return false.
*/
public function getLastPurgeTimestamp() {
- $cache = ObjectCache::getLocalClusterInstance();
-
- return $cache->get( $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ) );
+ wfDeprecated( __METHOD__, '1.29' );
+ return false;
}
/**