From: Aaron Schulz Date: Fri, 1 Feb 2013 19:42:36 +0000 (-0800) Subject: [Database] Added support for lock/unlock in Postgres. X-Git-Tag: 1.31.0-rc.0~20689 X-Git-Url: http://git.cyclocoop.org//%22%22.url_de_base%28%29.%22/%22?a=commitdiff_plain;h=da85010db35d0090cd47b55ceb96a706312217c5;p=lhc%2Fweb%2Fwiklou.git [Database] Added support for lock/unlock in Postgres. Change-Id: Ie422de58c36f195597eabdd51a27d3ed2c2880cf --- diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index 86b8e8a7bb..5049ecf52e 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -1436,4 +1436,65 @@ SQL; } return parent::streamStatementEnd( $sql, $newLine ); } + + /** + * Check to see if a named lock is available. This is non-blocking. + * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS + * + * @param $lockName String: name of lock to poll + * @param $method String: name of method calling us + * @return Boolean + * @since 1.20 + */ + public function lockIsFree( $lockName, $method ) { + $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) ); + $result = $this->query( "SELECT (CASE(pg_try_advisory_lock($key)) + WHEN 'f' THEN 'f' ELSE pg_advisory_unlock($key) END) AS lockstatus", $method ); + $row = $this->fetchObject( $result ); + return ( $row->lockstatus === 't' ); + } + + /** + * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS + * @param $lockName string + * @param $method string + * @param $timeout int + * @return bool + */ + public function lock( $lockName, $method, $timeout = 5 ) { + $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) ); + for ( $attempts=1; $attempts <= $timeout; ++$attempts ) { + $result = $this->query( + "SELECT pg_try_advisory_lock($key) AS lockstatus", $method ); + $row = $this->fetchObject( $result ); + if ( $row->lockstatus === 't' ) { + return true; + } else { + sleep( 1 ); + } + } + wfDebug( __METHOD__." failed to acquire lock\n" ); + return false; + } + + /** + * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKSFROM PG DOCS: http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS + * @param $lockName string + * @param $method string + * @return bool + */ + public function unlock( $lockName, $method ) { + $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) ); + $result = $this->query( "SELECT pg_advisory_unlock($key) as lockstatus", $method ); + $row = $this->fetchObject( $result ); + return ( $row->lockstatus === 't' ); + } + + /** + * @param string $lockName + * @return string Integer + */ + private function bigintFromLockName( $lockName ) { + return wfBaseConvert( substr( sha1( $lockName ), 0, 15 ), 16, 10 ); + } } // end DatabasePostgres class