Merge "Added readAffinity flag to FileBackendMultiWrite"
[lhc/web/wiklou.git] / includes / filebackend / FileBackendMultiWrite.php
index 10e5a1e..1603d44 100644 (file)
@@ -47,6 +47,8 @@ class FileBackendMultiWrite extends FileBackend {
 
        /** @var int Index of master backend */
        protected $masterIndex = -1;
+       /** @var int Index of read affinity backend */
+       protected $readIndex = -1;
 
        /** @var int Bitfield */
        protected $syncChecks = 0;
@@ -69,6 +71,7 @@ class FileBackendMultiWrite extends FileBackend {
         *                      FileBackendStore class, but with these additional settings:
         *                        - class         : The name of the backend class
         *                        - isMultiMaster : This must be set for one backend.
+        *                        - readAffinity  : Use this for reads without 'latest' set.
         *                        - template:     : If given a backend name, this will use
         *                                          the config of that backend as a template.
         *                                          Values specified here take precedence.
@@ -120,6 +123,9 @@ class FileBackendMultiWrite extends FileBackend {
                                $this->masterIndex = $index; // this is the "master"
                                $config['fileJournal'] = $this->fileJournal; // log under proxy backend
                        }
+                       if ( !empty( $config['readAffinity'] ) ) {
+                               $this->readIndex = $index; // prefer this for reads
+                       }
                        // Create sub-backend object
                        if ( !isset( $config['class'] ) ) {
                                throw new FileBackendError( 'No class given for a backend config.' );
@@ -130,6 +136,9 @@ class FileBackendMultiWrite extends FileBackend {
                if ( $this->masterIndex < 0 ) { // need backends and must have a master
                        throw new FileBackendError( 'No master backend defined.' );
                }
+               if ( $this->readIndex < 0 ) {
+                       $this->readIndex = $this->masterIndex; // default
+               }
        }
 
        final protected function doOperationsInternal( array $ops, array $opts ) {
@@ -505,44 +514,52 @@ class FileBackendMultiWrite extends FileBackend {
 
        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] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->concatenate( $realParams );
+               return $this->backends[$index]->concatenate( $realParams );
        }
 
        public function fileExists( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->fileExists( $realParams );
+               return $this->backends[$index]->fileExists( $realParams );
        }
 
        public function getFileTimestamp( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileTimestamp( $realParams );
+               return $this->backends[$index]->getFileTimestamp( $realParams );
        }
 
        public function getFileSize( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileSize( $realParams );
+               return $this->backends[$index]->getFileSize( $realParams );
        }
 
        public function getFileStat( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileStat( $realParams );
+               return $this->backends[$index]->getFileStat( $realParams );
        }
 
        public function getFileXAttributes( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileXAttributes( $realParams );
+               return $this->backends[$index]->getFileXAttributes( $realParams );
        }
 
        public function getFileContentsMulti( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
-               $contentsM = $this->backends[$this->masterIndex]->getFileContentsMulti( $realParams );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
+
+               $contentsM = $this->backends[$index]->getFileContentsMulti( $realParams );
 
                $contents = array(); // (path => FSFile) mapping using the proxy backend's name
                foreach ( $contentsM as $path => $data ) {
@@ -553,26 +570,31 @@ class FileBackendMultiWrite extends FileBackend {
        }
 
        public function getFileSha1Base36( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileSha1Base36( $realParams );
+               return $this->backends[$index]->getFileSha1Base36( $realParams );
        }
 
        public function getFileProps( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileProps( $realParams );
+               return $this->backends[$index]->getFileProps( $realParams );
        }
 
        public function streamFile( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->streamFile( $realParams );
+               return $this->backends[$index]->streamFile( $realParams );
        }
 
        public function getLocalReferenceMulti( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
-               $fsFilesM = $this->backends[$this->masterIndex]->getLocalReferenceMulti( $realParams );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
+
+               $fsFilesM = $this->backends[$index]->getLocalReferenceMulti( $realParams );
 
                $fsFiles = array(); // (path => FSFile) mapping using the proxy backend's name
                foreach ( $fsFilesM as $path => $fsFile ) {
@@ -583,8 +605,10 @@ class FileBackendMultiWrite extends FileBackend {
        }
 
        public function getLocalCopyMulti( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
-               $tempFilesM = $this->backends[$this->masterIndex]->getLocalCopyMulti( $realParams );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
+
+               $tempFilesM = $this->backends[$index]->getLocalCopyMulti( $realParams );
 
                $tempFiles = array(); // (path => TempFSFile) mapping using the proxy backend's name
                foreach ( $tempFilesM as $path => $tempFile ) {
@@ -595,9 +619,10 @@ class FileBackendMultiWrite extends FileBackend {
        }
 
        public function getFileHttpUrl( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
 
-               return $this->backends[$this->masterIndex]->getFileHttpUrl( $realParams );
+               return $this->backends[$index]->getFileHttpUrl( $realParams );
        }
 
        public function directoryExists( array $params ) {
@@ -630,13 +655,15 @@ class FileBackendMultiWrite extends FileBackend {
        }
 
        public function preloadCache( array $paths ) {
-               $realPaths = $this->substPaths( $paths, $this->backends[$this->masterIndex] );
-               $this->backends[$this->masterIndex]->preloadCache( $realPaths );
+               $realPaths = $this->substPaths( $paths, $this->backends[$this->readIndex] );
+               $this->backends[$this->readIndex]->preloadCache( $realPaths );
        }
 
        public function preloadFileStat( array $params ) {
-               $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
-               return $this->backends[$this->masterIndex]->preloadFileStat( $realParams );
+               $index = $this->getReadIndexFromParams( $params );
+               $realParams = $this->substOpPaths( $params, $this->backends[$index] );
+
+               return $this->backends[$index]->preloadFileStat( $realParams );
        }
 
        public function getScopedLocksForOps( array $ops, Status $status ) {
@@ -653,4 +680,12 @@ class FileBackendMultiWrite extends FileBackend {
                // Actually acquire the locks
                return $this->getScopedFileLocks( $pbPaths, 'mixed', $status );
        }
+
+       /**
+        * @param array $params
+        * @return int The master or read affinity backend index, based on $params['latest']
+        */
+       protected function getReadIndexFromParams( array $params ) {
+               return !empty( $params['latest'] ) ? $this->masterIndex : $this->readIndex;
+       }
 }