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.php122
1 files changed, 76 insertions, 46 deletions
diff --git a/includes/upload/UploadFromChunks.php b/includes/upload/UploadFromChunks.php
index ec83f7d3..0542bba5 100644
--- a/includes/upload/UploadFromChunks.php
+++ b/includes/upload/UploadFromChunks.php
@@ -1,5 +1,27 @@
<?php
/**
+ * Backend for uploading files from chunks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Upload
+ */
+
+/**
* Implements uploading from chunks
*
* @ingroup Upload
@@ -7,10 +29,10 @@
*/
class UploadFromChunks extends UploadFromFile {
protected $mOffset, $mChunkIndex, $mFileKey, $mVirtualTempPath;
-
+
/**
* Setup local pointers to stash, repo and user ( similar to UploadFromStash )
- *
+ *
* @param $user User
* @param $stash UploadStash
* @param $repo FileRepo
@@ -39,37 +61,37 @@ class UploadFromChunks extends UploadFromFile {
return true;
}
/**
- * Calls the parent stashFile and updates the uploadsession table to handle "chunks"
+ * Calls the parent stashFile and updates the uploadsession table to handle "chunks"
*
* @return UploadStashFile stashed file
*/
public function stashFile() {
- // Stash file is the called on creating a new chunk session:
+ // Stash file is the called on creating a new chunk session:
$this->mChunkIndex = 0;
$this->mOffset = 0;
// Create a local stash target
$this->mLocalFile = parent::stashFile();
- // Update the initial file offset ( based on file size )
+ // Update the initial file offset ( based on file size )
$this->mOffset = $this->mLocalFile->getSize();
$this->mFileKey = $this->mLocalFile->getFileKey();
// Output a copy of this first to chunk 0 location:
$status = $this->outputChunk( $this->mLocalFile->getPath() );
-
- // Update db table to reflect initial "chunk" state
+
+ // Update db table to reflect initial "chunk" state
$this->updateChunkStatus();
return $this->mLocalFile;
}
-
+
/**
* Continue chunk uploading
- */
+ */
public function continueChunks( $name, $key, $webRequestUpload ) {
$this->mFileKey = $key;
$this->mUpload = $webRequestUpload;
- // Get the chunk status form the db:
+ // Get the chunk status form the db:
$this->getChunkStatus();
-
+
$metadata = $this->stash->getMetadata( $key );
$this->initializePathInfo( $name,
$this->getRealPath( $metadata['us_path'] ),
@@ -77,13 +99,13 @@ class UploadFromChunks extends UploadFromFile {
false
);
}
-
+
/**
* Append the final chunk and ready file for parent::performUpload()
* @return FileRepoStatus
*/
public function concatenateChunks() {
- wfDebug( __METHOD__ . " concatenate {$this->mChunkIndex} chunks:" .
+ wfDebug( __METHOD__ . " concatenate {$this->mChunkIndex} chunks:" .
$this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
// Concatenate all the chunks to mVirtualTempPath
@@ -103,10 +125,10 @@ class UploadFromChunks extends UploadFromFile {
// Concatenate the chunks at the temp file
$status = $this->repo->concatenate( $fileList, $tmpPath, FileRepo::DELETE_SOURCE );
if( !$status->isOk() ){
- return $status;
+ return $status;
}
// Update the mTempPath and mLocalFile
- // ( for FileUpload or normal Stash to take over )
+ // ( for FileUpload or normal Stash to take over )
$this->mTempPath = $tmpPath; // file system path
$this->mLocalFile = parent::stashFile();
@@ -127,42 +149,44 @@ class UploadFromChunks extends UploadFromFile {
}
/**
- * Returns the virtual chunk location:
- * @param unknown_type $index
+ * Returns the virtual chunk location:
+ * @param $index
+ * @return string
*/
function getVirtualChunkLocation( $index ){
- return $this->repo->getVirtualUrl( 'temp' ) .
+ return $this->repo->getVirtualUrl( 'temp' ) .
'/' .
- $this->repo->getHashPath(
+ $this->repo->getHashPath(
$this->getChunkFileKey( $index )
- ) .
+ ) .
$this->getChunkFileKey( $index );
}
+
/**
* Add a chunk to the temporary directory
*
- * @param $chunkPath path to temporary chunk file
- * @param $chunkSize size of the current chunk
- * @param $offset offset of current chunk ( mutch match database chunk offset )
+ * @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 )
* @return Status
*/
public function addChunk( $chunkPath, $chunkSize, $offset ) {
// Get the offset before we add the chunk to the file system
$preAppendOffset = $this->getOffset();
-
+
if ( $preAppendOffset + $chunkSize > $this->getMaxUploadSize()) {
$status = Status::newFatal( 'file-too-large' );
} else {
// Make sure the client is uploading the correct chunk with a matching offset.
if ( $preAppendOffset == $offset ) {
- // Update local chunk index for the current chunk
+ // Update local chunk index for the current chunk
$this->mChunkIndex++;
$status = $this->outputChunk( $chunkPath );
if( $status->isGood() ){
- // Update local offset:
+ // Update local offset:
$this->mOffset = $preAppendOffset + $chunkSize;
- // Update chunk table status db
- $this->updateChunkStatus();
+ // Update chunk table status db
+ $this->updateChunkStatus();
}
} else {
$status = Status::newFatal( 'invalid-chunk-offset' );
@@ -170,18 +194,18 @@ class UploadFromChunks extends UploadFromFile {
}
return $status;
}
-
+
/**
- * Update the chunk db table with the current status:
+ * Update the chunk db table with the current status:
*/
private function updateChunkStatus(){
- wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" .
+ wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" .
$this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
-
+
$dbw = $this->repo->getMasterDb();
$dbw->update(
'uploadstash',
- array(
+ array(
'us_status' => 'chunks',
'us_chunk_inx' => $this->getChunkIndex(),
'us_size' => $this->getOffset()
@@ -190,16 +214,17 @@ class UploadFromChunks extends UploadFromFile {
__METHOD__
);
}
+
/**
* Get the chunk db state and populate update relevant local values
*/
private function getChunkStatus(){
- // get Master db to avoid race conditions.
+ // get Master db to avoid race conditions.
// Otherwise, if chunk upload time < replag there will be spurious errors
$dbw = $this->repo->getMasterDb();
$row = $dbw->selectRow(
- 'uploadstash',
- array(
+ 'uploadstash',
+ array(
'us_chunk_inx',
'us_size',
'us_path',
@@ -214,8 +239,9 @@ class UploadFromChunks extends UploadFromFile {
$this->mVirtualTempPath = $row->us_path;
}
}
+
/**
- * Get the current Chunk index
+ * Get the current Chunk index
* @return Integer index of the current chunk
*/
private function getChunkIndex(){
@@ -224,10 +250,10 @@ class UploadFromChunks extends UploadFromFile {
}
return 0;
}
-
+
/**
- * Gets the current offset in fromt the stashedupload table
- * @return Integer current byte offset of the chunk file set
+ * 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 ){
@@ -235,20 +261,23 @@ class UploadFromChunks extends UploadFromFile {
}
return 0;
}
-
+
/**
* Output the chunk to disk
- *
+ *
* @param $chunkPath string
+ * @throws UploadChunkFileException
+ * @return FileRepoStatus
*/
private function outputChunk( $chunkPath ){
// Key is fileKey + chunk index
$fileKey = $this->getChunkFileKey();
-
- // Store the chunk per its indexed fileKey:
+
+ // Store the chunk per its indexed fileKey:
$hashPath = $this->repo->getHashPath( $fileKey );
- $storeStatus = $this->repo->store( $chunkPath, 'temp', "$hashPath$fileKey" );
-
+ $storeStatus = $this->repo->quickImport( $chunkPath,
+ $this->repo->getZonePath( 'temp' ) . "/{$hashPath}{$fileKey}" );
+
// Check for error in stashing the chunk:
if ( ! $storeStatus->isOK() ) {
$error = $storeStatus->getErrorsArray();
@@ -264,6 +293,7 @@ class UploadFromChunks extends UploadFromFile {
}
return $storeStatus;
}
+
private function getChunkFileKey( $index = null ){
if( $index === null ){
$index = $this->getChunkIndex();