r52824 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r52823‎ | r52824 | r52825 >
Date:00:26, 7 July 2009
Author:demon
Status:deferred
Tags:
Comment:
* Port addwiki, fixSlaveDesync, fixTimestamps, namespaceDupes, populateLogUsertext, renamewiki
* Kill dbsource() everywhere possible. Use $db->sourceFile() if you've already got a DB object on hand (I'm eying you install-utils, your days are numbered!)
Modified paths:
  • /branches/maintenance-work/config/index.php (modified) (history)
  • /branches/maintenance-work/includes/db/DatabaseIbm_db2.php (modified) (history)
  • /branches/maintenance-work/includes/db/DatabaseOracle.php (modified) (history)
  • /branches/maintenance-work/includes/db/DatabasePostgres.php (modified) (history)
  • /branches/maintenance-work/maintenance/Maintenance.php (modified) (history)
  • /branches/maintenance-work/maintenance/addwiki.php (modified) (history)
  • /branches/maintenance-work/maintenance/fixSlaveDesync.php (modified) (history)
  • /branches/maintenance-work/maintenance/fixTimestamps.php (modified) (history)
  • /branches/maintenance-work/maintenance/namespaceDupes.php (modified) (history)
  • /branches/maintenance-work/maintenance/patchSql.php (modified) (history)
  • /branches/maintenance-work/maintenance/populateLogUsertext.inc (deleted) (history)
  • /branches/maintenance-work/maintenance/populateLogUsertext.php (modified) (history)
  • /branches/maintenance-work/maintenance/renamewiki.php (modified) (history)
  • /branches/maintenance-work/maintenance/updaters.inc (modified) (history)

Diff [purge]

Index: branches/maintenance-work/maintenance/populateLogUsertext.inc
@@ -1,54 +0,0 @@
2 -<?php
3 -/**
4 - * Makes the required database updates for the log_user_text column
5 - *
6 - * Run via update.php or directly through populateLogUsertext.php
7 - *
8 - * @file
9 - * @ingroup Maintenance
10 - */
11 -
12 -define( 'LOG_USERTEXT_BATCH_SIZE', 100 );
13 -
14 -function populate_logusertext( $db ) {
15 - $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ );
16 - if( !$start ) {
17 - echo "Nothing to do.\n";
18 - return true;
19 - }
20 - $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ );
21 -
22 - # Do remaining chunk
23 - $end += LOG_USERTEXT_BATCH_SIZE - 1;
24 - $blockStart = $start;
25 - $blockEnd = $start + LOG_USERTEXT_BATCH_SIZE - 1;
26 - while( $blockEnd <= $end ) {
27 - echo "...doing log_id from $blockStart to $blockEnd\n";
28 - $cond = "log_id BETWEEN $blockStart AND $blockEnd AND log_user = user_id";
29 - $res = $db->select( array('logging','user'),
30 - array('log_id','user_name'), $cond, __FUNCTION__ );
31 - $batch = array();
32 - $db->begin();
33 - while( $row = $db->fetchObject( $res ) ) {
34 - $db->update( 'logging', array('log_user_text' => $row->user_name),
35 - array('log_id' => $row->log_id), __FUNCTION__ );
36 - }
37 - $db->commit();
38 - $blockStart += LOG_USERTEXT_BATCH_SIZE;
39 - $blockEnd += LOG_USERTEXT_BATCH_SIZE;
40 - wfWaitForSlaves( 5 );
41 - }
42 - if( $db->insert(
43 - 'updatelog',
44 - array( 'ul_key' => 'populate log_usertext' ),
45 - __FUNCTION__,
46 - 'IGNORE'
47 - )
48 - ) {
49 - wfOut( "log_usertext population complete.\n" );
50 - return true;
51 - } else {
52 - wfOut( "Could not insert log_usertext population row.\n" );
53 - return false;
54 - }
55 -}
Index: branches/maintenance-work/maintenance/renamewiki.php
@@ -7,56 +7,62 @@
88 * @ingroup Maintenance
99 */
1010
11 -require_once( "commandLine.inc" );
 11+require_once( "Maintenance.php" );
1212
13 -if ( count( $args ) != 2 ) {
14 - wfDie( "Rename external storage dbs and leave a new one...\n" .
15 - "Usage: php renamewiki.php <olddb> <newdb>\n" );
16 -}
 13+class RenameWiki extends Maintenance {
 14+ public function __construct() {
 15+ parent::__construct();
 16+ $this->mDescription = "Rename external storage dbs and leave a new one";
 17+ $this->addArgs( array( 'olddb', 'newdb' ) );
 18+ }
1719
18 -list( $from, $to ) = $args;
 20+ public function execute() {
 21+ global $wgDefaultExternalStore;
1922
20 -echo "Renaming blob tables in ES from $from to $to...\n";
21 -echo "Sleeping 5 seconds...";
22 -sleep(5);
23 -echo "\n";
 23+ # Setup
 24+ $from = $this->getArg( 0 );
 25+ $to = $this->getArg( 1 );
 26+ $this->output( "Renaming blob tables in ES from $from to $to...\n" );
 27+ $this->output( "Sleeping 5 seconds...\n" );
 28+ sleep(5);
2429
25 -$maintenance = "$IP/maintenance";
 30+ # Initialise external storage
 31+ if ( is_array( $wgDefaultExternalStore ) ) {
 32+ $stores = $wgDefaultExternalStore;
 33+ } elseif ( $wgDefaultExternalStore ) {
 34+ $stores = array( $wgDefaultExternalStore );
 35+ } else {
 36+ $stores = array();
 37+ }
2638
27 -# Initialise external storage
28 -if ( is_array( $wgDefaultExternalStore ) ) {
29 - $stores = $wgDefaultExternalStore;
30 -} elseif ( $wgDefaultExternalStore ) {
31 - $stores = array( $wgDefaultExternalStore );
32 -} else {
33 - $stores = array();
34 -}
35 -if ( count( $stores ) ) {
36 - require_once( 'ExternalStoreDB.php' );
37 - print "Initialising external storage $store...\n";
38 - global $wgDBuser, $wgDBpassword, $wgExternalServers;
39 - foreach ( $stores as $storeURL ) {
40 - $m = array();
41 - if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
42 - continue;
 39+ if ( count( $stores ) ) {
 40+ $this->output( "Initialising external storage $store...\n" );
 41+ global $wgDBuser, $wgDBpassword, $wgExternalServers;
 42+ foreach ( $stores as $storeURL ) {
 43+ $m = array();
 44+ if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
 45+ continue;
 46+ }
 47+
 48+ $cluster = $m[1];
 49+
 50+ # Hack
 51+ $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
 52+ $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
 53+
 54+ $store = new ExternalStoreDB;
 55+ $extdb =& $store->getMaster( $cluster );
 56+ $extdb->query( "SET table_type=InnoDB" );
 57+ $extdb->query( "CREATE DATABASE {$to}" );
 58+ $extdb->query( "ALTER TABLE {$from}.blobs RENAME TO {$to}.blobs" );
 59+ $extdb->selectDB( $from );
 60+ $extdb->sourceFile( $this->getDir() . '/storage/blobs.sql' );
 61+ $extdb->immediateCommit();
 62+ }
4363 }
44 -
45 - $cluster = $m[1];
46 -
47 - # Hack
48 - $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
49 - $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
50 -
51 - $store = new ExternalStoreDB;
52 - $extdb =& $store->getMaster( $cluster );
53 - $extdb->query( "SET table_type=InnoDB" );
54 - $extdb->query( "CREATE DATABASE {$to}" );
55 - $extdb->query( "ALTER TABLE {$from}.blobs RENAME TO {$to}.blobs" );
56 - $extdb->selectDB( $from );
57 - dbsource( "$maintenance/storage/blobs.sql", $extdb );
58 - $extdb->immediateCommit();
 64+ $this->output( "done.\n" );
5965 }
6066 }
6167
62 -echo "done.\n";
63 -
 68+$maintClass = "RenameWiki";
 69+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/maintenance/updaters.inc
@@ -215,7 +215,7 @@
216216 wfOut( "...can't move table $from to $to, $to already exists.\n" );
217217 } else {
218218 wfOut( "Moving table $from to $to..." );
219 - dbsource( archive($patch), $wgDatabase );
 219+ $wgDatabase->sourceFile( archive($patch) );
220220 wfOut( "ok\n" );
221221 }
222222 } else {
@@ -232,9 +232,9 @@
233233 } else {
234234 wfOut( "Creating $name table..." );
235235 if( $fullpath ) {
236 - dbsource( $patch, $wgDatabase );
 236+ $wgDatabase->sourceFile( $patch );
237237 } else {
238 - dbsource( archive($patch), $wgDatabase );
 238+ $wgDatabase->sourceFile( archive($patch) );
239239 }
240240 wfOut( "ok\n" );
241241 }
@@ -249,9 +249,9 @@
250250 } else {
251251 wfOut( "Adding $field field to table $table..." );
252252 if( $fullpath ) {
253 - dbsource( $patch, $wgDatabase );
 253+ $wgDatabase->sourceFile( $patch );
254254 } else {
255 - dbsource( archive($patch), $wgDatabase );
 255+ $wgDatabase->sourceFile( archive($patch) );
256256 }
257257 wfOut( "ok\n" );
258258 }
@@ -264,9 +264,9 @@
265265 } else {
266266 wfOut( "Adding $index key to table $table... " );
267267 if( $fullpath ) {
268 - dbsource( $patch, $wgDatabase );
 268+ $wgDatabase->sourceFile( $patch );
269269 } else {
270 - dbsource( archive($patch), $wgDatabase );
 270+ $wgDatabase->sourceFile( archive($patch) );
271271 }
272272 wfOut( "ok\n" );
273273 }
@@ -280,10 +280,10 @@
281281 return true;
282282 }
283283 wfOut( "Creating interwiki table: " );
284 - dbsource( archive("patch-interwiki.sql") );
 284+ $wgDatabase->sourceFile( archive("patch-interwiki.sql") );
285285 wfOut( "ok\n" );
286286 wfOut( "Adding default interwiki definitions: " );
287 - dbsource( "$IP/maintenance/interwiki.sql" );
 287+ $wgDatabase->sourceFile( "$IP/maintenance/interwiki.sql" );
288288 wfOut( "ok\n" );
289289 }
290290
@@ -293,7 +293,7 @@
294294 $meta = $wgDatabase->fieldInfo( "recentchanges", "rc_timestamp" );
295295 if( !$meta->isMultipleKey() ) {
296296 wfOut( "Updating indexes to 20031107: " );
297 - dbsource( archive("patch-indexes.sql") );
 297+ $wgDatabase->sourceFile( archive("patch-indexes.sql") );
298298 wfOut( "ok\n" );
299299 return true;
300300 }
@@ -307,7 +307,7 @@
308308 $meta = $wgDatabase->fieldInfo( "image", "img_major_mime" );
309309 if( !$meta->isMultipleKey() ) {
310310 wfOut( "Updating indexes to 20050912: " );
311 - dbsource( archive("patch-mimesearch-indexes.sql") );
 311+ $wgDatabase->sourceFile( archive("patch-mimesearch-indexes.sql") );
312312 wfOut( "ok\n" );
313313 return true;
314314 }
@@ -321,7 +321,7 @@
322322 wfOut( "...image primary key already set.\n" );
323323 } else {
324324 wfOut( "Making img_name the primary key... " );
325 - dbsource( archive("patch-image_name_primary.sql"), $wgDatabase );
 325+ $wgDatabase->sourceFile( archive("patch-image_name_primary.sql") );
326326 wfOut( "ok\n" );
327327 }
328328 }
@@ -332,7 +332,7 @@
333333 wfOut( "...timestamp key on logging already exists.\n" );
334334 } else {
335335 wfOut( "Adding timestamp key on logging table... " );
336 - dbsource( archive("patch-logging-times-index.sql"), $wgDatabase );
 336+ $wgDatabase->sourceFile( archive("patch-logging-times-index.sql") );
337337 wfOut( "ok\n" );
338338 }
339339 }
@@ -343,7 +343,7 @@
344344 wfOut( "...usertext,timestamp key on archive already exists.\n" );
345345 } else {
346346 wfOut( "Adding usertext,timestamp key on archive table... " );
347 - dbsource( archive("patch-archive-user-index.sql"), $wgDatabase );
 347+ $wgDatabase->sourceFile( archive("patch-archive-user-index.sql") );
348348 wfOut( "ok\n" );
349349 }
350350 }
@@ -354,7 +354,7 @@
355355 wfOut( "...usertext,timestamp key on image already exists.\n" );
356356 } else {
357357 wfOut( "Adding usertext,timestamp key on image table... " );
358 - dbsource( archive("patch-image-user-index.sql"), $wgDatabase );
 358+ $wgDatabase->sourceFile( archive("patch-image-user-index.sql") );
359359 wfOut( "ok\n" );
360360 }
361361 }
@@ -365,7 +365,7 @@
366366 wfOut( "...usertext,timestamp key on oldimage already exists.\n" );
367367 } else {
368368 wfOut( "Adding usertext,timestamp key on oldimage table... " );
369 - dbsource( archive("patch-oldimage-user-index.sql"), $wgDatabase );
 369+ $wgDatabase->sourceFile( archive("patch-oldimage-user-index.sql") );
370370 wfOut( "ok\n" );
371371 }
372372 }
@@ -378,7 +378,7 @@
379379 } else {
380380 wfOut( "Adding wl_notificationtimestamp field for email notification management." );
381381 /* ALTER TABLE watchlist ADD (wl_notificationtimestamp varchar(14) binary NOT NULL default '0'); */
382 - dbsource( archive( 'patch-email-notification.sql' ), $wgDatabase );
 382+ $wgDatabase->sourceFile( archive( 'patch-email-notification.sql' ) );
383383 wfOut( "ok\n" );
384384 }
385385 # Check if we need to add talk page rows to the watchlist
@@ -444,7 +444,7 @@
445445 global $wgDatabase;
446446 if( $wgDatabase->fieldExists( 'user', 'user_emailauthenticationtimestamp' ) ) {
447447 wfOut( "User table contains old email authentication field. Dropping... " );
448 - dbsource( archive( 'patch-email-authentication.sql' ), $wgDatabase );
 448+ $wgDatabase->sourceFile( archive( 'patch-email-authentication.sql' ) );
449449 wfOut( "ok\n" );
450450 } else {
451451 wfOut( "...user table does not contain old email authentication field.\n" );
@@ -468,7 +468,7 @@
469469 wfOut( "$table table has correct $field encoding.\n" );
470470 } else {
471471 wfOut( "Fixing $field encoding on $table table... " );
472 - dbsource( archive( $patchFile ), $wgDatabase );
 472+ $wgDatabase->sourceFile( archive( $patchFile ) );
473473 wfOut( "ok\n" );
474474 }
475475 }
@@ -643,7 +643,7 @@
644644 global $wgDatabase;
645645 if( $wgDatabase->fieldExists( 'revision', 'inverse_timestamp' ) ) {
646646 wfOut( "Removing revision.inverse_timestamp and fixing indexes... " );
647 - dbsource( archive( 'patch-inverse_timestamp.sql' ), $wgDatabase );
 647+ $wgDatabase->sourceFile( archive( 'patch-inverse_timestamp.sql' ) );
648648 wfOut( "ok\n" );
649649 } else {
650650 wfOut( "revision timestamp indexes already up to 2005-03-13\n" );
@@ -656,7 +656,7 @@
657657 wfOut( "...rev_text_id already in place.\n" );
658658 } else {
659659 wfOut( "Adding rev_text_id field... " );
660 - dbsource( archive( 'patch-rev_text_id.sql' ), $wgDatabase );
 660+ $wgDatabase->sourceFile( archive( 'patch-rev_text_id.sql' ) );
661661 wfOut( "ok\n" );
662662 }
663663 }
@@ -705,7 +705,7 @@
706706 wfOut( "...already have pagelinks table.\n" );
707707 } else {
708708 wfOut( "Converting links and brokenlinks tables to pagelinks... " );
709 - dbsource( archive( 'patch-pagelinks.sql' ), $wgDatabase );
 709+ $wgDatabase->sourceFile( archive( 'patch-pagelinks.sql' ) );
710710 wfOut( "ok\n" );
711711 flush();
712712
@@ -744,7 +744,7 @@
745745
746746 if( $wgDatabase->fieldExists( 'image', 'img_type' ) ) {
747747 wfOut( "Dropping unused img_type field in image table... " );
748 - dbsource( archive( 'patch-drop_img_type.sql' ), $wgDatabase );
 748+ $wgDatabase->sourceFile( archive( 'patch-drop_img_type.sql' ) );
749749 wfOut( "ok\n" );
750750 } else {
751751 wfOut( "No img_type field in image table; Good.\n" );
@@ -766,7 +766,7 @@
767767 if ( $info && $info->type() === 'string' ) {
768768 wfOut( "Fixing ancient broken imagelinks table.\n" );
769769 wfOut( "NOTE: you will have to run maintenance/refreshLinks.php after this.\n" );
770 - dbsource( archive( 'patch-fix-il_from.sql' ) );
 770+ $wgDatabase->sourceFile( archive( 'patch-fix-il_from.sql' ) );
771771 wfOut( "ok\n" );
772772 } else {
773773 wfOut( "...il_from OK\n" );
@@ -783,7 +783,7 @@
784784 wfOut( "WARNING: This next step will probably fail due to unfixed duplicates...\n" );
785785 }
786786 wfOut( "Adding unique index on user_name... " );
787 - dbsource( archive( 'patch-user_nameindex.sql' ), $wgDatabase );
 787+ $wgDatabase->sourceFile( archive( 'patch-user_nameindex.sql' ) );
788788 wfOut( "ok\n" );
789789 }
790790 }
@@ -798,13 +798,13 @@
799799 }
800800
801801 wfOut( "Adding user_groups table... " );
802 - dbsource( archive( 'patch-user_groups.sql' ), $wgDatabase );
 802+ $wgDatabase->sourceFile( archive( 'patch-user_groups.sql' ) );
803803 wfOut( "ok\n" );
804804
805805 if( !$wgDatabase->tableExists( 'user_rights' ) ) {
806806 if( $wgDatabase->fieldExists( 'user', 'user_rights' ) ) {
807807 wfOut( "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion..." );
808 - dbsource( archive( 'patch-user_rights.sql' ), $wgDatabase );
 808+ $wgDatabase->sourceFile( archive( 'patch-user_rights.sql' ) );
809809 wfOut( "ok\n" );
810810 } else {
811811 wfOut( "*** WARNING: couldn't locate user_rights table or field for upgrade.\n" );
@@ -850,7 +850,7 @@
851851 wfOut( "ok\n" );
852852
853853 wfOut( "Re-adding fresh user_groups table... " );
854 - dbsource( archive( 'patch-user_groups.sql' ), $wgDatabase );
 854+ $wgDatabase->sourceFile( archive( 'patch-user_groups.sql' ) );
855855 wfOut( "ok\n" );
856856
857857 wfOut( "***\n" );
@@ -871,7 +871,7 @@
872872
873873 if( !$info->nullable() ) {
874874 wfOut( "Making wl_notificationtimestamp nullable... " );
875 - dbsource( archive( 'patch-watchlist-null.sql' ), $wgDatabase );
 875+ $wgDatabase->sourceFile( archive( 'patch-watchlist-null.sql' ) );
876876 wfOut( "ok\n" );
877877 } else {
878878 wfOut( "...wl_notificationtimestamp is already nullable.\n" );
@@ -903,7 +903,7 @@
904904 return;
905905 }
906906 wfOut( "Creating templatelinks table...\n" );
907 - dbsource( archive('patch-templatelinks.sql'), $wgDatabase );
 907+ $wgDatabase->sourceFile( archive('patch-templatelinks.sql') );
908908 wfOut( "Populating...\n" );
909909 if ( isset( $wgLoadBalancer ) && $wgLoadBalancer->getServerCount() > 1 ) {
910910 // Slow, replication-friendly update
@@ -959,7 +959,7 @@
960960 $info = $wgDatabase->indexInfo( 'recentchanges', $index, __METHOD__ );
961961 if( !$info ) {
962962 wfOut( "...index `{$index}` not found; adding..." );
963 - dbsource( archive( $patch ) );
 963+ $wgDatabase->sourceFile( archive( $patch ) );
964964 wfOut( "done.\n" );
965965 } else {
966966 wfOut( "...index `{$index}` seems ok.\n" );
@@ -989,7 +989,7 @@
990990 !index_has_field('templatelinks', 'tl_namespace', 'tl_from') ||
991991 !index_has_field('imagelinks', 'il_to', 'il_from'))
992992 {
993 - dbsource( archive( 'patch-backlinkindexes.sql' ) );
 993+ $wgDatabase->sourceFile( archive( 'patch-backlinkindexes.sql' ) );
994994 wfOut( "...backlinking indices updated\n" );
995995 }
996996 }
@@ -998,7 +998,7 @@
999999 wfOut( "Checking for categorylinks indices...\n" );
10001000 if (!index_has_field('categorylinks', 'cl_sortkey', 'cl_from'))
10011001 {
1002 - dbsource( archive( 'patch-categorylinksindex.sql' ) );
 1002+ $wgDatabase->sourceFile( archive( 'patch-categorylinksindex.sql' ) );
10031003 wfOut( "...categorylinks indices updated\n" );
10041004 }
10051005 }
@@ -1009,7 +1009,7 @@
10101010 $info = $wgDatabase->indexInfo( 'filearchive', 'fa_user_timestamp', __METHOD__ );
10111011 if ( !$info )
10121012 {
1013 - dbsource( archive( 'patch-filearchive-user-index.sql' ) );
 1013+ $wgDatabase->sourceFile( archive( 'patch-filearchive-user-index.sql' ) );
10141014 wfOut( "...filearchive indices updated\n" );
10151015 }
10161016 }
@@ -1022,7 +1022,7 @@
10231023 wfOut( "profiling table has pf_memory field.\n" );
10241024 } else {
10251025 wfOut( "Adding pf_memory field to table profiling..." );
1026 - dbsource( archive( 'patch-profiling-memory.sql' ), $wgDatabase );
 1026+ $wgDatabase->sourceFile( archive( 'patch-profiling-memory.sql' ) );
10271027 wfOut( "ok\n" );
10281028 }
10291029 }
@@ -1146,8 +1146,8 @@
11471147 wfOut( "...$name table already exists.\n" );
11481148 } else {
11491149 wfOut( "Creating $name table..." );
1150 - dbsource( archive($patch), $wgDatabase );
1151 - dbsource( archive($patch2), $wgDatabase );
 1150+ $wgDatabase->sourceFile( archive($patch) );
 1151+ $wgDatabase->sourceFile( archive($patch2) );
11521152 wfOut( "ok\n" );
11531153
11541154 wfOut( "Migrating old restrictions to new table..." );
@@ -1249,7 +1249,7 @@
12501250 wfOut( "...pl_namespace, tl_namespace, il_to indices are already UNIQUE.\n" );
12511251 } else {
12521252 wfOut( "Making pl_namespace, tl_namespace and il_to indices UNIQUE... " );
1253 - dbsource( archive( 'patch-pl-tl-il-unique.sql' ), $wgDatabase );
 1253+ $wgDatabase->sourceFile( archive( 'patch-pl-tl-il-unique.sql' ) );
12541254 wfOut( "ok\n" );
12551255 }
12561256 }
@@ -1619,7 +1619,7 @@
16201620 }
16211621
16221622 wfOut( "Creating table \"$nt[0]\"\n" );
1623 - dbsource(archive($nt[1]));
 1623+ $wgDatabase->sourceFile(archive($nt[1]));
