MediaWiki  master
LBFactory.php
Go to the documentation of this file.
1 <?php
24 namespace Wikimedia\Rdbms;
25 
26 use BagOStuff;
27 use EmptyBagOStuff;
28 use Exception;
29 use LogicException;
30 use Psr\Log\LoggerInterface;
31 use Psr\Log\NullLogger;
32 use RuntimeException;
33 use Throwable;
34 use WANObjectCache;
35 use Wikimedia\RequestTimeout\CriticalSectionProvider;
36 use Wikimedia\ScopedCallback;
37 
42 abstract class LBFactory implements ILBFactory {
44  private $chronProt;
46  private $csProvider;
51  private $profiler;
53  private $trxProfiler;
55  private $replLogger;
57  private $connLogger;
59  private $queryLogger;
61  private $perfLogger;
63  private $errorLogger;
66 
68  protected $cpStash;
70  protected $srvCache;
72  protected $wanCache;
73 
75  protected $localDomain;
76 
78  private $requestInfo;
80  private $cliMode;
82  private $agent;
84  private $secret;
85 
87  private $tableAliases = [];
89  private $indexAliases = [];
91  private $domainAliases = [];
94 
96  private $id;
98  private $ticket;
100  private $trxRoundId = false;
105 
107  protected $readOnlyReason = false;
108 
110  private $defaultGroup = null;
111 
113  protected $maxLag;
114 
116  private $nonLocalDomainCache = [];
117 
118  private const ROUND_CURSORY = 'cursory';
119  private const ROUND_BEGINNING = 'within-begin';
120  private const ROUND_COMMITTING = 'within-commit';
121  private const ROUND_ROLLING_BACK = 'within-rollback';
122  private const ROUND_COMMIT_CALLBACKS = 'within-commit-callbacks';
123  private const ROUND_ROLLBACK_CALLBACKS = 'within-rollback-callbacks';
124 
125  private static $loggerFields =
126  [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ];
127 
128  public function __construct( array $conf ) {
129  $this->localDomain = isset( $conf['localDomain'] )
130  ? DatabaseDomain::newFromId( $conf['localDomain'] )
132 
133  $this->maxLag = $conf['maxLag'] ?? null;
134  if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
135  $this->readOnlyReason = $conf['readOnlyReason'];
136  }
137 
138  $this->cpStash = $conf['cpStash'] ?? new EmptyBagOStuff();
139  $this->srvCache = $conf['srvCache'] ?? new EmptyBagOStuff();
140  $this->wanCache = $conf['wanCache'] ?? WANObjectCache::newEmpty();
141 
142  foreach ( self::$loggerFields as $key ) {
143  $this->$key = $conf[$key] ?? new NullLogger();
144  }
145  $this->errorLogger = $conf['errorLogger'] ?? static function ( Throwable $e ) {
146  trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
147  };
148  $this->deprecationLogger = $conf['deprecationLogger'] ?? static function ( $msg ) {
149  trigger_error( $msg, E_USER_DEPRECATED );
150  };
151 
152  $this->profiler = $conf['profiler'] ?? null;
153  $this->trxProfiler = $conf['trxProfiler'] ?? new TransactionProfiler();
154 
155  $this->csProvider = $conf['criticalSectionProvider'] ?? null;
156 
157  $this->requestInfo = [
158  'IPAddress' => $_SERVER[ 'REMOTE_ADDR' ] ?? '',
159  'UserAgent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
160  // Headers application can inject via LBFactory::setRequestInfo()
161  'ChronologyProtection' => null,
162  'ChronologyClientId' => null, // prior $cpClientId value from LBFactory::shutdown()
163  'ChronologyPositionIndex' => null // prior $cpIndex value from LBFactory::shutdown()
164  ];
165 
166  $this->cliMode = $conf['cliMode'] ?? ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
167  $this->agent = $conf['agent'] ?? '';
168  $this->defaultGroup = $conf['defaultGroup'] ?? null;
169  $this->secret = $conf['secret'] ?? '';
170  $this->replicationWaitTimeout = $this->cliMode ? 60 : 1;
171 
172  static $nextId, $nextTicket;
173  $this->id = $nextId = ( is_int( $nextId ) ? $nextId++ : mt_rand() );
174  $this->ticket = $nextTicket = ( is_int( $nextTicket ) ? $nextTicket++ : mt_rand() );
175  }
176 
177  public function destroy() {
179  $scope = ScopedCallback::newScopedIgnoreUserAbort();
180 
181  $this->forEachLBCallMethod( 'disable', [ __METHOD__, $this->id ] );
182  }
183 
184  public function getLocalDomainID() {
185  return $this->localDomain->getId();
186  }
187 
188  public function resolveDomainID( $domain ) {
189  return $this->resolveDomainInstance( $domain )->getId();
190  }
191 
196  final protected function resolveDomainInstance( $domain ) {
197  if ( $domain instanceof DatabaseDomain ) {
198  return $domain; // already a domain instance
199  } elseif ( $domain === false || $domain === $this->localDomain->getId() ) {
200  return $this->localDomain;
201  } elseif ( isset( $this->domainAliases[$domain] ) ) {
202  // This array acts as both the original map and as instance cache.
203  // Instances pass-through DatabaseDomain::newFromId as-is.
204  $this->domainAliases[$domain] =
205  DatabaseDomain::newFromId( $this->domainAliases[$domain] );
206 
207  return $this->domainAliases[$domain];
208  }
209 
210  $cachedDomain = $this->nonLocalDomainCache[$domain] ?? null;
211  if ( $cachedDomain === null ) {
212  $cachedDomain = DatabaseDomain::newFromId( $domain );
213  $this->nonLocalDomainCache = [ $domain => $cachedDomain ];
214  }
215 
216  return $cachedDomain;
217  }
218 
219  public function shutdown(
220  $flags = self::SHUTDOWN_NORMAL,
221  callable $workCallback = null,
222  &$cpIndex = null,
223  &$cpClientId = null
224  ) {
226  $scope = ScopedCallback::newScopedIgnoreUserAbort();
227 
229  if ( ( $flags & self::SHUTDOWN_NO_CHRONPROT ) != self::SHUTDOWN_NO_CHRONPROT ) {
230  $this->shutdownChronologyProtector( $chronProt, $workCallback, $cpIndex );
231  $this->replLogger->debug( __METHOD__ . ': finished ChronologyProtector shutdown' );
232  }
233  $cpClientId = $chronProt->getClientId();
234 
235  $this->commitPrimaryChanges( __METHOD__ );
236 
237  $this->replLogger->debug( 'LBFactory shutdown completed' );
238  }
239 
246  protected function forEachLBCallMethod( $methodName, array $args = [] ) {
247  $this->forEachLB(
248  static function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
249  $loadBalancer->$methodName( ...$args );
250  },
251  [ $methodName, $args ]
252  );
253  }
254 
255  public function flushReplicaSnapshots( $fname = __METHOD__ ) {
256  if ( $this->trxRoundId !== false && $this->trxRoundId !== $fname ) {
257  $this->queryLogger->warning(
258  "$fname: transaction round '{$this->trxRoundId}' still running",
259  [ 'trace' => ( new RuntimeException() )->getTraceAsString() ]
260  );
261  }
262  $this->forEachLBCallMethod( 'flushReplicaSnapshots', [ $fname, $this->id ] );
263  }
264 
265  final public function commitAll( $fname = __METHOD__, array $options = [] ) {
266  $this->commitPrimaryChanges( $fname, $options );
267  $this->forEachLBCallMethod( 'flushPrimarySnapshots', [ $fname, $this->id ] );
268  $this->forEachLBCallMethod( 'flushReplicaSnapshots', [ $fname, $this->id ] );
269  }
270 
271  final public function beginPrimaryChanges( $fname = __METHOD__ ) {
272  $this->assertTransactionRoundStage( self::ROUND_CURSORY );
274  $scope = ScopedCallback::newScopedIgnoreUserAbort();
275 
276  $this->trxRoundStage = self::ROUND_BEGINNING;
277  if ( $this->trxRoundId !== false ) {
278  throw new DBTransactionError(
279  null,
280  "$fname: transaction round '{$this->trxRoundId}' already started"
281  );
282  }
283  $this->trxRoundId = $fname;
284  // Set DBO_TRX flags on all appropriate DBs
285  $this->forEachLBCallMethod( 'beginPrimaryChanges', [ $fname, $this->id ] );
286  $this->trxRoundStage = self::ROUND_CURSORY;
287  }
288 
289  public function beginMasterChanges( $fname = __METHOD__ ) {
290  wfDeprecated( __METHOD__, '1.37' );
291  $this->beginPrimaryChanges( $fname );
292  }
293 
294  final public function commitPrimaryChanges( $fname = __METHOD__, array $options = [] ) {
295  $this->assertTransactionRoundStage( self::ROUND_CURSORY );
297  $scope = ScopedCallback::newScopedIgnoreUserAbort();
298 
299  $this->trxRoundStage = self::ROUND_COMMITTING;
300  if ( $this->trxRoundId !== false && $this->trxRoundId !== $fname ) {
301  throw new DBTransactionError(
302  null,
303  "$fname: transaction round '{$this->trxRoundId}' still running"
304  );
305  }
306  // Run pre-commit callbacks and suppress post-commit callbacks, aborting on failure
307  do {
308  $count = 0; // number of callbacks executed this iteration
309  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$count, $fname ) {
310  $count += $lb->finalizePrimaryChanges( $fname, $this->id );
311  } );
312  } while ( $count > 0 );
313  $this->trxRoundId = false;
314  // Perform pre-commit checks, aborting on failure
315  $this->forEachLBCallMethod( 'approvePrimaryChanges', [ $options, $fname, $this->id ] );
316  // Log the DBs and methods involved in multi-DB transactions
317  $this->logIfMultiDbTransaction();
318  // Actually perform the commit on all primary DB connections and revert DBO_TRX
319  $this->forEachLBCallMethod( 'commitPrimaryChanges', [ $fname, $this->id ] );
320  // Run all post-commit callbacks in a separate step
321  $this->trxRoundStage = self::ROUND_COMMIT_CALLBACKS;
322  $e = $this->executePostTransactionCallbacks();
323  $this->trxRoundStage = self::ROUND_CURSORY;
324  // Throw any last post-commit callback error
325  if ( $e instanceof Exception ) {
326  throw $e;
327  }
328  }
329 
330  final public function commitMasterChanges( $fname = __METHOD__, array $options = [] ) {
331  wfDeprecated( __METHOD__, '1.37' );
332  $this->commitPrimaryChanges( $fname, $options );
333  }
334 
335  final public function rollbackPrimaryChanges( $fname = __METHOD__ ) {
337  $scope = ScopedCallback::newScopedIgnoreUserAbort();
338 
339  $this->trxRoundStage = self::ROUND_ROLLING_BACK;
340  $this->trxRoundId = false;
341  // Actually perform the rollback on all primary DB connections and revert DBO_TRX
342  $this->forEachLBCallMethod( 'rollbackPrimaryChanges', [ $fname, $this->id ] );
343  // Run all post-commit callbacks in a separate step
344  $this->trxRoundStage = self::ROUND_ROLLBACK_CALLBACKS;
346  $this->trxRoundStage = self::ROUND_CURSORY;
347  }
348 
349  final public function rollbackMasterChanges( $fname = __METHOD__ ) {
350  wfDeprecated( __METHOD__, '1.37' );
351  $this->rollbackPrimaryChanges( $fname );
352  }
353 
357  private function executePostTransactionCallbacks() {
358  $fname = __METHOD__;
359  // Run all post-commit callbacks until new ones stop getting added
360  $e = null; // first callback exception
361  do {
362  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e, $fname ) {
363  $ex = $lb->runPrimaryTransactionIdleCallbacks( $fname, $this->id );
364  $e = $e ?: $ex;
365  } );
366  } while ( $this->hasPrimaryChanges() );
367  // Run all listener callbacks once
368  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e, $fname ) {
369  $ex = $lb->runPrimaryTransactionListenerCallbacks( $fname, $this->id );
370  $e = $e ?: $ex;
371  } );
372 
373  return $e;
374  }
375 
376  public function hasTransactionRound() {
377  return ( $this->trxRoundId !== false );
378  }
379 
380  public function isReadyForRoundOperations() {
381  return ( $this->trxRoundStage === self::ROUND_CURSORY );
382  }
383 
387  private function logIfMultiDbTransaction() {
388  $callersByDB = [];
389  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( &$callersByDB ) {
390  $primaryName = $lb->getServerName( $lb->getWriterIndex() );
391  $callers = $lb->pendingPrimaryChangeCallers();
392  if ( $callers ) {
393  $callersByDB[$primaryName] = $callers;
394  }
395  } );
396 
397  if ( count( $callersByDB ) >= 2 ) {
398  $dbs = implode( ', ', array_keys( $callersByDB ) );
399  $msg = "Multi-DB transaction [{$dbs}]:\n";
400  foreach ( $callersByDB as $db => $callers ) {
401  $msg .= "$db: " . implode( '; ', $callers ) . "\n";
402  }
403  $this->queryLogger->info( $msg );
404  }
405  }
406 
407  public function hasPrimaryChanges() {
408  $ret = false;
409  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( &$ret ) {
410  $ret = $ret || $lb->hasPrimaryChanges();
411  } );
412 
413  return $ret;
414  }
415 
416  public function hasMasterChanges() {
417  wfDeprecated( __METHOD__, '1.37' );
418  return $this->hasPrimaryChanges();
419  }
420 
421  public function laggedReplicaUsed() {
422  $ret = false;
423  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( &$ret ) {
424  $ret = $ret || $lb->laggedReplicaUsed();
425  } );
426 
427  return $ret;
428  }
429 
430  public function hasOrMadeRecentPrimaryChanges( $age = null ) {
431  $ret = false;
432  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( $age, &$ret ) {
433  $ret = $ret || $lb->hasOrMadeRecentPrimaryChanges( $age );
434  } );
435  return $ret;
436  }
437 
438  public function hasOrMadeRecentMasterChanges( $age = null ) {
439  wfDeprecated( __METHOD__, '1.37' );
440  return $this->hasOrMadeRecentPrimaryChanges( $age );
441  }
442 
443  public function waitForReplication( array $opts = [] ) {
444  $opts += [
445  'domain' => false,
446  'cluster' => false,
447  'timeout' => $this->replicationWaitTimeout,
448  'ifWritesSince' => null
449  ];
450 
451  if ( $opts['domain'] === false && isset( $opts['wiki'] ) ) {
452  $opts['domain'] = $opts['wiki']; // b/c
453  }
454 
455  // Figure out which clusters need to be checked
457  $lbs = [];
458  if ( $opts['cluster'] !== false ) {
459  $lbs[] = $this->getExternalLB( $opts['cluster'] );
460  } elseif ( $opts['domain'] !== false ) {
461  $lbs[] = $this->getMainLB( $opts['domain'] );
462  } else {
463  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( &$lbs ) {
464  $lbs[] = $lb;
465  } );
466  if ( !$lbs ) {
467  return true; // nothing actually used
468  }
469  }
470 
471  // Get all the primary DB positions of applicable DBs right now.
472  // This can be faster since waiting on one cluster reduces the
473  // time needed to wait on the next clusters.
474  $primaryPositions = array_fill( 0, count( $lbs ), false );
475  foreach ( $lbs as $i => $lb ) {
476  if (
477  // No writes to wait on getting replicated
478  !$lb->hasPrimaryConnection() ||
479  // No replication; avoid getPrimaryPos() permissions errors (T29975)
480  !$lb->hasStreamingReplicaServers() ||
481  // No writes since the last replication wait
482  (
483  $opts['ifWritesSince'] &&
484  $lb->lastPrimaryChangeTimestamp() < $opts['ifWritesSince']
485  )
486  ) {
487  continue; // no need to wait
488  }
489 
490  $primaryPositions[$i] = $lb->getPrimaryPos();
491  }
492 
493  // Run any listener callbacks *after* getting the DB positions. The more
494  // time spent in the callbacks, the less time is spent in waitForAll().
495  foreach ( $this->replicationWaitCallbacks as $callback ) {
496  $callback();
497  }
498 
499  $failed = [];
500  foreach ( $lbs as $i => $lb ) {
501  if ( $primaryPositions[$i] ) {
502  // The RDBMS may not support getPrimaryPos()
503  if ( !$lb->waitForAll( $primaryPositions[$i], $opts['timeout'] ) ) {
504  $failed[] = $lb->getServerName( $lb->getWriterIndex() );
505  }
506  }
507  }
508 
509  return !$failed;
510  }
511 
512  public function setWaitForReplicationListener( $name, callable $callback = null ) {
513  if ( $callback ) {
514  $this->replicationWaitCallbacks[$name] = $callback;
515  } else {
516  unset( $this->replicationWaitCallbacks[$name] );
517  }
518  }
519 
520  public function getEmptyTransactionTicket( $fname ) {
521  if ( $this->hasPrimaryChanges() ) {
522  $this->queryLogger->error(
523  __METHOD__ . ": $fname does not have outer scope",
524  [ 'trace' => ( new RuntimeException() )->getTraceAsString() ]
525  );
526 
527  return null;
528  }
529 
530  return $this->ticket;
531  }
532 
533  final public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
534  if ( $ticket !== $this->ticket ) {
535  $this->perfLogger->error(
536  __METHOD__ . ": $fname does not have outer scope",
537  [ 'trace' => ( new RuntimeException() )->getTraceAsString() ]
538  );
539 
540  return false;
541  }
542 
543  // The transaction owner and any caller with the empty transaction ticket can commit
544  // so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
545  if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
546  $this->queryLogger->info( "$fname: committing on behalf of {$this->trxRoundId}" );
547  $fnameEffective = $this->trxRoundId;
548  } else {
549  $fnameEffective = $fname;
550  }
551 
552  $this->commitPrimaryChanges( $fnameEffective );
553  $waitSucceeded = $this->waitForReplication( $opts );
554  // If a nested caller committed on behalf of $fname, start another empty $fname
555  // transaction, leaving the caller with the same empty transaction state as before.
556  if ( $fnameEffective !== $fname ) {
557  $this->beginPrimaryChanges( $fnameEffective );
558  }
559 
560  return $waitSucceeded;
561  }
562 
563  public function getChronologyProtectorTouched( $domain = false ) {
564  return $this->getChronologyProtector()->getTouched( $this->getMainLB( $domain ) );
565  }
566 
567  public function disableChronologyProtection() {
568  $this->getChronologyProtector()->setEnabled( false );
569  }
570 
574  protected function getChronologyProtector() {
575  if ( $this->chronProt ) {
576  return $this->chronProt;
577  }
578 
579  $this->chronProt = new ChronologyProtector(
580  $this->cpStash,
581  [
582  'ip' => $this->requestInfo['IPAddress'],
583  'agent' => $this->requestInfo['UserAgent'],
584  'clientId' => $this->requestInfo['ChronologyClientId'] ?: null
585  ],
586  $this->requestInfo['ChronologyPositionIndex'],
587  $this->secret
588  );
589  $this->chronProt->setLogger( $this->replLogger );
590 
591  if ( $this->cliMode ) {
592  $this->chronProt->setEnabled( false );
593  } elseif ( $this->requestInfo['ChronologyProtection'] === 'false' ) {
594  // Request opted out of using position wait logic. This is useful for requests
595  // done by the job queue or background ETL that do not have a meaningful session.
596  $this->chronProt->setWaitEnabled( false );
597  } elseif ( $this->cpStash instanceof EmptyBagOStuff ) {
598  // No where to store any DB positions and wait for them to appear
599  $this->chronProt->setEnabled( false );
600  $this->replLogger->debug( 'Cannot use ChronologyProtector with EmptyBagOStuff' );
601  }
602 
603  $this->replLogger->debug(
604  __METHOD__ . ': request info ' .
605  json_encode( $this->requestInfo, JSON_PRETTY_PRINT )
606  );
607 
608  return $this->chronProt;
609  }
610 
618  protected function shutdownChronologyProtector(
619  ChronologyProtector $cp, $workCallback, &$cpIndex = null
620  ) {
621  // Remark all of the relevant DB primary positions
622  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( $cp ) {
624  } );
625  // Write the positions to the persistent stash
626  $unsavedPositions = $cp->persistSessionReplicationPositions( $cpIndex );
627  if ( $unsavedPositions && $workCallback ) {
628  // Invoke callback in case it did not cache the result yet
629  $workCallback();
630  }
631  // If the positions failed to write to the stash, then wait on the local datacenter
632  // replica DBs to catch up before sending an HTTP response. As long as the request that
633  // caused such DB writes occurred in the primary datacenter, and clients are temporarily
634  // pinned to the primary datacenter after causing DB writes, then this should suffice.
635  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( $unsavedPositions ) {
636  $primaryName = $lb->getServerName( $lb->getWriterIndex() );
637  if ( isset( $unsavedPositions[$primaryName] ) ) {
638  $lb->waitForAll( $unsavedPositions[$primaryName] );
639  }
640  } );
641  }
642 
649  final protected function baseLoadBalancerParams( $owner ) {
650  if ( $this->trxRoundStage === self::ROUND_COMMIT_CALLBACKS ) {
652  } elseif ( $this->trxRoundStage === self::ROUND_ROLLBACK_CALLBACKS ) {
654  } else {
655  $initStage = null;
656  }
657 
658  return [
659  'localDomain' => $this->localDomain,
660  'readOnlyReason' => $this->readOnlyReason,
661  'srvCache' => $this->srvCache,
662  'wanCache' => $this->wanCache,
663  'profiler' => $this->profiler,
664  'trxProfiler' => $this->trxProfiler,
665  'queryLogger' => $this->queryLogger,
666  'connLogger' => $this->connLogger,
667  'replLogger' => $this->replLogger,
668  'perfLogger' => $this->perfLogger,
669  'errorLogger' => $this->errorLogger,
670  'deprecationLogger' => $this->deprecationLogger,
671  'cliMode' => $this->cliMode,
672  'agent' => $this->agent,
673  'maxLag' => $this->maxLag,
674  'defaultGroup' => $this->defaultGroup,
675  'chronologyCallback' => function ( ILoadBalancer $lb ) {
676  // Defer ChronologyProtector construction in case setRequestInfo() ends up
677  // being called later (but before the first connection attempt) (T192611)
678  $this->getChronologyProtector()->applySessionReplicationPosition( $lb );
679  },
680  'roundStage' => $initStage,
681  'ownerId' => $owner,
682  'criticalSectionProvider' => $this->csProvider
683  ];
684  }
685 
689  protected function initLoadBalancer( ILoadBalancer $lb ) {
690  if ( $this->trxRoundId !== false ) {
691  $lb->beginPrimaryChanges( $this->trxRoundId, $this->id ); // set DBO_TRX
692  }
693 
694  $lb->setTableAliases( $this->tableAliases );
695  $lb->setIndexAliases( $this->indexAliases );
696  $lb->setDomainAliases( $this->domainAliases );
697  }
698 
699  public function setTableAliases( array $aliases ) {
700  $this->tableAliases = $aliases;
701  }
702 
703  public function setIndexAliases( array $aliases ) {
704  $this->indexAliases = $aliases;
705  }
706 
707  public function setDomainAliases( array $aliases ) {
708  $this->domainAliases = $aliases;
709  }
710 
712  return $this->trxProfiler;
713  }
714 
715  public function setLocalDomainPrefix( $prefix ) {
716  $this->localDomain = new DatabaseDomain(
717  $this->localDomain->getDatabase(),
718  $this->localDomain->getSchema(),
719  $prefix
720  );
721 
722  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( $prefix ) {
723  $lb->setLocalDomainPrefix( $prefix );
724  } );
725  }
726 
727  public function redefineLocalDomain( $domain ) {
728  $this->closeAll();
729 
730  $this->localDomain = DatabaseDomain::newFromId( $domain );
731 
732  $this->forEachLB( function ( ILoadBalancer $lb ) {
733  $lb->redefineLocalDomain( $this->localDomain );
734  } );
735  }
736 
737  public function closeAll() {
739  $scope = ScopedCallback::newScopedIgnoreUserAbort();
740 
741  $this->forEachLBCallMethod( 'closeAll', [ __METHOD__, $this->id ] );
742  }
743 
744  public function setAgentName( $agent ) {
745  $this->agent = $agent;
746  }
747 
748  public function appendShutdownCPIndexAsQuery( $url, $index ) {
749  $usedCluster = 0;
750  $this->forEachLB( static function ( ILoadBalancer $lb ) use ( &$usedCluster ) {
751  $usedCluster |= $lb->hasStreamingReplicaServers();
752  } );
753 
754  if ( !$usedCluster ) {
755  return $url; // no primary/replica clusters touched
756  }
757 
758  return strpos( $url, '?' ) === false ? "$url?cpPosIndex=$index" : "$url&cpPosIndex=$index";
759  }
760 
761  public function getChronologyProtectorClientId() {
762  return $this->getChronologyProtector()->getClientId();
763  }
764 
774  public static function makeCookieValueFromCPIndex(
775  int $writeIndex,
776  int $time,
777  string $clientId
778  ) {
779  // Format is "<write index>@<write timestamp>#<client ID hash>"
780  return "{$writeIndex}@{$time}#{$clientId}";
781  }
782 
791  public static function getCPInfoFromCookieValue( ?string $value, int $minTimestamp ) {
792  static $placeholder = [ 'index' => null, 'clientId' => null ];
793 
794  if ( $value === null ) {
795  return $placeholder; // not set
796  }
797 
798  // Format is "<write index>@<write timestamp>#<client ID hash>"
799  if ( !preg_match( '/^(\d+)@(\d+)#([0-9a-f]{32})$/', $value, $m ) ) {
800  return $placeholder; // invalid
801  }
802 
803  $index = (int)$m[1];
804  if ( $index <= 0 ) {
805  return $placeholder; // invalid
806  } elseif ( isset( $m[2] ) && $m[2] !== '' && (int)$m[2] < $minTimestamp ) {
807  return $placeholder; // expired
808  }
809 
810  $clientId = ( isset( $m[3] ) && $m[3] !== '' ) ? $m[3] : null;
811 
812  return [ 'index' => $index, 'clientId' => $clientId ];
813  }
814 
815  public function setRequestInfo( array $info ) {
816  if ( $this->chronProt ) {
817  throw new LogicException( 'ChronologyProtector already initialized' );
818  }
819 
820  $this->requestInfo = $info + $this->requestInfo;
821  }
822 
823  public function setDefaultReplicationWaitTimeout( $seconds ) {
825  $this->replicationWaitTimeout = max( 1, (int)$seconds );
826 
827  return $old;
828  }
829 
834  final protected function getOwnershipId() {
835  return $this->id;
836  }
837 
841  private function assertTransactionRoundStage( $stage ) {
842  if ( $this->trxRoundStage !== $stage ) {
843  throw new DBTransactionError(
844  null,
845  "Transaction round stage must be '$stage' (not '{$this->trxRoundStage}')"
846  );
847  }
848  }
849 
850  public function __destruct() {
851  $this->destroy();
852  }
853 
858  public function setMockTime( &$time ) {
859  $this->getChronologyProtector()->setMockTime( $time );
860  }
861 }
Wikimedia\Rdbms\LBFactory\$cpStash
BagOStuff $cpStash
Definition: LBFactory.php:68
Wikimedia\Rdbms\LBFactory\hasPrimaryChanges
hasPrimaryChanges()
Determine if any primary connection has pending changes.
Definition: LBFactory.php:407
Wikimedia\Rdbms\ILoadBalancer\STAGE_POSTCOMMIT_CALLBACKS
const STAGE_POSTCOMMIT_CALLBACKS
Manager of ILoadBalancer instances is running post-commit callbacks.
Definition: ILoadBalancer.php:113
Wikimedia\Rdbms\LBFactory\getLocalDomainID
getLocalDomainID()
Get the local (and default) database domain ID of connection handles.
Definition: LBFactory.php:184
Wikimedia\Rdbms\LBFactory\appendShutdownCPIndexAsQuery
appendShutdownCPIndexAsQuery( $url, $index)
Append ?cpPosIndex parameter to a URL for ChronologyProtector purposes if needed.
Definition: LBFactory.php:748
Wikimedia\Rdbms\LBFactory\getTransactionProfiler
getTransactionProfiler()
Get the TransactionProfiler used by this instance.
Definition: LBFactory.php:711
Wikimedia\Rdbms\LBFactory\$replLogger
LoggerInterface $replLogger
Definition: LBFactory.php:55
Wikimedia\Rdbms\LBFactory\$replicationWaitTimeout
int $replicationWaitTimeout
Default replication wait timeout.
Definition: LBFactory.php:104
Wikimedia\Rdbms\DatabaseDomain\newFromId
static newFromId( $domain)
Definition: DatabaseDomain.php:77
Wikimedia\Rdbms\LBFactory\$errorLogger
callable $errorLogger
Error logger.
Definition: LBFactory.php:63
Wikimedia\Rdbms\ILoadBalancer\waitForAll
waitForAll( $pos, $timeout=null)
Set the primary wait position and wait for ALL replica DBs to catch up to it.
Wikimedia\Rdbms\LBFactory\setLocalDomainPrefix
setLocalDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
Definition: LBFactory.php:715
EmptyBagOStuff
A BagOStuff object with no objects in it.
Definition: EmptyBagOStuff.php:29
Wikimedia\Rdbms\ILoadBalancer\redefineLocalDomain
redefineLocalDomain( $domain)
Close all connection and redefine the local domain for testing or schema creation.
Wikimedia\Rdbms\LBFactory\$domainAliases
DatabaseDomain[] string[] $domainAliases
Map of (domain alias => DB domain)
Definition: LBFactory.php:91
Wikimedia\Rdbms\ILoadBalancer\setIndexAliases
setIndexAliases(array $aliases)
Convert certain index names to alternative names before querying the DB.
Wikimedia\Rdbms\LBFactory\$cliMode
bool $cliMode
Whether this PHP instance is for a CLI script.
Definition: LBFactory.php:80
Wikimedia\Rdbms\LBFactory\isReadyForRoundOperations
isReadyForRoundOperations()
Check if transaction rounds can be started, committed, or rolled back right now.
Definition: LBFactory.php:380
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:91
Wikimedia\Rdbms\LBFactory\setMockTime
setMockTime(&$time)
Definition: LBFactory.php:858
Wikimedia\Rdbms\LBFactory\$wanCache
WANObjectCache $wanCache
Definition: LBFactory.php:72
Wikimedia\Rdbms\LBFactory\__destruct
__destruct()
Definition: LBFactory.php:850
Wikimedia\Rdbms\LBFactory\$connLogger
LoggerInterface $connLogger
Definition: LBFactory.php:57
Wikimedia\Rdbms\LBFactory\commitAndWaitForReplication
commitAndWaitForReplication( $fname, $ticket, array $opts=[])
Call commitPrimaryChanges() and waitForReplication() if $ticket indicates it is safe.
Definition: LBFactory.php:533
Wikimedia\Rdbms\LBFactory\$secret
string $secret
Secret string for HMAC hashing.
Definition: LBFactory.php:84
Wikimedia\Rdbms\LBFactory\setDefaultReplicationWaitTimeout
setDefaultReplicationWaitTimeout( $seconds)
Set the default timeout for replication wait checks.
Definition: LBFactory.php:823
Wikimedia\Rdbms\ILoadBalancer\pendingPrimaryChangeCallers
pendingPrimaryChangeCallers()
Get the list of callers that have pending primary changes.
Wikimedia\Rdbms\LBFactory\$defaultGroup
string null $defaultGroup
Definition: LBFactory.php:110
Wikimedia\Rdbms\LBFactory\initLoadBalancer
initLoadBalancer(ILoadBalancer $lb)
Definition: LBFactory.php:689
Wikimedia\Rdbms\ILoadBalancer\hasPrimaryChanges
hasPrimaryChanges()
Whether there are pending changes or callbacks in a transaction by this thread.
Wikimedia\Rdbms\LBFactory\resolveDomainID
resolveDomainID( $domain)
Definition: LBFactory.php:188
Wikimedia\Rdbms\LBFactory\getOwnershipId
getOwnershipId()
Definition: LBFactory.php:834
Wikimedia\Rdbms\LBFactory\getChronologyProtector
getChronologyProtector()
Definition: LBFactory.php:574
Wikimedia\Rdbms\LBFactory\commitPrimaryChanges
commitPrimaryChanges( $fname=__METHOD__, array $options=[])
Commit changes and clear view snapshots on all primary connections.
Definition: LBFactory.php:294
Wikimedia\Rdbms
Definition: ChronologyProtector.php:24
Wikimedia\Rdbms\LBFactory\forEachLBCallMethod
forEachLBCallMethod( $methodName, array $args=[])
Call a method on each tracked (instantiated) load balancer instance.
Definition: LBFactory.php:246
Wikimedia\Rdbms\ILBFactory\forEachLB
forEachLB( $callback, array $params=[])
Execute a function for each instantiated tracked load balancer instance.
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:86
Wikimedia\Rdbms\LBFactory\resolveDomainInstance
resolveDomainInstance( $domain)
Definition: LBFactory.php:196
Wikimedia\Rdbms\LBFactory\flushReplicaSnapshots
flushReplicaSnapshots( $fname=__METHOD__)
Commit all replica DB transactions so as to flush any REPEATABLE-READ or SSI snapshot.
Definition: LBFactory.php:255
Wikimedia\Rdbms\LBFactory\$loggerFields
static $loggerFields
Definition: LBFactory.php:125
Wikimedia\Rdbms\ILoadBalancer\setLocalDomainPrefix
setLocalDomainPrefix( $prefix)
Set a new table prefix for the existing local domain ID for testing.
Wikimedia\Rdbms\ILBFactory\getMainLB
getMainLB( $domain=false)
Get the tracked load balancer instance for a main cluster.
Wikimedia\Rdbms\LBFactory\__construct
__construct(array $conf)
Construct a manager of ILoadBalancer instances.
Definition: LBFactory.php:128
Wikimedia\Rdbms\LBFactory\executePostTransactionCallbacks
executePostTransactionCallbacks()
Definition: LBFactory.php:357
Wikimedia\Rdbms\LBFactory\waitForReplication
waitForReplication(array $opts=[])
Waits for the replica DBs to catch up to the current primary position.
Definition: LBFactory.php:443
Wikimedia\Rdbms\LBFactory\setTableAliases
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
Definition: LBFactory.php:699
Wikimedia\Rdbms\ILoadBalancer\setTableAliases
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
Wikimedia\Rdbms\LBFactory\commitMasterChanges
commitMasterChanges( $fname=__METHOD__, array $options=[])
Definition: LBFactory.php:330
Wikimedia\Rdbms\LBFactory\rollbackPrimaryChanges
rollbackPrimaryChanges( $fname=__METHOD__)
Rollback changes on all primary connections.
Definition: LBFactory.php:335
Wikimedia\Rdbms\ChronologyProtector\persistSessionReplicationPositions
persistSessionReplicationPositions(&$clientPosIndex=null)
Persist any staged client "session consistency" replication positions.
Definition: ChronologyProtector.php:321
Wikimedia\Rdbms\LBFactory\closeAll
closeAll()
Close all connections on instantiated tracked load balancer instances.
Definition: LBFactory.php:737
Wikimedia\Rdbms\LBFactory\makeCookieValueFromCPIndex
static makeCookieValueFromCPIndex(int $writeIndex, int $time, string $clientId)
Build a string conveying the client and write index of the chronology protector data.
Definition: LBFactory.php:774
Wikimedia\Rdbms\DatabaseDomain\newUnspecified
static newUnspecified()
Definition: DatabaseDomain.php:118
WANObjectCache\newEmpty
static newEmpty()
Get an instance that wraps EmptyBagOStuff.
Definition: WANObjectCache.php:388
Wikimedia\Rdbms\LBFactory\hasOrMadeRecentPrimaryChanges
hasOrMadeRecentPrimaryChanges( $age=null)
Determine if any primary connection has pending/written changes from this request.
Definition: LBFactory.php:430
Wikimedia\Rdbms\LBFactory\$deprecationLogger
callable $deprecationLogger
Deprecation logger.
Definition: LBFactory.php:65
Wikimedia\Rdbms\LBFactory\$id
$id
var int An identifier for this class instance
Definition: LBFactory.php:96
Wikimedia\Rdbms\LBFactory\$srvCache
BagOStuff $srvCache
Definition: LBFactory.php:70
Wikimedia\Rdbms\ILoadBalancer\getServerName
getServerName( $i)
Get the readable name of the server with the specified index.
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Definition: GlobalFunctions.php:997
Wikimedia\Rdbms\LBFactory\$nonLocalDomainCache
DatabaseDomain[] $nonLocalDomainCache
Map of (domain ID => domain instance)
Definition: LBFactory.php:116
Wikimedia\Rdbms\ILoadBalancer\runPrimaryTransactionListenerCallbacks
runPrimaryTransactionListenerCallbacks( $fname=__METHOD__, $owner=null)
Run all recurring post-COMMIT/ROLLBACK listener callbacks.
Wikimedia\Rdbms\LBFactory\$queryLogger
LoggerInterface $queryLogger
Definition: LBFactory.php:59
Wikimedia\Rdbms\ILBFactory\getExternalLB
getExternalLB( $cluster)
Get the tracked load balancer instance for an external cluster.
Wikimedia\Rdbms\LBFactory\$readOnlyReason
string bool $readOnlyReason
Reason all LBs are read-only or false if not.
Definition: LBFactory.php:107
Wikimedia\Rdbms\LBFactory\ROUND_COMMIT_CALLBACKS
const ROUND_COMMIT_CALLBACKS
Definition: LBFactory.php:122
$args
if( $line===false) $args
Definition: mcc.php:124
Wikimedia\Rdbms\ILoadBalancer\getWriterIndex
getWriterIndex()
Get the specific server index of the primary server.
Wikimedia\Rdbms\LBFactory\baseLoadBalancerParams
baseLoadBalancerParams( $owner)
Get parameters to ILoadBalancer::__construct()
Definition: LBFactory.php:649
Wikimedia\Rdbms\ILoadBalancer\setDomainAliases
setDomainAliases(array $aliases)
Convert certain database domains to alternative ones.
Wikimedia\Rdbms\LBFactory\redefineLocalDomain
redefineLocalDomain( $domain)
Close all connections and redefine the local domain for testing or schema creation.
Definition: LBFactory.php:727
Wikimedia\Rdbms\ILoadBalancer\hasOrMadeRecentPrimaryChanges
hasOrMadeRecentPrimaryChanges( $age=null)
Check if this load balancer object had any recent or still pending writes issued against it by this P...
Wikimedia\Rdbms\LBFactory\$requestInfo
array $requestInfo
Web request information about the client.
Definition: LBFactory.php:78
Wikimedia\Rdbms\LBFactory\hasMasterChanges
hasMasterChanges()
Definition: LBFactory.php:416
Wikimedia\Rdbms\LBFactory\$indexAliases
string[] $indexAliases
Map of (index alias => index)
Definition: LBFactory.php:89
Wikimedia\Rdbms\ChronologyProtector\getClientId
getClientId()
Definition: ChronologyProtector.php:228
Wikimedia\Rdbms\LBFactory\$localDomain
DatabaseDomain $localDomain
Local domain.
Definition: LBFactory.php:75
Wikimedia\Rdbms\LBFactory\laggedReplicaUsed
laggedReplicaUsed()
Detemine if any lagged replica DB connection was used.
Definition: LBFactory.php:421
Wikimedia\Rdbms\LBFactory\ROUND_COMMITTING
const ROUND_COMMITTING
Definition: LBFactory.php:120
Wikimedia\Rdbms\LBFactory\hasOrMadeRecentMasterChanges
hasOrMadeRecentMasterChanges( $age=null)
Definition: LBFactory.php:438
Wikimedia\Rdbms\LBFactory\commitAll
commitAll( $fname=__METHOD__, array $options=[])
Commit open transactions on all connections.
Definition: LBFactory.php:265
Wikimedia\Rdbms\LBFactory\getEmptyTransactionTicket
getEmptyTransactionTicket( $fname)
Get a token asserting that no transaction writes are active on tracked load balancers.
Definition: LBFactory.php:520
Wikimedia\Rdbms\LBFactory\$replicationWaitCallbacks
callable[] $replicationWaitCallbacks
Definition: LBFactory.php:93
Wikimedia\Rdbms\LBFactory\ROUND_ROLLING_BACK
const ROUND_ROLLING_BACK
Definition: LBFactory.php:121
Wikimedia\Rdbms\LBFactory\$tableAliases
array[] $tableAliases
$aliases Map of (table => (dbname, schema, prefix) map)
Definition: LBFactory.php:87
Wikimedia\Rdbms\ChronologyProtector\stageSessionReplicationPosition
stageSessionReplicationPosition(ILoadBalancer $lb)
Update client "session consistency" replication position for an end-of-life ILoadBalancer.
Definition: ChronologyProtector.php:289
Wikimedia\Rdbms\LBFactory\$profiler
callable null $profiler
An optional callback that returns a ScopedCallback instance, meant to profile the actual query execut...
Definition: LBFactory.php:51
Wikimedia\Rdbms\LBFactory\$maxLag
int null $maxLag
Definition: LBFactory.php:113
Wikimedia\Rdbms\LBFactory\setAgentName
setAgentName( $agent)
Definition: LBFactory.php:744
WANObjectCache
Multi-datacenter aware caching interface.
Definition: WANObjectCache.php:131
Wikimedia\Rdbms\ILoadBalancer\laggedReplicaUsed
laggedReplicaUsed()
Checks whether the database for generic connections this request was both:
Wikimedia\Rdbms\LBFactory\hasTransactionRound
hasTransactionRound()
Check if an explicit transaction round is active.
Definition: LBFactory.php:376
Wikimedia\Rdbms\LBFactory\ROUND_BEGINNING
const ROUND_BEGINNING
Definition: LBFactory.php:119
Wikimedia\Rdbms\LBFactory\$csProvider
CriticalSectionProvider null $csProvider
Definition: LBFactory.php:46
Wikimedia\Rdbms\LBFactory\beginMasterChanges
beginMasterChanges( $fname=__METHOD__)
Definition: LBFactory.php:289
Wikimedia\Rdbms\DBTransactionError
@newable
Definition: DBTransactionError.php:29
Wikimedia\Rdbms\LBFactory\destroy
destroy()
Close all connections and make further attempts to open connections result in DBAccessError.
Definition: LBFactory.php:177
Wikimedia\Rdbms\LBFactory\rollbackMasterChanges
rollbackMasterChanges( $fname=__METHOD__)
Definition: LBFactory.php:349
Wikimedia\Rdbms\ChronologyProtector
Provide a given client with protection against visible database lag.
Definition: ChronologyProtector.php:136
Wikimedia\Rdbms\LBFactory\$ticket
int null $ticket
Ticket used to delegate transaction ownership.
Definition: LBFactory.php:98
Wikimedia\Rdbms\LBFactory\disableChronologyProtection
disableChronologyProtection()
Disable the ChronologyProtector on all instantiated tracked load balancer instances.
Definition: LBFactory.php:567
Wikimedia\Rdbms\LBFactory
An interface for generating database load balancers.
Definition: LBFactory.php:42
Wikimedia\Rdbms\LBFactory\getCPInfoFromCookieValue
static getCPInfoFromCookieValue(?string $value, int $minTimestamp)
Parse a string conveying the client and write index of the chronology protector data.
Definition: LBFactory.php:791
Wikimedia\Rdbms\LBFactory\$perfLogger
LoggerInterface $perfLogger
Definition: LBFactory.php:61
Wikimedia\Rdbms\ILoadBalancer\hasStreamingReplicaServers
hasStreamingReplicaServers()
Whether any replica servers use streaming replication from the primary server.
Wikimedia\Rdbms\ILoadBalancer\finalizePrimaryChanges
finalizePrimaryChanges( $fname=__METHOD__, $owner=null)
Run pre-commit callbacks and defer execution of post-commit callbacks.
Wikimedia\Rdbms\ILoadBalancer\runPrimaryTransactionIdleCallbacks
runPrimaryTransactionIdleCallbacks( $fname=__METHOD__, $owner=null)
Consume and run all pending post-COMMIT/ROLLBACK callbacks and commit dangling transactions.
Wikimedia\Rdbms\LBFactory\$trxRoundStage
string $trxRoundStage
One of the ROUND_* class constants.
Definition: LBFactory.php:102
Wikimedia\Rdbms\LBFactory\$trxProfiler
TransactionProfiler $trxProfiler
Definition: LBFactory.php:53
Wikimedia\Rdbms\LBFactory\ROUND_CURSORY
const ROUND_CURSORY
Definition: LBFactory.php:118
Wikimedia\Rdbms\LBFactory\$trxRoundId
string bool $trxRoundId
String if a requested DBO_TRX transaction round is active.
Definition: LBFactory.php:100
Wikimedia\Rdbms\LBFactory\assertTransactionRoundStage
assertTransactionRoundStage( $stage)
Definition: LBFactory.php:841
Wikimedia\Rdbms\LBFactory\setIndexAliases
setIndexAliases(array $aliases)
Convert certain index names to alternative names before querying the DB.
Definition: LBFactory.php:703
Wikimedia\Rdbms\LBFactory\shutdownChronologyProtector
shutdownChronologyProtector(ChronologyProtector $cp, $workCallback, &$cpIndex=null)
Get and record all of the staged DB positions into persistent memory storage.
Definition: LBFactory.php:618
Wikimedia\Rdbms\LBFactory\logIfMultiDbTransaction
logIfMultiDbTransaction()
Log query info if multi DB transactions are going to be committed now.
Definition: LBFactory.php:387
Wikimedia\Rdbms\LBFactory\shutdown
shutdown( $flags=self::SHUTDOWN_NORMAL, callable $workCallback=null, &$cpIndex=null, &$cpClientId=null)
Prepare all instantiated tracked load balancer instances for shutdown.
Definition: LBFactory.php:219
Wikimedia\Rdbms\LBFactory\$chronProt
ChronologyProtector $chronProt
Definition: LBFactory.php:44
Wikimedia\Rdbms\ILoadBalancer\beginPrimaryChanges
beginPrimaryChanges( $fname=__METHOD__, $owner=null)
Flush any primary transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
Wikimedia\Rdbms\LBFactory\getChronologyProtectorClientId
getChronologyProtectorClientId()
Get the client ID of the ChronologyProtector instance.
Definition: LBFactory.php:761
Wikimedia\Rdbms\LBFactory\getChronologyProtectorTouched
getChronologyProtectorTouched( $domain=false)
Get the UNIX timestamp when the client last touched the DB, if they did so recently.
Definition: LBFactory.php:563
Wikimedia\Rdbms\DatabaseDomain
Class to handle database/schema/prefix specifications for IDatabase.
Definition: DatabaseDomain.php:40
Wikimedia\Rdbms\TransactionProfiler
Detect high-contention DB queries via profiling calls.
Definition: TransactionProfiler.php:40
Wikimedia\Rdbms\ILoadBalancer\STAGE_POSTROLLBACK_CALLBACKS
const STAGE_POSTROLLBACK_CALLBACKS
Manager of ILoadBalancer instances is running post-rollback callbacks.
Definition: ILoadBalancer.php:115
Wikimedia\Rdbms\LBFactory\setDomainAliases
setDomainAliases(array $aliases)
Convert certain database domains to alternative ones.
Definition: LBFactory.php:707
Wikimedia\Rdbms\LBFactory\$agent
string $agent
Agent name for query profiling.
Definition: LBFactory.php:82
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
Wikimedia\Rdbms\LBFactory\ROUND_ROLLBACK_CALLBACKS
const ROUND_ROLLBACK_CALLBACKS
Definition: LBFactory.php:123
Wikimedia\Rdbms\LBFactory\setWaitForReplicationListener
setWaitForReplicationListener( $name, callable $callback=null)
Add a callback to be run in every call to waitForReplication() before waiting.
Definition: LBFactory.php:512
Wikimedia\Rdbms\ILBFactory
An interface for generating database load balancers.
Definition: ILBFactory.php:33
Wikimedia\Rdbms\LBFactory\beginPrimaryChanges
beginPrimaryChanges( $fname=__METHOD__)
Flush any primary transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
Definition: LBFactory.php:271
Wikimedia\Rdbms\LBFactory\setRequestInfo
setRequestInfo(array $info)
Inject HTTP request header/cookie information during setup of this instance.
Definition: LBFactory.php:815