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