MediaWiki REL1_28
LBFactory.php
Go to the documentation of this file.
1<?php
24use Psr\Log\LoggerInterface;
25use Wikimedia\ScopedCallback;
26
31abstract class LBFactory implements ILBFactory {
33 protected $chronProt;
35 protected $profiler;
37 protected $trxProfiler;
39 protected $replLogger;
41 protected $connLogger;
43 protected $queryLogger;
45 protected $perfLogger;
47 protected $errorLogger;
49 protected $srvCache;
51 protected $memCache;
53 protected $wanCache;
54
56 protected $localDomain;
58 protected $hostname;
60 protected $requestInfo;
61
63 protected $ticket;
65 protected $trxRoundId = false;
67 protected $readOnlyReason = false;
70
72 protected $cliMode;
74 protected $agent;
75
76 private static $loggerFields =
77 [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ];
78
79 public function __construct( array $conf ) {
80 $this->localDomain = isset( $conf['localDomain'] )
81 ? DatabaseDomain::newFromId( $conf['localDomain'] )
83
84 if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
85 $this->readOnlyReason = $conf['readOnlyReason'];
86 }
87
88 $this->srvCache = isset( $conf['srvCache'] ) ? $conf['srvCache'] : new EmptyBagOStuff();
89 $this->memCache = isset( $conf['memCache'] ) ? $conf['memCache'] : new EmptyBagOStuff();
90 $this->wanCache = isset( $conf['wanCache'] )
91 ? $conf['wanCache']
92 : WANObjectCache::newEmpty();
93
94 foreach ( self::$loggerFields as $key ) {
95 $this->$key = isset( $conf[$key] ) ? $conf[$key] : new \Psr\Log\NullLogger();
96 }
97 $this->errorLogger = isset( $conf['errorLogger'] )
98 ? $conf['errorLogger']
99 : function ( Exception $e ) {
100 trigger_error( E_USER_WARNING, get_class( $e ) . ': ' . $e->getMessage() );
101 };
102
103 $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null;
104 $this->trxProfiler = isset( $conf['trxProfiler'] )
105 ? $conf['trxProfiler']
106 : new TransactionProfiler();
107
108 $this->requestInfo = [
109 'IPAddress' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '',
110 'UserAgent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '',
111 'ChronologyProtection' => 'true'
112 ];
113
114 $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
115 $this->hostname = isset( $conf['hostname'] ) ? $conf['hostname'] : gethostname();
116 $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
117
118 $this->ticket = mt_rand();
119 }
120
121 public function destroy() {
122 $this->shutdown( self::SHUTDOWN_NO_CHRONPROT );
123 $this->forEachLBCallMethod( 'disable' );
124 }
125
126 public function shutdown(
127 $mode = self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback = null
128 ) {
130 if ( $mode === self::SHUTDOWN_CHRONPROT_SYNC ) {
131 $this->shutdownChronologyProtector( $chronProt, $workCallback, 'sync' );
132 } elseif ( $mode === self::SHUTDOWN_CHRONPROT_ASYNC ) {
133 $this->shutdownChronologyProtector( $chronProt, null, 'async' );
134 }
135
136 $this->commitMasterChanges( __METHOD__ ); // sanity
137 }
138
144 abstract public function newMainLB( $domain = false );
145
151 abstract public function getMainLB( $domain = false );
152
158 abstract public function newExternalLB( $cluster );
159
165 abstract public function getExternalLB( $cluster );
166
173 protected function forEachLBCallMethod( $methodName, array $args = [] ) {
174 $this->forEachLB(
175 function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
176 call_user_func_array( [ $loadBalancer, $methodName ], $args );
177 },
178 [ $methodName, $args ]
179 );
180 }
181
182 public function flushReplicaSnapshots( $fname = __METHOD__ ) {
183 $this->forEachLBCallMethod( 'flushReplicaSnapshots', [ $fname ] );
184 }
185
186 public function commitAll( $fname = __METHOD__, array $options = [] ) {
188 $this->forEachLBCallMethod( 'commitAll', [ $fname ] );
189 }
190
191 public function beginMasterChanges( $fname = __METHOD__ ) {
192 if ( $this->trxRoundId !== false ) {
193 throw new DBTransactionError(
194 null,
195 "$fname: transaction round '{$this->trxRoundId}' already started."
196 );
197 }
198 $this->trxRoundId = $fname;
199 // Set DBO_TRX flags on all appropriate DBs
200 $this->forEachLBCallMethod( 'beginMasterChanges', [ $fname ] );
201 }
202
203 public function commitMasterChanges( $fname = __METHOD__, array $options = [] ) {
204 if ( $this->trxRoundId !== false && $this->trxRoundId !== $fname ) {
205 throw new DBTransactionError(
206 null,
207 "$fname: transaction round '{$this->trxRoundId}' still running."
208 );
209 }
211 $scope = $this->getScopedPHPBehaviorForCommit(); // try to ignore client aborts
212 // Run pre-commit callbacks and suppress post-commit callbacks, aborting on failure
213 $this->forEachLBCallMethod( 'finalizeMasterChanges' );
214 $this->trxRoundId = false;
215 // Perform pre-commit checks, aborting on failure
216 $this->forEachLBCallMethod( 'approveMasterChanges', [ $options ] );
217 // Log the DBs and methods involved in multi-DB transactions
219 // Actually perform the commit on all master DB connections and revert DBO_TRX
220 $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
221 // Run all post-commit callbacks
223 $e = null; // first callback exception
224 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e ) {
225 $ex = $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_COMMIT );
226 $e = $e ?: $ex;
227 } );
228 // Commit any dangling DBO_TRX transactions from callbacks on one DB to another DB
229 $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
230 // Throw any last post-commit callback error
231 if ( $e instanceof Exception ) {
232 throw $e;
233 }
234 }
235
236 public function rollbackMasterChanges( $fname = __METHOD__ ) {
237 $this->trxRoundId = false;
238 $this->forEachLBCallMethod( 'suppressTransactionEndCallbacks' );
239 $this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] );
240 // Run all post-rollback callbacks
241 $this->forEachLB( function ( ILoadBalancer $lb ) {
242 $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_ROLLBACK );
243 } );
244 }
245
246 public function hasTransactionRound() {
247 return ( $this->trxRoundId !== false );
248 }
249
253 private function logIfMultiDbTransaction() {
254 $callersByDB = [];
255 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$callersByDB ) {
256 $masterName = $lb->getServerName( $lb->getWriterIndex() );
257 $callers = $lb->pendingMasterChangeCallers();
258 if ( $callers ) {
259 $callersByDB[$masterName] = $callers;
260 }
261 } );
262
263 if ( count( $callersByDB ) >= 2 ) {
264 $dbs = implode( ', ', array_keys( $callersByDB ) );
265 $msg = "Multi-DB transaction [{$dbs}]:\n";
266 foreach ( $callersByDB as $db => $callers ) {
267 $msg .= "$db: " . implode( '; ', $callers ) . "\n";
268 }
269 $this->queryLogger->info( $msg );
270 }
271 }
272
273 public function hasMasterChanges() {
274 $ret = false;
275 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
276 $ret = $ret || $lb->hasMasterChanges();
277 } );
278
279 return $ret;
280 }
281
282 public function laggedReplicaUsed() {
283 $ret = false;
284 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
285 $ret = $ret || $lb->laggedReplicaUsed();
286 } );
287
288 return $ret;
289 }
290
291 public function hasOrMadeRecentMasterChanges( $age = null ) {
292 $ret = false;
293 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $age, &$ret ) {
294 $ret = $ret || $lb->hasOrMadeRecentMasterChanges( $age );
295 } );
296 return $ret;
297 }
298
299 public function waitForReplication( array $opts = [] ) {
300 $opts += [
301 'domain' => false,
302 'cluster' => false,
303 'timeout' => 60,
304 'ifWritesSince' => null
305 ];
306
307 if ( $opts['domain'] === false && isset( $opts['wiki'] ) ) {
308 $opts['domain'] = $opts['wiki']; // b/c
309 }
310
311 // Figure out which clusters need to be checked
313 $lbs = [];
314 if ( $opts['cluster'] !== false ) {
315 $lbs[] = $this->getExternalLB( $opts['cluster'] );
316 } elseif ( $opts['domain'] !== false ) {
317 $lbs[] = $this->getMainLB( $opts['domain'] );
318 } else {
319 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$lbs ) {
320 $lbs[] = $lb;
321 } );
322 if ( !$lbs ) {
323 return; // nothing actually used
324 }
325 }
326
327 // Get all the master positions of applicable DBs right now.
328 // This can be faster since waiting on one cluster reduces the
329 // time needed to wait on the next clusters.
330 $masterPositions = array_fill( 0, count( $lbs ), false );
331 foreach ( $lbs as $i => $lb ) {
332 if ( $lb->getServerCount() <= 1 ) {
333 // Bug 27975 - Don't try to wait for replica DBs if there are none
334 // Prevents permission error when getting master position
335 continue;
336 } elseif ( $opts['ifWritesSince']
337 && $lb->lastMasterChangeTimestamp() < $opts['ifWritesSince']
338 ) {
339 continue; // no writes since the last wait
340 }
341 $masterPositions[$i] = $lb->getMasterPos();
342 }
343
344 // Run any listener callbacks *after* getting the DB positions. The more
345 // time spent in the callbacks, the less time is spent in waitForAll().
346 foreach ( $this->replicationWaitCallbacks as $callback ) {
347 $callback();
348 }
349
350 $failed = [];
351 foreach ( $lbs as $i => $lb ) {
352 if ( $masterPositions[$i] ) {
353 // The DBMS may not support getMasterPos()
354 if ( !$lb->waitForAll( $masterPositions[$i], $opts['timeout'] ) ) {
355 $failed[] = $lb->getServerName( $lb->getWriterIndex() );
356 }
357 }
358 }
359
360 if ( $failed ) {
361 throw new DBReplicationWaitError(
362 "Could not wait for replica DBs to catch up to " .
363 implode( ', ', $failed )
364 );
365 }
366 }
367
368 public function setWaitForReplicationListener( $name, callable $callback = null ) {
369 if ( $callback ) {
370 $this->replicationWaitCallbacks[$name] = $callback;
371 } else {
372 unset( $this->replicationWaitCallbacks[$name] );
373 }
374 }
375
377 if ( $this->hasMasterChanges() ) {
378 $this->queryLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
379 ( new RuntimeException() )->getTraceAsString() );
380
381 return null;
382 }
383
384 return $this->ticket;
385 }
386
387 public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
388 if ( $ticket !== $this->ticket ) {
389 $this->perfLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
390 ( new RuntimeException() )->getTraceAsString() );
391
392 return;
393 }
394
395 // The transaction owner and any caller with the empty transaction ticket can commit
396 // so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
397 if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
398 $this->queryLogger->info( "$fname: committing on behalf of {$this->trxRoundId}." );
399 $fnameEffective = $this->trxRoundId;
400 } else {
401 $fnameEffective = $fname;
402 }
403
404 $this->commitMasterChanges( $fnameEffective );
405 $this->waitForReplication( $opts );
406 // If a nested caller committed on behalf of $fname, start another empty $fname
407 // transaction, leaving the caller with the same empty transaction state as before.
408 if ( $fnameEffective !== $fname ) {
409 $this->beginMasterChanges( $fnameEffective );
410 }
411 }
412
413 public function getChronologyProtectorTouched( $dbName ) {
414 return $this->getChronologyProtector()->getTouched( $dbName );
415 }
416
417 public function disableChronologyProtection() {
418 $this->getChronologyProtector()->setEnabled( false );
419 }
420
424 protected function getChronologyProtector() {
425 if ( $this->chronProt ) {
426 return $this->chronProt;
427 }
428
429 $this->chronProt = new ChronologyProtector(
430 $this->memCache,
431 [
432 'ip' => $this->requestInfo['IPAddress'],
433 'agent' => $this->requestInfo['UserAgent'],
434 ],
435 isset( $_GET['cpPosTime'] ) ? $_GET['cpPosTime'] : null
436 );
437 $this->chronProt->setLogger( $this->replLogger );
438
439 if ( $this->cliMode ) {
440 $this->chronProt->setEnabled( false );
441 } elseif ( $this->requestInfo['ChronologyProtection'] === 'false' ) {
442 // Request opted out of using position wait logic. This is useful for requests
443 // done by the job queue or background ETL that do not have a meaningful session.
444 $this->chronProt->setWaitEnabled( false );
445 }
446
447 $this->replLogger->debug( __METHOD__ . ': using request info ' .
448 json_encode( $this->requestInfo, JSON_PRETTY_PRINT ) );
449
450 return $this->chronProt;
451 }
452
460 protected function shutdownChronologyProtector(
461 ChronologyProtector $cp, $workCallback, $mode
462 ) {
463 // Record all the master positions needed
464 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $cp ) {
465 $cp->shutdownLB( $lb );
466 } );
467 // Write them to the persistent stash. Try to do something useful by running $work
468 // while ChronologyProtector waits for the stash write to replicate to all DCs.
469 $unsavedPositions = $cp->shutdown( $workCallback, $mode );
470 if ( $unsavedPositions && $workCallback ) {
471 // Invoke callback in case it did not cache the result yet
472 $workCallback(); // work now to block for less time in waitForAll()
473 }
474 // If the positions failed to write to the stash, at least wait on local datacenter
475 // replica DBs to catch up before responding. Even if there are several DCs, this increases
476 // the chance that the user will see their own changes immediately afterwards. As long
477 // as the sticky DC cookie applies (same domain), this is not even an issue.
478 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $unsavedPositions ) {
479 $masterName = $lb->getServerName( $lb->getWriterIndex() );
480 if ( isset( $unsavedPositions[$masterName] ) ) {
481 $lb->waitForAll( $unsavedPositions[$masterName] );
482 }
483 } );
484 }
485
490 final protected function baseLoadBalancerParams() {
491 return [
492 'localDomain' => $this->localDomain,
493 'readOnlyReason' => $this->readOnlyReason,
494 'srvCache' => $this->srvCache,
495 'wanCache' => $this->wanCache,
496 'profiler' => $this->profiler,
497 'trxProfiler' => $this->trxProfiler,
498 'queryLogger' => $this->queryLogger,
499 'connLogger' => $this->connLogger,
500 'replLogger' => $this->replLogger,
501 'errorLogger' => $this->errorLogger,
502 'hostname' => $this->hostname,
503 'cliMode' => $this->cliMode,
504 'agent' => $this->agent
505 ];
506 }
507
511 protected function initLoadBalancer( ILoadBalancer $lb ) {
512 if ( $this->trxRoundId !== false ) {
513 $lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX
514 }
515 }
516
517 public function setDomainPrefix( $prefix ) {
518 $this->localDomain = new DatabaseDomain(
519 $this->localDomain->getDatabase(),
520 null,
521 $prefix
522 );
523
524 $this->forEachLB( function( ILoadBalancer $lb ) use ( $prefix ) {
525 $lb->setDomainPrefix( $prefix );
526 } );
527 }
528
529 public function closeAll() {
530 $this->forEachLBCallMethod( 'closeAll', [] );
531 }
532
533 public function setAgentName( $agent ) {
534 $this->agent = $agent;
535 }
536
537 public function appendPreShutdownTimeAsQuery( $url, $time ) {
538 $usedCluster = 0;
539 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$usedCluster ) {
540 $usedCluster |= ( $lb->getServerCount() > 1 );
541 } );
542
543 if ( !$usedCluster ) {
544 return $url; // no master/replica clusters touched
545 }
546
547 return strpos( $url, '?' ) === false ? "$url?cpPosTime=$time" : "$url&cpPosTime=$time";
548 }
549
550 public function setRequestInfo( array $info ) {
551 $this->requestInfo = $info + $this->requestInfo;
552 }
553
560 final protected function getScopedPHPBehaviorForCommit() {
561 if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
562 $old = ignore_user_abort( true ); // avoid half-finished operations
563 return new ScopedCallback( function () use ( $old ) {
564 ignore_user_abort( $old );
565 } );
566 }
567
568 return null;
569 }
570
571 function __destruct() {
572 $this->destroy();
573 }
574}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined.
Definition Setup.php:36
if( $line===false) $args
Definition cdb.php:64
interface is intended to be more or less compatible with the PHP memcached client.
Definition BagOStuff.php:47
Class for ensuring a consistent ordering of events as seen by the user, despite replication.
shutdown(callable $workCallback=null, $mode='sync')
Notify the ChronologyProtector that the LBFactory is done calling shutdownLB() for now.
shutdownLB(ILoadBalancer $lb)
Notify the ChronologyProtector that the ILoadBalancer is about to shut down.
setLogger(LoggerInterface $logger)
Exception class for replica DB wait timeouts.
Class to handle database/prefix specification for IDatabase domains.
static newFromId( $domain)
static newUnspecified()
A BagOStuff object with no objects in it.
An interface for generating database load balancers.
Definition LBFactory.php:31
getExternalLB( $cluster)
mixed $ticket
Definition LBFactory.php:63
setAgentName( $agent)
forEachLBCallMethod( $methodName, array $args=[])
Call a method of each tracked load balancer.
laggedReplicaUsed()
Detemine if any lagged replica DB connection was used.
shutdownChronologyProtector(ChronologyProtector $cp, $workCallback, $mode)
Get and record all of the staged DB positions into persistent memory storage.
setRequestInfo(array $info)
destroy()
Disables all load balancers.
string $agent
Agent name for query profiling.
Definition LBFactory.php:74
BagOStuff $memCache
Definition LBFactory.php:51
shutdown( $mode=self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback=null)
Prepare all tracked load balancers for shutdown.
commitAndWaitForReplication( $fname, $ticket, array $opts=[])
Convenience method for safely running commitMasterChanges()/waitForReplication()
LoggerInterface $perfLogger
Definition LBFactory.php:45
initLoadBalancer(ILoadBalancer $lb)
baseLoadBalancerParams()
Base parameters to LoadBalancer::__construct()
object string $profiler
Class name or object With profileIn/profileOut methods.
Definition LBFactory.php:35
__construct(array $conf)
Construct a manager of ILoadBalancer objects.
Definition LBFactory.php:79
disableChronologyProtection()
Disable the ChronologyProtector for all load balancers.
rollbackMasterChanges( $fname=__METHOD__)
Rollback changes on all master connections.
getChronologyProtector()
ChronologyProtector $chronProt
Definition LBFactory.php:33
WANObjectCache $wanCache
Definition LBFactory.php:53
hasTransactionRound()
Check if a transaction round is active.
hasMasterChanges()
Determine if any master connection has pending changes.
newMainLB( $domain=false)
flushReplicaSnapshots( $fname=__METHOD__)
Commit all replica DB transactions so as to flush any REPEATABLE-READ or SSI snapshot.
commitMasterChanges( $fname=__METHOD__, array $options=[])
Commit changes on all master connections.
callable $errorLogger
Error logger.
Definition LBFactory.php:47
LoggerInterface $queryLogger
Definition LBFactory.php:43
appendPreShutdownTimeAsQuery( $url, $time)
Append ?cpPosTime parameter to a URL for ChronologyProtector purposes if needed.
setWaitForReplicationListener( $name, callable $callback=null)
Add a callback to be run in every call to waitForReplication() before waiting.
hasOrMadeRecentMasterChanges( $age=null)
Determine if any master connection has pending/written changes from this request.
string bool $trxRoundId
String if a requested DBO_TRX transaction round is active.
Definition LBFactory.php:65
static $loggerFields
Definition LBFactory.php:76
getChronologyProtectorTouched( $dbName)
callable[] $replicationWaitCallbacks
Definition LBFactory.php:69
getScopedPHPBehaviorForCommit()
Make PHP ignore user aborts/disconnects until the returned value leaves scope.
string $hostname
Local hostname of the app server.
Definition LBFactory.php:58
BagOStuff $srvCache
Definition LBFactory.php:49
newExternalLB( $cluster)
LoggerInterface $replLogger
Definition LBFactory.php:39
string bool $readOnlyReason
Reason all LBs are read-only or false if not.
Definition LBFactory.php:67
commitAll( $fname=__METHOD__, array $options=[])
Commit open transactions on all connections.
beginMasterChanges( $fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
logIfMultiDbTransaction()
Log query info if multi DB transactions are going to be committed now.
getMainLB( $domain=false)
waitForReplication(array $opts=[])
Waits for the replica DBs to catch up to the current master position.
array $requestInfo
Web request information about the client.
Definition LBFactory.php:60
getEmptyTransactionTicket( $fname)
Get a token asserting that no transaction writes are active.
bool $cliMode
Whether this PHP instance is for a CLI script.
Definition LBFactory.php:72
DatabaseDomain $localDomain
Local domain.
Definition LBFactory.php:56
closeAll()
Close all open database connections on all open load balancers.
LoggerInterface $connLogger
Definition LBFactory.php:41
setDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
TransactionProfiler $trxProfiler
Definition LBFactory.php:37
Helper class that detects high-contention DB queries via profiling calls.
Multi-datacenter aware caching interface.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
the array() calling protocol came about after MediaWiki 1.4rc1.
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition hooks.txt:1752
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition hooks.txt:1096
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition hooks.txt:1949
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:304
returning false will NOT prevent logging $e
Definition hooks.txt:2110
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
An interface for generating database load balancers.
forEachLB( $callback, array $params=[])
Execute a function for each tracked load balancer The callback is called with the load balancer as th...
Database cluster connection, tracking, load balancing, and transaction manager interface.
beginMasterChanges( $fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
getServerCount()
Get the number of defined servers (not the number of open connections)
pendingMasterChangeCallers()
Get the list of callers that have pending master changes.
hasOrMadeRecentMasterChanges( $age=null)
Check if this load balancer object had any recent or still pending writes issued against it by this P...
setDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
runMasterPostTrxCallbacks( $type)
Issue all pending post-COMMIT/ROLLBACK callbacks.
waitForAll( $pos, $timeout=null)
Set the master wait position and wait for ALL replica DBs to catch up to it.
hasMasterChanges()
Determine if there are pending changes in a transaction by this thread.
getServerName( $i)
Get the host name or IP address of the server with the specified index Prefer a readable name if avai...
$params