Aude has uploaded a new change for review. https://gerrit.wikimedia.org/r/188965
Change subject: Split SiteLookup interface from SiteStore ...................................................................... Split SiteLookup interface from SiteStore * SiteLookup interface is added, and SiteStore extends it. (any SiteStore type hints can be changed to use SiteLookup if all they need is lookup functionality) * Memcached based SiteStore code is split from the database SiteStore, and SiteSQLStore is deprecated. If no caching is desired when using a SiteStore, then use a SiteDBStore instance, instead of passing $source parameter in SiteStore::getSite and SiteStore::getSites. * SiteListFileCache renamed to FileBasedSiteLookup and implements SiteLookup, and SitesListFileCacheBuilder to SitesFileCacheBuilder. * Renamed config sites cache setting, from wgSitesCacheFile to wgSitesFileCache, for more naming consistency. Bug: T77990 Change-Id: I36b599884c211580ea6806a8a190c65c4f9087cf --- M autoload.php M includes/DefaultSettings.php A includes/site/CachingSiteStore.php R includes/site/FileBasedSiteLookup.php A includes/site/SiteDBStore.php A includes/site/SiteLookup.php M includes/site/SiteSQLStore.php M includes/site/SiteStore.php R includes/site/SitesFileCacheBuilder.php R maintenance/rebuildSitesFileCache.php C tests/phpunit/includes/site/CachingSiteStoreTest.php R tests/phpunit/includes/site/FileBasedSiteLookupTest.php R tests/phpunit/includes/site/SiteDBStoreTest.php R tests/phpunit/includes/site/SitesFileCacheBuilderTest.php M tests/phpunit/includes/site/TestSites.php 15 files changed, 662 insertions(+), 470 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/65/188965/1 diff --git a/autoload.php b/autoload.php index 90cd074..5868989 100644 --- a/autoload.php +++ b/autoload.php @@ -185,6 +185,7 @@ 'CacheHelper' => __DIR__ . '/includes/cache/CacheHelper.php', 'CacheTime' => __DIR__ . '/includes/parser/CacheTime.php', 'CachedAction' => __DIR__ . '/includes/actions/CachedAction.php', + 'CachingSiteStore' => __DIR__ . '/includes/site/CachingSiteStore.php', 'CapsCleanup' => __DIR__ . '/maintenance/cleanupCaps.php', 'Category' => __DIR__ . '/includes/Category.php', 'CategoryFinder' => __DIR__ . '/includes/CategoryFinder.php', @@ -413,6 +414,7 @@ 'FileBackendStoreShardDirIterator' => __DIR__ . '/includes/filebackend/FileBackendStore.php', 'FileBackendStoreShardFileIterator' => __DIR__ . '/includes/filebackend/FileBackendStore.php', 'FileBackendStoreShardListIterator' => __DIR__ . '/includes/filebackend/FileBackendStore.php', + 'FileBasedSiteLookup' => __DIR__ . '/includes/site/FileBasedSiteLookup.php', 'FileCacheBase' => __DIR__ . '/includes/cache/FileCacheBase.php', 'FileDeleteForm' => __DIR__ . '/includes/FileDeleteForm.php', 'FileDependency' => __DIR__ . '/includes/cache/CacheDependency.php', @@ -936,7 +938,7 @@ 'RebuildLocalisationCache' => __DIR__ . '/maintenance/rebuildLocalisationCache.php', 'RebuildMessages' => __DIR__ . '/maintenance/rebuildmessages.php', 'RebuildRecentchanges' => __DIR__ . '/maintenance/rebuildrecentchanges.php', - 'RebuildSitesCache' => __DIR__ . '/maintenance/rebuildSitesCache.php', + 'RebuildSitesFileCache' => __DIR__ . '/maintenance/rebuildSitesFileCache.php', 'RebuildTextIndex' => __DIR__ . '/maintenance/rebuildtextindex.php', 'RecentChange' => __DIR__ . '/includes/changes/RecentChange.php', 'RecompressTracked' => __DIR__ . '/maintenance/storage/recompressTracked.php', @@ -1047,15 +1049,16 @@ 'Site' => __DIR__ . '/includes/site/Site.php', 'SiteArray' => __DIR__ . '/includes/site/SiteList.php', 'SiteConfiguration' => __DIR__ . '/includes/SiteConfiguration.php', + 'SiteDBStore' => __DIR__ . '/includes/site/SiteDBStore.php', 'SiteList' => __DIR__ . '/includes/site/SiteList.php', - 'SiteListFileCache' => __DIR__ . '/includes/site/SiteListFileCache.php', - 'SiteListFileCacheBuilder' => __DIR__ . '/includes/site/SiteListFileCacheBuilder.php', + 'SiteLookup' => __DIR__ . '/includes/site/SiteLookup.php', 'SiteObject' => __DIR__ . '/includes/site/Site.php', 'SiteSQLStore' => __DIR__ . '/includes/site/SiteSQLStore.php', 'SiteStats' => __DIR__ . '/includes/SiteStats.php', 'SiteStatsInit' => __DIR__ . '/includes/SiteStats.php', 'SiteStatsUpdate' => __DIR__ . '/includes/deferred/SiteStatsUpdate.php', 'SiteStore' => __DIR__ . '/includes/site/SiteStore.php', + 'SitesFileCacheBuilder' => __DIR__ . '/includes/site/SitesFileCacheBuilder.php', 'Skin' => __DIR__ . '/includes/skins/Skin.php', 'SkinApi' => __DIR__ . '/includes/skins/SkinApi.php', 'SkinApiTemplate' => __DIR__ . '/includes/skins/SkinApiTemplate.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 7bd80c4..fdf8583 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -3781,9 +3781,9 @@ */ /** - * Specify the file location for the SiteStore json cache file. + * Specify the file location for the Sites json cache file. */ -$wgSitesCacheFile = false; +$wgSitesFileCache = false; /** @} */ # end of SiteStore caching settings. diff --git a/includes/site/CachingSiteStore.php b/includes/site/CachingSiteStore.php new file mode 100644 index 0000000..4d983e8 --- /dev/null +++ b/includes/site/CachingSiteStore.php @@ -0,0 +1,187 @@ +<?php + +/** + * Represents the site configuration of a wiki. + * Holds a list of sites (ie SiteList), with a caching layer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 1.25 + * + * @file + * @ingroup Site + * + * @license GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + * @author Katie Filbert < aude.w...@gmail.com > + */ +class CachingSiteStore implements SiteStore { + + /** + * @var SiteList|null + */ + private $sites = null; + + /** + * @var string|null + */ + private $cacheKey = null; + + /** + * @var int + */ + private $cacheTimeout = 3600; + + /** + * @var BagOStuff + */ + private $cache; + + /** + * @var SiteStore + */ + private $siteStore; + + /** + * @param SiteStore $siteStore + * @param BagOStuff $cache + */ + public function __construct( SiteStore $siteStore, BagOStuff $cache ) { + $this->siteStore = $siteStore; + $this->cache = $cache; + } + + /** + * Constructs a cache key to use for caching the list of sites. + * + * This includes the concrete class name of the site list as well as a version identifier + * for the list's serialization, to avoid problems when unserializing site lists serialized + * by an older version, e.g. when reading from a cache. + * + * The cache key also includes information about where the sites were loaded from, e.g. + * the name of a database table. + * + * @see SiteList::getSerialVersionId + * + * @return string The cache key. + */ + private function getCacheKey() { + if ( $this->cacheKey === null ) { + $type = 'SiteList#' . SiteList::getSerialVersionId(); + $this->cacheKey = wfMemcKey( "sites/$type" ); + } + + return $this->cacheKey; + } + + /** + * @see SiteStore::getSites + * + * @since 1.25 + * + * @return SiteList + */ + public function getSites() { + if ( $this->sites === null ) { + $this->sites = $this->cache->get( $this->getCacheKey() ); + + if ( !is_object( $this->sites ) ) { + $this->sites = $this->siteStore->getSites(); + + $this->cache->set( $this->getCacheKey(), $this->sites, $this->cacheTimeout ); + } + } + + return $this->sites; + } + + /** + * @see SiteStore::getSite + * + * @since 1.25 + * + * @param string $globalId + * + * @return Site|null + */ + public function getSite( $globalId ) { + $sites = $this->getSites(); + + return $sites->hasSite( $globalId ) ? $sites->getSite( $globalId ) : null; + } + + /** + * @see SiteStore::saveSite + * + * @since 1.25 + * + * @param Site $site + * + * @return bool Success indicator + */ + public function saveSite( Site $site ) { + return $this->saveSites( array( $site ) ); + } + + /** + * @see SiteStore::saveSites + * + * @since 1.25 + * + * @param Site[] $sites + * + * @return bool Success indicator + */ + public function saveSites( array $sites ) { + if ( empty( $sites ) ) { + return true; + } + + $success = $this->siteStore->saveSites( $sites ); + + // purge cache + $this->reset(); + + return $success; + } + + /** + * Purges the internal and external cache of the site list, forcing the list + * of sites to be reloaded. + * + * @since 1.25 + */ + public function reset() { + // purge cache + $this->cache->delete( $this->getCacheKey() ); + $this->sites = null; + + } + + /** + * Clears the list of sites stored. + * + * @see SiteStore::clear() + * + * @return bool Success + */ + public function clear() { + $this->reset(); + + return $this->siteStore->clear(); + } + +} diff --git a/includes/site/SiteListFileCache.php b/includes/site/FileBasedSiteLookup.php similarity index 96% rename from includes/site/SiteListFileCache.php rename to includes/site/FileBasedSiteLookup.php index e48a187..03121f8 100644 --- a/includes/site/SiteListFileCache.php +++ b/includes/site/FileBasedSiteLookup.php @@ -24,11 +24,11 @@ * Provides a file-based cache of a SiteStore, stored as a json file. * The cache can be built with the rebuildSitesCache.php maintenance script, * and a MediaWiki instance can be setup to use this by setting the - * 'wgSitesCacheFile' configuration to the cache file location. + * 'wgSitesFileCache' configuration to the cache file location. * * @since 1.25 */ -class SiteListFileCache { +class FileBasedSiteLookup implements SiteLookup { /** * @var SiteList diff --git a/includes/site/SiteDBStore.php b/includes/site/SiteDBStore.php new file mode 100644 index 0000000..315c396 --- /dev/null +++ b/includes/site/SiteDBStore.php @@ -0,0 +1,345 @@ +<?php + +/** + * Represents the site configuration of a wiki. + * Holds a list of sites (ie SiteList), stored in the database. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 1.25 + * + * @file + * @ingroup Site + * + * @license GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +class SiteDBStore implements SiteStore { + + /** + * @var SiteList|null + */ + protected $sites = null; + + /** + * @var ORMTable + */ + protected $sitesTable; + + /** + * @since 1.25 + * + * @param ORMTable|null $sitesTable + */ + public function __construct( ORMTable $sitesTable = null ) { + if ( $sitesTable === null ) { + $sitesTable = $this->newSitesTable(); + } + + $this->sitesTable = $sitesTable; + } + + /** + * @see SiteStore::getSites + * + * @since 1.25 + * + * @return SiteList + */ + public function getSites() { + $this->loadSites(); + + return $this->sites; + } + + /** + * Returns a new Site object constructed from the provided ORMRow. + * + * @since 1.25 + * + * @param ORMRow $siteRow + * + * @return Site + */ + protected function siteFromRow( ORMRow $siteRow ) { + + $site = Site::newForType( $siteRow->getField( 'type', Site::TYPE_UNKNOWN ) ); + + $site->setGlobalId( $siteRow->getField( 'global_key' ) ); + + $site->setInternalId( $siteRow->getField( 'id' ) ); + + if ( $siteRow->hasField( 'forward' ) ) { + $site->setForward( $siteRow->getField( 'forward' ) ); + } + + if ( $siteRow->hasField( 'group' ) ) { + $site->setGroup( $siteRow->getField( 'group' ) ); + } + + if ( $siteRow->hasField( 'language' ) ) { + $site->setLanguageCode( $siteRow->getField( 'language' ) === '' + ? null + : $siteRow->getField( 'language' ) + ); + } + + if ( $siteRow->hasField( 'source' ) ) { + $site->setSource( $siteRow->getField( 'source' ) ); + } + + if ( $siteRow->hasField( 'data' ) ) { + $site->setExtraData( $siteRow->getField( 'data' ) ); + } + + if ( $siteRow->hasField( 'config' ) ) { + $site->setExtraConfig( $siteRow->getField( 'config' ) ); + } + + return $site; + } + + /** + * Get a new ORMRow from a Site object + * + * @since 1.25 + * + * @param Site $site + * + * @return ORMRow + */ + protected function getRowFromSite( Site $site ) { + $fields = array( + // Site data + 'global_key' => $site->getGlobalId(), // TODO: check not null + 'type' => $site->getType(), + 'group' => $site->getGroup(), + 'source' => $site->getSource(), + 'language' => $site->getLanguageCode() === null ? '' : $site->getLanguageCode(), + 'protocol' => $site->getProtocol(), + 'domain' => strrev( $site->getDomain() ) . '.', + 'data' => $site->getExtraData(), + + // Site config + 'forward' => $site->shouldForward(), + 'config' => $site->getExtraConfig(), + ); + + if ( $site->getInternalId() !== null ) { + $fields['id'] = $site->getInternalId(); + } + + return new ORMRow( $this->sitesTable, $fields ); + } + + /** + * Fetches the site from the database and loads them into the sites field. + * + * @since 1.25 + */ + protected function loadSites() { + $this->sites = new SiteList(); + + foreach ( $this->sitesTable->select() as $siteRow ) { + $this->sites[] = $this->siteFromRow( $siteRow ); + } + + // Batch load the local site identifiers. + $ids = wfGetDB( $this->sitesTable->getReadDb() )->select( + 'site_identifiers', + array( + 'si_site', + 'si_type', + 'si_key', + ), + array(), + __METHOD__ + ); + + foreach ( $ids as $id ) { + if ( $this->sites->hasInternalId( $id->si_site ) ) { + $site = $this->sites->getSiteByInternalId( $id->si_site ); + $site->addLocalId( $id->si_type, $id->si_key ); + $this->sites->setSite( $site ); + } + } + } + + /** + * @see SiteStore::getSite + * + * @since 1.25 + * + * @param string $globalId + * + * @return Site|null + */ + public function getSite( $globalId ) { + if ( $this->sites === null ) { + $this->sites = $this->getSites(); + } + + return $this->sites->hasSite( $globalId ) ? $this->sites->getSite( $globalId ) : null; + } + + /** + * @see SiteStore::saveSite + * + * @since 1.25 + * + * @param Site $site + * + * @return bool Success indicator + */ + public function saveSite( Site $site ) { + return $this->saveSites( array( $site ) ); + } + + /** + * @see SiteStore::saveSites + * + * @since 1.25 + * + * @param Site[] $sites + * + * @return bool Success indicator + */ + public function saveSites( array $sites ) { + if ( empty( $sites ) ) { + return true; + } + + $dbw = $this->sitesTable->getWriteDbConnection(); + + $dbw->startAtomic( __METHOD__ ); + + $success = true; + + $internalIds = array(); + $localIds = array(); + + foreach ( $sites as $site ) { + if ( $site->getInternalId() !== null ) { + $internalIds[] = $site->getInternalId(); + } + + $siteRow = $this->getRowFromSite( $site ); + $success = $siteRow->save( __METHOD__ ) && $success; + + foreach ( $site->getLocalIds() as $idType => $ids ) { + foreach ( $ids as $id ) { + $localIds[] = array( $siteRow->getId(), $idType, $id ); + } + } + } + + if ( $internalIds !== array() ) { + $dbw->delete( + 'site_identifiers', + array( 'si_site' => $internalIds ), + __METHOD__ + ); + } + + foreach ( $localIds as $localId ) { + $dbw->insert( + 'site_identifiers', + array( + 'si_site' => $localId[0], + 'si_type' => $localId[1], + 'si_key' => $localId[2], + ), + __METHOD__ + ); + } + + $dbw->endAtomic( __METHOD__ ); + + $this->reset(); + + return $success; + } + + /** + * Resets the SiteList + * + * @since 1.25 + */ + public function reset() { + $this->sites = null; + } + + /** + * Clears the list of sites stored in the database. + * + * @see SiteStore::clear() + * + * @return bool Success + */ + public function clear() { + $dbw = $this->sitesTable->getWriteDbConnection(); + + $dbw->startAtomic( __METHOD__ ); + $ok = $dbw->delete( 'sites', '*', __METHOD__ ); + $ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok; + $dbw->endAtomic( __METHOD__ ); + + $this->reset(); + + return $ok; + } + + /** + * @since 1.25 + * + * @return ORMTable + */ + protected function newSitesTable() { + return new ORMTable( + 'sites', + array( + 'id' => 'id', + + // Site data + 'global_key' => 'str', + 'type' => 'str', + 'group' => 'str', + 'source' => 'str', + 'language' => 'str', + 'protocol' => 'str', + 'domain' => 'str', + 'data' => 'array', + + // Site config + 'forward' => 'bool', + 'config' => 'array', + ), + array( + 'type' => Site::TYPE_UNKNOWN, + 'group' => Site::GROUP_NONE, + 'source' => Site::SOURCE_LOCAL, + 'data' => array(), + + 'forward' => false, + 'config' => array(), + 'language' => '', + ), + 'ORMRow', + 'site_' + ); + } + +} diff --git a/includes/site/SiteLookup.php b/includes/site/SiteLookup.php new file mode 100644 index 0000000..610bf0b --- /dev/null +++ b/includes/site/SiteLookup.php @@ -0,0 +1,50 @@ +<?php + +/** + * Interface for service objects providing a lookup of Site objects. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 1.25 + * + * @file + * @ingroup Site + * + * @license GNU GPL v2+ + */ +interface SiteLookup { + + /** + * Returns the site with provided global id, or null if there is no such site. + * + * @since 1.25 + * + * @param string $globalId + * + * @return Site|null + */ + public function getSite( $globalId ); + + /** + * Returns a list of all sites. + * + * @since 1.25 + * + * @return SiteList + */ + public function getSites(); + +} diff --git a/includes/site/SiteSQLStore.php b/includes/site/SiteSQLStore.php index 8f25c76..3e8a932 100644 --- a/includes/site/SiteSQLStore.php +++ b/includes/site/SiteSQLStore.php @@ -28,36 +28,11 @@ * @license GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > */ -class SiteSQLStore implements SiteStore { - /** - * @since 1.21 - * - * @var SiteList|null - */ - protected $sites = null; - - /** - * @var ORMTable - */ - protected $sitesTable; - - /** - * @var string|null - */ - private $cacheKey = null; - - /** - * @var int - */ - private $cacheTimeout = 3600; - - /** - * @var BagOStuff - */ - private $cache; +class SiteSQLStore extends CachingSiteStore { /** * @since 1.21 + * @deprecated 1.25 Construct a SiteStore instance directly instead. * * @param ORMTable|null $sitesTable * @param BagOStuff|null $cache @@ -69,370 +44,9 @@ $cache = wfGetMainCache(); } - return new static( $cache, $sitesTable ); - } + $siteStore = new SiteDBStore(); - /** - * Constructor. - * - * @since 1.21 - * - * @param BagOStuff $cache - * @param ORMTable|null $sitesTable - */ - protected function __construct( BagOStuff $cache, ORMTable $sitesTable = null ) { - if ( $sitesTable === null ) { - $sitesTable = $this->newSitesTable(); - } - - $this->cache = $cache; - $this->sitesTable = $sitesTable; - } - - /** - * Constructs a cache key to use for caching the list of sites. - * - * This includes the concrete class name of the site list as well as a version identifier - * for the list's serialization, to avoid problems when unserializing site lists serialized - * by an older version, e.g. when reading from a cache. - * - * The cache key also includes information about where the sites were loaded from, e.g. - * the name of a database table. - * - * @see SiteList::getSerialVersionId - * - * @return string The cache key. - */ - protected function getCacheKey() { - - if ( $this->cacheKey === null ) { - $type = 'SiteList#' . SiteList::getSerialVersionId(); - $source = $this->sitesTable->getName(); - - if ( $this->sitesTable->getTargetWiki() !== false ) { - $source = $this->sitesTable->getTargetWiki() . '.' . $source; - } - - $this->cacheKey = wfMemcKey( "$source/$type" ); - } - - return $this->cacheKey; - } - - /** - * @see SiteStore::getSites - * - * @since 1.21 - * - * @param string $source Either 'cache' or 'recache' - * - * @return SiteList - */ - public function getSites( $source = 'cache' ) { - - if ( $source === 'cache' ) { - if ( $this->sites === null ) { - $sites = $this->cache->get( $this->getCacheKey() ); - - if ( is_object( $sites ) ) { - $this->sites = $sites; - } else { - $this->loadSites(); - } - } - } - else { - $this->loadSites(); - } - - return $this->sites; - } - - /** - * Returns a new Site object constructed from the provided ORMRow. - * - * @since 1.21 - * - * @param ORMRow $siteRow - * - * @return Site - */ - protected function siteFromRow( ORMRow $siteRow ) { - - $site = Site::newForType( $siteRow->getField( 'type', Site::TYPE_UNKNOWN ) ); - - $site->setGlobalId( $siteRow->getField( 'global_key' ) ); - - $site->setInternalId( $siteRow->getField( 'id' ) ); - - if ( $siteRow->hasField( 'forward' ) ) { - $site->setForward( $siteRow->getField( 'forward' ) ); - } - - if ( $siteRow->hasField( 'group' ) ) { - $site->setGroup( $siteRow->getField( 'group' ) ); - } - - if ( $siteRow->hasField( 'language' ) ) { - $site->setLanguageCode( $siteRow->getField( 'language' ) === '' - ? null - : $siteRow->getField( 'language' ) - ); - } - - if ( $siteRow->hasField( 'source' ) ) { - $site->setSource( $siteRow->getField( 'source' ) ); - } - - if ( $siteRow->hasField( 'data' ) ) { - $site->setExtraData( $siteRow->getField( 'data' ) ); - } - - if ( $siteRow->hasField( 'config' ) ) { - $site->setExtraConfig( $siteRow->getField( 'config' ) ); - } - - return $site; - } - - /** - * Get a new ORMRow from a Site object - * - * @since 1.22 - * - * @param Site $site - * - * @return ORMRow - */ - protected function getRowFromSite( Site $site ) { - $fields = array( - // Site data - 'global_key' => $site->getGlobalId(), // TODO: check not null - 'type' => $site->getType(), - 'group' => $site->getGroup(), - 'source' => $site->getSource(), - 'language' => $site->getLanguageCode() === null ? '' : $site->getLanguageCode(), - 'protocol' => $site->getProtocol(), - 'domain' => strrev( $site->getDomain() ) . '.', - 'data' => $site->getExtraData(), - - // Site config - 'forward' => $site->shouldForward(), - 'config' => $site->getExtraConfig(), - ); - - if ( $site->getInternalId() !== null ) { - $fields['id'] = $site->getInternalId(); - } - - return new ORMRow( $this->sitesTable, $fields ); - } - - /** - * Fetches the site from the database and loads them into the sites field. - * - * @since 1.21 - */ - protected function loadSites() { - - $this->sites = new SiteList(); - - foreach ( $this->sitesTable->select() as $siteRow ) { - $this->sites[] = $this->siteFromRow( $siteRow ); - } - - // Batch load the local site identifiers. - $ids = wfGetDB( $this->sitesTable->getReadDb() )->select( - 'site_identifiers', - array( - 'si_site', - 'si_type', - 'si_key', - ), - array(), - __METHOD__ - ); - - foreach ( $ids as $id ) { - if ( $this->sites->hasInternalId( $id->si_site ) ) { - $site = $this->sites->getSiteByInternalId( $id->si_site ); - $site->addLocalId( $id->si_type, $id->si_key ); - $this->sites->setSite( $site ); - } - } - - $this->cache->set( $this->getCacheKey(), $this->sites, $this->cacheTimeout ); - - } - - /** - * @see SiteStore::getSite - * - * @since 1.21 - * - * @param string $globalId - * @param string $source - * - * @return Site|null - */ - public function getSite( $globalId, $source = 'cache' ) { - - $sites = $this->getSites( $source ); - - return $sites->hasSite( $globalId ) ? $sites->getSite( $globalId ) : null; - } - - /** - * @see SiteStore::saveSite - * - * @since 1.21 - * - * @param Site $site - * - * @return bool Success indicator - */ - public function saveSite( Site $site ) { - return $this->saveSites( array( $site ) ); - } - - /** - * @see SiteStore::saveSites - * - * @since 1.21 - * - * @param Site[] $sites - * - * @return bool Success indicator - */ - public function saveSites( array $sites ) { - - if ( empty( $sites ) ) { - return true; - } - - $dbw = $this->sitesTable->getWriteDbConnection(); - - $dbw->startAtomic( __METHOD__ ); - - $success = true; - - $internalIds = array(); - $localIds = array(); - - foreach ( $sites as $site ) { - if ( $site->getInternalId() !== null ) { - $internalIds[] = $site->getInternalId(); - } - - $siteRow = $this->getRowFromSite( $site ); - $success = $siteRow->save( __METHOD__ ) && $success; - - foreach ( $site->getLocalIds() as $idType => $ids ) { - foreach ( $ids as $id ) { - $localIds[] = array( $siteRow->getId(), $idType, $id ); - } - } - } - - if ( $internalIds !== array() ) { - $dbw->delete( - 'site_identifiers', - array( 'si_site' => $internalIds ), - __METHOD__ - ); - } - - foreach ( $localIds as $localId ) { - $dbw->insert( - 'site_identifiers', - array( - 'si_site' => $localId[0], - 'si_type' => $localId[1], - 'si_key' => $localId[2], - ), - __METHOD__ - ); - } - - $dbw->endAtomic( __METHOD__ ); - - // purge cache - $this->reset(); - - return $success; - } - - /** - * Purges the internal and external cache of the site list, forcing the list - * of sites to be re-read from the database. - * - * @since 1.21 - */ - public function reset() { - // purge cache - $this->cache->delete( $this->getCacheKey() ); - $this->sites = null; - - } - - /** - * Clears the list of sites stored in the database. - * - * @see SiteStore::clear() - * - * @return bool Success - */ - public function clear() { - $dbw = $this->sitesTable->getWriteDbConnection(); - - $dbw->startAtomic( __METHOD__ ); - $ok = $dbw->delete( 'sites', '*', __METHOD__ ); - $ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok; - $dbw->endAtomic( __METHOD__ ); - - $this->reset(); - - return $ok; - } - - /** - * @since 1.21 - * - * @return ORMTable - */ - protected function newSitesTable() { - return new ORMTable( - 'sites', - array( - 'id' => 'id', - - // Site data - 'global_key' => 'str', - 'type' => 'str', - 'group' => 'str', - 'source' => 'str', - 'language' => 'str', - 'protocol' => 'str', - 'domain' => 'str', - 'data' => 'array', - - // Site config - 'forward' => 'bool', - 'config' => 'array', - ), - array( - 'type' => Site::TYPE_UNKNOWN, - 'group' => Site::GROUP_NONE, - 'source' => Site::SOURCE_LOCAL, - 'data' => array(), - - 'forward' => false, - 'config' => array(), - 'language' => '', - ), - 'ORMRow', - 'site_' - ); + return new static( $siteStore, $cache ); } } diff --git a/includes/site/SiteStore.php b/includes/site/SiteStore.php index 537f1cc..c645548 100644 --- a/includes/site/SiteStore.php +++ b/includes/site/SiteStore.php @@ -26,7 +26,7 @@ * @license GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > */ -interface SiteStore { +interface SiteStore extends SiteLookup { /** * Saves the provided site. @@ -56,26 +56,19 @@ * @since 1.21 * * @param string $globalId - * @param string $source Either 'cache' or 'recache'. - * If 'cache', the values are allowed (but not obliged) to come from a cache. * * @return Site|null */ - public function getSite( $globalId, $source = 'cache' ); + public function getSite( $globalId ); /** - * Returns a list of all sites. By default this site is - * fetched from the cache, which can be changed to loading - * the list from the database using the $useCache parameter. + * Returns a list of all sites. * * @since 1.21 * - * @param string $source Either 'cache' or 'recache'. - * If 'cache', the values are allowed (but not obliged) to come from a cache. - * * @return SiteList */ - public function getSites( $source = 'cache' ); + public function getSites(); /** * Deletes all sites from the database. After calling clear(), getSites() will return an empty diff --git a/includes/site/SiteListFileCacheBuilder.php b/includes/site/SitesFileCacheBuilder.php similarity index 89% rename from includes/site/SiteListFileCacheBuilder.php rename to includes/site/SitesFileCacheBuilder.php index 7307a6f..89ae65b 100644 --- a/includes/site/SiteListFileCacheBuilder.php +++ b/includes/site/SitesFileCacheBuilder.php @@ -22,12 +22,12 @@ * * @license GNU GPL v2+ */ -class SiteListFileCacheBuilder { +class SitesFileCacheBuilder { /** - * @var SiteStore + * @var SiteLookup */ - private $siteStore; + private $siteLookup; /** * @var string @@ -35,16 +35,16 @@ private $cacheFile; /** - * @param SiteStore $siteStore + * @param SiteLookup $siteLookup * @param string $cacheFile */ - public function __construct( SiteStore $siteStore, $cacheFile ) { - $this->siteStore = $siteStore; + public function __construct( SiteLookup $siteLookup, $cacheFile ) { + $this->siteLookup = $siteLookup; $this->cacheFile = $cacheFile; } public function build() { - $this->sites = $this->siteStore->getSites( 'recache' ); + $this->sites = $this->siteLookup->getSites(); $this->cacheSites( $this->sites->getArrayCopy() ); } diff --git a/maintenance/rebuildSitesCache.php b/maintenance/rebuildSitesFileCache.php similarity index 73% rename from maintenance/rebuildSitesCache.php rename to maintenance/rebuildSitesFileCache.php index 862a983..1c4b01b 100644 --- a/maintenance/rebuildSitesCache.php +++ b/maintenance/rebuildSitesFileCache.php @@ -23,26 +23,26 @@ require_once __DIR__ . '/Maintenance.php'; /** - * Maintenance script to dump the SiteStore as a static json file. + * Maintenance script to dump a SiteStore as a static json file. * * @ingroup Maintenance */ -class RebuildSitesCache extends Maintenance { +class RebuildSitesFileCache extends Maintenance { public function __construct() { parent::__construct(); - $this->mDescription = "Dumps site store as json"; + $this->mDescription = "Cache sites as json for file-based lookup."; $this->addOption( 'file', 'File to output the json to', false, true ); } public function execute() { - $siteListFileCacheBuilder = new SiteListFileCacheBuilder( - SiteSQLStore::newInstance(), + $sitesFileCacheBuilder = new SitesFileCacheBuilder( + new SiteDBStore(), $this->getCacheFile() ); - $siteListFileCacheBuilder->build(); + $sitesFileCacheBuilder->build(); } /** @@ -52,10 +52,10 @@ if ( $this->hasOption( 'file' ) ) { $jsonFile = $this->getOption( 'file' ); } else { - $jsonFile = $this->getConfig()->get( 'SitesCacheFile' ); + $jsonFile = $this->getConfig()->get( 'SitesFileCache' ); if ( $jsonFile === false ) { - $this->error( 'Error: No sites cache file is set in configuration.', 1 ); + $this->error( 'Error: No file set in configuration for SitesFileCache.', 1 ); } } @@ -64,5 +64,5 @@ } -$maintClass = "RebuildSitesCache"; +$maintClass = "RebuildSitesFileCache"; require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/tests/phpunit/includes/site/SiteSQLStoreTest.php b/tests/phpunit/includes/site/CachingSiteStoreTest.php similarity index 84% copy from tests/phpunit/includes/site/SiteSQLStoreTest.php copy to tests/phpunit/includes/site/CachingSiteStoreTest.php index 6002c1a..9db7b5a 100644 --- a/tests/phpunit/includes/site/SiteSQLStoreTest.php +++ b/tests/phpunit/includes/site/CachingSiteStoreTest.php @@ -1,7 +1,7 @@ <?php /** - * Tests for the SiteSQLStore class. + * Tests for the CachingSiteStore class. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,16 +30,16 @@ * @licence GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > */ -class SiteSQLStoreTest extends MediaWikiTestCase { +class CachingSiteStoreTest extends MediaWikiTestCase { /** - * @covers SiteSQLStore::getSites + * @covers CachingSiteStore::getSites */ public function testGetSites() { $expectedSites = TestSites::getSites(); TestSites::insertIntoDb(); - $store = SiteSQLStore::newInstance(); + $store = new CachingSiteStore( new SiteDBStore(), wfGetMainCache() ); $sites = $store->getSites(); @@ -60,10 +60,10 @@ } /** - * @covers SiteSQLStore::saveSites + * @covers CachingSiteStore::saveSites */ public function testSaveSites() { - $store = SiteSQLStore::newInstance(); + $store = new CachingSiteStore( new SiteDBStore(), wfGetMainCache() ); $sites = array(); @@ -93,11 +93,11 @@ } /** - * @covers SiteSQLStore::reset + * @covers CachingSiteStore::reset */ public function testReset() { - $store1 = SiteSQLStore::newInstance(); - $store2 = SiteSQLStore::newInstance(); + $store1 = new CachingSiteStore( new SiteDBStore(), wfGetMainCache() ); + $store2 = new CachingSiteStore( new SiteDBStore(), wfGetMainCache() ); // initialize internal cache $this->assertGreaterThan( 0, $store1->getSites()->count() ); @@ -119,10 +119,10 @@ } /** - * @covers SiteSQLStore::clear + * @covers CachingSiteStore::clear */ public function testClear() { - $store = SiteSQLStore::newInstance(); + $store = new CachingSiteStore( new SiteDBStore(), wfGetMainCache() ); $this->assertTrue( $store->clear() ); $site = $store->getSite( 'enwiki' ); diff --git a/tests/phpunit/includes/site/SiteListFileCacheTest.php b/tests/phpunit/includes/site/FileBasedSiteLookupTest.php similarity index 77% rename from tests/phpunit/includes/site/SiteListFileCacheTest.php rename to tests/phpunit/includes/site/FileBasedSiteLookupTest.php index 05dcd8a..e9c1874 100644 --- a/tests/phpunit/includes/site/SiteListFileCacheTest.php +++ b/tests/phpunit/includes/site/FileBasedSiteLookupTest.php @@ -22,13 +22,13 @@ * @ingroup Site * @ingroup Test * - * @covers SiteListFileCache + * @covers FileBasedSiteLookup * @group Site * * @licence GNU GPL v2+ * @author Katie Filbert < aude.w...@gmail.com > */ -class SiteListFileCacheTest extends PHPUnit_Framework_TestCase { +class FileBasedSiteLookupTest extends PHPUnit_Framework_TestCase { protected function setUp() { $this->cacheFile = $this->getCacheFile(); @@ -40,40 +40,40 @@ public function testGetSites() { $sites = $this->getSites(); - $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites ); + $cacheBuilder = $this->newSitesFileCacheBuilder( $sites ); $cacheBuilder->build(); - $cache = new SiteListFileCache( $this->cacheFile ); + $cache = new FileBasedSiteLookup( $this->cacheFile ); $this->assertEquals( $sites, $cache->getSites() ); } public function testGetSite() { $sites = $this->getSites(); - $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites ); + $cacheBuilder = $this->newSitesFileCacheBuilder( $sites ); $cacheBuilder->build(); - $cache = new SiteListFileCache( $this->cacheFile ); + $cache = new FileBasedSiteLookup( $this->cacheFile ); $this->assertEquals( $sites->getSite( 'enwiktionary' ), $cache->getSite( 'enwiktionary' ) ); } - private function newSiteListFileCacheBuilder( SiteList $sites ) { - return new SiteListFileCacheBuilder( - $this->getSiteSQLStore( $sites ), + private function newSitesFileCacheBuilder( SiteList $sites ) { + return new SitesFileCacheBuilder( + $this->getSiteLookup( $sites ), $this->cacheFile ); } - private function getSiteSQLStore( SiteList $sites ) { - $siteSQLStore = $this->getMockBuilder( 'SiteSQLStore' ) + private function getSiteLookup( SiteList $sites ) { + $siteLookup = $this->getMockBuilder( 'SiteLookup' ) ->disableOriginalConstructor() ->getMock(); - $siteSQLStore->expects( $this->any() ) + $siteLookup->expects( $this->any() ) ->method( 'getSites' ) ->will( $this->returnValue( $sites ) ); - return $siteSQLStore; + return $siteLookup; } private function getSites() { diff --git a/tests/phpunit/includes/site/SiteSQLStoreTest.php b/tests/phpunit/includes/site/SiteDBStoreTest.php similarity index 88% rename from tests/phpunit/includes/site/SiteSQLStoreTest.php rename to tests/phpunit/includes/site/SiteDBStoreTest.php index 6002c1a..ae2720f 100644 --- a/tests/phpunit/includes/site/SiteSQLStoreTest.php +++ b/tests/phpunit/includes/site/SiteDBStoreTest.php @@ -1,7 +1,7 @@ <?php /** - * Tests for the SiteSQLStore class. + * Tests for the SiteDBStore class. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,16 +30,16 @@ * @licence GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > */ -class SiteSQLStoreTest extends MediaWikiTestCase { +class SiteDBStoreTest extends MediaWikiTestCase { /** - * @covers SiteSQLStore::getSites + * @covers SiteDBStore::getSites */ public function testGetSites() { $expectedSites = TestSites::getSites(); TestSites::insertIntoDb(); - $store = SiteSQLStore::newInstance(); + $store = new SiteDBStore(); $sites = $store->getSites(); @@ -60,10 +60,10 @@ } /** - * @covers SiteSQLStore::saveSites + * @covers SiteDBStore::saveSites */ public function testSaveSites() { - $store = SiteSQLStore::newInstance(); + $store = new SiteDBStore(); $sites = array(); @@ -93,11 +93,11 @@ } /** - * @covers SiteSQLStore::reset + * @covers SiteDBStore::reset */ public function testReset() { - $store1 = SiteSQLStore::newInstance(); - $store2 = SiteSQLStore::newInstance(); + $store1 = new SiteDBStore(); + $store2 = new SiteDBStore(); // initialize internal cache $this->assertGreaterThan( 0, $store1->getSites()->count() ); @@ -119,10 +119,10 @@ } /** - * @covers SiteSQLStore::clear + * @covers SiteDBStore::clear */ public function testClear() { - $store = SiteSQLStore::newInstance(); + $store = new SiteDBStore(); $this->assertTrue( $store->clear() ); $site = $store->getSite( 'enwiki' ); diff --git a/tests/phpunit/includes/site/SiteListFileCacheBuilderTest.php b/tests/phpunit/includes/site/SitesFileCacheBuilderTest.php similarity index 86% rename from tests/phpunit/includes/site/SiteListFileCacheBuilderTest.php rename to tests/phpunit/includes/site/SitesFileCacheBuilderTest.php index bbe8cc7..e44c25e 100644 --- a/tests/phpunit/includes/site/SiteListFileCacheBuilderTest.php +++ b/tests/phpunit/includes/site/SitesFileCacheBuilderTest.php @@ -22,13 +22,13 @@ * @ingroup Site * @ingroup Test * - * @covers SiteListFileCacheBuilder + * @covers SitesFileCacheBuilder * @group Site * * @licence GNU GPL v2+ * @author Katie Filbert < aude.w...@gmail.com > */ -class SiteListFileCacheBuilderTest extends PHPUnit_Framework_TestCase { +class SitesFileCacheBuilderTest extends PHPUnit_Framework_TestCase { protected function setUp() { $this->cacheFile = $this->getCacheFile(); @@ -39,7 +39,7 @@ } public function testBuild() { - $cacheBuilder = $this->newSiteListFileCacheBuilder( $this->getSites() ); + $cacheBuilder = $this->newSitesFileCacheBuilder( $this->getSites() ); $cacheBuilder->build(); $contents = file_get_contents( $this->cacheFile ); @@ -91,23 +91,23 @@ ); } - private function newSiteListFileCacheBuilder( SiteList $sites ) { - return new SiteListFileCacheBuilder( - $this->getSiteSQLStore( $sites ), + private function newSitesFileCacheBuilder( SiteList $sites ) { + return new SitesFileCacheBuilder( + $this->getSiteLookup( $sites ), $this->cacheFile ); } - private function getSiteSQLStore( SiteList $sites ) { - $siteSQLStore = $this->getMockBuilder( 'SiteSQLStore' ) + private function getSiteLookup( SiteList $sites ) { + $siteLookup = $this->getMockBuilder( 'SiteLookup' ) ->disableOriginalConstructor() ->getMock(); - $siteSQLStore->expects( $this->any() ) + $siteLookup->expects( $this->any() ) ->method( 'getSites' ) ->will( $this->returnValue( $sites ) ); - return $siteSQLStore; + return $siteLookup; } private function getSites() { diff --git a/tests/phpunit/includes/site/TestSites.php b/tests/phpunit/includes/site/TestSites.php index af314ba..a11118d 100644 --- a/tests/phpunit/includes/site/TestSites.php +++ b/tests/phpunit/includes/site/TestSites.php @@ -108,7 +108,7 @@ * @since 0.1 */ public static function insertIntoDb() { - $sitesTable = SiteSQLStore::newInstance(); + $sitesTable = new SiteDBStore(); $sitesTable->clear(); $sitesTable->saveSites( TestSites::getSites() ); } -- To view, visit https://gerrit.wikimedia.org/r/188965 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I36b599884c211580ea6806a8a190c65c4f9087cf Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits