Fix some LoadBalancer::waitFor*() inconsistencies
authorAaron Schulz <aschulz@wikimedia.org>
Fri, 14 Apr 2017 02:15:42 +0000 (19:15 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Fri, 14 Apr 2017 02:23:09 +0000 (19:23 -0700)
* Make sure waitFor() always handles laggedReplicaMode updates,
  even if the actual waiting was deferred until a connection was
  needed.
* Restore the old mWaitForPos in waitForOne()/waitForAll() since
  this do not care about the generic reader index or the sort of
  ChronologyProtector logic related to it.

Change-Id: I0767e9831b8fd7fd115a472354977e3c1e12114a

includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php

index 8b5a98d..cbd0ff3 100644 (file)
@@ -135,6 +135,10 @@ interface ILoadBalancer {
         * If a DB_REPLICA connection has been opened already, then wait immediately.
         * Otherwise sets a variable telling it to wait if such a connection is opened.
         *
         * If a DB_REPLICA connection has been opened already, then wait immediately.
         * Otherwise sets a variable telling it to wait if such a connection is opened.
         *
+        * This only applies to connections to the generic replica DB for this request.
+        * If a timeout happens when waiting, then getLaggedReplicaMode()/laggedReplicaUsed()
+        * will return true.
+        *
         * @param DBMasterPos|bool $pos Master position or false
         */
        public function waitFor( $pos );
         * @param DBMasterPos|bool $pos Master position or false
         */
        public function waitFor( $pos );
index ffa4f78..e8069c0 100644 (file)
@@ -411,7 +411,11 @@ class LoadBalancer implements ILoadBalancer {
                        # Replica DB connection successful.
                        # Wait for the session master pos for a short time.
                        if ( $this->mWaitForPos && $i > 0 ) {
                        # Replica DB connection successful.
                        # Wait for the session master pos for a short time.
                        if ( $this->mWaitForPos && $i > 0 ) {
-                               $this->doWait( $i );
+                               # When LoadBalancer::waitFor() set mWaitForPos, the wait will happen here.
+                               # Be sure to update laggedReplicaMode accordingly for consistency.
+                               if ( !$this->doWait( $i ) ) {
+                                       $laggedReplicaMode = true;
+                               }
                        }
                        if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group === false ) {
                                $this->mReadIndex = $i;
                        }
                        if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group === false ) {
                                $this->mReadIndex = $i;
@@ -440,7 +444,7 @@ class LoadBalancer implements ILoadBalancer {
                                }
                        }
                } finally {
                                }
                        }
                } finally {
-                       // Restore the older position if it was higher
+                       // Restore the older position if it was higher since this is used for lag-protection
                        $this->setWaitForPositionIfHigher( $oldPos );
                }
        }
                        $this->setWaitForPositionIfHigher( $oldPos );
                }
        }
@@ -465,8 +469,8 @@ class LoadBalancer implements ILoadBalancer {
                                $ok = true; // no applicable loads
                        }
                } finally {
                                $ok = true; // no applicable loads
                        }
                } finally {
-                       // Restore the older position if it was higher
-                       $this->setWaitForPositionIfHigher( $oldPos );
+                       # Restore the old position, as this is not used for lag-protection but for throttling
+                       $this->mWaitForPos = $oldPos;
                }
 
                return $ok;
                }
 
                return $ok;
@@ -485,8 +489,8 @@ class LoadBalancer implements ILoadBalancer {
                                }
                        }
                } finally {
                                }
                        }
                } finally {
-                       // Restore the older position if it was higher
-                       $this->setWaitForPositionIfHigher( $oldPos );
+                       # Restore the old position, as this is not used for lag-protection but for throttling
+                       $this->mWaitForPos = $oldPos;
                }
 
                return $ok;
                }
 
                return $ok;