Merge "[FileBackend] Added optional callback parameter to concatenate()."
This commit is contained in:
commit
d0997617b2
3 changed files with 27 additions and 2 deletions
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue