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
This commit is contained in:
Kunal Mehta 2015-07-26 16:07:59 -07:00
parent 2c44bef931
commit 32d1017e7d

View file

@ -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();
}
}