r83245 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r83244‎ | r83245 | r83246 >
Date:21:57, 4 March 2011
Author:btongminh
Status:ok (Comments)
Tags:
Comment:
Fix and make file moving better resilient against errors by first copying the files, then doing the db updates and finally cleaning up the source.
* FsRepo::cleanupBatch now accepts either pairs, virtual urls and real paths
* Add missing begin() and commit() to LocalFileMoveBatch
* Actually set an error after incrementing failCount because otherwise the status is still good
* Changed some isOk() to isGood() and set ->ok explicitly to false after rollback
Modified paths:
  • /trunk/phase3/includes/filerepo/FSRepo.php (modified) (history)
  • /trunk/phase3/includes/filerepo/LocalFile.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/filerepo/LocalFile.php
@@ -2043,16 +2043,32 @@
20442044 $triplets = $this->getMoveTriplets();
20452045
20462046 $triplets = $this->removeNonexistentFiles( $triplets );
 2047+
 2048+ // Copy the files into their new location
 2049+ $statusMove = $repo->storeBatch( $triplets );
 2050+ wfDebugLog( 'imagemove', "Moved files for {$this->file->name}: {$statusMove->successCount} successes, {$statusMove->failCount} failures" );
 2051+ if ( !$statusMove->isGood() ) {
 2052+ wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
 2053+ $this->cleanupTarget( $triplets );
 2054+ $statusMove->ok = false;
 2055+ return $statusMove;
 2056+ }
 2057+
 2058+ $this->db->begin();
20472059 $statusDb = $this->doDBUpdates();
20482060 wfDebugLog( 'imagemove', "Renamed {$this->file->name} in database: {$statusDb->successCount} successes, {$statusDb->failCount} failures" );
2049 - $statusMove = $repo->storeBatch( $triplets, FSRepo::DELETE_SOURCE );
2050 - wfDebugLog( 'imagemove', "Moved files for {$this->file->name}: {$statusMove->successCount} successes, {$statusMove->failCount} failures" );
2051 -
2052 - if ( !$statusMove->isOk() ) {
2053 - wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
 2061+ if ( !$statusDb->isGood() ) {
20542062 $this->db->rollback();
 2063+ // Something went wrong with the DB updates, so remove the target files
 2064+ $this->cleanupTarget( $triplets );
 2065+ $statusDb->ok = false;
 2066+ return $statusDb;
20552067 }
2056 -
 2068+ $this->db->commit();
 2069+
 2070+ // Everything went ok, remove the source files
 2071+ $this->cleanupSource( $triplets );
 2072+
20572073 $status->merge( $statusDb );
20582074 $status->merge( $statusMove );
20592075
@@ -2082,6 +2098,8 @@
20832099 $status->successCount++;
20842100 } else {
20852101 $status->failCount++;
 2102+ $status->fatal( 'imageinvalidfilename' );
 2103+ return $status;
20862104 }
20872105
20882106 // Update old images
@@ -2099,6 +2117,9 @@
21002118 $total = $this->oldCount;
21012119 $status->successCount += $affected;
21022120 $status->failCount += $total - $affected;
 2121+ if ( $status->failCount ) {
 2122+ $status->error( 'imageinvalidfilename' );
 2123+ }
21032124
21042125 return $status;
21052126 }
@@ -2143,4 +2164,32 @@
21442165
21452166 return $filteredTriplets;
21462167 }
 2168+
 2169+ /**
 2170+ * Cleanup a partially moved array of triplets by deleting the target
 2171+ * files. Called if something went wrong half way.
 2172+ */
 2173+ function cleanupTarget( $triplets ) {
 2174+ // Create dest pairs from the triplets
 2175+ $pairs = array();
 2176+ foreach ( $triplets as $triplet ) {
 2177+ $pairs[] = array( $triplet[1], $triplet[2] );
 2178+ }
 2179+
 2180+ $this->file->repo->cleanupBatch( $pairs );
 2181+ }
 2182+
 2183+ /**
 2184+ * Cleanup a fully moved array of triplets by deleting the source files.
 2185+ * Called at the end of the move process if everything else went ok.
 2186+ */
 2187+ function cleanupSource( $triplets ) {
 2188+ // Create source file names from the triplets
 2189+ $files = array();
 2190+ foreach ( $triplets as $triplet ) {
 2191+ $files[] = $triplet[0];
 2192+ }
 2193+
 2194+ $this->file->repo->cleanupBatch( $files );
 2195+ }
21472196 }
Index: trunk/phase3/includes/filerepo/FSRepo.php
@@ -262,16 +262,28 @@
263263 }
264264
265265 /**
266 - * Deletes a batch of (zone, rel) pairs. It will try to delete each pair,
267 - * but ignores any errors doing so.
 266+ * Deletes a batch of files. Each file can be a (zone, rel) pairs, a
 267+ * virtual url or a real path. It will try to delete each file, but
 268+ * ignores any errors that may occur
268269 *
269 - * @param $pairs array Pair of (zone, rel) pairs to delete
 270+ * @param $pairs array List of files to delete
270271 */
271 - function cleanupBatch( $pairs ) {
272 - foreach ( $pairs as $pair ) {
273 - list( $zone, $rel ) = $pair;
274 - $root = $this->getZonePath( $zone );
275 - $path = "$root/$rel";
 272+ function cleanupBatch( $files ) {
 273+ foreach ( $files as $file ) {
 274+ if ( is_array( $file ) ) {
 275+ // This is a pair, extract it
 276+ list( $zone, $rel ) = $file;
 277+ $root = $this->getZonePath( $zone );
 278+ $path = "$root/$rel";
 279+ } else {
 280+ if ( self::isVirtualUrl( $file ) ) {
 281+ // This is a virtual url, resolve it
 282+ $path = $this->resolveVirtualUrl( $file );
 283+ } else {
 284+ // This is a full file name
 285+ $path = $file;
 286+ }
 287+ }
276288
277289 wfSuppressWarnings();
278290 unlink( $path );

Comments

#Comment by Bryan (talk | contribs)   22:00, 4 March 2011

This commit could prevent data loss in certain rare circumstances, so it would be nice if this were deployed, but it depends on r81536 and both require review from somebody who knows the ins and outs of filerepo.

Status & tagging log