MediaWiki  REL1_22
initEditCount.php
Go to the documentation of this file.
00001 <?php
00025 require_once __DIR__ . '/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;