[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * http://www.gnu.org/copyleft/gpl.html 17 * 18 * @file 19 */ 20 21 /** 22 * Class for handling updates to the site_stats table 23 */ 24 class SiteStatsUpdate implements DeferrableUpdate { 25 /** @var int */ 26 protected $views = 0; 27 28 /** @var int */ 29 protected $edits = 0; 30 31 /** @var int */ 32 protected $pages = 0; 33 34 /** @var int */ 35 protected $articles = 0; 36 37 /** @var int */ 38 protected $users = 0; 39 40 /** @var int */ 41 protected $images = 0; 42 43 // @todo deprecate this constructor 44 function __construct( $views, $edits, $good, $pages = 0, $users = 0 ) { 45 $this->views = $views; 46 $this->edits = $edits; 47 $this->articles = $good; 48 $this->pages = $pages; 49 $this->users = $users; 50 } 51 52 /** 53 * @param array $deltas 54 * @return SiteStatsUpdate 55 */ 56 public static function factory( array $deltas ) { 57 $update = new self( 0, 0, 0 ); 58 59 $fields = array( 'views', 'edits', 'pages', 'articles', 'users', 'images' ); 60 foreach ( $fields as $field ) { 61 if ( isset( $deltas[$field] ) && $deltas[$field] ) { 62 $update->$field = $deltas[$field]; 63 } 64 } 65 66 return $update; 67 } 68 69 public function doUpdate() { 70 global $wgSiteStatsAsyncFactor; 71 72 $rate = $wgSiteStatsAsyncFactor; // convenience 73 // If set to do so, only do actual DB updates 1 every $rate times. 74 // The other times, just update "pending delta" values in memcached. 75 if ( $rate && ( $rate < 0 || mt_rand( 0, $rate - 1 ) != 0 ) ) { 76 $this->doUpdatePendingDeltas(); 77 } else { 78 // Need a separate transaction because this a global lock 79 wfGetDB( DB_MASTER )->onTransactionIdle( array( $this, 'tryDBUpdateInternal' ) ); 80 } 81 } 82 83 /** 84 * Do not call this outside of SiteStatsUpdate 85 */ 86 public function tryDBUpdateInternal() { 87 global $wgSiteStatsAsyncFactor; 88 89 $dbw = wfGetDB( DB_MASTER ); 90 $lockKey = wfMemcKey( 'site_stats' ); // prepend wiki ID 91 $pd = array(); 92 if ( $wgSiteStatsAsyncFactor ) { 93 // Lock the table so we don't have double DB/memcached updates 94 if ( !$dbw->lockIsFree( $lockKey, __METHOD__ ) 95 || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout 96 ) { 97 $this->doUpdatePendingDeltas(); 98 99 return; 100 } 101 $pd = $this->getPendingDeltas(); 102 // Piggy-back the async deltas onto those of this stats update.... 103 $this->views += ( $pd['ss_total_views']['+'] - $pd['ss_total_views']['-'] ); 104 $this->edits += ( $pd['ss_total_edits']['+'] - $pd['ss_total_edits']['-'] ); 105 $this->articles += ( $pd['ss_good_articles']['+'] - $pd['ss_good_articles']['-'] ); 106 $this->pages += ( $pd['ss_total_pages']['+'] - $pd['ss_total_pages']['-'] ); 107 $this->users += ( $pd['ss_users']['+'] - $pd['ss_users']['-'] ); 108 $this->images += ( $pd['ss_images']['+'] - $pd['ss_images']['-'] ); 109 } 110 111 // Build up an SQL query of deltas and apply them... 112 $updates = ''; 113 $this->appendUpdate( $updates, 'ss_total_views', $this->views ); 114 $this->appendUpdate( $updates, 'ss_total_edits', $this->edits ); 115 $this->appendUpdate( $updates, 'ss_good_articles', $this->articles ); 116 $this->appendUpdate( $updates, 'ss_total_pages', $this->pages ); 117 $this->appendUpdate( $updates, 'ss_users', $this->users ); 118 $this->appendUpdate( $updates, 'ss_images', $this->images ); 119 if ( $updates != '' ) { 120 $dbw->update( 'site_stats', array( $updates ), array(), __METHOD__ ); 121 } 122 123 if ( $wgSiteStatsAsyncFactor ) { 124 // Decrement the async deltas now that we applied them 125 $this->removePendingDeltas( $pd ); 126 // Commit the updates and unlock the table 127 $dbw->unlock( $lockKey, __METHOD__ ); 128 } 129 } 130 131 /** 132 * @param DatabaseBase $dbw 133 * @return bool|mixed 134 */ 135 public static function cacheUpdate( $dbw ) { 136 global $wgActiveUserDays; 137 $dbr = wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow' ) ); 138 # Get non-bot users than did some recent action other than making accounts. 139 # If account creation is included, the number gets inflated ~20+ fold on enwiki. 140 $activeUsers = $dbr->selectField( 141 'recentchanges', 142 'COUNT( DISTINCT rc_user_text )', 143 array( 144 'rc_user != 0', 145 'rc_bot' => 0, 146 'rc_log_type != ' . $dbr->addQuotes( 'newusers' ) . ' OR rc_log_type IS NULL', 147 'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX ) 148 - $wgActiveUserDays * 24 * 3600 ) ), 149 ), 150 __METHOD__ 151 ); 152 $dbw->update( 153 'site_stats', 154 array( 'ss_active_users' => intval( $activeUsers ) ), 155 array( 'ss_row_id' => 1 ), 156 __METHOD__ 157 ); 158 159 return $activeUsers; 160 } 161 162 protected function doUpdatePendingDeltas() { 163 $this->adjustPending( 'ss_total_views', $this->views ); 164 $this->adjustPending( 'ss_total_edits', $this->edits ); 165 $this->adjustPending( 'ss_good_articles', $this->articles ); 166 $this->adjustPending( 'ss_total_pages', $this->pages ); 167 $this->adjustPending( 'ss_users', $this->users ); 168 $this->adjustPending( 'ss_images', $this->images ); 169 } 170 171 /** 172 * @param string $sql 173 * @param string $field 174 * @param int $delta 175 */ 176 protected function appendUpdate( &$sql, $field, $delta ) { 177 if ( $delta ) { 178 if ( $sql ) { 179 $sql .= ','; 180 } 181 if ( $delta < 0 ) { 182 $sql .= "$field=$field-" . abs( $delta ); 183 } else { 184 $sql .= "$field=$field+" . abs( $delta ); 185 } 186 } 187 } 188 189 /** 190 * @param string $type 191 * @param string $sign ('+' or '-') 192 * @return string 193 */ 194 private function getTypeCacheKey( $type, $sign ) { 195 return wfMemcKey( 'sitestatsupdate', 'pendingdelta', $type, $sign ); 196 } 197 198 /** 199 * Adjust the pending deltas for a stat type. 200 * Each stat type has two pending counters, one for increments and decrements 201 * @param string $type 202 * @param int $delta Delta (positive or negative) 203 */ 204 protected function adjustPending( $type, $delta ) { 205 global $wgMemc; 206 207 if ( $delta < 0 ) { // decrement 208 $key = $this->getTypeCacheKey( $type, '-' ); 209 } else { // increment 210 $key = $this->getTypeCacheKey( $type, '+' ); 211 } 212 213 $magnitude = abs( $delta ); 214 if ( !$wgMemc->incr( $key, $magnitude ) ) { // not there? 215 if ( !$wgMemc->add( $key, $magnitude ) ) { // race? 216 $wgMemc->incr( $key, $magnitude ); 217 } 218 } 219 } 220 221 /** 222 * Get pending delta counters for each stat type 223 * @return array Positive and negative deltas for each type 224 */ 225 protected function getPendingDeltas() { 226 global $wgMemc; 227 228 $pending = array(); 229 foreach ( array( 'ss_total_views', 'ss_total_edits', 230 'ss_good_articles', 'ss_total_pages', 'ss_users', 'ss_images' ) as $type 231 ) { 232 // Get pending increments and pending decrements 233 $pending[$type]['+'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '+' ) ); 234 $pending[$type]['-'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '-' ) ); 235 } 236 237 return $pending; 238 } 239 240 /** 241 * Reduce pending delta counters after updates have been applied 242 * @param array $pd Result of getPendingDeltas(), used for DB update 243 */ 244 protected function removePendingDeltas( array $pd ) { 245 global $wgMemc; 246 247 foreach ( $pd as $type => $deltas ) { 248 foreach ( $deltas as $sign => $magnitude ) { 249 // Lower the pending counter now that we applied these changes 250 $wgMemc->decr( $this->getTypeCacheKey( $type, $sign ), $magnitude ); 251 } 252 } 253 } 254 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |