3 * Job to update links for a given title.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 * @author Aaron Schulz
26 * Class with Backlink related Job helper methods
31 class BacklinkJobUtils
{
33 * Break down $job into approximately ($bSize/$cSize) leaf jobs and a single partition
34 * job that covers the remaining backlink range (if needed). Jobs for the first $bSize
35 * titles are collated ($cSize per job) into leaf jobs to do actual work. All the
36 * resulting jobs are of the same class as $job. No partition job is returned if the
37 * range covered by $job was less than $bSize, as the leaf jobs have full coverage.
39 * The leaf jobs have the 'pages' param set to a (<page ID>:(<namespace>,<DB key>),...)
40 * map so that the run() function knows what pages to act on. The leaf jobs will keep
41 * the same job title as the parent job (e.g. $job).
43 * The partition jobs have the 'range' parameter set to a map of the format
44 * (start:<integer>, end:<integer>, batchSize:<integer>, subranges:((<start>,<end>),...)),
45 * the 'table' parameter set to that of $job, and the 'recursive' parameter set to true.
46 * This method can be called on the resulting job to repeat the process again.
48 * The job provided ($job) must have the 'recursive' parameter set to true and the 'table'
49 * parameter must be set to a backlink table. The job title will be used as the title to
50 * find backlinks for. Any 'range' parameter must follow the same format as mentioned above.
51 * This should be managed by recursive calls to this method.
53 * The first jobs return are always the leaf jobs. This lets the caller use push() to
54 * put them directly into the queue and works well if the queue is FIFO. In such a queue,
55 * the leaf jobs have to get finished first before anything can resolve the next partition
56 * job, which keeps the queue very small.
59 * - params : extra job parameters to include in each job
62 * @param int $bSize BacklinkCache partition size; usually $wgUpdateRowsPerJob
63 * @param int $cSize Max titles per leaf job; Usually 1 or a modest value
64 * @param array $opts Optional parameter map
65 * @return Job[] List of Job objects
67 public static function partitionBacklinkJob( Job
$job, $bSize, $cSize, $opts = array() ) {
68 $class = get_class( $job );
69 $title = $job->getTitle();
70 $params = $job->getParams();
72 if ( isset( $params['pages'] ) ||
empty( $params['recursive'] ) ) {
73 $ranges = array(); // sanity; this is a leaf node
74 wfWarn( __METHOD__
. " called on {$job->getType()} leaf job (explosive recursion)." );
75 } elseif ( isset( $params['range'] ) ) {
76 // This is a range job to trigger the insertion of partitioned/title jobs...
77 $ranges = $params['range']['subranges'];
78 $realBSize = $params['range']['batchSize'];
80 // This is a base job to trigger the insertion of partitioned jobs...
81 $ranges = $title->getBacklinkCache()->partition( $params['table'], $bSize );
85 $extraParams = isset( $opts['params'] ) ?
$opts['params'] : array();
88 // Combine the first range (of size $bSize) backlinks into leaf jobs
89 if ( isset( $ranges[0] ) ) {
90 list( $start, $end ) = $ranges[0];
91 $titles = $title->getBacklinkCache()->getLinks( $params['table'], $start, $end );
92 foreach ( array_chunk( iterator_to_array( $titles ), $cSize ) as $titleBatch ) {
94 foreach ( $titleBatch as $tl ) {
95 $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDBKey() );
98 $title, // maintain parent job title
99 array( 'pages' => $pages ) +
$extraParams
103 // Take all of the remaining ranges and build a partition job from it
104 if ( isset( $ranges[1] ) ) {
105 $jobs[] = new $class(
106 $title, // maintain parent job title
109 'table' => $params['table'],
111 'start' => $ranges[1][0],
112 'end' => $ranges[count( $ranges ) - 1][1],
113 'batchSize' => $realBSize,
114 'subranges' => array_slice( $ranges, 1 )