diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2013-12-08 09:55:49 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2013-12-08 09:55:49 +0100 |
commit | 4ac9fa081a7c045f6a9f1cfc529d82423f485b2e (patch) | |
tree | af68743f2f4a47d13f2b0eb05f5c4aaf86d8ea37 /includes/filebackend/FileBackendMultiWrite.php | |
parent | af4da56f1ad4d3ef7b06557bae365da2ea27a897 (diff) |
Update to MediaWiki 1.22.0
Diffstat (limited to 'includes/filebackend/FileBackendMultiWrite.php')
-rw-r--r-- | includes/filebackend/FileBackendMultiWrite.php | 179 |
1 files changed, 44 insertions, 135 deletions
diff --git a/includes/filebackend/FileBackendMultiWrite.php b/includes/filebackend/FileBackendMultiWrite.php index 939315d1..97584a71 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,26 +136,15 @@ class FileBackendMultiWrite extends FileBackend { } } - /** - * @see FileBackend::doOperationsInternal() - * @return Status - */ final protected function doOperationsInternal( array $ops, array $opts ) { $status = Status::newGood(); $mbe = $this->backends[$this->masterIndex]; // convenience - // Get the paths to lock from the master backend - $realOps = $this->substOpBatchPaths( $ops, $mbe ); - $paths = $mbe->getPathsToLockForOpsInternal( $mbe->getOperationsInternal( $realOps ) ); - // Get the paths under the proxy backend's name - $paths['sh'] = $this->unsubstPaths( $paths['sh'] ); - $paths['ex'] = $this->unsubstPaths( $paths['ex'] ); // Try to lock those files for the scope of this function... if ( empty( $opts['nonLocking'] ) ) { // Try to lock those files for the scope of this function... - $scopeLockS = $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status ); - $scopeLockE = $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status ); + $scopeLock = $this->getScopedLocksForOps( $ops, $status ); if ( !$status->isOK() ) { return $status; // abort } @@ -177,6 +171,7 @@ class FileBackendMultiWrite extends FileBackend { } } // Actually attempt the operation batch on the master backend... + $realOps = $this->substOpBatchPaths( $ops, $mbe ); $masterStatus = $mbe->doOperations( $realOps, $opts ); $status->merge( $masterStatus ); // Propagate the operations to the clone backends if there were no unexpected errors @@ -304,11 +299,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 +311,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 +377,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 +398,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 +410,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 +435,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... @@ -457,14 +464,10 @@ class FileBackendMultiWrite extends FileBackend { * @return bool Path container should have dir changes pushed to all backends */ protected function replicateContainerDirChanges( $path ) { - list( , $shortCont, ) = self::splitStoragePath( $path ); + list( , $shortCont, ) = self::splitStoragePath( $path ); 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 +480,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 +492,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 +504,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 +516,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 +553,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 +579,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 +590,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,19 +617,17 @@ class FileBackendMultiWrite extends FileBackend { } } - /** - * @see FileBackend::getScopedLocksForOps() - */ public function getScopedLocksForOps( array $ops, Status $status ) { - $fileOps = $this->backends[$this->masterIndex]->getOperationsInternal( $ops ); + $realOps = $this->substOpBatchPaths( $ops, $this->backends[$this->masterIndex] ); + $fileOps = $this->backends[$this->masterIndex]->getOperationsInternal( $realOps ); // Get the paths to lock from the master backend $paths = $this->backends[$this->masterIndex]->getPathsToLockForOpsInternal( $fileOps ); // Get the paths under the proxy backend's name - $paths['sh'] = $this->unsubstPaths( $paths['sh'] ); - $paths['ex'] = $this->unsubstPaths( $paths['ex'] ); - return array( - $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status ), - $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status ) + $pbPaths = array( + LockManager::LOCK_UW => $this->unsubstPaths( $paths[LockManager::LOCK_UW] ), + LockManager::LOCK_EX => $this->unsubstPaths( $paths[LockManager::LOCK_EX] ) ); + // Actually acquire the locks + return array( $this->getScopedFileLocks( $pbPaths, 'mixed', $status ) ); } } |