16241624 }
16251625
16261626 ## Needed before newcols
@@ -1633,7 +1633,7 @@
16341634 wfOut( "Dropping rule \"archive_delete\"\n" );
16351635 $wgDatabase->query("DROP RULE archive_delete ON archive");
16361636 }
1637 - dbsource(archive("patch-remove-archive2.sql"));
 1637+ $wgDatabase->sourceFile(archive("patch-remove-archive2.sql"));
16381638 }
16391639 else
16401640 wfOut( "... obsolete table \"archive2\" does not exist\n" );
@@ -1728,7 +1728,7 @@
17291729 continue;
17301730 }
17311731 wfOut( "Adding rule \"$nr[1]\" to table \"$nr[0]\"\n" );
1732 - dbsource(archive($nr[2]));
 1732+ $wgDatabase->sourceFile(archive($nr[2]));
17331733 }
17341734
17351735 if ($wgDatabase->hasConstraint("oldimage_oi_name_fkey")) {
@@ -1742,7 +1742,7 @@
17431743
17441744 if (!$wgDatabase->triggerExists("page", "page_deleted")) {
17451745 wfOut( "Adding function and trigger \"page_deleted\" to table \"page\"\n" );
1746 - dbsource(archive('patch-page_deleted.sql'));
 1746+ $wgDatabase->sourceFile(archive('patch-page_deleted.sql'));
17471747 }
17481748 else
17491749 wfOut( "... table \"page\" has \"page_deleted\" trigger\n" );
@@ -1750,7 +1750,7 @@
17511751 $fi = $wgDatabase->fieldInfo("recentchanges", "rc_cur_id");
17521752 if (!$fi->nullable()) {
17531753 wfOut( "Removing NOT NULL constraint from \"recentchanges.rc_cur_id\"\n" );
1754 - dbsource(archive('patch-rc_cur_id-not-null.sql'));
 1754+ $wgDatabase->sourceFile(archive('patch-rc_cur_id-not-null.sql'));
17551755 }
17561756 else
17571757 wfOut( "... column \"recentchanges.rc_cur_id\" has a NOT NULL constraint\n" );
@@ -1776,7 +1776,7 @@
17771777 }
17781778 else {
17791779 wfOut( "Changing constraint \"revision_rev_user_fkey\" to ON DELETE RESTRICT\n" );
1780 - dbsource(archive('patch-revision_rev_user_fkey.sql'));
 1780+ $wgDatabase->sourceFile(archive('patch-revision_rev_user_fkey.sql'));
17811781 }
17821782
17831783 # Fix ipb_address index
@@ -1789,7 +1789,7 @@
17901790 }
17911791 else {
17921792 wfOut( "Adding ipb_address_unique index\n" );
1793 - dbsource(archive('patch-ipb_address_unique.sql'));
 1793+ $wgDatabase->sourceFile(archive('patch-ipb_address_unique.sql'));
17941794 }
17951795
17961796 global $wgExtNewTables, $wgExtPGNewFields, $wgExtPGAlteredFields, $wgExtNewIndexes;
@@ -1800,7 +1800,7 @@
18011801 continue;
18021802 }
18031803 wfOut( "Creating table \"$nt[0]\"\n" );
1804 - dbsource($nt[1]);
 1804+ $wgDatabase->sourceFile($nt[1]);
18051805 }
18061806 # Add missing extension fields
18071807 foreach ( $wgExtPGNewFields as $nc ) {
@@ -1843,18 +1843,18 @@
18441844 $wgDatabase->query( "CREATE INDEX $ni[1] ON $ni[0] $ni[2]" );
18451845 }
18461846 else {
1847 - dbsource($ni[2]);
 1847+ $wgDatabase->sourceFile($ni[2]);
18481848 }
18491849 }
18501850
18511851 # Tweak the page_title tsearch2 trigger to filter out slashes
18521852 # This is create or replace, so harmless to call if not needed
1853 - dbsource(archive('patch-ts2pagetitle.sql'));
 1853+ $wgDatabase->sourceFile(archive('patch-ts2pagetitle.sql'));
18541854
18551855 ## If the server is 8.3 or higher, rewrite the tsearch2 triggers
18561856 ## in case they have the old 'default' versions
18571857 if ( $numver >= 8.3 )
1858 - dbsource(archive('patch-tsearch2funcs.sql'));
 1858+ $wgDatabase->sourceFile(archive('patch-tsearch2funcs.sql'));
