MediaWiki  1.34.0
FileCacheBase.php
Go to the documentation of this file.
1 <?php
29 abstract class FileCacheBase {
30  protected $mKey;
31  protected $mType = 'object';
32  protected $mExt = 'cache';
33  protected $mFilePath;
34  protected $mUseGzip;
35  /* lazy loaded */
36  protected $mCached;
37 
38  /* @todo configurable? */
39  const MISS_FACTOR = 15; // log 1 every MISS_FACTOR cache misses
40  const MISS_TTL_SEC = 3600; // how many seconds ago is "recent"
41 
42  protected function __construct() {
43  global $wgUseGzip;
44 
45  $this->mUseGzip = (bool)$wgUseGzip;
46  }
47 
52  final protected function baseCacheDirectory() {
53  global $wgFileCacheDirectory;
54 
55  return $wgFileCacheDirectory;
56  }
57 
62  abstract protected function cacheDirectory();
63 
68  protected function cachePath() {
69  if ( $this->mFilePath !== null ) {
70  return $this->mFilePath;
71  }
72 
73  $dir = $this->cacheDirectory();
74  # Build directories (methods include the trailing "/")
75  $subDirs = $this->typeSubdirectory() . $this->hashSubdirectory();
76  # Avoid extension confusion
77  $key = str_replace( '.', '%2E', urlencode( $this->mKey ) );
78  # Build the full file path
79  $this->mFilePath = "{$dir}/{$subDirs}{$key}.{$this->mExt}";
80  if ( $this->useGzip() ) {
81  $this->mFilePath .= '.gz';
82  }
83 
84  return $this->mFilePath;
85  }
86 
91  public function isCached() {
92  if ( $this->mCached === null ) {
93  $this->mCached = file_exists( $this->cachePath() );
94  }
95 
96  return $this->mCached;
97  }
98 
103  public function cacheTimestamp() {
104  $timestamp = filemtime( $this->cachePath() );
105 
106  return ( $timestamp !== false )
107  ? wfTimestamp( TS_MW, $timestamp )
108  : false;
109  }
110 
117  public function isCacheGood( $timestamp = '' ) {
118  global $wgCacheEpoch;
119 
120  if ( !$this->isCached() ) {
121  return false;
122  }
123 
124  $cachetime = $this->cacheTimestamp();
125  $good = ( $timestamp <= $cachetime && $wgCacheEpoch <= $cachetime );
126  wfDebug( __METHOD__ .
127  ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good\n" );
128 
129  return $good;
130  }
131 
136  protected function useGzip() {
137  return $this->mUseGzip;
138  }
139 
144  public function fetchText() {
145  if ( $this->useGzip() ) {
146  $fh = gzopen( $this->cachePath(), 'rb' );
147 
148  return stream_get_contents( $fh );
149  } else {
150  return file_get_contents( $this->cachePath() );
151  }
152  }
153 
159  public function saveText( $text ) {
160  if ( $this->useGzip() ) {
161  $text = gzencode( $text );
162  }
163 
164  $this->checkCacheDirs(); // build parent dir
165  if ( !file_put_contents( $this->cachePath(), $text, LOCK_EX ) ) {
166  wfDebug( __METHOD__ . "() failed saving " . $this->cachePath() . "\n" );
167  $this->mCached = null;
168 
169  return false;
170  }
171 
172  $this->mCached = true;
173 
174  return $text;
175  }
176 
181  public function clearCache() {
182  Wikimedia\suppressWarnings();
183  unlink( $this->cachePath() );
184  Wikimedia\restoreWarnings();
185  $this->mCached = false;
186  }
187 
192  protected function checkCacheDirs() {
193  wfMkdirParents( dirname( $this->cachePath() ), null, __METHOD__ );
194  }
195 
203  protected function typeSubdirectory() {
204  return $this->mType . '/';
205  }
206 
212  protected function hashSubdirectory() {
213  global $wgFileCacheDepth;
214 
215  $subdir = '';
216  if ( $wgFileCacheDepth > 0 ) {
217  $hash = md5( $this->mKey );
218  for ( $i = 1; $i <= $wgFileCacheDepth; $i++ ) {
219  $subdir .= substr( $hash, 0, $i ) . '/';
220  }
221  }
222 
223  return $subdir;
224  }
225 
231  public function incrMissesRecent( WebRequest $request ) {
232  if ( mt_rand( 0, self::MISS_FACTOR - 1 ) == 0 ) {
233  # Get a large IP range that should include the user even if that
234  # person's IP address changes
235  $ip = $request->getIP();
236  if ( !IP::isValid( $ip ) ) {
237  return;
238  }
239 
240  $ip = IP::isIPv6( $ip )
241  ? IP::sanitizeRange( "$ip/32" )
242  : IP::sanitizeRange( "$ip/16" );
243 
244  # Bail out if a request already came from this range...
246  $key = $cache->makeKey( static::class, 'attempt', $this->mType, $this->mKey, $ip );
247  if ( !$cache->add( $key, 1, self::MISS_TTL_SEC ) ) {
248  return; // possibly the same user
249  }
250 
251  # Increment the number of cache misses...
252  $cache->incrWithInit( $this->cacheMissKey( $cache ), self::MISS_TTL_SEC );
253  }
254  }
255 
260  public function getMissesRecent() {
262 
263  return self::MISS_FACTOR * $cache->get( $this->cacheMissKey( $cache ) );
264  }
265 
270  protected function cacheMissKey( BagOStuff $cache ) {
271  return $cache->makeKey( static::class, 'misses', $this->mType, $this->mKey );
272  }
273 }
FileCacheBase\__construct
__construct()
Definition: FileCacheBase.php:42
FileCacheBase\cacheMissKey
cacheMissKey(BagOStuff $cache)
Definition: FileCacheBase.php:270
FileCacheBase\MISS_FACTOR
const MISS_FACTOR
Definition: FileCacheBase.php:39
ObjectCache\getLocalClusterInstance
static getLocalClusterInstance()
Get the main cluster-local cache object.
Definition: ObjectCache.php:342
FileCacheBase\saveText
saveText( $text)
Save and compress text to the cache.
Definition: FileCacheBase.php:159
FileCacheBase\isCacheGood
isCacheGood( $timestamp='')
Check if up to date cache file exists.
Definition: FileCacheBase.php:117
wfMkdirParents
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
Definition: GlobalFunctions.php:1966
FileCacheBase\$mCached
$mCached
Definition: FileCacheBase.php:36
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1869
FileCacheBase\$mUseGzip
$mUseGzip
Definition: FileCacheBase.php:34
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:63
IP\isIPv6
static isIPv6( $ip)
Given a string, determine if it as valid IP in IPv6 only.
Definition: IP.php:88
$fh
$fh
Definition: make-tables.php:46
FileCacheBase\hashSubdirectory
hashSubdirectory()
Return relative multi-level hash subdirectory (with trailing slash) or the empty string if not $wgFil...
Definition: FileCacheBase.php:212
FileCacheBase\$mKey
$mKey
Definition: FileCacheBase.php:30
FileCacheBase\$mExt
$mExt
Definition: FileCacheBase.php:32
FileCacheBase\useGzip
useGzip()
Check if the cache is gzipped.
Definition: FileCacheBase.php:136
FileCacheBase\baseCacheDirectory
baseCacheDirectory()
Get the base file cache directory.
Definition: FileCacheBase.php:52
$wgUseGzip
$wgUseGzip
When using the file cache, we can store the cached HTML gzipped to save disk space.
Definition: DefaultSettings.php:2698
FileCacheBase\fetchText
fetchText()
Get the uncompressed text from the cache.
Definition: FileCacheBase.php:144
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:913
FileCacheBase\typeSubdirectory
typeSubdirectory()
Get the cache type subdirectory (with trailing slash) An extending class could use that method to alt...
Definition: FileCacheBase.php:203
FileCacheBase\MISS_TTL_SEC
const MISS_TTL_SEC
Definition: FileCacheBase.php:40
$wgFileCacheDepth
$wgFileCacheDepth
Depth of the subdirectory hierarchy to be created under $wgFileCacheDirectory.
Definition: DefaultSettings.php:2668
FileCacheBase\isCached
isCached()
Check if the cache file exists.
Definition: FileCacheBase.php:91
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:181
IP\isValid
static isValid( $ip)
Validate an IP address.
Definition: IP.php:111
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:1274
FileCacheBase\$mFilePath
$mFilePath
Definition: FileCacheBase.php:33
$wgCacheEpoch
$wgCacheEpoch
Set this to current time to invalidate all prior cached pages.
Definition: DefaultSettings.php:2647
FileCacheBase\getMissesRecent
getMissesRecent()
Roughly gets the cache misses in the last hour by unique visitors.
Definition: FileCacheBase.php:260
FileCacheBase\$mType
$mType
Definition: FileCacheBase.php:31
$cache
$cache
Definition: mcc.php:33
FileCacheBase\cachePath
cachePath()
Get the path to the cache file.
Definition: FileCacheBase.php:68
$wgFileCacheDirectory
$wgFileCacheDirectory
Directory where the cached page will be saved.
Definition: DefaultSettings.php:262
FileCacheBase\incrMissesRecent
incrMissesRecent(WebRequest $request)
Roughly increments the cache misses in the last hour by unique visitors.
Definition: FileCacheBase.php:231
IP\sanitizeRange
static sanitizeRange( $range)
Gets rid of unneeded numbers in quad-dotted/octet IP strings For example, 127.111....
Definition: IP.php:712
FileCacheBase\cacheTimestamp
cacheTimestamp()
Get the last-modified timestamp of the cache file.
Definition: FileCacheBase.php:103
FileCacheBase\checkCacheDirs
checkCacheDirs()
Create parent directors of $this->cachePath()
Definition: FileCacheBase.php:192
FileCacheBase
Base class for data storage in the file system.
Definition: FileCacheBase.php:29