https://www.mediawiki.org/wiki/Special:Code/MediaWiki/104366
Revision: 104366 Author: aaron Date: 2011-11-27 21:48:46 +0000 (Sun, 27 Nov 2011) Log Message: ----------- * Renamed resolveVirtualPath() -> resolveStoragePath() * Added splitStoragePath() function * Renamed storagePathsToLock() -> storagePathsUsed() * Added FileBackendGroup class to handle registration * Made File::getTimestamp() use FileBackend::getFileTimestamp() * Replaced unlink() in LocalFile::cleanupDeletedBatch() Modified Paths: -------------- branches/FileBackend/phase3/includes/AutoLoader.php branches/FileBackend/phase3/includes/filerepo/FileRepo.php branches/FileBackend/phase3/includes/filerepo/LocalRepo.php branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php branches/FileBackend/phase3/includes/filerepo/backend/FileBackendMultiWrite.php branches/FileBackend/phase3/includes/filerepo/backend/FileOp.php branches/FileBackend/phase3/includes/filerepo/file/File.php Added Paths: ----------- branches/FileBackend/phase3/includes/filerepo/backend/FileBackendGroup.php Modified: branches/FileBackend/phase3/includes/AutoLoader.php =================================================================== --- branches/FileBackend/phase3/includes/AutoLoader.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/AutoLoader.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -484,6 +484,7 @@ 'TempFSFile' => 'includes/filerepo/file/TempFSFile.php', # includes/filerepo/backend + 'FileBackendGroup' => 'includes/filerepo/backend/FileBackendGroup', 'FileBackendBase' => 'includes/filerepo/backend/FileBackend.php', 'FileBackend' => 'includes/filerepo/backend/FileBackend.php', 'FileBackendMultiWrite' => 'includes/filerepo/backend/FileBackendMultiWrite.php', Modified: branches/FileBackend/phase3/includes/filerepo/FileRepo.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/FileRepo.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/FileRepo.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -753,7 +753,7 @@ // Cleanup for disk source files... foreach ( $sourceFSFilesToDelete as $file ) { wfSuppressWarnings(); - unlink( $file ); + unlink( $file ); // FS cleanup wfRestoreWarnings(); } @@ -802,7 +802,7 @@ // Cleanup for disk source files... foreach ( $sourceFSFilesToDelete as $file ) { wfSuppressWarnings(); - unlink( $path ); + unlink( $path ); // FS cleanup wfRestoreWarnings(); } } @@ -964,7 +964,7 @@ // Cleanup for disk source files... foreach ( $sourceFSFilesToDelete as $file ) { wfSuppressWarnings(); - unlink( $file ); + unlink( $file ); // FS cleanup wfRestoreWarnings(); } @@ -1005,9 +1005,9 @@ $result[$key] = $this->backend->fileExists( array( 'source' => $file ) ); } else { if ( $flags & self::FILES_ONLY ) { - $result[$key] = is_file( $file ); + $result[$key] = is_file( $file ); // FS only } else { - $result[$key] = file_exists( $file ); // @TODO: kill this + $result[$key] = file_exists( $file ); // FS only } } } Modified: branches/FileBackend/phase3/includes/filerepo/LocalRepo.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/LocalRepo.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/LocalRepo.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -56,6 +56,7 @@ * @return FileRepoStatus */ function cleanupDeletedBatch( $storageKeys ) { + $backend = $this->backend; // convenience $root = $this->getZonePath( 'deleted' ); $dbw = $this->getMasterDB(); $status = $this->newGood(); @@ -70,10 +71,8 @@ $hidden = $this->hiddenFileHasKey( $key, 'lock' ); if ( !$deleted && !$hidden ) { // not in use now wfDebug( __METHOD__ . ": deleting $key\n" ); - wfSuppressWarnings(); - $unlink = unlink( $path ); - wfRestoreWarnings(); - if ( !$unlink ) { + $op = array( 'operation' => 'delete', 'source' => $path ); + if ( !$backend->doOperations( array( $op ) )->isOK() ) { $status->error( 'undelete-cleanup-error', $path ); $status->failCount++; } Modified: branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -37,7 +37,7 @@ function store( array $params ) { $status = Status::newGood(); - list( $c, $dest ) = $this->resolveVirtualPath( $params['dest'] ); + list( $c, $dest ) = $this->resolveStoragePath( $params['dest'] ); if ( $dest === null ) { $status->fatal( 'backend-fail-invalidpath', $params['dest'] ); return $status; @@ -87,12 +87,12 @@ function move( array $params ) { $status = Status::newGood(); - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { $status->fatal( 'backend-fail-invalidpath', $params['source'] ); return $status; } - list( $c, $dest ) = $this->resolveVirtualPath( $params['dest'] ); + list( $c, $dest ) = $this->resolveStoragePath( $params['dest'] ); if ( $dest === null ) { $status->fatal( 'backend-fail-invalidpath', $params['dest'] ); return $status; @@ -135,7 +135,7 @@ function delete( array $params ) { $status = Status::newGood(); - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { $status->fatal( 'backend-fail-invalidpath', $params['source'] ); return $status; @@ -162,7 +162,7 @@ function concatenate( array $params ) { $status = Status::newGood(); - list( $c, $dest ) = $this->resolveVirtualPath( $params['dest'] ); + list( $c, $dest ) = $this->resolveStoragePath( $params['dest'] ); if ( $dest === null ) { $status->fatal( 'backend-fail-invalidpath', $params['dest'] ); return $status; @@ -193,7 +193,7 @@ return $status; } foreach ( $params['sources'] as $virtualSource ) { - list( $c, $source ) = $this->resolveVirtualPath( $virtualSource ); + list( $c, $source ) = $this->resolveStoragePath( $virtualSource ); if ( $source === null ) { $status->fatal( 'backend-fail-invalidpath', $virtualSource ); return $status; @@ -262,7 +262,7 @@ function create( array $params ) { $status = Status::newGood(); - list( $c, $dest ) = $this->resolveVirtualPath( $params['dest'] ); + list( $c, $dest ) = $this->resolveStoragePath( $params['dest'] ); if ( $dest === null ) { $status->fatal( 'backend-fail-invalidpath', $params['dest'] ); return $status; @@ -303,7 +303,7 @@ function prepare( array $params ) { $status = Status::newGood(); - list( $c, $dir ) = $this->resolveVirtualPath( $params['directory'] ); + list( $c, $dir ) = $this->resolveStoragePath( $params['directory'] ); if ( $dir === null ) { $status->fatal( 'backend-fail-invalidpath', $params['directory'] ); return $status; // invalid storage path @@ -323,7 +323,7 @@ function secure( array $params ) { $status = Status::newGood(); - list( $c, $dir ) = $this->resolveVirtualPath( $params['directory'] ); + list( $c, $dir ) = $this->resolveStoragePath( $params['directory'] ); if ( $dir === null ) { $status->fatal( 'backend-fail-invalidpath', $params['directory'] ); return $status; // invalid storage path @@ -356,7 +356,7 @@ } function fileExists( array $params ) { - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { return false; // invalid storage path } @@ -368,7 +368,7 @@ } function getFileHash( array $params ) { - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { return false; // invalid storage path } @@ -376,7 +376,7 @@ } function getFileTimestamp( array $params ) { - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { return false; // invalid storage path } @@ -385,7 +385,7 @@ } function getFileProps( array $params ) { - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { return FSFile::placeholderProps(); // invalid storage path } @@ -394,7 +394,7 @@ } function getFileList( array $params ) { - list( $c, $dir ) = $this->resolveVirtualPath( $params['directory'] ); + list( $c, $dir ) = $this->resolveStoragePath( $params['directory'] ); if ( $dir === null ) { // invalid storage path return array(); // empty result } @@ -404,7 +404,7 @@ function streamFile( array $params ) { $status = Status::newGood(); - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { $status->fatal( 'backend-fail-invalidpath', $params['source'] ); return $status; @@ -420,7 +420,7 @@ } function getLocalCopy( array $params ) { - list( $c, $source ) = $this->resolveVirtualPath( $params['source'] ); + list( $c, $source ) = $this->resolveStoragePath( $params['source'] ); if ( $source === null ) { return null; } Modified: branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -392,7 +392,7 @@ // Build up a list of files to lock... $filesToLock = array(); foreach ( $performOps as $index => $fileOp ) { - $filesToLock = array_merge( $filesToLock, $fileOp->storagePathsToLock() ); + $filesToLock = array_merge( $filesToLock, $fileOp->storagePathsUsed() ); } // Try to lock those files... @@ -481,21 +481,37 @@ /** * Split a storage path (e.g. "mwstore://backend/container/path/to/object") - * into a container name and a full object name within that container. + * into a backend name, a container name, and a relative object path. * * @param $storagePath string + * @return Array (backend, container, rel object) or (null, null, null) + */ + final public static function splitStoragePath( $storagePath ) { + if ( self::isStoragePath( $storagePath ) ) { + // Note: strlen( 'mwstore://' ) = 10 + $parts = explode( '/', substr( $storagePath, 10 ), 3 ); + if ( count( $parts ) == 3 ) { + return $parts; + } + } + return array( null, null, null ); + } + + /** + * Split a storage path (e.g. "mwstore://backend/container/path/to/object") + * into a backend name, a container name and an internal relative object name. + * + * @param $storagePath string * @return Array (container, object name) or (null, null) if path is invalid */ - final protected function resolveVirtualPath( $storagePath ) { - if ( strpos( $storagePath, 'mwstore://' ) === 0 ) { - $m = explode( '/', substr( $storagePath, 10 ), 3 ); - if ( count( $m ) == 3 ) { - list( $backend, $container, $relPath ) = $m; - if ( $backend === $this->name ) { // sanity - $relPath = $this->resolveContainerPath( $container, $relPath ); - if ( $relPath !== null ) { - return array( $container, $relPath ); // (container, path) - } + final protected function resolveStoragePath( $storagePath ) { + $parts = self::splitStoragePath( $storagePath ); + if ( $parts[0] !== null ) { // either all null or all not null + list( $backend, $container, $relPath ) = $parts; + if ( $backend === $this->name ) { // sanity + $relPath = $this->resolveContainerPath( $container, $relPath ); + if ( $relPath !== null ) { + return array( $container, $relPath ); // (container, path) } } } Added: branches/FileBackend/phase3/includes/filerepo/backend/FileBackendGroup.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/backend/FileBackendGroup.php (rev 0) +++ branches/FileBackend/phase3/includes/filerepo/backend/FileBackendGroup.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -0,0 +1,88 @@ +<?php +/** + * @file + * @ingroup FileRepo + * @ingroup FileBackend + */ + +/** + * Class to handle file backend registration + * + * @ingroup FileRepo + * @ingroup FileBackend + */ +class FileBackendGroup { + protected static $instance = null; + + /** @var Array of (name => ('class' =>, 'config' =>, 'instance' =>)) */ + protected $backends = array(); + + protected function __construct() {} + protected function __clone() {} + + public static function singleton() { + if ( self::$instance == null ) { + self::$instance = new self(); + } + return self::$instance; + } + + /** + * Register a file backend from configuration + * + * @param $config Array + * @return void + * @throws MWException + */ + public function register( array $config ) { + if ( !isset( $config['name'] ) ) { + throw new MWException( "Cannot register a backend with no name." ); + } + $name = $config['name']; + if ( !isset( $config['class'] ) ) { + throw new MWException( "Cannot register backend `{$name}` with no class." ); + } + $class = $config['class']; + + unset( $config['class'] ); // backend won't need this + $this->backends[$name] = array( + 'class' => $class, + 'config' => $config, + 'instance' => null + ); + } + + /** + * Get the backend object with a given name + * + * @param $name string + * @return FileBackendBase + * @throws MWException + */ + public function getBackend( $name ) { + if ( !isset( $this->backends[$name] ) ) { + throw new MWException( "No backend defined with the name `$name`." ); + } + // Lazy-load the actual backend instance + if ( !isset( $this->backends[$name]['instance'] ) ) { + $class = $this->backends[$name]['class']; + $config = $this->backends[$name]['config']; + $this->backends[$name]['instance'] = new $class( $config ); + } + return $this->backends[$name]['instance']; + } + + /** + * Get an appropriate backend object from a storage path + * + * @param $storagePath string + * @return FileBackendBase|null Backend or null on failure + */ + public function backendFromPath( $storagePath ) { + list( $backend, $c, $p ) = FileBackend::splitStoragePath( $storagePath ); + if ( $backend !== null && isset( $this->backends[$backend] ) ) { + return $this->backends[$backend]; + } + return null; + } +} Property changes on: branches/FileBackend/phase3/includes/filerepo/backend/FileBackendGroup.php ___________________________________________________________________ Added: svn:eol-style + native Modified: branches/FileBackend/phase3/includes/filerepo/backend/FileBackendMultiWrite.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/backend/FileBackendMultiWrite.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/backend/FileBackendMultiWrite.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -81,7 +81,7 @@ // locks two or three times (depending on the number of backends). if ( $index == 0 ) { foreach ( $performOps as $index => $fileOp ) { - $filesToLock = array_merge( $filesToLock, $fileOp->storagePathsToLock() ); + $filesToLock = array_merge( $filesToLock, $fileOp->storagePathsUsed() ); } } } Modified: branches/FileBackend/phase3/includes/filerepo/backend/FileOp.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/backend/FileOp.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/backend/FileOp.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -117,7 +117,7 @@ * * @return Array */ - public function storagePathsToLock() { + public function storagePathsUsed() { return array(); } @@ -301,7 +301,7 @@ return md5_file( $this->params['source'] ); } - function storagePathsToLock() { + function storagePathsUsed() { return array( $this->params['dest'] ); } } @@ -347,7 +347,7 @@ return md5( $this->params['content'] ); } - function storagePathsToLock() { + function storagePathsUsed() { return array( $this->params['dest'] ); } } @@ -400,7 +400,7 @@ return $this->getFileMD5( $this->params['source'] ); } - function storagePathsToLock() { + function storagePathsUsed() { return array( $this->params['source'], $this->params['dest'] ); } } @@ -485,7 +485,7 @@ return $this->getFileMD5( $this->params['source'] ); } - function storagePathsToLock() { + function storagePathsUsed() { return array( $this->params['source'], $this->params['dest'] ); } } @@ -531,7 +531,7 @@ return null; // defer this until we finish building the new file } - function storagePathsToLock() { + function storagePathsUsed() { return array_merge( $this->params['sources'], $this->params['dest'] ); } } @@ -569,7 +569,7 @@ return $status; } - function storagePathsToLock() { + function storagePathsUsed() { return array( $this->params['source'] ); } } Modified: branches/FileBackend/phase3/includes/filerepo/file/File.php =================================================================== --- branches/FileBackend/phase3/includes/filerepo/file/File.php 2011-11-27 21:16:08 UTC (rev 104365) +++ branches/FileBackend/phase3/includes/filerepo/file/File.php 2011-11-27 21:48:46 UTC (rev 104366) @@ -835,10 +835,10 @@ global $wgStylePath, $wgStyleDirectory; $try = array( 'fileicon-' . $this->getExtension() . '.png', 'fileicon.png' ); - foreach( $try as $icon ) { + foreach ( $try as $icon ) { $path = '/common/images/icons/' . $icon; $filepath = $wgStyleDirectory . $path; - if( file_exists( $filepath ) ) { + if ( file_exists( $filepath ) ) { // always FS return new ThumbnailImage( $this, $wgStylePath . $path, 120, 120 ); } } @@ -1450,17 +1450,13 @@ } /** - * Get the 14-character timestamp of the file upload, or false if - * it doesn't exist + * Get the 14-character timestamp of the file upload * - * @return string + * @return string|false TS_MW timestamp or false on failure */ function getTimestamp() { - $path = $this->getPath(); - if ( !$this->repo->fileExists( $path ) ) { - return false; - } - return wfTimestamp( TS_MW, filemtime( $path ) ); + $this->assertRepoDefined(); + return $this->repo->getBackend()->getFileTimestamp( $this->getPath() ); } /** _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs