From: Kunal Mehta Date: Sun, 26 Jul 2015 23:07:59 +0000 (-0700) Subject: Don't let LinkCache grow indefinitely X-Git-Tag: 1.31.0-rc.0~10634^2 X-Git-Url: https://git.heureux-cyclage.org/?a=commitdiff_plain;h=32d1017e7d779effabb719f513b3cd346bfa814b;p=lhc%2Fweb%2Fwiklou.git Don't let LinkCache grow indefinitely Especially in long running maintenance scripts, this can be problematic. LinkCache is now LRU-based, and will store a maximum of 10,000 good titles, and 10,000 bad ones. LinkCache::getGoodLinks() and getBadLinks() are deprecated since they problematic to support in this implementation and are unused. Bug: T106998 Change-Id: I1328149d65a5e75a5d6e10cb2686a099562a1847 --- diff --git a/includes/cache/LinkCache.php b/includes/cache/LinkCache.php index e8cc5e5b67..56c92569ec 100644 --- a/includes/cache/LinkCache.php +++ b/includes/cache/LinkCache.php @@ -29,18 +29,34 @@ class LinkCache { // Increment $mClassVer whenever old serialized versions of this class // becomes incompatible with the new version. - private $mClassVer = 4; + private $mClassVer = 5; - private $mGoodLinks = array(); - private $mGoodLinkFields = array(); - private $mBadLinks = array(); + /** + * @var MapCacheLRU + */ + private $mGoodLinks; + /** + * @var MapCacheLRU + */ + private $mBadLinks; private $mForUpdate = false; + /** + * How many Titles to store. There are two caches, so the amount actually + * stored in memory can be up to twice this. + */ + const MAX_SIZE = 10000; + /** * @var LinkCache */ protected static $instance; + public function __construct() { + $this->mGoodLinks = new MapCacheLRU( self::MAX_SIZE ); + $this->mBadLinks = new MapCacheLRU( self::MAX_SIZE ); + } + /** * Get an instance of this class. * @@ -90,8 +106,9 @@ class LinkCache { * @return int */ public function getGoodLinkID( $title ) { - if ( array_key_exists( $title, $this->mGoodLinks ) ) { - return $this->mGoodLinks[$title]; + if ( $this->mGoodLinks->has( $title ) ) { + $info = $this->mGoodLinks->get( $title ); + return $info['id']; } else { return 0; } @@ -106,8 +123,9 @@ class LinkCache { */ public function getGoodLinkFieldObj( $title, $field ) { $dbkey = $title->getPrefixedDBkey(); - if ( array_key_exists( $dbkey, $this->mGoodLinkFields ) ) { - return $this->mGoodLinkFields[$dbkey][$field]; + if ( $this->mGoodLinks->has( $dbkey ) ) { + $info = $this->mGoodLinks->get( $dbkey ); + return $info[$field]; } else { return null; } @@ -118,7 +136,8 @@ class LinkCache { * @return bool */ public function isBadLink( $title ) { - return array_key_exists( $title, $this->mBadLinks ); + // We need to use get here since has will not call ping. + return $this->mBadLinks->get( $title ) !== null; } /** @@ -135,13 +154,13 @@ class LinkCache { $revision = 0, $model = null ) { $dbkey = $title->getPrefixedDBkey(); - $this->mGoodLinks[$dbkey] = (int)$id; - $this->mGoodLinkFields[$dbkey] = array( + $this->mGoodLinks->set( $dbkey, array( + 'id' => (int)$id, 'length' => (int)$len, 'redirect' => (int)$redir, 'revision' => (int)$revision, 'model' => $model ? (string)$model : null, - ); + ) ); } /** @@ -153,13 +172,13 @@ class LinkCache { */ public function addGoodLinkObjFromRow( $title, $row ) { $dbkey = $title->getPrefixedDBkey(); - $this->mGoodLinks[$dbkey] = intval( $row->page_id ); - $this->mGoodLinkFields[$dbkey] = array( + $this->mGoodLinks->set( $dbkey, array( + 'id' => intval( $row->page_id ), 'length' => intval( $row->page_len ), 'redirect' => intval( $row->page_is_redirect ), 'revision' => intval( $row->page_latest ), 'model' => !empty( $row->page_content_model ) ? strval( $row->page_content_model ) : null, - ); + ) ); } /** @@ -168,12 +187,12 @@ class LinkCache { public function addBadLinkObj( $title ) { $dbkey = $title->getPrefixedDBkey(); if ( !$this->isBadLink( $dbkey ) ) { - $this->mBadLinks[$dbkey] = 1; + $this->mBadLinks->set( $dbkey, 1 ); } } public function clearBadLink( $title ) { - unset( $this->mBadLinks[$title] ); + $this->mBadLinks->clear( array( $title ) ); } /** @@ -181,17 +200,33 @@ class LinkCache { */ public function clearLink( $title ) { $dbkey = $title->getPrefixedDBkey(); - unset( $this->mBadLinks[$dbkey] ); - unset( $this->mGoodLinks[$dbkey] ); - unset( $this->mGoodLinkFields[$dbkey] ); + $this->mBadLinks->clear( array( $dbkey ) ); + $this->mGoodLinks->clear( array( $dbkey ) ); } + + /** + * @deprecated since 1.26 + * @return array + */ public function getGoodLinks() { - return $this->mGoodLinks; + wfDeprecated( __METHOD__, '1.26' ); + $links = array(); + foreach ( $this->mGoodLinks->getAllKeys() as $key ) { + $info = $this->mGoodLinks->get( $key ); + $links[$key] = $info['id']; + } + + return $links; } + /** + * @deprecated since 1.26 + * @return array + */ public function getBadLinks() { - return array_keys( $this->mBadLinks ); + wfDeprecated( __METHOD__, '1.26' ); + return $this->mBadLinks->getAllKeys(); } /** @@ -262,8 +297,7 @@ class LinkCache { * Clears cache */ public function clear() { - $this->mGoodLinks = array(); - $this->mGoodLinkFields = array(); - $this->mBadLinks = array(); + $this->mGoodLinks->clear(); + $this->mBadLinks->clear(); } }