Merge "Fix assertArrayEquals() calls with bogus 3rd parameter"
[lhc/web/wiklou.git] / includes / objectcache / SqlBagOStuff.php
index a581ac8..66b488e 100644 (file)
@@ -92,7 +92,9 @@ class SqlBagOStuff extends BagOStuff {
         *                  shards-1. The number of digits will be the minimum number
         *                  required to hold the largest shard index. Data will be
         *                  distributed across all tables by key hash. This is for
-        *                  MySQL bugs 61735 and 61736.
+        *                  MySQL bugs 61735 <https://bugs.mysql.com/bug.php?id=61735>
+        *                  and 61736 <https://bugs.mysql.com/bug.php?id=61736>.
+        *
         *   - slaveOnly:   Whether to only use replica DBs and avoid triggering
         *                  garbage collection logic of expired items. This only
         *                  makes sense if the primary DB is used and only if get()
@@ -309,7 +311,7 @@ class SqlBagOStuff extends BagOStuff {
                return $values;
        }
 
-       public function setMulti( array $data, $expiry = 0 ) {
+       public function setMulti( array $data, $expiry = 0, $flags = 0 ) {
                $keysByTable = [];
                foreach ( $data as $key => $value ) {
                        list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
@@ -379,7 +381,7 @@ class SqlBagOStuff extends BagOStuff {
                return $ok;
        }
 
-       protected function cas( $casToken, $key, $value, $exptime = 0 ) {
+       protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
                list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
                $db = null;
                $silenceScope = $this->silenceTransactionProfiler();
@@ -421,7 +423,9 @@ class SqlBagOStuff extends BagOStuff {
                return (bool)$db->affectedRows();
        }
 
-       public function delete( $key ) {
+       public function delete( $key, $flags = 0 ) {
+               $ok = true;
+
                list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
                $db = null;
                $silenceScope = $this->silenceTransactionProfiler();
@@ -433,10 +437,13 @@ class SqlBagOStuff extends BagOStuff {
                                __METHOD__ );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $db, $serverIndex );
-                       return false;
+                       $ok = false;
+               }
+               if ( ( $flags & self::WRITE_SYNC ) == self::WRITE_SYNC ) {
+                       $ok = $this->waitForReplication() && $ok;
                }
 
-               return true;
+               return $ok;
        }
 
        public function incr( $key, $step = 1 ) {
@@ -486,7 +493,7 @@ class SqlBagOStuff extends BagOStuff {
        }
 
        public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
-               $ok = $this->mergeViaCas( $key, $callback, $exptime, $attempts );
+               $ok = $this->mergeViaCas( $key, $callback, $exptime, $attempts, $flags );
                if ( ( $flags & self::WRITE_SYNC ) == self::WRITE_SYNC ) {
                        $ok = $this->waitForReplication() && $ok;
                }
@@ -494,7 +501,7 @@ class SqlBagOStuff extends BagOStuff {
                return $ok;
        }
 
-       public function changeTTL( $key, $expiry = 0 ) {
+       public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
                list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
                $db = null;
                $silenceScope = $this->silenceTransactionProfiler();
@@ -689,7 +696,7 @@ class SqlBagOStuff extends BagOStuff {
                        $decomp = gzinflate( $serial );
                        Wikimedia\restoreWarnings();
 
-                       if ( false !== $decomp ) {
+                       if ( $decomp !== false ) {
                                $serial = $decomp;
                        }
                }
@@ -709,14 +716,8 @@ class SqlBagOStuff extends BagOStuff {
                if ( $exception instanceof DBConnectionError ) {
                        $this->markServerDown( $exception, $serverIndex );
                }
-               $this->logger->error( "DBError: {$exception->getMessage()}" );
-               if ( $exception instanceof DBConnectionError ) {
-                       $this->setLastError( BagOStuff::ERR_UNREACHABLE );
-                       $this->logger->debug( __METHOD__ . ": ignoring connection error" );
-               } else {
-                       $this->setLastError( BagOStuff::ERR_UNEXPECTED );
-                       $this->logger->debug( __METHOD__ . ": ignoring query error" );
-               }
+
+               $this->setAndLogDBError( $exception );
        }
 
        /**
@@ -730,15 +731,15 @@ class SqlBagOStuff extends BagOStuff {
        protected function handleWriteError( DBError $exception, IDatabase $db = null, $serverIndex ) {
                if ( !$db ) {
                        $this->markServerDown( $exception, $serverIndex );
-               } elseif ( $db->wasReadOnlyError() ) {
-                       if ( $db->trxLevel() && $this->usesMainDB() ) {
-                               // Errors like deadlocks and connection drops already cause rollback.
-                               // For consistency, we have no choice but to throw an error and trigger
-                               // complete rollback if the main DB is also being used as the cache DB.
-                               throw $exception;
-                       }
                }
 
+               $this->setAndLogDBError( $exception );
+       }
+
+       /**
+        * @param DBError $exception
+        */
+       private function setAndLogDBError( DBError $exception ) {
                $this->logger->error( "DBError: {$exception->getMessage()}" );
                if ( $exception instanceof DBConnectionError ) {
                        $this->setLastError( BagOStuff::ERR_UNREACHABLE );
@@ -811,20 +812,26 @@ class SqlBagOStuff extends BagOStuff {
                }
 
                // Main LB is used; wait for any replica DBs to catch up
-               $masterPos = $lb->getMasterPos();
-               if ( !$masterPos ) {
-                       return true; // not applicable
-               }
+               try {
+                       $masterPos = $lb->getMasterPos();
+                       if ( !$masterPos ) {
+                               return true; // not applicable
+                       }
 
-               $loop = new WaitConditionLoop(
-                       function () use ( $lb, $masterPos ) {
-                               return $lb->waitForAll( $masterPos, 1 );
-                       },
-                       $this->syncTimeout,
-                       $this->busyCallbacks
-               );
+                       $loop = new WaitConditionLoop(
+                               function () use ( $lb, $masterPos ) {
+                                       return $lb->waitForAll( $masterPos, 1 );
+                               },
+                               $this->syncTimeout,
+                               $this->busyCallbacks
+                       );
 
-               return ( $loop->invoke() === $loop::CONDITION_REACHED );
+                       return ( $loop->invoke() === $loop::CONDITION_REACHED );
+               } catch ( DBError $e ) {
+                       $this->setAndLogDBError( $e );
+
+                       return false;
+               }
        }
 
        /**