This was originally a global search and replace. I manually checked all replacements and reverted them if (due to the lack of type hints) either null (that would be 0 when counted) or a Countable object can end in the variable or property in question. Now this patch only touches places where I'm sure nothing can break. For the sanity of the honorable reviewers this patch is exclusively touching negated counts. You should not find a single `!== []` in this patch, that would be a mistake. Change-Id: I5eafd4d8fccdb53a668be8e6f25a566f9c3a0a95
82 lines
2.3 KiB
PHP
82 lines
2.3 KiB
PHP
<?php
|
|
|
|
use Wikimedia\Rdbms\DBError;
|
|
|
|
/**
|
|
* PostgreSQL version of DBLockManager that supports shared locks.
|
|
* All locks are non-blocking, which avoids deadlocks.
|
|
*
|
|
* @ingroup LockManager
|
|
*/
|
|
class PostgreSqlLockManager extends DBLockManager {
|
|
/** @var array Mapping of lock types to the type actually used */
|
|
protected $lockTypeMap = [
|
|
self::LOCK_SH => self::LOCK_SH,
|
|
self::LOCK_UW => self::LOCK_SH,
|
|
self::LOCK_EX => self::LOCK_EX
|
|
];
|
|
|
|
protected function doGetLocksOnServer( $lockSrv, array $paths, $type ) {
|
|
$status = StatusValue::newGood();
|
|
if ( $paths === [] ) {
|
|
return $status; // nothing to lock
|
|
}
|
|
|
|
$db = $this->getConnection( $lockSrv ); // checked in isServerUp()
|
|
$bigints = array_unique( array_map(
|
|
function ( $key ) {
|
|
return Wikimedia\base_convert( substr( $key, 0, 15 ), 16, 10 );
|
|
},
|
|
array_map( [ $this, 'sha1Base16Absolute' ], $paths )
|
|
) );
|
|
|
|
// Try to acquire all the locks...
|
|
$fields = [];
|
|
foreach ( $bigints as $bigint ) {
|
|
$fields[] = ( $type == self::LOCK_SH )
|
|
? "pg_try_advisory_lock_shared({$db->addQuotes( $bigint )}) AS K$bigint"
|
|
: "pg_try_advisory_lock({$db->addQuotes( $bigint )}) AS K$bigint";
|
|
}
|
|
$res = $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
|
|
$row = $res->fetchRow();
|
|
|
|
if ( in_array( 'f', $row ) ) {
|
|
// Release any acquired locks if some could not be acquired...
|
|
$fields = [];
|
|
foreach ( $row as $kbigint => $ok ) {
|
|
if ( $ok === 't' ) { // locked
|
|
$bigint = substr( $kbigint, 1 ); // strip off the "K"
|
|
$fields[] = ( $type == self::LOCK_SH )
|
|
? "pg_advisory_unlock_shared({$db->addQuotes( $bigint )})"
|
|
: "pg_advisory_unlock({$db->addQuotes( $bigint )})";
|
|
}
|
|
}
|
|
if ( count( $fields ) ) {
|
|
$db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
|
|
}
|
|
foreach ( $paths as $path ) {
|
|
$status->fatal( 'lockmanager-fail-acquirelock', $path );
|
|
}
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* @see QuorumLockManager::releaseAllLocks()
|
|
* @return StatusValue
|
|
*/
|
|
protected function releaseAllLocks() {
|
|
$status = StatusValue::newGood();
|
|
|
|
foreach ( $this->conns as $lockDb => $db ) {
|
|
try {
|
|
$db->query( "SELECT pg_advisory_unlock_all()", __METHOD__ );
|
|
} catch ( DBError $e ) {
|
|
$status->fatal( 'lockmanager-fail-db-release', $lockDb );
|
|
}
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
}
|