From: Aaron Schulz Date: Fri, 10 Jul 2015 23:18:23 +0000 (-0700) Subject: Made the prior user existence check in LoginForm use DB_MASTER X-Git-Tag: 1.31.0-rc.0~10811^2 X-Git-Url: http://git.cyclocoop.org/%22%20.%20generer_url_ecrire%28%22auteur_infos%22%2C%20%22id_auteur=%24id%22%29%20.%20%22?a=commitdiff_plain;h=08698e48e8cf0987b9cbc35653e6cf4352ee3767;p=lhc%2Fweb%2Fwiklou.git Made the prior user existence check in LoginForm use DB_MASTER * This helps if multiple account creation attempts were made in a row and the slave selected was lagged (either too much for Chronology Protector or the user did not resend the cookies to link the session). * The locking also better handles concurrent attempt to make another account, especially with CentralAuth trying to make external accounts. This assumes that the rate of concurrent account creations with close names is low enough given trx speed to avoid gap locking issues. This will need to be confirmed with low error log rates to be sure. * The User::idFromName() method now includes a $flags parameter. Bug: T104615 Change-Id: I8385526a19efc528a016ad2bbf376b377138966b --- diff --git a/includes/User.php b/includes/User.php index 63c0d37e45..dea9750b6a 100644 --- a/includes/User.php +++ b/includes/User.php @@ -3705,19 +3705,29 @@ class User implements IDBAccessObject { /** * If only this user's username is known, and it exists, return the user ID. + * + * @param int $flags Bitfield of User:READ_* constants; useful for existence checks * @return int */ - public function idForName() { + public function idForName( $flags = 0 ) { $s = trim( $this->getName() ); if ( $s === '' ) { return 0; } - $dbr = wfGetDB( DB_SLAVE ); - $id = $dbr->selectField( 'user', 'user_id', array( 'user_name' => $s ), __METHOD__ ); + $db = ( ( $flags & self::READ_LATEST ) == self::READ_LATEST ) + ? wfGetDB( DB_MASTER ) + : wfGetDB( DB_SLAVE ); + + $options = ( ( $flags & self::READ_LOCKING ) == self::READ_LOCKING ) + ? array( 'FOR UPDATE' ) + : array(); + + $id = $db->selectField( 'user', 'user_id', array( 'user_name' => $s ), __METHOD__, $options ); if ( $id === false ) { $id = 0; } + return $id; } diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php index 472fdb71dc..aa5141514e 100644 --- a/includes/specials/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -529,9 +529,9 @@ class LoginForm extends SpecialPage { # Now create a dummy user ($u) and check if it is valid $u = User::newFromName( $this->mUsername, 'creatable' ); - if ( !is_object( $u ) ) { + if ( !$u ) { return Status::newFatal( 'noname' ); - } elseif ( 0 != $u->idForName() ) { + } elseif ( 0 != $u->idForName( User::READ_LOCKING ) ) { return Status::newFatal( 'userexists' ); }