IGNITE-3948: Fixed a bug causing TTL manager to continue tracking of evicted entries. This closes #1101.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1938a17b Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1938a17b Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1938a17b Branch: refs/heads/ignite-ssl-hotfix Commit: 1938a17b01fac1e08c30011180bbcc3ed7374d83 Parents: f9a0676 Author: Andrey V. Mashenkov <andrey.mashen...@gmail.com> Authored: Tue Oct 11 14:50:18 2016 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Tue Oct 11 14:50:18 2016 +0300 ---------------------------------------------------------------------- .../processors/cache/GridCacheMapEntry.java | 13 +- .../GridCacheTtlManagerEvictionSelfTest.java | 160 +++++++++++++++++++ .../ignite/testsuites/IgniteCacheTestSuite.java | 2 + 3 files changed, 173 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/1938a17b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java index a9ac1e7..5996672 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java @@ -29,6 +29,7 @@ import javax.cache.Cache; import javax.cache.expiry.ExpiryPolicy; import javax.cache.processor.EntryProcessor; import javax.cache.processor.EntryProcessorResult; + import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; @@ -4196,8 +4197,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme } } } - else + else { + if (this.expireTimeUnlocked() > 0) + cctx.ttl().removeTrackedEntry(this); + clearIndex(prev); + } // Nullify value after swap. value(null); @@ -4250,8 +4255,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme } } } - else + else { + if (this.expireTimeUnlocked() > 0) + cctx.ttl().removeTrackedEntry(this); + clearIndex(prevVal); + } // Nullify value after swap. value(null); http://git-wip-us.apache.org/repos/asf/ignite/blob/1938a17b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTtlManagerEvictionSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTtlManagerEvictionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTtlManagerEvictionSelfTest.java new file mode 100644 index 0000000..4c7c1c0 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTtlManagerEvictionSelfTest.java @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.cache.CacheMemoryMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteKernal; +import org.apache.ignite.internal.util.lang.GridAbsPredicate; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import java.util.concurrent.TimeUnit; +import javax.cache.expiry.CreatedExpiryPolicy; +import javax.cache.expiry.Duration; + +/** + * TTL manager eviction self test. + */ +public class GridCacheTtlManagerEvictionSelfTest extends GridCommonAbstractTest { + /** */ + private static final int ENTRIES_TO_PUT = 10_100; + + /** */ + private static final int ENTRIES_LIMIT = 1_000; + + /** IP finder. */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** Cache mode. */ + private volatile CacheMode cacheMode; + + /** Cache memory mode. */ + private volatile CacheMemoryMode cacheMemoryMode; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); + + discoSpi.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(discoSpi); + + CacheConfiguration ccfg = new CacheConfiguration(); + + ccfg.setCacheMode(cacheMode); + ccfg.setMemoryMode(cacheMemoryMode); + ccfg.setEagerTtl(true); + ccfg.setSwapEnabled(false); + ccfg.setEvictionPolicy(new FifoEvictionPolicy(ENTRIES_LIMIT, 100)); + ccfg.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.HOURS, 12))); + + cfg.setCacheConfiguration(ccfg); + + return cfg; + } + + /** + * @throws Exception If failed. + */ + public void testLocalEviction() throws Exception { + checkEviction(CacheMode.LOCAL, CacheMemoryMode.ONHEAP_TIERED); + checkEviction(CacheMode.LOCAL, CacheMemoryMode.OFFHEAP_TIERED); + } + + /** + * @throws Exception If failed. + */ + public void testPartitionedEviction() throws Exception { + checkEviction(CacheMode.PARTITIONED, CacheMemoryMode.ONHEAP_TIERED); + checkEviction(CacheMode.PARTITIONED, CacheMemoryMode.OFFHEAP_TIERED); + } + + /** + * @throws Exception If failed. + */ + public void testReplicatedEviction() throws Exception { + checkEviction(CacheMode.REPLICATED, CacheMemoryMode.ONHEAP_TIERED); + checkEviction(CacheMode.REPLICATED, CacheMemoryMode.OFFHEAP_TIERED); + } + + /** + * @param mode Cache mode. + * @throws Exception If failed. + */ + @SuppressWarnings("ConstantConditions") + private void checkEviction(CacheMode mode, CacheMemoryMode memoryMode) throws Exception { + cacheMode = mode; + cacheMemoryMode = memoryMode; + + final IgniteKernal g = (IgniteKernal)startGrid(0); + + try { + final IgniteCache<Object, Object> cache = g.cache(null); + + final GridCacheContext<Object, Object> cctx = g.cachex(null).context(); + + for (int i = 1; i <= ENTRIES_TO_PUT; i++) { + String key = "Some test entry key#" + i; + String value = "Some test entry value#" + i; + + cache.put(key, value); + } + + GridTestUtils.waitForCondition(new GridAbsPredicate() { + @Override public boolean apply() { + return (cctx.isSwapOrOffheapEnabled()) ? + ENTRIES_TO_PUT == cctx.ttl().pendingSize() : + ENTRIES_LIMIT == cctx.ttl().pendingSize(); + } + }, 3_000); + + if (log.isTraceEnabled()) + cctx.ttl().printMemoryStats(); + + final String firstKey = "Some test entry key#0"; + final String lastKey = "Some test entry key#" + ENTRIES_TO_PUT; + + if (cctx.isSwapOrOffheapEnabled()) { + assertTrue("last key should NOT be evicted", cache.containsKey(lastKey)); + + assertEquals(ENTRIES_TO_PUT, cctx.ttl().pendingSize()); + } + else { + assertFalse("first key should be evicted", cache.containsKey(firstKey)); + + assertTrue("last key should NOT be evicted", cache.containsKey(lastKey)); + + assertEquals("Ttl Manager should NOT track evicted entries", ENTRIES_LIMIT, cctx.ttl().pendingSize()); + } + } + finally { + Ignition.stopAll(true); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/1938a17b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java index 5ad4cb8..d8231fc 100755 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java @@ -83,6 +83,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheStorePutxSelfTest; import org.apache.ignite.internal.processors.cache.GridCacheStoreValueBytesSelfTest; import org.apache.ignite.internal.processors.cache.GridCacheSwapPreloadSelfTest; import org.apache.ignite.internal.processors.cache.GridCacheSwapReloadSelfTest; +import org.apache.ignite.internal.processors.cache.GridCacheTtlManagerEvictionSelfTest; import org.apache.ignite.internal.processors.cache.GridCacheTtlManagerSelfTest; import org.apache.ignite.internal.processors.cache.GridCacheTxPartitionedLocalStoreSelfTest; import org.apache.ignite.internal.processors.cache.IgniteCacheAtomicInvokeTest; @@ -268,6 +269,7 @@ public class IgniteCacheTestSuite extends TestSuite { suite.addTestSuite(GridCacheAsyncOperationsLimitSelfTest.class); suite.addTestSuite(IgniteCacheManyAsyncOperationsTest.class); suite.addTestSuite(GridCacheTtlManagerSelfTest.class); + suite.addTestSuite(GridCacheTtlManagerEvictionSelfTest.class); suite.addTestSuite(GridCacheLifecycleAwareSelfTest.class); suite.addTestSuite(IgniteCacheAtomicStopBusySelfTest.class); suite.addTestSuite(IgniteCacheTransactionalStopBusySelfTest.class);