* - content : the raw file contents
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
} else {
$status = $this->doCreateInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
}
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
* - src : source path on disk
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
} else {
$status = $this->doStoreInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
}
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
* - src : source storage path
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
wfProfileIn( __METHOD__ . '-' . $this->name );
$status = $this->doCopyInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
return $status;
* - src : source storage path
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
$status = $this->doMoveInternal( $params );
$this->clearCache( array( $params['src'], $params['dst'] ) );
$this->deleteFileCache( $params['src'] ); // persistent cache
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
return $status;
// Try to lock the source files for the scope of this function
$scopeLockS = $this->getScopedFileLocks( $params['srcs'], LockManager::LOCK_UW, $status );
if ( $status->isOK() ) {
- // Actually do the concatenation
+ // Actually do the file concatenation...
+ $start_time = microtime( true );
$status->merge( $this->doConcatenate( $params ) );
+ $sec = microtime( true ) - $start_time;
+ if ( !$status->isOK() ) {
+ wfDebugLog( 'FileOperation', get_class( $this ) . " failed to concatenate " .
+ count( $params['srcs'] ) . " file(s) [$sec sec]" );
+ }
}
wfProfileOut( __METHOD__ . '-' . $this->name );
}
// Clear any file cache entries (after locks acquired)
- $this->clearCache();
+ if ( empty( $opts['preserveCache'] ) ) {
+ $this->clearCache();
+ }
// Load from the persistent file and container caches
$this->primeFileCache( $performOps );
$this->primeContainerCache( $performOps );
// Actually attempt the operation batch...
+ $opts = $this->setConcurrencyFlags( $opts );
$subStatus = FileOpBatch::attempt( $performOps, $opts, $this->fileJournal );
// Merge errors into status fields
return array();
}
+ /**
+ * @see FileBackend::preloadCache()
+ */
+ final public function preloadCache( array $paths ) {
+ $fullConts = array(); // full container names
+ foreach ( $paths as $path ) {
+ list( $fullCont, $r, $s ) = $this->resolveStoragePath( $path );
+ $fullConts[] = $fullCont;
+ }
+ // Load from the persistent file and container caches
+ $this->primeContainerCache( $fullConts );
+ $this->primeFileCache( $paths );
+ }
+
/**
* @see FileBackend::clearCache()
*/
}
/**
- * Set the cached stat info for a file path
+ * Set the cached stat info for a file path.
+ * Negatives (404s) are not cached. By not caching negatives, we can skip cache
+ * salting for the case when a file is created at a path were there was none before.
*
* @param $path string Storage path
* @param $val mixed Information to cache
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
}
+
+ /**
+ * Set the 'concurrency' option from a list of operation options
+ *
+ * @param $opts array Map of operation options
+ * @return Array
+ */
+ final protected function setConcurrencyFlags( array $opts ) {
+ $opts['concurrency'] = 1; // off
+ if ( $this->parallelize === 'implicit' ) {
+ if ( !isset( $opts['parallelize'] ) || $opts['parallelize'] ) {
+ $opts['concurrency'] = $this->concurrency;
+ }
+ } elseif ( $this->parallelize === 'explicit' ) {
+ if ( !empty( $opts['parallelize'] ) ) {
+ $opts['concurrency'] = $this->concurrency;
+ }
+ }
+ return $opts;
+ }
}
/**