3 * PostgreSQL version of DBLockManager that supports shared locks.
4 * All locks are non-blocking, which avoids deadlocks.
8 class PostgreSqlLockManager
extends DBLockManager
{
9 /** @var array Mapping of lock types to the type actually used */
10 protected $lockTypeMap = [
11 self
::LOCK_SH
=> self
::LOCK_SH
,
12 self
::LOCK_UW
=> self
::LOCK_SH
,
13 self
::LOCK_EX
=> self
::LOCK_EX
16 protected function doGetLocksOnServer( $lockSrv, array $paths, $type ) {
17 $status = StatusValue
::newGood();
18 if ( !count( $paths ) ) {
19 return $status; // nothing to lock
22 $db = $this->getConnection( $lockSrv ); // checked in isServerUp()
23 $bigints = array_unique( array_map(
25 return Wikimedia\base_convert
( substr( $key, 0, 15 ), 16, 10 );
27 array_map( [ $this, 'sha1Base16Absolute' ], $paths )
30 // Try to acquire all the locks...
32 foreach ( $bigints as $bigint ) {
33 $fields[] = ( $type == self
::LOCK_SH
)
34 ?
"pg_try_advisory_lock_shared({$db->addQuotes( $bigint )}) AS K$bigint"
35 : "pg_try_advisory_lock({$db->addQuotes( $bigint )}) AS K$bigint";
37 $res = $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__
);
38 $row = $res->fetchRow();
40 if ( in_array( 'f', $row ) ) {
41 // Release any acquired locks if some could not be acquired...
43 foreach ( $row as $kbigint => $ok ) {
44 if ( $ok === 't' ) { // locked
45 $bigint = substr( $kbigint, 1 ); // strip off the "K"
46 $fields[] = ( $type == self
::LOCK_SH
)
47 ?
"pg_advisory_unlock_shared({$db->addQuotes( $bigint )})"
48 : "pg_advisory_unlock({$db->addQuotes( $bigint )})";
51 if ( count( $fields ) ) {
52 $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__
);
54 foreach ( $paths as $path ) {
55 $status->fatal( 'lockmanager-fail-acquirelock', $path );
63 * @see QuorumLockManager::releaseAllLocks()
66 protected function releaseAllLocks() {
67 $status = StatusValue
::newGood();
69 foreach ( $this->conns
as $lockDb => $db ) {
71 $db->query( "SELECT pg_advisory_unlock_all()", __METHOD__
);
72 } catch ( DBError
$e ) {
73 $status->fatal( 'lockmanager-fail-db-release', $lockDb );