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