From: Aaron Schulz Date: Sun, 18 Sep 2016 21:40:38 +0000 (-0700) Subject: Dependency cleanups to FileBackendStore X-Git-Tag: 1.31.0-rc.0~5355 X-Git-Url: https://git.cyclocoop.org/%242?a=commitdiff_plain;h=81a0e795ec297e5e20e96a330a076eda82b1cbb8;p=lhc%2Fweb%2Fwiklou.git Dependency cleanups to FileBackendStore * Inject a PSR logger in place of wf* logging methods. * Replace wfTimestamp() call with ConvertableTimestamp. * Inject the Profiler object. * Rename $wiki => $domain to avoid "wiki" mentions. * Remove stray FSFile::extractImageSizeInfo() method. Change-Id: I3e3a43d36506bec341dc5727b52f5f5a5d32bff5 --- diff --git a/includes/filebackend/FileBackendGroup.php b/includes/filebackend/FileBackendGroup.php index d0a99d4d65..d9e5a540e2 100644 --- a/includes/filebackend/FileBackendGroup.php +++ b/includes/filebackend/FileBackendGroup.php @@ -21,6 +21,7 @@ * @ingroup FileBackend * @author Aaron Schulz */ +use \MediaWiki\Logger\LoggerFactory; /** * Class to handle file backend registration @@ -169,6 +170,8 @@ class FileBackendGroup { $config['mimeCallback'] = [ $this, 'guessMimeInternal' ]; $config['statusWrapper'] = [ 'Status', 'wrap' ]; $config['tmpDirectory'] = wfTempDir(); + $config['logger'] = LoggerFactory::getInstance( 'FileOperation' ); + $config['profiler'] = Profiler::instance(); $this->backends[$name]['instance'] = new $class( $config ); } diff --git a/includes/filebackend/FileBackendMultiWrite.php b/includes/filebackend/FileBackendMultiWrite.php index 52b84d4e66..db79155533 100644 --- a/includes/filebackend/FileBackendMultiWrite.php +++ b/includes/filebackend/FileBackendMultiWrite.php @@ -121,7 +121,7 @@ class FileBackendMultiWrite extends FileBackend { unset( $config['readOnly'] ); // use proxy backend setting unset( $config['fileJournal'] ); // use proxy backend journal unset( $config['lockManager'] ); // lock under proxy backend - $config['wikiId'] = $this->wikiId; // use the proxy backend wiki ID + $config['domainId'] = $this->domainId; // use the proxy backend wiki ID if ( !empty( $config['isMultiMaster'] ) ) { if ( $this->masterIndex >= 0 ) { throw new LogicException( 'More than one master backend defined.' ); diff --git a/includes/filebackend/FileBackendStore.php b/includes/filebackend/FileBackendStore.php index 9efec36c5d..31c94ce56f 100644 --- a/includes/filebackend/FileBackendStore.php +++ b/includes/filebackend/FileBackendStore.php @@ -116,7 +116,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function createInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); if ( strlen( $params['content'] ) > $this->maxFileSizeInternal() ) { $status = $this->newStatus( 'backend-fail-maxsize', $params['dst'], $this->maxFileSizeInternal() ); @@ -157,7 +157,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function storeInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); if ( filesize( $params['src'] ) > $this->maxFileSizeInternal() ) { $status = $this->newStatus( 'backend-fail-maxsize', $params['dst'], $this->maxFileSizeInternal() ); @@ -199,7 +199,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function copyInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->doCopyInternal( $params ); $this->clearCache( [ $params['dst'] ] ); if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) { @@ -231,7 +231,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function deleteInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->doDeleteInternal( $params ); $this->clearCache( [ $params['src'] ] ); $this->deleteFileCache( $params['src'] ); // persistent cache @@ -265,7 +265,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function moveInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->doMoveInternal( $params ); $this->clearCache( [ $params['src'], $params['dst'] ] ); $this->deleteFileCache( $params['src'] ); // persistent cache @@ -311,7 +311,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue */ final public function describeInternal( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); if ( count( $params['headers'] ) ) { $status = $this->doDescribeInternal( $params ); $this->clearCache( [ $params['src'] ] ); @@ -344,7 +344,7 @@ abstract class FileBackendStore extends FileBackend { } final public function concatenate( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); // Try to lock the source files for the scope of this function @@ -355,7 +355,7 @@ abstract class FileBackendStore extends FileBackend { $status->merge( $this->doConcatenate( $params ) ); $sec = microtime( true ) - $start_time; if ( !$status->isOK() ) { - wfDebugLog( 'FileOperation', get_class( $this ) . "-{$this->name}" . + $this->logger->error( get_class( $this ) . "-{$this->name}" . " failed to concatenate " . count( $params['srcs'] ) . " file(s) [$sec sec]" ); } } @@ -437,7 +437,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doPrepare( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] ); @@ -450,7 +450,7 @@ abstract class FileBackendStore extends FileBackend { if ( $shard !== null ) { // confined to a single container/shard $status->merge( $this->doPrepareInternal( $fullCont, $dir, $params ) ); } else { // directory is on several shards - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); foreach ( $this->getContainerSuffixes( $shortCont ) as $suffix ) { $status->merge( $this->doPrepareInternal( "{$fullCont}{$suffix}", $dir, $params ) ); @@ -472,7 +472,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doSecure( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] ); @@ -485,7 +485,7 @@ abstract class FileBackendStore extends FileBackend { if ( $shard !== null ) { // confined to a single container/shard $status->merge( $this->doSecureInternal( $fullCont, $dir, $params ) ); } else { // directory is on several shards - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); foreach ( $this->getContainerSuffixes( $shortCont ) as $suffix ) { $status->merge( $this->doSecureInternal( "{$fullCont}{$suffix}", $dir, $params ) ); @@ -507,7 +507,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doPublish( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] ); @@ -520,7 +520,7 @@ abstract class FileBackendStore extends FileBackend { if ( $shard !== null ) { // confined to a single container/shard $status->merge( $this->doPublishInternal( $fullCont, $dir, $params ) ); } else { // directory is on several shards - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); foreach ( $this->getContainerSuffixes( $shortCont ) as $suffix ) { $status->merge( $this->doPublishInternal( "{$fullCont}{$suffix}", $dir, $params ) ); @@ -542,7 +542,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doClean( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); // Recursive: first delete all empty subdirs recursively @@ -575,7 +575,7 @@ abstract class FileBackendStore extends FileBackend { $status->merge( $this->doCleanInternal( $fullCont, $dir, $params ) ); $this->deleteContainerCache( $fullCont ); // purge cache } else { // directory is on several shards - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); foreach ( $this->getContainerSuffixes( $shortCont ) as $suffix ) { $status->merge( $this->doCleanInternal( "{$fullCont}{$suffix}", $dir, $params ) ); @@ -598,21 +598,21 @@ abstract class FileBackendStore extends FileBackend { } final public function fileExists( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $stat = $this->getFileStat( $params ); return ( $stat === null ) ? null : (bool)$stat; // null => failure } final public function getFileTimestamp( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $stat = $this->getFileStat( $params ); return $stat ? $stat['mtime'] : false; } final public function getFileSize( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $stat = $this->getFileStat( $params ); return $stat ? $stat['size'] : false; @@ -623,7 +623,7 @@ abstract class FileBackendStore extends FileBackend { if ( $path === null ) { return false; // invalid storage path } - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $latest = !empty( $params['latest'] ); // use latest data? if ( !$latest && !$this->cheapCache->has( $path, 'stat', self::CACHE_TTL ) ) { $this->primeFileCache( [ $path ] ); // check persistent cache @@ -661,9 +661,9 @@ abstract class FileBackendStore extends FileBackend { $this->cheapCache->set( $path, 'stat', $latest ? 'NOT_EXIST_LATEST' : 'NOT_EXIST' ); $this->cheapCache->set( $path, 'xattr', [ 'map' => false, 'latest' => $latest ] ); $this->cheapCache->set( $path, 'sha1', [ 'hash' => false, 'latest' => $latest ] ); - wfDebug( __METHOD__ . ": File $path does not exist.\n" ); + $this->logger->debug( __METHOD__ . ": File $path does not exist.\n" ); } else { // an error occurred - wfDebug( __METHOD__ . ": Could not stat file $path.\n" ); + $this->logger->warning( __METHOD__ . ": Could not stat file $path.\n" ); } return $stat; @@ -675,7 +675,7 @@ abstract class FileBackendStore extends FileBackend { abstract protected function doGetFileStat( array $params ); public function getFileContentsMulti( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $params = $this->setConcurrencyFlags( $params ); $contents = $this->doGetFileContentsMulti( $params ); @@ -704,7 +704,7 @@ abstract class FileBackendStore extends FileBackend { if ( $path === null ) { return false; // invalid storage path } - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $latest = !empty( $params['latest'] ); // use latest data? if ( $this->cheapCache->has( $path, 'xattr', self::CACHE_TTL ) ) { $stat = $this->cheapCache->get( $path, 'xattr' ); @@ -734,7 +734,7 @@ abstract class FileBackendStore extends FileBackend { if ( $path === null ) { return false; // invalid storage path } - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $latest = !empty( $params['latest'] ); // use latest data? if ( $this->cheapCache->has( $path, 'sha1', self::CACHE_TTL ) ) { $stat = $this->cheapCache->get( $path, 'sha1' ); @@ -765,7 +765,7 @@ abstract class FileBackendStore extends FileBackend { } final public function getFileProps( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $fsFile = $this->getLocalReference( $params ); $props = $fsFile ? $fsFile->getProps() : FSFile::placeholderProps(); @@ -773,7 +773,7 @@ abstract class FileBackendStore extends FileBackend { } final public function getLocalReferenceMulti( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $params = $this->setConcurrencyFlags( $params ); @@ -816,7 +816,7 @@ abstract class FileBackendStore extends FileBackend { } final public function getLocalCopyMulti( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $params = $this->setConcurrencyFlags( $params ); $tmpFiles = $this->doGetLocalCopyMulti( $params ); @@ -841,7 +841,7 @@ abstract class FileBackendStore extends FileBackend { } final public function streamFile( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); // Always set some fields for subclass convenience @@ -897,7 +897,7 @@ abstract class FileBackendStore extends FileBackend { if ( $shard !== null ) { // confined to a single container/shard return $this->doDirectoryExists( $fullCont, $dir, $params ); } else { // directory is on several shards - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); $res = false; // response foreach ( $this->getContainerSuffixes( $shortCont ) as $suffix ) { @@ -933,7 +933,7 @@ abstract class FileBackendStore extends FileBackend { // File listing is confined to a single container/shard return $this->getDirectoryListInternal( $fullCont, $dir, $params ); } else { - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); // File listing spans multiple containers/shards list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); @@ -963,7 +963,7 @@ abstract class FileBackendStore extends FileBackend { // File listing is confined to a single container/shard return $this->getFileListInternal( $fullCont, $dir, $params ); } else { - wfDebug( __METHOD__ . ": iterating over all container shards.\n" ); + $this->logger->debug( __METHOD__ . ": iterating over all container shards.\n" ); // File listing spans multiple containers/shards list( , $shortCont, ) = self::splitStoragePath( $params['dir'] ); @@ -1059,7 +1059,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doOperationsInternal( array $ops, array $opts ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); // Fix up custom header name/value pairs... @@ -1111,7 +1111,7 @@ abstract class FileBackendStore extends FileBackend { $subStatus->success[$i] = false; ++$subStatus->failCount; } - wfDebugLog( 'FileOperation', get_class( $this ) . "-{$this->name} " . + $this->logger->error( get_class( $this ) . "-{$this->name} " . " stat failure; aborted operations: " . FormatJson::encode( $ops ) ); } @@ -1126,7 +1126,7 @@ abstract class FileBackendStore extends FileBackend { } final protected function doQuickOperationsInternal( array $ops ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $status = $this->newStatus(); // Fix up custom header name/value pairs... @@ -1193,7 +1193,7 @@ abstract class FileBackendStore extends FileBackend { * @return StatusValue[] Map of StatusValue objects */ final public function executeOpHandlesInternal( array $fileOpHandles ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); foreach ( $fileOpHandles as $fileOpHandle ) { if ( !( $fileOpHandle instanceof FileBackendStoreOpHandle ) ) { @@ -1297,7 +1297,7 @@ abstract class FileBackendStore extends FileBackend { } final public function preloadFileStat( array $params ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $success = true; // no network errors $params['concurrency'] = ( $this->parallelize !== 'off' ) ? $this->concurrency : 1; @@ -1333,10 +1333,10 @@ abstract class FileBackendStore extends FileBackend { [ 'map' => false, 'latest' => $latest ] ); $this->cheapCache->set( $path, 'sha1', [ 'hash' => false, 'latest' => $latest ] ); - wfDebug( __METHOD__ . ": File $path does not exist.\n" ); + $this->logger->debug( __METHOD__ . ": File $path does not exist.\n" ); } else { // an error occurred $success = false; - wfDebug( __METHOD__ . ": Could not stat file $path.\n" ); + $this->logger->warning( __METHOD__ . ": Could not stat file $path.\n" ); } } @@ -1566,8 +1566,8 @@ abstract class FileBackendStore extends FileBackend { * @return string */ final protected function fullContainerName( $container ) { - if ( $this->wikiId != '' ) { - return "{$this->wikiId}-$container"; + if ( $this->domainId != '' ) { + return "{$this->domainId}-$container"; } else { return $container; } @@ -1606,7 +1606,7 @@ abstract class FileBackendStore extends FileBackend { * @return string */ private function containerCacheKey( $container ) { - return "filebackend:{$this->name}:{$this->wikiId}:container:{$container}"; + return "filebackend:{$this->name}:{$this->domainId}:container:{$container}"; } /** @@ -1639,7 +1639,7 @@ abstract class FileBackendStore extends FileBackend { * @param array $items */ final protected function primeContainerCache( array $items ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $paths = []; // list of storage paths $contNames = []; // (cache key => resolved container name) @@ -1687,7 +1687,7 @@ abstract class FileBackendStore extends FileBackend { * @return string */ private function fileCacheKey( $path ) { - return "filebackend:{$this->name}:{$this->wikiId}:file:" . sha1( $path ); + return "filebackend:{$this->name}:{$this->domainId}:file:" . sha1( $path ); } /** @@ -1703,7 +1703,7 @@ abstract class FileBackendStore extends FileBackend { if ( $path === null ) { return; // invalid storage path } - $mtime = wfTimestamp( TS_UNIX, $val['mtime'] ); + $mtime = ConvertibleTimestamp::convert( TS_UNIX, $val['mtime'] ); $ttl = $this->memCache->adaptiveTTL( $mtime, 7 * 86400, 300, .1 ); $key = $this->fileCacheKey( $path ); // Set the cache unless it is currently salted. @@ -1736,7 +1736,7 @@ abstract class FileBackendStore extends FileBackend { * @param array $items List of storage paths */ final protected function primeFileCache( array $items ) { - $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" ); + $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" ); $paths = []; // list of storage paths $pathNames = []; // (cache key => storage path) diff --git a/includes/filebackend/FileOpBatch.php b/includes/filebackend/FileOpBatch.php index e34ad8ccb4..71b5c7d575 100644 --- a/includes/filebackend/FileOpBatch.php +++ b/includes/filebackend/FileOpBatch.php @@ -164,6 +164,7 @@ class FileOpBatch { $statuses = []; $opHandles = []; // Get the backend; all sub-batch ops belong to a single backend + /** @var FileBackendStore $backend */ $backend = reset( $performOpsBatch )->getBackend(); // Get the operation handles or actually do it if there is just one. // If attemptAsync() returns a StatusValue, it was either due to an error diff --git a/includes/libs/filebackend/FSFile.php b/includes/libs/filebackend/FSFile.php index d0e93da7ba..dacad1cb26 100644 --- a/includes/libs/filebackend/FSFile.php +++ b/includes/libs/filebackend/FSFile.php @@ -153,26 +153,6 @@ class FSFile { return $info; } - /** - * Exract image size information - * - * @param array $gis - * @return array - */ - protected function extractImageSizeInfo( array $gis ) { - $info = []; - # NOTE: $gis[2] contains a code for the image type. This is no longer used. - $info['width'] = $gis[0]; - $info['height'] = $gis[1]; - if ( isset( $gis['bits'] ) ) { - $info['bits'] = $gis['bits']; - } else { - $info['bits'] = 0; - } - - return $info; - } - /** * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case * encoding, zero padded to 31 digits. diff --git a/includes/libs/filebackend/FileBackend.php b/includes/libs/filebackend/FileBackend.php index 0b9eee0624..b53c545be5 100644 --- a/includes/libs/filebackend/FileBackend.php +++ b/includes/libs/filebackend/FileBackend.php @@ -28,6 +28,8 @@ * @ingroup FileBackend * @author Aaron Schulz */ +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; /** * @brief Base class for all file backend classes (including multi-write backends). @@ -36,16 +38,21 @@ * Outside callers can assume that all backends will have these functions. * * All "storage paths" are of the format "mwstore:////". - * The "backend" portion is unique name for MediaWiki to refer to a backend, while + * The "backend" portion is unique name for the application to refer to a backend, while * the "container" portion is a top-level directory of the backend. The "path" portion * is a relative path that uses UNIX file system (FS) notation, though any particular * backend may not actually be using a local filesystem. Therefore, the relative paths * are only virtual. * - * Backend contents are stored under wiki-specific container names by default. - * Global (qualified) backends are achieved by configuring the "wiki ID" to a constant. + * Backend contents are stored under "domain"-specific container names by default. + * A domain is simply a logical umbrella for entities, such as those belonging to a certain + * application or portion of a website, for example. A domain can be local or global. + * Global (qualified) backends are achieved by configuring the "domain ID" to a constant. + * Global domains are simpler, but local domains can be used by choosing a domain ID based on + * the current context, such as which language of a website is being used. + * * For legacy reasons, the FSFileBackend class allows manually setting the paths of - * containers to ones that do not respect the "wiki ID". + * containers to ones that do not respect the "domain ID". * * In key/value (object) stores, containers are the only hierarchy (the rest is emulated). * FS-based backends are somewhat more restrictive due to the existence of real @@ -82,12 +89,12 @@ * @ingroup FileBackend * @since 1.19 */ -abstract class FileBackend { +abstract class FileBackend implements LoggerAwareInterface { /** @var string Unique backend name */ protected $name; - /** @var string Unique wiki name */ - protected $wikiId; + /** @var string Unique domain name */ + protected $domainId; /** @var string Read-only explanation message */ protected $readOnly; @@ -103,9 +110,12 @@ abstract class FileBackend { /** @var LockManager */ protected $lockManager; - /** @var FileJournal */ protected $fileJournal; + /** @var LoggerInterface */ + protected $logger; + /** @var object|string Class name or object With profileIn/profileOut methods */ + protected $profiler; /** @var callable */ protected $statusWrapper; @@ -124,7 +134,7 @@ abstract class FileBackend { * This should consist of alphanumberic, '-', and '_' characters. * This name should not be changed after use (e.g. with journaling). * Note that the name is *not* used in actual container names. - * - wikiId : Prefix to container names that is unique to this backend. + * - domainId : Prefix to container names that is unique to this backend. * It should only consist of alphanumberic, '-', and '_' characters. * This ID is what avoids collisions if multiple logical backends * use the same storage system, so this should be set carefully. @@ -139,15 +149,20 @@ abstract class FileBackend { * - concurrency : How many file operations can be done in parallel. * - tmpDirectory : Directory to use for temporary files. If this is not set or null, * then the backend will try to discover a usable temporary directory. + * - logger : Optional PSR logger object. + * - profiler : Optional class name or object With profileIn/profileOut methods. * @throws InvalidArgumentException */ public function __construct( array $config ) { $this->name = $config['name']; - $this->wikiId = $config['wikiId']; // e.g. "my_wiki-en_" + $this->domainId = isset( $config['domainId'] ) + ? $config['domainId'] // e.g. "my_wiki-en_" + : $config['wikiId']; // b/c alias if ( !preg_match( '!^[a-zA-Z0-9-_]{1,255}$!', $this->name ) ) { throw new InvalidArgumentException( "Backend name '{$this->name}' is invalid." ); - } elseif ( !is_string( $this->wikiId ) ) { - throw new InvalidArgumentException( "Backend wiki ID not provided for '{$this->name}'." ); + } elseif ( !is_string( $this->domainId ) ) { + throw new InvalidArgumentException( + "Backend domain ID not provided for '{$this->name}'." ); } $this->lockManager = isset( $config['lockManager'] ) ? $config['lockManager'] @@ -164,10 +179,16 @@ abstract class FileBackend { $this->concurrency = isset( $config['concurrency'] ) ? (int)$config['concurrency'] : 50; + $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null; + $this->logger = isset( $config['logger'] ) ? $config['logger'] : new \Psr\Log\NullLogger(); $this->statusWrapper = isset( $config['statusWrapper'] ) ? $config['statusWrapper'] : null; $this->tmpDirectory = isset( $config['tmpDirectory'] ) ? $config['tmpDirectory'] : null; } + public function setLogger( LoggerInterface $logger ) { + $this->logger = $logger; + } + /** * Get the unique backend name. * We may have multiple different backends of the same type. @@ -180,14 +201,22 @@ abstract class FileBackend { } /** - * Get the wiki identifier used for this backend (possibly empty). - * Note that this might *not* be in the same format as wfWikiID(). + * Get the domain identifier used for this backend (possibly empty). * * @return string + * @since 1.28 + */ + final public function getDomainId() { + return $this->domainId; + } + + /** + * Alias to getDomainId() + * @return string * @since 1.20 */ final public function getWikiId() { - return $this->wikiId; + return $this->getDomainId(); } /** @@ -1569,4 +1598,17 @@ abstract class FileBackend { final protected function wrapStatus( StatusValue $sv ) { return $this->statusWrapper ? call_user_func( $this->statusWrapper, $sv ) : $sv; } + + /** + * @param string $section + * @return ScopedCallback|null + */ + protected function scopedProfileSection( $section ) { + if ( $this->profiler ) { + call_user_func( [ $this->profiler, 'profileIn' ], $section ); + return new ScopedCallback( [ $this->profiler, 'profileOut' ] ); + } + + return null; + } }