X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Ffilebackend%2FFileBackendStore.php;h=ce4deddf9af5435f2ce146b23e74db65d23155e8;hb=06db1a2335826d7da5da2a47ddec44a08094376d;hp=2d8214edc5204eca3dcee2c56f768ec78a7bfe96;hpb=eed31dbcd9f5ba292ba411094d6fbf86844ad726;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/filebackend/FileBackendStore.php b/includes/filebackend/FileBackendStore.php index 2d8214edc5..ce4deddf9a 100644 --- a/includes/filebackend/FileBackendStore.php +++ b/includes/filebackend/FileBackendStore.php @@ -46,7 +46,7 @@ abstract class FileBackendStore extends FileBackend { /** @var array Map of container names to sharding config */ protected $shardViaHashLevels = array(); - /** @var callback Method to get the MIME type of files */ + /** @var callable Method to get the MIME type of files */ protected $mimeCallback; protected $maxFileSize = 4294967296; // integer bytes (4GiB) @@ -464,7 +464,7 @@ abstract class FileBackendStore extends FileBackend { /** * @see FileBackendStore::doPrepare() - * @param $container + * @param string $container * @param string $dir * @param array $params * @return Status @@ -499,7 +499,7 @@ abstract class FileBackendStore extends FileBackend { /** * @see FileBackendStore::doSecure() - * @param $container + * @param string $container * @param string $dir * @param array $params * @return Status @@ -534,7 +534,7 @@ abstract class FileBackendStore extends FileBackend { /** * @see FileBackendStore::doPublish() - * @param $container + * @param string $container * @param string $dir * @param array $params * @return Status @@ -590,7 +590,7 @@ abstract class FileBackendStore extends FileBackend { /** * @see FileBackendStore::doClean() - * @param $container + * @param string $container * @param string $dir * @param array $params * @return Status @@ -962,7 +962,7 @@ abstract class FileBackendStore extends FileBackend { * @param string $container Resolved container name * @param string $dir Resolved path relative to container * @param array $params - * @return Traversable|Array|null Returns null on failure + * @return Traversable|array|null Returns null on failure */ abstract public function getDirectoryListInternal( $container, $dir, array $params ); @@ -992,7 +992,7 @@ abstract class FileBackendStore extends FileBackend { * @param string $container Resolved container name * @param string $dir Resolved path relative to container * @param array $params - * @return Traversable|Array|null Returns null on failure + * @return Traversable|array|null Returns null on failure */ abstract public function getFileListInternal( $container, $dir, array $params ); @@ -1102,19 +1102,35 @@ abstract class FileBackendStore extends FileBackend { $paths = array_merge( $paths, $op->storagePathsRead() ); $paths = array_merge( $paths, $op->storagePathsChanged() ); } + + // Enlarge the cache to fit the stat entries of these files + $this->cheapCache->resize( max( 2 * count( $paths ), self::CACHE_CHEAP_SIZE ) ); + // Load from the persistent container caches $this->primeContainerCache( $paths ); // Get the latest stat info for all the files (having locked them) - $this->preloadFileStat( array( 'srcs' => $paths, 'latest' => true ) ); + $ok = $this->preloadFileStat( array( 'srcs' => $paths, 'latest' => true ) ); - // Actually attempt the operation batch... - $opts = $this->setConcurrencyFlags( $opts ); - $subStatus = FileOpBatch::attempt( $performOps, $opts, $this->fileJournal ); + if ( $ok ) { + // Actually attempt the operation batch... + $opts = $this->setConcurrencyFlags( $opts ); + $subStatus = FileOpBatch::attempt( $performOps, $opts, $this->fileJournal ); + } else { + // If we could not even stat some files, then bail out... + $subStatus = Status::newFatal( 'backend-fail-internal', $this->name ); + foreach ( $ops as $i => $op ) { // mark each op as failed + $subStatus->success[$i] = false; + ++$subStatus->failCount; + } + } // Merge errors into status fields $status->merge( $subStatus ); $status->success = $subStatus->success; // not done in merge() + // Shrink the stat cache back to normal size + $this->cheapCache->resize( self::CACHE_CHEAP_SIZE ); + return $status; } @@ -1282,11 +1298,12 @@ abstract class FileBackendStore extends FileBackend { final public function preloadFileStat( array $params ) { $section = new ProfileSection( __METHOD__ . "-{$this->name}" ); + $success = true; // no network errors $params['concurrency'] = ( $this->parallelize !== 'off' ) ? $this->concurrency : 1; $stats = $this->doGetFileStatMulti( $params ); if ( $stats === null ) { - return; // not supported + return true; // not supported } $latest = !empty( $params['latest'] ); // use latest data? @@ -1318,9 +1335,12 @@ abstract class FileBackendStore extends FileBackend { array( 'hash' => false, 'latest' => $latest ) ); wfDebug( __METHOD__ . ": File $path does not exist.\n" ); } else { // an error occurred + $success = false; wfDebug( __METHOD__ . ": Could not stat file $path.\n" ); } } + + return $success; } /** @@ -1666,7 +1686,22 @@ abstract class FileBackendStore extends FileBackend { } $age = time() - wfTimestamp( TS_UNIX, $val['mtime'] ); $ttl = min( 7 * 86400, max( 300, floor( .1 * $age ) ) ); - $this->memCache->add( $this->fileCacheKey( $path ), $val, $ttl ); + $key = $this->fileCacheKey( $path ); + // Set the cache unless it is currently salted with the value "PURGED". + // Using add() handles this except it also is a no-op in that case where + // the current value is not "latest" but $val is, so use CAS in that case. + if ( !$this->memCache->add( $key, $val, $ttl ) && !empty( $val['latest'] ) ) { + $this->memCache->merge( + $key, + function( BagOStuff $cache, $key, $cValue ) use ( $val ) { + return ( is_array( $cValue ) && empty( $cValue['latest'] ) ) + ? $val // update the stat cache with the lastest info + : false; // do nothing (cache is salted or some error happened) + }, + $ttl, + 1 + ); + } } /**