* Do fewer unnecessary full writes of user rows; only update user_touched
authorBrion Vibber <brion@users.mediawiki.org>
Tue, 3 Oct 2006 22:30:40 +0000 (22:30 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Tue, 3 Oct 2006 22:30:40 +0000 (22:30 +0000)
  for watch/unwatch, group membership change, and login operations

RELEASE-NOTES
includes/Article.php
includes/SpecialUserlogin.php
includes/User.php

index eac2f15..c253ff3 100644 (file)
@@ -255,6 +255,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 6889) PHP notices in thumb.php with missing params
 * Cleaner error behavior on thumb.php with invalid page selection
 * (bug 6617) Validate timestamps on Special:Undelete
+* Do fewer unnecessary full writes of user rows; only update user_touched
+  for watch/unwatch, group membership change, and login operations
 
 
 == Languages updated ==
index 4764d46..5f81730 100644 (file)
@@ -1464,7 +1464,6 @@ class Article {
                
                if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
                        $wgUser->addWatch( $this->mTitle );
-                       $wgUser->saveSettings();
 
                        return wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
                }
@@ -1512,7 +1511,6 @@ class Article {
 
                if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$this))) {
                        $wgUser->removeWatch( $this->mTitle );
-                       $wgUser->saveSettings();
 
                        return wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
                }
index 5e5f7b0..cc7339f 100644 (file)
@@ -365,9 +365,13 @@ class LoginForm {
                {
                        case self::SUCCESS:
                                # We've verified now, update the real record
-                               $wgUser->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 );
+                               if( (bool)$this->mRemember != (bool)$wgUser->getOption( 'rememberpassword' ) ) {
+                                       $wgUser->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 );
+                                       $wgUser->saveSettings();
+                               } else {
+                                       $wgUser->invalidateCache();
+                               }
                                $wgUser->setCookies();
-                               $wgUser->saveSettings();
 
                                if( $this->hasSessionCookie() ) {
                                        return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
index 4913de8..7dc4689 100644 (file)
@@ -1094,16 +1094,49 @@ class User {
                                }
                        }
                        $this->invalidateCache();
-                       $this->saveSettings();
+               }
+       }
+       
+       /**
+        * Generate a current or new-future timestamp to be stored in the
+        * user_touched field when we update things.
+        */
+       private static function newTouchedTimestamp() {
+               global $wgClockSkewFudge;
+               return wfTimestamp( TS_MW, time() + $wgClockSkewFudge );
+       }
+       
+       /**
+        * Clear user data from memcached.
+        * Use after applying fun updates to the database; caller's
+        * responsibility to update user_touched if appropriate.
+        *
+        * Called implicitly from invalidateCache() and saveSettings().
+        */
+       private function clearUserCache() {
+               if( $this->mId ) {
+                       global $wgMemc, $wgDBname;
+                       $wgMemc->delete( "$wgDBname:user:id:$this->mId" );
                }
        }
 
+       /**
+        * Immediately touch the user data cache for this account.
+        * Updates user_touched field, and removes account data from memcached
+        * for reload on the next hit.
+        */
        function invalidateCache() {
-               global $wgClockSkewFudge;
-               $this->loadFromDatabase();
-               $this->mTouched = wfTimestamp(TS_MW, time() + $wgClockSkewFudge );
-               # Don't forget to save the options after this or
-               # it won't take effect!
+               if( $this->mId ) {
+                       $this->mTouched = self::newTouchedTimestamp();
+                       
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $dbw->update( 'user',
+                               array( 'user_touched' => $dbw->timestamp( $this->mTouched ) ),
+                               array( 'user_id' => $this->mId ),
+                               __METHOD__ );
+                       
+                       $this->clearUserCache();
+               }
        }
 
        function validateCache( $timestamp ) {
@@ -1252,7 +1285,6 @@ class User {
                $val = str_replace( "\r", "\n", $val );
                $val = str_replace( "\n", " ", $val );
                $this->mOptions[$oname] = $val;
-               $this->invalidateCache();
        }
 
        function getRights() {
@@ -1303,7 +1335,6 @@ class User {
                $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
 
                $this->invalidateCache();
-               $this->saveSettings();
        }
 
        /**
@@ -1324,7 +1355,6 @@ class User {
                $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
 
                $this->invalidateCache();
-               $this->saveSettings();
        }
 
 
@@ -1579,13 +1609,15 @@ class User {
 
        /**
         * Save object settings into database
+        * @fixme Only rarely do all these fields need to be set!
         */
        function saveSettings() {
-               global $wgMemc, $wgDBname;
                $fname = 'User::saveSettings';
 
                if ( wfReadOnly() ) { return; }
                if ( 0 == $this->mId ) { return; }
+               
+               $this->mTouched = self::newTouchedTimestamp();
 
                $dbw =& wfGetDB( DB_MASTER );
                $dbw->update( 'user',
@@ -1603,7 +1635,7 @@ class User {
                                'user_id' => $this->mId
                        ), $fname
                );
-               $wgMemc->delete( "$wgDBname:user:id:$this->mId" );
+               $this->clearUserCache();
        }