[BUGFIX] Too many tags by identifier in CacheBackends 92/33592/2
authorMichael Stucki <michael.stucki@typo3.org>
Fri, 24 Oct 2014 09:38:52 +0000 (11:38 +0200)
committerMichael Stucki <michael.stucki@typo3.org>
Fri, 31 Oct 2014 08:10:31 +0000 (09:10 +0100)
This patch is a backport of 3d93017022a8ef03842d75f2d7bd3912365c95be.

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: Markus Klein <klein.t3@reelworx.at>
Reviewed-by: Michael Stucki <michael.stucki@typo3.org>
Tested-by: Michael Stucki <michael.stucki@typo3.org>
t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php
t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php
tests/t3lib/cache/backend/t3lib_cache_backend_apcbackendTest.php
tests/t3lib/cache/backend/t3lib_cache_backend_memcachedbackendTest.php

index c042022..7bf64f4 100644 (file)
@@ -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);
                }
        }
 
index 790a1b0..644a18a 100644 (file)
@@ -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);
+                       }
                }
        }
 
index b3d0963..de022e0 100644 (file)
@@ -287,6 +287,27 @@ class t3lib_cache_backend_ApcBackendTest extends tx_phpunit_testcase {
        }
 
        /**
+        * @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
         *
         * @param array $backendOptions Options for the APC backend
index 150c2f5..39f52c4 100644 (file)
@@ -290,6 +290,28 @@ class t3lib_cache_backend_MemcachedBackendTest extends tx_phpunit_testcase {
        }
 
        /**
+        * @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
         *
         * @param       array   $backendOptions Options for the memcache backend