MediaWiki  master
PostgreSqlLockManager.php
Go to the documentation of this file.
1 <?php
2 
4 
15  protected $lockTypeMap = [
16  self::LOCK_SH => self::LOCK_SH,
17  self::LOCK_UW => self::LOCK_SH,
18  self::LOCK_EX => self::LOCK_EX
19  ];
20 
21  protected function doGetLocksOnServer( $lockSrv, array $paths, $type ) {
22  $status = StatusValue::newGood();
23  if ( $paths === [] ) {
24  return $status; // nothing to lock
25  }
26 
27  $db = $this->getConnection( $lockSrv ); // checked in isServerUp()
28  $bigints = array_unique( array_map(
29  function ( $key ) {
30  return Wikimedia\base_convert( substr( $key, 0, 15 ), 16, 10 );
31  },
32  array_map( [ $this, 'sha1Base16Absolute' ], $paths )
33  ) );
34 
35  // Try to acquire all the locks...
36  $fields = [];
37  foreach ( $bigints as $bigint ) {
38  $fields[] = ( $type == self::LOCK_SH )
39  ? "pg_try_advisory_lock_shared({$db->addQuotes( $bigint )}) AS K$bigint"
40  : "pg_try_advisory_lock({$db->addQuotes( $bigint )}) AS K$bigint";
41  }
42  $res = $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
43  $row = $res->fetchRow();
44 
45  if ( in_array( 'f', $row ) ) {
46  // Release any acquired locks if some could not be acquired...
47  $fields = [];
48  foreach ( $row as $kbigint => $ok ) {
49  if ( $ok === 't' ) { // locked
50  $bigint = substr( $kbigint, 1 ); // strip off the "K"
51  $fields[] = ( $type == self::LOCK_SH )
52  ? "pg_advisory_unlock_shared({$db->addQuotes( $bigint )})"
53  : "pg_advisory_unlock({$db->addQuotes( $bigint )})";
54  }
55  }
56  if ( count( $fields ) ) {
57  $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
58  }
59  foreach ( $paths as $path ) {
60  $status->fatal( 'lockmanager-fail-acquirelock', $path );
61  }
62  }
63 
64  return $status;
65  }
66 
71  protected function releaseAllLocks() {
72  $status = StatusValue::newGood();
73 
74  foreach ( $this->conns as $lockDb => $db ) {
75  try {
76  $db->query( "SELECT pg_advisory_unlock_all()", __METHOD__ );
77  } catch ( DBError $e ) {
78  $status->fatal( 'lockmanager-fail-db-release', $lockDb );
79  }
80  }
81 
82  return $status;
83  }
84 }
array $lockTypeMap
Mapping of lock types to the type actually used.
Version of LockManager based on using named/row DB locks.
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
doGetLocksOnServer( $lockSrv, array $paths, $type)
getConnection( $lockDb)
Get (or reuse) a connection to a lock DB.
PostgreSQL version of DBLockManager that supports shared locks.
Database error base class.
Definition: DBError.php:30