diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2015-06-04 07:31:04 +0200 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2015-06-04 07:58:39 +0200 |
commit | f6d65e533c62f6deb21342d4901ece24497b433e (patch) | |
tree | f28adf0362d14bcd448f7b65a7aaf38650f923aa /includes/filerepo/file | |
parent | c27b2e832fe25651ef2410fae85b41072aae7519 (diff) |
Update to MediaWiki 1.25.1
Diffstat (limited to 'includes/filerepo/file')
-rw-r--r-- | includes/filerepo/file/ArchivedFile.php | 12 | ||||
-rw-r--r-- | includes/filerepo/file/File.php | 51 | ||||
-rw-r--r-- | includes/filerepo/file/LocalFile.php | 194 | ||||
-rw-r--r-- | includes/filerepo/file/OldLocalFile.php | 14 | ||||
-rw-r--r-- | includes/filerepo/file/UnregisteredLocalFile.php | 12 |
5 files changed, 122 insertions, 161 deletions
diff --git a/includes/filerepo/file/ArchivedFile.php b/includes/filerepo/file/ArchivedFile.php index 5b0d8e2b..1d454283 100644 --- a/includes/filerepo/file/ArchivedFile.php +++ b/includes/filerepo/file/ArchivedFile.php @@ -100,8 +100,9 @@ class ArchivedFile { * @param Title $title * @param int $id * @param string $key + * @param string $sha1 */ - function __construct( $title, $id = 0, $key = '' ) { + function __construct( $title, $id = 0, $key = '', $sha1 = '' ) { $this->id = -1; $this->title = false; $this->name = false; @@ -136,7 +137,11 @@ class ArchivedFile { $this->key = $key; } - if ( !$id && !$key && !( $title instanceof Title ) ) { + if ( $sha1 ) { + $this->sha1 = $sha1; + } + + if ( !$id && !$key && !( $title instanceof Title ) && !$sha1 ) { throw new MWException( "No specifications provided to ArchivedFile constructor." ); } } @@ -162,6 +167,9 @@ class ArchivedFile { if ( $this->title ) { $conds['fa_name'] = $this->title->getDBkey(); } + if ( $this->sha1 ) { + $conds['fa_sha1'] = $this->sha1; + } if ( !count( $conds ) ) { throw new MWException( "No specific information for retrieving archived file" ); diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php index b574c5e7..6edd6fcc 100644 --- a/includes/filerepo/file/File.php +++ b/includes/filerepo/file/File.php @@ -47,7 +47,7 @@ * * @ingroup FileAbstraction */ -abstract class File { +abstract class File implements IDBAccessObject { // Bitfield values akin to the Revision deletion constants const DELETED_FILE = 1; const DELETED_COMMENT = 2; @@ -138,10 +138,10 @@ abstract class File { /** @var Title */ protected $redirectTitle; - /** @var bool Wether the output of transform() for this file is likely to be valid. */ + /** @var bool Whether the output of transform() for this file is likely to be valid. */ protected $canRender; - /** @var bool Wether this media file is in a format that is unlikely to + /** @var bool Whether this media file is in a format that is unlikely to * contain viruses or malicious content */ protected $isSafeFile; @@ -490,7 +490,7 @@ abstract class File { sort( $sortedBuckets ); foreach ( $sortedBuckets as $bucket ) { - if ( $bucket > $imageWidth ) { + if ( $bucket >= $imageWidth ) { return false; } @@ -837,6 +837,18 @@ abstract class File { } /** + * Load any lazy-loaded file object fields from source + * + * This is only useful when setting $flags + * + * Overridden by LocalFile to actually query the DB + * + * @param integer $flags Bitfield of File::READ_* constants + */ + public function load( $flags = 0 ) { + } + + /** * Returns true if file exists in the repository. * * Overridden by LocalFile to avoid unnecessary stat calls. @@ -996,7 +1008,6 @@ abstract class File { function transform( $params, $flags = 0 ) { global $wgThumbnailEpoch; - wfProfileIn( __METHOD__ ); do { if ( !$this->canRender() ) { $thumb = $this->iconThumb(); @@ -1069,8 +1080,6 @@ abstract class File { } } while ( false ); - wfProfileOut( __METHOD__ ); - return is_object( $thumb ) ? $thumb : false; } @@ -1100,9 +1109,7 @@ abstract class File { } // Actually render the thumbnail... - wfProfileIn( __METHOD__ . '-doTransform' ); $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams ); - wfProfileOut( __METHOD__ . '-doTransform' ); $tmpFile->bind( $thumb ); // keep alive with $thumb if ( !$thumb ) { // bad params? @@ -1123,7 +1130,7 @@ abstract class File { $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $transformParams, $flags ); } // Give extensions a chance to do something with this thumbnail... - wfRunHooks( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) ); + Hooks::run( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) ); } // Purge. Useful in the event of Core -> Squid connection failure or squid @@ -1237,7 +1244,7 @@ abstract class File { $that = $this; $work = new PoolCounterWorkViaCallback( 'GetLocalFileCopy', sha1( $this->getName() ), array( - 'doWork' => function() use ( $that ) { + 'doWork' => function () use ( $that ) { return $that->getLocalRefPath(); } ) @@ -1458,7 +1465,7 @@ abstract class File { /** * Get the path of the file relative to the public zone root. - * This function is overriden in OldLocalFile to be like getArchiveRel(). + * This function is overridden in OldLocalFile to be like getArchiveRel(). * * @return string */ @@ -1502,7 +1509,7 @@ abstract class File { /** * Get urlencoded path of the file relative to the public zone root. - * This function is overriden in OldLocalFile to be like getArchiveUrl(). + * This function is overridden in OldLocalFile to be like getArchiveUrl(). * * @return string */ @@ -1770,14 +1777,15 @@ abstract class File { } /** + * @param bool|IContextSource $context Context to use (optional) * @return bool */ - function formatMetadata() { + function formatMetadata( $context = false ) { if ( !$this->getHandler() ) { return false; } - return $this->getHandler()->formatMetadata( $this, $this->getMetadata() ); + return $this->getHandler()->formatMetadata( $this, $context ); } /** @@ -2013,7 +2021,7 @@ abstract class File { wfDebug( "miss\n" ); } wfDebug( "Fetching shared description from $renderUrl\n" ); - $res = Http::get( $renderUrl ); + $res = Http::get( $renderUrl, array(), __METHOD__ ); if ( $res && $this->repo->descriptionCacheExpiry > 0 ) { $wgMemc->set( $key, $res, $this->repo->descriptionCacheExpiry ); } @@ -2052,6 +2060,17 @@ abstract class File { } /** + * Returns the timestamp (in TS_MW format) of the last change of the description page. + * Returns false if the file does not have a description page, or retrieving the timestamp + * would be expensive. + * @since 1.25 + * @return string|bool + */ + public function getDescriptionTouched() { + return false; + } + + /** * Get the SHA-1 base 36 hash of the file * * @return string diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 8824b669..b4cced38 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -109,6 +109,9 @@ class LocalFile extends File { /** @var string Description of current revision of the file */ private $description; + /** @var string TS_MW timestamp of the last change of the file description */ + private $descriptionTouched; + /** @var bool Whether the row was upgraded on load */ private $upgraded; @@ -121,13 +124,8 @@ class LocalFile extends File { /** @var bool True if file is not present in file system. Not to be cached in memcached */ private $missing; - /** @var int UNIX timestamp of last markVolatile() call */ - private $lastMarkedVolatile = 0; - - const LOAD_ALL = 1; // integer; load all the lazy fields too (like metadata) - const LOAD_VIA_SLAVE = 2; // integer; use a slave to load the data - - const VOLATILE_TTL = 300; // integer; seconds + // @note: higher than IDBAccessObject constants + const LOAD_ALL = 16; // integer; load all the lazy fields too (like metadata) /** * Create a LocalFile from a title @@ -247,13 +245,11 @@ class LocalFile extends File { function loadFromCache() { global $wgMemc; - wfProfileIn( __METHOD__ ); $this->dataLoaded = false; $this->extraDataLoaded = false; $key = $this->getCacheKey(); if ( !$key ) { - wfProfileOut( __METHOD__ ); return false; } @@ -280,8 +276,6 @@ class LocalFile extends File { wfIncrStats( 'image_cache_miss' ); } - wfProfileOut( __METHOD__ ); - return $this->dataLoaded; } @@ -382,17 +376,15 @@ class LocalFile extends File { * @param int $flags */ function loadFromDB( $flags = 0 ) { - # Polymorphic function name to distinguish foreign and local fetches $fname = get_class( $this ) . '::' . __FUNCTION__; - wfProfileIn( $fname ); # Unconditionally set loaded=true, we don't want the accessors constantly rechecking $this->dataLoaded = true; $this->extraDataLoaded = true; - $dbr = ( $flags & self::LOAD_VIA_SLAVE ) - ? $this->repo->getSlaveDB() - : $this->repo->getMasterDB(); + $dbr = ( $flags & self::READ_LATEST ) + ? $this->repo->getMasterDB() + : $this->repo->getSlaveDB(); $row = $dbr->selectRow( 'image', $this->getCacheFields( 'img_' ), array( 'img_name' => $this->getName() ), $fname ); @@ -402,8 +394,6 @@ class LocalFile extends File { } else { $this->fileExists = false; } - - wfProfileOut( $fname ); } /** @@ -411,9 +401,7 @@ class LocalFile extends File { * This covers fields that are sometimes not cached. */ protected function loadExtraFromDB() { - # Polymorphic function name to distinguish foreign and local fetches $fname = get_class( $this ) . '::' . __FUNCTION__; - wfProfileIn( $fname ); # Unconditionally set loaded=true, we don't want the accessors constantly rechecking $this->extraDataLoaded = true; @@ -428,11 +416,8 @@ class LocalFile extends File { $this->$name = $value; } } else { - wfProfileOut( $fname ); throw new MWException( "Could not find data for image '{$this->getName()}'." ); } - - wfProfileOut( $fname ); } /** @@ -540,13 +525,14 @@ class LocalFile extends File { */ function load( $flags = 0 ) { if ( !$this->dataLoaded ) { - if ( !$this->loadFromCache() ) { - $this->loadFromDB( $this->isVolatile() ? 0 : self::LOAD_VIA_SLAVE ); + if ( ( $flags & self::READ_LATEST ) || !$this->loadFromCache() ) { + $this->loadFromDB( $flags ); $this->saveToCache(); } $this->dataLoaded = true; } if ( ( $flags & self::LOAD_ALL ) && !$this->extraDataLoaded ) { + // @note: loads on name/timestamp to reduce race condition problems $this->loadExtraFromDB(); } } @@ -587,7 +573,6 @@ class LocalFile extends File { * Fix assorted version-related problems with the image row by reloading it from the file */ function upgradeRow() { - wfProfileIn( __METHOD__ ); $this->lock(); // begin @@ -597,7 +582,6 @@ class LocalFile extends File { if ( !$this->fileExists ) { $this->unlock(); wfDebug( __METHOD__ . ": file does not exist, aborting\n" ); - wfProfileOut( __METHOD__ ); return; } @@ -607,7 +591,6 @@ class LocalFile extends File { if ( wfReadOnly() ) { $this->unlock(); - wfProfileOut( __METHOD__ ); return; } @@ -633,7 +616,6 @@ class LocalFile extends File { $this->unlock(); // done - wfProfileOut( __METHOD__ ); } /** @@ -672,7 +654,7 @@ class LocalFile extends File { /** getURL inherited */ /** getViewURL inherited */ /** getPath inherited */ - /** isVisible inhereted */ + /** isVisible inherited */ /** * @return bool @@ -860,7 +842,7 @@ class LocalFile extends File { * Refresh metadata in memcached, but don't touch thumbnails or squid */ function purgeMetadataCache() { - $this->loadFromDB(); + $this->loadFromDB( File::READ_LATEST ); $this->saveToCache(); $this->purgeHistory(); } @@ -889,7 +871,6 @@ class LocalFile extends File { * @note This used to purge old thumbnails by default as well, but doesn't anymore. */ function purgeCache( $options = array() ) { - wfProfileIn( __METHOD__ ); // Refresh metadata cache $this->purgeMetadataCache(); @@ -898,7 +879,6 @@ class LocalFile extends File { // Purge squid cache for this file SquidUpdate::purge( array( $this->getURL() ) ); - wfProfileOut( __METHOD__ ); } /** @@ -907,13 +887,12 @@ class LocalFile extends File { */ function purgeOldThumbnails( $archiveName ) { global $wgUseSquid; - wfProfileIn( __METHOD__ ); // Get a list of old thumbnails and URLs $files = $this->getThumbnails( $archiveName ); // Purge any custom thumbnail caches - wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, $archiveName ) ); + Hooks::run( 'LocalFilePurgeThumbnails', array( $this, $archiveName ) ); $dir = array_shift( $files ); $this->purgeThumbList( $dir, $files ); @@ -927,7 +906,6 @@ class LocalFile extends File { SquidUpdate::purge( $urls ); } - wfProfileOut( __METHOD__ ); } /** @@ -936,7 +914,6 @@ class LocalFile extends File { */ function purgeThumbnails( $options = array() ) { global $wgUseSquid; - wfProfileIn( __METHOD__ ); // Delete thumbnails $files = $this->getThumbnails(); @@ -958,7 +935,7 @@ class LocalFile extends File { } // Purge any custom thumbnail caches - wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, false ) ); + Hooks::run( 'LocalFilePurgeThumbnails', array( $this, false ) ); $dir = array_shift( $files ); $this->purgeThumbList( $dir, $files ); @@ -968,7 +945,6 @@ class LocalFile extends File { SquidUpdate::purge( $urls ); } - wfProfileOut( __METHOD__ ); } /** @@ -1035,7 +1011,7 @@ class LocalFile extends File { $opts['ORDER BY'] = "oi_timestamp $order"; $opts['USE INDEX'] = array( 'oldimage' => 'oi_name_timestamp' ); - wfRunHooks( 'LocalFile::getHistory', array( &$this, &$tables, &$fields, + Hooks::run( 'LocalFile::getHistory', array( &$this, &$tables, &$fields, &$conds, &$opts, &$join_conds ) ); $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $opts, $join_conds ); @@ -1146,7 +1122,6 @@ class LocalFile extends File { } if ( !$props ) { - wfProfileIn( __METHOD__ . '-getProps' ); if ( $this->repo->isVirtualUrl( $srcPath ) || FileBackend::isStoragePath( $srcPath ) ) { @@ -1154,7 +1129,6 @@ class LocalFile extends File { } else { $props = FSFile::getPropsFromPath( $srcPath ); } - wfProfileOut( __METHOD__ . '-getProps' ); } $options = array(); @@ -1236,7 +1210,6 @@ class LocalFile extends File { function recordUpload2( $oldver, $comment, $pageText, $props = false, $timestamp = false, $user = null ) { - wfProfileIn( __METHOD__ ); if ( is_null( $user ) ) { global $wgUser; @@ -1247,9 +1220,7 @@ class LocalFile extends File { $dbw->begin( __METHOD__ ); if ( !$props ) { - wfProfileIn( __METHOD__ . '-getProps' ); $props = $this->repo->getFileProps( $this->getVirtualUrl() ); - wfProfileOut( __METHOD__ . '-getProps' ); } # Imports or such might force a certain timestamp; otherwise we generate @@ -1271,7 +1242,6 @@ class LocalFile extends File { if ( !$this->fileExists ) { wfDebug( __METHOD__ . ": File " . $this->getRel() . " went missing!\n" ); $dbw->rollback( __METHOD__ ); - wfProfileOut( __METHOD__ ); return false; } @@ -1303,9 +1273,11 @@ class LocalFile extends File { ); if ( $dbw->affectedRows() == 0 ) { if ( $allowTimeKludge ) { - # Use FOR UPDATE to ignore any transaction snapshotting + # Use LOCK IN SHARE MODE to ignore any transaction snapshotting $ltimestamp = $dbw->selectField( 'image', 'img_timestamp', - array( 'img_name' => $this->getName() ), __METHOD__, array( 'FOR UPDATE' ) ); + array( 'img_name' => $this->getName() ), + __METHOD__, + array( 'LOCK IN SHARE MODE' ) ); $lUnixtime = $ltimestamp ? wfTimestamp( TS_UNIX, $ltimestamp ) : false; # Avoid a timestamp that is not newer than the last version # TODO: the image/oldimage tables should be like page/revision with an ID field @@ -1404,12 +1376,14 @@ class LocalFile extends File { // Page exists, do RC entry now (otherwise we wait for later). $logEntry->publish( $logId ); } - wfProfileIn( __METHOD__ . '-edit' ); if ( $exists ) { # Create a null revision $latest = $descTitle->getLatestRevID(); - $editSummary = LogFormatter::newFromEntry( $logEntry )->getPlainActionText(); + // Use own context to get the action text in content language + $formatter = LogFormatter::newFromEntry( $logEntry ); + $formatter->setContext( RequestContext::newExtraneousContext( $descTitle ) ); + $editSummary = $formatter->getPlainActionText(); $nullRevision = Revision::newNullRevision( $dbw, @@ -1421,7 +1395,7 @@ class LocalFile extends File { if ( !is_null( $nullRevision ) ) { $nullRevision->insertOn( $dbw ); - wfRunHooks( 'NewRevisionFromEditComplete', array( $wikiPage, $nullRevision, $latest, $user ) ); + Hooks::run( 'NewRevisionFromEditComplete', array( $wikiPage, $nullRevision, $latest, $user ) ); $wikiPage->updateRevisionOn( $dbw, $nullRevision ); } } @@ -1468,22 +1442,16 @@ class LocalFile extends File { $dbw->commit( __METHOD__ ); // commit before anything bad can happen } - wfProfileOut( __METHOD__ . '-edit' ); - if ( $reupload ) { # Delete old thumbnails - wfProfileIn( __METHOD__ . '-purge' ); $this->purgeThumbnails(); - wfProfileOut( __METHOD__ . '-purge' ); # Remove the old file from the squid cache SquidUpdate::purge( array( $this->getURL() ) ); } # Hooks, hooks, the magic of hooks... - wfProfileIn( __METHOD__ . '-hooks' ); - wfRunHooks( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) ); - wfProfileOut( __METHOD__ . '-hooks' ); + Hooks::run( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) ); # Invalidate cache for all pages using this file $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' ); @@ -1492,8 +1460,6 @@ class LocalFile extends File { LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' ); } - wfProfileOut( __METHOD__ ); - return true; } @@ -1811,6 +1777,25 @@ class LocalFile extends File { } /** + * @return bool|string + */ + public function getDescriptionTouched() { + // The DB lookup might return false, e.g. if the file was just deleted, or the shared DB repo + // itself gets it from elsewhere. To avoid repeating the DB lookups in such a case, we + // need to differentiate between null (uninitialized) and false (failed to load). + if ( $this->descriptionTouched === null ) { + $cond = array( + 'page_namespace' => $this->title->getNamespace(), + 'page_title' => $this->title->getDBkey() + ); + $touched = $this->repo->getSlaveDB()->selectField( 'page', 'page_touched', $cond, __METHOD__ ); + $this->descriptionTouched = $touched ? wfTimestamp( TS_MW, $touched ) : false; + } + + return $this->descriptionTouched; + } + + /** * @return string */ function getSha1() { @@ -1850,7 +1835,7 @@ class LocalFile extends File { * Start a transaction and lock the image for update * Increments a reference counter if the lock is already held * @throws MWException Throws an error if the lock was not acquired - * @return bool Success + * @return bool Whether the file lock owns/spawned the DB transaction */ function lock() { $dbw = $this->repo->getMasterDB(); @@ -1875,9 +1860,7 @@ class LocalFile extends File { } ); } - $this->markVolatile(); // file may change soon - - return true; + return $this->lockedOwnTrx; } /** @@ -1896,48 +1879,6 @@ class LocalFile extends File { } /** - * Mark a file as about to be changed - * - * This sets a cache key that alters master/slave DB loading behavior - * - * @return bool Success - */ - protected function markVolatile() { - global $wgMemc; - - $key = $this->repo->getSharedCacheKey( 'file-volatile', md5( $this->getName() ) ); - if ( $key ) { - $this->lastMarkedVolatile = time(); - return $wgMemc->set( $key, $this->lastMarkedVolatile, self::VOLATILE_TTL ); - } - - return true; - } - - /** - * Check if a file is about to be changed or has been changed recently - * - * @see LocalFile::isVolatile() - * @return bool Whether the file is volatile - */ - protected function isVolatile() { - global $wgMemc; - - $key = $this->repo->getSharedCacheKey( 'file-volatile', md5( $this->getName() ) ); - if ( !$key ) { - // repo unavailable; bail. - return false; - } - - if ( $this->lastMarkedVolatile === 0 ) { - $this->lastMarkedVolatile = $wgMemc->get( $key ) ?: 0; - } - - $volatileDuration = time() - $this->lastMarkedVolatile; - return $volatileDuration <= self::VOLATILE_TTL; - } - - /** * Roll back the DB transaction and mark the image unlocked */ function unlockAndRollback() { @@ -1985,7 +1926,7 @@ class LocalFileDeleteBatch { /** @var array Items to be processed in the deletion batch */ private $deletionBatch; - /** @var bool Wether to suppress all suppressable fields when deleting */ + /** @var bool Whether to suppress all suppressable fields when deleting */ private $suppress; /** @var FileRepoStatus */ @@ -2238,26 +2179,9 @@ class LocalFileDeleteBatch { * @return FileRepoStatus */ function execute() { - wfProfileIn( __METHOD__ ); $this->file->lock(); - // Leave private files alone - $privateFiles = array(); - list( $oldRels, ) = $this->getOldRels(); - $dbw = $this->file->repo->getMasterDB(); - - if ( !empty( $oldRels ) ) { - $res = $dbw->select( 'oldimage', - array( 'oi_archive_name' ), - array( 'oi_name' => $this->file->getName(), - 'oi_archive_name' => array_keys( $oldRels ), - $dbw->bitAnd( 'oi_deleted', File::DELETED_FILE ) => File::DELETED_FILE ), - __METHOD__ ); - foreach ( $res as $row ) { - $privateFiles[$row->oi_archive_name] = 1; - } - } // Prepare deletion batch $hashes = $this->getHashes(); $this->deletionBatch = array(); @@ -2265,9 +2189,8 @@ class LocalFileDeleteBatch { $dotExt = $ext === '' ? '' : ".$ext"; foreach ( $this->srcRels as $name => $srcRel ) { - // Skip files that have no hash (missing source). - // Keep private files where they are. - if ( isset( $hashes[$name] ) && !array_key_exists( $name, $privateFiles ) ) { + // Skip files that have no hash (e.g. missing DB record, or sha1 field and file source) + if ( isset( $hashes[$name] ) ) { $hash = $hashes[$name]; $key = $hash . $dotExt; $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key; @@ -2284,6 +2207,7 @@ class LocalFileDeleteBatch { $this->doDBInserts(); // Removes non-existent file from the batch, so we don't get errors. + // This also handles files in the 'deleted' zone deleted via revision deletion. $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch ); if ( !$checkStatus->isGood() ) { $this->status->merge( $checkStatus ); @@ -2303,7 +2227,6 @@ class LocalFileDeleteBatch { // Roll back inserts, release lock and abort // TODO: delete the defunct filearchive rows if we are using a non-transactional DB $this->file->unlockAndRollback(); - wfProfileOut( __METHOD__ ); return $this->status; } @@ -2313,7 +2236,6 @@ class LocalFileDeleteBatch { // Commit and return $this->file->unlock(); - wfProfileOut( __METHOD__ ); return $this->status; } @@ -2366,7 +2288,7 @@ class LocalFileRestoreBatch { /** @var bool Add all revisions of the file */ private $all; - /** @var bool Wether to remove all settings for suppressed fields */ + /** @var bool Whether to remove all settings for suppressed fields */ private $unsuppress = false; /** @@ -2419,13 +2341,19 @@ class LocalFileRestoreBatch { return $this->file->repo->newGood(); } - $this->file->lock(); + $lockOwnsTrx = $this->file->lock(); $dbw = $this->file->repo->getMasterDB(); $status = $this->file->repo->newGood(); $exists = (bool)$dbw->selectField( 'image', '1', - array( 'img_name' => $this->file->getName() ), __METHOD__, array( 'FOR UPDATE' ) ); + array( 'img_name' => $this->file->getName() ), + __METHOD__, + // The lock() should already prevents changes, but this still may need + // to bypass any transaction snapshot. However, if lock() started the + // trx (which it probably did) then snapshot is post-lock and up-to-date. + $lockOwnsTrx ? array() : array( 'LOCK IN SHARE MODE' ) + ); // Fetch all or selected archived revisions for the file, // sorted from the most recent to the oldest. @@ -2797,7 +2725,7 @@ class LocalFileMoveBatch { array( 'oi_archive_name', 'oi_deleted' ), array( 'oi_name' => $this->oldName ), __METHOD__, - array( 'FOR UPDATE' ) // ignore snapshot + array( 'LOCK IN SHARE MODE' ) // ignore snapshot ); foreach ( $result as $row ) { diff --git a/includes/filerepo/file/OldLocalFile.php b/includes/filerepo/file/OldLocalFile.php index 710058fb..fd92e11a 100644 --- a/includes/filerepo/file/OldLocalFile.php +++ b/includes/filerepo/file/OldLocalFile.php @@ -175,11 +175,12 @@ class OldLocalFile extends LocalFile { } function loadFromDB( $flags = 0 ) { - wfProfileIn( __METHOD__ ); - $this->dataLoaded = true; - $dbr = $this->repo->getSlaveDB(); + $dbr = ( $flags & self::READ_LATEST ) + ? $this->repo->getMasterDB() + : $this->repo->getSlaveDB(); + $conds = array( 'oi_name' => $this->getName() ); if ( is_null( $this->requestedTime ) ) { $conds['oi_archive_name'] = $this->archive_name; @@ -194,14 +195,12 @@ class OldLocalFile extends LocalFile { $this->fileExists = false; } - wfProfileOut( __METHOD__ ); } /** * Load lazy file metadata from the DB */ protected function loadExtraFromDB() { - wfProfileIn( __METHOD__ ); $this->extraDataLoaded = true; $dbr = $this->repo->getSlaveDB(); @@ -226,11 +225,9 @@ class OldLocalFile extends LocalFile { $this->$name = $value; } } else { - wfProfileOut( __METHOD__ ); throw new MWException( "Could not find data for image '{$this->archive_name}'." ); } - wfProfileOut( __METHOD__ ); } /** @@ -260,13 +257,11 @@ class OldLocalFile extends LocalFile { } function upgradeRow() { - wfProfileIn( __METHOD__ ); $this->loadFromFile(); # Don't destroy file info of missing files if ( !$this->fileExists ) { wfDebug( __METHOD__ . ": file does not exist, aborting\n" ); - wfProfileOut( __METHOD__ ); return; } @@ -291,7 +286,6 @@ class OldLocalFile extends LocalFile { 'oi_archive_name' => $this->archive_name ), __METHOD__ ); - wfProfileOut( __METHOD__ ); } /** diff --git a/includes/filerepo/file/UnregisteredLocalFile.php b/includes/filerepo/file/UnregisteredLocalFile.php index 5a3e4e9c..4c11341b 100644 --- a/includes/filerepo/file/UnregisteredLocalFile.php +++ b/includes/filerepo/file/UnregisteredLocalFile.php @@ -166,6 +166,18 @@ class UnregisteredLocalFile extends File { } /** + * @return int + */ + function getBitDepth() { + $gis = $this->getImageSize( $this->getLocalRefPath() ); + + if ( !$gis || !isset( $gis['bits'] ) ) { + return 0; + } + return $gis['bits']; + } + + /** * @return bool */ function getMetadata() { |