summaryrefslogtreecommitdiff
path: root/includes/filerepo/LocalRepo.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/filerepo/LocalRepo.php')
-rw-r--r--includes/filerepo/LocalRepo.php113
1 files changed, 99 insertions, 14 deletions
diff --git a/includes/filerepo/LocalRepo.php b/includes/filerepo/LocalRepo.php
index 926fd0b8..6a2c0640 100644
--- a/includes/filerepo/LocalRepo.php
+++ b/includes/filerepo/LocalRepo.php
@@ -29,6 +29,9 @@
* @ingroup FileRepo
*/
class LocalRepo extends FileRepo {
+ /** @var bool */
+ protected $hasSha1Storage = false;
+
/** @var array */
protected $fileFactory = array( 'LocalFile', 'newFromTitle' );
@@ -47,6 +50,20 @@ class LocalRepo extends FileRepo {
/** @var array */
protected $oldFileFactoryKey = array( 'OldLocalFile', 'newFromKey' );
+ function __construct( array $info = null ) {
+ parent::__construct( $info );
+
+ $this->hasSha1Storage = isset( $info['storageLayout'] ) && $info['storageLayout'] === 'sha1';
+
+ if ( $this->hasSha1Storage() ) {
+ $this->backend = new FileBackendDBRepoWrapper( array(
+ 'backend' => $this->backend,
+ 'repoName' => $this->name,
+ 'dbHandleFactory' => $this->getDBFactory()
+ ) );
+ }
+ }
+
/**
* @throws MWException
* @param stdClass $row
@@ -82,6 +99,11 @@ class LocalRepo extends FileRepo {
* @return FileRepoStatus
*/
function cleanupDeletedBatch( array $storageKeys ) {
+ if ( $this->hasSha1Storage() ) {
+ wfDebug( __METHOD__ . ": skipped because storage uses sha1 paths\n" );
+ return Status::newGood();
+ }
+
$backend = $this->backend; // convenience
$root = $this->getZonePath( 'deleted' );
$dbw = $this->getMasterDB();
@@ -90,7 +112,7 @@ class LocalRepo extends FileRepo {
foreach ( $storageKeys as $key ) {
$hashPath = $this->getDeletedHashPath( $key );
$path = "$root/$hashPath$key";
- $dbw->begin( __METHOD__ );
+ $dbw->startAtomic( __METHOD__ );
// Check for usage in deleted/hidden files and preemptively
// lock the key to avoid any future use until we are finished.
$deleted = $this->deletedFileHasKey( $key, 'lock' );
@@ -106,7 +128,7 @@ class LocalRepo extends FileRepo {
wfDebug( __METHOD__ . ": $key still in use\n" );
$status->successCount++;
}
- $dbw->commit( __METHOD__ );
+ $dbw->endAtomic( __METHOD__ );
}
return $status;
@@ -170,7 +192,7 @@ class LocalRepo extends FileRepo {
* @return bool|Title
*/
function checkRedirect( Title $title ) {
- global $wgMemc;
+ $cache = ObjectCache::getMainWANInstance();
$title = File::normalizeTitle( $title, 'exception' );
@@ -181,7 +203,7 @@ class LocalRepo extends FileRepo {
} else {
$expiry = 86400; // has invalidation, 1 day
}
- $cachedValue = $wgMemc->get( $memcKey );
+ $cachedValue = $cache->get( $memcKey );
if ( $cachedValue === ' ' || $cachedValue === '' ) {
// Does not exist
return false;
@@ -191,7 +213,7 @@ class LocalRepo extends FileRepo {
$id = $this->getArticleID( $title );
if ( !$id ) {
- $wgMemc->add( $memcKey, " ", $expiry );
+ $cache->set( $memcKey, " ", $expiry );
return false;
}
@@ -205,11 +227,11 @@ class LocalRepo extends FileRepo {
if ( $row && $row->rd_namespace == NS_FILE ) {
$targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title );
- $wgMemc->add( $memcKey, $targetTitle->getDBkey(), $expiry );
+ $cache->set( $memcKey, $targetTitle->getDBkey(), $expiry );
return $targetTitle;
} else {
- $wgMemc->add( $memcKey, '', $expiry );
+ $cache->set( $memcKey, '', $expiry );
return false;
}
@@ -275,17 +297,17 @@ class LocalRepo extends FileRepo {
);
};
- $repo = $this;
+ $that = $this;
$applyMatchingFiles = function ( ResultWrapper $res, &$searchSet, &$finalFiles )
- use ( $repo, $fileMatchesSearch, $flags )
+ use ( $that, $fileMatchesSearch, $flags )
{
global $wgContLang;
- $info = $repo->getInfo();
+ $info = $that->getInfo();
foreach ( $res as $row ) {
- $file = $repo->newFileFromRow( $row );
+ $file = $that->newFileFromRow( $row );
// There must have been a search for this DB key, but this has to handle the
// cases were title capitalization is different on the client and repo wikis.
- $dbKeysLook = array( str_replace( ' ', '_', $file->getName() ) );
+ $dbKeysLook = array( strtr( $file->getName(), ' ', '_' ) );
if ( !empty( $info['initialCapital'] ) ) {
// Search keys for "hi.png" and "Hi.png" should use the "Hi.png file"
$dbKeysLook[] = $wgContLang->lcfirst( $file->getName() );
@@ -470,6 +492,16 @@ class LocalRepo extends FileRepo {
}
/**
+ * Get a callback to get a DB handle given an index (DB_SLAVE/DB_MASTER)
+ * @return Closure
+ */
+ protected function getDBFactory() {
+ return function( $index ) {
+ return wfGetDB( $index );
+ };
+ }
+
+ /**
* Get a key on the primary cache for this repository.
* Returns false if the repository's cache is not accessible at this site.
* The parameters are the parts of the key, as for wfMemcKey().
@@ -489,14 +521,15 @@ class LocalRepo extends FileRepo {
* @return void
*/
function invalidateImageRedirect( Title $title ) {
- global $wgMemc;
+ $cache = ObjectCache::getMainWANInstance();
+
$memcKey = $this->getSharedCacheKey( 'image_redirect', md5( $title->getDBkey() ) );
if ( $memcKey ) {
// Set a temporary value for the cache key, to ensure
// that this value stays purged long enough so that
// it isn't refreshed with a stale value due to a
// lagged slave.
- $wgMemc->set( $memcKey, ' PURGED', 12 );
+ $cache->delete( $memcKey, 12 );
}
}
@@ -513,4 +546,56 @@ class LocalRepo extends FileRepo {
'favicon' => wfExpandUrl( $wgFavicon ),
) );
}
+
+ public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function storeBatch( array $triplets, $flags = 0 ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function cleanupBatch( array $files, $flags = 0 ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function publish(
+ $srcPath,
+ $dstRel,
+ $archiveRel,
+ $flags = 0,
+ array $options = array()
+ ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function publishBatch( array $ntuples, $flags = 0 ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function delete( $srcRel, $archiveRel ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ public function deleteBatch( array $sourceDestPairs ) {
+ return $this->skipWriteOperationIfSha1( __FUNCTION__, func_get_args() );
+ }
+
+ /**
+ * Skips the write operation if storage is sha1-based, executes it normally otherwise
+ *
+ * @param string $function
+ * @param array $args
+ * @return FileRepoStatus
+ */
+ protected function skipWriteOperationIfSha1( $function, array $args ) {
+ $this->assertWritableRepo(); // fail out if read-only
+
+ if ( $this->hasSha1Storage() ) {
+ wfDebug( __METHOD__ . ": skipped because storage uses sha1 paths\n" );
+ return Status::newGood();
+ } else {
+ return call_user_func_array( 'parent::' . $function, $args );
+ }
+ }
}