* Don't connect to the commons DB on cache hits, in order to determine the cache key name. Removed remnants of that bright idea from GlobalFunctions.php.
* Fixed total failure of negative caching in checkRedirect() due to memcached stripping trailing spaces from string values. Probably never worked.
Also:
* Respect hasSharedCache in foreign repos. Recently-added code was apparently ignorant of this setting.
* Renamed getMemcKey() to getSharedCacheKey() to make its function more clear, introduced getLocalCacheKey() to do the other thing. Fixed its parameters to be like wfMemcKey() and used it in more places.
* Used getLocalCacheKey() in various places instead of wfMemc(), to avoid having multiple repositories overwrite each others' caches.
* Fixed the BagOStuff bug that the FIXME in LocalRepo::checkRedirect() appears to refer to.
* Removed getMasterDB() and getSlaveDB() from FileRepo, it's incorrect to assume that a repo other than a LocalRepo has an associated database.
* Made FileRepo::invalidateImageRedirect() a stub, to match FileRepo::checkRedirect(). Moved the functionality to LocalRepo where checkRedirect() is concretely implemented.
* (bug 18173) MediaWiki now fails when unable to determine a client IP
* (bug 19170) Special:Version should follow the content language direction
* (bug 19160) maintenance/purgeOldText.inc is now compatible with PostgreSQL
+* Fixed performance regression in "bad image list" feature
== API changes in 1.16 ==
}
function get($key) {
- if(!$this->bag[$key])
+ if( !isset( $this->bag[$key] ) )
return false;
if($this->_expire($key))
return false;
}
function delete($key,$time=0) {
- if(!$this->bag[$key])
+ if( !isset( $this->bag[$key] ) )
return false;
unset($this->bag[$key]);
return true;
* Get an ASCII string identifying this wiki
* This is used as a prefix in memcached keys
*/
-function wfWikiID( $db = null ) {
- if( $db instanceof Database ) {
- return $db->getWikiID();
- } else {
+function wfWikiID() {
global $wgDBprefix, $wgDBname;
- if ( $wgDBprefix ) {
- return "$wgDBname-$wgDBprefix";
- } else {
- return $wgDBname;
- }
+ if ( $wgDBprefix ) {
+ return "$wgDBname-$wgDBprefix";
+ } else {
+ return $wgDBname;
}
}
if ( $renderUrl ) {
if ( $this->repo->descriptionCacheExpiry > 0 ) {
wfDebug("Attempting to get the description from cache...");
- $key = wfMemcKey( 'RemoteFileDescription', 'url', $wgContLang->getCode(),
+ $key = $this->getLocalCacheKey( 'RemoteFileDescription', 'url', $wgContLang->getCode(),
$this->getName() );
$obj = $wgMemc->get($key);
if ($obj) {
/**
* Invalidates image redirect cache related to that image
- *
+ * Doesn't do anything for repositories that don't support image redirects.
+ *
+ * STUB
* @param Title $title Title of image
*/
- function invalidateImageRedirect( $title ) {
- global $wgMemc;
- $memcKey = $this->getMemcKey( "image_redirect:" . md5( $title->getPrefixedDBkey() ) );
- $wgMemc->delete( $memcKey );
- }
+ function invalidateImageRedirect( $title ) {}
+ /**
+ * Get an array or iterator of file objects for files that have a given
+ * SHA-1 content hash.
+ *
+ * STUB
+ */
function findBySha1( $hash ) {
return array();
}
return wfMsg( 'shared-repo' );
}
- function getSlaveDB() {
- return wfGetDB( DB_SLAVE );
- }
-
- function getMasterDB() {
- return wfGetDB( DB_MASTER );
+ /**
+ * Get a key on the primary cache for this repository.
+ * Returns false if the repository's cache is not accessible at this site.
+ * The parameters are the parts of the key, as for wfMemcKey().
+ *
+ * STUB
+ */
+ function getSharedCacheKey( /*...*/ ) {
+ return false;
}
- function getMemcKey( $key ) {
- return wfWikiID( $this->getSlaveDB() ) . ":{$key}";
+ /**
+ * Get a key for this repo in the local cache domain. These cache keys are
+ * not shared with remote instances of the repo.
+ * The parameters are the parts of the key, as for wfMemcKey().
+ */
+ function getLocalCacheKey( /*...*/ ) {
+ $args = func_get_args();
+ array_unshift( $args, 'filerepo', $this->getName() );
+ return call_user_func_array( 'wfMemcKey', $args );
}
-
}
function purgeDescriptionPage() {
global $wgMemc, $wgContLang;
$url = $this->repo->getDescriptionRenderUrl( $this->getName(), $wgContLang->getCode() );
- $key = wfMemcKey( 'RemoteFileDescription', 'url', md5($url) );
+ $key = $this->repo->getLocalCacheKey( 'RemoteFileDescription', 'url', md5($url) );
$wgMemc->delete( $key );
}
function purgeThumbnails() {
global $wgMemc;
- $key = wfMemcKey( 'ForeignAPIRepo', 'ThumbUrl', $this->getName() );
+ $key = $this->repo->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $this->getName() );
$wgMemc->delete( $key );
$files = $this->getThumbnails();
$dir = $this->getThumbPath( $this->getName() );
'action' => 'query' ) ) );
if( !isset( $this->mQueryCache[$url] ) ) {
- $key = wfMemcKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
+ $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
$data = $wgMemc->get( $key );
if( !$data ) {
$data = Http::get( $url );
return $this->getThumbUrl( $name, $width, $height );
}
- $key = wfMemcKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
+ $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
if ( $thumbUrl = $wgMemc->get($key) ) {
wfDebug("Got thumb from local cache. $thumbUrl \n");
return $thumbUrl;
return $file;
}
- function getCacheKey() {
- if ( $this->repo->hasSharedCache() ) {
- $hashedName = md5($this->name);
- return wfForeignMemcKey( $this->repo->dbName, $this->repo->tablePrefix,
- 'file', $hashedName );
- } else {
- return false;
- }
- }
-
function publish( $srcPath, $flags = 0 ) {
$this->readOnlyError();
}
return $this->hasSharedCache;
}
+ /**
+ * Get a key on the primary cache for this repository.
+ * Returns false if the repository's cache is not accessible at this site.
+ * The parameters are the parts of the key, as for wfMemcKey().
+ */
+ function getSharedCacheKey( /*...*/ ) {
+ if ( $this->hasSharedCache() ) {
+ $args = func_get_args();
+ array_unshift( $args, $this->dbName, $this->tablePrefix );
+ return call_user_func_array( 'wfForeignMemcKey', $args );
+ } else {
+ return false;
+ }
+ }
+
function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
throw new MWException( get_class($this) . ': write operations are not supported' );
}
return $this->hasSharedCache;
}
+ /**
+ * Get a key on the primary cache for this repository.
+ * Returns false if the repository's cache is not accessible at this site.
+ * The parameters are the parts of the key, as for wfMemcKey().
+ */
+ function getSharedCacheKey( /*...*/ ) {
+ if ( $this->hasSharedCache() ) {
+ $args = func_get_args();
+ array_unshift( $args, $this->wiki );
+ return implode( ':', $args );
+ } else {
+ return false;
+ }
+ }
+
function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
throw new MWException( get_class($this) . ': write operations are not supported' );
}
}
/**
- * Get the memcached key
+ * Get the memcached key for the main data for this file, or false if
+ * there is no access to the shared cache.
*/
function getCacheKey() {
$hashedName = md5($this->getName());
- return wfMemcKey( 'file', $hashedName );
+ return $this->repo->getSharedCacheKey( 'file', $hashedName );
}
/**
function purgeHistory() {
global $wgMemc;
$hashedName = md5($this->getName());
- $oldKey = wfMemcKey( 'oldfile', $hashedName );
- $wgMemc->delete( $oldKey );
+ $oldKey = $this->getSharedCacheKey( 'oldfile', $hashedName );
+ if ( $oldKey ) {
+ $wgMemc->delete( $oldKey );
+ }
}
/**
$title = Title::makeTitle( NS_FILE, $title->getText() );
}
- $memcKey = $this->getMemcKey( "image_redirect:" . md5( $title->getPrefixedDBkey() ) );
+ $memcKey = $this->getSharedCacheKey( 'image_redirect', md5( $title->getPrefixedDBkey() ) );
+ if ( $memcKey === false ) {
+ $memcKey = $this->getLocalCacheKey( 'image_redirect', md5( $title->getPrefixedDBkey() ) );
+ $expiry = 300; // no invalidation, 5 minutes
+ } else {
+ $expiry = 86400; // has invalidation, 1 day
+ }
$cachedValue = $wgMemc->get( $memcKey );
- if( $cachedValue ) {
- return Title::newFromDbKey( $cachedValue );
- } elseif( $cachedValue == ' ' ) { # FIXME: ugly hack, but BagOStuff caching seems to be weird and return false if !cachedValue, not only if it doesn't exist
+ if ( $cachedValue === ' ' || $cachedValue === '' ) {
+ // Does not exist
return false;
- }
+ } elseif ( strval( $cachedValue ) !== '' ) {
+ return Title::newFromText( $cachedValue );
+ } // else $cachedValue is false or null: cache miss
$id = $this->getArticleID( $title );
if( !$id ) {
- $wgMemc->set( $memcKey, " ", 9000 );
+ $wgMemc->set( $memcKey, " ", $expiry );
return false;
}
$dbr = $this->getSlaveDB();
__METHOD__
);
- if( $row ) $targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title );
- $wgMemc->set( $memcKey, ($row ? $targetTitle->getPrefixedDBkey() : " "), 9000 );
- if( !$row ) {
+ if( $row ) {
+ $targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title );
+ $wgMemc->set( $memcKey, $targetTitle->getPrefixedDBkey(), $expiry );
+ return $targetTitle;
+ } else {
+ $wgMemc->set( $memcKey, '', $expiry );
return false;
}
- return $targetTitle;
}
return $id;
}
-
-
+ /**
+ * Get an array or iterator of file objects for files that have a given
+ * SHA-1 content hash.
+ */
function findBySha1( $hash ) {
$dbr = $this->getSlaveDB();
$res = $dbr->select(
$res->free();
return $result;
}
+
+ /**
+ * Get a connection to the slave DB
+ */
+ function getSlaveDB() {
+ return wfGetDB( DB_SLAVE );
+ }
+
+ /**
+ * Get a connection to the master DB
+ */
+ function getMasterDB() {
+ return wfGetDB( DB_MASTER );
+ }
+
+ /**
+ * Get a key on the primary cache for this repository.
+ * Returns false if the repository's cache is not accessible at this site.
+ * The parameters are the parts of the key, as for wfMemcKey().
+ */
+ function getSharedCacheKey( /*...*/ ) {
+ $args = func_get_args();
+ return call_user_func_array( 'wfMemcKey', $args );
+ }
+
+ /**
+ * Invalidates image redirect cache related to that image
+ *
+ * @param Title $title Title of image
+ */
+ function invalidateImageRedirect( $title ) {
+ global $wgMemc;
+ $memcKey = $this->getSharedCacheKey( 'image_redirect', md5( $title->getPrefixedDBkey() ) );
+ if ( $memcKey ) {
+ $wgMemc->delete( $memcKey );
+ }
+ }
}
+