MediaWiki  master
FileCacheBase.php
Go to the documentation of this file.
1 <?php
24 use Wikimedia\IPUtils;
25 
31 abstract class FileCacheBase {
32  protected $mKey;
33  protected $mType = 'object';
34  protected $mExt = 'cache';
35  protected $mFilePath;
36  protected $mUseGzip;
37  /* lazy loaded */
38  protected $mCached;
39 
40  /* @todo configurable? */
41  private const MISS_FACTOR = 15; // log 1 every MISS_FACTOR cache misses
42  private const MISS_TTL_SEC = 3600; // how many seconds ago is "recent"
43 
44  protected function __construct() {
45  global $wgUseGzip;
46 
47  $this->mUseGzip = (bool)$wgUseGzip;
48  }
49 
54  final protected function baseCacheDirectory() {
55  global $wgFileCacheDirectory;
56 
57  return $wgFileCacheDirectory;
58  }
59 
64  abstract protected function cacheDirectory();
65 
70  protected function cachePath() {
71  if ( $this->mFilePath !== null ) {
72  return $this->mFilePath;
73  }
74 
75  $dir = $this->cacheDirectory();
76  # Build directories (methods include the trailing "/")
77  $subDirs = $this->typeSubdirectory() . $this->hashSubdirectory();
78  # Avoid extension confusion
79  $key = str_replace( '.', '%2E', urlencode( $this->mKey ) );
80  # Build the full file path
81  $this->mFilePath = "{$dir}/{$subDirs}{$key}.{$this->mExt}";
82  if ( $this->useGzip() ) {
83  $this->mFilePath .= '.gz';
84  }
85 
86  return $this->mFilePath;
87  }
88 
93  public function isCached() {
94  if ( $this->mCached === null ) {
95  $this->mCached = file_exists( $this->cachePath() );
96  }
97 
98  return $this->mCached;
99  }
100 
105  public function cacheTimestamp() {
106  $timestamp = filemtime( $this->cachePath() );
107 
108  return ( $timestamp !== false )
109  ? wfTimestamp( TS_MW, $timestamp )
110  : false;
111  }
112 
119  public function isCacheGood( $timestamp = '' ) {
120  global $wgCacheEpoch;
121 
122  if ( !$this->isCached() ) {
123  return false;
124  }
125 
126  $cachetime = $this->cacheTimestamp();
127  $good = ( $timestamp <= $cachetime && $wgCacheEpoch <= $cachetime );
128  wfDebug( __METHOD__ .
129  ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good" );
130 
131  return $good;
132  }
133 
138  protected function useGzip() {
139  return $this->mUseGzip;
140  }
141 
146  public function fetchText() {
147  if ( $this->useGzip() ) {
148  $fh = gzopen( $this->cachePath(), 'rb' );
149 
150  return stream_get_contents( $fh );
151  } else {
152  return file_get_contents( $this->cachePath() );
153  }
154  }
155 
161  public function saveText( $text ) {
162  if ( $this->useGzip() ) {
163  $text = gzencode( $text );
164  }
165 
166  $this->checkCacheDirs(); // build parent dir
167  if ( !file_put_contents( $this->cachePath(), $text, LOCK_EX ) ) {
168  wfDebug( __METHOD__ . "() failed saving " . $this->cachePath() );
169  $this->mCached = null;
170 
171  return false;
172  }
173 
174  $this->mCached = true;
175 
176  return $text;
177  }
178 
183  public function clearCache() {
184  Wikimedia\suppressWarnings();
185  unlink( $this->cachePath() );
186  Wikimedia\restoreWarnings();
187  $this->mCached = false;
188  }
189 
194  protected function checkCacheDirs() {
195  wfMkdirParents( dirname( $this->cachePath() ), null, __METHOD__ );
196  }
197 
205  protected function typeSubdirectory() {
206  return $this->mType . '/';
207  }
208 
214  protected function hashSubdirectory() {
215  global $wgFileCacheDepth;
216 
217  $subdir = '';
218  if ( $wgFileCacheDepth > 0 ) {
219  $hash = md5( $this->mKey );
220  for ( $i = 1; $i <= $wgFileCacheDepth; $i++ ) {
221  $subdir .= substr( $hash, 0, $i ) . '/';
222  }
223  }
224 
225  return $subdir;
226  }
227 
233  public function incrMissesRecent( WebRequest $request ) {
234  if ( mt_rand( 0, self::MISS_FACTOR - 1 ) == 0 ) {
235  # Get a large IP range that should include the user even if that
236  # person's IP address changes
237  $ip = $request->getIP();
238  if ( !IPUtils::isValid( $ip ) ) {
239  return;
240  }
241 
242  $ip = IPUtils::isIPv6( $ip )
243  ? IPUtils::sanitizeRange( "$ip/32" )
244  : IPUtils::sanitizeRange( "$ip/16" );
245 
246  # Bail out if a request already came from this range...
248  $key = $cache->makeKey( static::class, 'attempt', $this->mType, $this->mKey, $ip );
249  if ( !$cache->add( $key, 1, self::MISS_TTL_SEC ) ) {
250  return; // possibly the same user
251  }
252 
253  # Increment the number of cache misses...
254  $cache->incrWithInit( $this->cacheMissKey( $cache ), self::MISS_TTL_SEC );
255  }
256  }
257 
262  public function getMissesRecent() {
264 
265  return self::MISS_FACTOR * $cache->get( $this->cacheMissKey( $cache ) );
266  }
267 
272  protected function cacheMissKey( BagOStuff $cache ) {
273  return $cache->makeKey( static::class, 'misses', $this->mType, $this->mKey );
274  }
275 }
FileCacheBase\__construct
__construct()
Definition: FileCacheBase.php:44
FileCacheBase\cacheMissKey
cacheMissKey(BagOStuff $cache)
Definition: FileCacheBase.php:272
FileCacheBase\MISS_FACTOR
const MISS_FACTOR
Definition: FileCacheBase.php:41
ObjectCache\getLocalClusterInstance
static getLocalClusterInstance()
Get the main cluster-local cache object.
Definition: ObjectCache.php:272
FileCacheBase\saveText
saveText( $text)
Save and compress text to the cache.
Definition: FileCacheBase.php:161
FileCacheBase\isCacheGood
isCacheGood( $timestamp='')
Check if up to date cache file exists.
Definition: FileCacheBase.php:119
wfMkdirParents
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
Definition: GlobalFunctions.php:1890
FileCacheBase\$mCached
$mCached
Definition: FileCacheBase.php:38
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1808
FileCacheBase\$mUseGzip
$mUseGzip
Definition: FileCacheBase.php:36
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:71
FileCacheBase\hashSubdirectory
hashSubdirectory()
Return relative multi-level hash subdirectory (with trailing slash) or the empty string if not $wgFil...
Definition: FileCacheBase.php:214
FileCacheBase\$mKey
$mKey
Definition: FileCacheBase.php:32
FileCacheBase\$mExt
$mExt
Definition: FileCacheBase.php:34
FileCacheBase\useGzip
useGzip()
Check if the cache is gzipped.
Definition: FileCacheBase.php:138
FileCacheBase\baseCacheDirectory
baseCacheDirectory()
Get the base file cache directory.
Definition: FileCacheBase.php:54
$wgUseGzip
$wgUseGzip
When using the file cache, we can store the cached HTML gzipped to save disk space.
Definition: DefaultSettings.php:2835
FileCacheBase\fetchText
fetchText()
Get the uncompressed text from the cache.
Definition: FileCacheBase.php:146
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:909
FileCacheBase\typeSubdirectory
typeSubdirectory()
Get the cache type subdirectory (with trailing slash) An extending class could use that method to alt...
Definition: FileCacheBase.php:205
FileCacheBase\MISS_TTL_SEC
const MISS_TTL_SEC
Definition: FileCacheBase.php:42
$wgFileCacheDepth
$wgFileCacheDepth
Depth of the subdirectory hierarchy to be created under $wgFileCacheDirectory.
Definition: DefaultSettings.php:2798
FileCacheBase\isCached
isCached()
Check if the cache file exists.
Definition: FileCacheBase.php:93
FileCacheBase\cacheDirectory
cacheDirectory()
Get the base cache directory (not specific to this file)
FileCacheBase\clearCache
clearCache()
Clear the cache for this page.
Definition: FileCacheBase.php:183
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:42
WebRequest\getIP
getIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Definition: WebRequest.php:1287
FileCacheBase\$mFilePath
$mFilePath
Definition: FileCacheBase.php:35
$wgCacheEpoch
$wgCacheEpoch
Set this to current time to invalidate all prior cached pages.
Definition: DefaultSettings.php:2777
FileCacheBase\getMissesRecent
getMissesRecent()
Roughly gets the cache misses in the last hour by unique visitors.
Definition: FileCacheBase.php:262
FileCacheBase\$mType
$mType
Definition: FileCacheBase.php:33
$cache
$cache
Definition: mcc.php:33
FileCacheBase\cachePath
cachePath()
Get the path to the cache file.
Definition: FileCacheBase.php:70
$wgFileCacheDirectory
$wgFileCacheDirectory
Directory where the cached page will be saved.
Definition: DefaultSettings.php:298
FileCacheBase\incrMissesRecent
incrMissesRecent(WebRequest $request)
Roughly increments the cache misses in the last hour by unique visitors.
Definition: FileCacheBase.php:233
FileCacheBase\cacheTimestamp
cacheTimestamp()
Get the last-modified timestamp of the cache file.
Definition: FileCacheBase.php:105
FileCacheBase\checkCacheDirs
checkCacheDirs()
Create parent directors of $this->cachePath()
Definition: FileCacheBase.php:194
FileCacheBase
Base class for data storage in the file system.
Definition: FileCacheBase.php:31