Commit f56c52f1 authored by Michael Stucki's avatar Michael Stucki
Browse files

[BUGFIX] Too many tags by identifier in CacheBackends

This patch is a backport of 3d930170.

Applies to Apc/Memcached backends.

After an array_merge the values aren't unique. This leads to duplicate
tags per identifier. This patch changes that and also moves the
findTagsByIdentifier call out of the foreach loop.

Resolves: #62513
Releases: 4.5
Change-Id: Ia4713eeb399a4770b2c23e5738e076a91afe2a64
Reviewed-on: http://review.typo3.org/33592


Reviewed-by: default avatarMarkus Klein <klein.t3@reelworx.at>
Reviewed-by: Michael Stucki's avatarMichael Stucki <michael.stucki@typo3.org>
Tested-by: Michael Stucki's avatarMichael Stucki <michael.stucki@typo3.org>
parent 528429b9
......@@ -330,20 +330,28 @@ class t3lib_cache_backend_ApcBackend extends t3lib_cache_backend_AbstractBackend
* @author Dmitry Dulepov <dmitry.@typo3.org>
*/
protected function addIdentifierToTags($entryIdentifier, array $tags) {
// Get identifier-to-tag index to look for updates
$existingTags = $this->findTagsByIdentifier($entryIdentifier);
$existingTagsUpdated = FALSE;
foreach ($tags as $tag) {
// Update tag-to-identifier index
$identifiers = $this->findIdentifiersByTag($tag);
if (array_search($entryIdentifier, $identifiers) === FALSE) {
if (!in_array($entryIdentifier, $identifiers, TRUE)) {
$identifiers[] = $entryIdentifier;
apc_store($this->getIdentifierPrefix() . 'tag_' . $tag, $identifiers);
}
// Update identifier-to-tag index
$existingTags = $this->findTagsByIdentifier($entryIdentifier);
if (array_search($entryIdentifier, $existingTags) === false) {
apc_store($this->getIdentifierPrefix() . 'ident_' . $entryIdentifier, array_merge($existingTags, $tags));
// Test if identifier-to-tag index needs update
if (!in_array($tag, $existingTags, TRUE)) {
$existingTags[] = $tag;
$existingTagsUpdated = TRUE;
}
}
// Update identifier-to-tag index if needed
if ($existingTagsUpdated) {
apc_store($this->getIdentifierPrefix() . 'ident_' . $entryIdentifier, $existingTags);
}
}
......
......@@ -438,22 +438,30 @@ class t3lib_cache_backend_MemcachedBackend extends t3lib_cache_backend_AbstractB
*/
protected function addIdentifierToTags($entryIdentifier, array $tags) {
if ($this->serverConnected) {
// Get identifier-to-tag index to look for updates
$existingTags = $this->findTagsByIdentifier($entryIdentifier);
$existingTagsUpdated = FALSE;
foreach ($tags as $tag) {
// Update tag-to-identifier index
// Update tag-to-identifier index
$identifiers = $this->findIdentifiersByTag($tag);
if (array_search($entryIdentifier, $identifiers) === false) {
if (!in_array($entryIdentifier, $identifiers, TRUE)) {
$identifiers[] = $entryIdentifier;
$this->memcache->set($this->identifierPrefix . 'tag_' . $tag,
$identifiers);
}
// Update identifier-to-tag index
$existingTags = $this->findTagsByIdentifier($entryIdentifier);
if (array_search($tag, $existingTags) === FALSE) {
$this->memcache->set($this->identifierPrefix . 'ident_' . $entryIdentifier,
array_merge($existingTags, $tags));
// Test if identifier-to-tag index needs update
if (!in_array($tag, $existingTags, TRUE)) {
$existingTags[] = $tag;
$existingTagsUpdated = TRUE;
}
}
// Update identifier-to-tag index if needed
if ($existingTagsUpdated) {
$this->memcache->set($this->identifierPrefix . 'ident_' . $entryIdentifier, $existingTags);
}
}
}
......
......@@ -286,6 +286,27 @@ class t3lib_cache_backend_ApcBackendTest extends tx_phpunit_testcase {
$this->assertEquals($backend->get($identifier), $data);
}
/**
* @test
*/
public function setTagsOnlyOnceToIdentifier() {
$identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
$tags = array('UnitTestTag%test', 'UnitTestTag%boring');
$backend = $this->setUpBackend();
$backend->addIdentifierToTags($identifier, $tags);
$this->assertSame(
$tags,
$backend->findTagsByIdentifier($identifier)
);
$backend->addIdentifierToTags($identifier, $tags);
$this->assertSame(
$tags,
$backend->findTagsByIdentifier($identifier)
);
}
/**
* Sets up the APC backend used for testing
*
......
......@@ -289,6 +289,28 @@ class t3lib_cache_backend_MemcachedBackendTest extends tx_phpunit_testcase {
$this->assertEquals($backend->get('tooLargeData'), $data);
}
/**
* @test
*/
public function setTagsOnlyOnceToIdentifier() {
$backendOptions = array('servers' => array('localhost:11211'));
$identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
$tags = array('UnitTestTag%test', 'UnitTestTag%boring');
$backend = $this->setUpBackend($backendOptions, TRUE);
$backend->addIdentifierToTags($identifier, $tags);
$this->assertEquals(
$tags,
$backend->findTagsByIdentifier($identifier)
);
$backend->addIdentifierToTags($identifier, $tags);
$this->assertEquals(
$tags,
$backend->findTagsByIdentifier($identifier)
);
}
/**
* Sets up the memcached backend used for testing
*
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment