82d2fcaa63db6c3c39254088b710693da6aed96f
[lhc/web/wiklou.git] / includes / JobQueue.php
1 <?php
2
3 if ( !defined( 'MEDIAWIKI' ) ) {
4 die( "This file is part of MediaWiki, it is not a valid entry point\n" );
5 }
6
7 class Job {
8 var $command,
9 $title,
10 $params,
11 $removeDuplicates,
12 $error;
13
14 /*-------------------------------------------------------------------------
15 * Static functions
16 *------------------------------------------------------------------------*/
17 /**
18 * Add an array of refreshLinks jobs to the queue
19 * @param array $titles Array of title objects.
20 * @static
21 */
22 function queueLinksJobs( $titles ) {
23 $fname = 'Job::queueLinksJobs';
24 wfProfileIn( $fname );
25 foreach ( $titles as $title ) {
26 $job = new Job( 'refreshLinks', $title );
27 $job->insert();
28 }
29 wfProfileOut( $fname );
30 }
31
32 /**
33 * Pop a job off the front of the queue
34 * @static
35 * @return Job or false if there's no jobs
36 */
37 function pop() {
38 $fname = 'Job::pop';
39 wfProfileIn( $fname );
40
41 // First check to see if there are any jobs in the slave DB
42 $dbr =& wfGetDB( DB_SLAVE );
43 $id = $dbr->selectField( 'job', 'job_id', '', $fname, array( 'LIMIT' => 1 ) );
44 if ( $id === false ) {
45 wfProfileOut( $fname );
46 return false;
47 }
48
49 // Pop an item off the front of the queue
50 // Method due to Domas, may not work on all DBMSes
51 $dbw =& wfGetDB( DB_MASTER );
52 $dbw->immediateBegin();
53 $jobTable = $dbw->tableName( 'job' );
54 $dbw->query( "DELETE FROM $jobTable WHERE " .
55 '(job_cmd = @job_cmd := job_cmd) AND ' .
56 '(job_namespace = @job_namespace := job_namespace) AND ' .
57 '(job_title = @job_title := job_title) AND ' .
58 '(job_params = @job_params := job_params) ' .
59 'LIMIT 1', $fname );
60 $affected = $dbw->affectedRows();
61 // Commit now before 100 other threads pile up behind us
62 $dbw->immediateCommit();
63 if ( !$affected ) {
64 wfProfileOut( $fname );
65 return false;
66 }
67
68 $res = $dbw->query( "SELECT @job_cmd, @job_namespace, @job_title, @job_params", $fname );
69 $row = $dbw->fetchRow( $res );
70 if ( !$row ) {
71 wfProfileOut( $fname );
72 return false;
73 }
74
75 $command = $row['@job_cmd'];
76 $namespace = $row['@job_namespace'];
77 $dbkey = $row['@job_title'];
78 $title = Title::makeTitleSafe( $namespace, $dbkey );
79 $params = $row['@job_params'];
80 $job = new Job( $command, $title, $params );
81 wfProfileOut( $fname );
82 return $job;
83 }
84
85 /*-------------------------------------------------------------------------
86 * Non-static functions
87 *------------------------------------------------------------------------*/
88
89 function Job( $command, $title, $params = '' ) {
90 $this->command = $command;
91 $this->title = $title;
92 $this->params = $params;
93
94 // A bit of premature generalisation
95 // Oh well, the whole class is premature generalisation really
96 $this->removeDuplicates = true;
97 }
98
99 function insert() {
100 $fname = 'Job::insert';
101
102 $fields = array(
103 'job_cmd' => $this->command,
104 'job_namespace' => $this->title->getNamespace(),
105 'job_title' => $this->title->getDBkey(),
106 'job_params' => $this->params
107 );
108
109 $dbw =& wfGetDB( DB_MASTER );
110
111 if ( $this->removeDuplicates ) {
112 $dbw->delete( 'job', $fields, $fname );
113 }
114 $fields['job_id'] = $dbw->nextSequenceValue( 'job_job_id_seq' );
115 $dbw->insert( 'job', $fields, $fname );
116 }
117
118 /**
119 * Run the job
120 * @return boolean success
121 */
122 function run() {
123 $fname = 'Job::run';
124 wfProfileIn( $fname );
125 switch ( $this->command ) {
126 case 'refreshLinks':
127 $retval = $this->refreshLinks();
128 break;
129 default:
130 $this->error = "Invalid job type {$this->command}, ignoring";
131 wfDebug( $this->error . "\n" );
132 $retval = false;
133 }
134 wfProfileOut( $fname );
135 return $retval;
136 }
137
138 /**
139 * Run a refreshLinks job
140 * @return boolean success
141 */
142 function refreshLinks() {
143 global $wgParser;
144
145 $dbw =& wfGetDB( DB_MASTER );
146
147 $linkCache =& LinkCache::singleton();
148 $linkCache->clear();
149
150 if ( is_null( $this->title ) ) {
151 $this->error = "refreshLinks: Invalid title";
152 return false;
153 }
154
155 $revision = Revision::newFromTitle( $this->title );
156 if ( !$revision ) {
157 $this->error = 'refreshLinks: Article not found "' . $this->title->getPrefixedDBkey() . '"';
158 return false;
159 }
160
161 $options = new ParserOptions;
162 $parserOutput = $wgParser->parse( $revision->getText(), $this->title, $options, true, true, $revision->getId() );
163 $update = new LinksUpdate( $this->title, $parserOutput );
164 $update->doUpdate();
165 return true;
166 }
167
168 function toString() {
169 if ( is_object( $this->title ) ) {
170 $s = "{$this->command} " . $this->title->getPrefixedDBkey();
171 if ( $this->params !== '' ) {
172 $s .= ', ' . $this->params;
173 }
174 return $s;
175 } else {
176 return "{$this->command} {$this->params}";
177 }
178 }
179
180 function getLastError() {
181 return $this->error;
182 }
183 }