MediaWiki  REL1_19
initEditCount.php
Go to the documentation of this file.
00001 <?php
00025 require_once( dirname( __FILE__ ) . '/Maintenance.php' );
00026 
00027 class InitEditCount extends Maintenance {
00028         public function __construct() {
00029                 parent::__construct();
00030                 $this->addOption( 'quick', 'Force the update to be done in a single query' );
00031                 $this->addOption( 'background', 'Force replication-friendly mode; may be inefficient but
00032                 avoids locking tables or lagging slaves with large updates;
00033                 calculates counts on a slave if possible.
00034 
00035 Background mode will be automatically used if the server is MySQL 4.0
00036 (which does not support subqueries) or if multiple servers are listed
00037 in the load balancer, usually indicating a replication environment.' );
00038                 $this->mDescription = "Batch-recalculate user_editcount fields from the revision table";
00039         }
00040 
00041         public function execute() {
00042                 $dbw = wfGetDB( DB_MASTER );
00043                 $user = $dbw->tableName( 'user' );
00044                 $revision = $dbw->tableName( 'revision' );
00045 
00046                 $dbver = $dbw->getServerVersion();
00047 
00048                 // Autodetect mode...
00049                 $backgroundMode = wfGetLB()->getServerCount() > 1 ||
00050                         ( $dbw instanceof DatabaseMysql && version_compare( $dbver, '4.1' ) < 0 );
00051 
00052                 if ( $this->hasOption( 'background' ) ) {
00053                         $backgroundMode = true;
00054                 } elseif ( $this->hasOption( 'quick' ) ) {
00055                         $backgroundMode = false;
00056                 }
00057 
00058                 if ( $backgroundMode ) {
00059                         $this->output( "Using replication-friendly background mode...\n" );
00060 
00061                         $dbr = wfGetDB( DB_SLAVE );
00062                         $chunkSize = 100;
00063                         $lastUser = $dbr->selectField( 'user', 'MAX(user_id)', '', __METHOD__ );
00064 
00065                         $start = microtime( true );
00066                         $migrated = 0;
00067                         for ( $min = 0; $min <= $lastUser; $min += $chunkSize ) {
00068                                 $max = $min + $chunkSize;
00069                                 $result = $dbr->query(
00070                                         "SELECT
00071                                                 user_id,
00072                                                 COUNT(rev_user) AS user_editcount
00073                                         FROM $user
00074                                         LEFT OUTER JOIN $revision ON user_id=rev_user
00075                                         WHERE user_id > $min AND user_id <= $max
00076                                         GROUP BY user_id",
00077                                         __METHOD__ );
00078 
00079                                 foreach ( $result as $row ) {
00080                                         $dbw->update( 'user',
00081                                                 array( 'user_editcount' => $row->user_editcount ),
00082                                                 array( 'user_id' => $row->user_id ),
00083                                                 __METHOD__ );
00084                                         ++$migrated;
00085                                 }
00086 
00087                                 $delta = microtime( true ) - $start;
00088                                 $rate = ( $delta == 0.0 ) ? 0.0 : $migrated / $delta;
00089                                 $this->output( sprintf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n",
00090                                         wfWikiID(),
00091                                         $migrated,
00092                                         min( $max, $lastUser ) / $lastUser * 100.0,
00093                                         $delta,
00094                                         $rate ) );
00095 
00096                                 wfWaitForSlaves();
00097                         }
00098                 } else {
00099                         // Subselect should work on modern MySQLs etc
00100                         $this->output( "Using single-query mode...\n" );
00101                         $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
00102                         $dbw->query( $sql );
00103                 }
00104 
00105                 $this->output( "Done!\n" );
00106         }
00107 }
00108 
00109 $maintClass = "InitEditCount";
00110 require_once( RUN_MAINTENANCE_IF_MAIN );