MediaWiki  master
ObjectCache.php
Go to the documentation of this file.
1 <?php
27 
65 class ObjectCache {
67  public static $instances = [];
68 
75  public static function getInstance( $id ) {
76  if ( !isset( self::$instances[$id] ) ) {
77  self::$instances[$id] = self::newFromId( $id );
78  }
79 
80  return self::$instances[$id];
81  }
82 
90  private static function newFromId( $id ) {
91  global $wgObjectCaches;
92 
93  if ( !isset( $wgObjectCaches[$id] ) ) {
94  // Always recognize these ones
95  if ( $id === CACHE_NONE ) {
96  return new EmptyBagOStuff();
97  } elseif ( $id === CACHE_HASH ) {
98  return new HashBagOStuff();
99  }
100 
101  throw new InvalidArgumentException( "Invalid object cache type \"$id\" requested. " .
102  "It is not present in \$wgObjectCaches." );
103  }
104 
105  return self::newFromParams( $wgObjectCaches[$id] );
106  }
107 
117  private static function getDefaultKeyspace() {
118  global $wgCachePrefix;
119 
120  $keyspace = $wgCachePrefix;
121  if ( is_string( $keyspace ) && $keyspace !== '' ) {
122  return $keyspace;
123  }
124 
125  return WikiMap::getCurrentWikiDbDomain()->getId();
126  }
127 
139  public static function newFromParams( array $params, Config $conf = null ) {
140  $services = MediaWikiServices::getInstance();
141  // Apply default parameters and resolve the logger instance
142  $params += [
143  'logger' => LoggerFactory::getInstance( $params['loggroup'] ?? 'objectcache' ),
144  'keyspace' => self::getDefaultKeyspace(),
145  'asyncHandler' => [ DeferredUpdates::class, 'addCallableUpdate' ],
146  'reportDupes' => true,
147  'stats' => $services->getStatsdDataFactory(),
148  ];
149 
150  if ( isset( $params['factory'] ) ) {
151  $args = $params['args'] ?? [ $params ];
152 
153  return call_user_func( $params['factory'], ...$args );
154  }
155 
156  if ( !isset( $params['class'] ) ) {
157  throw new InvalidArgumentException(
158  'No "factory" nor "class" provided; got "' . print_r( $params, true ) . '"'
159  );
160  }
161 
162  $class = $params['class'];
163  $conf ??= $services->getMainConfig();
164 
165  // Normalization and DI for SqlBagOStuff
166  if ( is_a( $class, SqlBagOStuff::class, true ) ) {
167  if ( isset( $params['globalKeyLB'] ) ) {
168  throw new InvalidArgumentException(
169  'globalKeyLB in $wgObjectCaches is no longer supported' );
170  }
171  if ( isset( $params['server'] ) && !isset( $params['servers'] ) ) {
172  $params['servers'] = [ $params['server'] ];
173  unset( $params['server'] );
174  }
175  if ( isset( $params['servers'] ) ) {
176  // In the past it was not required to set 'dbDirectory' in $wgObjectCaches
177  foreach ( $params['servers'] as &$server ) {
178  if ( $server['type'] === 'sqlite' && !isset( $server['dbDirectory'] ) ) {
179  $server['dbDirectory'] = $conf->get( MainConfigNames::SQLiteDataDir );
180  }
181  }
182  } elseif ( isset( $params['cluster'] ) ) {
183  $cluster = $params['cluster'];
184  $params['loadBalancerCallback'] = static function () use ( $services, $cluster ) {
185  return $services->getDBLoadBalancerFactory()->getExternalLB( $cluster );
186  };
187  $params += [ 'dbDomain' => false ];
188  } else {
189  $params['loadBalancerCallback'] = static function () use ( $services ) {
190  return $services->getDBLoadBalancer();
191  };
192  $params += [ 'dbDomain' => false ];
193  }
194  $params += [ 'writeBatchSize' => $conf->get( MainConfigNames::UpdateRowsPerQuery ) ];
195  }
196 
197  // Normalization and DI for MemcachedBagOStuff
198  if ( is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
199  $params += [
200  'servers' => $conf->get( MainConfigNames::MemCachedServers ),
201  'persistent' => $conf->get( MainConfigNames::MemCachedPersistent ),
202  'timeout' => $conf->get( MainConfigNames::MemCachedTimeout ),
203  ];
204  }
205 
206  // Normalization and DI for MultiWriteBagOStuff
207  if ( is_a( $class, MultiWriteBagOStuff::class, true ) ) {
208  // Phan warns about foreach with non-array because it
209  // thinks any key can be Closure|IBufferingStatsdDataFactory
210  '@phan-var array{caches:array[]} $params';
211  foreach ( $params['caches'] ?? [] as $i => $cacheInfo ) {
212  // Ensure logger, keyspace, asyncHandler, etc are injected just as if
213  // one of these was configured without MultiWriteBagOStuff.
214  $params['caches'][$i] = self::newFromParams( $cacheInfo, $conf );
215  }
216  }
217 
218  return new $class( $params );
219  }
220 
234  public static function newAnything( $params ) {
237  foreach ( $candidates as $candidate ) {
238  if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) {
239  $cache = self::getInstance( $candidate );
240  // CACHE_ACCEL might default to nothing if no APCu
241  // See includes/ServiceWiring.php
242  if ( !( $cache instanceof EmptyBagOStuff ) ) {
243  return $cache;
244  }
245  }
246  }
247 
248  if ( MediaWikiServices::getInstance()->isServiceDisabled( 'DBLoadBalancer' ) ) {
249  // The LoadBalancer is disabled, probably because
250  // MediaWikiServices::disableStorageBackend was called.
251  $candidate = CACHE_NONE;
252  } else {
253  $candidate = CACHE_DB;
254  }
255 
256  return self::getInstance( $candidate );
257  }
258 
276  public static function getLocalServerInstance( $fallback = CACHE_NONE ) {
277  $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
278  if ( $cache instanceof EmptyBagOStuff ) {
279  if ( is_array( $fallback ) ) {
280  $fallback = $fallback['fallback'] ?? CACHE_NONE;
281  }
282  $cache = self::getInstance( $fallback );
283  }
284 
285  return $cache;
286  }
287 
294  public static function getLocalClusterInstance() {
295  global $wgMainCacheType;
296 
298  }
299 
303  public static function clear() {
304  self::$instances = [];
305  }
306 
321  public static function makeLocalServerCache(): BagOStuff {
322  $params = [
323  'reportDupes' => false,
324  // Even simple caches must use a keyspace (T247562)
325  'keyspace' => self::getDefaultKeyspace(),
326  ];
327  if ( function_exists( 'apcu_fetch' ) ) {
328  // Make sure the APCu methods actually store anything
329  if ( PHP_SAPI !== 'cli' || ini_get( 'apc.enable_cli' ) ) {
330  return new APCUBagOStuff( $params );
331  }
332  } elseif ( function_exists( 'wincache_ucache_get' ) ) {
333  return new WinCacheBagOStuff( $params );
334  }
335 
336  return new EmptyBagOStuff( $params );
337  }
338 }
const CACHE_NONE
Definition: Defines.php:86
const CACHE_ANYTHING
Definition: Defines.php:85
const CACHE_HASH
Definition: Defines.php:90
const CACHE_DB
Definition: Defines.php:87
$fallback
Definition: MessagesAb.php:8
This is a wrapper for APCu's shared memory functions.
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:85
A BagOStuff object with no objects in it.
Simple store for keeping values in an associative array for the current process.
PSR-3 logger instance factory.
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
Functions to get cache objects.
Definition: ObjectCache.php:65
static getLocalServerInstance( $fallback=CACHE_NONE)
Factory function for CACHE_ACCEL (referenced from configuration)
static makeLocalServerCache()
Create a new BagOStuff instance for local-server caching.
static newAnything( $params)
Factory function for CACHE_ANYTHING (referenced by configuration)
static clear()
Clear all the cached instances.
static BagOStuff[] $instances
Map of (id => BagOStuff)
Definition: ObjectCache.php:67
static newFromParams(array $params, Config $conf=null)
Create a new cache object from parameters.
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:75
static getLocalClusterInstance()
Get the main cluster-local cache object.
static getCurrentWikiDbDomain()
Definition: WikiMap.php:290
Wrapper for WinCache object caching functions; identical interface to the APC wrapper.
$wgObjectCaches
Config variable stub for the ObjectCaches setting, for use by phpdoc and IDEs.
$wgParserCacheType
Config variable stub for the ParserCacheType setting, for use by phpdoc and IDEs.
$wgMainCacheType
Config variable stub for the MainCacheType setting, for use by phpdoc and IDEs.
$wgCachePrefix
Config variable stub for the CachePrefix setting, for use by phpdoc and IDEs.
$wgMessageCacheType
Config variable stub for the MessageCacheType setting, for use by phpdoc and IDEs.
Interface for configuration instances.
Definition: Config.php:30