From 4d487d19429c6370436b1ab0c4f2cc203a674f0d Mon Sep 17 00:00:00 2001 From: Hashar Date: Wed, 16 Nov 2016 10:35:20 +0000 Subject: [PATCH] Revert "objectcache: detect default getWithSetCallback() set options" Causes HHVM 3.12.7 to segfault and or: Fatal error: Stack overflow in includes/libs/objectcache/BagOStuff.php on line 754 This reverts commit b47ce21cec3a4340dd37c773210a514350f10297. Bug: T150833 Change-Id: Ia52fdf65f5e386c0eaa1046328680fb5c8a9081a --- includes/ServiceWiring.php | 5 +- includes/db/MWLBFactory.php | 19 --- includes/libs/objectcache/WANObjectCache.php | 31 ----- includes/libs/rdbms/database/DBConnRef.php | 8 -- includes/libs/rdbms/database/Database.php | 73 ++--------- includes/libs/rdbms/database/IDatabase.php | 20 --- includes/libs/rdbms/lbfactory/ILBFactory.php | 28 ----- includes/libs/rdbms/lbfactory/LBFactory.php | 42 ------- .../libs/rdbms/loadbalancer/ILoadBalancer.php | 28 ----- .../libs/rdbms/loadbalancer/LoadBalancer.php | 44 +------ .../rdbms/loadbalancer/LoadBalancerSingle.php | 13 -- tests/phpunit/includes/db/LBFactoryTest.php | 119 ++++-------------- .../libs/objectcache/WANObjectCacheTest.php | 31 ----- 13 files changed, 42 insertions(+), 419 deletions(-) diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index beefb33173..c2197a65a0 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -52,10 +52,7 @@ return [ ); $class = MWLBFactory::getLBFactoryClass( $lbConf ); - $instance = new $class( $lbConf ); - MWLBFactory::setCacheUsageCallbacks( $instance, $services ); - - return $instance; + return new $class( $lbConf ); }, 'DBLoadBalancer' => function( MediaWikiServices $services ) { diff --git a/includes/db/MWLBFactory.php b/includes/db/MWLBFactory.php index 5a5c46c0bd..42ef6851f8 100644 --- a/includes/db/MWLBFactory.php +++ b/includes/db/MWLBFactory.php @@ -133,25 +133,6 @@ abstract class MWLBFactory { return $lbConf; } - /** - * @param LBFactory $lbf New LBFactory instance that will be bound to $services - * @param MediaWikiServices $services - */ - public static function setCacheUsageCallbacks( LBFactory $lbf, MediaWikiServices $services ) { - // Account for lag and pending updates by default in cache generator callbacks - $wCache = $services->getMainWANObjectCache(); - $wCache->setDefaultCacheSetOptionCallbacks( - function () use ( $lbf ) { - return $lbf->declareUsageSectionStart(); - }, - function ( $id ) use ( $lbf ) { - $info = $lbf->declareUsageSectionEnd( $id ); - - return $info['cacheSetOptions'] ?: []; - } - ); - } - /** * Returns the LBFactory class to use and the load balancer configuration. * diff --git a/includes/libs/objectcache/WANObjectCache.php b/includes/libs/objectcache/WANObjectCache.php index b9753d3bb2..8d3c6d96e4 100644 --- a/includes/libs/objectcache/WANObjectCache.php +++ b/includes/libs/objectcache/WANObjectCache.php @@ -93,11 +93,6 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { /** @var mixed[] Temporary warm-up cache */ private $warmupCache = []; - /** @var callable Callback used in generating default options in getWithSetCallback() */ - private $sowSetOptsCallback; - /** @var callable Callback used in generating default options in getWithSetCallback() */ - private $reapSetOptsCallback; - /** Max time expected to pass between delete() and DB commit finishing */ const MAX_COMMIT_DELAY = 3; /** Max replication+snapshot lag before applying TTL_LAGGED or disallowing set() */ @@ -186,12 +181,6 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { ? $params['relayers']['purge'] : new EventRelayerNull( [] ); $this->setLogger( isset( $params['logger'] ) ? $params['logger'] : new NullLogger() ); - $this->sowSetOptsCallback = function () { - return null; // no-op - }; - $this->reapSetOptsCallback = function () { - return []; // no-op - }; } public function setLogger( LoggerInterface $logger ) { @@ -1012,9 +1001,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { $setOpts = []; ++$this->callbackDepth; try { - $tag = call_user_func( $this->sowSetOptsCallback ); $value = call_user_func_array( $callback, [ $cValue, &$ttl, &$setOpts, $asOf ] ); - $setOptDefaults = call_user_func( $this->reapSetOptsCallback, $tag ); } finally { --$this->callbackDepth; } @@ -1039,8 +1026,6 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { $setOpts['lockTSE'] = $lockTSE; // Use best known "since" timestamp if not provided $setOpts += [ 'since' => $preCallbackTime ]; - // Use default "lag" and "pending" values if not set - $setOpts += $setOptDefaults; // Update the cache; this will fail if the key is tombstoned $this->set( $key, $value, $ttl, $setOpts ); } @@ -1267,22 +1252,6 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { return (int)min( $maxTTL, max( $minTTL, $factor * $age ) ); } - /** - * Set the callbacks that provide the fallback values for cache set options - * - * The $reap callback returns default values to use for the "lag", "since", and "pending" - * options used by WANObjectCache::set(). It takes the ID from $sow as the sole parameter. - * An empty array should be returned if there is no usage to base the return value on. - * - * @param callable $sow Function that starts recording and returns an ID - * @param callable $reap Function that takes an ID, stops recording, and returns the options - * @since 1.28 - */ - public function setDefaultCacheSetOptionCallbacks( callable $sow, callable $reap ) { - $this->sowSetOptsCallback = $sow; - $this->reapSetOptsCallback = $reap; - } - /** * Do the actual async bus purge of a key * diff --git a/includes/libs/rdbms/database/DBConnRef.php b/includes/libs/rdbms/database/DBConnRef.php index 90da154a6d..20198bf14c 100644 --- a/includes/libs/rdbms/database/DBConnRef.php +++ b/includes/libs/rdbms/database/DBConnRef.php @@ -591,14 +591,6 @@ class DBConnRef implements IDatabase { return $this->__call( __FUNCTION__, func_get_args() ); } - public function declareUsageSectionStart( $id ) { - return $this->__call( __FUNCTION__, func_get_args() ); - } - - public function declareUsageSectionEnd( $id ) { - return $this->__call( __FUNCTION__, func_get_args() ); - } - /** * Clean up the connection when out of scope */ diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index 0bbbb82e27..3d35d76ca3 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -69,8 +69,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware protected $cliMode; /** @var string Agent name for query profiling */ protected $agent; - /** @var array[] Map of (section ID => info map) for usage section IDs */ - protected $usageSectionInfo = []; /** @var BagOStuff APC cache */ protected $srvCache; @@ -920,29 +918,16 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } private function doProfiledQuery( $sql, $commentedSql, $isWrite, $fname ) { - // Update usage information for all active usage tracking sections - foreach ( $this->usageSectionInfo as $id => &$info ) { - if ( $isWrite ) { - ++$info['writeQueries']; - } else { - ++$info['readQueries']; - } - if ( $info['cacheSetOptions'] === null ) { - $info['cacheSetOptions'] = self::getCacheSetOptions( $this ); - } - } - unset( $info ); // destroy any reference - $isMaster = !is_null( $this->getLBInfo( 'master' ) ); - // generalizeSQL() will probably cut down the query to reasonable - // logging size most of the time. The substr is really just a sanity check. + # generalizeSQL() will probably cut down the query to reasonable + # logging size most of the time. The substr is really just a sanity check. if ( $isMaster ) { $queryProf = 'query-m: ' . substr( self::generalizeSQL( $sql ), 0, 255 ); } else { $queryProf = 'query: ' . substr( self::generalizeSQL( $sql ), 0, 255 ); } - // Include query transaction state + # Include query transaction state $queryProf .= $this->mTrxShortId ? " [TRX#{$this->mTrxShortId}]" : ""; $startTime = microtime( true ); @@ -3038,33 +3023,20 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * @since 1.27 */ public static function getCacheSetOptions( IDatabase $db1 ) { - $opts = [ 'lag' => 0, 'since' => INF, 'pending' => false ]; + $res = [ 'lag' => 0, 'since' => INF, 'pending' => false ]; foreach ( func_get_args() as $db ) { /** @var IDatabase $db */ - $dbOpts = $db->getSessionLagStatus(); - $dbOpts['pending'] = $db->writesPending(); - $opts = self::mergeCacheSetOptions( $opts, $dbOpts ); - } - - return $opts; - } - - /** - * @param array $base Map in the format of getCacheSetOptions() results - * @param array $other Map in the format of getCacheSetOptions() results - * @return array Pessimistically merged result of $base/$other in the format of $base - * @since 1.28 - */ - public static function mergeCacheSetOptions( array $base, array $other ) { - if ( $other['lag'] === false ) { - $base['lag'] = false; - } elseif ( $base['lag'] !== false ) { - $base['lag'] = max( $base['lag'], $other['lag'] ); + $status = $db->getSessionLagStatus(); + if ( $status['lag'] === false ) { + $res['lag'] = false; + } elseif ( $res['lag'] !== false ) { + $res['lag'] = max( $res['lag'], $status['lag'] ); + } + $res['since'] = min( $res['since'], $status['since'] ); + $res['pending'] = $res['pending'] ?: $db->writesPending(); } - $base['since'] = min( $base['since'], $other['since'] ); - $base['pending'] = $base['pending'] ?: $other['pending']; - return $base; + return $res; } public function getLag() { @@ -3411,25 +3383,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->tableAliases = $aliases; } - public function declareUsageSectionStart( $id ) { - $this->usageSectionInfo[$id] = [ - 'readQueries' => 0, - 'writeQueries' => 0, - 'cacheSetOptions' => null - ]; - } - - public function declareUsageSectionEnd( $id ) { - if ( !isset( $this->usageSectionInfo[$id] ) ) { - throw new InvalidArgumentException( "No section with ID '$id'" ); - } - - $info = $this->usageSectionInfo[$id]; - unset( $this->usageSectionInfo[$id] ); - - return $info; - } - /** * @return bool Whether a DB user is required to access the DB * @since 1.28 diff --git a/includes/libs/rdbms/database/IDatabase.php b/includes/libs/rdbms/database/IDatabase.php index 761b6edb2e..48d76c4023 100644 --- a/includes/libs/rdbms/database/IDatabase.php +++ b/includes/libs/rdbms/database/IDatabase.php @@ -1792,24 +1792,4 @@ interface IDatabase { * @since 1.28 */ public function setTableAliases( array $aliases ); - - /** - * Mark the beginning of a new section to track database usage information for - * - * @param string|integer Section ID - */ - public function declareUsageSectionStart( $id ); - - /** - * End a section started by declareUsageSectionStart() and return the information map - * - * The map includes information about activity during the section: - * - readQueries: number of read queries issued. - * - writeQueries: number of write queries issued. - * - cacheSetOptions: result of getCacheSetOptions() before the first query. - * This is null if no actual queries took place in the section interval. - * @param integer|string $id Section ID passed to declareUsageSectionStart() earlier - * @return array - */ - public function declareUsageSectionEnd( $id ); } diff --git a/includes/libs/rdbms/lbfactory/ILBFactory.php b/includes/libs/rdbms/lbfactory/ILBFactory.php index f0d39954f9..5288c24908 100644 --- a/includes/libs/rdbms/lbfactory/ILBFactory.php +++ b/includes/libs/rdbms/lbfactory/ILBFactory.php @@ -310,32 +310,4 @@ interface ILBFactory { * - ChronologyProtection : cookie/header value specifying ChronologyProtector usage */ public function setRequestInfo( array $info ); - - /** - * Mark the beginning of a new section to track database usage information for - * - * This returns an ID which can be passed to declareUsageSectionEnd() to indicate - * the end of the section. If $id is provided, the returned ID equals $id. - * @param string|integer Section ID to use instead of auto-generated ID [optional] - * @return string|integer - */ - public function declareUsageSectionStart( $id = null ); - - /** - * End a section started by declareUsageSectionStart() and return the information map - * - * The map includes information about activity during the section: - * - readQueries: number of read queries issued. - * - writeQueries: number of write queries issued. - * - cacheSetOptions: result of pessimistically merging the result of getCacheSetOptions() - * on each DB handle before the first query of the respective handle. This is null if - * no actual queries took place in the section interval. - * - * This can be called before cache value generation functions commence queries - * and then passed the caching storage layer to detect and avoid lag race conditions. - * - * @param integer|string $id Section ID passed to declareUsageSectionStart() earlier - * @return array - */ - public function declareUsageSectionEnd( $id ); } diff --git a/includes/libs/rdbms/lbfactory/LBFactory.php b/includes/libs/rdbms/lbfactory/LBFactory.php index 70302a0177..15a5c0d78f 100644 --- a/includes/libs/rdbms/lbfactory/LBFactory.php +++ b/includes/libs/rdbms/lbfactory/LBFactory.php @@ -59,9 +59,6 @@ abstract class LBFactory implements ILBFactory { /** @var array Web request information about the client */ protected $requestInfo; - /** @var bool[] Map of (section ID => true) for usage section IDs */ - protected $usageSections = []; - /** @var mixed */ protected $ticket; /** @var string|bool String if a requested DBO_TRX transaction round is active */ @@ -506,17 +503,12 @@ abstract class LBFactory implements ILBFactory { } /** - * Method called whenever a new LoadBalancer is created - * * @param ILoadBalancer $lb */ protected function initLoadBalancer( ILoadBalancer $lb ) { if ( $this->trxRoundId !== false ) { $lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX } - foreach ( $this->usageSections as $id => $unused ) { - $lb->declareUsageSectionStart( $id ); - } } public function setDomainPrefix( $prefix ) { @@ -556,40 +548,6 @@ abstract class LBFactory implements ILBFactory { $this->requestInfo = $info + $this->requestInfo; } - public function declareUsageSectionStart( $id = null ) { - static $nextId = 1; - if ( $id === null ) { - $id = $nextId; - ++$nextId; - } - // Handle existing load balancers - $this->forEachLB( function ( ILoadBalancer $lb ) use ( $id ) { - $lb->declareUsageSectionStart( $id ); - } ); - // Remember to set this for new load balancers - $this->usageSections[$id] = true; - - return $id; - } - - public function declareUsageSectionEnd( $id ) { - $info = [ 'readQueries' => 0, 'writeQueries' => 0, 'cacheSetOptions' => null ]; - $this->forEachLB( function ( ILoadBalancer $lb ) use ( $id, &$info ) { - $lbInfo = $lb->declareUsageSectionEnd( $id ); - $info['readQueries'] += $lbInfo['readQueries']; - $info['writeQueries'] += $lbInfo['writeQueries']; - $dbCacheOpts = $lbInfo['cacheSetOptions']; - if ( $dbCacheOpts ) { - $info['cacheSetOptions'] = $info['cacheSetOptions'] - ? Database::mergeCacheSetOptions( $info['cacheSetOptions'], $dbCacheOpts ) - : $dbCacheOpts; - } - } ); - unset( $this->usageSections[$id] ); - - return $info; - } - /** * Make PHP ignore user aborts/disconnects until the returned * value leaves scope. This returns null and does nothing in CLI mode. diff --git a/includes/libs/rdbms/loadbalancer/ILoadBalancer.php b/includes/libs/rdbms/loadbalancer/ILoadBalancer.php index 65b18e711a..8854479a63 100644 --- a/includes/libs/rdbms/loadbalancer/ILoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/ILoadBalancer.php @@ -549,32 +549,4 @@ interface ILoadBalancer { * @param array[] $aliases Map of (table => (dbname, schema, prefix) map) */ public function setTableAliases( array $aliases ); - - /** - * Mark the beginning of a new section to track database usage information for - * - * This returns an ID which can be passed to declareUsageSectionEnd() to indicate - * the end of the section. If $id is provided, the returned ID equals $id. - * @param string|integer Section ID to use instead of auto-generated ID [optional] - * @return string|integer - */ - public function declareUsageSectionStart( $id = null ); - - /** - * End a section started by declareUsageSectionStart() and return the information map - * - * The map includes information about activity during the section: - * - readQueries: number of read queries issued. - * - writeQueries: number of write queries issued. - * - cacheSetOptions: result of pessimistically merging the result of getCacheSetOptions() - * on each DB handle before the first query of the respective handle. This is null if - * no actual queries took place in the section interval. - * - * This can be called before cache value generation functions commence queries - * and then passed the caching storage layer to detect and avoid lag race conditions. - * - * @param integer|string $id Section ID passed to declareUsageSectionStart() earlier - * @return array - */ - public function declareUsageSectionEnd( $id ); } diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancer.php b/includes/libs/rdbms/loadbalancer/LoadBalancer.php index 61359bc3bc..d42fed9590 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancer.php @@ -94,11 +94,9 @@ class LoadBalancer implements ILoadBalancer { /** @var string Current server name */ private $host; /** @var bool Whether this PHP instance is for a CLI script */ - private $cliMode; + protected $cliMode; /** @var string Agent name for query profiling */ - private $agent; - /** @var bool[] Map of (section ID => true) for usage section IDs */ - private $usageSections = []; + protected $agent; /** @var callable Exception logger */ private $errorLogger; @@ -866,10 +864,6 @@ class LoadBalancer implements ILoadBalancer { } } - foreach ( $this->usageSections as $id => $unused ) { - $db->declareUsageSectionStart( $id ); - } - return $db; } @@ -1528,40 +1522,6 @@ class LoadBalancer implements ILoadBalancer { } ); } - public function declareUsageSectionStart( $id = null ) { - static $nextId = 1; - if ( $id === null ) { - $id = $nextId; - ++$nextId; - } - // Handle existing connections - $this->forEachOpenConnection( function ( IDatabase $db ) use ( $id ) { - $db->declareUsageSectionStart( $id ); - } ); - // Remember to set this for new connections - $this->usageSections[$id] = true; - - return $id; - } - - public function declareUsageSectionEnd( $id ) { - $info = [ 'readQueries' => 0, 'writeQueries' => 0, 'cacheSetOptions' => null ]; - $this->forEachOpenConnection( function ( IDatabase $db ) use ( $id, &$info ) { - $dbInfo = $db->declareUsageSectionEnd( $id ); - $info['readQueries'] += $dbInfo['readQueries']; - $info['writeQueries'] += $dbInfo['writeQueries']; - $dbCacheOpts = $dbInfo['cacheSetOptions']; - if ( $dbCacheOpts ) { - $info['cacheSetOptions'] = $info['cacheSetOptions'] - ? Database::mergeCacheSetOptions( $info['cacheSetOptions'], $dbCacheOpts ) - : $dbCacheOpts; - } - } ); - unset( $this->usageSections[$id] ); - - return $info; - } - /** * Make PHP ignore user aborts/disconnects until the returned * value leaves scope. This returns null and does nothing in CLI mode. diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php b/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php index 707db0a8ac..0a05202504 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php @@ -71,17 +71,4 @@ class LoadBalancerSingle extends LoadBalancer { protected function reallyOpenConnection( array $server, $dbNameOverride = false ) { return $this->db; } - - public function forEachOpenConnection( $callback, array $params = [] ) { - $mergedParams = array_merge( [ $this->db ], $params ); - call_user_func_array( $callback, $mergedParams ); - } - - public function forEachOpenMasterConnection( $callback, array $params = [] ) { - return $this->forEachOpenConnection( $callback, $params ); - } - - public function forEachOpenReplicaConnection( $callback, array $params = [] ) { - return $this->forEachOpenConnection( $callback, $params ); - } } diff --git a/tests/phpunit/includes/db/LBFactoryTest.php b/tests/phpunit/includes/db/LBFactoryTest.php index 13c5e1e49e..d8773f8ad2 100644 --- a/tests/phpunit/includes/db/LBFactoryTest.php +++ b/tests/phpunit/includes/db/LBFactoryTest.php @@ -240,6 +240,32 @@ class LBFactoryTest extends MediaWikiTestCase { $cp->shutdown(); } + private function newLBFactoryMulti( array $baseOverride = [], array $serverOverride = [] ) { + global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgSQLiteDataDir; + + return new LBFactoryMulti( $baseOverride + [ + 'sectionsByDB' => [], + 'sectionLoads' => [ + 'DEFAULT' => [ + 'test-db1' => 1, + ], + ], + 'serverTemplate' => $serverOverride + [ + 'dbname' => $wgDBname, + 'user' => $wgDBuser, + 'password' => $wgDBpassword, + 'type' => $wgDBtype, + 'dbDirectory' => $wgSQLiteDataDir, + 'flags' => DBO_DEFAULT + ], + 'hostsByName' => [ + 'test-db1' => $wgDBserver, + ], + 'loadMonitorClass' => 'LoadMonitorNull', + 'localDomain' => wfWikiID() + ] ); + } + public function testNiceDomains() { global $wgDBname, $wgDBtype; @@ -388,99 +414,6 @@ class LBFactoryTest extends MediaWikiTestCase { $factory->destroy(); } - /** - * @covers LBFactory::declareUsageSectionStart() - * @covers LBFactory::declareUsageSectionEnd() - * @covers LoadBalancer::declareUsageSectionStart() - * @covers LoadBalancer::declareUsageSectionEnd() - */ - public function testUsageInfo() { - $wallTime = microtime( true ); - - $mockDB = $this->getMockBuilder( 'DatabaseMysql' ) - ->disableOriginalConstructor() - ->setMethods( [ - 'doQuery', - 'affectedRows', - 'getLag', - 'assertOpen', - 'getSessionLagStatus', - 'getApproximateLagStatus' - ] ) - ->getMock(); - $mockDB->method( 'doQuery' )->willReturn( new FakeResultWrapper( [] ) ); - $mockDB->method( 'affectedRows' )->willReturn( 0 ); - $mockDB->method( 'getLag' )->willReturn( 3 ); - $mockDB->method( 'getSessionLagStatus' )->willReturn( [ - 'lag' => 3, 'since' => $wallTime - ] ); - $mockDB->method( 'getApproximateLagStatus' )->willReturn( [ - 'lag' => 3, 'since' => $wallTime - ] ); - $mockDBProbe = TestingAccessWrapper::newFromObject( $mockDB ); - $mockDBProbe->profiler = new ProfilerStub( [] ); - $mockDBProbe->trxProfiler = new TransactionProfiler(); - $mockDBProbe->connLogger = new \Psr\Log\NullLogger(); - $mockDBProbe->queryLogger = new \Psr\Log\NullLogger(); - $lbFactory = new LBFactorySingle( [ - 'connection' => $mockDB - ] ); - $mockDB->setLBInfo( 'replica', true ); - - $id = $lbFactory->declareUsageSectionStart( 'test' ); - $mockDB->query( "SELECT 1" ); - $mockDB->query( "SELECT 1" ); - $mockDB->query( "SELECT 1" ); - $info = $lbFactory->declareUsageSectionEnd( $id ); - - $this->assertEquals( 3, $info['readQueries'] ); - $this->assertEquals( 0, $info['writeQueries'] ); - $this->assertEquals( false, $info['cacheSetOptions']['pending'] ); - $this->assertEquals( 3, $info['cacheSetOptions']['lag'] ); - $this->assertGreaterThanOrEqual( $wallTime - 10, $info['cacheSetOptions']['since'] ); - $this->assertLessThan( $wallTime + 10, $info['cacheSetOptions']['since'] ); - - $mockDB->begin(); - $mockDB->query( "UPDATE x SET y=1" ); - $id = $lbFactory->declareUsageSectionStart( 'k' ); - $mockDB->query( "UPDATE x SET y=2" ); - $mockDB->commit(); - $info = $lbFactory->declareUsageSectionEnd( $id ); - - $this->assertEquals( 2, $info['readQueries'] ); // +1 for ping() - $this->assertEquals( 1, $info['writeQueries'] ); - $this->assertEquals( true, $info['cacheSetOptions']['pending'] ); - $this->assertEquals( 3, $info['cacheSetOptions']['lag'] ); - $this->assertGreaterThanOrEqual( $wallTime - 10, $info['cacheSetOptions']['since'] ); - $this->assertLessThan( $wallTime + 10, $info['cacheSetOptions']['since'] ); - } - - private function newLBFactoryMulti( array $baseOverride = [], array $serverOverride = [] ) { - global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgSQLiteDataDir; - - return new LBFactoryMulti( $baseOverride + [ - 'sectionsByDB' => [], - 'sectionLoads' => [ - 'DEFAULT' => [ - 'test-db1' => 1, - ], - ], - 'serverTemplate' => $serverOverride + [ - 'dbname' => $wgDBname, - 'user' => $wgDBuser, - 'password' => $wgDBpassword, - 'type' => $wgDBtype, - 'dbDirectory' => $wgSQLiteDataDir, - 'flags' => DBO_DEFAULT - ], - 'hostsByName' => [ - 'test-db1' => $wgDBserver, - ], - 'loadMonitorClass' => 'LoadMonitorNull', - 'localDomain' => wfWikiID() - ] ); - } - private function quoteTable( Database $db, $table ) { if ( $db->getType() === 'sqlite' ) { return $table; diff --git a/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php b/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php index e456328821..aa46c966ad 100644 --- a/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php +++ b/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php @@ -960,35 +960,4 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase { [ null, 86400, 800, .2, 800 ] ]; } - - public function testDefaultCacheOptions() { - $wCache = clone $this->cache; - $key = wfRandomString(); - - $called = false; - $infos = []; - $wCache->setDefaultCacheSetOptionCallbacks( - function () use ( &$infos ) { - $infos['sometag'] = [ 'since' => 1999, 'lag' => 4, 'pending' => false ]; - - return 'sometag'; - }, - function ( $tag ) use ( &$infos, &$called ) { - $res = $infos[$tag]; - unset( $infos[$tag] ); - $called = true; - - return $res; - } - ); - - $callback = function () { - return 42; - }; - - $value = $wCache->getWithSetCallback( $key, 5, $callback ); - - $this->assertEquals( 42, $value, 'Correct value' ); - $this->assertTrue( $called, 'Options callback ran' ); - } } -- 2.20.1