Merge "Add checks to try to catch T92046"
[lhc/web/wiklou.git] / includes / db / LoadBalancer.php
index 4c9fd32..48c636e 100644 (file)
@@ -328,9 +328,11 @@ class LoadBalancer {
                                        $this->mServers[$i]['slave pos'] = $conn->getSlavePos();
                                }
                        }
-                       if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group !== false ) {
+                       if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group === false ) {
                                $this->mReadIndex = $i;
                        }
+                       $serverName = $this->getServerName( $i );
+                       wfDebug( __METHOD__ . ": using server $serverName for group '$group'\n" );
                }
 
                return $i;
@@ -469,6 +471,9 @@ class LoadBalancer {
                        ? array( false ) // check one "group": the generic pool
                        : (array)$groups;
 
+               $masterOnly = ( $i == DB_MASTER || $i == $this->getWriterIndex() );
+               $oldConnsOpened = $this->connsOpened; // connections open now
+
                if ( $i == DB_MASTER ) {
                        $i = $this->getWriterIndex();
                } else {
@@ -476,8 +481,6 @@ class LoadBalancer {
                        foreach ( $groups as $group ) {
                                $groupIndex = $this->getReaderIndex( $group, $wiki );
                                if ( $groupIndex !== false ) {
-                                       $serverName = $this->getServerName( $groupIndex );
-                                       wfDebug( __METHOD__ . ": using server $serverName for group $group\n" );
                                        $i = $groupIndex;
                                        break;
                                }
@@ -506,6 +509,14 @@ class LoadBalancer {
                        return $this->reportConnectionError();
                }
 
+               # Profile any new connections that happen
+               if ( $this->connsOpened > $oldConnsOpened ) {
+                       $host = $conn->getServer();
+                       $dbname = $conn->getDBname();
+                       $trxProf = Profiler::instance()->getTransactionProfiler();
+                       $trxProf->recordConnection( $host, $dbname, $masterOnly );
+               }
+
                return $conn;
        }
 
@@ -1011,8 +1022,7 @@ class LoadBalancer {
        }
 
        /**
-        * Determine if there are any pending changes that need to be rolled back
-        * or committed.
+        * Determine if there are pending changes in a transaction by this thread
         * @since 1.23
         * @return bool
         */
@@ -1033,6 +1043,42 @@ class LoadBalancer {
                return false;
        }
 
+       /**
+        * Get the timestamp of the latest write query done by this thread
+        * @since 1.25
+        * @return float|bool UNIX timestamp or false
+        */
+       public function lastMasterChangeTimestamp() {
+               $lastTime = false;
+               // Always 0, but who knows.. :)
+               $masterIndex = $this->getWriterIndex();
+               foreach ( $this->mConns as $conns2 ) {
+                       if ( empty( $conns2[$masterIndex] ) ) {
+                               continue;
+                       }
+                       /** @var DatabaseBase $conn */
+                       foreach ( $conns2[$masterIndex] as $conn ) {
+                               $lastTime = max( $lastTime, $conn->lastDoneWrites() );
+                       }
+               }
+               return $lastTime;
+       }
+
+       /**
+        * Check if this load balancer object had any recent or still
+        * pending writes issued against it by this PHP thread
+        *
+        * @param float $age How many seconds ago is "recent" [defaults to mWaitTimeout]
+        * @return bool
+        * @since 1.25
+        */
+       public function hasOrMadeRecentMasterChanges( $age = null ) {
+               $age = ( $age === null ) ? $this->mWaitTimeout : $age;
+
+               return ( $this->hasMasterChanges()
+                       || $this->lastMasterChangeTimestamp() > microtime( true ) - $age );
+       }
+
        /**
         * @param mixed $value
         * @return mixed