From 36c0c1edb6e713a797e7fde52f716ca17f548866 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 22 Aug 2012 11:51:38 -0700 Subject: [PATCH] [FileBackend] MultiWrite options to avoid pushing certain changes to all backends. * This can be used to no-op dir and file operations on the clone backends for the 'thumb' and 'temp' zones to reduce load or avoid hitting certain mounts. Change-Id: I2c57904b8264b7479b17736333b0b9228b469bbc --- .../filebackend/FileBackendMultiWrite.php | 93 +++++++++++++------ 1 file changed, 64 insertions(+), 29 deletions(-) diff --git a/includes/filebackend/FileBackendMultiWrite.php b/includes/filebackend/FileBackendMultiWrite.php index f4a7eac00c..0c8968aadf 100644 --- a/includes/filebackend/FileBackendMultiWrite.php +++ b/includes/filebackend/FileBackendMultiWrite.php @@ -43,7 +43,10 @@ class FileBackendMultiWrite extends FileBackend { /** @var Array Prioritized list of FileBackendStore objects */ protected $backends = array(); // array of (backend index => backends) protected $masterIndex = -1; // integer; index of master backend - protected $syncChecks = 0; // integer bitfield + protected $syncChecks = 0; // integer; bitfield + /** @var Array */ + protected $noPushDirConts = array(); + protected $noPushQuickOps = false; // boolean /* Possible internal backend consistency checks */ const CHECK_SIZE = 1; @@ -55,18 +58,21 @@ class FileBackendMultiWrite extends FileBackend { * Locking, journaling, and read-only checks are handled by the proxy backend. * * Additional $config params include: - * - backends : Array of backend config and multi-backend settings. - * Each value is the config used in the constructor of a - * FileBackendStore class, but with these additional settings: - * - class : The name of the backend class - * - isMultiMaster : This must be set for one backend. - * - template: : If given a backend name, this will use - * the config of that backend as a template. - * Values specified here take precedence. - * - syncChecks : Integer bitfield of internal backend sync checks to perform. - * Possible bits include the FileBackendMultiWrite::CHECK_* constants. - * There are constants for SIZE, TIME, and SHA1. - * The checks are done before allowing any file operations. + * - backends : Array of backend config and multi-backend settings. + * Each value is the config used in the constructor of a + * FileBackendStore class, but with these additional settings: + * - class : The name of the backend class + * - isMultiMaster : This must be set for one backend. + * - template: : If given a backend name, this will use + * the config of that backend as a template. + * Values specified here take precedence. + * - syncChecks : Integer bitfield of internal backend sync checks to perform. + * Possible bits include the FileBackendMultiWrite::CHECK_* constants. + * There are constants for SIZE, TIME, and SHA1. + * The checks are done before allowing any file operations. + * - noPushQuickOps : (hack) Only apply doQuickOperations() to the master backend. + * - noPushDirConts : (hack) Only apply directory functions to the master backend. + * * @param $config Array * @throws MWException */ @@ -75,6 +81,12 @@ class FileBackendMultiWrite extends FileBackend { $this->syncChecks = isset( $config['syncChecks'] ) ? $config['syncChecks'] : self::CHECK_SIZE; + $this->noPushQuickOps = isset( $config['noPushQuickOps'] ) + ? $config['noPushQuickOps'] + : false; + $this->noPushDirConts = isset( $config['noPushDirConts'] ) + ? $config['noPushDirConts'] + : array(); // Construct backends here rather than via registration // to keep these backends hidden from outside the proxy. $namesUsed = array(); @@ -368,10 +380,12 @@ class FileBackendMultiWrite extends FileBackend { $masterStatus = $this->backends[$this->masterIndex]->doQuickOperations( $realOps ); $status->merge( $masterStatus ); // Propagate the operations to the clone backends... - foreach ( $this->backends as $index => $backend ) { - if ( $index !== $this->masterIndex ) { // not done already - $realOps = $this->substOpBatchPaths( $ops, $backend ); - $status->merge( $backend->doQuickOperations( $realOps ) ); + if ( !$this->noPushQuickOps ) { + foreach ( $this->backends as $index => $backend ) { + if ( $index !== $this->masterIndex ) { // not done already + $realOps = $this->substOpBatchPaths( $ops, $backend ); + $status->merge( $backend->doQuickOperations( $realOps ) ); + } } } // Make 'success', 'successCount', and 'failCount' fields reflect @@ -383,15 +397,27 @@ class FileBackendMultiWrite extends FileBackend { return $status; } + /** + * @param $path string Storage path + * @return bool Path container should have dir changes pushed to all backends + */ + protected function replicateContainerDirChanges( $path ) { + list( $b, $shortCont, $r ) = self::splitStoragePath( $path ); + return !in_array( $shortCont, $this->noPushDirConts ); + } + /** * @see FileBackend::doPrepare() * @return Status */ protected function doPrepare( array $params ) { $status = Status::newGood(); - foreach ( $this->backends as $backend ) { - $realParams = $this->substOpPaths( $params, $backend ); - $status->merge( $backend->doPrepare( $realParams ) ); + $replicate = $this->replicateContainerDirChanges( $params['dir'] ); + foreach ( $this->backends as $index => $backend ) { + if ( $replicate || $index == $this->masterIndex ) { + $realParams = $this->substOpPaths( $params, $backend ); + $status->merge( $backend->doPrepare( $realParams ) ); + } } return $status; } @@ -403,9 +429,12 @@ class FileBackendMultiWrite extends FileBackend { */ protected function doSecure( array $params ) { $status = Status::newGood(); - foreach ( $this->backends as $backend ) { - $realParams = $this->substOpPaths( $params, $backend ); - $status->merge( $backend->doSecure( $realParams ) ); + $replicate = $this->replicateContainerDirChanges( $params['dir'] ); + foreach ( $this->backends as $index => $backend ) { + if ( $replicate || $index == $this->masterIndex ) { + $realParams = $this->substOpPaths( $params, $backend ); + $status->merge( $backend->doSecure( $realParams ) ); + } } return $status; } @@ -417,9 +446,12 @@ class FileBackendMultiWrite extends FileBackend { */ protected function doPublish( array $params ) { $status = Status::newGood(); - foreach ( $this->backends as $backend ) { - $realParams = $this->substOpPaths( $params, $backend ); - $status->merge( $backend->doPublish( $realParams ) ); + $replicate = $this->replicateContainerDirChanges( $params['dir'] ); + foreach ( $this->backends as $index => $backend ) { + if ( $replicate || $index == $this->masterIndex ) { + $realParams = $this->substOpPaths( $params, $backend ); + $status->merge( $backend->doPublish( $realParams ) ); + } } return $status; } @@ -431,9 +463,12 @@ class FileBackendMultiWrite extends FileBackend { */ protected function doClean( array $params ) { $status = Status::newGood(); - foreach ( $this->backends as $backend ) { - $realParams = $this->substOpPaths( $params, $backend ); - $status->merge( $backend->doClean( $realParams ) ); + $replicate = $this->replicateContainerDirChanges( $params['dir'] ); + foreach ( $this->backends as $index => $backend ) { + if ( $replicate || $index == $this->masterIndex ) { + $realParams = $this->substOpPaths( $params, $backend ); + $status->merge( $backend->doClean( $realParams ) ); + } } return $status; } -- 2.20.1