Merge "Database: Behave correctly when inserting booleans"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 21 Sep 2016 18:54:32 +0000 (18:54 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 21 Sep 2016 18:54:32 +0000 (18:54 +0000)
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
resources/src/mediawiki/api/upload.js
tests/phpunit/includes/db/LBFactoryTest.php

index cf9a298..d75ba93 100644 (file)
@@ -410,14 +410,14 @@ abstract class LBFactory {
         * This makes sense when lag being waiting on is caused by the code that does this check.
         * In that case, setting "ifWritesSince" can avoid the overhead of waiting for clusters
         * that were not changed since the last wait check. To forcefully wait on a specific cluster
-        * for a given wiki, use the 'wiki' parameter. To forcefully wait on an "external" cluster,
+        * for a given domain, use the 'domain' parameter. To forcefully wait on an "external" cluster,
         * use the "cluster" parameter.
         *
         * Never call this function after a large DB write that is *still* in a transaction.
         * It only makes sense to call this after the possible lag inducing changes were committed.
         *
         * @param array $opts Optional fields that include:
-        *   - wiki : wait on the load balancer DBs that handles the given wiki
+        *   - domain : wait on the load balancer DBs that handles the given domain ID
         *   - cluster : wait on the given external load balancer DBs
         *   - timeout : Max wait time. Default: ~60 seconds
         *   - ifWritesSince: Only wait if writes were done since this UNIX timestamp
@@ -426,19 +426,23 @@ abstract class LBFactory {
         */
        public function waitForReplication( array $opts = [] ) {
                $opts += [
-                       'wiki' => false,
+                       'domain' => false,
                        'cluster' => false,
                        'timeout' => 60,
                        'ifWritesSince' => null
                ];
 
+               if ( $opts['domain'] === false && isset( $opts['wiki'] ) ) {
+                       $opts['domain'] = $opts['wiki']; // b/c
+               }
+
                // Figure out which clusters need to be checked
                /** @var ILoadBalancer[] $lbs */
                $lbs = [];
                if ( $opts['cluster'] !== false ) {
                        $lbs[] = $this->getExternalLB( $opts['cluster'] );
-               } elseif ( $opts['wiki'] !== false ) {
-                       $lbs[] = $this->getMainLB( $opts['wiki'] );
+               } elseif ( $opts['domain'] !== false ) {
+                       $lbs[] = $this->getMainLB( $opts['domain'] );
                } else {
                        $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$lbs ) {
                                $lbs[] = $lb;
index 9c07043..c030cb2 100644 (file)
@@ -136,9 +136,10 @@ class LoadBalancer implements ILoadBalancer {
 
                $this->mReadIndex = -1;
                $this->mConns = [
-                       'local' => [],
+                       'local'       => [],
                        'foreignUsed' => [],
-                       'foreignFree' => [] ];
+                       'foreignFree' => []
+               ];
                $this->mLoads = [];
                $this->mWaitForPos = false;
                $this->mErrorConnection = false;
@@ -598,21 +599,18 @@ class LoadBalancer implements ILoadBalancer {
                        return;
                }
 
-               $dbName = $conn->getDBname();
-               $prefix = $conn->tablePrefix();
-               if ( strval( $prefix ) !== '' ) {
-                       $domain = "$dbName-$prefix";
-               } else {
-                       $domain = $dbName;
-               }
+               $domain = $conn->getDomainID();
                if ( $this->mConns['foreignUsed'][$serverIndex][$domain] !== $conn ) {
-                       throw new InvalidArgumentException( __METHOD__ . ": connection not found, has " .
-                               "the connection been freed already?" );
+                       throw new InvalidArgumentException( __METHOD__ .
+                               ": connection not found, has the connection been freed already?" );
                }
                $conn->setLBInfo( 'foreignPoolRefCount', --$refCount );
                if ( $refCount <= 0 ) {
                        $this->mConns['foreignFree'][$serverIndex][$domain] = $conn;
                        unset( $this->mConns['foreignUsed'][$serverIndex][$domain] );
+                       if ( !$this->mConns['foreignUsed'][$serverIndex] ) {
+                               unset( $this->mConns[ 'foreignUsed' ][$serverIndex] ); // clean up
+                       }
                        $this->connLogger->debug( __METHOD__ . ": freed connection $serverIndex/$domain" );
                } else {
                        $this->connLogger->debug( __METHOD__ .
@@ -707,11 +705,10 @@ class LoadBalancer implements ILoadBalancer {
                        // Reuse a connection from another domain
                        $conn = reset( $this->mConns['foreignFree'][$i] );
                        $oldDomain = key( $this->mConns['foreignFree'][$i] );
-
                        // The empty string as a DB name means "don't care".
                        // DatabaseMysqlBase::open() already handle this on connection.
-                       if ( $dbName !== '' && !$conn->selectDB( $dbName ) ) {
-                               $this->mLastError = "Error selecting database $dbName on server " .
+                       if ( strlen( $dbName ) && !$conn->selectDB( $dbName ) ) {
+                               $this->mLastError = "Error selecting database '$dbName' on server " .
                                        $conn->getServer() . " from client host {$this->host}";
                                $this->mErrorConnection = $conn;
                                $conn = false;
@@ -770,7 +767,7 @@ class LoadBalancer implements ILoadBalancer {
         * @access private
         *
         * @param array $server
-        * @param bool $dbNameOverride
+        * @param string|bool $dbNameOverride Use "" to not select any database
         * @return IDatabase
         * @throws DBAccessError
         * @throws InvalidArgumentException
@@ -1473,6 +1470,17 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        public function setDomainPrefix( $prefix ) {
+               if ( $this->mConns['foreignUsed'] ) {
+                       // Do not switch connections to explicit foreign domains unless marked as free
+                       $domains = [];
+                       foreach ( $this->mConns['foreignUsed'] as $i => $connsByDomain ) {
+                               $domains = array_merge( $domains, array_keys( $connsByDomain ) );
+                       }
+                       $domains = implode( ', ', $domains );
+                       throw new DBUnexpectedError( null,
+                               "Foreign domain connections are still in use ($domains)." );
+               }
+
                $this->localDomain = new DatabaseDomain(
                        $this->localDomain->getDatabase(),
                        null,
index c2da10e..8169449 100644 (file)
                        this[ this.needToken() ? 'postWithEditToken' : 'post' ]( data, {
                                // Use FormData (if we got here, we know that it's available)
                                contentType: 'multipart/form-data',
+                               // No timeout (default from mw.Api is 30 seconds)
+                               timeout: 0,
                                // Provide upload progress notifications
                                xhr: function () {
                                        var xhr = $.ajaxSettings.xhr();
index adf8a40..d72768d 100644 (file)
@@ -272,6 +272,7 @@ class LBFactoryTest extends MediaWikiTestCase {
 
                /** @var DatabaseBase $db */
                $db = $lb->getConnection( DB_MASTER, [], '' );
+               $lb->reuseConnection( $db ); // don't care
 
                $this->assertEquals(
                        '',
@@ -323,6 +324,7 @@ class LBFactoryTest extends MediaWikiTestCase {
                $lb = $factory->getMainLB();
                /** @var DatabaseBase $db */
                $db = $lb->getConnection( DB_MASTER, [], '' );
+               $lb->reuseConnection( $db ); // don't care
 
                $this->assertEquals(
                        '',