MediaWiki  1.34.0
DBLockManager.php
Go to the documentation of this file.
1 <?php
27 
42 abstract class DBLockManager extends QuorumLockManager {
44  protected $dbServers; // (DB name => server config array)
46  protected $statusCache;
47 
48  protected $lockExpiry; // integer number of seconds
49  protected $safeDelay; // integer number of seconds
51  protected $conns = [];
52 
73  public function __construct( array $config ) {
74  parent::__construct( $config );
75 
76  $this->dbServers = $config['dbServers'];
77  // Sanitize srvsByBucket config to prevent PHP errors
78  $this->srvsByBucket = array_filter( $config['dbsByBucket'], 'is_array' );
79  $this->srvsByBucket = array_values( $this->srvsByBucket ); // consecutive
80 
81  if ( isset( $config['lockExpiry'] ) ) {
82  $this->lockExpiry = $config['lockExpiry'];
83  } else {
84  $met = ini_get( 'max_execution_time' );
85  $this->lockExpiry = $met ?: 60; // use some sane amount if 0
86  }
87  $this->safeDelay = ( $this->lockExpiry <= 0 )
88  ? 60 // pick a safe-ish number to match DB timeout default
89  : $this->lockExpiry; // cover worst case
90 
91  // Tracks peers that couldn't be queried recently to avoid lengthy
92  // connection timeouts. This is useless if each bucket has one peer.
93  $this->statusCache = $config['srvCache'] ?? new HashBagOStuff();
94  }
95 
102  protected function getLocksOnServer( $lockSrv, array $pathsByType ) {
104  foreach ( $pathsByType as $type => $paths ) {
105  $status->merge( $this->doGetLocksOnServer( $lockSrv, $paths, $type ) );
106  }
107 
108  return $status;
109  }
110 
111  abstract protected function doGetLocksOnServer( $lockSrv, array $paths, $type );
112 
113  protected function freeLocksOnServer( $lockSrv, array $pathsByType ) {
114  return StatusValue::newGood();
115  }
116 
122  protected function isServerUp( $lockSrv ) {
123  if ( !$this->cacheCheckFailures( $lockSrv ) ) {
124  return false; // recent failure to connect
125  }
126  try {
127  $this->getConnection( $lockSrv );
128  } catch ( DBError $e ) {
129  $this->cacheRecordFailure( $lockSrv );
130 
131  return false; // failed to connect
132  }
133 
134  return true;
135  }
136 
145  protected function getConnection( $lockDb ) {
146  if ( !isset( $this->conns[$lockDb] ) ) {
147  if ( $this->dbServers[$lockDb] instanceof IDatabase ) {
148  // Direct injected connection hande for $lockDB
149  $db = $this->dbServers[$lockDb];
150  } elseif ( is_array( $this->dbServers[$lockDb] ) ) {
151  // Parameters to construct a new database connection
152  $config = $this->dbServers[$lockDb];
153  $config['flags'] = ( $config['flags'] ?? 0 );
154  $config['flags'] &= ~( IDatabase::DBO_TRX | IDatabase::DBO_DEFAULT );
155  $db = Database::factory( $config['type'], $config );
156  } else {
157  throw new UnexpectedValueException( "No server called '$lockDb'." );
158  }
159  # If the connection drops, try to avoid letting the DB rollback
160  # and release the locks before the file operations are finished.
161  # This won't handle the case of DB server restarts however.
162  $options = [];
163  if ( $this->lockExpiry > 0 ) {
164  $options['connTimeout'] = $this->lockExpiry;
165  }
166  $db->setSessionOptions( $options );
167  $this->initConnection( $lockDb, $db );
168 
169  $this->conns[$lockDb] = $db;
170  }
171 
172  return $this->conns[$lockDb];
173  }
174 
182  protected function initConnection( $lockDb, IDatabase $db ) {
183  }
184 
192  protected function cacheCheckFailures( $lockDb ) {
193  return ( $this->safeDelay > 0 )
194  ? !$this->statusCache->get( $this->getMissKey( $lockDb ) )
195  : true;
196  }
197 
204  protected function cacheRecordFailure( $lockDb ) {
205  return ( $this->safeDelay > 0 )
206  ? $this->statusCache->set( $this->getMissKey( $lockDb ), 1, $this->safeDelay )
207  : true;
208  }
209 
216  protected function getMissKey( $lockDb ) {
217  return 'dblockmanager:downservers:' . str_replace( ' ', '_', $lockDb );
218  }
219 
223  function __destruct() {
224  $this->releaseAllLocks();
225  foreach ( $this->conns as $db ) {
226  $db->close();
227  }
228  }
229 }
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:49
HashBagOStuff
Simple store for keeping values in an associative array for the current process.
Definition: HashBagOStuff.php:31
DBLockManager\isServerUp
isServerUp( $lockSrv)
Definition: DBLockManager.php:122
DBLockManager\cacheRecordFailure
cacheRecordFailure( $lockDb)
Log a lock request failure to the cache.
Definition: DBLockManager.php:204
DBLockManager\__construct
__construct(array $config)
Construct a new instance from configuration.
Definition: DBLockManager.php:73
DBLockManager\getLocksOnServer
getLocksOnServer( $lockSrv, array $pathsByType)
Definition: DBLockManager.php:102
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:63
DBLockManager\$safeDelay
$safeDelay
Definition: DBLockManager.php:49
Wikimedia\Rdbms\DBError
Database error base class.
Definition: DBError.php:30
DBO_TRX
const DBO_TRX
Definition: defines.php:12
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
DBLockManager\cacheCheckFailures
cacheCheckFailures( $lockDb)
Checks if the DB has not recently had connection/query errors.
Definition: DBLockManager.php:192
QuorumLockManager
Version of LockManager that uses a quorum from peer servers for locks.
Definition: QuorumLockManager.php:31
QuorumLockManager\releaseAllLocks
releaseAllLocks()
Release all locks that this session is holding.
DBLockManager\getMissKey
getMissKey( $lockDb)
Get a cache key for recent query misses for a DB.
Definition: DBLockManager.php:216
DBLockManager\doGetLocksOnServer
doGetLocksOnServer( $lockSrv, array $paths, $type)
DBLockManager\initConnection
initConnection( $lockDb, IDatabase $db)
Do additional initialization for new lock DB connection.
Definition: DBLockManager.php:182
DBLockManager\$dbServers
array[] IDatabase[] $dbServers
Map of (DB names => server config or IDatabase)
Definition: DBLockManager.php:44
DBLockManager\$conns
IDatabase[] $conns
Map Database connections (DB name => Database)
Definition: DBLockManager.php:51
DBLockManager\__destruct
__destruct()
Make sure remaining locks get cleared for sanity.
Definition: DBLockManager.php:223
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
DBLockManager\$lockExpiry
$lockExpiry
Definition: DBLockManager.php:48
DBLockManager\$statusCache
BagOStuff $statusCache
Definition: DBLockManager.php:46
$status
return $status
Definition: SyntaxHighlight.php:347
DBLockManager\getConnection
getConnection( $lockDb)
Get (or reuse) a connection to a lock DB.
Definition: DBLockManager.php:145
DBLockManager
Version of LockManager based on using named/row DB locks.
Definition: DBLockManager.php:42
DBO_DEFAULT
const DBO_DEFAULT
Definition: defines.php:13
DBLockManager\freeLocksOnServer
freeLocksOnServer( $lockSrv, array $pathsByType)
Get a connection to a lock server and release locks on $paths.
Definition: DBLockManager.php:113
$type
$type
Definition: testCompression.php:48