MediaWiki
REL1_24
|
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;