[FileRepo] Split out store/purge functions for thumbnails and made them skip file...
authorAaron <aschulz@wikimedia.org>
Mon, 16 Apr 2012 23:51:55 +0000 (16:51 -0700)
committerAaron <aschulz@wikimedia.org>
Mon, 16 Apr 2012 23:52:15 +0000 (16:52 -0700)
* Added quickImport()/quickPurge() functions to store and delete files as fast as possible.
* Also added a cleanDir() function to avoid having File directly use FileBackend functions.

Change-Id: I9a19862f1a720c5a464bd37f79b58a505c5961f9

includes/filerepo/FileRepo.php
includes/filerepo/file/File.php
includes/filerepo/file/ForeignAPIFile.php
includes/filerepo/file/LocalFile.php

index dcc9610..8fe786a 100644 (file)
@@ -783,6 +783,86 @@ class FileRepo {
                return $status;
        }
 
+       /**
+        * Import a file from the local file system into the repo.
+        * This does no locking nor journaling and overrides existing files.
+        * This is intended for copying generated thumbnails into the repo.
+        *
+        * @param $src string File system path
+        * @param $dst string Virtual URL or storage path
+        * @return FileRepoStatus
+        */
+       final public function quickImport( $src, $dst ) {
+               return $this->quickImportBatch( array( array( $src, $dst ) ) );
+       }
+
+       /**
+        * Purge a file from the repo. This does no locking nor journaling.
+        * This is intended for purging thumbnail.
+        *
+        * @param $path string Virtual URL or storage path
+        * @return FileRepoStatus
+        */
+       final public function quickPurge( $path ) {
+               return $this->quickPurgeBatch( array( $path ) );
+       }
+
+       /**
+        * Import a batch of files from the local file system into the repo.
+        * This does no locking nor journaling and overrides existing files.
+        * This is intended for copying generated thumbnails into the repo.
+        *
+        * @param $src Array List of tuples (file system path, virtual URL or storage path)
+        * @return FileRepoStatus
+        */
+       public function quickImportBatch( array $pairs ) {
+               $this->assertWritableRepo(); // fail out if read-only
+
+               $status = $this->newGood();
+               $operations = array();
+               foreach ( $pairs as $pair ) {
+                       list ( $src, $dst ) = $pair;
+                       $operations[] = array(
+                               'op'        => 'store',
+                               'src'       => $src,
+                               'dst'       => $this->resolveToStoragePath( $dst ),
+                               'overwrite' => true
+                       );
+                       $this->backend->prepare( array( 'dir' => dirname( $dst ) ) );
+               }
+               $status->merge( $this->backend->doOperations( $operations,
+                       array( 'force' => 1, 'nonLocking' => 1, 'allowStale' => 1, 'nonJournaled' => 1 )
+               ) );
+
+               return $status;
+       }
+
+       /**
+        * Purge a batch of files from the repo. This does no locking nor journaling.
+        * This is intended for purging thumbnails.
+        *
+        * @param $path Array List of virtual URLs or storage paths
+        * @return FileRepoStatus
+        */
+       public function quickPurgeBatch( array $paths ) {
+               $this->assertWritableRepo(); // fail out if read-only
+
+               $status = $this->newGood();
+               $operations = array();
+               foreach ( $paths as $path ) {
+                       $operations[] = array(
+                               'op'                  => 'delete',
+                               'src'                 => $this->resolveToStoragePath( $path ),
+                               'ignoreMissingSource' => true
+                       );
+               }
+               $status->merge( $this->backend->doOperations( $operations,
+                       array( 'force' => 1, 'nonLocking' => 1, 'allowStale' => 1, 'nonJournaled' => 1 )
+               ) );
+
+               return $status;
+       }
+
        /**
         * Pick a random name in the temp zone and store a file to it.
         * Returns a FileRepoStatus object with the file Virtual URL in the value,
@@ -927,7 +1007,7 @@ class FileRepo {
                foreach ( $triplets as $i => $triplet ) {
                        list( $srcPath, $dstRel, $archiveRel ) = $triplet;
                        // Resolve source to a storage path if virtual
-                       if ( substr( $srcPath, 0, 9 ) == 'mwrepo://' ) {
+                       if ( $this->isVirtualUrl( $srcPath ) ) {
                                $srcPath = $this->resolveVirtualUrl( $srcPath );
                        }
                        if ( !$this->validateFilename( $dstRel ) ) {
@@ -1012,6 +1092,22 @@ class FileRepo {
                return $status;
        }
 
+       /**
+        * Deletes a directory if empty
+        *
+        * @param $dir string Virtual URL (or storage path) of directory to clean
+        * @return Status
+        */
+       public function cleanDir( $dir ) {
+               $this->assertWritableRepo(); // fail out if read-only
+
+               $status = $this->newGood();
+               $status->merge( $this->backend->clean(
+                       array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );
+
+               return $status;
+       }
+
        /**
         * Checks existence of a a file
         *
index ce69a03..de9efb5 100644 (file)
@@ -865,13 +865,8 @@ abstract class File {
                                }
                        } elseif ( $this->repo && $thumb->hasFile() && !$thumb->fileIsSource() ) {
                                $backend = $this->repo->getBackend();
-                               // Copy the thumbnail from the file system into storage. This avoids using
-                               // FileRepo::store(); getThumbPath() uses a different zone in some subclasses.
-                               $backend->prepare( array( 'dir' => dirname( $thumbPath ) ) );
-                               $status = $backend->store(
-                                       array( 'src' => $tmpThumbPath, 'dst' => $thumbPath, 'overwrite' => 1 ),
-                                       array( 'force' => 1, 'nonLocking' => 1, 'allowStale' => 1 )
-                               );
+                               // Copy the thumbnail from the file system into storage...
+                               $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath );
                                if ( $status->isOK() ) {
                                        $thumb->setStoragePath( $thumbPath );
                                } else {
index 16828fa..9ae501a 100644 (file)
@@ -247,8 +247,8 @@ class ForeignAPIFile extends File {
                }
 
                # Delete the thumbnails
-               $this->repo->cleanupBatch( $purgeList, FileRepo::SKIP_LOCKING );
+               $this->repo->quickPurgeBatch( $purgeList );
                # Clear out the thumbnail directory if empty
-               $this->repo->getBackend()->clean( array( 'dir' => $dir ) );
+               $this->repo->cleanDir( $dir );
        }
 }
index 04d7a47..af1b7cd 100644 (file)
@@ -777,9 +777,9 @@ class LocalFile extends File {
                }
 
                # Delete the thumbnails
-               $this->repo->cleanupBatch( $purgeList, FileRepo::SKIP_LOCKING );
+               $this->repo->quickPurgeBatch( $purgeList );
                # Clear out the thumbnail directory if empty
-               $this->repo->getBackend()->clean( array( 'dir' => $dir ) );
+               $this->repo->cleanDir( $dir );
        }
 
        /** purgeDescription inherited */