* Appllied patch for bug 1686, image metadata cache by Andrius Ramanauskas.
authorTim Starling <tstarling@users.mediawiki.org>
Sun, 13 Mar 2005 15:00:59 +0000 (15:00 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Sun, 13 Mar 2005 15:00:59 +0000 (15:00 +0000)
* Changed memcached invalidation style in this patch to recache instead of deleting, which is better for concurrency
* Added a fix for the media link problem, differnet to my fix for the same problem in REL1_4 but either should work.
* Fixed image deletion, it didn't work at all. Not sure when it was broken or if it's been reported. It was working in REL1_4. It was a trivial error.

includes/DefaultSettings.php
includes/Image.php
includes/ImagePage.php
includes/SpecialUndelete.php
includes/SpecialUpload.php

index 4f8da74..c36ef05 100644 (file)
@@ -126,6 +126,8 @@ $wgUseSharedUploads = false;
 $wgSharedUploadPath = "http://commons.wikimedia.org/shared/images";
 /** Path on the file system where shared uploads can be found */
 $wgSharedUploadDirectory = "/var/www/wiki3/images";
+/** Path on the file system where shared uploads can be found */
+$wgSharedUploadDBname = "commons";
 
 /**
  * Set the following to false especially if you have a set of files that need to
index de25a38..4269464 100644 (file)
@@ -36,70 +36,139 @@ class Image
         * Create an Image object from an image name
         *
         * @param string $name name of the image, used to create a title object using Title::makeTitleSafe
+        * @param bool $recache if true, ignores anything in memcached and sets the updated metadata
         * @access public
         */
-       function Image( $name ) {
+       function Image( $name, $recache = false ) {
 
-               global $wgUseSharedUploads, $wgUseLatin1, $wgSharedLatin1, $wgLang;
+               global $wgUseSharedUploads, $wgUseLatin1, $wgSharedLatin1, $wgLang, $wgMemc, $wgDBname;
 
                $this->name      = $name;
                $this->title     = Title::makeTitleSafe( NS_IMAGE, $this->name );
                $this->fromSharedDirectory = false;
                $this->imagePath = $this->getFullPath();
-               $this->fileExists = file_exists( $this->imagePath);             
+
+               $n = strrpos( $name, '.' );
+               $this->extension = strtolower( $n ? substr( $name, $n + 1 ) : '' );
+               $gis = false;
+               $hashedName = md5($this->name);
+               $cacheKey = "$wgDBname:Image:".$hashedName;
+               $foundCached = false;
                
-               # If the file is not found, and a shared upload directory 
-               # like the Wikimedia Commons is used, look for it there.
-               if (!$this->fileExists && $wgUseSharedUploads) {                        
-                       
-                       # In case we're on a wgCapitalLinks=false wiki, we 
-                       # capitalize the first letter of the filename before 
-                       # looking it up in the shared repository.
-                       $this->name= $wgLang->ucfirst($name);
-                       
-                       # Encode the filename if we're on a Latin1 wiki and the
-                       # shared repository is UTF-8
-                       if($wgUseLatin1 && !$wgSharedLatin1) {
-                               $this->name  = utf8_encode($name);
+               if ( !$recache ) {
+                       $cachedValues = $wgMemc->get( $cacheKey );
+
+                       if (!empty($cachedValues) && is_array($cachedValues)) {
+                               if ($wgUseSharedUploads && $cachedValues['fromShared']) {
+                                       # if this is shared file, we need to check if image
+                                       # in shared repository has not changed
+                                       $commonsCachedValues = $wgMemc->get( "$wgSharedUploadDBname:Image:".$hashedName );
+                                       if (!empty($commonsCachedValues) && is_array($commonsCachedValues)) {
+                                               $this->name = $commonsCachedValues['name'];
+                                               $this->imagePath = $commonsCachedValues['imagePath'];
+                                               $this->fileExists = $commonsCachedValues['fileExists'];
+                                               $this->fromSharedDirectory = true;
+                                               $gis = $commonsCachedValues['gis'];
+                                               $foundCached = true;
+                                       }
+                               }
+                               else {
+                                       $this->name = $cachedValues['name'];
+                                       $this->imagePath = $cachedValues['imagePath'];
+                                       $this->fileExists = $cachedValues['fileExists'];
+                                       $this->fromSharedDirectory = false;
+                                       $gis = $cachedValues['gis'];
+                                       $foundCached = true;
+                               }
                        }
-                       
-                       $this->imagePath = $this->getFullPath(true);
-                       $this->fileExists = file_exists( $this->imagePath);
-                       $this->fromSharedDirectory = true;
-                       $name=$this->name;
-                       
                }
-               if($this->fileExists) {                 
-                       $this->url = $this->wfImageUrl( $this->name, $this->fromSharedDirectory );
-               } else {
-                       $this->url='';
-               }
-               
-               $n = strrpos( $name, '.' );
-               $this->extension = strtolower( $n ? substr( $name, $n + 1 ) : '' );
-                               
 
-               if ( $this->fileExists ) {
-                       if( $this->extension == 'svg' ) {
-                               @$gis = getSVGsize( $this->imagePath );
-                       } else {
-                               @$gis = getimagesize( $this->imagePath );
+               if (!$foundCached) {
+                       $this->fileExists = file_exists( $this->imagePath);     
+
+                       # If the file is not found, and a shared upload directory 
+                       # like the Wikimedia Commons is used, look for it there.
+                       if (!$this->fileExists && $wgUseSharedUploads) {                        
+                               
+                               # In case we're on a wgCapitalLinks=false wiki, we 
+                               # capitalize the first letter of the filename before 
+                               # looking it up in the shared repository.
+                               $this->name= $wgLang->ucfirst($name);
+                               
+                               # Encode the filename if we're on a Latin1 wiki and the
+                               # shared repository is UTF-8
+                               if($wgUseLatin1 && !$wgSharedLatin1) {
+                                       $this->name  = utf8_encode($name);
+                               }
+                               
+                               $this->imagePath = $this->getFullPath(true);
+                               $this->fileExists = file_exists( $this->imagePath);
+                               $this->fromSharedDirectory = true;
+                               $name=$this->name;
                        }
-                       if( $gis !== false ) {
-                               $this->width = $gis[0];
-                               $this->height = $gis[1];
-                               $this->type = $gis[2];
-                               $this->attr = $gis[3];
-                               if ( isset( $gis['bits'] ) )  {
-                                       $this->bits = $gis['bits'];
+
+                       if ( $this->fileExists ) {
+                               # Don't try to get the size of sound and video files, that's bad for performance
+                               if ( !Image::isKnownImageExtension( $this->extension ) ) {
+                                       $gis = false;
+                               } elseif( $this->extension == 'svg' ) {
+                                       wfSuppressWarnings();
+                                       $gis = getSVGsize( $this->imagePath );
+                                       wfRestoreWarnings();
                                } else {
-                                       $this->bits = 0;
+                                       wfSuppressWarnings();
+                                       $gis = getimagesize( $this->imagePath );
+                                       wfRestoreWarnings();
                                }
                        }
+
+                       $cachedValues = array('name' => $this->name,
+                                                                 'imagePath' => $this->imagePath,
+                                                                 'fileExists' => $this->fileExists,
+                                                                 'fromShared' => $this->fromSharedDirectory,
+                                                                 'gis' => $gis);
+
+                       $wgMemc->set( $cacheKey, $cachedValues );
+
+                       if ($wgUseSharedUploads && $this->fromSharedDirectory) {
+                               $cachedValues['fromShared'] = false;
+                               $wgMemc->set( "$wgSharedUploadDBname:Image:".$hashedName, $cachedValues );
+                       }
+               }
+
+               if( $gis !== false ) {
+                       $this->width = $gis[0];
+                       $this->height = $gis[1];
+                       $this->type = $gis[2];
+                       $this->attr = $gis[3];
+                       if ( isset( $gis['bits'] ) )  {
+                               $this->bits = $gis['bits'];
+                       } else {
+                               $this->bits = 0;
+                       }
+               }
+
+               if($this->fileExists) {                 
+                       $this->url = $this->wfImageUrl( $this->name, $this->fromSharedDirectory );
+               } else {
+                       $this->url='';
                }
                $this->historyLine = 0;                         
        }
 
+       /**
+        * Remove image metadata from cache if any
+        *
+        * Don't call this, use the $recache parameter of Image::Image() instead
+        *
+        * @param string $name the title of an image
+        * @static
+        */
+       function invalidateMetadataCache( $name ) {
+               global $wgMemc, $wgDBname;
+               $wgMemc->delete("$wgDBname:Image:".md5($name));
+       }
+
        /**
         * Factory function
         *
@@ -588,6 +657,15 @@ class Image
                return $fullpath;
        }
        
+       /**
+        * @return bool
+        * @static
+        */
+       function isKnownImageExtension( $ext ) {
+               static $extensions = array( 'svg', 'png', 'jpg', 'jpeg', 'gif', 'bmp', 'xbm' );
+               return in_array( $ext, $extensions );
+       }
+       
 } //class
 
 
index 105eb89..d0285e8 100644 (file)
@@ -187,7 +187,7 @@ class ImagePage extends Article {
        {
                global $wgUser, $wgOut, $wgRequest;
 
-               $confirm = $wgRequest->getBool( 'wpConfirm' );
+               $confirm = $wgRequest->getBool( 'wpConfirmB' );
                $image = $wgRequest->getVal( 'image' );
                $oldimage = $wgRequest->getVal( 'oldimage' );
                
@@ -307,6 +307,9 @@ class ImagePage extends Article {
                        $article = new Article( $nt );
                        $article->doDeleteArticle( $reason ); # ignore errors
 
+                       /* refresh image metadata cache */
+                       new Image( $image, true );
+
                        $deleted = $image;
                }
 
@@ -404,6 +407,10 @@ class ImagePage extends Article {
                        $wgOut->fileCopyError( "${archive}/{$oldimage}", $curfile );
                }
                wfRecordUpload( $name, $oldver, $size, wfMsg( "reverted" ) );
+
+               /* refresh image metadata cache */
+               new Image( $name, true );
+
                # Squid purging
                if ( $wgUseSquid ) {
                        $urlArr = Array(
index 91b3273..648efdc 100644 (file)
@@ -259,7 +259,7 @@ class PageArchive {
                        $reason = wfMsg( 'undeletedrevisions', $restoreRevisions );
                }
                $log->addEntry( 'restore', $this->title, $reason );
-               
+
                return true;
        }
 }
@@ -429,6 +429,12 @@ class UndeleteForm {
                        $archive = new PageArchive( $this->mTargetObj );
                        if( $archive->undelete( $this->mTargetTimestamp ) ) {
                                $wgOut->addWikiText( wfMsg( "undeletedtext", $this->mTarget ) );
+
+                               if (NS_IMAGE == $this->mTargetObj->getNamespace()) {
+                                       /* refresh image metadata cache */
+                                       new Image( $this->mTargetObj->getText(), true );
+                               }
+
                                return true;
                        }
                }
index 9aa57b8..a5b32f0 100644 (file)
@@ -270,6 +270,10 @@ class UploadForm {
                                        $this->mUploadDescription,
                                        $this->mUploadCopyStatus,
                                        $this->mUploadSource );
+
+                       /* refresh image metadata cache */
+                       new Image( $this->mUploadSaveName, true );
+
                        $this->showSuccess();
                }
        }