diff options
Diffstat (limited to 'includes/upload/UploadFromChunks.php')
-rw-r--r-- | includes/upload/UploadFromChunks.php | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/includes/upload/UploadFromChunks.php b/includes/upload/UploadFromChunks.php index 531f7be4..4b331e98 100644 --- a/includes/upload/UploadFromChunks.php +++ b/includes/upload/UploadFromChunks.php @@ -37,7 +37,7 @@ class UploadFromChunks extends UploadFromFile { * @param $stash UploadStash * @param $repo FileRepo */ - public function __construct( $user = false, $stash = false, $repo = false ) { + public function __construct( $user = null, $stash = false, $repo = false ) { // user object. sometimes this won't exist, as when running from cron. $this->user = $user; @@ -60,12 +60,13 @@ class UploadFromChunks extends UploadFromFile { return true; } + /** * Calls the parent stashFile and updates the uploadsession table to handle "chunks" * * @return UploadStashFile stashed file */ - public function stashFile() { + public function stashFile( User $user = null ) { // Stash file is the called on creating a new chunk session: $this->mChunkIndex = 0; $this->mOffset = 0; @@ -78,7 +79,7 @@ class UploadFromChunks extends UploadFromFile { $this->mFileKey = $this->mLocalFile->getFileKey(); // Output a copy of this first to chunk 0 location: - $status = $this->outputChunk( $this->mLocalFile->getPath() ); + $this->outputChunk( $this->mLocalFile->getPath() ); // Update db table to reflect initial "chunk" state $this->updateChunkStatus(); @@ -113,7 +114,7 @@ class UploadFromChunks extends UploadFromFile { // Concatenate all the chunks to mVirtualTempPath $fileList = Array(); // The first chunk is stored at the mVirtualTempPath path so we start on "chunk 1" - for( $i = 0; $i <= $this->getChunkIndex(); $i++ ){ + for( $i = 0; $i <= $this->getChunkIndex(); $i++ ) { $fileList[] = $this->getVirtualChunkLocation( $i ); } @@ -122,13 +123,16 @@ class UploadFromChunks extends UploadFromFile { // Get a 0-byte temp file to perform the concatenation at $tmpFile = TempFSFile::factory( 'chunkedupload_', $ext ); $tmpPath = $tmpFile - ? $tmpFile->getPath() + ? $tmpFile->bind( $this )->getPath() // keep alive with $this : false; // fail in concatenate() // Concatenate the chunks at the temp file + $tStart = microtime( true ); $status = $this->repo->concatenate( $fileList, $tmpPath, FileRepo::DELETE_SOURCE ); - if( !$status->isOk() ){ + $tAmount = microtime( true ) - $tStart; + if( !$status->isOk() ) { return $status; } + wfDebugLog( 'fileconcatenate', "Combined $i chunks in $tAmount seconds.\n" ); $this->mTempPath = $tmpPath; // file system path $this->mFileSize = filesize( $this->mTempPath ); //Since this was set for the last chunk previously @@ -141,7 +145,11 @@ class UploadFromChunks extends UploadFromFile { // Update the mTempPath and mLocalFile // ( for FileUpload or normal Stash to take over ) - $this->mLocalFile = parent::stashFile(); + $tStart = microtime( true ); + $this->mLocalFile = parent::stashFile( $this->user ); + $tAmount = microtime( true ) - $tStart; + $this->mLocalFile->setLocalReference( $tmpFile ); // reuse (e.g. for getImageInfo()) + wfDebugLog( 'fileconcatenate', "Stashed combined file ($i chunks) in $tAmount seconds.\n" ); return $status; } @@ -164,7 +172,7 @@ class UploadFromChunks extends UploadFromFile { * @param $index * @return string */ - function getVirtualChunkLocation( $index ){ + function getVirtualChunkLocation( $index ) { return $this->repo->getVirtualUrl( 'temp' ) . '/' . $this->repo->getHashPath( @@ -176,9 +184,9 @@ class UploadFromChunks extends UploadFromFile { /** * Add a chunk to the temporary directory * - * @param $chunkPath string path to temporary chunk file - * @param $chunkSize int size of the current chunk - * @param $offset int offset of current chunk ( mutch match database chunk offset ) + * @param string $chunkPath path to temporary chunk file + * @param int $chunkSize size of the current chunk + * @param int $offset offset of current chunk ( mutch match database chunk offset ) * @return Status */ public function addChunk( $chunkPath, $chunkSize, $offset ) { @@ -202,7 +210,7 @@ class UploadFromChunks extends UploadFromFile { return Status::newFatal( $e->getMessage() ); } $status = $this->outputChunk( $chunkPath ); - if( $status->isGood() ){ + if( $status->isGood() ) { // Update local offset: $this->mOffset = $preAppendOffset + $chunkSize; // Update chunk table status db @@ -218,11 +226,14 @@ class UploadFromChunks extends UploadFromFile { /** * Update the chunk db table with the current status: */ - private function updateChunkStatus(){ + private function updateChunkStatus() { wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" . $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" ); $dbw = $this->repo->getMasterDb(); + // Use a quick transaction since we will upload the full temp file into shared + // storage, which takes time for large files. We don't want to hold locks then. + $dbw->begin( __METHOD__ ); $dbw->update( 'uploadstash', array( @@ -233,12 +244,13 @@ class UploadFromChunks extends UploadFromFile { array( 'us_key' => $this->mFileKey ), __METHOD__ ); + $dbw->commit( __METHOD__ ); } /** * Get the chunk db state and populate update relevant local values */ - private function getChunkStatus(){ + private function getChunkStatus() { // get Master db to avoid race conditions. // Otherwise, if chunk upload time < replag there will be spurious errors $dbw = $this->repo->getMasterDb(); @@ -264,8 +276,8 @@ class UploadFromChunks extends UploadFromFile { * Get the current Chunk index * @return Integer index of the current chunk */ - private function getChunkIndex(){ - if( $this->mChunkIndex !== null ){ + private function getChunkIndex() { + if( $this->mChunkIndex !== null ) { return $this->mChunkIndex; } return 0; @@ -275,8 +287,8 @@ class UploadFromChunks extends UploadFromFile { * Gets the current offset in fromt the stashedupload table * @return Integer current byte offset of the chunk file set */ - private function getOffset(){ - if ( $this->mOffset !== null ){ + private function getOffset() { + if ( $this->mOffset !== null ) { return $this->mOffset; } return 0; @@ -289,7 +301,7 @@ class UploadFromChunks extends UploadFromFile { * @throws UploadChunkFileException * @return FileRepoStatus */ - private function outputChunk( $chunkPath ){ + private function outputChunk( $chunkPath ) { // Key is fileKey + chunk index $fileKey = $this->getChunkFileKey(); @@ -314,11 +326,11 @@ class UploadFromChunks extends UploadFromFile { return $storeStatus; } - private function getChunkFileKey( $index = null ){ - if( $index === null ){ + private function getChunkFileKey( $index = null ) { + if( $index === null ) { $index = $this->getChunkIndex(); } - return $this->mFileKey . '.' . $index ; + return $this->mFileKey . '.' . $index; } /** |