diff --git a/core/core.services.yml b/core/core.services.yml index 9e5916c..46517e7 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -9,6 +9,7 @@ services: arguments: ['@database', '@cache_tag_factory'] cache.backend.memory: class: Drupal\Core\Cache\MemoryBackendFactory + arguments: ['@cache_tag_factory'] cache.bootstrap: class: Drupal\Core\Cache\CacheBackendInterface tags: @@ -76,6 +77,12 @@ services: arguments: ['@database'] tags: - { name: cache.tag } + - { name: persist } + cache.tag.memory: + class: Drupal\Core\Cache\MemoryTag + tags: + - { name: cache.tag } + - { name: persist } config.cachedstorage.storage: class: Drupal\Core\Config\FileStorage factory_class: Drupal\Core\Config\FileStorageFactory diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 0b25e59..181606a 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -383,6 +383,8 @@ function install_begin_request(&$install_state) { ->addArgument(new Reference('event_dispatcher')) ->addArgument(new Reference('config.typed')); + $container->register('cache.tag.memory', 'Drupal\Core\Cache\MemoryTag'); + // Register the 'language_manager' service. $container->register('language_manager', 'Drupal\Core\Language\LanguageManager') ->addArgument(new Reference('language.default')); @@ -393,6 +395,7 @@ function install_begin_request(&$install_state) { foreach (array('bootstrap', 'config', 'cache', 'menu', 'page', 'path') as $bin) { $container ->register("cache.$bin", 'Drupal\Core\Cache\MemoryBackend') + ->addArgument(new Reference('cache.tag.memory')) ->addArgument($bin); } diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 0046918..58af9e9 100644 --- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -186,27 +186,6 @@ public function delete($cid); public function deleteMultiple(array $cids); /** - * Deletes items with any of the specified tags. - * - * If the cache items are being deleted because they are no longer "fresh", - * you may consider using invalidateTags() instead. This allows callers to - * retrieve the invalid items by calling get() with $allow_invalid set to TRUE. - * In some cases an invalid item may be acceptable rather than having to - * rebuild the cache. - * - * @param array $tags - * Associative array of tags, in the same format that is passed to - * CacheBackendInterface::set(). - * - * @see \Drupal\Core\Cache\CacheBackendInterface::set() - * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags() - * @see \Drupal\Core\Cache\CacheBackendInterface::delete() - * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple() - * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll() - */ - public function deleteTags(array $tags); - - /** * Deletes all cache items in a bin. * * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll() @@ -249,21 +228,6 @@ public function invalidate($cid); public function invalidateMultiple(array $cids); /** - * Marks cache items with any of the specified tags as invalid. - * - * @param array $tags - * Associative array of tags, in the same format that is passed to - * CacheBackendInterface::set(). - * - * @see \Drupal\Core\Cache\CacheBackendInterface::set() - * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags() - * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate() - * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple() - * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll() - */ - public function invalidateTags(array $tags); - - /** * Marks all cache items as invalid. * * Invalid items may be returned in later calls to get(), if the $allow_invalid diff --git a/core/lib/Drupal/Core/Cache/CacheTagBase.php b/core/lib/Drupal/Core/Cache/CacheTagBase.php index 006f78d..bfcc211 100644 --- a/core/lib/Drupal/Core/Cache/CacheTagBase.php +++ b/core/lib/Drupal/Core/Cache/CacheTagBase.php @@ -13,16 +13,6 @@ abstract class CacheTagBase implements CacheTagInterface { /** - * {@inheritdoc} - */ - abstract public function invalidateTags(array $tags); - - /** - * {@inheritdoc} - */ - abstract public function deleteTags(array $tags); - - /** * 'Flattens' a tags array into an array of strings. * * @param array $tags diff --git a/core/lib/Drupal/Core/Cache/CacheTagInterface.php b/core/lib/Drupal/Core/Cache/CacheTagInterface.php index 318e42e..fd09b70 100644 --- a/core/lib/Drupal/Core/Cache/CacheTagInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheTagInterface.php @@ -34,4 +34,8 @@ public function deleteTags(array $tags); */ public function invalidateTags(array $tags); + public function checksumTags(array $tags); + + public function prepareGet(&$item); + } diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index d11be9d..d818f67 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -119,19 +119,17 @@ protected function prepareItem($cache, $allow_invalid) { $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array(); - $checksum = $this->cacheTag->checksumTags($cache->tags); + // Check expire time. + $cache->valid = $time_valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME; - // Check if deleteTags() has been called with any of the entry's tags. - if ($cache->checksum_deletions != $checksum['deletions']) { + $this->cacheTag->prepareGet($cache); + if ($cache->deleted) { + $this->delete($cache->cid); return FALSE; } - // Check expire time. - $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME; - - // Check if invalidateTags() has been called with any of the entry's tags. - if ($cache->checksum_invalidations != $checksum['invalidations']) { - $cache->valid = FALSE; + if ($time_valid && !$cache->valid) { + $this->invalidate($cache->cid); } if (!$allow_invalid && !$cache->valid) { @@ -173,8 +171,8 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array * Actually set the cache. */ protected function doSet($cid, $data, $expire, $tags) { + $checksum = $this->cacheTag->checksumTags($tags); $flat_tags = $this->cacheTag->flattenTags($tags); - $checksum = $this->cacheTag->checksumTags($flat_tags); $fields = array( 'serialized' => 0, 'created' => REQUEST_TIME, @@ -229,13 +227,6 @@ public function deleteMultiple(array $cids) { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). - */ - public function deleteTags(array $tags) { - $this->cacheTag->deleteTags($tags); - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). */ public function deleteAll() { @@ -279,13 +270,6 @@ public function invalidateMultiple(array $cids) { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). - */ - public function invalidateTags(array $tags) { - $this->cacheTag->invalidateTags($tags); - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll(). */ public function invalidateAll() { diff --git a/core/lib/Drupal/Core/Cache/DatabaseTag.php b/core/lib/Drupal/Core/Cache/DatabaseTag.php index 2f3fef3..10f6a9e 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseTag.php +++ b/core/lib/Drupal/Core/Cache/DatabaseTag.php @@ -80,14 +80,15 @@ public function deleteTags(array $tags) { * Returns the sum total of validations for a given set of tags. * * @param array $tags - * Array of flat tags. + * Array of tags. * * @return int * Sum of all invalidations. * * @see Drupal\Core\Cache\DatabaseBackend::flattenTags() */ - public function checksumTags($flat_tags) { + public function checksumTags(array $tags) { + $flat_tags = $this->flattenTags($tags); $checksum = array( 'invalidations' => 0, 'deletions' => 0, @@ -111,6 +112,21 @@ public function checksumTags($flat_tags) { } /** + * {@inheritdoc} + */ + public function prepareGet(&$item) { + $checksum = $this->checksumTags($item->tags); + + // Check if deleteTags() has been called with any of the entry's tags. + $item->deleted = $item->checksum_deletions != $checksum['deletions']; + + // Check if invalidateTags() has been called with any of the entry's tags. + if ($item->checksum_invalidations != $checksum['invalidations']) { + $item->valid = FALSE; + } + } + + /** * Act on an exception when cache might be stale. * * If the cache_tags table does not yet exist, that's fine but if the table diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php index a7faca6..261712b 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackend.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php @@ -24,12 +24,20 @@ class MemoryBackend implements CacheBackendInterface { protected $cache = array(); /** + * The cache tag service. + * + * @var \Drupal\Core\Cache\CacheTagInterface + */ + protected $cacheTag; + + /** * Constructs a MemoryBackend object. * * @param string $bin * The cache bin for which the object is created. */ - public function __construct($bin) { + public function __construct(CacheTagInterface $cache_tag, $bin) { + $this->cacheTag = $cache_tag; } /** @@ -83,7 +91,17 @@ protected function prepareItem($cache, $allow_invalid) { } // Check expire time. - $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME; + $cache->valid = $time_valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME; + + $this->cacheTag->prepareGet($item); + if ($cache->deleted) { + $this->delete($cache->cid); + return FALSE; + } + + if ($time_valid && !$cache->valid) { + $this->invalidate($cache->cid); + } if (!$allow_invalid && !$cache->valid) { return FALSE; @@ -96,12 +114,15 @@ protected function prepareItem($cache, $allow_invalid) { * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) { + $checksum = $this->cacheTag->checksumTags($tags); $this->cache[$cid] = (object) array( 'cid' => $cid, 'data' => $data, 'created' => REQUEST_TIME, 'expire' => $expire, 'tags' => $this->flattenTags($tags), + 'checksum_invalidations' => $checksum['invalidations'], + 'checksum_deletions' => $checksum['deletions'], ); } @@ -120,18 +141,6 @@ public function deleteMultiple(array $cids) { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). - */ - public function deleteTags(array $tags) { - $flat_tags = $this->flattenTags($tags); - foreach ($this->cache as $cid => $item) { - if (array_intersect($flat_tags, $item->tags)) { - unset($this->cache[$cid]); - } - } - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). */ public function deleteAll() { @@ -157,18 +166,6 @@ public function invalidateMultiple(array $cids) { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). - */ - public function invalidateTags(array $tags) { - $flat_tags = $this->flattenTags($tags); - foreach ($this->cache as $cid => $item) { - if (array_intersect($flat_tags, $item->tags)) { - $this->cache[$cid]->expire = REQUEST_TIME - 1; - } - } - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll(). */ public function invalidateAll() { diff --git a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php index c9e288d..917110d 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php @@ -10,10 +10,26 @@ class MemoryBackendFactory implements CacheFactoryInterface { /** + * The cache tag factory service. + * + * @var \Drupal\Core\Cache\CacheTagFactory + */ + protected $cacheTagFactory; + + /** + * Constructs the DatabaseBackendFactory object. + * + * @param \Drupal\Core\Database\Connection $connection + */ + function __construct(CacheTagFactory $cache_tag_factory) { + $this->cacheTagFactory = $cache_tag_factory; + } + + /** * {@inheritdoc} */ function get($bin) { - return new MemoryBackend($bin); + return new MemoryBackend($this->cacheTagFactory->get(), $bin); } } diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php index 4776214..bcf8c06 100644 --- a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php +++ b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php @@ -36,7 +36,8 @@ public function register(ContainerBuilder $container) { $container->register('module_handler', 'Drupal\Core\Extension\UpdateModuleHandler') ->addArgument('%container.modules%'); $container - ->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory'); + ->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory') + ->addArgument(new Reference('cache_tag_factory')); $container ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic'); diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index df4731b..a3cf703 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -13,6 +13,7 @@ use Drupal\field\FieldException; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInstanceInterface; +use Drupal\field\Field as FieldInfo; /** * Defines the Field instance entity. @@ -249,7 +250,7 @@ public function __construct(array $values, $entity_type = 'field_instance') { // Field instances configuration is stored with a 'field_uuid' property // unambiguously identifying the field. if (isset($values['field_uuid'])) { - $field = field_info_field_by_id($values['field_uuid']); + $field = FieldInfo::fieldInfo()->getFieldById($values['field_uuid']); if (!$field) { throw new FieldException(format_string('Attempt to create an instance of unknown field @uuid', array('@uuid' => $values['field_uuid']))); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainUnitTest.php index 3323b1a..c2207d5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainUnitTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\BackendChain; use Drupal\Core\Cache\MemoryBackend; +use Drupal\Core\Cache\MemoryTag; /** * Tests BackendChain using GenericCacheBackendUnitTestBase. @@ -27,10 +28,11 @@ protected function createCacheBackend($bin) { $chain = new BackendChain($bin); // We need to create some various backends in the chain. + $cache_tag = new MemoryTag(); $chain - ->appendBackend(new MemoryBackend('foo')) - ->prependBackend(new MemoryBackend('bar')) - ->appendBackend(new MemoryBackend('baz')); + ->appendBackend(new MemoryBackend($cache_tag, 'foo')) + ->prependBackend(new MemoryBackend($cache_tag, 'bar')) + ->appendBackend(new MemoryBackend($cache_tag, 'baz')); return $chain; } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/MemoryBackendUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/MemoryBackendUnitTest.php index d3a29e3..9ae5488 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/MemoryBackendUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/MemoryBackendUnitTest.php @@ -8,6 +8,7 @@ namespace Drupal\system\Tests\Cache; use Drupal\Core\Cache\MemoryBackend; +use Drupal\Core\Cache\MemoryTag; /** * Tests MemoryBackend using GenericCacheBackendUnitTestBase. @@ -29,6 +30,6 @@ public static function getInfo() { * A new MemoryBackend object. */ protected function createCacheBackend($bin) { - return new MemoryBackend($bin); + return new MemoryBackend(new MemoryTag(), $bin); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php index b305d28..a701027 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\MemoryBackendFactory; use Drupal\Core\Cache\MemoryBackend; +use Drupal\Core\Cache\MemoryTag; use Drupal\system\Tests\Plugin\Discovery\DiscoveryTestBase; use Drupal\Component\Plugin\Discovery\StaticDiscovery; use Drupal\Core\Plugin\Discovery\CacheDecorator; @@ -47,7 +48,7 @@ public function setUp() { // Use a non-db cache backend, so that we can use DiscoveryTestBase (which // extends UnitTestBase). // @todo switch to injecting the MemoryBackend http://drupal.org/node/1903346 - \Drupal::getContainer()->set("cache.$this->cacheBin", new MemoryBackend($this->cacheBin)); + \Drupal::getContainer()->set("cache.$this->cacheBin", new MemoryBackend(new MemoryTag(), $this->cacheBin)); // Create discovery objects to test. $this->emptyDiscovery = new StaticDiscovery(); diff --git a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php index 75c0a97..71a5642 100644 --- a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Cache\BackendChain; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\MemoryBackend; +use Drupal\Core\Cache\MemoryTag; use Drupal\Tests\UnitTestCase; /** @@ -59,9 +60,10 @@ public function setUp() { parent::setUp(); // Set up three memory backends to be used in the chain. - $this->firstBackend = new MemoryBackend('foo'); - $this->secondBackend = new MemoryBackend('bar'); - $this->thirdBackend = new MemoryBackend('baz'); + $cache_tag = new MemoryTag(); + $this->firstBackend = new MemoryBackend($cache_tag, 'foo'); + $this->secondBackend = new MemoryBackend($cache_tag, 'bar'); + $this->thirdBackend = new MemoryBackend($cache_tag, 'baz'); // Set an initial fixed dataset for all testing. The next three data // collections will test two edge cases (last backend has the data, and diff --git a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php index 6c60af4..3ad73a1 100644 --- a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\Core\Config; +use Drupal\Core\Cache\MemoryTag; use Drupal\Tests\UnitTestCase; use Drupal\Core\Config\CachedStorage; use Drupal\Core\Cache\MemoryBackend; @@ -51,7 +52,7 @@ public function testListAllPrimedPersistentCache() { $storage->expects($this->never())->method('listAll'); $response = array("$prefix." . $this->randomName(), "$prefix." . $this->randomName()); - $cache = new MemoryBackend(__FUNCTION__); + $cache = new MemoryBackend(new MemoryTag(), __FUNCTION__); $cache->set('find:' . $prefix, $response); $cachedStorage = new CachedStorage($storage, $cache); $this->assertEquals($response, $cachedStorage->listAll($prefix)); @@ -75,7 +76,7 @@ public function testGetMultipleOnPrimedCache() { ); $storage = $this->getMock('Drupal\Core\Config\StorageInterface'); $storage->expects($this->never())->method('readMultiple'); - $cache = new MemoryBackend(__FUNCTION__); + $cache = new MemoryBackend(new MemoryTag(), __FUNCTION__); foreach ($configCacheValues as $key => $value) { $cache->set($key, $value); } @@ -102,7 +103,7 @@ public function testGetMultipleOnPartiallyPrimedCache() { 'foo' => 'bar', ), ); - $cache = new MemoryBackend(__FUNCTION__); + $cache = new MemoryBackend(new MemoryTag(), __FUNCTION__); foreach ($configCacheValues as $key => $value) { $cache->set($key, $value); }