/**
* Store a file to a given destination.
*
- * @param $srcPath String: source FS path, storage path, or virtual URL
+ * @param $srcPath String: source file system path, storage path, or virtual URL
* @param $dstZone String: destination zone
* @param $dstRel String: destination relative path
* @param $flags Integer: bitwise combination of the following flags:
* This function can be used to write to otherwise read-only foreign repos.
* This is intended for copying generated thumbnails into the repo.
*
- * @param $src string File system path
+ * @param $src string Source file system path, storage path, or virtual URL
* @param $dst string Virtual URL or storage path
* @param $disposition string|null Content-Disposition if given and supported
* @return FileRepoStatus
* This function can be used to write to otherwise read-only foreign repos.
* This is intended for copying generated thumbnails into the repo.
*
+ * All path parameters may be a file system path, storage path, or virtual URL.
* When "dispositions" are given they are used as Content-Disposition if supported.
*
- * @param $triples Array List of (file system path, virtual URL/storage path, disposition)
+ * @param $triples Array List of (source path, destination path, disposition)
* @return FileRepoStatus
*/
public function quickImportBatch( array $triples ) {
$operations = array();
foreach ( $triples as $triple ) {
list( $src, $dst ) = $triple;
+ $src = $this->resolveToStoragePath( $src );
$dst = $this->resolveToStoragePath( $dst );
$operations[] = array(
- 'op' => 'store',
+ 'op' => FileBackend::isStoragePath( $src ) ? 'copy' : 'store',
'src' => $src,
'dst' => $dst,
'disposition' => isset( $triple[2] ) ? $triple[2] : null
/**
* Copy or move a file either from a storage path, virtual URL,
- * or FS path, into this repository at the specified destination location.
+ * or file system path, into this repository at the specified destination location.
*
* Returns a FileRepoStatus object. On success, the value contains "new" or
* "archived", to indicate whether the file was new with that name.
*
- * @param $srcPath String: the source FS path, storage path, or URL
+ * @param $srcPath String: the source file system path, storage path, or URL
* @param $dstRel String: the destination relative path
* @param $archiveRel String: the relative path where the existing file is to
* be archived, if there is one. Relative to the public zone root.
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 );
* @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
// 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();
}
/**
- * Returns the virtual chunk location:
+ * 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 );
}
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' );
}
/**
- * 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()
* 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',
}
/**
- * Get the current Chunk index
+ * Get the current Chunk index
* @return Integer index of the current chunk
*/
private function getChunkIndex(){
}
/**
- * 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 ){
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();