From: Aaron Schulz Date: Sun, 11 Feb 2018 19:04:20 +0000 (-0800) Subject: Various cleanup to SiteStats classes X-Git-Tag: 1.31.0-rc.0~623 X-Git-Url: http://git.heureux-cyclage.org/?a=commitdiff_plain;h=6094897687ccbab72131b3c742995f45fb377588;p=lhc%2Fweb%2Fwiklou.git Various cleanup to SiteStats classes * Mark method visibility * Remove unused code/methods * Use WAN cache process cache in pagesInNs() * Remove "m" prefix from SiteStatsInit fields * Avoid use of $wg variables Change-Id: Iab4001f02c9b2e8667ca4bac033fd4f6ef272148 --- diff --git a/includes/SiteStats.php b/includes/SiteStats.php index 0346f23a70..7b2b8d38e2 100644 --- a/includes/SiteStats.php +++ b/includes/SiteStats.php @@ -23,60 +23,47 @@ use Wikimedia\Rdbms\Database; use Wikimedia\Rdbms\IDatabase; use MediaWiki\MediaWikiServices; +use Wikimedia\Rdbms\LoadBalancer; /** * Static accessor class for site_stats and related things */ class SiteStats { - /** @var bool|stdClass */ + /** @var stdClass */ private static $row; - /** @var bool */ - private static $loaded = false; - /** @var int[] */ - private static $pageCount = []; - - static function unload() { - self::$loaded = false; - } - - static function recache() { - self::load( true ); - } - /** - * @param bool $recache + * Trigger a reload next time a field is accessed */ - static function load( $recache = false ) { - if ( self::$loaded && !$recache ) { - return; - } - - self::$row = self::loadAndLazyInit(); + public static function unload() { + self::$row = null; + } - self::$loaded = true; + protected static function load() { + if ( self::$row === null ) { + self::$row = self::loadAndLazyInit(); + } } /** - * @return bool|stdClass + * @return stdClass */ - static function loadAndLazyInit() { - global $wgMiserMode; + protected static function loadAndLazyInit() { + $config = MediaWikiServices::getInstance()->getMainConfig(); + $lb = self::getLB(); + $dbr = $lb->getConnection( DB_REPLICA ); wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" ); - $row = self::doLoad( wfGetDB( DB_REPLICA ) ); + $row = self::doLoadFromDB( $dbr ); - if ( !self::isSane( $row ) ) { - $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); - if ( $lb->hasOrMadeRecentMasterChanges() ) { - // Might have just been initialized during this request? Underflow? - wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" ); - $row = self::doLoad( wfGetDB( DB_MASTER ) ); - } + if ( !self::isSane( $row ) && $lb->hasOrMadeRecentMasterChanges() ) { + // Might have just been initialized during this request? Underflow? + wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" ); + $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) ); } if ( !self::isSane( $row ) ) { - if ( $wgMiserMode ) { + if ( $config->get( 'MiserMode' ) ) { // Start off with all zeroes, assuming that this is a new wiki or any // repopulations where done manually via script. SiteStatsInit::doPlaceholderInit(); @@ -86,14 +73,15 @@ class SiteStats { // broken, however, for instance when importing from a dump into a // clean schema with mwdumper. wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" ); - SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) ); + SiteStatsInit::doAllAndCommit( $dbr ); } - $row = self::doLoad( wfGetDB( DB_MASTER ) ); + $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) ); } if ( !self::isSane( $row ) ) { wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" ); + // Always return a row-like object $row = (object)array_fill_keys( self::selectFields(), 0 ); } @@ -102,9 +90,9 @@ class SiteStats { /** * @param IDatabase $db - * @return bool|stdClass + * @return stdClass|bool */ - static function doLoad( $db ) { + private static function doLoadFromDB( IDatabase $db ) { return $db->selectRow( 'site_stats', self::selectFields(), @@ -114,63 +102,56 @@ class SiteStats { } /** - * Return the total number of page views. Except we don't track those anymore. - * Stop calling this function, it will be removed some time in the future. It's - * kept here simply to prevent fatal errors. - * - * @deprecated since 1.25 * @return int */ - static function views() { - wfDeprecated( __METHOD__, '1.25' ); - return 0; - } - - /** - * @return int - */ - static function edits() { + public static function edits() { self::load(); + return self::$row->ss_total_edits; } /** * @return int */ - static function articles() { + public static function articles() { self::load(); + return self::$row->ss_good_articles; } /** * @return int */ - static function pages() { + public static function pages() { self::load(); + return self::$row->ss_total_pages; } /** * @return int */ - static function users() { + public static function users() { self::load(); + return self::$row->ss_users; } /** * @return int */ - static function activeUsers() { + public static function activeUsers() { self::load(); + return self::$row->ss_active_users; } /** * @return int */ - static function images() { + public static function images() { self::load(); + return self::$row->ss_images; } @@ -179,17 +160,17 @@ class SiteStats { * @param string $group Name of group * @return int */ - static function numberingroup( $group ) { + public static function numberingroup( $group ) { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + return $cache->getWithSetCallback( $cache->makeKey( 'SiteStats', 'groupcounts', $group ), $cache::TTL_HOUR, function ( $oldValue, &$ttl, array &$setOpts ) use ( $group ) { - $dbr = wfGetDB( DB_REPLICA ); - + $dbr = self::getLB()->getConnection( DB_REPLICA ); $setOpts += Database::getCacheSetOptions( $dbr ); - return $dbr->selectField( + return (int)$dbr->selectField( 'user_groups', 'COUNT(*)', [ @@ -207,8 +188,9 @@ class SiteStats { * Total number of jobs in the job queue. * @return int */ - static function jobs() { + public static function jobs() { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + return $cache->getWithSetCallback( $cache->makeKey( 'SiteStats', 'jobscount' ), $cache::TTL_MINUTE, @@ -226,20 +208,27 @@ class SiteStats { /** * @param int $ns - * * @return int */ - static function pagesInNs( $ns ) { - if ( !isset( self::$pageCount[$ns] ) ) { - $dbr = wfGetDB( DB_REPLICA ); - self::$pageCount[$ns] = (int)$dbr->selectField( - 'page', - 'COUNT(*)', - [ 'page_namespace' => $ns ], - __METHOD__ - ); - } - return self::$pageCount[$ns]; + public static function pagesInNs( $ns ) { + $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + + return $cache->getWithSetCallback( + $cache->makeKey( 'SiteStats', 'page-in-namespace', $ns ), + $cache::TTL_HOUR, + function ( $oldValue, &$ttl, array &$setOpts ) use ( $ns ) { + $dbr = self::getLB()->getConnection( DB_REPLICA ); + $setOpts += Database::getCacheSetOptions( $dbr ); + + return (int)$dbr->selectField( + 'page', + 'COUNT(*)', + [ 'page_namespace' => $ns ], + __METHOD__ + ); + }, + [ 'pcTTL' => $cache::TTL_PROC_LONG ] + ); } /** @@ -283,6 +272,14 @@ class SiteStats { return false; } } + return true; } + + /** + * @return LoadBalancer + */ + private static function getLB() { + return MediaWikiServices::getInstance()->getDBLoadBalancer(); + } } diff --git a/includes/SiteStatsInit.php b/includes/SiteStatsInit.php index 775963f642..f8886909a9 100644 --- a/includes/SiteStatsInit.php +++ b/includes/SiteStatsInit.php @@ -18,18 +18,24 @@ * @file */ use Wikimedia\Rdbms\IDatabase; +use MediaWiki\MediaWikiServices; /** * Class designed for counting of stats. */ class SiteStatsInit { - - // Database connection - private $db; - - // Various stats - private $mEdits = null, $mArticles = null, $mPages = null; - private $mUsers = null, $mFiles = null; + /* @var IDatabase */ + private $dbr; + /** @var int */ + private $edits; + /** @var int */ + private $articles; + /** @var int */ + private $pages; + /** @var int */ + private $users; + /** @var int */ + private $files; /** * @param bool|IDatabase $database @@ -38,11 +44,11 @@ class SiteStatsInit { */ public function __construct( $database = false ) { if ( $database instanceof IDatabase ) { - $this->db = $database; + $this->dbr = $database; } elseif ( $database ) { - $this->db = wfGetDB( DB_MASTER ); + $this->dbr = self::getDB( DB_MASTER ); } else { - $this->db = wfGetDB( DB_REPLICA, 'vslow' ); + $this->dbr = self::getDB( DB_REPLICA, 'vslow' ); } } @@ -51,9 +57,10 @@ class SiteStatsInit { * @return int */ public function edits() { - $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ ); - $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ ); - return $this->mEdits; + $this->edits = $this->dbr->selectField( 'revision', 'COUNT(*)', '', __METHOD__ ); + $this->edits += $this->dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ ); + + return $this->edits; } /** @@ -61,7 +68,7 @@ class SiteStatsInit { * @return int */ public function articles() { - global $wgArticleCountMethod; + $config = MediaWikiServices::getInstance()->getMainConfig(); $tables = [ 'page' ]; $conds = [ @@ -69,10 +76,10 @@ class SiteStatsInit { 'page_is_redirect' => 0, ]; - if ( $wgArticleCountMethod == 'link' ) { + if ( $config->get( 'ArticleCountMethod' ) == 'link' ) { $tables[] = 'pagelinks'; $conds[] = 'pl_from=page_id'; - } elseif ( $wgArticleCountMethod == 'comma' ) { + } elseif ( $config->get( 'ArticleCountMethod' ) == 'comma' ) { // To make a correct check for this, we would need, for each page, // to load the text, maybe uncompress it, maybe decode it and then // check if there's one comma. @@ -81,9 +88,14 @@ class SiteStatsInit { $conds[] = 'page_len > 0'; } - $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)', - $conds, __METHOD__ ); - return $this->mArticles; + $this->articles = $this->dbr->selectField( + $tables, + 'COUNT(DISTINCT page_id)', + $conds, + __METHOD__ + ); + + return $this->articles; } /** @@ -91,8 +103,9 @@ class SiteStatsInit { * @return int */ public function pages() { - $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ ); - return $this->mPages; + $this->pages = $this->dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ ); + + return $this->pages; } /** @@ -100,8 +113,9 @@ class SiteStatsInit { * @return int */ public function users() { - $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ ); - return $this->mUsers; + $this->users = $this->dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ ); + + return $this->users; } /** @@ -109,8 +123,9 @@ class SiteStatsInit { * @return int */ public function files() { - $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ ); - return $this->mFiles; + $this->files = $this->dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ ); + + return $this->files; } /** @@ -127,7 +142,7 @@ class SiteStatsInit { $options += [ 'update' => false, 'activeUsers' => false ]; // Grab the object and count everything - $counter = new SiteStatsInit( $database ); + $counter = new self( $database ); $counter->edits(); $counter->articles(); @@ -139,7 +154,7 @@ class SiteStatsInit { // Count active users if need be if ( $options['activeUsers'] ) { - SiteStatsUpdate::cacheUpdate( wfGetDB( DB_MASTER ) ); + SiteStatsUpdate::cacheUpdate( self::getDB( DB_MASTER ) ); } } @@ -147,7 +162,7 @@ class SiteStatsInit { * Insert a dummy row with all zeroes if no row is present */ public static function doPlaceholderInit() { - $dbw = wfGetDB( DB_MASTER ); + $dbw = self::getDB( DB_MASTER ); $exists = $dbw->selectField( 'site_stats', '1', [ 'ss_row_id' => 1 ], __METHOD__ ); if ( $exists === false ) { $dbw->insert( @@ -165,14 +180,27 @@ class SiteStatsInit { public function refresh() { $values = [ 'ss_row_id' => 1, - 'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ), - 'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ), - 'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ), - 'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ), - 'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ), + 'ss_total_edits' => $this->edits === null ? $this->edits() : $this->edits, + 'ss_good_articles' => $this->articles === null ? $this->articles() : $this->articles, + 'ss_total_pages' => $this->pages === null ? $this->pages() : $this->pages, + 'ss_users' => $this->users === null ? $this->users() : $this->users, + 'ss_images' => $this->files === null ? $this->files() : $this->files, ]; - $dbw = wfGetDB( DB_MASTER ); - $dbw->upsert( 'site_stats', $values, [ 'ss_row_id' ], $values, __METHOD__ ); + self::getDB( DB_MASTER )->upsert( + 'site_stats', + $values, + [ 'ss_row_id' ], + $values, + __METHOD__ + ); + } + + /** + * @param int $index + * @return IDatabase + */ + private static function getDB( $index ) { + return MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( $index ); } } diff --git a/includes/deferred/SiteStatsUpdate.php b/includes/deferred/SiteStatsUpdate.php index 44876a68ef..ad1f172460 100644 --- a/includes/deferred/SiteStatsUpdate.php +++ b/includes/deferred/SiteStatsUpdate.php @@ -25,6 +25,8 @@ use Wikimedia\Rdbms\IDatabase; * Class for handling updates to the site_stats table */ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { + /** @var BagOStuff */ + protected $stash; /** @var int */ protected $edits = 0; /** @var int */ @@ -44,6 +46,8 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { $this->articles = $good; $this->pages = $pages; $this->users = $users; + + $this->stash = MediaWikiServices::getInstance()->getMainObjectStash(); } public function merge( MergeableUpdate $update ) { @@ -72,11 +76,9 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { } public function doUpdate() { - global $wgSiteStatsAsyncFactor; - $this->doUpdateContextStats(); - $rate = $wgSiteStatsAsyncFactor; // convenience + $rate = MediaWikiServices::getInstance()->getMainConfig()->get( 'SiteStatsAsyncFactor' ); // If set to do so, only do actual DB updates 1 every $rate times. // The other times, just update "pending delta" values in memcached. if ( $rate && ( $rate < 0 || mt_rand( 0, $rate - 1 ) != 0 ) ) { @@ -91,12 +93,13 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { * Do not call this outside of SiteStatsUpdate */ public function tryDBUpdateInternal() { - global $wgSiteStatsAsyncFactor; + $services = MediaWikiServices::getInstance(); + $config = $services->getMainConfig(); - $dbw = wfGetDB( DB_MASTER ); - $lockKey = wfWikiID() . ':site_stats'; // prepend wiki ID + $dbw = $services->getDBLoadBalancer()->getConnection( DB_MASTER ); + $lockKey = $dbw->getDomainID() . ':site_stats'; // prepend wiki ID $pd = []; - if ( $wgSiteStatsAsyncFactor ) { + if ( $config->get( 'SiteStatsAsyncFactor' ) ) { // Lock the table so we don't have double DB/memcached updates if ( !$dbw->lockIsFree( $lockKey, __METHOD__ ) || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout @@ -125,7 +128,7 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { $dbw->update( 'site_stats', [ $updates ], [], __METHOD__ ); } - if ( $wgSiteStatsAsyncFactor ) { + if ( $config->get( 'SiteStatsAsyncFactor' ) ) { // Decrement the async deltas now that we applied them $this->removePendingDeltas( $pd ); // Commit the updates and unlock the table @@ -140,9 +143,11 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { * @param IDatabase $dbw * @return bool|mixed */ - public static function cacheUpdate( $dbw ) { - global $wgActiveUserDays; - $dbr = wfGetDB( DB_REPLICA, 'vslow' ); + public static function cacheUpdate( IDatabase $dbw ) { + $services = MediaWikiServices::getInstance(); + $config = $services->getMainConfig(); + + $dbr = $services->getDBLoadBalancer()->getConnection( DB_REPLICA, 'vslow' ); # Get non-bot users than did some recent action other than making accounts. # If account creation is included, the number gets inflated ~20+ fold on enwiki. $activeUsers = $dbr->selectField( @@ -153,8 +158,8 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { 'rc_user != 0', 'rc_bot' => 0, 'rc_log_type != ' . $dbr->addQuotes( 'newusers' ) . ' OR rc_log_type IS NULL', - 'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX ) - - $wgActiveUserDays * 24 * 3600 ) ), + 'rc_timestamp >= ' . $dbr->addQuotes( + $dbr->timestamp( time() - $config->get( 'ActiveUserDays' ) * 24 * 3600 ) ), ], __METHOD__ ); @@ -208,13 +213,13 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { } /** - * @param BagOStuff $cache + * @param BagOStuff $stash * @param string $type * @param string $sign ('+' or '-') * @return string */ - private function getTypeCacheKey( BagOStuff $cache, $type, $sign ) { - return $cache->makeKey( 'sitestatsupdate', 'pendingdelta', $type, $sign ); + private function getTypeCacheKey( BagOStuff $stash, $type, $sign ) { + return $stash->makeKey( 'sitestatsupdate', 'pendingdelta', $type, $sign ); } /** @@ -224,15 +229,14 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { * @param int $delta Delta (positive or negative) */ protected function adjustPending( $type, $delta ) { - $cache = MediaWikiServices::getInstance()->getMainObjectStash(); if ( $delta < 0 ) { // decrement - $key = $this->getTypeCacheKey( $cache, $type, '-' ); + $key = $this->getTypeCacheKey( $this->stash, $type, '-' ); } else { // increment - $key = $this->getTypeCacheKey( $cache, $type, '+' ); + $key = $this->getTypeCacheKey( $this->stash, $type, '+' ); } $magnitude = abs( $delta ); - $cache->incrWithInit( $key, 0, $magnitude, $magnitude ); + $this->stash->incrWithInit( $key, 0, $magnitude, $magnitude ); } /** @@ -240,16 +244,20 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { * @return array Positive and negative deltas for each type */ protected function getPendingDeltas() { - $cache = MediaWikiServices::getInstance()->getMainObjectStash(); - $pending = []; foreach ( [ 'ss_total_edits', 'ss_good_articles', 'ss_total_pages', 'ss_users', 'ss_images' ] as $type ) { // Get pending increments and pending decrements $flg = BagOStuff::READ_LATEST; - $pending[$type]['+'] = (int)$cache->get( $this->getTypeCacheKey( $cache, $type, '+' ), $flg ); - $pending[$type]['-'] = (int)$cache->get( $this->getTypeCacheKey( $cache, $type, '-' ), $flg ); + $pending[$type]['+'] = (int)$this->stash->get( + $this->getTypeCacheKey( $this->stash, $type, '+' ), + $flg + ); + $pending[$type]['-'] = (int)$this->stash->get( + $this->getTypeCacheKey( $this->stash, $type, '-' ), + $flg + ); } return $pending; @@ -260,12 +268,11 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate { * @param array $pd Result of getPendingDeltas(), used for DB update */ protected function removePendingDeltas( array $pd ) { - $cache = MediaWikiServices::getInstance()->getMainObjectStash(); - foreach ( $pd as $type => $deltas ) { foreach ( $deltas as $sign => $magnitude ) { // Lower the pending counter now that we applied these changes - $cache->decr( $this->getTypeCacheKey( $cache, $type, $sign ), $magnitude ); + $key = $this->getTypeCacheKey( $this->stash, $type, $sign ); + $this->stash->decr( $key, $magnitude ); } } }