summaryrefslogtreecommitdiff
path: root/includes/cache
diff options
context:
space:
mode:
Diffstat (limited to 'includes/cache')
-rw-r--r--includes/cache/CacheDependency.php23
-rw-r--r--includes/cache/FileCacheBase.php35
-rw-r--r--includes/cache/GenderCache.php93
-rw-r--r--includes/cache/HTMLCacheUpdate.php21
-rw-r--r--includes/cache/HTMLFileCache.php33
-rw-r--r--includes/cache/LinkBatch.php28
-rw-r--r--includes/cache/LinkCache.php22
-rw-r--r--includes/cache/MemcachedSessions.php98
-rw-r--r--includes/cache/MessageCache.php40
-rw-r--r--includes/cache/ObjectFileCache.php24
-rw-r--r--includes/cache/ProcessCacheLRU.php120
-rw-r--r--includes/cache/ResourceFileCache.php24
-rw-r--r--includes/cache/SquidUpdate.php64
-rw-r--r--includes/cache/UserCache.php134
14 files changed, 609 insertions, 150 deletions
diff --git a/includes/cache/CacheDependency.php b/includes/cache/CacheDependency.php
index 0df0cd89..a3c2b52a 100644
--- a/includes/cache/CacheDependency.php
+++ b/includes/cache/CacheDependency.php
@@ -1,11 +1,32 @@
<?php
/**
+ * Data caching with dependencies.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
* This class stores an arbitrary value along with its dependencies.
* Users should typically only use DependencyWrapper::getValueFromCache(),
* rather than instantiating one of these objects directly.
* @ingroup Cache
*/
-
class DependencyWrapper {
var $value;
var $deps;
diff --git a/includes/cache/FileCacheBase.php b/includes/cache/FileCacheBase.php
index 37401655..c0c5609c 100644
--- a/includes/cache/FileCacheBase.php
+++ b/includes/cache/FileCacheBase.php
@@ -1,9 +1,31 @@
<?php
/**
- * Contain the FileCacheBase class
+ * Data storage in the file system.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
+
+/**
+ * Base class for data storage in the file system.
+ *
+ * @ingroup Cache
+ */
abstract class FileCacheBase {
protected $mKey;
protected $mType = 'object';
@@ -74,7 +96,7 @@ abstract class FileCacheBase {
/**
* Get the last-modified timestamp of the cache file
- * @return string|false TS_MW timestamp
+ * @return string|bool TS_MW timestamp
*/
public function cacheTimestamp() {
$timestamp = filemtime( $this->cachePath() );
@@ -116,9 +138,12 @@ abstract class FileCacheBase {
* @return string
*/
public function fetchText() {
- // gzopen can transparently read from gziped or plain text
- $fh = gzopen( $this->cachePath(), 'rb' );
- return stream_get_contents( $fh );
+ if( $this->useGzip() ) {
+ $fh = gzopen( $this->cachePath(), 'rb' );
+ return stream_get_contents( $fh );
+ } else {
+ return file_get_contents( $this->cachePath() );
+ }
}
/**
diff --git a/includes/cache/GenderCache.php b/includes/cache/GenderCache.php
index 342f8dba..2a169bb3 100644
--- a/includes/cache/GenderCache.php
+++ b/includes/cache/GenderCache.php
@@ -1,8 +1,30 @@
<?php
-
/**
* Caches user genders when needed to use correct namespace aliases.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
* @author Niklas Laxström
+ * @ingroup Cache
+ */
+
+/**
+ * Caches user genders when needed to use correct namespace aliases.
+ *
* @since 1.18
*/
class GenderCache {
@@ -37,14 +59,18 @@ class GenderCache {
/**
* Returns the gender for given username.
- * @param $username String: username
+ * @param $username String or User: username
* @param $caller String: the calling method
* @return String
*/
public function getGenderOf( $username, $caller = '' ) {
global $wgUser;
- $username = strtr( $username, '_', ' ' );
+ if( $username instanceof User ) {
+ $username = $username->getName();
+ }
+
+ $username = self::normalizeUsername( $username );
if ( !isset( $this->cache[$username] ) ) {
if ( $this->misses >= $this->missLimit && $wgUser->getName() !== $username ) {
@@ -56,11 +82,7 @@ class GenderCache {
} else {
$this->misses++;
- if ( !User::isValidUserName( $username ) ) {
- $this->cache[$username] = $this->getDefault();
- } else {
- $this->doQuery( $username, $caller );
- }
+ $this->doQuery( $username, $caller );
}
}
@@ -82,7 +104,6 @@ class GenderCache {
foreach ( $data as $ns => $pagenames ) {
if ( !MWNamespace::hasGenderDistinction( $ns ) ) continue;
foreach ( array_keys( $pagenames ) as $username ) {
- if ( isset( $this->cache[$username] ) ) continue;
$users[$username] = true;
}
}
@@ -91,6 +112,29 @@ class GenderCache {
}
/**
+ * Wrapper for doQuery that processes a title or string array.
+ *
+ * @since 1.20
+ * @param $titles List: array of Title objects or strings
+ * @param $caller String: the calling method
+ */
+ public function doTitlesArray( $titles, $caller = '' ) {
+ $users = array();
+ foreach ( $titles as $title ) {
+ $titleObj = is_string( $title ) ? Title::newFromText( $title ) : $title;
+ if ( !$titleObj ) {
+ continue;
+ }
+ if ( !MWNamespace::hasGenderDistinction( $titleObj->getNamespace() ) ) {
+ continue;
+ }
+ $users[] = $titleObj->getText();
+ }
+
+ $this->doQuery( $users, $caller );
+ }
+
+ /**
* Preloads genders for given list of users.
* @param $users List|String: usernames
* @param $caller String: the calling method
@@ -98,26 +142,28 @@ class GenderCache {
public function doQuery( $users, $caller = '' ) {
$default = $this->getDefault();
- foreach ( (array) $users as $index => $value ) {
- $name = strtr( $value, '_', ' ' );
- if ( isset( $this->cache[$name] ) ) {
- // Skip users whose gender setting we already know
- unset( $users[$index] );
- } else {
- $users[$index] = $name;
+ $usersToCheck = array();
+ foreach ( (array) $users as $value ) {
+ $name = self::normalizeUsername( $value );
+ // Skip users whose gender setting we already know
+ if ( !isset( $this->cache[$name] ) ) {
// For existing users, this value will be overwritten by the correct value
$this->cache[$name] = $default;
+ // query only for valid names, which can be in the database
+ if( User::isValidUserName( $name ) ) {
+ $usersToCheck[] = $name;
+ }
}
}
- if ( count( $users ) === 0 ) {
+ if ( count( $usersToCheck ) === 0 ) {
return;
}
$dbr = wfGetDB( DB_SLAVE );
$table = array( 'user', 'user_properties' );
$fields = array( 'user_name', 'up_value' );
- $conds = array( 'user_name' => $users );
+ $conds = array( 'user_name' => $usersToCheck );
$joins = array( 'user_properties' =>
array( 'LEFT JOIN', array( 'user_id = up_user', 'up_property' => 'gender' ) ) );
@@ -125,11 +171,20 @@ class GenderCache {
if ( strval( $caller ) !== '' ) {
$comment .= "/$caller";
}
- $res = $dbr->select( $table, $fields, $conds, $comment, $joins, $joins );
+ $res = $dbr->select( $table, $fields, $conds, $comment, array(), $joins );
foreach ( $res as $row ) {
$this->cache[$row->user_name] = $row->up_value ? $row->up_value : $default;
}
}
+ private static function normalizeUsername( $username ) {
+ // Strip off subpages
+ $indexSlash = strpos( $username, '/' );
+ if ( $indexSlash !== false ) {
+ $username = substr( $username, 0, $indexSlash );
+ }
+ // normalize underscore/spaces
+ return strtr( $username, '_', ' ' );
+ }
}
diff --git a/includes/cache/HTMLCacheUpdate.php b/includes/cache/HTMLCacheUpdate.php
index 11e2ae74..0a3c0023 100644
--- a/includes/cache/HTMLCacheUpdate.php
+++ b/includes/cache/HTMLCacheUpdate.php
@@ -1,4 +1,25 @@
<?php
+/**
+ * HTML cache invalidation of all pages linking to a given title.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
/**
* Class to invalidate the HTML cache of all the pages linking to a given title.
diff --git a/includes/cache/HTMLFileCache.php b/includes/cache/HTMLFileCache.php
index 92130f69..6bfeed32 100644
--- a/includes/cache/HTMLFileCache.php
+++ b/includes/cache/HTMLFileCache.php
@@ -1,9 +1,33 @@
<?php
/**
- * Contain the HTMLFileCache class
+ * Page view caching in the file system.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
+
+/**
+ * Page view caching in the file system.
+ * The only cacheable actions are "view" and "history". Also special pages
+ * will not be cached.
+ *
+ * @ingroup Cache
+ */
class HTMLFileCache extends FileCacheBase {
/**
* Construct an ObjectFileCache from a Title and an action
@@ -105,19 +129,22 @@ class HTMLFileCache extends FileCacheBase {
wfDebug( __METHOD__ . "()\n");
$filename = $this->cachePath();
+
$context->getOutput()->sendCacheControl();
header( "Content-Type: $wgMimeType; charset=UTF-8" );
header( "Content-Language: $wgLanguageCode" );
if ( $this->useGzip() ) {
if ( wfClientAcceptsGzip() ) {
header( 'Content-Encoding: gzip' );
+ readfile( $filename );
} else {
/* Send uncompressed */
+ wfDebug( __METHOD__ . " uncompressing cache file and sending it\n" );
readgzfile( $filename );
- return;
}
+ } else {
+ readfile( $filename );
}
- readfile( $filename );
$context->getOutput()->disable(); // tell $wgOut that output is taken care of
}
diff --git a/includes/cache/LinkBatch.php b/includes/cache/LinkBatch.php
index 17e8739b..372f983b 100644
--- a/includes/cache/LinkBatch.php
+++ b/includes/cache/LinkBatch.php
@@ -1,4 +1,25 @@
<?php
+/**
+ * Batch query to determine page existence.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
/**
* Class representing a list of titles
@@ -45,6 +66,11 @@ class LinkBatch {
}
}
+ /**
+ * @param $ns int
+ * @param $dbkey string
+ * @return mixed
+ */
public function add( $ns, $dbkey ) {
if ( $ns < 0 ) {
return;
@@ -190,7 +216,7 @@ class LinkBatch {
}
$genderCache = GenderCache::singleton();
- $genderCache->dolinkBatch( $this->data, $this->caller );
+ $genderCache->doLinkBatch( $this->data, $this->caller );
return true;
}
diff --git a/includes/cache/LinkCache.php b/includes/cache/LinkCache.php
index a73eaaa4..f759c020 100644
--- a/includes/cache/LinkCache.php
+++ b/includes/cache/LinkCache.php
@@ -1,5 +1,27 @@
<?php
/**
+ * Page existence cache.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
* Cache for article titles (prefixed DB keys) and ids linked from one source
*
* @ingroup Cache
diff --git a/includes/cache/MemcachedSessions.php b/includes/cache/MemcachedSessions.php
deleted file mode 100644
index 36733595..00000000
--- a/includes/cache/MemcachedSessions.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * This file gets included if $wgSessionsInMemcache is set in the config.
- * It redirects session handling functions to store their data in memcached
- * instead of the local filesystem. Depending on circumstances, it may also
- * be necessary to change the cookie settings to work across hostnames.
- * See: http://www.php.net/manual/en/function.session-set-save-handler.php
- *
- * @file
- * @ingroup Cache
- */
-
-/**
- * Get a cache key for the given session id.
- *
- * @param $id String: session id
- * @return String: cache key
- */
-function memsess_key( $id ) {
- return wfMemcKey( 'session', $id );
-}
-
-/**
- * Callback when opening a session.
- * NOP: $wgMemc should be set up already.
- *
- * @param $save_path String: path used to store session files, unused
- * @param $session_name String: session name
- * @return Boolean: success
- */
-function memsess_open( $save_path, $session_name ) {
- return true;
-}
-
-/**
- * Callback when closing a session.
- * NOP.
- *
- * @return Boolean: success
- */
-function memsess_close() {
- return true;
-}
-
-/**
- * Callback when reading session data.
- *
- * @param $id String: session id
- * @return Mixed: session data
- */
-function memsess_read( $id ) {
- global $wgMemc;
- $data = $wgMemc->get( memsess_key( $id ) );
- if( ! $data ) return '';
- return $data;
-}
-
-/**
- * Callback when writing session data.
- *
- * @param $id String: session id
- * @param $data Mixed: session data
- * @return Boolean: success
- */
-function memsess_write( $id, $data ) {
- global $wgMemc;
- $wgMemc->set( memsess_key( $id ), $data, 3600 );
- return true;
-}
-
-/**
- * Callback to destroy a session when calling session_destroy().
- *
- * @param $id String: session id
- * @return Boolean: success
- */
-function memsess_destroy( $id ) {
- global $wgMemc;
-
- $wgMemc->delete( memsess_key( $id ) );
- return true;
-}
-
-/**
- * Callback to execute garbage collection.
- * NOP: Memcached performs garbage collection.
- *
- * @param $maxlifetime Integer: maximum session life time
- * @return Boolean: success
- */
-function memsess_gc( $maxlifetime ) {
- return true;
-}
-
-function memsess_write_close() {
- session_write_close();
-}
-
diff --git a/includes/cache/MessageCache.php b/includes/cache/MessageCache.php
index 146edd28..b854a2ec 100644
--- a/includes/cache/MessageCache.php
+++ b/includes/cache/MessageCache.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Localisation messages cache.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
@@ -115,6 +132,7 @@ class MessageCache {
function getParserOptions() {
if ( !$this->mParserOptions ) {
$this->mParserOptions = new ParserOptions;
+ $this->mParserOptions->setEditSection( false );
}
return $this->mParserOptions;
}
@@ -126,7 +144,7 @@ class MessageCache {
*
* @param $hash String: the hash of contents, to check validity.
* @param $code Mixed: Optional language code, see documenation of load().
- * @return false on failure.
+ * @return bool on failure.
*/
function loadFromLocal( $hash, $code ) {
global $wgCacheDirectory, $wgLocalMessageCacheSerialized;
@@ -260,6 +278,7 @@ class MessageCache {
* is disabled.
*
* @param $code String: language to which load messages
+ * @return bool
*/
function load( $code = false ) {
global $wgUseLocalMessageCache;
@@ -496,7 +515,7 @@ class MessageCache {
if ( $code === 'en' ) {
// Delete all sidebars, like for example on action=purge on the
// sidebar messages
- $codes = array_keys( Language::getLanguageNames() );
+ $codes = array_keys( Language::fetchLanguageNames() );
}
global $wgMemc;
@@ -520,7 +539,7 @@ class MessageCache {
* @param $cache Array: cached messages with a version.
* @param $memc Bool: Wether to update or not memcache.
* @param $code String: Language code.
- * @return False on somekind of error.
+ * @return bool on somekind of error.
*/
protected function saveToCaches( $cache, $memc = true, $code = false ) {
wfProfileIn( __METHOD__ );
@@ -588,7 +607,7 @@ class MessageCache {
* @param $isFullKey Boolean: specifies whether $key is a two part key
* "msg/lang".
*
- * @return string|false
+ * @return string|bool
*/
function get( $key, $useDB = true, $langcode = true, $isFullKey = false ) {
global $wgLanguageCode, $wgContLang;
@@ -696,7 +715,7 @@ class MessageCache {
* @param $title String: Message cache key with initial uppercase letter.
* @param $code String: code denoting the language to try.
*
- * @return string|false
+ * @return string|bool False on failure
*/
function getMsgFromNamespace( $title, $code ) {
global $wgAdaptiveMessageCache;
@@ -747,12 +766,14 @@ class MessageCache {
}
# Try loading it from the database
- $revision = Revision::newFromTitle( Title::makeTitle( NS_MEDIAWIKI, $title ) );
+ $revision = Revision::newFromTitle(
+ Title::makeTitle( NS_MEDIAWIKI, $title ), false, Revision::READ_LATEST
+ );
if ( $revision ) {
$message = $revision->getText();
if ($message === false) {
// A possibly temporary loading failure.
- wfDebugLog( 'MessageCache', __METHOD__ . ": failed to load message page text for {$title->getDbKey()} ($code)" );
+ wfDebugLog( 'MessageCache', __METHOD__ . ": failed to load message page text for {$title} ($code)" );
} else {
$this->mCache[$code][$title] = ' ' . $message;
$this->mMemc->set( $titleKey, ' ' . $message, $this->mExpiry );
@@ -868,7 +889,7 @@ class MessageCache {
* Clear all stored messages. Mainly used after a mass rebuild.
*/
function clear() {
- $langs = Language::getLanguageNames( false );
+ $langs = Language::fetchLanguageNames( null, 'mw' );
foreach ( array_keys($langs) as $code ) {
# Global cache
$this->mMemc->delete( wfMemcKey( 'messages', $code ) );
@@ -890,8 +911,7 @@ class MessageCache {
}
$lang = array_pop( $pieces );
- $validCodes = Language::getLanguageNames();
- if( !array_key_exists( $lang, $validCodes ) ) {
+ if( !Language::fetchLanguageName( $lang, null, 'mw' ) ) {
return array( $key, $wgLanguageCode );
}
diff --git a/includes/cache/ObjectFileCache.php b/includes/cache/ObjectFileCache.php
index 3356f1fc..ed1e49a6 100644
--- a/includes/cache/ObjectFileCache.php
+++ b/includes/cache/ObjectFileCache.php
@@ -1,9 +1,31 @@
<?php
/**
- * Contain the ObjectFileCache class
+ * Object cache in the file system.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
+
+/**
+ * Object cache in the file system.
+ *
+ * @ingroup Cache
+ */
class ObjectFileCache extends FileCacheBase {
/**
* Construct an ObjectFileCache from a key and a type
diff --git a/includes/cache/ProcessCacheLRU.php b/includes/cache/ProcessCacheLRU.php
new file mode 100644
index 00000000..f215ebd8
--- /dev/null
+++ b/includes/cache/ProcessCacheLRU.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * Per-process memory cache for storing items.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * Handles per process caching of items
+ * @ingroup Cache
+ */
+class ProcessCacheLRU {
+ /** @var Array */
+ protected $cache = array(); // (key => prop => value)
+
+ protected $maxCacheKeys; // integer; max entries
+
+ /**
+ * @param $maxKeys integer Maximum number of entries allowed (min 1).
+ * @throws MWException When $maxCacheKeys is not an int or =< 0.
+ */
+ public function __construct( $maxKeys ) {
+ if ( !is_int( $maxKeys ) || $maxKeys < 1 ) {
+ throw new MWException( __METHOD__ . " must be given an integer and >= 1" );
+ }
+ $this->maxCacheKeys = $maxKeys;
+ }
+
+ /**
+ * Set a property field for a cache entry.
+ * This will prune the cache if it gets too large.
+ * If the item is already set, it will be pushed to the top of the cache.
+ *
+ * @param $key string
+ * @param $prop string
+ * @param $value mixed
+ * @return void
+ */
+ public function set( $key, $prop, $value ) {
+ if ( isset( $this->cache[$key] ) ) {
+ $this->ping( $key ); // push to top
+ } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
+ reset( $this->cache );
+ unset( $this->cache[key( $this->cache )] );
+ }
+ $this->cache[$key][$prop] = $value;
+ }
+
+ /**
+ * Check if a property field exists for a cache entry.
+ *
+ * @param $key string
+ * @param $prop string
+ * @return bool
+ */
+ public function has( $key, $prop ) {
+ return isset( $this->cache[$key][$prop] );
+ }
+
+ /**
+ * Get a property field for a cache entry.
+ * This returns null if the property is not set.
+ * If the item is already set, it will be pushed to the top of the cache.
+ *
+ * @param $key string
+ * @param $prop string
+ * @return mixed
+ */
+ public function get( $key, $prop ) {
+ if ( isset( $this->cache[$key][$prop] ) ) {
+ $this->ping( $key ); // push to top
+ return $this->cache[$key][$prop];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Clear one or several cache entries, or all cache entries
+ *
+ * @param $keys string|Array
+ * @return void
+ */
+ public function clear( $keys = null ) {
+ if ( $keys === null ) {
+ $this->cache = array();
+ } else {
+ foreach ( (array)$keys as $key ) {
+ unset( $this->cache[$key] );
+ }
+ }
+ }
+
+ /**
+ * Push an entry to the top of the cache
+ *
+ * @param $key string
+ */
+ protected function ping( $key ) {
+ $item = $this->cache[$key];
+ unset( $this->cache[$key] );
+ $this->cache[$key] = $item;
+ }
+}
diff --git a/includes/cache/ResourceFileCache.php b/includes/cache/ResourceFileCache.php
index e73fc2d7..61f1e8c3 100644
--- a/includes/cache/ResourceFileCache.php
+++ b/includes/cache/ResourceFileCache.php
@@ -1,9 +1,31 @@
<?php
/**
- * Contain the ResourceFileCache class
+ * Resource loader request result caching in the file system.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
+
+/**
+ * Resource loader request result caching in the file system.
+ *
+ * @ingroup Cache
+ */
class ResourceFileCache extends FileCacheBase {
protected $mCacheWorthy;
diff --git a/includes/cache/SquidUpdate.php b/includes/cache/SquidUpdate.php
index d47b5b5e..423e3884 100644
--- a/includes/cache/SquidUpdate.php
+++ b/includes/cache/SquidUpdate.php
@@ -1,6 +1,22 @@
<?php
/**
- * See deferred.txt
+ * Squid cache purging.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Cache
*/
@@ -12,13 +28,18 @@
class SquidUpdate {
var $urlArr, $mMaxTitles;
- function __construct( $urlArr = Array(), $maxTitles = false ) {
+ /**
+ * @param $urlArr array
+ * @param $maxTitles bool|int
+ */
+ function __construct( $urlArr = array(), $maxTitles = false ) {
global $wgMaxSquidPurgeTitles;
if ( $maxTitles === false ) {
$this->mMaxTitles = $wgMaxSquidPurgeTitles;
} else {
$this->mMaxTitles = $maxTitles;
}
+ $urlArr = array_unique( $urlArr ); // Remove duplicates
if ( count( $urlArr ) > $this->mMaxTitles ) {
$urlArr = array_slice( $urlArr, 0, $this->mMaxTitles );
}
@@ -102,23 +123,19 @@ class SquidUpdate {
* @return void
*/
static function purge( $urlArr ) {
- global $wgSquidServers, $wgHTCPMulticastAddress, $wgHTCPPort;
-
- /*if ( (@$wgSquidServers[0]) == 'echo' ) {
- echo implode("<br />\n", $urlArr) . "<br />\n";
- return;
- }*/
+ global $wgSquidServers, $wgHTCPMulticastRouting;
if( !$urlArr ) {
return;
}
- if ( $wgHTCPMulticastAddress && $wgHTCPPort ) {
+ if ( $wgHTCPMulticastRouting ) {
SquidUpdate::HTCPPurge( $urlArr );
}
wfProfileIn( __METHOD__ );
+ $urlArr = array_unique( $urlArr ); // Remove duplicates
$maxSocketsPerSquid = 8; // socket cap per Squid
$urlsPerSocket = 400; // 400 seems to be a good tradeoff, opening a socket takes a while
$socketsPerSquid = ceil( count( $urlArr ) / $urlsPerSocket );
@@ -147,7 +164,7 @@ class SquidUpdate {
* @param $urlArr array
*/
static function HTCPPurge( $urlArr ) {
- global $wgHTCPMulticastAddress, $wgHTCPMulticastTTL, $wgHTCPPort;
+ global $wgHTCPMulticastRouting, $wgHTCPMulticastTTL;
wfProfileIn( __METHOD__ );
$htcpOpCLR = 4; // HTCP CLR
@@ -168,11 +185,20 @@ class SquidUpdate {
socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_TTL,
$wgHTCPMulticastTTL );
+ $urlArr = array_unique( $urlArr ); // Remove duplicates
foreach ( $urlArr as $url ) {
if( !is_string( $url ) ) {
throw new MWException( 'Bad purge URL' );
}
$url = SquidUpdate::expand( $url );
+ $conf = self::getRuleForURL( $url, $wgHTCPMulticastRouting );
+ if ( !$conf ) {
+ wfDebug( "No HTCP rule configured for URL $url , skipping\n" );
+ continue;
+ }
+ if ( !isset( $conf['host'] ) || !isset( $conf['port'] ) ) {
+ throw new MWException( "Invalid HTCP rule for URL $url\n" );
+ }
// Construct a minimal HTCP request diagram
// as per RFC 2756
@@ -196,7 +222,7 @@ class SquidUpdate {
// Send out
wfDebug( "Purging URL $url via HTCP\n" );
socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
- $wgHTCPMulticastAddress, $wgHTCPPort );
+ $conf['host'], $conf['port'] );
}
} else {
$errstr = socket_strerror( socket_last_error() );
@@ -223,4 +249,20 @@ class SquidUpdate {
static function expand( $url ) {
return wfExpandUrl( $url, PROTO_INTERNAL );
}
+
+ /**
+ * Find the HTCP routing rule to use for a given URL.
+ * @param $url string URL to match
+ * @param $rules array Array of rules, see $wgHTCPMulticastRouting for format and behavior
+ * @return mixed Element of $rules that matched, or false if nothing matched
+ */
+ static function getRuleForURL( $url, $rules ) {
+ foreach ( $rules as $regex => $routing ) {
+ if ( $regex === '' || preg_match( $regex, $url ) ) {
+ return $routing;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/includes/cache/UserCache.php b/includes/cache/UserCache.php
new file mode 100644
index 00000000..6ec23669
--- /dev/null
+++ b/includes/cache/UserCache.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Caches current user names and other info based on user IDs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * @since 1.20
+ */
+class UserCache {
+ protected $cache = array(); // (uid => property => value)
+ protected $typesCached = array(); // (uid => cache type => 1)
+
+ /**
+ * @return UserCache
+ */
+ public static function singleton() {
+ static $instance = null;
+ if ( $instance === null ) {
+ $instance = new self();
+ }
+ return $instance;
+ }
+
+ protected function __construct() {}
+
+ /**
+ * Get a property of a user based on their user ID
+ *
+ * @param $userId integer User ID
+ * @param $prop string User property
+ * @return mixed The property or false if the user does not exist
+ */
+ public function getProp( $userId, $prop ) {
+ if ( !isset( $this->cache[$userId][$prop] ) ) {
+ wfDebug( __METHOD__ . ": querying DB for prop '$prop' for user ID '$userId'.\n" );
+ $this->doQuery( array( $userId ) ); // cache miss
+ }
+ return isset( $this->cache[$userId][$prop] )
+ ? $this->cache[$userId][$prop]
+ : false; // user does not exist?
+ }
+
+ /**
+ * Preloads user names for given list of users.
+ * @param $userIds Array List of user IDs
+ * @param $options Array Option flags; include 'userpage' and 'usertalk'
+ * @param $caller String: the calling method
+ */
+ public function doQuery( array $userIds, $options = array(), $caller = '' ) {
+ wfProfileIn( __METHOD__ );
+
+ $usersToCheck = array();
+ $usersToQuery = array();
+
+ foreach ( $userIds as $userId ) {
+ $userId = (int)$userId;
+ if ( $userId <= 0 ) {
+ continue; // skip anons
+ }
+ if ( isset( $this->cache[$userId]['name'] ) ) {
+ $usersToCheck[$userId] = $this->cache[$userId]['name']; // already have name
+ } else {
+ $usersToQuery[] = $userId; // we need to get the name
+ }
+ }
+
+ // Lookup basic info for users not yet loaded...
+ if ( count( $usersToQuery ) ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ $table = array( 'user' );
+ $conds = array( 'user_id' => $usersToQuery );
+ $fields = array( 'user_name', 'user_real_name', 'user_registration', 'user_id' );
+
+ $comment = __METHOD__;
+ if ( strval( $caller ) !== '' ) {
+ $comment .= "/$caller";
+ }
+
+ $res = $dbr->select( $table, $fields, $conds, $comment );
+ foreach ( $res as $row ) { // load each user into cache
+ $userId = (int)$row->user_id;
+ $this->cache[$userId]['name'] = $row->user_name;
+ $this->cache[$userId]['real_name'] = $row->user_real_name;
+ $this->cache[$userId]['registration'] = $row->user_registration;
+ $usersToCheck[$userId] = $row->user_name;
+ }
+ }
+
+ $lb = new LinkBatch();
+ foreach ( $usersToCheck as $userId => $name ) {
+ if ( $this->queryNeeded( $userId, 'userpage', $options ) ) {
+ $lb->add( NS_USER, str_replace( ' ', '_', $row->user_name ) );
+ $this->typesCached[$userId]['userpage'] = 1;
+ }
+ if ( $this->queryNeeded( $userId, 'usertalk', $options ) ) {
+ $lb->add( NS_USER_TALK, str_replace( ' ', '_', $row->user_name ) );
+ $this->typesCached[$userId]['usertalk'] = 1;
+ }
+ }
+ $lb->execute();
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Check if a cache type is in $options and was not loaded for this user
+ *
+ * @param $uid integer user ID
+ * @param $type string Cache type
+ * @param $options Array Requested cache types
+ * @return bool
+ */
+ protected function queryNeeded( $uid, $type, array $options ) {
+ return ( in_array( $type, $options ) && !isset( $this->typesCached[$uid][$type] ) );
+ }
+}