From 1eae9941d9d18492e5ecc651b0d6dc7f02a5f30b Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Fri, 4 Dec 2009 01:55:05 +0000 Subject: [PATCH] Fix bug in BacklinkCache: the lack of an ORDER BY clause in getLinks(), combined with the lack of sensible indexes on the categorylinks table, was causing partition() to return starts and ends scaterred randomly across the result set. For large jobs, many partitions end up being large, causing HTMLCacheUpdate::doPartialUpdate() to repartition, thus requeueing jobs in an infinite recursive loop. The BacklinkCache bug was there since r47317, but was relatively harmless until r54841 introduced the infinite loop issue. --- RELEASE-NOTES | 2 ++ includes/BacklinkCache.php | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 3683eb012b..9fd3ce74ec 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -661,6 +661,8 @@ Hopefully we will remove this configuration var soon) * (bug 18762) both redirects and links get fixed one after another if redirects-only switch is not present * (bug 20159) thumbnails rerendered if older that $wgThumbnailEpoch +* Fixed a bug which in some situations causes the job queue to grow forever, + due to an infinite loop of job requeues. == API changes in 1.16 == diff --git a/includes/BacklinkCache.php b/includes/BacklinkCache.php index a7bcd8583a..ff1a1a329c 100644 --- a/includes/BacklinkCache.php +++ b/includes/BacklinkCache.php @@ -53,13 +53,13 @@ class BacklinkCache { public function getLinks( $table, $startId = false, $endId = false ) { wfProfileIn( __METHOD__ ); + $fromField = $this->getPrefix( $table ) . '_from'; if ( $startId || $endId ) { // Partial range, not cached wfDebug( __METHOD__.": from DB (uncacheable range)\n" ); $conds = $this->getConditions( $table ); // Use the from field in the condition rather than the joined page_id, // because databases are stupid and don't necessarily propagate indexes. - $fromField = $this->getPrefix( $table ) . '_from'; if ( $startId ) { $conds[] = "$fromField >= " . intval( $startId ); } @@ -71,7 +71,10 @@ class BacklinkCache { array( 'page_namespace', 'page_title', 'page_id'), $conds, __METHOD__, - array('STRAIGHT_JOIN') ); + array( + 'STRAIGHT_JOIN', + 'ORDER BY' => $fromField + ) ); $ta = TitleArray::newFromResult( $res ); wfProfileOut( __METHOD__ ); return $ta; @@ -84,7 +87,10 @@ class BacklinkCache { array( 'page_namespace', 'page_title', 'page_id' ), $this->getConditions( $table ), __METHOD__, - array('STRAIGHT_JOIN') ); + array( + 'STRAIGHT_JOIN', + 'ORDER BY' => $fromField, + ) ); $this->fullResultCache[$table] = $res; } $ta = TitleArray::newFromResult( $this->fullResultCache[$table] ); @@ -225,6 +231,12 @@ class BacklinkCache { $row = $res->fetchObject(); $end = $row->page_id - 1; } + + # Sanity check order + if ( $start && $end && $start > $end ) { + throw new MWException( __METHOD__.': Internal error: query result out of order' ); + } + $batches[] = array( $start, $end ); } return array( 'numRows' => $numRows, 'batches' => $batches ); -- 2.20.1