18591859
18601860 ## Put a new row in the mediawiki_version table
18611861 $wgDatabase->insert( 'mediawiki_version',
Index: branches/maintenance-work/maintenance/addwiki.php
@@ -7,250 +7,254 @@
88 * @ingroup Maintenance
99 */
1010
11 -$wgNoDBParam = true;
 11+require_once( "Maintenance.php" );
1212
13 -require_once( "commandLine.inc" );
14 -require_once( "rebuildInterwiki.inc" );
15 -require_once( "languages/Names.php" );
16 -if ( count( $args ) != 3 ) {
17 - wfDie( "Usage: php addwiki.php <language> <site> <dbname>\nThe site for Wikipedia is 'wikipedia'.\n" );
18 -}
 13+class AddWiki extends Maintenance {
 14+ public function __construct() {
 15+ parent::__construct();
 16+ $this->mDescription = "Add a new wiki to the family. Wikimedia specific!";
 17+ $this->addArgs( 'language', 'site', 'dbname' );
 18+ }
 19+
 20+ public function execute() {
 21+ global $IP, $wgLanguageNames, $wgDefaultExternalStore, $wgNoDBParam;
1922
20 -addWiki( $args[0], $args[1], $args[2] );
 23+ $wgNoDBParam = true;
 24+ $lang = $this->getArg(0);
 25+ $site = $this->getArg(1);
 26+ $dbName = $this->getArg(2);
2127
22 -# -----------------------------------------------------------------
 28+ if ( !isset( $wgLanguageNames[$lang] ) ) {
 29+ $this->error( "Language $lang not found in \$wgLanguageNames\n", true );
 30+ }
 31+ $name = $wgLanguageNames[$lang];
2332
24 -function addWiki( $lang, $site, $dbName )
25 -{
26 - global $IP, $wgLanguageNames, $wgDefaultExternalStore;
 33+ $dbw = wfGetDB( DB_MASTER );
 34+ $common = "/home/wikipedia/common";
2735
28 - if ( !isset( $wgLanguageNames[$lang] ) ) {
29 - print "Language $lang not found in \$wgLanguageNames\n";
30 - return;
31 - }
32 - $name = $wgLanguageNames[$lang];
 36+ $this->output( "Creating database $dbName for $lang.$site ($name)\n" );
3337
34 - $dbw = wfGetDB( DB_MASTER );
35 - $common = "/home/wikipedia/common";
36 - $maintenance = "$IP/maintenance";
 38+ # Set up the database
 39+ $dbw->query( "SET table_type=Innodb" );
 40+ $dbw->query( "CREATE DATABASE $dbName" );
 41+ $dbw->selectDB( $dbName );
3742
38 - print "Creating database $dbName for $lang.$site ($name)\n";
39 -
40 - # Set up the database
41 - $dbw->query( "SET table_type=Innodb" );
42 - $dbw->query( "CREATE DATABASE $dbName" );
43 - $dbw->selectDB( $dbName );
 43+ $this->output( "Initialising tables\n" );
 44+ $dbw->sourceFile( $this->getDir() . '/tables.sql' );
 45+ $dbw->sourceFile( "$IP/extensions/OAI/update_table.sql" );
 46+ $dbw->sourceFile( "$IP/extensions/AntiSpoof/sql/patch-antispoof.mysql.sql" );
 47+ $dbw->sourceFile( "$IP/extensions/CheckUser/cu_changes.sql" );
 48+ $dbw->sourceFile( "$IP/extensions/CheckUser/cu_log.sql" );
 49+ $dbw->sourceFile( "$IP/extensions/TitleKey/titlekey.sql" );
 50+ $dbw->sourceFile( "$IP/extensions/Oversight/hidden.sql" );
 51+ $dbw->sourceFile( "$IP/extensions/GlobalBlocking/localdb_patches/setup-global_block_whitelist.sql" );
 52+ $dbw->sourceFile( "$IP/extensions/AbuseFilter/abusefilter.tables.sql" );
4453
45 - print "Initialising tables\n";
46 - dbsource( "$maintenance/tables.sql", $dbw );
47 - dbsource( "$IP/extensions/OAI/update_table.sql", $dbw );
48 - dbsource( "$IP/extensions/AntiSpoof/sql/patch-antispoof.mysql.sql", $dbw );
49 - dbsource( "$IP/extensions/CheckUser/cu_changes.sql", $dbw );
50 - dbsource( "$IP/extensions/CheckUser/cu_log.sql", $dbw );
51 - dbsource( "$IP/extensions/TitleKey/titlekey.sql", $dbw );
52 - dbsource( "$IP/extensions/Oversight/hidden.sql", $dbw );
53 - dbsource( "$IP/extensions/GlobalBlocking/localdb_patches/setup-global_block_whitelist.sql", $dbw );
54 - dbsource( "$IP/extensions/AbuseFilter/abusefilter.tables.sql", $dbw );
 54+ $dbw->query( "INSERT INTO site_stats(ss_row_id) VALUES (1)" );
5555
56 - $dbw->query( "INSERT INTO site_stats(ss_row_id) VALUES (1)" );
 56+ # Initialise external storage
 57+ if ( is_array( $wgDefaultExternalStore ) ) {
 58+ $stores = $wgDefaultExternalStore;
 59+ } elseif ( $stores ) {
 60+ $stores = array( $wgDefaultExternalStore );
 61+ } else {
 62+ $stores = array();
 63+ }
 64+ if ( count( $stores ) ) {
 65+ global $wgDBuser, $wgDBpassword, $wgExternalServers;
 66+ foreach ( $stores as $storeURL ) {
 67+ $m = array();
 68+ if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
 69+ continue;
 70+ }
5771
58 - # Initialise external storage
59 - if ( is_array( $wgDefaultExternalStore ) ) {
60 - $stores = $wgDefaultExternalStore;
61 - } elseif ( $stores ) {
62 - $stores = array( $wgDefaultExternalStore );
63 - } else {
64 - $stores = array();
65 - }
66 - if ( count( $stores ) ) {
67 - require_once( 'ExternalStoreDB.php' );
68 - global $wgDBuser, $wgDBpassword, $wgExternalServers;
69 - foreach ( $stores as $storeURL ) {
70 - $m = array();
71 - if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
72 - continue;
73 - }
74 -
75 - $cluster = $m[1];
76 - print "Initialising external storage $cluster...\n";
77 -
78 - # Hack
79 - $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
80 - $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
 72+ $cluster = $m[1];
 73+ $this->output( "Initialising external storage $cluster...\n" );
8174
82 - $store = new ExternalStoreDB;
83 - $extdb = $store->getMaster( $cluster );
84 - $extdb->query( "SET table_type=InnoDB" );
85 - $extdb->query( "CREATE DATABASE $dbName" );
86 - $extdb->selectDB( $dbName );
 75+ # Hack
 76+ $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
 77+ $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
8778
88 - # Hack x2
89 - $blobsTable = $store->getTable( $extdb );
90 - $blobsFile = popen( "sed s/blobs\\\\\\>/$blobsTable/ $maintenance/storage/blobs.sql", 'r' );
91 - $extdb->sourceStream( $blobsFile );
92 - pclose( $blobsFile );
93 - $extdb->immediateCommit();
 79+ $store = new ExternalStoreDB;
 80+ $extdb = $store->getMaster( $cluster );
 81+ $extdb->query( "SET table_type=InnoDB" );
 82+ $extdb->query( "CREATE DATABASE $dbName" );
 83+ $extdb->selectDB( $dbName );
 84+
 85+ # Hack x2
 86+ $blobsTable = $store->getTable( $extdb );
 87+ $sedCmd = "sed s/blobs\\\\\\>/$blobsTable/ " . $this->getDir() . "/storage/blobs.sql";
 88+ $blobsFile = popen( $sedCmd, 'r' );
 89+ $extdb->sourceStream( $blobsFile );
 90+ pclose( $blobsFile );
 91+ $extdb->immediateCommit();
 92+ }
9493 }
95 - }
9694
97 - global $wgTitle, $wgArticle;
98 - $wgTitle = Title::newFromText( wfMsgWeirdKey( "mainpage/$lang" ) );
99 - print "Writing main page to " . $wgTitle->getPrefixedDBkey() . "\n";
100 - $wgArticle = new Article( $wgTitle );
101 - $ucsite = ucfirst( $site );
 95+ global $wgTitle, $wgArticle;
 96+ $wgTitle = Title::newFromText( wfMsgWeirdKey( "mainpage/$lang" ) );
 97+ $this->output( "Writing main page to " . $wgTitle->getPrefixedDBkey() . "\n" );
 98+ $wgArticle = new Article( $wgTitle );
 99+ $ucsite = ucfirst( $site );
102100
103 - $wgArticle->insertNewArticle( <<<EOT
104 -==This subdomain is reserved for the creation of a [[wikimedia:Our projects|$ucsite]] in '''[[w:en:{$name}|{$name}]]''' language==
 101+ $wgArticle->insertNewArticle( $this->getFirstArticle( $ucsite, $name ), '', false, false );
105102
106 -* Please '''do not start editing''' this new site. This site has a test project on the [[incubator:|Wikimedia Incubator]] (or on the [[betawikiversity:|BetaWikiversity]] or on the [[oldwikisource:|Old Wikisource]]) and it will be imported to here.
 103+ $this->output( "Adding to dblists\n" );
107104
108 -* If you would like to help translating the interface to this language, please do not translate here, but go to [[betawiki:|Betawiki]], a special wiki for translating the interface. That way everyone can use it on every wiki using the [[mw:|same software]].
 105+ # Add to dblist
 106+ $file = fopen( "$common/all.dblist", "a" );
 107+ fwrite( $file, "$dbName\n" );
 108+ fclose( $file );
109109
110 -* For information about how to edit and for other general help, see [[m:Help:Contents|Help on Wikimedia's Meta-Wiki]] or [[mw:Help:Contents|Help on MediaWiki.org]].
 110+ # Update the sublists
 111+ shell_exec("cd $common && ./refresh-dblist");
111112
112 -== Sister projects ==
113 -<span class="plainlinks">
114 -[http://www.wikipedia.org Wikipedia] |
115 -[http://www.wiktionary.org Wiktonary] |
116 -[http://www.wikibooks.org Wikibooks] |
117 -[http://www.wikinews.org Wikinews] |
118 -[http://www.wikiquote.org Wikiquote] |
119 -[http://www.wikisource.org Wikisource]
120 -[http://www.wikiversity.org Wikiversity]
121 -</span>
 113+ #print "Constructing interwiki SQL\n";
 114+ # Rebuild interwiki tables
 115+ #passthru( '/home/wikipedia/conf/interwiki/update' );
122116
123 -See Wikimedia's [[m:|Meta-Wiki]] for the coordination of these projects.
 117+ $this->output( "Script ended. You still have to:
 118+ * Add any required settings in InitialiseSettings.php
 119+ * Run sync-common-all
 120+ * Run /home/wikipedia/conf/interwiki/update
 121+ " );
 122+ }
 123+
 124+ private function getFirstArticle( $ucsite, $name ) {
 125+ return <<<EOT
 126+ ==This subdomain is reserved for the creation of a [[wikimedia:Our projects|$ucsite]] in '''[[w:en:{$name}|{$name}]]''' language==
124127
125 -[[aa:]]
126 -[[af:]]
127 -[[als:]]
128 -[[ar:]]
129 -[[de:]]
130 -[[en:]]
131 -[[as:]]
132 -[[ast:]]
133 -[[ay:]]
134 -[[az:]]
135 -[[bcl:]]
136 -[[be:]]
137 -[[bg:]]
138 -[[bn:]]
139 -[[bo:]]
140 -[[bs:]]
141 -[[cs:]]
142 -[[co:]]
143 -[[cs:]]
144 -[[cy:]]
145 -[[da:]]
146 -[[el:]]
147 -[[eo:]]
148 -[[es:]]
149 -[[et:]]
150 -[[eu:]]
151 -[[fa:]]
152 -[[fi:]]
153 -[[fr:]]
154 -[[fy:]]
155 -[[ga:]]
156 -[[gl:]]
157 -[[gn:]]
158 -[[gu:]]
159 -[[he:]]
160 -[[hi:]]
161 -[[hr:]]
162 -[[hsb:]]
163 -[[hy:]]
164 -[[ia:]]
165 -[[id:]]
166 -[[is:]]
167 -[[it:]]
168 -[[ja:]]
169 -[[ka:]]
170 -[[kk:]]
171 -[[km:]]
172 -[[kn:]]
173 -[[ko:]]
174 -[[ks:]]
175 -[[ku:]]
176 -[[ky:]]
177 -[[la:]]
178 -[[ln:]]
179 -[[lo:]]
180 -[[lt:]]
181 -[[lv:]]
182 -[[hu:]]
183 -[[mi:]]
184 -[[mk:]]
185 -[[ml:]]
186 -[[mn:]]
187 -[[mr:]]
188 -[[ms:]]
189 -[[mt:]]
190 -[[my:]]
191 -[[na:]]
192 -[[nah:]]
193 -[[nds:]]
194 -[[ne:]]
195 -[[nl:]]
196 -[[no:]]
197 -[[oc:]]
198 -[[om:]]
199 -[[pa:]]
200 -[[pl:]]
201 -[[ps:]]
202 -[[pt:]]
203 -[[qu:]]
204 -[[ro:]]
205 -[[ru:]]
206 -[[sa:]]
207 -[[si:]]
208 -[[sk:]]
209 -[[sl:]]
210 -[[sq:]]
211 -[[sr:]]
212 -[[sv:]]
213 -[[sw:]]
214 -[[ta:]]
215 -[[te:]]
216 -[[tg:]]
217 -[[th:]]
218 -[[tk:]]
219 -[[tl:]]
220 -[[tr:]]
221 -[[tt:]]
222 -[[ug:]]
223 -[[uk:]]
224 -[[ur:]]
225 -[[uz:]]
226 -[[vi:]]
227 -[[vo:]]
228 -[[xh:]]
229 -[[yo:]]
230 -[[za:]]
231 -[[zh:]]
232 -[[zu:]]
 128+ * Please '''do not start editing''' this new site. This site has a test project on the [[incubator:|Wikimedia Incubator]] (or on the [[betawikiversity:|BetaWikiversity]] or on the [[oldwikisource:|Old Wikisource]]) and it will be imported to here.
233129
234 -EOT
235 -, '', false, false );
 130+ * If you would like to help translating the interface to this language, please do not translate here, but go to [[betawiki:|Betawiki]], a special wiki for translating the interface. That way everyone can use it on every wiki using the [[mw:|same software]].
236131
237 - print "Adding to dblists\n";
 132+ * For information about how to edit and for other general help, see [[m:Help:Contents|Help on Wikimedia's Meta-Wiki]] or [[mw:Help:Contents|Help on MediaWiki.org]].
238133
239 - # Add to dblist
240 - $file = fopen( "$common/all.dblist", "a" );
241 - fwrite( $file, "$dbName\n" );
242 - fclose( $file );
 134+ == Sister projects ==
 135+ <span class="plainlinks">
 136+ [http://www.wikipedia.org Wikipedia] |
 137+ [http://www.wiktionary.org Wiktonary] |
 138+ [http://www.wikibooks.org Wikibooks] |
 139+ [http://www.wikinews.org Wikinews] |
 140+ [http://www.wikiquote.org Wikiquote] |
 141+ [http://www.wikisource.org Wikisource]
 142+ [http://www.wikiversity.org Wikiversity]
 143+ </span>
243144
244 - # Update the sublists
245 - shell_exec("cd $common && ./refresh-dblist");
 145+ See Wikimedia's [[m:|Meta-Wiki]] for the coordination of these projects.
246146
247 - #print "Constructing interwiki SQL\n";
248 - # Rebuild interwiki tables
249 - #passthru( '/home/wikipedia/conf/interwiki/update' );
 147+ [[aa:]]
 148+ [[af:]]
 149+ [[als:]]
 150+ [[ar:]]
 151+ [[de:]]
 152+ [[en:]]
 153+ [[as:]]
 154+ [[ast:]]
 155+ [[ay:]]
 156+ [[az:]]
 157+ [[bcl:]]
 158+ [[be:]]
 159+ [[bg:]]
 160+ [[bn:]]
 161+ [[bo:]]
 162+ [[bs:]]
 163+ [[cs:]]
 164+ [[co:]]
 165+ [[cs:]]
 166+ [[cy:]]
 167+ [[da:]]
 168+ [[el:]]
 169+ [[eo:]]
 170+ [[es:]]
 171+ [[et:]]
 172+ [[eu:]]
 173+ [[fa:]]
 174+ [[fi:]]
 175+ [[fr:]]
 176+ [[fy:]]
 177+ [[ga:]]
 178+ [[gl:]]
 179+ [[gn:]]
 180+ [[gu:]]
 181+ [[he:]]
 182+ [[hi:]]
 183+ [[hr:]]
 184+ [[hsb:]]
 185+ [[hy:]]
 186+ [[ia:]]
 187+ [[id:]]
 188+ [[is:]]
 189+ [[it:]]
 190+ [[ja:]]
 191+ [[ka:]]
 192+ [[kk:]]
 193+ [[km:]]
 194+ [[kn:]]
 195+ [[ko:]]
 196+ [[ks:]]
 197+ [[ku:]]
 198+ [[ky:]]
 199+ [[la:]]
 200+ [[ln:]]
 201+ [[lo:]]
 202+ [[lt:]]
 203+ [[lv:]]
 204+ [[hu:]]
 205+ [[mi:]]
 206+ [[mk:]]
 207+ [[ml:]]
 208+ [[mn:]]
 209+ [[mr:]]
 210+ [[ms:]]
 211+ [[mt:]]
 212+ [[my:]]
 213+ [[na:]]
 214+ [[nah:]]
 215+ [[nds:]]
 216+ [[ne:]]
 217+ [[nl:]]
 218+ [[no:]]
 219+ [[oc:]]
 220+ [[om:]]
 221+ [[pa:]]
 222+ [[pl:]]
 223+ [[ps:]]
 224+ [[pt:]]
 225+ [[qu:]]
 226+ [[ro:]]
 227+ [[ru:]]
 228+ [[sa:]]
 229+ [[si:]]
 230+ [[sk:]]
 231+ [[sl:]]
 232+ [[sq:]]
 233+ [[sr:]]
 234+ [[sv:]]
 235+ [[sw:]]
 236+ [[ta:]]
 237+ [[te:]]
 238+ [[tg:]]
 239+ [[th:]]
 240+ [[tk:]]
 241+ [[tl:]]
 242+ [[tr:]]
 243+ [[tt:]]
 244+ [[ug:]]
 245+ [[uk:]]
 246+ [[ur:]]
 247+ [[uz:]]
 248+ [[vi:]]
 249+ [[vo:]]
 250+ [[xh:]]
 251+ [[yo:]]
 252+ [[za:]]
 253+ [[zh:]]
 254+ [[zu:]]
250255
251 - print "Script ended. You still have to:
252 -* Add any required settings in InitialiseSettings.php
253 -* Run sync-common-all
254 -* Run /home/wikipedia/conf/interwiki/update
255 -";
 256+EOT;
 257+ }
256258 }
257259
 260+$maintClass = "AddWiki";
 261+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/maintenance/patchSql.php
@@ -20,7 +20,7 @@
2121 foreach( $files as $file ) {
2222 if( file_exists( $file ) ) {
2323 echo "$file ...\n";
24 - dbsource( $file );
 24+ wfGetDB( DB_MASTER )->fileSource( $file );
2525 continue 2;
2626 }
2727 }
Index: branches/maintenance-work/maintenance/Maintenance.php
@@ -675,6 +675,13 @@
676676 # Done
677677 $dbw->commit();
678678 }
 679+
 680+ /**
 681+ * Get the maintenance directory.
 682+ */
 683+ protected function getDir() {
 684+ return dirname( __FILE__ );
 685+ }
679686
680687 /**
681688 * Get the list of available maintenance scripts. Note
@@ -695,6 +702,7 @@
696703 if( !self::$mCoreScripts ) {
697704 $d = dirname( __FILE__ ) . DIRECTORY_SEPARATOR;
698705 self::$mCoreScripts = array(
 706+ 'AddWiki' => $d . 'addwiki.php',
699707 'AttachLatest' => $d . 'attachLatest.php',
700708 'BenchmarkPurge' => $d . 'benchmarkPurge.php',
701709 'ChangePassword' => $d . 'changePassword.php',
@@ -723,6 +731,8 @@
724732 'EditCLI' => $d . 'edit.php',
725733 'EvalPrompt' => $d . 'eval.php',
726734 'FetchText' => $d . 'fetchText.php',
 735+ 'FixSlaveDesync' => $d . 'fixSlaveDesync.php',
 736+ 'FixTimestamps' => $d . 'fixTimestamps.php',
727737 'FixUserRegistration' => $d . 'fixUserRegistration.php',
728738 'GenerateSitemap' => $d . 'generateSitemap.php',
729739 'GetLagTimes' => $d . 'getLagTimes.php',
@@ -752,6 +762,7 @@
753763 'RefreshLinks' => $d . 'refreshLinks.php',
754764 'RemoveUnusedAccounts' => $d . 'removeUnusedAccounts.php',
755765 'RenameDbPrefix' => $d . 'renameDbPrefix.php',
 766+ 'RenameWiki' => $d . 'renamewiki.php',
756767 'DumpRenderer' => $d . 'renderDump.php',
757768 'RunJobs' => $d . 'runJobs.php',
758769 'ShowJobs' => $d . 'showJobs.php',
Index: branches/maintenance-work/maintenance/fixTimestamps.php
@@ -9,98 +9,99 @@
1010 * @file
1111 * @ingroup Maintenance
1212 */
 13+
 14+require_once( "Maintenance.php" );
1315
14 -require_once( 'commandLine.inc' );
 16+class FixTimestamps extends Maintenance {
 17+ public function __construct() {
 18+ parent::__construct();
 19+ $this->mDescription = "";
 20+ $this->addArgs( array( 'offset', 'start', 'end' ) );
 21+ }
1522
16 -if ( count( $args ) < 3 ) {
17 - echo "Usage: php fixTimestamps.php <offset in hours> <start time> <end time>\n";
18 - exit(1);
19 -}
 23+ public function execute() {
 24+ $offset = $this->getArg(0) * 3600;
 25+ $start = $this->getArg(1);
 26+ $end = $this->getArg(2);
 27+ $grace = 60; // maximum normal clock offset
 28+
 29+ # Find bounding revision IDs
 30+ $dbw = wfGetDB( DB_MASTER );
 31+ $revisionTable = $dbw->tableName( 'revision' );
 32+ $res = $dbw->query( "SELECT MIN(rev_id) as minrev, MAX(rev_id) as maxrev FROM $revisionTable " .
 33+ "WHERE rev_timestamp BETWEEN '{$start}' AND '{$end}'", __METHOD__ );
 34+ $row = $dbw->fetchObject( $res );
 35+
 36+ if ( is_null( $row->minrev ) ) {
 37+ $this->error( "No revisions in search period.\n", true );
 38+ }
 39+
 40+ $minRev = $row->minrev;
 41+ $maxRev = $row->maxrev;
 42+
 43+ # Select all timestamps and IDs
 44+ $sql = "SELECT rev_id, rev_timestamp FROM $revisionTable " .
 45+ "WHERE rev_id BETWEEN $minRev AND $maxRev";
 46+ if ( $offset > 0 ) {
 47+ $sql .= " ORDER BY rev_id DESC";
 48+ $expectedSign = -1;
 49+ } else {
 50+ $expectedSign = 1;
 51+ }
 52+
 53+ $res = $dbw->query( $sql, __METHOD__ );
 54+
 55+ $lastNormal = 0;
 56+ $badRevs = array();
 57+ $numGoodRevs = 0;
 58+
 59+ while ( $row = $dbw->fetchObject( $res ) ) {
 60+ $timestamp = wfTimestamp( TS_UNIX, $row->rev_timestamp );
 61+ $delta = $timestamp - $lastNormal;
 62+ $sign = $delta == 0 ? 0 : $delta / abs( $delta );
 63+ if ( $sign == 0 || $sign == $expectedSign ) {
 64+ // Monotonic change
 65+ $lastNormal = $timestamp;
 66+ ++ $numGoodRevs;
 67+ continue;
 68+ } elseif ( abs( $delta ) <= $grace ) {
 69+ // Non-monotonic change within grace interval
 70+ ++ $numGoodRevs;
 71+ continue;
 72+ } else {
 73+ // Non-monotonic change larger than grace interval
 74+ $badRevs[] = $row->rev_id;
 75+ }
 76+ }
 77+ $dbw->freeResult( $res );
 78+
 79+ $numBadRevs = count( $badRevs );
 80+ if ( $numBadRevs > $numGoodRevs ) {
 81+ $this->error(
 82+ "The majority of revisions in the search interval are marked as bad.
2083
21 -$offset = $args[0] * 3600;
22 -$start = $args[1];
23 -$end = $args[2];
24 -$fname = 'fixTimestamps.php';
25 -$grace = 60; // maximum normal clock offset
 84+ Are you sure the offset ($offset) has the right sign? Positive means the clock
 85+ was incorrectly set forward, negative means the clock was incorrectly set back.
2686
27 -# Find bounding revision IDs
28 -$dbw = wfGetDB( DB_MASTER );
29 -$revisionTable = $dbw->tableName( 'revision' );
30 -$res = $dbw->query( "SELECT MIN(rev_id) as minrev, MAX(rev_id) as maxrev FROM $revisionTable " .
31 - "WHERE rev_timestamp BETWEEN '{$start}' AND '{$end}'", $fname );
32 -$row = $dbw->fetchObject( $res );
33 -
34 -if ( is_null( $row->minrev ) ) {
35 - echo "No revisions in search period.\n";
36 - exit(0);
37 -}
38 -
39 -$minRev = $row->minrev;
40 -$maxRev = $row->maxrev;
41 -
42 -# Select all timestamps and IDs
43 -$sql = "SELECT rev_id, rev_timestamp FROM $revisionTable " .
44 - "WHERE rev_id BETWEEN $minRev AND $maxRev";
45 -if ( $offset > 0 ) {
46 - $sql .= " ORDER BY rev_id DESC";
47 - $expectedSign = -1;
48 -} else {
49 - $expectedSign = 1;
50 -}
51 -
52 -$res = $dbw->query( $sql, $fname );
53 -
54 -$lastNormal = 0;
55 -$badRevs = array();
56 -$numGoodRevs = 0;
57 -
58 -while ( $row = $dbw->fetchObject( $res ) ) {
59 - $timestamp = wfTimestamp( TS_UNIX, $row->rev_timestamp );
60 - $delta = $timestamp - $lastNormal;
61 - $sign = $delta == 0 ? 0 : $delta / abs( $delta );
62 - if ( $sign == 0 || $sign == $expectedSign ) {
63 - // Monotonic change
64 - $lastNormal = $timestamp;
65 - ++ $numGoodRevs;
66 - continue;
67 - } elseif ( abs( $delta ) <= $grace ) {
68 - // Non-monotonic change within grace interval
69 - ++ $numGoodRevs;
70 - continue;
71 - } else {
72 - // Non-monotonic change larger than grace interval
73 - $badRevs[] = $row->rev_id;
 87+ If the offset is right, then increase the search interval until there are enough
 88+ good revisions to provide a majority reference.
 89+ ", true );
 90+ } elseif ( $numBadRevs == 0 ) {
 91+ $this->output( "No bad revisions found.\n" );
 92+ exit(0);
 93+ }
 94+
 95+ $this->output( sprintf( "Fixing %d revisions (%.2f%% of revisions in search interval)\n",
 96+ $numBadRevs, $numBadRevs / ($numGoodRevs + $numBadRevs) * 100 ) );
 97+
 98+ $fixup = -$offset;
 99+ $sql = "UPDATE $revisionTable " .
 100+ "SET rev_timestamp=DATE_FORMAT(DATE_ADD(rev_timestamp, INTERVAL $fixup SECOND), '%Y%m%d%H%i%s') " .
 101+ "WHERE rev_id IN (" . $dbw->makeList( $badRevs ) . ')';
 102+ $dbw->query( $sql, __METHOD__ );
 103+ $this->output( "Done\n" );
74104 }
75105 }
76 -$dbw->freeResult( $res );
77106
78 -$numBadRevs = count( $badRevs );
79 -if ( $numBadRevs > $numGoodRevs ) {
80 - echo
81 -"The majority of revisions in the search interval are marked as bad.
82 -
83 -Are you sure the offset ($offset) has the right sign? Positive means the clock
84 -was incorrectly set forward, negative means the clock was incorrectly set back.
85 -
86 -If the offset is right, then increase the search interval until there are enough
87 -good revisions to provide a majority reference.
88 -";
89 -
90 - exit(1);
91 -} elseif ( $numBadRevs == 0 ) {
92 - echo "No bad revisions found.\n";
93 - exit(0);
94 -}
95 -
96 -printf( "Fixing %d revisions (%.2f%% of revisions in search interval)\n",
97 - $numBadRevs, $numBadRevs / ($numGoodRevs + $numBadRevs) * 100 );
98 -
99 -$fixup = -$offset;
100 -$sql = "UPDATE $revisionTable " .
101 - "SET rev_timestamp=DATE_FORMAT(DATE_ADD(rev_timestamp, INTERVAL $fixup SECOND), '%Y%m%d%H%i%s') " .
102 - "WHERE rev_id IN (" . $dbw->makeList( $badRevs ) . ')';
103 -//echo "$sql\n";
104 -$dbw->query( $sql, $fname );
105 -echo "Done\n";
106 -
107 -
 107+$maintClass = "FixTimestamps";
 108+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/maintenance/populateLogUsertext.php
@@ -9,9 +9,59 @@
1010 * @ingroup Maintenance
1111 */
1212
13 -require_once 'commandLine.inc';
14 -require_once 'populateLogUsertext.inc';
15 -
16 -$db =& wfGetDB( DB_MASTER );
 13+require_once( "Maintenance.php" );
1714
18 -populate_logusertext( $db );
 15+class PopulateLogUsertext extends Maintenance {
 16+ public function __construct() {
 17+ parent::__construct();
 18+ $this->mDescription = "Populates the log_user_text";
 19+ $this->setBatchSize( 100 );
 20+ }
 21+
 22+ public function execute() {
 23+ $db = wfGetDB( DB_MASTER );
 24+ $start = $db->selectField( 'logging', 'MIN(log_id)', false, __METHOD__ );
 25+ if( !$start ) {
 26+ $this->output( "Nothing to do.\n" );
 27+ return true;
 28+ }
 29+ $end = $db->selectField( 'logging', 'MAX(log_id)', false, __METHOD__ );
 30+
 31+ # Do remaining chunk
 32+ $end += $this->mBatchSize - 1;
 33+ $blockStart = $start;
 34+ $blockEnd = $start + $this->mBatchSize - 1;
 35+ while( $blockEnd <= $end ) {
 36+ $this->output( "...doing log_id from $blockStart to $blockEnd\n" );
 37+ $cond = "log_id BETWEEN $blockStart AND $blockEnd AND log_user = user_id";
 38+ $res = $db->select( array('logging','user'),
 39+ array('log_id','user_name'), $cond, __METHOD__ );
 40+ $batch = array();
 41+ $db->begin();
 42+ while( $row = $db->fetchObject( $res ) ) {
 43+ $db->update( 'logging', array('log_user_text' => $row->user_name),
 44+ array('log_id' => $row->log_id), __METHOD__ );
 45+ }
 46+ $db->commit();
 47+ $blockStart += $this->mBatchSize;
 48+ $blockEnd += $this->mBatchSize;
 49+ wfWaitForSlaves( 5 );
 50+ }
 51+ if( $db->insert(
 52+ 'updatelog',
 53+ array( 'ul_key' => 'populate log_usertext' ),
 54+ __METHOD__,
 55+ 'IGNORE'
 56+ )
 57+ ) {
 58+ $this->output( "log_usertext population complete.\n" );
 59+ return true;
 60+ } else {
 61+ $this->output( "Could not insert log_usertext population row.\n" );
 62+ return false;
 63+ }
 64+ }
 65+}
 66+
 67+$maintClass = "PopulateLogUsertext";
 68+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/maintenance/namespaceDupes.php
@@ -22,33 +22,50 @@
2323 * @ingroup Maintenance
2424 */
2525
26 -$options = array( 'fix', 'suffix', 'help' );
 26+require_once( "Maintenance.php" );
2727
28 -/** */
29 -require_once( 'commandLine.inc' );
 28+class NamespaceConflictChecker extends Maintenance {
 29+ public function __construct() {
 30+ parent::__construct();
 31+ $this->mDescription = "";
 32+ $this->addOption( 'fix', 'Attempt to automatically fix errors' );
 33+ $this->addOption( 'suffix', "Dupes will be renamed with correct namespace with\n" .
 34+ "\t\t<text> Appended after the article name", false, true );
 35+ $this->addOption( 'prefix', "Do an explicit check for the given title prefix\n" .
 36+ "\t\tappended after the article name", false, true );
 37+ $this->addOption( 'wiki', 'Enter the wiki database to edit', false, true );
 38+ }
3039
31 -if(isset( $options['help'] ) ) {
32 -print <<<ENDS
33 -usage: namespaceDupes.php [--fix] [--suffix=<text>] [--help]
34 - --help : this help message
35 - --fix : attempt to automatically fix errors
36 - --suffix=<text> : dupes will be renamed with correct namespace with <text>
37 - appended after the article name.
38 - --prefix=<text> : Do an explicit check for the given title prefix
39 - in place of the standard namespace list.
40 - --verbose : Display output for checked namespaces without conflicts
41 - --wiki=<wiki> : enter the wiki database to edit
42 -ENDS;
43 -die;
44 -}
 40+ public function execute() {
 41+ global $wgTitle;
4542
46 -class NamespaceConflictChecker {
47 - function NamespaceConflictChecker( $db, $verbose=false ) {
48 - $this->db = $db;
49 - $this->verbose = $verbose;
 43+ $this->db = wfGetDB( DB_MASTER );
 44+ $wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' );
 45+
 46+ $fix = $this->hasOption( 'fix' );
 47+ $suffix = $this->getOption( 'suffix', '' );
 48+ $prefix = $this->getOption( 'prefix', '' );
 49+ $key = intval( $this->getOption( 'key', 0 ) );
 50+
 51+ if( $prefix ) {
 52+ $retval = $this->checkPrefix( $key, $prefix, $fix, $suffix );
 53+ } else {
 54+ $retval = $this->checkAll( $fix, $suffix );
 55+ }
 56+
 57+ if( $retval ) {
 58+ $this->output( "\nLooks good!\n" );
 59+ } else {
 60+ $this->output( "\nOh noeees\n" );
 61+ }
5062 }
5163
52 - function checkAll( $fix, $suffix = '' ) {
 64+ /**
 65+ * @todo Document
 66+ * @param $fix bool Whether or not to fix broken entries
 67+ * @param $suffix String Suffix to append to renamed articles
 68+ */
 69+ private function checkAll( $fix, $suffix = '' ) {
5370 global $wgContLang, $wgNamespaceAliases, $wgCanonicalNamespaceNames;
5471 global $wgCapitalLinks;
5572
@@ -112,7 +129,11 @@
113130 }
114131 return $ok;
115132 }
116 -
 133+
 134+ /**
 135+ * Get the interwiki list
 136+ * @return array
 137+ */
117138 private function getInterwikiList() {
118139 $result = $this->db->select( 'interwiki', array( 'iw_prefix' ) );
119140 $prefixes = array();
@@ -123,7 +144,14 @@
124145 return $prefixes;
125146 }
126147
127 - function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
 148+ /**
 149+ * @todo Document
 150+ * @param $ns int A namespace id
 151+ * @param $name String
 152+ * @param $fix bool Whether to fix broken entries
 153+ * @param $suffix String Suffix to append to renamed articles
 154+ */
 155+ private function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
128156 if( $ns == 0 ) {
129157 $header = "Checking interwiki prefix: \"$name\"\n";
130158 } else {
@@ -133,15 +161,11 @@
134162 $conflicts = $this->getConflicts( $ns, $name );
135163 $count = count( $conflicts );
136164 if( $count == 0 ) {
137 - if( $this->verbose ) {
138 - echo $header;
139 - echo "... no conflicts detected!\n";
140 - }
 165+ $this->output( $header . "... no conflict detected!\n" );
141166 return true;
142167 }
143168
144 - echo $header;
145 - echo "... $count conflicts detected:\n";
 169+ $this->output( $header . "... $count conflicts detected:\n" );
146170 $ok = true;
147171 foreach( $conflicts as $row ) {
148172 $resolvable = $this->reportConflict( $row, $suffix );
@@ -156,12 +180,18 @@
157181 /**
158182 * @todo: do this for reals
159183 */
160 - function checkPrefix( $key, $prefix, $fix, $suffix = '' ) {
161 - echo "Checking prefix \"$prefix\" vs namespace $key\n";
 184+ private function checkPrefix( $key, $prefix, $fix, $suffix = '' ) {
 185+ $this->output( "Checking prefix \"$prefix\" vs namespace $key\n" );
162186 return $this->checkNamespace( $key, $prefix, $fix, $suffix );
163187 }
164188
165 - function getConflicts( $ns, $name ) {
 189+ /**
 190+ * Find pages in mainspace that have a prefix of the new namespace
 191+ * so we know titles that will need migrating
 192+ * @param $ns int Namespace id (id for new namespace?)
 193+ * @param $name String Prefix that is being made a namespace
 194+ */
 195+ private function getConflicts( $ns, $name ) {
166196 $page = 'page';
167197 $table = $this->db->tableName( $page );
168198
@@ -194,52 +224,61 @@
195225 return $set;
196226 }
197227
198 - function reportConflict( $row, $suffix ) {
 228+ /**
 229+ * Report any conflicts we find
 230+ */
 231+ private function reportConflict( $row, $suffix ) {
199232 $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
200233 if( is_null($newTitle) || !$newTitle->canExist() ) {
201234 // Title is also an illegal title...
202235 // For the moment we'll let these slide to cleanupTitles or whoever.
203 - printf( "... %d (0,\"%s\")\n",
 236+ $this->output( sprintf( "... %d (0,\"%s\")\n",
204237 $row->id,
205 - $row->oldtitle );
206 - echo "... *** cannot resolve automatically; illegal title ***\n";
 238+ $row->oldtitle ) );
 239+ $this->output( "... *** cannot resolve automatically; illegal title ***\n" );
207240 return false;
208241 }
209 -
210 - printf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
 242+
 243+ $this->output( sprintf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
211244 $row->id,
212245 $row->oldtitle,
213246 $newTitle->getNamespace(),
214247 $newTitle->getDBkey(),
215 - $newTitle->getPrefixedText() );
 248+ $newTitle->getPrefixedText() ) );
216249
217250 $id = $newTitle->getArticleId();
218251 if( $id ) {
219 - echo "... *** cannot resolve automatically; page exists with ID $id ***\n";
 252+ $this->output( "... *** cannot resolve automatically; page exists with ID $id ***\n" );
220253 return false;
221254 } else {
222255 return true;
223256 }
224257 }
225258
226 - function resolveConflict( $row, $resolvable, $suffix ) {
 259+ /**
 260+ * Resolve any conflicts
 261+ * @param $row Row from the page table to fix
 262+ * @param $resolveable bool
 263+ * @param $suffix String Suffix to append to the fixed page
 264+ */
 265+ private function resolveConflict( $row, $resolvable, $suffix ) {
227266 if( !$resolvable ) {
228 - echo "... *** old title {$row->title}\n";
 267+ $this->output( "... *** old title {$row->title}\n" );
229268 while( true ) {
230269 $row->title .= $suffix;
231 - echo "... *** new title {$row->title}\n";
 270+ $this->output( "... *** new title {$row->title}\n" );
232271 $title = Title::makeTitleSafe( $row->namespace, $row->title );
233272 if ( ! $title ) {
234 - echo "... !!! invalid title\n";
 273+ $this->output( "... !!! invalid title\n" );
235274 return false;
236275 }
237276 if ( $id = $title->getArticleId() ) {
238 - echo "... *** page exists with ID $id ***\n";
 277+ $this->output( "... *** page exists with ID $id ***\n" );
239278 } else {
240279 break;
241280 }
242281 }
243 - echo "... *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n";
 282+ $this->output( "... *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n" );
244283 }
245284 $tables = array( 'page' );
246285 foreach( $tables as $table ) {
@@ -248,8 +287,13 @@
249288 return true;
250289 }
251290
252 - function resolveConflictOn( $row, $table ) {
253 - echo "... resolving on $table... ";
 291+ /**
 292+ * Resolve a given conflict
 293+ * @param $row Row from the old broken entry
 294+ * @param $table String Table to update
 295+ */
 296+ private function resolveConflictOn( $row, $table ) {
 297+ $this->output( "... resolving on $table... " );
254298 $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
255299 $this->db->update( $table,
256300 array(
@@ -261,37 +305,10 @@
262306 "{$table}_title" => $row->oldtitle,
263307 ),
264308 __METHOD__ );
265 - echo "ok.\n";
 309+ $this->output( "ok.\n" );
266310 return true;
267311 }
268312 }
269313
270 -
271 -
272 -
273 -$wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' );
274 -
275 -$verbose = isset( $options['verbose'] );
276 -$fix = isset( $options['fix'] );
277 -$suffix = isset( $options['suffix'] ) ? $options['suffix'] : '';
278 -$prefix = isset( $options['prefix'] ) ? $options['prefix'] : '';
279 -$key = isset( $options['key'] ) ? intval( $options['key'] ) : 0;
280 -
281 -$dbw = wfGetDB( DB_MASTER );
282 -$duper = new NamespaceConflictChecker( $dbw, $verbose );
283 -
284 -if( $prefix ) {
285 - $retval = $duper->checkPrefix( $key, $prefix, $fix, $suffix );
286 -} else {
287 - $retval = $duper->checkAll( $fix, $suffix );
288 -}
289 -
290 -if( $retval ) {
291 - echo "\nLooks good!\n";
292 - exit( 0 );
293 -} else {
294 - echo "\nOh noeees\n";
295 - exit( -1 );
296 -}
297 -
298 -
 314+$maintClass = "NamespaceConflictChecker";
 315+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/maintenance/fixSlaveDesync.php
@@ -4,193 +4,199 @@
55 * @ingroup Maintenance
66 */
77
8 -$wgUseRootUser = true;
9 -require_once( 'commandLine.inc' );
 8+require_once( "Maintenance.php" );
109
11 -//$wgDebugLogFile = '/dev/stdout';
12 -
13 -$slaveIndexes = array();
14 -for ( $i = 1; $i < count( $wgDBservers ); $i++ ) {
15 - if ( wfGetLB()->isNonZeroLoad( $i ) ) {
16 - $slaveIndexes[] = $i;
 10+class FixSlaveDesync extends Maintenance {
 11+ public function __construct() {
 12+ parent::__construct();
 13+ $this->mDescription = "";
 14+
1715 }
18 -}
19 -/*
20 -foreach ( wfGetLB()->mServers as $i => $server ) {
21 - wfGetLB()->mServers[$i]['flags'] |= DBO_DEBUG;
22 -}*/
23 -$reportingInterval = 1000;
 16+
 17+ public function execute() {
 18+ global $wgUseRootUser, $wgDBservers;
 19+ $wgUseRootUser = true;
2420
25 -if ( isset( $args[0] ) ) {
26 - desyncFixPage( $args[0] );
27 -} else {
28 - $dbw = wfGetDB( DB_MASTER );
29 - $maxPage = $dbw->selectField( 'page', 'MAX(page_id)', false, 'fixDesync.php' );
30 - $corrupt = findPageLatestCorruption();
31 - foreach ( $corrupt as $id => $dummy ) {
32 - desyncFixPage( $id );
33 - }
34 - /*
35 - for ( $i=1; $i <= $maxPage; $i++ ) {
36 - desyncFixPage( $i );
37 - if ( !($i % $reportingInterval) ) {
38 - print "$i\n";
 21+ $slaveIndexes = array();
 22+ for ( $i = 1; $i < count( $wgDBservers ); $i++ ) {
 23+ if ( wfGetLB()->isNonZeroLoad( $i ) ) {
 24+ $slaveIndexes[] = $i;
 25+ }
3926 }
40 - }*/
41 -}
4227
43 -function findPageLatestCorruption() {
44 - $desync = array();
45 - $n = 0;
46 - $dbw = wfGetDB( DB_MASTER );
47 - $masterIDs = array();
48 - $res = $dbw->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
49 - print "Number of pages: " . $dbw->numRows( $res ) . "\n";
50 - while ( $row = $dbw->fetchObject( $res ) ) {
51 - $masterIDs[$row->page_id] = $row->page_latest;
52 - if ( !( ++$n % 10000 ) ) {
53 - print "$n\r";
 28+ if ( $this->hasArg() ) {
 29+ $this->desyncFixPage( $this->getArg() );
 30+ } else {
 31+ $dbw = wfGetDB( DB_MASTER );
 32+ $maxPage = $dbw->selectField( 'page', 'MAX(page_id)', false, __METHOD__ );
 33+ $corrupt = $this->findPageLatestCorruption();
 34+ foreach ( $corrupt as $id => $dummy ) {
 35+ $this->desyncFixPage( $id );
 36+ }
5437 }
5538 }
56 - print "\n";
57 - $dbw->freeResult( $res );
58 -
59 - global $slaveIndexes;
60 - foreach ( $slaveIndexes as $i ) {
61 - $db = wfGetDB( $i );
62 - $res = $db->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
63 - while ( $row = $db->fetchObject( $res ) ) {
64 - if ( isset( $masterIDs[$row->page_id] ) && $masterIDs[$row->page_id] != $row->page_latest ) {
65 - $desync[$row->page_id] = true;
66 - print $row->page_id . "\t";
 39+
 40+ /**
 41+ * Find all pages that have a corrupted page_latest
 42+ * @return array
 43+ */
 44+ private function findPageLatestCorruption() {
 45+ $desync = array();
 46+ $n = 0;
 47+ $dbw = wfGetDB( DB_MASTER );
 48+ $masterIDs = array();
 49+ $res = $dbw->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
 50+ $this->output( "Number of pages: " . $dbw->numRows( $res ) . "\n" );
 51+ while ( $row = $dbw->fetchObject( $res ) ) {
 52+ $masterIDs[$row->page_id] = $row->page_latest;
 53+ if ( !( ++$n % 10000 ) ) {
 54+ $this->output( "$n\r" );
6755 }
6856 }
69 - $db->freeResult( $res );
 57+ $this->output( "\n" );
 58+ $dbw->freeResult( $res );
 59+
 60+ global $slaveIndexes;
 61+ foreach ( $slaveIndexes as $i ) {
 62+ $db = wfGetDB( $i );
 63+ $res = $db->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
 64+ while ( $row = $db->fetchObject( $res ) ) {
 65+ if ( isset( $masterIDs[$row->page_id] ) && $masterIDs[$row->page_id] != $row->page_latest ) {
 66+ $desync[$row->page_id] = true;
 67+ $this->output( $row->page_id . "\t" );
 68+ }
 69+ }
 70+ $db->freeResult( $res );
 71+ }
 72+ $this->output( "\n" );
 73+ return $desync;
7074 }
71 - print "\n";
72 - return $desync;
73 -}
7475
75 -function desyncFixPage( $pageID ) {
76 - global $slaveIndexes;
77 - $fname = 'desyncFixPage';
 76+ /**
 77+ * Fix a broken page entry
 78+ * @param $pageID int The page_id to fix
 79+ */
 80+ private function desyncFixPage( $pageID ) {
 81+ global $slaveIndexes;
7882
79 - # Check for a corrupted page_latest
80 - $dbw = wfGetDB( DB_MASTER );
81 - $dbw->begin();
82 - $realLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ),
83 - $fname, 'FOR UPDATE' );
84 - #list( $masterFile, $masterPos ) = $dbw->getMasterPos();
85 - $found = false;
86 - foreach ( $slaveIndexes as $i ) {
87 - $db = wfGetDB( $i );
88 - /*
89 - if ( !$db->masterPosWait( $masterFile, $masterPos, 10 ) ) {
90 - echo "Slave is too lagged, aborting\n";
91 - $dbw->commit();
92 - sleep(10);
93 - return;
94 - }*/
95 - $latest = $db->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), $fname );
96 - $max = $db->selectField( 'revision', 'MAX(rev_id)', false, $fname );
97 - if ( $latest != $realLatest && $realLatest < $max ) {
98 - print "page_latest corrupted in page $pageID, server $i\n";
99 - $found = true;
100 - break;
 83+ # Check for a corrupted page_latest
 84+ $dbw = wfGetDB( DB_MASTER );
 85+ $dbw->begin();
 86+ $realLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ),
 87+ __METHOD__, 'FOR UPDATE' );
 88+ #list( $masterFile, $masterPos ) = $dbw->getMasterPos();
 89+ $found = false;
 90+ foreach ( $slaveIndexes as $i ) {
 91+ $db = wfGetDB( $i );
 92+ /*
 93+ if ( !$db->masterPosWait( $masterFile, $masterPos, 10 ) ) {
 94+ $this->output( "Slave is too lagged, aborting\n" );
 95+ $dbw->commit();
 96+ sleep(10);
 97+ return;
 98+ }*/
 99+ $latest = $db->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), __METHOD__ );
 100+ $max = $db->selectField( 'revision', 'MAX(rev_id)', false, __METHOD__ );
 101+ if ( $latest != $realLatest && $realLatest < $max ) {
 102+ $this->output( "page_latest corrupted in page $pageID, server $i\n" );
 103+ $found = true;
 104+ break;
 105+ }
101106 }
102 - }
103 - if ( !$found ) {
104 - print "page_id $pageID seems fine\n";
105 - $dbw->commit();
106 - return;
107 - }
 107+ if ( !$found ) {
 108+ $this->output( "page_id $pageID seems fine\n" );
 109+ $dbw->commit();
 110+ return;
 111+ }
108112
109 - # Find the missing revisions
110 - $res = $dbw->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ),
111 - $fname, 'FOR UPDATE' );
112 - $masterIDs = array();
113 - while ( $row = $dbw->fetchObject( $res ) ) {
114 - $masterIDs[] = $row->rev_id;
115 - }
116 - $dbw->freeResult( $res );
 113+ # Find the missing revisions
 114+ $res = $dbw->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ),
 115+ __METHOD__, 'FOR UPDATE' );
 116+ $masterIDs = array();
 117+ while ( $row = $dbw->fetchObject( $res ) ) {
 118+ $masterIDs[] = $row->rev_id;
 119+ }
 120+ $dbw->freeResult( $res );
117121
118 - $res = $db->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ), $fname );
119 - $slaveIDs = array();
120 - while ( $row = $db->fetchObject( $res ) ) {
121 - $slaveIDs[] = $row->rev_id;
122 - }
123 - $db->freeResult( $res );
124 - if ( count( $masterIDs ) < count( $slaveIDs ) ) {
125 - $missingIDs = array_diff( $slaveIDs, $masterIDs );
126 - if ( count( $missingIDs ) ) {
127 - print "Found " . count( $missingIDs ) . " lost in master, copying from slave... ";
128 - $dbFrom = $db;
129 - $found = true;
130 - $toMaster = true;
131 - } else {
132 - $found = false;
 122+ $res = $db->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ), __METHOD__ );
 123+ $slaveIDs = array();
 124+ while ( $row = $db->fetchObject( $res ) ) {
 125+ $slaveIDs[] = $row->rev_id;
133126 }
134 - } else {
135 - $missingIDs = array_diff( $masterIDs, $slaveIDs );
136 - if ( count( $missingIDs ) ) {
137 - print "Found " . count( $missingIDs ) . " missing revision(s), copying from master... ";
138 - $dbFrom = $dbw;
139 - $found = true;
140 - $toMaster = false;
 127+ $db->freeResult( $res );
 128+ if ( count( $masterIDs ) < count( $slaveIDs ) ) {
 129+ $missingIDs = array_diff( $slaveIDs, $masterIDs );
 130+ if ( count( $missingIDs ) ) {
 131+ $this->output( "Found " . count( $missingIDs ) . " lost in master, copying from slave... " );
 132+ $dbFrom = $db;
 133+ $found = true;
 134+ $toMaster = true;
 135+ } else {
 136+ $found = false;
 137+ }
141138 } else {
142 - $found = false;
 139+ $missingIDs = array_diff( $masterIDs, $slaveIDs );
 140+ if ( count( $missingIDs ) ) {
 141+ $this->output( "Found " . count( $missingIDs ) . " missing revision(s), copying from master... " );
 142+ $dbFrom = $dbw;
 143+ $found = true;
 144+ $toMaster = false;
 145+ } else {
 146+ $found = false;
 147+ }
143148 }
144 - }
145149
146 - if ( $found ) {
147 - foreach ( $missingIDs as $rid ) {
148 - print "$rid ";
149 - # Revision
150 - $row = $dbFrom->selectRow( 'revision', '*', array( 'rev_id' => $rid ), $fname );
151 - if ( $toMaster ) {
152 - $id = $dbw->selectField( 'revision', 'rev_id', array( 'rev_id' => $rid ),
153 - $fname, 'FOR UPDATE' );
154 - if ( $id ) {
155 - echo "Revision already exists\n";
156 - $found = false;
157 - break;
 150+ if ( $found ) {
 151+ foreach ( $missingIDs as $rid ) {
 152+ $this->output( "$rid " );
 153+ # Revision
 154+ $row = $dbFrom->selectRow( 'revision', '*', array( 'rev_id' => $rid ), __METHOD__ );
 155+ if ( $toMaster ) {
 156+ $id = $dbw->selectField( 'revision', 'rev_id', array( 'rev_id' => $rid ),
 157+ __METHOD__, 'FOR UPDATE' );
 158+ if ( $id ) {
 159+ $this->output( "Revision already exists\n" );
 160+ $found = false;
 161+ break;
 162+ } else {
 163+ $dbw->insert( 'revision', get_object_vars( $row ), __METHOD__, 'IGNORE' );
 164+ }
158165 } else {
159 - $dbw->insert( 'revision', get_object_vars( $row ), $fname, 'IGNORE' );
 166+ foreach ( $slaveIndexes as $i ) {
 167+ $db = wfGetDB( $i );
 168+ $db->insert( 'revision', get_object_vars( $row ), __METHOD__, 'IGNORE' );
 169+ }
160170 }
161 - } else {
162 - foreach ( $slaveIndexes as $i ) {
163 - $db = wfGetDB( $i );
164 - $db->insert( 'revision', get_object_vars( $row ), $fname, 'IGNORE' );
 171+
 172+ # Text
 173+ $row = $dbFrom->selectRow( 'text', '*', array( 'old_id' => $row->rev_text_id ), __METHOD__ );
 174+ if ( $toMaster ) {
 175+ $dbw->insert( 'text', get_object_vars( $row ), __METHOD__, 'IGNORE' );
 176+ } else {
 177+ foreach ( $slaveIndexes as $i ) {
 178+ $db = wfGetDB( $i );
 179+ $db->insert( 'text', get_object_vars( $row ), __METHOD__, 'IGNORE' );
 180+ }
165181 }
166182 }
 183+ $this->output( "done\n" );
 184+ }
167185
168 - # Text
169 - $row = $dbFrom->selectRow( 'text', '*', array( 'old_id' => $row->rev_text_id ), $fname );
 186+ if ( $found ) {
 187+ $this->output( "Fixing page_latest... " );
170188 if ( $toMaster ) {
171 - $dbw->insert( 'text', get_object_vars( $row ), $fname, 'IGNORE' );
 189+ #$dbw->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), __METHOD__ );
172190 } else {
173191 foreach ( $slaveIndexes as $i ) {
174192 $db = wfGetDB( $i );
175 - $db->insert( 'text', get_object_vars( $row ), $fname, 'IGNORE' );
 193+ $db->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), __METHOD__ );
176194 }
177195 }
 196+ $this->output( "done\n" );
178197 }
179 - print "done\n";
 198+ $dbw->commit();
180199 }
181 -
182 - if ( $found ) {
183 - print "Fixing page_latest... ";
184 - if ( $toMaster ) {
185 - #$dbw->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), $fname );
186 - } else {
187 - foreach ( $slaveIndexes as $i ) {
188 - $db = wfGetDB( $i );
189 - $db->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), $fname );
190 - }
191 - }
192 - print "done\n";
193 - }
194 - $dbw->commit();
195200 }
196201
197 -
 202+$maintClass = "FixSlaveDesync";
 203+require_once( DO_MAINTENANCE );
Index: branches/maintenance-work/includes/db/DatabaseOracle.php
@@ -881,7 +881,7 @@
882882 global $wgVersion, $wgDBmwschema, $wgDBts2schema, $wgDBport, $wgDBuser;
883883
884884 echo "<li>Creating DB objects</li>\n";
885 - $res = dbsource( "../maintenance/ora/tables.sql", $this);
 885+ $res = $this->sourceFile( "../maintenance/ora/tables.sql" );
886886
887887 // Avoid the non-standard "REPLACE INTO" syntax
888888 echo "<li>Populating table interwiki</li>\n";
Index: branches/maintenance-work/includes/db/DatabasePostgres.php
@@ -1232,7 +1232,7 @@
12331233 }
12341234 $this->doQuery("DROP TABLE $safeschema.$ctest");
12351235
1236 - $res = dbsource( "../maintenance/postgres/tables.sql", $this);
 1236+ $res = $this->sourceFile( "../maintenance/postgres/tables.sql" );
12371237
12381238 ## Update version information
12391239 $mwv = $this->addQuotes($wgVersion);
Index: branches/maintenance-work/includes/db/DatabaseIbm_db2.php
@@ -707,7 +707,7 @@
708708 $this->applySchema();
709709 $this->begin();
710710
711 - $res = dbsource( "../maintenance/ibm_db2/tables.sql", $this);
 711+ $res = $this->sourceFile( "../maintenance/ibm_db2/tables.sql" );
712712 $res = null;
713713
714714 // TODO: update mediawiki_version table
Index: branches/maintenance-work/config/index.php
@@ -983,7 +983,7 @@
984984 if ($wgDatabase->isOpen()) {
985985 $wgDBOracleDefTS = $conf->DBdefTS_ora;
986986 $wgDBOracleTempTS = $conf->DBtempTS_ora;
987 - dbsource( "../maintenance/ora/user.sql", $wgDatabase );
 987+ $wgDatabase->fileSource( "../maintenance/ora/user.sql", );
988988 } else {
989989 echo "<li>Invalid database superuser, please supply a valid superuser account.</li>";
990990 echo "<li>ERR: ".print_r(oci_error(), true)."</li>";
@@ -1156,7 +1156,7 @@
11571157 print " <b class='error'>If the next step fails, see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'>http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b>";
11581158 }
11591159 print "</li>\n";
1160 - dbsource( "../maintenance/users.sql", $wgDatabase );
 1160+ $wgDatabase->fileSource( "../maintenance/users.sql" );
11611161 }
11621162 }
11631163 }
@@ -1190,8 +1190,8 @@
11911191 # FIXME: Check for errors
11921192 print "<li>Creating tables...";
11931193 if ($conf->DBtype == 'mysql') {
1194 - dbsource( "../maintenance/tables.sql", $wgDatabase );
1195 - dbsource( "../maintenance/interwiki.sql", $wgDatabase );
 1194+ $wgDatabase->fileSource( "../maintenance/tables.sql" );
 1195+ $wgDatabase->fileSource( "../maintenance/interwiki.sql" );
11961196 } elseif (is_callable(array($wgDatabase, 'setup_database'))) {
11971197 $wgDatabase->setup_database();
11981198 }
@@ -1224,7 +1224,7 @@
12251225 } else {
12261226 # Yes, so run the grants
12271227 echo( "<li>" . htmlspecialchars( "Granting user permissions to $wgDBuser on $wgDBname..." ) );
1228 - dbsource( "../maintenance/users.sql", $wgDatabase );
 1228+ $wgDatabase->fileSource( "../maintenance/users.sql" );
12291229 echo( "success.</li>\n" );
12301230 }
12311231 }

Status & tagging log