* @return string
*/
function wfMemcKey( /*...*/ ) {
- global $wgCachePrefix;
- $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
- $args = func_get_args();
- $key = $prefix . ':' . implode( ':', $args );
- return strtr( $key, ' ', '_' );
+ return call_user_func_array(
+ array( ObjectCache::getMainClusterInstance(), 'makeKey' ),
+ func_get_args()
+ );
}
/**
*/
function wfForeignMemcKey( $db, $prefix /*...*/ ) {
$args = array_slice( func_get_args(), 2 );
- if ( $prefix ) {
- // Match wfWikiID() logic
- $key = "$db-$prefix:" . implode( ':', $args );
- } else {
- $key = $db . ':' . implode( ':', $args );
- }
- return strtr( $key, ' ', '_' );
+ $keyspace = $prefix ? "$db-$prefix" : $db;
+ return call_user_func_array(
+ array( ObjectCache::getMainClusterInstance(), 'makeKeyInternal' ),
+ array( $keyspace, $args )
+ );
}
/**
* @return string
*/
function wfGlobalCacheKey( /*...*/ ) {
- $args = func_get_args();
- $key = 'global:' . implode( ':', $args );
- return strtr( $key, ' ', '_' );
+ return call_user_func_array(
+ array( ObjectCache::getMainClusterInstance(), 'makeGlobalKey' ),
+ func_get_args()
+ );
}
/**
abstract class BagOStuff implements LoggerAwareInterface {
/** @var array[] Lock tracking */
protected $locks = array();
+
/** @var integer */
protected $lastError = self::ERR_NONE;
+ /** @var string */
+ protected $keyspace = 'local';
+
/** @var LoggerInterface */
protected $logger;
} else {
$this->setLogger( new NullLogger() );
}
+
+ if ( isset( $params['keyspace'] ) ) {
+ $this->keyspace = $params['keyspace'];
+ }
}
/**
protected function isInteger( $value ) {
return ( is_int( $value ) || ctype_digit( $value ) );
}
+
+ /**
+ * Construct a cache key.
+ *
+ * @since 1.27
+ * @param string $keyspace
+ * @param array $args
+ * @return string
+ */
+ public function makeKeyInternal( $keyspace, $args ) {
+ $key = $keyspace . ':' . implode( ':', $args );
+ return strtr( $key, ' ', '_' );
+ }
+
+ /**
+ * Make a global cache key.
+ *
+ * @since 1.27
+ * @param string $args,...
+ * @return string
+ */
+ public function makeGlobalKey() {
+ return $this->makeKeyInternal( 'global', func_get_args() );
+ }
+
+ /**
+ * Make a cache key, scoped to this instance's keyspace.
+ *
+ * @since 1.27
+ * @param string $args,...
+ * @return string
+ */
+ public function makeKey() {
+ return $this->makeKeyInternal( $this->keyspace, func_get_args() );
+ }
}
return self::newFromParams( $wgObjectCaches[$id] );
}
+ /**
+ * Get the default keyspace for this wiki.
+ *
+ * This is either the value of the `CachePrefix` configuration variable,
+ * or (if the former is unset) the `DBname` configuration variable, with
+ * `DBprefix` (if defined).
+ *
+ * @return string
+ */
+ public static function getDefaultKeyspace() {
+ global $wgCachePrefix, $wgDBname, $wgDBprefix;
+
+ $keyspace = $wgCachePrefix;
+ if ( is_string( $keyspace ) && $keyspace !== '' ) {
+ return $keyspace;
+ }
+
+ $keyspace = $wgDBname;
+ if ( is_string( $wgDBprefix ) && $wgDBprefix !== '' ) {
+ $keyspace .= '-' . $wgDBprefix;
+ }
+
+ return $keyspace;
+ }
+
/**
* Create a new cache object from parameters.
*
// have all logging suddenly disappear
$params['logger'] = LoggerFactory::getInstance( 'objectcache' );
}
+ if ( !isset( $params['keyspace'] ) ) {
+ $params['keyspace'] = self::getDefaultKeyspace();
+ }
if ( isset( $params['factory'] ) ) {
return call_user_func( $params['factory'], $params );
} elseif ( isset( $params['class'] ) ) {
* @return BagOStuff
*/
public static function getMainClusterInstance() {
- $config = RequestContext::getMain()->getConfig();
- $id = $config->get( 'MainCacheType' );
- return self::getInstance( $id );
+ global $wgMainCacheType;
+
+ return self::getInstance( $wgMainCacheType );
}
/**
}
public function testWfMemcKey() {
- // Just assert the exact output so we can catch unintentional changes to key
- // construction, which would effectively invalidate all existing cache.
-
- $this->setMwGlobals( array(
- 'wgCachePrefix' => false,
- 'wgDBname' => 'example',
- 'wgDBprefix' => '',
- ) );
- $this->assertEquals(
- wfMemcKey( 'foo', '123', 'bar' ),
- 'example:foo:123:bar'
- );
-
- $this->setMwGlobals( array(
- 'wgCachePrefix' => false,
- 'wgDBname' => 'example',
- 'wgDBprefix' => 'mw_',
- ) );
- $this->assertEquals(
- wfMemcKey( 'foo', '123', 'bar' ),
- 'example-mw_:foo:123:bar'
- );
-
- $this->setMwGlobals( array(
- 'wgCachePrefix' => 'custom',
- 'wgDBname' => 'example',
- 'wgDBprefix' => 'mw_',
- ) );
+ $cache = ObjectCache::getMainClusterInstance();
$this->assertEquals(
- wfMemcKey( 'foo', '123', 'bar' ),
- 'custom:foo:123:bar'
+ $cache->makeKey( 'foo', 123, 'bar' ),
+ wfMemcKey( 'foo', 123, 'bar' )
);
}
public function testWfForeignMemcKey() {
- $this->setMwGlobals( array(
- 'wgCachePrefix' => false,
- 'wgDBname' => 'example',
- 'wgDBprefix' => '',
- ) );
- $local = wfMemcKey( 'foo', 'bar' );
-
- $this->setMwGlobals( array(
- 'wgDBname' => 'other',
- 'wgDBprefix' => 'mw_',
- ) );
+ $cache = ObjectCache::getMainClusterInstance();
+ $keyspace = $this->readAttribute( $cache, 'keyspace' );
$this->assertEquals(
- wfForeignMemcKey( 'example', '', 'foo', 'bar' ),
- $local,
- 'Match output of wfMemcKey from local wiki'
+ wfForeignMemcKey( $keyspace, '', 'foo', 'bar' ),
+ $cache->makeKey( 'foo', 'bar' )
);
}
public function testWfGlobalCacheKey() {
- $this->setMwGlobals( array(
- 'wgCachePrefix' => 'ignored',
- 'wgDBname' => 'example',
- 'wgDBprefix' => ''
- ) );
- $one = wfGlobalCacheKey( 'some', 'thing' );
- $this->assertEquals(
- $one,
- 'global:some:thing'
- );
-
- $this->setMwGlobals( array(
- 'wgDBname' => 'other',
- 'wgDBprefix' => 'mw_'
- ) );
- $two = wfGlobalCacheKey( 'some', 'thing' );
-
+ $cache = ObjectCache::getMainClusterInstance();
$this->assertEquals(
- $one,
- $two,
- 'Not fragmented by wiki id'
+ $cache->makeGlobalKey( 'foo', 123, 'bar' ),
+ wfGlobalCacheKey( 'foo', 123, 'bar' )
);
}
$this->cache->delete( wfMemcKey( 'test' ) );
}
+ /**
+ * @covers BagOStuff::makeGlobalKey
+ * @covers BagOStuff::makeKeyInternal
+ */
+ public function testMakeKey() {
+ $cache = ObjectCache::newFromId( 'hash' );
+
+ $localKey = $cache->makeKey( 'first', 'second', 'third' );
+ $globalKey = $cache->makeGlobalKey( 'first', 'second', 'third' );
+
+ $this->assertStringMatchesFormat(
+ '%Sfirst%Ssecond%Sthird%S',
+ $localKey,
+ 'Local key interpolates parameters'
+ );
+
+ $this->assertStringMatchesFormat(
+ 'global%Sfirst%Ssecond%Sthird%S',
+ $globalKey,
+ 'Global key interpolates parameters and contains global prefix'
+ );
+
+ $this->assertNotEquals(
+ $localKey,
+ $globalKey,
+ 'Local key and global key with same parameters should not be equal'
+ );
+ }
+
/**
* @covers BagOStuff::merge
* @covers BagOStuff::mergeViaLock