Merge "[FileBackend] Added optional callback parameter to concatenate()."

This commit is contained in:
Demon 2012-11-21 13:01:49 +00:00 committed by Gerrit Code Review
commit d0997617b2
3 changed files with 27 additions and 2 deletions

View file

@ -660,11 +660,21 @@ abstract class FileBackend {
* 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 );

View file

@ -350,8 +350,12 @@ abstract class FileBackendStore extends FileBackend {
*/
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();
@ -359,6 +363,7 @@ abstract class FileBackendStore extends FileBackend {
wfRestoreWarnings();
if ( !$ok ) { // not present or not empty
$status->fatal( 'backend-fail-opentemp', $tmpPath );
$callback( $status, null ); // update progress
return $status;
}
@ -369,6 +374,7 @@ abstract class FileBackendStore extends FileBackend {
$fsFile = $this->getLocalReference( array( 'src' => $path ) );
if ( !$fsFile ) { // retry failed?
$status->fatal( 'backend-fail-read', $path );
$callback( $status, null ); // update progress
return $status;
}
}
@ -379,16 +385,20 @@ abstract class FileBackendStore extends FileBackend {
$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)
@ -396,16 +406,20 @@ abstract class FileBackendStore extends FileBackend {
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;
}

View file

@ -988,9 +988,10 @@ class FileRepo {
* @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 ) {
public function concatenate( array $srcPaths, $dstPath, $flags = 0, Closure $callback = null ) {
$this->assertWritableRepo(); // fail out if read-only
$status = $this->newGood();
@ -1003,7 +1004,7 @@ class FileRepo {
}
// Concatenate the chunks into one FS file
$params = array( 'srcs' => $sources, 'dst' => $dstPath );
$params = array( 'srcs' => $sources, 'dst' => $dstPath, 'callback' => $callback );
$status->merge( $this->backend->concatenate( $params ) );
if ( !$status->isOK() ) {
return $status;