diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-05-01 15:32:59 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-05-01 15:32:59 -0400 |
commit | 6dc1997577fab2c366781fd7048144935afa0012 (patch) | |
tree | 8918d28c7ab4342f0738985e37af1dfc42d0e93a /includes/filerepo/LocalRepo.php | |
parent | 150f94f051128f367bc89f6b7e5f57eb2a69fc62 (diff) | |
parent | fa89acd685cb09cdbe1c64cbb721ec64975bbbc1 (diff) |
Merge commit 'fa89acd'
# Conflicts:
# .gitignore
# extensions/ArchInterWiki.sql
Diffstat (limited to 'includes/filerepo/LocalRepo.php')
-rw-r--r-- | includes/filerepo/LocalRepo.php | 113 |
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 ); + } + } } |