MediaWiki  REL1_24
cleanupUploadStash.php
Go to the documentation of this file.
00001 <?php
00028 require_once __DIR__ . '/Maintenance.php';
00029 
00036 class UploadStashCleanup extends Maintenance {
00037 
00038     public function __construct() {
00039         parent::__construct();
00040         $this->mDescription = "Clean up abandoned files in temporary uploaded file stash";
00041         $this->setBatchSize( 50 );
00042     }
00043 
00044     public function execute() {
00045         global $wgUploadStashMaxAge;
00046 
00047         $repo = RepoGroup::singleton()->getLocalRepo();
00048         $tempRepo = $repo->getTempRepo();
00049 
00050         $dbr = $repo->getSlaveDb();
00051 
00052         // how far back should this look for files to delete?
00053         $cutoff = time() - $wgUploadStashMaxAge;
00054 
00055         $this->output( "Getting list of files to clean up...\n" );
00056         $res = $dbr->select(
00057             'uploadstash',
00058             'us_key',
00059             'us_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $cutoff ) ),
00060             __METHOD__
00061         );
00062 
00063         // Delete all registered stash files...
00064         if ( $res->numRows() == 0 ) {
00065             $this->output( "No stashed files to cleanup according to the DB.\n" );
00066         } else {
00067             // finish the read before starting writes.
00068             $keys = array();
00069             foreach ( $res as $row ) {
00070                 array_push( $keys, $row->us_key );
00071             }
00072 
00073             $this->output( 'Removing ' . count( $keys ) . " file(s)...\n" );
00074             // this could be done some other, more direct/efficient way, but using
00075             // UploadStash's own methods means it's less likely to fall accidentally
00076             // out-of-date someday
00077             $stash = new UploadStash( $repo );
00078 
00079             $i = 0;
00080             foreach ( $keys as $key ) {
00081                 $i++;
00082                 try {
00083                     $stash->getFile( $key, true );
00084                     $stash->removeFileNoAuth( $key );
00085                 } catch ( UploadStashException $ex ) {
00086                     $type = get_class( $ex );
00087                     $this->output( "Failed removing stashed upload with key: $key ($type)\n" );
00088                 }
00089                 if ( $i % 100 == 0 ) {
00090                     $this->output( "$i\n" );
00091                 }
00092             }
00093             $this->output( "$i done\n" );
00094         }
00095 
00096         // Delete all the corresponding thumbnails...
00097         $dir = $tempRepo->getZonePath( 'thumb' );
00098         $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir, 'adviseStat' => 1 ) );
00099         $this->output( "Deleting old thumbnails...\n" );
00100         $i = 0;
00101         $batch = array(); // operation batch
00102         foreach ( $iterator as $file ) {
00103             if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
00104                 $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
00105                 if ( count( $batch ) >= $this->mBatchSize ) {
00106                     $this->doOperations( $tempRepo, $batch );
00107                     $i += count( $batch );
00108                     $batch = array();
00109                     $this->output( "$i\n" );
00110                 }
00111             }
00112         }
00113         if ( count( $batch ) ) {
00114             $this->doOperations( $tempRepo, $batch );
00115             $i += count( $batch );
00116         }
00117         $this->output( "$i done\n" );
00118 
00119         // Apparently lots of stash files are not registered in the DB...
00120         $dir = $tempRepo->getZonePath( 'public' );
00121         $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir, 'adviseStat' => 1 ) );
00122         $this->output( "Deleting orphaned temp files...\n" );
00123         if ( strpos( $dir, '/local-temp' ) === false ) { // sanity check
00124             $this->error( "Temp repo is not using the temp container.", 1 ); // die
00125         }
00126         $i = 0;
00127         $batch = array(); // operation batch
00128         foreach ( $iterator as $file ) {
00129             if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
00130                 $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
00131                 if ( count( $batch ) >= $this->mBatchSize ) {
00132                     $this->doOperations( $tempRepo, $batch );
00133                     $i += count( $batch );
00134                     $batch = array();
00135                     $this->output( "$i\n" );
00136                 }
00137             }
00138         }
00139         if ( count( $batch ) ) {
00140             $this->doOperations( $tempRepo, $batch );
00141             $i += count( $batch );
00142         }
00143         $this->output( "$i done\n" );
00144     }
00145 
00146     protected function doOperations( FileRepo $tempRepo, array $ops ) {
00147         $status = $tempRepo->getBackend()->doQuickOperations( $ops );
00148         if ( !$status->isOK() ) {
00149             $this->error( print_r( $status->getErrorsArray(), true ) );
00150         }
00151     }
00152 }
00153 
00154 $maintClass = "UploadStashCleanup";
00155 require_once RUN_MAINTENANCE_IF_MAIN;