summaryrefslogtreecommitdiff
path: root/includes/upload/UploadFromChunks.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/upload/UploadFromChunks.php')
-rw-r--r--includes/upload/UploadFromChunks.php56
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;
}
/**