* otherwise safe from modification from other processes. Normally,
* the file will be a new temp file, which should be adequate.
*
- * If a callback function is given, it will be called each time a segment is
- * appended and when the overall concatenate operation completes or fails.
- * The arguments passed in are:
- * - 1) A Status object containing errors if any problems occurred.
- * - 2) The index of the relevant segment (starting at 1) if a segment was appended
- * (including the last one) or null in the case of overall success or failure.
- * When a good Status is returned with a null segment, then the operation completed.
- * Callbacks should generally avoid throwing exceptions.
- *
* @param $params Array Operation parameters
* $params include:
* - srcs : ordered source storage paths (e.g. chunk1, chunk2, ...)
* - dst : file system path to 0-byte temp file
* - parallelize : try to do operations in parallel when possible
- * - callback : closure called when chunks are appended and on success/failure
* @return Status
*/
abstract public function concatenate( array $params );
*/
protected function doConcatenate( array $params ) {
$status = Status::newGood();
-
$tmpPath = $params['dst']; // convenience
unset( $params['latest'] ); // sanity
- $callback = isset( $params['callback'] )
- ? $params['callback']
- : function( Status $status, $segment ) {};
// Check that the specified temp file is valid...
wfSuppressWarnings();
wfRestoreWarnings();
if ( !$ok ) { // not present or not empty
$status->fatal( 'backend-fail-opentemp', $tmpPath );
- $callback( $status, null ); // update progress
return $status;
}
$fsFile = $this->getLocalReference( array( 'src' => $path ) );
if ( !$fsFile ) { // retry failed?
$status->fatal( 'backend-fail-read', $path );
- $callback( $status, null ); // update progress
return $status;
}
}
$tmpHandle = fopen( $tmpPath, 'ab' );
if ( $tmpHandle === false ) {
$status->fatal( 'backend-fail-opentemp', $tmpPath );
- $callback( $status, null ); // update progress
return $status;
}
- $segment = 0; // segment number
// Build up the temp file using the source chunks (in order)...
foreach ( $fsFiles as $virtualSource => $fsFile ) {
- ++$segment; // first segment is "1"
// Get a handle to the local FS version
$sourceHandle = fopen( $fsFile->getPath(), 'rb' );
if ( $sourceHandle === false ) {
fclose( $tmpHandle );
$status->fatal( 'backend-fail-read', $virtualSource );
- $callback( $status, null ); // update progress
return $status;
}
// Append chunk to file (pass chunk size to avoid magic quotes)
fclose( $sourceHandle );
fclose( $tmpHandle );
$status->fatal( 'backend-fail-writetemp', $tmpPath );
- $callback( $status , null );
return $status;
}
fclose( $sourceHandle );
- $callback( $status, $segment ); // update progress (chunk success)
}
if ( !fclose( $tmpHandle ) ) {
$status->fatal( 'backend-fail-closetemp', $tmpPath );
- $callback( $status, null ); // update progress
return $status;
}
clearstatcache(); // temp file changed
- $callback( $status, null ); // update progress (full success)
return $status;
}
* @param $dstPath String Target file system path
* @param $flags Integer: bitwise combination of the following flags:
* self::DELETE_SOURCE Delete the source files
- * @param $callback Closure Optional callback function (see FileBackend::concatenate())
* @return FileRepoStatus
*/
- public function concatenate( array $srcPaths, $dstPath, $flags = 0, Closure $callback = null ) {
+ public function concatenate( array $srcPaths, $dstPath, $flags = 0 ) {
$this->assertWritableRepo(); // fail out if read-only
$status = $this->newGood();
}
// Concatenate the chunks into one FS file
- $params = array( 'srcs' => $sources, 'dst' => $dstPath, 'callback' => $callback );
+ $params = array( 'srcs' => $sources, 'dst' => $dstPath );
$status->merge( $this->backend->concatenate( $params ) );
if ( !$status->isOK() ) {
return $status;