Index: branches/maintenance-work/maintenance/populateLogSearch.inc |
— | — | @@ -1,78 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Makes the required database updates for log display in Special:RevisionDelete |
5 | | - * |
6 | | - * Run via update.php or directly through populateLogSearch.php |
7 | | - * |
8 | | - * @file |
9 | | - * @ingroup Maintenance |
10 | | - */ |
11 | | - |
12 | | -define( 'LOG_SEARCH_BATCH_SIZE', 100 ); |
13 | | - |
14 | | -function migrate_log_params( $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_SEARCH_BATCH_SIZE - 1; |
24 | | - $blockStart = $start; |
25 | | - $blockEnd = $start + LOG_SEARCH_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"; |
29 | | - $res = $db->select( 'logging', '*', $cond, __FUNCTION__ ); |
30 | | - $batch = array(); |
31 | | - while( $row = $db->fetchObject( $res ) ) { |
32 | | - // RevisionDelete logs - revisions |
33 | | - if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) { |
34 | | - $params = LogPage::extractParams( $row->log_params ); |
35 | | - // Param format: <urlparam> <item CSV> [<ofield> <nfield>] |
36 | | - if( count($params) >= 2 ) { |
37 | | - $field = RevisionDeleter::getRelationType($params[0]); |
38 | | - // B/C, the params may start with a title key |
39 | | - if( $field == null ) { |
40 | | - array_shift($params); |
41 | | - $field = RevisionDeleter::getRelationType($params[0]); |
42 | | - } |
43 | | - if( $field == null ) { |
44 | | - echo "Invalid param type for $row->log_id\n"; |
45 | | - continue; // skip this row |
46 | | - } |
47 | | - $items = explode(',',$params[1]); |
48 | | - $log = new LogPage( $row->log_type ); |
49 | | - $log->addRelations( $field, $items, $row->log_id ); |
50 | | - } |
51 | | - // RevisionDelete logs - log events |
52 | | - } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) { |
53 | | - $params = LogPage::extractParams( $row->log_params ); |
54 | | - // Param format: <item CSV> [<ofield> <nfield>] |
55 | | - if( count($params) >= 1 ) { |
56 | | - $items = explode(',',$params[0]); |
57 | | - $log = new LogPage( $row->log_type ); |
58 | | - $log->addRelations( 'log_id', $items, $row->log_id ); |
59 | | - } |
60 | | - } |
61 | | - } |
62 | | - $blockStart += LOG_SEARCH_BATCH_SIZE; |
63 | | - $blockEnd += LOG_SEARCH_BATCH_SIZE; |
64 | | - wfWaitForSlaves( 5 ); |
65 | | - } |
66 | | - if( $db->insert( |
67 | | - 'updatelog', |
68 | | - array( 'ul_key' => 'populate log_search' ), |
69 | | - __FUNCTION__, |
70 | | - 'IGNORE' |
71 | | - ) |
72 | | - ) { |
73 | | - wfOut( "log_search population complete.\n" ); |
74 | | - return true; |
75 | | - } else { |
76 | | - wfOut( "Could not insert log_search population row.\n" ); |
77 | | - return false; |
78 | | - } |
79 | | -} |
Index: branches/maintenance-work/maintenance/undelete.php |
— | — | @@ -6,34 +6,35 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -$usage = <<<EOT |
11 | | -Undelete a page |
12 | | -Usage: php undelete.php [-u <user>] [-r <reason>] <pagename> |
| 10 | +require_once( "Maintenance.php" ); |
13 | 11 | |
14 | | -EOT; |
| 12 | +class Undelete extends Maintenance { |
| 13 | + public function __construct() { |
| 14 | + parent::__construct(); |
| 15 | + $this->mDescription = "Undelete a page"; |
| 16 | + $this->addParam( 'u', 'The user to perform the undeletion', false, true ); |
| 17 | + $this->addParam( 'r', 'The reason to undelete', false, true ); |
| 18 | + $this->addArgs( array( 'pagename' ) ); |
| 19 | + } |
15 | 20 | |
16 | | -$optionsWithArgs = array( 'u', 'r' ); |
17 | | -require_once( 'commandLine.inc' ); |
| 21 | + public function execute() { |
| 22 | + global $wgUser; |
18 | 23 | |
19 | | -$user = 'Command line script'; |
20 | | -$reason = ''; |
| 24 | + $user = $this->getOption( 'u', 'Command line script' ); |
| 25 | + $reason = $this->getOption( 'r', '' ); |
| 26 | + $pageName = $this->getArg(); |
21 | 27 | |
22 | | -if ( isset( $options['u'] ) ) { |
23 | | - $user = $options['u']; |
| 28 | + $title = Title::newFromText( $pageName ); |
| 29 | + if ( !$title ) { |
| 30 | + $this->error( "Invalid title", true ); |
| 31 | + } |
| 32 | + $wgUser = User::newFromName( $user ); |
| 33 | + $archive = new PageArchive( $title ); |
| 34 | + $this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' ); |
| 35 | + $archive->undelete( array(), $reason ); |
| 36 | + $this->output( "done\n" ); |
| 37 | + } |
24 | 38 | } |
25 | | -if ( isset( $options['r'] ) ) { |
26 | | - $reason = $options['r']; |
27 | | -} |
28 | | -$pageName = @$args[0]; |
29 | | -$title = Title::newFromText( $pageName ); |
30 | | -if ( !$title ) { |
31 | | - echo $usage; |
32 | | - exit( 1 ); |
33 | | -} |
34 | | -$wgUser = User::newFromName( $user ); |
35 | | -$archive = new PageArchive( $title ); |
36 | | -echo "Undeleting " . $title->getPrefixedDBkey() . '...'; |
37 | | -$archive->undelete( array(), $reason ); |
38 | | -echo "done\n"; |
39 | 39 | |
40 | | - |
| 40 | +$maintClass = "Undelete"; |
| 41 | +require_once( DO_MAINTENANCE ); |
Index: branches/maintenance-work/maintenance/updateSpecialPages.php |
— | — | @@ -6,114 +6,114 @@ |
7 | 7 | * @file |
8 | 8 | * @ingroup Maintenance |
9 | 9 | */ |
10 | | -$options = array('only','help'); |
| 10 | + |
| 11 | +require_once( "Maintenance.php" ); |
11 | 12 | |
12 | | -require_once( 'commandLine.inc' ); |
13 | | - |
14 | | -require_once( "$IP/includes/SpecialPage.php" ); |
15 | | -require_once( "$IP/includes/QueryPage.php" ); |
16 | | - |
17 | | -if(@$options['help']) { |
18 | | - print "usage:updateSpecialPages.php [--help] [--only=page]\n"; |
19 | | - print " --help : this help message\n"; |
20 | | - print " --list : list special pages names\n"; |
21 | | - print " --only=page : only update 'page'. Ex: --only=BrokenRedirects\n"; |
22 | | - print " --override : update even pages which have had updates disabled\n"; |
23 | | - wfDie(); |
24 | | -} |
25 | | - |
26 | | -$wgOut->disable(); |
27 | | -$dbw = wfGetDB( DB_MASTER ); |
28 | | - |
29 | | -foreach( $wgSpecialPageCacheUpdates as $special => $call ) { |
30 | | - if( !is_callable($call) ) { |
31 | | - print "Uncallable function $call!\n"; |
32 | | - continue; |
| 13 | +class UpdateSpecialPages extends Maintenance { |
| 14 | + public function __construct() { |
| 15 | + parent::__construct(); |
| 16 | + $this->addParam( 'list', 'List special page names' ); |
| 17 | + $this->addParam( 'only', 'Only update "page". Ex: --only=BrokenRedirects', false, true ); |
| 18 | + $this->addParam( 'override', 'Also update pages that have updates disabled' ); |
33 | 19 | } |
34 | | - $t1 = explode( ' ', microtime() ); |
35 | | - call_user_func( $call, $dbw ); |
36 | | - $t2 = explode( ' ', microtime() ); |
37 | | - printf( '%-30s ', $special ); |
38 | | - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
39 | | - $hours = intval( $elapsed / 3600 ); |
40 | | - $minutes = intval( $elapsed % 3600 / 60 ); |
41 | | - $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
42 | | - if ( $hours ) { |
43 | | - print $hours . 'h '; |
44 | | - } |
45 | | - if ( $minutes ) { |
46 | | - print $minutes . 'm '; |
47 | | - } |
48 | | - printf( "completed in %.2fs\n", $seconds ); |
49 | | - # Wait for the slave to catch up |
50 | | - wfWaitForSlaves( 5 ); |
51 | | -} |
52 | 20 | |
53 | | -foreach( $wgQueryPages as $page ) { |
54 | | - @list( $class, $special, $limit ) = $page; |
| 21 | + public function execute() { |
| 22 | + global $wgOut; |
| 23 | + $wgOut->disable(); |
| 24 | + $dbw = wfGetDB( DB_MASTER ); |
55 | 25 | |
56 | | - # --list : just show the name of pages |
57 | | - if( @$options['list'] ) { |
58 | | - print "$special\n"; |
59 | | - continue; |
60 | | - } |
61 | | - |
62 | | - if ( !isset( $options['override'] ) && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { |
63 | | - printf("%-30s disabled\n", $special); |
64 | | - continue; |
65 | | - } |
66 | | - |
67 | | - $specialObj = SpecialPage::getPage( $special ); |
68 | | - if ( !$specialObj ) { |
69 | | - print "No such special page: $special\n"; |
70 | | - exit; |
71 | | - } |
72 | | - if ( !class_exists( $class ) ) { |
73 | | - $file = $specialObj->getFile(); |
74 | | - require_once( $file ); |
75 | | - } |
76 | | - $queryPage = new $class; |
77 | | - |
78 | | - if( !isset($options['only']) or $options['only'] == $queryPage->getName() ) { |
79 | | - printf( '%-30s ', $special ); |
80 | | - if ( $queryPage->isExpensive() ) { |
| 26 | + foreach( $wgSpecialPageCacheUpdates as $special => $call ) { |
| 27 | + if( !is_callable($call) ) { |
| 28 | + $this->error( "Uncallable function $call!\n" ); |
| 29 | + continue; |
| 30 | + } |
81 | 31 | $t1 = explode( ' ', microtime() ); |
82 | | - # Do the query |
83 | | - $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); |
| 32 | + call_user_func( $call, $dbw ); |
84 | 33 | $t2 = explode( ' ', microtime() ); |
85 | | - if ( $num === false ) { |
86 | | - print "FAILED: database error\n"; |
87 | | - } else { |
88 | | - print "got $num rows in "; |
89 | | - |
90 | | - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
91 | | - $hours = intval( $elapsed / 3600 ); |
92 | | - $minutes = intval( $elapsed % 3600 / 60 ); |
93 | | - $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
94 | | - if ( $hours ) { |
95 | | - print $hours . 'h '; |
| 34 | + $this->output( sprintf( '%-30s ', $special ) ); |
| 35 | + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
| 36 | + $hours = intval( $elapsed / 3600 ); |
| 37 | + $minutes = intval( $elapsed % 3600 / 60 ); |
| 38 | + $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
| 39 | + if ( $hours ) { |
| 40 | + $this->output( $hours . 'h ' ); |
| 41 | + } |
| 42 | + if ( $minutes ) { |
| 43 | + $this->output( $minutes . 'm ' ); |
| 44 | + } |
| 45 | + $this->output( sprintf( "completed in %.2fs\n", $seconds ) ); |
| 46 | + # Wait for the slave to catch up |
| 47 | + wfWaitForSlaves( 5 ); |
| 48 | + } |
| 49 | + |
| 50 | + foreach( $wgQueryPages as $page ) { |
| 51 | + @list( $class, $special, $limit ) = $page; |
| 52 | + |
| 53 | + # --list : just show the name of pages |
| 54 | + if( $this->hasOption('list') ) { |
| 55 | + $this->output( "$special\n" ); |
| 56 | + continue; |
| 57 | + } |
| 58 | + |
| 59 | + if ( $this->hasOption('override') && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { |
| 60 | + $this->output( sprintf( "%-30s disabled\n", $special ) ); |
| 61 | + continue; |
| 62 | + } |
| 63 | + |
| 64 | + $specialObj = SpecialPage::getPage( $special ); |
| 65 | + if ( !$specialObj ) { |
| 66 | + $this->output( "No such special page: $special\n" ); |
| 67 | + exit; |
| 68 | + } |
| 69 | + if ( !class_exists( $class ) ) { |
| 70 | + $file = $specialObj->getFile(); |
| 71 | + require_once( $file ); |
| 72 | + } |
| 73 | + $queryPage = new $class; |
| 74 | + |
| 75 | + if( !$this->hasOption('only') || $this->getOption('only') == $queryPage->getName() ) { |
| 76 | + $this->output( sprintf( '%-30s ', $special ) ); |
| 77 | + if ( $queryPage->isExpensive() ) { |
| 78 | + $t1 = explode( ' ', microtime() ); |
| 79 | + # Do the query |
| 80 | + $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); |
| 81 | + $t2 = explode( ' ', microtime() ); |
| 82 | + if ( $num === false ) { |
| 83 | + $this->output( "FAILED: database error\n" ); |
| 84 | + } else { |
| 85 | + $this->output( "got $num rows in " ); |
| 86 | + |
| 87 | + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
| 88 | + $hours = intval( $elapsed / 3600 ); |
| 89 | + $minutes = intval( $elapsed % 3600 / 60 ); |
| 90 | + $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
| 91 | + if ( $hours ) { |
| 92 | + $this->output( $hours . 'h ' ); |
| 93 | + } |
| 94 | + if ( $minutes ) { |
| 95 | + $this->output( $minutes . 'm ' ); |
| 96 | + } |
| 97 | + $this->output( sprintf( "%.2fs\n", $seconds ) ); |
96 | 98 | } |
97 | | - if ( $minutes ) { |
98 | | - print $minutes . 'm '; |
| 99 | + # Reopen any connections that have closed |
| 100 | + if ( !wfGetLB()->pingAll()) { |
| 101 | + $this->output( "\n" ); |
| 102 | + do { |
| 103 | + $this->error( "Connection failed, reconnecting in 10 seconds...\n" ); |
| 104 | + sleep(10); |
| 105 | + } while ( !wfGetLB()->pingAll() ); |
| 106 | + $this->output( "Reconnected\n\n" ); |
| 107 | + } else { |
| 108 | + # Commit the results |
| 109 | + $dbw->immediateCommit(); |
99 | 110 | } |
100 | | - printf( "%.2fs\n", $seconds ); |
| 111 | + # Wait for the slave to catch up |
| 112 | + wfWaitForSlaves( 5 ); |
| 113 | + } else { |
| 114 | + $this->output( "cheap, skipped\n" ); |
| 115 | + } |
| 116 | + } |
101 | 117 | } |
102 | | - # Reopen any connections that have closed |
103 | | - if ( !wfGetLB()->pingAll()) { |
104 | | - print "\n"; |
105 | | - do { |
106 | | - print "Connection failed, reconnecting in 10 seconds...\n"; |
107 | | - sleep(10); |
108 | | - } while ( !wfGetLB()->pingAll() ); |
109 | | - print "Reconnected\n\n"; |
110 | | - } else { |
111 | | - # Commit the results |
112 | | - $dbw->immediateCommit(); |
113 | | - } |
114 | | - # Wait for the slave to catch up |
115 | | - wfWaitForSlaves( 5 ); |
116 | | - } else { |
117 | | - print "cheap, skipped\n"; |
118 | | - } |
119 | 118 | } |
120 | 119 | } |
| 120 | + |
Index: branches/maintenance-work/maintenance/runJobs.php |
— | — | @@ -10,71 +10,77 @@ |
11 | 11 | * @ingroup Maintenance |
12 | 12 | */ |
13 | 13 | |
14 | | -$optionsWithArgs = array( 'maxjobs', 'type', 'procs' ); |
15 | | -$wgUseNormalUser = true; |
16 | | -require_once( 'commandLine.inc' ); |
| 14 | +require_once( "Maintenance.php" ); |
17 | 15 | |
18 | | -if ( isset( $options['procs'] ) ) { |
19 | | - $procs = intval( $options['procs'] ); |
20 | | - if ( $procs < 1 || $procs > 1000 ) { |
21 | | - echo "Invalid argument to --procs\n"; |
22 | | - exit( 1 ); |
| 16 | +class RunJobs extends Maintenance { |
| 17 | + public function __construct() { |
| 18 | + global $wgUseNormalUser; |
| 19 | + parent::__construct(); |
| 20 | + $this->mDescription = "Run pending jobs"; |
| 21 | + $this->addParam( 'maxjobs', 'Maximum number of jobs to run', false, true ); |
| 22 | + $this->addParam( 'type', 'Type of job to run', false, true ); |
| 23 | + $this->addParam( 'procs', 'Number of processes to use', false, true ); |
| 24 | + $wgUseNormalUser = true; |
23 | 25 | } |
24 | | - $fc = new ForkController( $procs ); |
25 | | - if ( $fc->start( $procs ) != 'child' ) { |
26 | | - exit( 0 ); |
27 | | - } |
28 | | -} |
29 | 26 | |
30 | | -if ( isset( $options['maxjobs'] ) ) { |
31 | | - $maxJobs = $options['maxjobs']; |
32 | | -} else { |
33 | | - $maxJobs = 10000; |
34 | | -} |
| 27 | + public function execute() { |
| 28 | + global $wgTitle; |
| 29 | + if ( $this->hasOption( 'procs' ) ) { |
| 30 | + $procs = intval( $this->getOption('procs') ); |
| 31 | + if ( $procs < 1 || $procs > 1000 ) { |
| 32 | + $this->error( "Invalid argument to --procs\n", true ); |
| 33 | + } |
| 34 | + $fc = new ForkController( $procs ); |
| 35 | + if ( $fc->start( $procs ) != 'child' ) { |
| 36 | + exit( 0 ); |
| 37 | + } |
| 38 | + } |
| 39 | + $maxJobs = $this->getOption( 'maxjobs', 10000 ); |
| 40 | + $type = $this->getOption( 'type', false ); |
| 41 | + $wgTitle = Title::newFromText( 'RunJobs.php' ); |
| 42 | + $dbw = wfGetDB( DB_MASTER ); |
| 43 | + $n = 0; |
| 44 | + $conds = ''; |
| 45 | + if ($type !== false) |
| 46 | + $conds = "job_cmd = " . $dbw->addQuotes($type); |
35 | 47 | |
36 | | -$type = false; |
37 | | -if ( isset( $options['type'] ) ) |
38 | | - $type = $options['type']; |
39 | | - |
40 | | -$wgTitle = Title::newFromText( 'RunJobs.php' ); |
41 | | - |
42 | | -$dbw = wfGetDB( DB_MASTER ); |
43 | | -$n = 0; |
44 | | -$conds = ''; |
45 | | -if ($type !== false) |
46 | | - $conds = "job_cmd = " . $dbw->addQuotes($type); |
47 | | - |
48 | | -while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { |
49 | | - $offset=0; |
50 | | - for (;;) { |
51 | | - $job = ($type == false) ? |
52 | | - Job::pop($offset) |
53 | | - : Job::pop_type($type); |
54 | | - |
55 | | - if ($job == false) |
56 | | - break; |
57 | | - |
58 | | - wfWaitForSlaves( 5 ); |
59 | | - $t = microtime( true ); |
60 | | - $offset=$job->id; |
61 | | - $status = $job->run(); |
62 | | - $t = microtime( true ) - $t; |
63 | | - $timeMs = intval( $t * 1000 ); |
64 | | - if ( !$status ) { |
65 | | - runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); |
66 | | - } else { |
67 | | - runJobsLog( $job->toString() . " t=$timeMs good" ); |
| 48 | + while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { |
| 49 | + $offset=0; |
| 50 | + for (;;) { |
| 51 | + $job = ($type == false) ? |
| 52 | + Job::pop($offset) |
| 53 | + : Job::pop_type($type); |
| 54 | + |
| 55 | + if ($job == false) |
| 56 | + break; |
| 57 | + |
| 58 | + wfWaitForSlaves( 5 ); |
| 59 | + $t = microtime( true ); |
| 60 | + $offset=$job->id; |
| 61 | + $status = $job->run(); |
| 62 | + $t = microtime( true ) - $t; |
| 63 | + $timeMs = intval( $t * 1000 ); |
| 64 | + if ( !$status ) { |
| 65 | + $this->runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); |
| 66 | + } else { |
| 67 | + $this->runJobsLog( $job->toString() . " t=$timeMs good" ); |
| 68 | + } |
| 69 | + if ( $maxJobs && ++$n > $maxJobs ) { |
| 70 | + break 2; |
| 71 | + } |
| 72 | + } |
68 | 73 | } |
69 | | - if ( $maxJobs && ++$n > $maxJobs ) { |
70 | | - break 2; |
71 | | - } |
72 | 74 | } |
73 | | -} |
74 | 75 | |
75 | | - |
76 | | -function runJobsLog( $msg ) { |
77 | | - print wfTimestamp( TS_DB ) . " $msg\n"; |
78 | | - wfDebugLog( 'runJobs', $msg ); |
| 76 | + /** |
| 77 | + * Log the job message |
| 78 | + * @param $msg String The message to log |
| 79 | + */ |
| 80 | + private function runJobsLog( $msg ) { |
| 81 | + $this->output( wfTimestamp( TS_DB ) . " $msg\n" ); |
| 82 | + wfDebugLog( 'runJobs', $msg ); |
| 83 | + } |
79 | 84 | } |
80 | 85 | |
81 | | - |
| 86 | +$maintClass = "RunJobs"; |
| 87 | +require_once( DO_MAINTENANCE ); |
Index: branches/maintenance-work/maintenance/Maintenance.php |
— | — | @@ -46,6 +46,9 @@ |
47 | 47 | |
48 | 48 | // Have we already loaded our user input? |
49 | 49 | private $inputLoaded = false; |
| 50 | + |
| 51 | + // Batch size |
| 52 | + protected $mBatchSize = 100; |
50 | 53 | |
51 | 54 | /** |
52 | 55 | * Default constructor. Children should call this if implementing |
— | — | @@ -125,6 +128,14 @@ |
126 | 129 | } |
127 | 130 | |
128 | 131 | /** |
| 132 | + * Set the batch size. |
| 133 | + * @param $s int The number of operations to do in a batch |
| 134 | + */ |
| 135 | + protected function setBatchSize( $s = 0 ) { |
| 136 | + $this->mBatchSize = $s; |
| 137 | + } |
| 138 | + |
| 139 | + /** |
129 | 140 | * Return input from stdin. |
130 | 141 | * @param $length int The number of bytes to read. If null, |
131 | 142 | * just return the handle |
Index: branches/maintenance-work/maintenance/deleteImageMemcached.php |
— | — | @@ -3,40 +3,36 @@ |
4 | 4 | * This script delete image information from memcached. |
5 | 5 | * |
6 | 6 | * Usage example: |
7 | | - * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 --report 10 |
| 7 | + * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 |
8 | 8 | * |
9 | 9 | * @file |
10 | 10 | * @ingroup Maintenance |
11 | 11 | */ |
12 | 12 | |
13 | | -$optionsWithArgs = array( 'until', 'sleep', 'report' ); |
| 13 | +require_once( "Maintenance.php" ); |
14 | 14 | |
15 | | -require_once 'commandLine.inc'; |
16 | | - |
17 | | -/** |
18 | | - * @ingroup Maintenance |
19 | | - */ |
20 | | -class DeleteImageCache { |
21 | | - var $until, $sleep, $report; |
22 | | - |
23 | | - function DeleteImageCache( $until, $sleep, $report ) { |
24 | | - $this->until = $until; |
25 | | - $this->sleep = $sleep; |
26 | | - $this->report = $report; |
| 15 | +class DeleteImageCache extends Maintenance { |
| 16 | + public function __construct() { |
| 17 | + parent::__construct(); |
| 18 | + $this->mDescription = "Delete image information from memcached"; |
| 19 | + $this->addParam( 'sleep', 'How many seconds to sleep between deletions', true, true ); |
| 20 | + $this->addParam( 'until', 'Timestamp to delete all entries prior to', true, true ); |
27 | 21 | } |
28 | 22 | |
29 | | - function main() { |
| 23 | + public function execute() { |
30 | 24 | global $wgMemc; |
31 | | - $fname = 'DeleteImageCache::main'; |
32 | 25 | |
| 26 | + $until = preg_replace( "/[^\d]/", '', $this->getOption('until') ); |
| 27 | + $sleep = (int)$this->getOption('sleep') * 1000; // milliseconds |
| 28 | + |
33 | 29 | ini_set( 'display_errors', false ); |
34 | 30 | |
35 | 31 | $dbr = wfGetDB( DB_SLAVE ); |
36 | 32 | |
37 | 33 | $res = $dbr->select( 'image', |
38 | 34 | array( 'img_name' ), |
39 | | - array( "img_timestamp < {$this->until}" ), |
40 | | - $fname |
| 35 | + array( "img_timestamp < {$until}" ), |
| 36 | + __METHOD__ |
41 | 37 | ); |
42 | 38 | |
43 | 39 | $i = 0; |
— | — | @@ -44,29 +40,22 @@ |
45 | 41 | |
46 | 42 | while ( $row = $dbr->fetchObject( $res ) ) { |
47 | 43 | if ($i % $this->report == 0) |
48 | | - printf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 )); |
| 44 | + $this->output( sprintf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ) ) ); |
49 | 45 | $md5 = md5( $row->img_name ); |
50 | 46 | $wgMemc->delete( wfMemcKey( 'Image', $md5 ) ); |
51 | 47 | |
52 | | - if ($this->sleep != 0) |
53 | | - usleep( $this->sleep ); |
| 48 | + if ($sleep != 0) |
| 49 | + usleep( $sleep ); |
54 | 50 | |
55 | 51 | ++$i; |
56 | 52 | } |
57 | 53 | } |
58 | 54 | |
59 | | - function getImageCount() { |
60 | | - $fname = 'DeleteImageCache::getImageCount'; |
61 | | - |
| 55 | + private function getImageCount() { |
62 | 56 | $dbr = wfGetDB( DB_SLAVE ); |
63 | | - return $dbr->selectField( 'image', 'COUNT(*)', array(), $fname ); |
| 57 | + return $dbr->selectField( 'image', 'COUNT(*)', array(), __METHOD__ ); |
64 | 58 | } |
65 | 59 | } |
66 | 60 | |
67 | | -$until = preg_replace( "/[^\d]/", '', $options['until'] ); |
68 | | -$sleep = (int)$options['sleep'] * 1000; // milliseconds |
69 | | -$report = (int)$options['report']; |
70 | | - |
71 | | -$dic = new DeleteImageCache( $until, $sleep, $report ); |
72 | | -$dic->main(); |
73 | | - |
| 61 | +$maintClass = "DeleteImageCache"; |
| 62 | +require_once( DO_MAINTENANCE ); |
Index: branches/maintenance-work/maintenance/populateLogSearch.php |
— | — | @@ -9,13 +9,88 @@ |
10 | 10 | * @ingroup Maintenance |
11 | 11 | */ |
12 | 12 | |
13 | | -require_once 'commandLine.inc'; |
14 | | -require_once 'populateLogSearch.inc'; |
| 13 | +require_once( "Maintenance.php" ); |
| 14 | + |
| 15 | +class PopulateLogSearch extends Maintenance { |
| 16 | + |
| 17 | + const LOG_SEARCH_BATCH_SIZE = 100; |
| 18 | + |
| 19 | + public function __construct() { |
| 20 | + parent::__construct(); |
| 21 | + $this->mDescription = "Migrate log params to new table and index for searching"; |
| 22 | + } |
| 23 | + |
| 24 | + public function execute() { |
| 25 | + $db = wfGetDB( DB_MASTER ); |
| 26 | + if ( !$db->tableExists( 'log_search' ) ) { |
| 27 | + $this->error( "log_search does not exist\n", true ); |
| 28 | + } |
| 29 | + $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ ); |
| 30 | + if( !$start ) { |
| 31 | + $this->output( "Nothing to do.\n" ); |
| 32 | + return true; |
| 33 | + } |
| 34 | + $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ ); |
15 | 35 | |
16 | | -$db =& wfGetDB( DB_MASTER ); |
17 | | -if ( !$db->tableExists( 'log_search' ) ) { |
18 | | - echo "log_search does not exist\n"; |
19 | | - exit( 1 ); |
| 36 | + # Do remaining chunk |
| 37 | + $end += self::LOG_SEARCH_BATCH_SIZE - 1; |
| 38 | + $blockStart = $start; |
| 39 | + $blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1; |
| 40 | + while( $blockEnd <= $end ) { |
| 41 | + $this->output( "...doing log_id from $blockStart to $blockEnd\n" ); |
| 42 | + $cond = "log_id BETWEEN $blockStart AND $blockEnd"; |
| 43 | + $res = $db->select( 'logging', '*', $cond, __FUNCTION__ ); |
| 44 | + $batch = array(); |
| 45 | + while( $row = $db->fetchObject( $res ) ) { |
| 46 | + // RevisionDelete logs - revisions |
| 47 | + if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) { |
| 48 | + $params = LogPage::extractParams( $row->log_params ); |
| 49 | + // Param format: <urlparam> <item CSV> [<ofield> <nfield>] |
| 50 | + if( count($params) >= 2 ) { |
| 51 | + $field = RevisionDeleter::getRelationType($params[0]); |
| 52 | + // B/C, the params may start with a title key |
| 53 | + if( $field == null ) { |
| 54 | + array_shift($params); |
| 55 | + $field = RevisionDeleter::getRelationType($params[0]); |
| 56 | + } |
| 57 | + if( $field == null ) { |
| 58 | + $this->output( "Invalid param type for $row->log_id\n" ); |
| 59 | + continue; // skip this row |
| 60 | + } |
| 61 | + $items = explode(',',$params[1]); |
| 62 | + $log = new LogPage( $row->log_type ); |
| 63 | + $log->addRelations( $field, $items, $row->log_id ); |
| 64 | + } |
| 65 | + // RevisionDelete logs - log events |
| 66 | + } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) { |
| 67 | + $params = LogPage::extractParams( $row->log_params ); |
| 68 | + // Param format: <item CSV> [<ofield> <nfield>] |
| 69 | + if( count($params) >= 1 ) { |
| 70 | + $items = explode(',',$params[0]); |
| 71 | + $log = new LogPage( $row->log_type ); |
| 72 | + $log->addRelations( 'log_id', $items, $row->log_id ); |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + $blockStart += self::LOG_SEARCH_BATCH_SIZE; |
| 77 | + $blockEnd += self::LOG_SEARCH_BATCH_SIZE; |
| 78 | + wfWaitForSlaves( 5 ); |
| 79 | + } |
| 80 | + if( $db->insert( |
| 81 | + 'updatelog', |
| 82 | + array( 'ul_key' => 'populate log_search' ), |
| 83 | + __FUNCTION__, |
| 84 | + 'IGNORE' |
| 85 | + ) |
| 86 | + ) { |
| 87 | + $this->output( "log_search population complete.\n" ); |
| 88 | + return true; |
| 89 | + } else { |
| 90 | + $this->output( "Could not insert log_search population row.\n" ); |
| 91 | + return false; |
| 92 | + } |
| 93 | + } |
20 | 94 | } |
21 | 95 | |
22 | | -migrate_log_params( $db ); |
| 96 | +$maintClass = "PopulateLogSearch"; |
| 97 | +require_once( DO_MAINTENANCE ); |
Index: branches/maintenance-work/maintenance/sql.php |
— | — | @@ -7,38 +7,56 @@ |
8 | 8 | * @ingroup Database Maintenance |
9 | 9 | */ |
10 | 10 | |
11 | | -require_once( dirname(__FILE__) . '/' . 'commandLine.inc' ); |
| 11 | +require_once( "Maintenance.php" ); |
12 | 12 | |
13 | | -if ( isset( $options['help'] ) ) { |
14 | | - echo "Send SQL queries to a MediaWiki database.\nUsage: php sql.php [<file>]\n"; |
15 | | - exit( 1 ); |
16 | | -} |
| 13 | +class MwSql extends Maintenance { |
| 14 | + public function __construct() { |
| 15 | + parent::__construct(); |
| 16 | + $this->mDescription = "Send SQL queries to a MediaWiki database"; |
| 17 | + } |
17 | 18 | |
18 | | -if ( isset( $args[0] ) ) { |
19 | | - $fileName = $args[0]; |
20 | | - $file = fopen( $fileName, 'r' ); |
21 | | - $promptCallback = false; |
22 | | -} else { |
23 | | - $file = STDIN; |
24 | | - $promptObject = new SqlPromptPrinter( "> " ); |
25 | | - $promptCallback = $promptObject->cb(); |
26 | | -} |
| 19 | + public function execute() { |
| 20 | + if ( $this->hasArg() ) { |
| 21 | + $fileName = $this->getArg(); |
| 22 | + $file = fopen( $fileName, 'r' ); |
| 23 | + $promptCallback = false; |
| 24 | + } else { |
| 25 | + $file = $this->getStdin(); |
| 26 | + $promptObject = new SqlPromptPrinter( "> " ); |
| 27 | + $promptCallback = $promptObject->cb(); |
| 28 | + } |
| 29 | + |
| 30 | + if ( !$file ) |
| 31 | + $this->error( "Unable to open input file\n", true ); |
27 | 32 | |
28 | | -if ( !$file ) { |
29 | | - echo "Unable to open input file\n"; |
30 | | - exit( 1 ); |
31 | | -} |
| 33 | + $dbw = wfGetDB( DB_MASTER ); |
| 34 | + $error = $dbw->sourceStream( $file, $promptCallback, array( $this, 'sqlPrintResult' ) ); |
| 35 | + if ( $error !== true ) { |
| 36 | + $this->error( $error, true ); |
| 37 | + } else { |
| 38 | + exit( 0 ); |
| 39 | + } |
| 40 | + } |
32 | 41 | |
33 | | -$dbw =& wfGetDB( DB_MASTER ); |
34 | | -$error = $dbw->sourceStream( $file, $promptCallback, 'sqlPrintResult' ); |
35 | | -if ( $error !== true ) { |
36 | | - echo $error; |
37 | | - exit( 1 ); |
38 | | -} else { |
39 | | - exit( 0 ); |
| 42 | + /** |
| 43 | + * Print the results, callback for $db->sourceStream() |
| 44 | + * @param $res The results object |
| 45 | + * @param $db Database object |
| 46 | + */ |
| 47 | + public function sqlPrintResult( $res, $db ) { |
| 48 | + if ( !$res ) { |
| 49 | + // Do nothing |
| 50 | + } elseif ( is_object( $res ) && $res->numRows() ) { |
| 51 | + while ( $row = $res->fetchObject() ) { |
| 52 | + $this->output( print_r( $row, true ) ); |
| 53 | + } |
| 54 | + } else { |
| 55 | + $affected = $db->affectedRows(); |
| 56 | + $this->output( "Query OK, $affected row(s) affected\n" ); |
| 57 | + } |
| 58 | + } |
40 | 59 | } |
41 | 60 | |
42 | | -//----------------------------------------------------------------------------- |
43 | 61 | class SqlPromptPrinter { |
44 | 62 | function __construct( $prompt ) { |
45 | 63 | $this->prompt = $prompt; |
— | — | @@ -53,17 +71,5 @@ |
54 | 72 | } |
55 | 73 | } |
56 | 74 | |
57 | | -function sqlPrintResult( $res, $db ) { |
58 | | - if ( !$res ) { |
59 | | - // Do nothing |
60 | | - } elseif ( is_object( $res ) && $res->numRows() ) { |
61 | | - while ( $row = $res->fetchObject() ) { |
62 | | - print_r( $row ); |
63 | | - } |
64 | | - } else { |
65 | | - $affected = $db->affectedRows(); |
66 | | - echo "Query OK, $affected row(s) affected\n"; |
67 | | - } |
68 | | -} |
69 | | - |
70 | | - |
| 75 | +$maintClass = "MwSql"; |
| 76 | +require_once( DO_MAINTENANCE ); |