X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Ffilebackend%2FFileBackendMultiWrite.php;h=7d354870d7a028a6eb5f9ed460de6366abc9d116;hb=2fe1b773d3da27e379485e049c239d9ac6cd6365;hp=17b060c37111541c15ea1259c9ac638f944a88fa;hpb=e0f1be027b69e666ea315cd98795146a55fcabe9;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/filebackend/FileBackendMultiWrite.php b/includes/filebackend/FileBackendMultiWrite.php index 17b060c371..7d354870d7 100644 --- a/includes/filebackend/FileBackendMultiWrite.php +++ b/includes/filebackend/FileBackendMultiWrite.php @@ -75,10 +75,13 @@ class FileBackendMultiWrite extends FileBackend { * - autoResync : Automatically resync the clone backends to the master backend * when pre-operation sync checks fail. This should only be used * if the master backend is stable and not missing any files. + * Use "conservative" to limit resyncing to copying newer master + * backend files over older (or non-existing) clone backend files. + * Cases that cannot be handled will result in operation abortion. * - noPushQuickOps : (hack) Only apply doQuickOperations() to the master backend. * - noPushDirConts : (hack) Only apply directory functions to the master backend. * - * @param $config Array + * @param Array $config * @throws MWException */ public function __construct( array $config ) { @@ -86,7 +89,9 @@ class FileBackendMultiWrite extends FileBackend { $this->syncChecks = isset( $config['syncChecks'] ) ? $config['syncChecks'] : self::CHECK_SIZE; - $this->autoResync = !empty( $config['autoResync'] ); + $this->autoResync = isset( $config['autoResync'] ) + ? $config['autoResync'] + : false; $this->noPushQuickOps = isset( $config['noPushQuickOps'] ) ? $config['noPushQuickOps'] : false; @@ -131,10 +136,6 @@ class FileBackendMultiWrite extends FileBackend { } } - /** - * @see FileBackend::doOperationsInternal() - * @return Status - */ final protected function doOperationsInternal( array $ops, array $opts ) { $status = Status::newGood(); @@ -304,11 +305,11 @@ class FileBackendMultiWrite extends FileBackend { $mBackend = $this->backends[$this->masterIndex]; foreach ( $paths as $path ) { $mPath = $this->substPaths( $path, $mBackend ); - $mSha1 = $mBackend->getFileSha1Base36( array( 'src' => $mPath ) ); - $mExist = $mBackend->fileExists( array( 'src' => $mPath ) ); - // Check if the master backend is available... - if ( $mExist === null ) { + $mSha1 = $mBackend->getFileSha1Base36( array( 'src' => $mPath, 'latest' => true ) ); + $mStat = $mBackend->getFileStat( array( 'src' => $mPath, 'latest' => true ) ); + if ( $mStat === null || ( $mSha1 !== false && !$mStat ) ) { // sanity $status->fatal( 'backend-fail-internal', $this->name ); + continue; // file is not available on the master backend... } // Check of all clone backends agree with the master... foreach ( $this->backends as $index => $cBackend ) { @@ -316,15 +317,31 @@ class FileBackendMultiWrite extends FileBackend { continue; // master } $cPath = $this->substPaths( $path, $cBackend ); - $cSha1 = $cBackend->getFileSha1Base36( array( 'src' => $cPath ) ); + $cSha1 = $cBackend->getFileSha1Base36( array( 'src' => $cPath, 'latest' => true ) ); + $cStat = $cBackend->getFileStat( array( 'src' => $cPath, 'latest' => true ) ); + if ( $cStat === null || ( $cSha1 !== false && !$cStat ) ) { // sanity + $status->fatal( 'backend-fail-internal', $cBackend->getName() ); + continue; // file is not available on the clone backend... + } if ( $mSha1 === $cSha1 ) { // already synced; nothing to do - } elseif ( $mSha1 ) { // file is in master - $fsFile = $mBackend->getLocalReference( array( 'src' => $mPath ) ); + } elseif ( $mSha1 !== false ) { // file is in master + if ( $this->autoResync === 'conservative' + && $cStat && $cStat['mtime'] > $mStat['mtime'] ) + { + $status->fatal( 'backend-fail-synced', $path ); + continue; // don't rollback data + } + $fsFile = $mBackend->getLocalReference( + array( 'src' => $mPath, 'latest' => true ) ); $status->merge( $cBackend->quickStore( array( 'src' => $fsFile->getPath(), 'dst' => $cPath ) ) ); - } elseif ( $mExist === false ) { // file is not in master + } elseif ( $mStat === false ) { // file is not in master + if ( $this->autoResync === 'conservative' ) { + $status->fatal( 'backend-fail-synced', $path ); + continue; // don't delete data + } $status->merge( $cBackend->quickDelete( array( 'src' => $cPath ) ) ); } } @@ -366,7 +383,7 @@ class FileBackendMultiWrite extends FileBackend { * for a set of operations with that of a given internal backend. * * @param array $ops List of file operation arrays - * @param $backend FileBackendStore + * @param FileBackendStore $backend * @return Array */ protected function substOpBatchPaths( array $ops, FileBackendStore $backend ) { @@ -387,7 +404,7 @@ class FileBackendMultiWrite extends FileBackend { * Same as substOpBatchPaths() but for a single operation * * @param array $ops File operation array - * @param $backend FileBackendStore + * @param FileBackendStore $backend * @return Array */ protected function substOpPaths( array $ops, FileBackendStore $backend ) { @@ -399,7 +416,7 @@ class FileBackendMultiWrite extends FileBackend { * Substitute the backend of storage paths with an internal backend's name * * @param array|string $paths List of paths or single string path - * @param $backend FileBackendStore + * @param FileBackendStore $backend * @return Array|string */ protected function substPaths( $paths, FileBackendStore $backend ) { @@ -424,10 +441,6 @@ class FileBackendMultiWrite extends FileBackend { ); } - /** - * @see FileBackend::doQuickOperationsInternal() - * @return Status - */ protected function doQuickOperationsInternal( array $ops ) { $status = Status::newGood(); // Do the operations on the master backend; setting Status fields... @@ -461,10 +474,6 @@ class FileBackendMultiWrite extends FileBackend { return !in_array( $shortCont, $this->noPushDirConts ); } - /** - * @see FileBackend::doPrepare() - * @return Status - */ protected function doPrepare( array $params ) { $status = Status::newGood(); $replicate = $this->replicateContainerDirChanges( $params['dir'] ); @@ -477,11 +486,6 @@ class FileBackendMultiWrite extends FileBackend { return $status; } - /** - * @see FileBackend::doSecure() - * @param $params array - * @return Status - */ protected function doSecure( array $params ) { $status = Status::newGood(); $replicate = $this->replicateContainerDirChanges( $params['dir'] ); @@ -494,11 +498,6 @@ class FileBackendMultiWrite extends FileBackend { return $status; } - /** - * @see FileBackend::doPublish() - * @param $params array - * @return Status - */ protected function doPublish( array $params ) { $status = Status::newGood(); $replicate = $this->replicateContainerDirChanges( $params['dir'] ); @@ -511,11 +510,6 @@ class FileBackendMultiWrite extends FileBackend { return $status; } - /** - * @see FileBackend::doClean() - * @param $params array - * @return Status - */ protected function doClean( array $params ) { $status = Status::newGood(); $replicate = $this->replicateContainerDirChanges( $params['dir'] ); @@ -528,62 +522,32 @@ class FileBackendMultiWrite extends FileBackend { return $status; } - /** - * @see FileBackend::concatenate() - * @param $params array - * @return Status - */ public function concatenate( array $params ) { // We are writing to an FS file, so we don't need to do this per-backend $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->concatenate( $realParams ); } - /** - * @see FileBackend::fileExists() - * @param $params array - * @return bool|null - */ public function fileExists( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->fileExists( $realParams ); } - /** - * @see FileBackend::getFileTimestamp() - * @param $params array - * @return bool|string - */ public function getFileTimestamp( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileTimestamp( $realParams ); } - /** - * @see FileBackend::getFileSize() - * @param $params array - * @return bool|int - */ public function getFileSize( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileSize( $realParams ); } - /** - * @see FileBackend::getFileStat() - * @param $params array - * @return Array|bool|null - */ public function getFileStat( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileStat( $realParams ); } - /** - * @see FileBackend::getFileContentsMulti() - * @param $params array - * @return bool|string - */ public function getFileContentsMulti( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); $contentsM = $this->backends[$this->masterIndex]->getFileContentsMulti( $realParams ); @@ -595,41 +559,21 @@ class FileBackendMultiWrite extends FileBackend { return $contents; } - /** - * @see FileBackend::getFileSha1Base36() - * @param $params array - * @return bool|string - */ public function getFileSha1Base36( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileSha1Base36( $realParams ); } - /** - * @see FileBackend::getFileProps() - * @param $params array - * @return Array - */ public function getFileProps( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileProps( $realParams ); } - /** - * @see FileBackend::streamFile() - * @param $params array - * @return \Status - */ public function streamFile( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->streamFile( $realParams ); } - /** - * @see FileBackend::getLocalReferenceMulti() - * @param $params array - * @return FSFile|null - */ public function getLocalReferenceMulti( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); $fsFilesM = $this->backends[$this->masterIndex]->getLocalReferenceMulti( $realParams ); @@ -641,11 +585,6 @@ class FileBackendMultiWrite extends FileBackend { return $fsFiles; } - /** - * @see FileBackend::getLocalCopyMulti() - * @param $params array - * @return null|TempFSFile - */ public function getLocalCopyMulti( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); $tempFilesM = $this->backends[$this->masterIndex]->getLocalCopyMulti( $realParams ); @@ -657,48 +596,26 @@ class FileBackendMultiWrite extends FileBackend { return $tempFiles; } - /** - * @see FileBackend::getFileHttpUrl() - * @return string|null - */ public function getFileHttpUrl( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileHttpUrl( $realParams ); } - /** - * @see FileBackend::directoryExists() - * @param $params array - * @return bool|null - */ public function directoryExists( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->directoryExists( $realParams ); } - /** - * @see FileBackend::getSubdirectoryList() - * @param $params array - * @return Array|null|Traversable - */ public function getDirectoryList( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getDirectoryList( $realParams ); } - /** - * @see FileBackend::getFileList() - * @param $params array - * @return Array|null|\Traversable - */ public function getFileList( array $params ) { $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); return $this->backends[$this->masterIndex]->getFileList( $realParams ); } - /** - * @see FileBackend::clearCache() - */ public function clearCache( array $paths = null ) { foreach ( $this->backends as $backend ) { $realPaths = is_array( $paths ) ? $this->substPaths( $paths, $backend ) : null; @@ -706,9 +623,6 @@ class FileBackendMultiWrite extends FileBackend { } } - /** - * @see FileBackend::getScopedLocksForOps() - */ public function getScopedLocksForOps( array $ops, Status $status ) { $fileOps = $this->backends[$this->masterIndex]->getOperationsInternal( $ops ); // Get the paths to lock from the master backend