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 === '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 
140  public static function newFromParams( array $params, Config $conf = null ) {
141  $services = MediaWikiServices::getInstance();
142  // Apply default parameters and resolve the logger instance
143  $params += [
144  'logger' => LoggerFactory::getInstance( $params['loggroup'] ?? 'objectcache' ),
145  'keyspace' => self::getDefaultKeyspace(),
146  'asyncHandler' => [ DeferredUpdates::class, 'addCallableUpdate' ],
147  'reportDupes' => true,
148  ];
149 
150  if ( !isset( $params['stats'] ) ) {
151  $params['stats'] = $services->getStatsdDataFactory();
152  }
153 
154  if ( isset( $params['factory'] ) ) {
155  $args = $params['args'] ?? [ $params ];
156 
157  return call_user_func( $params['factory'], ...$args );
158  }
159 
160  if ( !isset( $params['class'] ) ) {
161  throw new InvalidArgumentException(
162  'No "factory" nor "class" provided; got "' . print_r( $params, true ) . '"'
163  );
164  }
165 
166  $class = $params['class'];
167  $conf = $conf ?? $services->getMainConfig();
168 
169  // Do config normalization for SqlBagOStuff
170  if ( is_a( $class, SqlBagOStuff::class, true ) ) {
171  if ( isset( $params['globalKeyLB'] ) ) {
172  throw new InvalidArgumentException(
173  'globalKeyLB in $wgObjectCaches is no longer supported' );
174  }
175  if ( isset( $params['server'] ) && !isset( $params['servers'] ) ) {
176  $params['servers'] = [ $params['server'] ];
177  unset( $params['server'] );
178  }
179  if ( isset( $params['servers'] ) ) {
180  // In the past it was not required to set 'dbDirectory' in $wgObjectCaches
181  foreach ( $params['servers'] as &$server ) {
182  if ( $server['type'] === 'sqlite' && !isset( $server['dbDirectory'] ) ) {
183  $server['dbDirectory'] = $conf->get( MainConfigNames::SQLiteDataDir );
184  }
185  }
186  } elseif ( isset( $params['cluster'] ) ) {
187  $cluster = $params['cluster'];
188  $params['loadBalancerCallback'] = static function () use ( $services, $cluster ) {
189  return $services->getDBLoadBalancerFactory()->getExternalLB( $cluster );
190  };
191  $params += [ 'dbDomain' => false ];
192  } else {
193  $params['loadBalancerCallback'] = static function () use ( $services ) {
194  return $services->getDBLoadBalancer();
195  };
196  $params += [ 'dbDomain' => false ];
197  }
198  $params += [ 'writeBatchSize' => $conf->get( MainConfigNames::UpdateRowsPerQuery ) ];
199  }
200 
201  // Do config normalization for MemcachedBagOStuff
202  if ( is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
203  $params += [
204  'servers' => $conf->get( MainConfigNames::MemCachedServers ),
205  'persistent' => $conf->get( MainConfigNames::MemCachedPersistent ),
206  'timeout' => $conf->get( MainConfigNames::MemCachedTimeout ),
207  ];
208  }
209 
210  return new $class( $params );
211  }
212 
226  public static function newAnything( $params ) {
229  foreach ( $candidates as $candidate ) {
230  if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) {
231  $cache = self::getInstance( $candidate );
232  // CACHE_ACCEL might default to nothing if no APCu
233  // See includes/ServiceWiring.php
234  if ( !( $cache instanceof EmptyBagOStuff ) ) {
235  return $cache;
236  }
237  }
238  }
239 
240  if ( MediaWikiServices::getInstance()->isServiceDisabled( 'DBLoadBalancer' ) ) {
241  // The LoadBalancer is disabled, probably because
242  // MediaWikiServices::disableStorageBackend was called.
243  $candidate = CACHE_NONE;
244  } else {
245  $candidate = CACHE_DB;
246  }
247 
248  return self::getInstance( $candidate );
249  }
250 
268  public static function getLocalServerInstance( $fallback = CACHE_NONE ) {
269  $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
270  if ( $cache instanceof EmptyBagOStuff ) {
271  if ( is_array( $fallback ) ) {
272  $fallback = $fallback['fallback'] ?? CACHE_NONE;
273  }
275  }
276 
277  return $cache;
278  }
279 
286  public static function getLocalClusterInstance() {
287  global $wgMainCacheType;
288 
290  }
291 
295  public static function clear() {
296  self::$instances = [];
297  }
298 
313  public static function makeLocalServerCache(): BagOStuff {
314  $params = [
315  'reportDupes' => false,
316  // Even simple caches must use a keyspace (T247562)
317  'keyspace' => self::getDefaultKeyspace(),
318  ];
319  if ( function_exists( 'apcu_fetch' ) ) {
320  // Make sure the APCu methods actually store anything
321  if ( PHP_SAPI !== 'cli' || ini_get( 'apc.enable_cli' ) ) {
322  return new APCUBagOStuff( $params );
323  }
324  } elseif ( function_exists( 'wincache_ucache_get' ) ) {
325  return new WinCacheBagOStuff( $params );
326  }
327 
328  return new EmptyBagOStuff( $params );
329  }
330 }
const CACHE_NONE
Definition: Defines.php:86
const CACHE_ANYTHING
Definition: Defines.php:85
const CACHE_DB
Definition: Defines.php:87
$fallback
Definition: MessagesAb.php:11
This is a wrapper for APCu's shared memory functions.
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:87
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 newFromId( $id)
Create a new cache object of the specified type.
Definition: ObjectCache.php:90
static newAnything( $params)
Factory function for CACHE_ANYTHING (referenced by configuration)
static getDefaultKeyspace()
Get the default keyspace for this wiki.
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:293
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
$cache
Definition: mcc.php:33
if( $line===false) $args
Definition: mcc.php:124