MediaWiki REL1_31
LBFactory.php
Go to the documentation of this file.
1<?php
24namespace Wikimedia\Rdbms;
25
26use Psr\Log\LoggerInterface;
27use Wikimedia\ScopedCallback;
31use Exception;
32use RuntimeException;
33use LogicException;
34
39abstract class LBFactory implements ILBFactory {
41 protected $chronProt;
43 protected $profiler;
45 protected $trxProfiler;
47 protected $replLogger;
49 protected $connLogger;
51 protected $queryLogger;
53 protected $perfLogger;
55 protected $errorLogger;
59 protected $srvCache;
61 protected $memStash;
63 protected $wanCache;
64
66 protected $localDomain;
68 protected $hostname;
70 protected $requestInfo;
71
73 protected $ticket;
75 protected $trxRoundId = false;
77 protected $readOnlyReason = false;
80
82 protected $tableAliases = [];
84 protected $indexAliases = [];
85
87 protected $cliMode;
89 protected $agent;
90
91 private static $loggerFields =
92 [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ];
93
94 public function __construct( array $conf ) {
95 $this->localDomain = isset( $conf['localDomain'] )
96 ? DatabaseDomain::newFromId( $conf['localDomain'] )
98
99 if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
100 $this->readOnlyReason = $conf['readOnlyReason'];
101 }
102
103 $this->srvCache = isset( $conf['srvCache'] ) ? $conf['srvCache'] : new EmptyBagOStuff();
104 $this->memStash = isset( $conf['memStash'] ) ? $conf['memStash'] : new EmptyBagOStuff();
105 $this->wanCache = isset( $conf['wanCache'] )
106 ? $conf['wanCache']
107 : WANObjectCache::newEmpty();
108
109 foreach ( self::$loggerFields as $key ) {
110 $this->$key = isset( $conf[$key] ) ? $conf[$key] : new \Psr\Log\NullLogger();
111 }
112 $this->errorLogger = isset( $conf['errorLogger'] )
113 ? $conf['errorLogger']
114 : function ( Exception $e ) {
115 trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
116 };
117 $this->deprecationLogger = isset( $conf['deprecationLogger'] )
118 ? $conf['deprecationLogger']
119 : function ( $msg ) {
120 trigger_error( $msg, E_USER_DEPRECATED );
121 };
122
123 $this->profiler = isset( $conf['profiler'] ) ? $conf['profiler'] : null;
124 $this->trxProfiler = isset( $conf['trxProfiler'] )
125 ? $conf['trxProfiler']
126 : new TransactionProfiler();
127
128 $this->requestInfo = [
129 'IPAddress' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '',
130 'UserAgent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '',
131 'ChronologyProtection' => 'true',
132 'ChronologyPositionIndex' => isset( $_GET['cpPosIndex'] ) ? $_GET['cpPosIndex'] : null
133 ];
134
135 $this->cliMode = isset( $conf['cliMode'] )
136 ? $conf['cliMode']
137 : ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
138 $this->hostname = isset( $conf['hostname'] ) ? $conf['hostname'] : gethostname();
139 $this->agent = isset( $conf['agent'] ) ? $conf['agent'] : '';
140
141 $this->ticket = mt_rand();
142 }
143
144 public function destroy() {
145 $this->shutdown( self::SHUTDOWN_NO_CHRONPROT );
146 $this->forEachLBCallMethod( 'disable' );
147 }
148
149 public function shutdown(
150 $mode = self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback = null, &$cpIndex = null
151 ) {
153 if ( $mode === self::SHUTDOWN_CHRONPROT_SYNC ) {
154 $this->shutdownChronologyProtector( $chronProt, $workCallback, 'sync', $cpIndex );
155 } elseif ( $mode === self::SHUTDOWN_CHRONPROT_ASYNC ) {
156 $this->shutdownChronologyProtector( $chronProt, null, 'async', $cpIndex );
157 }
158
159 $this->commitMasterChanges( __METHOD__ ); // sanity
160 }
161
167 abstract public function newMainLB( $domain = false );
168
174 abstract public function getMainLB( $domain = false );
175
181 abstract public function newExternalLB( $cluster );
182
188 abstract public function getExternalLB( $cluster );
189
196 protected function forEachLBCallMethod( $methodName, array $args = [] ) {
197 $this->forEachLB(
198 function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
199 call_user_func_array( [ $loadBalancer, $methodName ], $args );
200 },
201 [ $methodName, $args ]
202 );
203 }
204
205 public function flushReplicaSnapshots( $fname = __METHOD__ ) {
206 $this->forEachLBCallMethod( 'flushReplicaSnapshots', [ $fname ] );
207 }
208
209 public function commitAll( $fname = __METHOD__, array $options = [] ) {
211 $this->forEachLBCallMethod( 'commitAll', [ $fname ] );
212 }
213
214 public function beginMasterChanges( $fname = __METHOD__ ) {
215 if ( $this->trxRoundId !== false ) {
216 throw new DBTransactionError(
217 null,
218 "$fname: transaction round '{$this->trxRoundId}' already started."
219 );
220 }
221 $this->trxRoundId = $fname;
222 // Set DBO_TRX flags on all appropriate DBs
223 $this->forEachLBCallMethod( 'beginMasterChanges', [ $fname ] );
224 }
225
226 public function commitMasterChanges( $fname = __METHOD__, array $options = [] ) {
227 if ( $this->trxRoundId !== false && $this->trxRoundId !== $fname ) {
228 throw new DBTransactionError(
229 null,
230 "$fname: transaction round '{$this->trxRoundId}' still running."
231 );
232 }
234 $scope = $this->getScopedPHPBehaviorForCommit(); // try to ignore client aborts
235 // Run pre-commit callbacks and suppress post-commit callbacks, aborting on failure
236 $this->forEachLBCallMethod( 'finalizeMasterChanges' );
237 $this->trxRoundId = false;
238 // Perform pre-commit checks, aborting on failure
239 $this->forEachLBCallMethod( 'approveMasterChanges', [ $options ] );
240 // Log the DBs and methods involved in multi-DB transactions
242 // Actually perform the commit on all master DB connections and revert DBO_TRX
243 $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
244 // Run all post-commit callbacks
246 $e = null; // first callback exception
247 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e ) {
248 $ex = $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_COMMIT );
249 $e = $e ?: $ex;
250 } );
251 // Commit any dangling DBO_TRX transactions from callbacks on one DB to another DB
252 $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
253 // Throw any last post-commit callback error
254 if ( $e instanceof Exception ) {
255 throw $e;
256 }
257 }
258
259 public function rollbackMasterChanges( $fname = __METHOD__ ) {
260 $this->trxRoundId = false;
261 $this->forEachLBCallMethod( 'suppressTransactionEndCallbacks' );
262 $this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] );
263 // Run all post-rollback callbacks
264 $this->forEachLB( function ( ILoadBalancer $lb ) {
265 $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_ROLLBACK );
266 } );
267 }
268
269 public function hasTransactionRound() {
270 return ( $this->trxRoundId !== false );
271 }
272
276 private function logIfMultiDbTransaction() {
277 $callersByDB = [];
278 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$callersByDB ) {
279 $masterName = $lb->getServerName( $lb->getWriterIndex() );
280 $callers = $lb->pendingMasterChangeCallers();
281 if ( $callers ) {
282 $callersByDB[$masterName] = $callers;
283 }
284 } );
285
286 if ( count( $callersByDB ) >= 2 ) {
287 $dbs = implode( ', ', array_keys( $callersByDB ) );
288 $msg = "Multi-DB transaction [{$dbs}]:\n";
289 foreach ( $callersByDB as $db => $callers ) {
290 $msg .= "$db: " . implode( '; ', $callers ) . "\n";
291 }
292 $this->queryLogger->info( $msg );
293 }
294 }
295
296 public function hasMasterChanges() {
297 $ret = false;
298 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
299 $ret = $ret || $lb->hasMasterChanges();
300 } );
301
302 return $ret;
303 }
304
305 public function laggedReplicaUsed() {
306 $ret = false;
307 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
308 $ret = $ret || $lb->laggedReplicaUsed();
309 } );
310
311 return $ret;
312 }
313
314 public function hasOrMadeRecentMasterChanges( $age = null ) {
315 $ret = false;
316 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $age, &$ret ) {
317 $ret = $ret || $lb->hasOrMadeRecentMasterChanges( $age );
318 } );
319 return $ret;
320 }
321
322 public function waitForReplication( array $opts = [] ) {
323 $opts += [
324 'domain' => false,
325 'cluster' => false,
326 'timeout' => $this->cliMode ? 60 : 10,
327 'ifWritesSince' => null
328 ];
329
330 if ( $opts['domain'] === false && isset( $opts['wiki'] ) ) {
331 $opts['domain'] = $opts['wiki']; // b/c
332 }
333
334 // Figure out which clusters need to be checked
336 $lbs = [];
337 if ( $opts['cluster'] !== false ) {
338 $lbs[] = $this->getExternalLB( $opts['cluster'] );
339 } elseif ( $opts['domain'] !== false ) {
340 $lbs[] = $this->getMainLB( $opts['domain'] );
341 } else {
342 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$lbs ) {
343 $lbs[] = $lb;
344 } );
345 if ( !$lbs ) {
346 return; // nothing actually used
347 }
348 }
349
350 // Get all the master positions of applicable DBs right now.
351 // This can be faster since waiting on one cluster reduces the
352 // time needed to wait on the next clusters.
353 $masterPositions = array_fill( 0, count( $lbs ), false );
354 foreach ( $lbs as $i => $lb ) {
355 if ( $lb->getServerCount() <= 1 ) {
356 // T29975 - Don't try to wait for replica DBs if there are none
357 // Prevents permission error when getting master position
358 continue;
359 } elseif ( $opts['ifWritesSince']
360 && $lb->lastMasterChangeTimestamp() < $opts['ifWritesSince']
361 ) {
362 continue; // no writes since the last wait
363 }
364 $masterPositions[$i] = $lb->getMasterPos();
365 }
366
367 // Run any listener callbacks *after* getting the DB positions. The more
368 // time spent in the callbacks, the less time is spent in waitForAll().
369 foreach ( $this->replicationWaitCallbacks as $callback ) {
370 $callback();
371 }
372
373 $failed = [];
374 foreach ( $lbs as $i => $lb ) {
375 if ( $masterPositions[$i] ) {
376 // The RDBMS may not support getMasterPos()
377 if ( !$lb->waitForAll( $masterPositions[$i], $opts['timeout'] ) ) {
378 $failed[] = $lb->getServerName( $lb->getWriterIndex() );
379 }
380 }
381 }
382
383 if ( $failed ) {
384 throw new DBReplicationWaitError(
385 null,
386 "Could not wait for replica DBs to catch up to " .
387 implode( ', ', $failed )
388 );
389 }
390 }
391
392 public function setWaitForReplicationListener( $name, callable $callback = null ) {
393 if ( $callback ) {
394 $this->replicationWaitCallbacks[$name] = $callback;
395 } else {
396 unset( $this->replicationWaitCallbacks[$name] );
397 }
398 }
399
401 if ( $this->hasMasterChanges() ) {
402 $this->queryLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
403 ( new RuntimeException() )->getTraceAsString() );
404
405 return null;
406 }
407
408 return $this->ticket;
409 }
410
411 public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
412 if ( $ticket !== $this->ticket ) {
413 $this->perfLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
414 ( new RuntimeException() )->getTraceAsString() );
415
416 return;
417 }
418
419 // The transaction owner and any caller with the empty transaction ticket can commit
420 // so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
421 if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
422 $this->queryLogger->info( "$fname: committing on behalf of {$this->trxRoundId}." );
423 $fnameEffective = $this->trxRoundId;
424 } else {
425 $fnameEffective = $fname;
426 }
427
428 $this->commitMasterChanges( $fnameEffective );
429 $this->waitForReplication( $opts );
430 // If a nested caller committed on behalf of $fname, start another empty $fname
431 // transaction, leaving the caller with the same empty transaction state as before.
432 if ( $fnameEffective !== $fname ) {
433 $this->beginMasterChanges( $fnameEffective );
434 }
435 }
436
437 public function getChronologyProtectorTouched( $dbName ) {
438 return $this->getChronologyProtector()->getTouched( $dbName );
439 }
440
441 public function disableChronologyProtection() {
442 $this->getChronologyProtector()->setEnabled( false );
443 }
444
448 protected function getChronologyProtector() {
449 if ( $this->chronProt ) {
450 return $this->chronProt;
451 }
452
453 $this->chronProt = new ChronologyProtector(
454 $this->memStash,
455 [
456 'ip' => $this->requestInfo['IPAddress'],
457 'agent' => $this->requestInfo['UserAgent'],
458 ],
459 $this->requestInfo['ChronologyPositionIndex']
460 );
461 $this->chronProt->setLogger( $this->replLogger );
462
463 if ( $this->cliMode ) {
464 $this->chronProt->setEnabled( false );
465 } elseif ( $this->requestInfo['ChronologyProtection'] === 'false' ) {
466 // Request opted out of using position wait logic. This is useful for requests
467 // done by the job queue or background ETL that do not have a meaningful session.
468 $this->chronProt->setWaitEnabled( false );
469 } elseif ( $this->memStash instanceof EmptyBagOStuff ) {
470 // No where to store any DB positions and wait for them to appear
471 $this->chronProt->setEnabled( false );
472 $this->replLogger->info( 'Cannot use ChronologyProtector with EmptyBagOStuff.' );
473 }
474
475 $this->replLogger->debug( __METHOD__ . ': using request info ' .
476 json_encode( $this->requestInfo, JSON_PRETTY_PRINT ) );
477
478 return $this->chronProt;
479 }
480
489 protected function shutdownChronologyProtector(
490 ChronologyProtector $cp, $workCallback, $mode, &$cpIndex = null
491 ) {
492 // Record all the master positions needed
493 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $cp ) {
494 $cp->shutdownLB( $lb );
495 } );
496 // Write them to the persistent stash. Try to do something useful by running $work
497 // while ChronologyProtector waits for the stash write to replicate to all DCs.
498 $unsavedPositions = $cp->shutdown( $workCallback, $mode, $cpIndex );
499 if ( $unsavedPositions && $workCallback ) {
500 // Invoke callback in case it did not cache the result yet
501 $workCallback(); // work now to block for less time in waitForAll()
502 }
503 // If the positions failed to write to the stash, at least wait on local datacenter
504 // replica DBs to catch up before responding. Even if there are several DCs, this increases
505 // the chance that the user will see their own changes immediately afterwards. As long
506 // as the sticky DC cookie applies (same domain), this is not even an issue.
507 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $unsavedPositions ) {
508 $masterName = $lb->getServerName( $lb->getWriterIndex() );
509 if ( isset( $unsavedPositions[$masterName] ) ) {
510 $lb->waitForAll( $unsavedPositions[$masterName] );
511 }
512 } );
513 }
514
519 final protected function baseLoadBalancerParams() {
520 return [
521 'localDomain' => $this->localDomain,
522 'readOnlyReason' => $this->readOnlyReason,
523 'srvCache' => $this->srvCache,
524 'wanCache' => $this->wanCache,
525 'profiler' => $this->profiler,
526 'trxProfiler' => $this->trxProfiler,
527 'queryLogger' => $this->queryLogger,
528 'connLogger' => $this->connLogger,
529 'replLogger' => $this->replLogger,
530 'errorLogger' => $this->errorLogger,
531 'deprecationLogger' => $this->deprecationLogger,
532 'hostname' => $this->hostname,
533 'cliMode' => $this->cliMode,
534 'agent' => $this->agent,
535 'chronologyCallback' => function ( ILoadBalancer $lb ) {
536 // Defer ChronologyProtector construction in case setRequestInfo() ends up
537 // being called later (but before the first connection attempt) (T192611)
538 $this->getChronologyProtector()->initLB( $lb );
539 }
540 ];
541 }
542
546 protected function initLoadBalancer( ILoadBalancer $lb ) {
547 if ( $this->trxRoundId !== false ) {
548 $lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX
549 }
550
551 $lb->setTableAliases( $this->tableAliases );
552 $lb->setIndexAliases( $this->indexAliases );
553 }
554
555 public function setTableAliases( array $aliases ) {
556 $this->tableAliases = $aliases;
557 }
558
559 public function setIndexAliases( array $aliases ) {
560 $this->indexAliases = $aliases;
561 }
562
563 public function setDomainPrefix( $prefix ) {
564 $this->localDomain = new DatabaseDomain(
565 $this->localDomain->getDatabase(),
566 null,
567 $prefix
568 );
569
570 $this->forEachLB( function ( ILoadBalancer $lb ) use ( $prefix ) {
571 $lb->setDomainPrefix( $prefix );
572 } );
573 }
574
575 public function closeAll() {
576 $this->forEachLBCallMethod( 'closeAll', [] );
577 }
578
579 public function setAgentName( $agent ) {
580 $this->agent = $agent;
581 }
582
583 public function appendShutdownCPIndexAsQuery( $url, $index ) {
584 $usedCluster = 0;
585 $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$usedCluster ) {
586 $usedCluster |= ( $lb->getServerCount() > 1 );
587 } );
588
589 if ( !$usedCluster ) {
590 return $url; // no master/replica clusters touched
591 }
592
593 return strpos( $url, '?' ) === false ? "$url?cpPosIndex=$index" : "$url&cpPosIndex=$index";
594 }
595
596 public function setRequestInfo( array $info ) {
597 if ( $this->chronProt ) {
598 throw new LogicException( 'ChronologyProtector already initialized.' );
599 }
600
601 $this->requestInfo = $info + $this->requestInfo;
602 }
603
610 final protected function getScopedPHPBehaviorForCommit() {
611 if ( PHP_SAPI != 'cli' ) { // https://bugs.php.net/bug.php?id=47540
612 $old = ignore_user_abort( true ); // avoid half-finished operations
613 return new ScopedCallback( function () use ( $old ) {
614 ignore_user_abort( $old );
615 } );
616 }
617
618 return null;
619 }
620
621 function __destruct() {
622 $this->destroy();
623 }
624}
625
626class_alias( LBFactory::class, 'LBFactory' );
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings,...
Definition Setup.php:112
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
A BagOStuff object with no objects in it.
Multi-datacenter aware caching interface.
Class for ensuring a consistent ordering of events as seen by the user, despite replication.
shutdownLB(ILoadBalancer $lb)
Notify the ChronologyProtector that the ILoadBalancer is about to shut down.
shutdown(callable $workCallback=null, $mode='sync', &$cpIndex=null)
Notify the ChronologyProtector that the LBFactory is done calling shutdownLB() for now.
Exception class for replica DB wait timeouts.
Class to handle database/prefix specification for IDatabase domains.
An interface for generating database load balancers.
Definition LBFactory.php:39
LoggerInterface $replLogger
Definition LBFactory.php:47
callable[] $replicationWaitCallbacks
Definition LBFactory.php:79
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
hasMasterChanges()
Determine if any master connection has pending changes.
WANObjectCache $wanCache
Definition LBFactory.php:63
shutdownChronologyProtector(ChronologyProtector $cp, $workCallback, $mode, &$cpIndex=null)
Get and record all of the staged DB positions into persistent memory storage.
string[] $indexAliases
Map of (index alias => index)
Definition LBFactory.php:84
newMainLB( $domain=false)
getEmptyTransactionTicket( $fname)
Get a token asserting that no transaction writes are active.
hasTransactionRound()
Check if a transaction round is active.
LoggerInterface $connLogger
Definition LBFactory.php:49
setRequestInfo(array $info)
LoggerInterface $queryLogger
Definition LBFactory.php:51
commitAndWaitForReplication( $fname, $ticket, array $opts=[])
Convenience method for safely running commitMasterChanges()/waitForReplication()
shutdown( $mode=self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback=null, &$cpIndex=null)
Prepare all tracked load balancers for shutdown.
callable $errorLogger
Error logger.
Definition LBFactory.php:55
beginMasterChanges( $fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
array $requestInfo
Web request information about the client.
Definition LBFactory.php:70
string $hostname
Local hostname of the app server.
Definition LBFactory.php:68
getMainLB( $domain=false)
getChronologyProtectorTouched( $dbName)
getScopedPHPBehaviorForCommit()
Make PHP ignore user aborts/disconnects until the returned value leaves scope.
setDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
waitForReplication(array $opts=[])
Waits for the replica DBs to catch up to the current master position.
LoggerInterface $perfLogger
Definition LBFactory.php:53
rollbackMasterChanges( $fname=__METHOD__)
Rollback changes on all master connections.
initLoadBalancer(ILoadBalancer $lb)
hasOrMadeRecentMasterChanges( $age=null)
Determine if any master connection has pending/written changes from this request.
DatabaseDomain $localDomain
Local domain.
Definition LBFactory.php:66
TransactionProfiler $trxProfiler
Definition LBFactory.php:45
ChronologyProtector $chronProt
Definition LBFactory.php:41
string bool $trxRoundId
String if a requested DBO_TRX transaction round is active.
Definition LBFactory.php:75
destroy()
Disables all load balancers.
__construct(array $conf)
Construct a manager of ILoadBalancer objects.
Definition LBFactory.php:94
forEachLBCallMethod( $methodName, array $args=[])
Call a method of each tracked load balancer.
object string $profiler
Class name or object With profileIn/profileOut methods.
Definition LBFactory.php:43
setWaitForReplicationListener( $name, callable $callback=null)
Add a callback to be run in every call to waitForReplication() before waiting.
laggedReplicaUsed()
Detemine if any lagged replica DB connection was used.
appendShutdownCPIndexAsQuery( $url, $index)
Append ?cpPosIndex parameter to a URL for ChronologyProtector purposes if needed.
disableChronologyProtection()
Disable the ChronologyProtector for all load balancers.
setIndexAliases(array $aliases)
Convert certain index names to alternative names before querying the DB.
commitMasterChanges( $fname=__METHOD__, array $options=[])
Commit changes on all master connections.
commitAll( $fname=__METHOD__, array $options=[])
Commit open transactions on all connections.
bool $cliMode
Whether this PHP instance is for a CLI script.
Definition LBFactory.php:87
logIfMultiDbTransaction()
Log query info if multi DB transactions are going to be committed now.
string bool $readOnlyReason
Reason all LBs are read-only or false if not.
Definition LBFactory.php:77
baseLoadBalancerParams()
Base parameters to LoadBalancer::__construct()
string $agent
Agent name for query profiling.
Definition LBFactory.php:89
callable $deprecationLogger
Deprecation logger.
Definition LBFactory.php:57
closeAll()
Close all open database connections on all open load balancers.
flushReplicaSnapshots( $fname=__METHOD__)
Commit all replica DB transactions so as to flush any REPEATABLE-READ or SSI snapshot.
Helper class that detects high-contention DB queries via profiling calls.
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.
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 & $options
Definition hooks.txt:2001
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:2005
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
returning false will NOT prevent logging $e
Definition hooks.txt:2176
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.
setDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
hasOrMadeRecentMasterChanges( $age=null)
Check if this load balancer object had any recent or still pending writes issued against it by this P...
beginMasterChanges( $fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
pendingMasterChangeCallers()
Get the list of callers that have pending master changes.
hasMasterChanges()
Determine if there are pending changes in a transaction by this thread.
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
runMasterPostTrxCallbacks( $type)
Issue all pending post-COMMIT/ROLLBACK callbacks.
laggedReplicaUsed()
Checks whether the database for generic connections this request was both:
getServerCount()
Get the number of defined servers (not the number of open connections)
setIndexAliases(array $aliases)
Convert certain index names to alternative names before querying the DB.
getServerName( $i)
Get the host name or IP address of the server with the specified index.
waitForAll( $pos, $timeout=null)
Set the master wait position and wait for ALL replica DBs to catch up to it.