Avoid "Incorrect user-level lock name " errors in Database lock() method
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 16 Dec 2015 05:34:52 +0000 (21:34 -0800)
committerKrinkle <krinklemail@gmail.com>
Wed, 16 Dec 2015 16:00:46 +0000 (16:00 +0000)
Use a sha1 hash if the lock name exceeds the MySQL limit. The class
for Postgres already avoids this problem with number hashes.

Change-Id: If587c672b4ff210ee3b512bbe2910ae247079d3f

includes/db/DatabaseMysqlBase.php

index ca568ad..b36de98 100644 (file)
@@ -845,7 +845,7 @@ abstract class DatabaseMysqlBase extends Database {
         * @since 1.20
         */
        public function lockIsFree( $lockName, $method ) {
-               $lockName = $this->addQuotes( $lockName );
+               $lockName = $this->addQuotes( $this->makeLockName( $lockName ) );
                $result = $this->query( "SELECT IS_FREE_LOCK($lockName) AS lockstatus", $method );
                $row = $this->fetchObject( $result );
 
@@ -859,7 +859,7 @@ abstract class DatabaseMysqlBase extends Database {
         * @return bool
         */
        public function lock( $lockName, $method, $timeout = 5 ) {
-               $lockName = $this->addQuotes( $lockName );
+               $lockName = $this->addQuotes( $this->makeLockName( $lockName ) );
                $result = $this->query( "SELECT GET_LOCK($lockName, $timeout) AS lockstatus", $method );
                $row = $this->fetchObject( $result );
 
@@ -880,13 +880,19 @@ abstract class DatabaseMysqlBase extends Database {
         * @return bool
         */
        public function unlock( $lockName, $method ) {
-               $lockName = $this->addQuotes( $lockName );
+               $lockName = $this->addQuotes( $this->makeLockName( $lockName ) );
                $result = $this->query( "SELECT RELEASE_LOCK($lockName) as lockstatus", $method );
                $row = $this->fetchObject( $result );
 
                return ( $row->lockstatus == 1 );
        }
 
+       private function makeLockName( $lockName ) {
+               // http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock
+               // Newer version enforce a 64 char length limit.
+               return ( strlen( $lockName ) > 64 ) ? sha1( $lockName ) : $lockName;
+       }
+
        public function namedLocksEnqueue() {
                return true;
        }