Merge "rdbms: make $i in LoadBalancer::getConnection override $groups"
[lhc/web/wiklou.git] / includes / libs / rdbms / loadbalancer / LoadBalancer.php
index 4de17b7..e2d3b33 100644 (file)
@@ -111,6 +111,8 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @var callable Exception logger */
        private $errorLogger;
+       /** @var callable Deprecation logger */
+       private $deprecationLogger;
 
        /** @var bool */
        private $disabled = false;
@@ -223,6 +225,11 @@ class LoadBalancer implements ILoadBalancer {
                        : function ( Exception $e ) {
                                trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
                        };
+               $this->deprecationLogger = isset( $params['deprecationLogger'] )
+                       ? $params['deprecationLogger']
+                       : function ( $msg ) {
+                               trigger_error( $msg, E_USER_DEPRECATED );
+                       };
 
                foreach ( [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ] as $key ) {
                        $this->$key = isset( $params[$key] ) ? $params[$key] : new NullLogger();
@@ -532,7 +539,7 @@ class LoadBalancer implements ILoadBalancer {
                                if ( $this->loads[$i] > 0 ) {
                                        $start = microtime( true );
                                        $ok = $this->doWait( $i, true, $timeout ) && $ok;
-                                       $timeout -= ( microtime( true ) - $start );
+                                       $timeout -= intval( microtime( true ) - $start );
                                        if ( $timeout <= 0 ) {
                                                break; // timeout reached
                                        }
@@ -568,7 +575,6 @@ class LoadBalancer implements ILoadBalancer {
                        if ( !empty( $connsByServer[$i] ) ) {
                                /** @var IDatabase[] $serverConns */
                                $serverConns = $connsByServer[$i];
-
                                return reset( $serverConns );
                        }
                }
@@ -682,7 +688,7 @@ class LoadBalancer implements ILoadBalancer {
                        $domain = false; // local connection requested
                }
 
-               if ( ( $flags & self::CONN_TRX_AUTO ) === self::CONN_TRX_AUTO ) {
+               if ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) === self::CONN_TRX_AUTOCOMMIT ) {
                        // Assuming all servers are of the same type (or similar), which is overwhelmingly
                        // the case, use the master server information to get the attributes. The information
                        // for $i cannot be used since it might be DB_REPLICA, which might require connection
@@ -693,8 +699,9 @@ class LoadBalancer implements ILoadBalancer {
                                // rows (e.g. FOR UPDATE) or (b) make small commits during a larger transactions
                                // to reduce lock contention. None of these apply for sqlite and using separate
                                // connections just causes self-deadlocks.
-                               $flags &= ~self::CONN_TRX_AUTO;
-                               $this->connLogger->info( __METHOD__ . ': ignoring CONN_TRX_AUTO to avoid deadlocks.' );
+                               $flags &= ~self::CONN_TRX_AUTOCOMMIT;
+                               $this->connLogger->info( __METHOD__ .
+                                       ': ignoring CONN_TRX_AUTOCOMMIT to avoid deadlocks.' );
                        }
                }
 
@@ -707,7 +714,7 @@ class LoadBalancer implements ILoadBalancer {
 
                if ( $i == self::DB_MASTER ) {
                        $i = $this->getWriterIndex();
-               } else {
+               } elseif ( $i == self::DB_REPLICA ) {
                        # Try to find an available server in any the query groups (in order)
                        foreach ( $groups as $group ) {
                                $groupIndex = $this->getReaderIndex( $group, $domain );
@@ -852,7 +859,7 @@ class LoadBalancer implements ILoadBalancer {
                // main set of DB connections but rather its own pool since:
                // a) those are usually set to implicitly use transaction rounds via DBO_TRX
                // b) those must support the use of explicit transaction rounds via beginMasterChanges()
-               $autoCommit = ( ( $flags & self::CONN_TRX_AUTO ) == self::CONN_TRX_AUTO );
+               $autoCommit = ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) == self::CONN_TRX_AUTOCOMMIT );
 
                if ( $domain !== false ) {
                        // Connection is to a foreign domain
@@ -930,7 +937,7 @@ class LoadBalancer implements ILoadBalancer {
                $domainInstance = DatabaseDomain::newFromId( $domain );
                $dbName = $domainInstance->getDatabase();
                $prefix = $domainInstance->getTablePrefix();
-               $autoCommit = ( ( $flags & self::CONN_TRX_AUTO ) == self::CONN_TRX_AUTO );
+               $autoCommit = ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) == self::CONN_TRX_AUTOCOMMIT );
 
                if ( $autoCommit ) {
                        $connFreeKey = self::KEY_FOREIGN_FREE_NOROUND;
@@ -1067,6 +1074,7 @@ class LoadBalancer implements ILoadBalancer {
                $server['connLogger'] = $this->connLogger;
                $server['queryLogger'] = $this->queryLogger;
                $server['errorLogger'] = $this->errorLogger;
+               $server['deprecationLogger'] = $this->deprecationLogger;
                $server['profiler'] = $this->profiler;
                $server['trxProfiler'] = $this->trxProfiler;
                // Use the same agent and PHP mode for all DB handles
@@ -1212,7 +1220,7 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        public function closeConnection( IDatabase $conn ) {
-               $serverIndex = $conn->getLBInfo( 'serverIndex' ); // second index level of mConns
+               $serverIndex = $conn->getLBInfo( 'serverIndex' );
                foreach ( $this->conns as $type => $connsByServer ) {
                        if ( !isset( $connsByServer[$serverIndex] ) ) {
                                continue;
@@ -1423,6 +1431,12 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        /**
+        * Make all DB servers with DBO_DEFAULT/DBO_TRX set join the transaction round
+        *
+        * Some servers may have neither flag enabled, meaning that they opt out of such
+        * transaction rounds and remain in auto-commit mode. Such behavior might be desired
+        * when a DB server is used for something like simple key/value storage.
+        *
         * @param IDatabase $conn
         */
        private function applyTransactionRoundFlags( IDatabase $conn ) {
@@ -1434,9 +1448,10 @@ class LoadBalancer implements ILoadBalancer {
                        // DBO_TRX is controlled entirely by CLI mode presence with DBO_DEFAULT.
                        // Force DBO_TRX even in CLI mode since a commit round is expected soon.
                        $conn->setFlag( $conn::DBO_TRX, $conn::REMEMBER_PRIOR );
-                       // If config has explicitly requested DBO_TRX be either on or off by not
-                       // setting DBO_DEFAULT, then respect that. Forcing no transactions is useful
-                       // for things like blob stores (ExternalStore) which want auto-commit mode.
+               }
+
+               if ( $conn->getFlag( $conn::DBO_TRX ) ) {
+                       $conn->setLBInfo( 'trxRoundId', $this->trxRoundId );
                }
        }
 
@@ -1448,6 +1463,10 @@ class LoadBalancer implements ILoadBalancer {
                        return; // transaction rounds do not apply to these connections
                }
 
+               if ( $conn->getFlag( $conn::DBO_TRX ) ) {
+                       $conn->setLBInfo( 'trxRoundId', false );
+               }
+
                if ( $conn->getFlag( $conn::DBO_DEFAULT ) ) {
                        $conn->restoreFlags( $conn::RESTORE_PRIOR );
                }