MediaWiki
REL1_24
|
00001 <?php 00024 require __DIR__ . '/../commandLine.inc'; 00025 00032 class UpdateLogging { 00033 00037 public $dbw; 00038 public $batchSize = 1000; 00039 public $minTs = false; 00040 00041 function execute() { 00042 $this->dbw = wfGetDB( DB_MASTER ); 00043 $logging = $this->dbw->tableName( 'logging' ); 00044 $logging_1_10 = $this->dbw->tableName( 'logging_1_10' ); 00045 $logging_pre_1_10 = $this->dbw->tableName( 'logging_pre_1_10' ); 00046 00047 if ( $this->dbw->tableExists( 'logging_pre_1_10' ) && !$this->dbw->tableExists( 'logging' ) ) { 00048 # Fix previous aborted run 00049 echo "Cleaning up from previous aborted run\n"; 00050 $this->dbw->query( "RENAME TABLE $logging_pre_1_10 TO $logging", __METHOD__ ); 00051 } 00052 00053 if ( $this->dbw->tableExists( 'logging_pre_1_10' ) ) { 00054 echo "This script has already been run to completion\n"; 00055 00056 return; 00057 } 00058 00059 # Create the target table 00060 if ( !$this->dbw->tableExists( 'logging_1_10' ) ) { 00061 global $wgDBTableOptions; 00062 00063 $sql = <<<EOT 00064 CREATE TABLE $logging_1_10 ( 00065 -- Log ID, for referring to this specific log entry, probably for deletion and such. 00066 log_id int unsigned NOT NULL auto_increment, 00067 00068 -- Symbolic keys for the general log type and the action type 00069 -- within the log. The output format will be controlled by the 00070 -- action field, but only the type controls categorization. 00071 log_type varbinary(10) NOT NULL default '', 00072 log_action varbinary(10) NOT NULL default '', 00073 00074 -- Timestamp. Duh. 00075 log_timestamp binary(14) NOT NULL default '19700101000000', 00076 00077 -- The user who performed this action; key to user_id 00078 log_user int unsigned NOT NULL default 0, 00079 00080 -- Key to the page affected. Where a user is the target, 00081 -- this will point to the user page. 00082 log_namespace int NOT NULL default 0, 00083 log_title varchar(255) binary NOT NULL default '', 00084 00085 -- Freeform text. Interpreted as edit history comments. 00086 log_comment varchar(255) NOT NULL default '', 00087 00088 -- LF separated list of miscellaneous parameters 00089 log_params blob NOT NULL, 00090 00091 -- rev_deleted for logs 00092 log_deleted tinyint unsigned NOT NULL default '0', 00093 00094 PRIMARY KEY log_id (log_id), 00095 KEY type_time (log_type, log_timestamp), 00096 KEY user_time (log_user, log_timestamp), 00097 KEY page_time (log_namespace, log_title, log_timestamp), 00098 KEY times (log_timestamp) 00099 00100 ) $wgDBTableOptions 00101 EOT; 00102 echo "Creating table logging_1_10\n"; 00103 $this->dbw->query( $sql, __METHOD__ ); 00104 } 00105 00106 # Synchronise the tables 00107 echo "Doing initial sync...\n"; 00108 $this->sync( 'logging', 'logging_1_10' ); 00109 echo "Sync done\n\n"; 00110 00111 # Rename the old table away 00112 echo "Renaming the old table to $logging_pre_1_10\n"; 00113 $this->dbw->query( "RENAME TABLE $logging TO $logging_pre_1_10", __METHOD__ ); 00114 00115 # Copy remaining old rows 00116 # Done before the new table is active so that $copyPos is accurate 00117 echo "Doing final sync...\n"; 00118 $this->sync( 'logging_pre_1_10', 'logging_1_10' ); 00119 00120 # Move the new table in 00121 echo "Moving the new table in...\n"; 00122 $this->dbw->query( "RENAME TABLE $logging_1_10 TO $logging", __METHOD__ ); 00123 echo "Finished.\n"; 00124 } 00125 00131 function sync( $srcTable, $dstTable ) { 00132 $batchSize = 1000; 00133 $minTs = $this->dbw->selectField( $srcTable, 'MIN(log_timestamp)', false, __METHOD__ ); 00134 $minTsUnix = wfTimestamp( TS_UNIX, $minTs ); 00135 $numRowsCopied = 0; 00136 00137 while ( true ) { 00138 $maxTs = $this->dbw->selectField( $srcTable, 'MAX(log_timestamp)', false, __METHOD__ ); 00139 $copyPos = $this->dbw->selectField( $dstTable, 'MAX(log_timestamp)', false, __METHOD__ ); 00140 $maxTsUnix = wfTimestamp( TS_UNIX, $maxTs ); 00141 $copyPosUnix = wfTimestamp( TS_UNIX, $copyPos ); 00142 00143 if ( $copyPos === null ) { 00144 $percent = 0; 00145 } else { 00146 $percent = ( $copyPosUnix - $minTsUnix ) / ( $maxTsUnix - $minTsUnix ) * 100; 00147 } 00148 printf( "%s %.2f%%\n", $copyPos, $percent ); 00149 00150 # Handle all entries with timestamp equal to $copyPos 00151 if ( $copyPos !== null ) { 00152 $numRowsCopied += $this->copyExactMatch( $srcTable, $dstTable, $copyPos ); 00153 } 00154 00155 # Now copy a batch of rows 00156 if ( $copyPos === null ) { 00157 $conds = false; 00158 } else { 00159 $conds = array( 'log_timestamp > ' . $this->dbw->addQuotes( $copyPos ) ); 00160 } 00161 $srcRes = $this->dbw->select( $srcTable, '*', $conds, __METHOD__, 00162 array( 'LIMIT' => $batchSize, 'ORDER BY' => 'log_timestamp' ) ); 00163 00164 if ( !$srcRes->numRows() ) { 00165 # All done 00166 break; 00167 } 00168 00169 $batch = array(); 00170 foreach ( $srcRes as $srcRow ) { 00171 $batch[] = (array)$srcRow; 00172 } 00173 $this->dbw->insert( $dstTable, $batch, __METHOD__ ); 00174 $numRowsCopied += count( $batch ); 00175 00176 wfWaitForSlaves(); 00177 } 00178 echo "Copied $numRowsCopied rows\n"; 00179 } 00180 00181 function copyExactMatch( $srcTable, $dstTable, $copyPos ) { 00182 $numRowsCopied = 0; 00183 $srcRes = $this->dbw->select( $srcTable, '*', array( 'log_timestamp' => $copyPos ), __METHOD__ ); 00184 $dstRes = $this->dbw->select( $dstTable, '*', array( 'log_timestamp' => $copyPos ), __METHOD__ ); 00185 00186 if ( $srcRes->numRows() ) { 00187 $srcRow = $srcRes->fetchObject(); 00188 $srcFields = array_keys( (array)$srcRow ); 00189 $srcRes->seek( 0 ); 00190 $dstRowsSeen = array(); 00191 00192 # Make a hashtable of rows that already exist in the destination 00193 foreach ( $dstRes as $dstRow ) { 00194 $reducedDstRow = array(); 00195 foreach ( $srcFields as $field ) { 00196 $reducedDstRow[$field] = $dstRow->$field; 00197 } 00198 $hash = md5( serialize( $reducedDstRow ) ); 00199 $dstRowsSeen[$hash] = true; 00200 } 00201 00202 # Copy all the source rows that aren't already in the destination 00203 foreach ( $srcRes as $srcRow ) { 00204 $hash = md5( serialize( (array)$srcRow ) ); 00205 if ( !isset( $dstRowsSeen[$hash] ) ) { 00206 $this->dbw->insert( $dstTable, (array)$srcRow, __METHOD__ ); 00207 $numRowsCopied++; 00208 } 00209 } 00210 } 00211 00212 return $numRowsCopied; 00213 } 00214 } 00215 00216 $ul = new UpdateLogging; 00217 $ul->execute();