$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 );
}
// Purge any custom thumbnail caches
- wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, false ) );
+ Hooks::run( 'LocalFilePurgeThumbnails', array( $this, false ) );
$dir = array_shift( $files );
$this->purgeThumbList( $dir, $files );
$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 );
);
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
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 );
}
}
# Hooks, hooks, the magic of hooks...
wfProfileIn( __METHOD__ . '-hooks' );
- wfRunHooks( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) );
+ Hooks::run( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) );
wfProfileOut( __METHOD__ . '-hooks' );
# Invalidate cache for all pages using this 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();
$this->markVolatile(); // file may change soon
- return true;
+ return $this->lockedOwnTrx;
}
/**
$this->doDBInserts();
// Removes non-existent file from the batch, so we don't get errors.
- $this->deletionBatch = $this->removeNonexistentFiles( $this->deletionBatch );
+ $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch );
+ if ( !$checkStatus->isGood() ) {
+ $this->status->merge( $checkStatus );
+ return $this->status;
+ }
+ $this->deletionBatch = $checkStatus->value;
// Execute the file deletion batch
$status = $this->file->repo->deleteBatch( $this->deletionBatch );
/**
* Removes non-existent files from a deletion batch.
* @param array $batch
- * @return array
+ * @return Status
*/
function removeNonexistentFiles( $batch ) {
$files = $newBatch = array();
}
$result = $this->file->repo->fileExistsBatch( $files );
+ if ( in_array( null, $result, true ) ) {
+ return Status::newFatal( 'backend-fail-internal',
+ $this->file->repo->getBackend()->getName() );
+ }
foreach ( $batch as $batchItem ) {
if ( $result[$batchItem[0]] ) {
}
}
- return $newBatch;
+ return Status::newGood( $newBatch );
}
}
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.
}
// Remove missing files from batch, so we don't get errors when undeleting them
- $storeBatch = $this->removeNonexistentFiles( $storeBatch );
+ $checkStatus = $this->removeNonexistentFiles( $storeBatch );
+ if ( !$checkStatus->isGood() ) {
+ $status->merge( $checkStatus );
+ return $status;
+ }
+ $storeBatch = $checkStatus->value;
// Run the store batch
// Use the OVERWRITE_SAME flag to smooth over a common error
/**
* Removes non-existent files from a store batch.
* @param array $triplets
- * @return array
+ * @return Status
*/
function removeNonexistentFiles( $triplets ) {
$files = $filteredTriplets = array();
}
$result = $this->file->repo->fileExistsBatch( $files );
+ if ( in_array( null, $result, true ) ) {
+ return Status::newFatal( 'backend-fail-internal',
+ $this->file->repo->getBackend()->getName() );
+ }
foreach ( $triplets as $file ) {
if ( $result[$file[0]] ) {
}
}
- return $filteredTriplets;
+ return Status::newGood( $filteredTriplets );
}
/**
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 ) {
$status = $repo->newGood();
$triplets = $this->getMoveTriplets();
- $triplets = $this->removeNonexistentFiles( $triplets );
+ $checkStatus = $this->removeNonexistentFiles( $triplets );
+ if ( !$checkStatus->isGood() ) {
+ $status->merge( $checkStatus );
+ return $status;
+ }
+ $triplets = $checkStatus->value;
$destFile = wfLocalFile( $this->target );
$this->file->lock(); // begin
/**
* Removes non-existent files from move batch.
* @param array $triplets
- * @return array
+ * @return Status
*/
function removeNonexistentFiles( $triplets ) {
$files = array();
}
$result = $this->file->repo->fileExistsBatch( $files );
- $filteredTriplets = array();
+ if ( in_array( null, $result, true ) ) {
+ return Status::newFatal( 'backend-fail-internal',
+ $this->file->repo->getBackend()->getName() );
+ }
+ $filteredTriplets = array();
foreach ( $triplets as $file ) {
if ( $result[$file[0]] ) {
$filteredTriplets[] = $file;
}
}
- return $filteredTriplets;
+ return Status::newGood( $filteredTriplets );
}
/**