79 public const CONSTRUCTOR_OPTIONS = [
80 MainConfigNames::SQLiteDataDir,
81 MainConfigNames::UpdateRowsPerQuery,
82 MainConfigNames::MemCachedServers,
83 MainConfigNames::MemCachedPersistent,
84 MainConfigNames::MemCachedTimeout,
85 MainConfigNames::CachePrefix,
86 MainConfigNames::ObjectCaches,
87 MainConfigNames::MainCacheType,
88 MainConfigNames::MessageCacheType,
89 MainConfigNames::ParserCacheType,
96 private $instances = [];
97 private string $domainId;
99 private $dbLoadBalancerFactory;
110 callable $dbLoadBalancerFactory,
114 $this->options = $options;
115 $this->stats = $stats;
116 $this->logger = $loggerSpi;
117 $this->dbLoadBalancerFactory = $dbLoadBalancerFactory;
118 $this->domainId = $domainId;
130 private function getDefaultKeyspace(): string {
132 if ( is_string( $cachePrefix ) && $cachePrefix !==
'' ) {
136 return $this->domainId;
145 private function newFromId( $id ):
BagOStuff {
147 $id = $this->getAnythingId();
150 if ( !isset( $this->options->get( MainConfigNames::ObjectCaches )[$id] ) ) {
157 return self::makeLocalServerCache( $this->getDefaultKeyspace() );
158 } elseif ( $id ===
'wincache' ) {
159 wfDeprecated( __METHOD__ .
' with cache ID "wincache"',
'1.43' );
160 return self::makeLocalServerCache( $this->getDefaultKeyspace() );
163 throw new InvalidArgumentException(
"Invalid object cache type \"$id\" requested. " .
164 "It is not present in \$wgObjectCaches." );
167 return $this->newFromParams( $this->options->get( MainConfigNames::ObjectCaches )[$id] );
177 if ( !isset( $this->instances[$id] ) ) {
178 $this->instances[$id] = $this->newFromId( $id );
181 return $this->instances[$id];
200 $logger = $this->logger->getLogger(
$params[
'loggroup'] ??
'objectcache' );
204 'keyspace' => $this->getDefaultKeyspace(),
205 'asyncHandler' => [ DeferredUpdates::class,
'addCallableUpdate' ],
206 'reportDupes' =>
true,
207 'stats' => $this->stats,
210 if ( isset(
$params[
'factory'] ) ) {
213 return call_user_func(
$params[
'factory'], ...$args );
216 if ( !isset(
$params[
'class'] ) ) {
217 throw new InvalidArgumentException(
218 'No "factory" nor "class" provided; got "' . print_r(
$params,
true ) .
'"'
225 if ( is_a( $class, SqlBagOStuff::class,
true ) ) {
226 $this->prepareSqlBagOStuffFromParams(
$params );
230 if ( is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
231 $this->prepareMemcachedBagOStuffFromParams(
$params );
235 if ( is_a( $class, MultiWriteBagOStuff::class,
true ) ) {
236 $this->prepareMultiWriteBagOStuffFromParams(
$params );
238 if ( is_a( $class, RESTBagOStuff::class,
true ) ) {
239 $this->prepareRESTBagOStuffFromParams(
$params );
245 private function prepareSqlBagOStuffFromParams( array &
$params ): void {
247 throw new InvalidArgumentException(
248 'globalKeyLB in $wgObjectCaches is no longer supported' );
250 if ( isset(
$params[
'server'] ) && !isset(
$params[
'servers'] ) ) {
254 if ( isset(
$params[
'servers'] ) ) {
256 foreach (
$params[
'servers'] as &$server ) {
257 if ( $server[
'type'] ===
'sqlite' && !isset( $server[
'dbDirectory'] ) ) {
258 $server[
'dbDirectory'] = $this->options->get( MainConfigNames::SQLiteDataDir );
261 } elseif ( isset(
$params[
'cluster'] ) ) {
263 $dbLbFactory = $this->dbLoadBalancerFactory;
264 $params[
'loadBalancerCallback'] =
static function () use ( $cluster, $dbLbFactory ) {
265 return $dbLbFactory()->getExternalLB( $cluster );
267 $params += [
'dbDomain' => false ];
269 $dbLbFactory = $this->dbLoadBalancerFactory;
270 $params[
'loadBalancerCallback'] =
static function () use ( $dbLbFactory ) {
271 return $dbLbFactory()->getMainLb();
273 $params += [
'dbDomain' => false ];
275 $params += [
'writeBatchSize' => $this->options->get( MainConfigNames::UpdateRowsPerQuery ) ];
278 private function prepareMemcachedBagOStuffFromParams( array &
$params ): void {
281 'persistent' => $this->options->get(
MainConfigNames::MemCachedPersistent ),
286 private function prepareMultiWriteBagOStuffFromParams( array &
$params ): void {
289 '@phan-var array{caches:array[]} $params';
290 foreach (
$params[
'caches'] ?? [] as $i => $cacheInfo ) {
293 $params[
'caches'][$i] = $this->newFromParams( $cacheInfo );
297 private function prepareRESTBagOStuffFromParams( array &
$params ): void {
323 $cache = $this->getInstance(
$fallback );
333 $this->instances = [];
340 private static function getLocalServerCacheClass() {
341 if ( self::$localServerCacheClass !==
null ) {
342 return self::$localServerCacheClass;
344 if ( function_exists(
'apcu_fetch' ) ) {
346 if ( PHP_SAPI !==
'cli' || ini_get(
'apc.enable_cli' ) ) {
347 return APCUBagOStuff::class;
352 return EmptyBagOStuff::class;
363 $this->options->get( MainConfigNames::MainCacheType ),
364 $this->options->get( MainConfigNames::MessageCacheType ),
365 $this->options->get( MainConfigNames::ParserCacheType )
367 foreach ( $candidates as $candidate ) {
371 $class = self::getLocalServerCacheClass();
372 if ( $class !== EmptyBagOStuff::class ) {
380 $services = MediaWikiServices::getInstance();
382 if ( $services->isServiceDisabled(
'DBLoadBalancer' ) ) {
385 } elseif ( $services->isStorageDisabled() ) {
416 'reportDupes' =>
false,
418 'keyspace' => $keyspace,
420 $class = self::getLocalServerCacheClass();
437 $id = $this->getAnythingId();
438 return $this->isDatabaseId( $id );
441 if ( !isset( $this->options->get( MainConfigNames::ObjectCaches )[$id] ) ) {
444 $cache = $this->options->get( MainConfigNames::ObjectCaches )[$id];
445 if ( ( $cache[
'class'] ??
'' ) === SqlBagOStuff::class ) {
459 return $this->getInstance(
460 $this->options->get( MainConfigNames::MainCacheType )
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.