You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/04/10 16:34:19 UTC
[1/2] ignite git commit: IGNITE-4534 - Added offheap evictions
Repository: ignite
Updated Branches:
refs/heads/ignite-3477-master baa3835ee -> ff5b3e168
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
index 190349a..9546890 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
@@ -18,9 +18,11 @@
package org.apache.ignite.internal.processors.cache.database.tree.io;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.PageMemory;
@@ -254,6 +256,29 @@ public class DataPageIO extends PageIO {
/**
* @param pageAddr Page address.
+ * @param c Closure.
+ * @param <T> Closure return type.
+ * @return Collection of closure results for all items in page.
+ * @throws IgniteCheckedException In case of error in closure body.
+ */
+ public <T> List<T> forAllItems(long pageAddr, CC<T> c) throws IgniteCheckedException {
+ long pageId = getPageId(pageAddr);
+
+ int cnt = getDirectCount(pageAddr);
+
+ List<T> res = new ArrayList<>(cnt);
+
+ for (int i = 0; i < cnt; i++) {
+ long link = PageIdUtils.link(pageId, i);
+
+ res.add(c.apply(link));
+ }
+
+ return res;
+ }
+
+ /**
+ * @param pageAddr Page address.
* @param cnt Indirect count.
*/
private void setIndirectCount(long pageAddr, int cnt) {
@@ -1007,7 +1032,8 @@ public class DataPageIO extends PageIO {
final int keySize = row.key().valueBytesLength(null);
final int valSize = row.value().valueBytesLength(null);
- int written = writeFragment(row, buf, rowOff, payloadSize, EntryPart.KEY, keySize, valSize);
+ int written = writeFragment(row, buf, rowOff, payloadSize, EntryPart.CACHE_ID, keySize, valSize);
+ written += writeFragment(row, buf, rowOff + written, payloadSize - written, EntryPart.KEY, keySize, valSize);
written += writeFragment(row, buf, rowOff + written, payloadSize - written, EntryPart.EXPIRE_TIME, keySize, valSize);
written += writeFragment(row, buf, rowOff + written, payloadSize - written, EntryPart.VALUE, keySize, valSize);
written += writeFragment(row, buf, rowOff + written, payloadSize - written, EntryPart.VERSION, keySize, valSize);
@@ -1039,28 +1065,36 @@ public class DataPageIO extends PageIO {
final int prevLen;
final int curLen;
+ int cacheIdSize = row.cacheId() == 0 ? 0 : 4;
+
switch (type) {
- case KEY:
+ case CACHE_ID:
prevLen = 0;
- curLen = keySize;
+ curLen = cacheIdSize;
+
+ break;
+
+ case KEY:
+ prevLen = cacheIdSize;
+ curLen = cacheIdSize + keySize;
break;
case EXPIRE_TIME:
- prevLen = keySize;
- curLen = keySize + 8;
+ prevLen = cacheIdSize + keySize;
+ curLen = cacheIdSize + keySize + 8;
break;
case VALUE:
- prevLen = keySize + 8;
- curLen = keySize + valSize + 8;
+ prevLen = cacheIdSize + keySize + 8;
+ curLen = cacheIdSize + keySize + valSize + 8;
break;
case VERSION:
- prevLen = keySize + valSize + 8;
- curLen = keySize + valSize + CacheVersionIO.size(row.version(), false) + 8;
+ prevLen = cacheIdSize + keySize + valSize + 8;
+ curLen = cacheIdSize + keySize + valSize + CacheVersionIO.size(row.version(), false) + 8;
break;
@@ -1075,6 +1109,8 @@ public class DataPageIO extends PageIO {
if (type == EntryPart.EXPIRE_TIME)
writeExpireTimeFragment(buf, row.expireTime(), rowOff, len, prevLen);
+ else if (type == EntryPart.CACHE_ID)
+ writeCacheIdFragment(buf, row.cacheId(), rowOff, len, prevLen);
else if (type != EntryPart.VERSION) {
// Write key or value.
final CacheObject co = type == EntryPart.KEY ? row.key() : row.value();
@@ -1139,6 +1175,32 @@ public class DataPageIO extends PageIO {
}
/**
+ * @param buf Buffer.
+ * @param cacheId Cache ID.
+ * @param rowOff Row offset.
+ * @param len Length.
+ * @param prevLen Prev length.
+ */
+ private void writeCacheIdFragment(ByteBuffer buf, int cacheId, int rowOff, int len, int prevLen) {
+ if (cacheId == 0)
+ return;
+
+ int size = 4;
+
+ if (size <= len)
+ buf.putInt(cacheId);
+ else {
+ ByteBuffer cacheIdBuf = ByteBuffer.allocate(size);
+
+ cacheIdBuf.order(buf.order());
+
+ cacheIdBuf.putInt(cacheId);
+
+ buf.put(cacheIdBuf.array(), rowOff - prevLen, len);
+ }
+ }
+
+ /**
*
*/
private enum EntryPart {
@@ -1152,7 +1214,10 @@ public class DataPageIO extends PageIO {
VERSION,
/** */
- EXPIRE_TIME
+ EXPIRE_TIME,
+
+ /** */
+ CACHE_ID
}
/**
@@ -1326,14 +1391,21 @@ public class DataPageIO extends PageIO {
) throws IgniteCheckedException {
long addr = pageAddr + dataOff;
+ int cacheIdSize = row.cacheId() != 0 ? 4 : 0;
+
if (newRow) {
PageUtils.putShort(addr, 0, (short)payloadSize);
addr += 2;
+ if (cacheIdSize != 0)
+ PageUtils.putInt(addr, 0, row.cacheId());
+
+ addr += cacheIdSize;
+
addr += row.key().putValue(addr);
}
else
- addr += (2 + row.key().valueBytesLength(null));
+ addr += (2 + cacheIdSize + row.key().valueBytesLength(null));
addr += row.value().putValue(addr);
@@ -1358,4 +1430,20 @@ public class DataPageIO extends PageIO {
PageUtils.putBytes(pageAddr, dataOff, payload);
}
+
+ /**
+ * Defines closure interface for applying computations to data page items.
+ *
+ * @param <T> Closure return type.
+ */
+ public interface CC<T> {
+ /**
+ * Closure body.
+ *
+ * @param link Link to item.
+ * @return Closure return value.
+ * @throws IgniteCheckedException In case of error in closure body.
+ */
+ public T apply(long link) throws IgniteCheckedException;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index d652767..5a8dfa0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -1795,6 +1795,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
// Do not check topology version if topology was locked on near node by
// external transaction or explicit lock.
if (req.topologyLocked() || !needRemap(req.topologyVersion(), top.topologyVersion())) {
+ ctx.shared().database().ensureFreeSpace(ctx.memoryPolicy());
+
locked = lockEntries(req, req.topologyVersion());
boolean hasNear = ctx.discovery().cacheNearNode(node, name());
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index c257154..64f6187 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -2673,6 +2673,8 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements AutoClosea
GridCacheEntryEx entry = cacheCtx.cache().entryEx(key, topVer);
try {
+ cacheCtx.shared().database().ensureFreeSpace(cacheCtx.memoryPolicy());
+
EntryGetResult verVal = entry.versionedValue(cacheVal,
ver,
null,
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
index 767ce84..e5cd469 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
@@ -334,7 +334,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
CacheObject val = cached.peek(null);
- if (val == null && cached.evictInternal(xidVer, null)) {
+ if (val == null && cached.evictInternal(xidVer, null, false)) {
evicted.add(entry.txKey());
return false;
@@ -395,7 +395,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
CacheObject peek = cached.peek(null);
- if (peek == null && cached.evictInternal(xidVer, null)) {
+ if (peek == null && cached.evictInternal(xidVer, null, false)) {
cached.context().cache().removeIfObsolete(key.key());
evicted.add(key);
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
index da92692..b8c0e36 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
@@ -791,6 +791,8 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
CacheEntryPredicate[] filters = CU.filterArray(filter);
+ ctx.shared().database().ensureFreeSpace(ctx.memoryPolicy());
+
if (writeThrough && keys.size() > 1) {
return updateWithBatch(op,
keys,
@@ -995,8 +997,8 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
null,
null,
/*read-through*/true,
- /**update-metrics*/true,
- /**event*/true,
+ /*update-metrics*/true,
+ /*event*/true,
subjId,
entryProcessor,
taskName,
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index 4ec89e1..9beb296 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -180,13 +180,6 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
public CacheObject toCacheObject(CacheObjectContext ctx, ByteBuffer buf);
/**
- * @param ctx Cache context.
- * @param buf Buffer to read from.
- * @return Cache object.
- */
- public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, ByteBuffer buf) throws IgniteCheckedException;
-
- /**
* @param ctx Cache object context.
* @param buf Buffer.
* @param incompleteObj Incomplete cache object or {@code null} if it's a first read.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index 4726d86..a8595fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -188,22 +188,6 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
}
/** {@inheritDoc} */
- @Override public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, ByteBuffer buf) throws IgniteCheckedException {
- int len = buf.getInt();
-
- if (len == 0)
- return null;
-
- byte type = buf.get();
-
- byte[] data = new byte[len];
-
- buf.get(data);
-
- return toKeyCacheObject(ctx, type, data);
- }
-
- /** {@inheritDoc} */
@Override public IncompleteCacheObject toCacheObject(
final CacheObjectContext ctx,
final ByteBuffer buf,
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
index 46dec44..adbd6f1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
@@ -369,7 +369,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
/** @inheritDoc */
@Override public boolean evictInternal(GridCacheVersion obsoleteVer,
- @Nullable CacheEntryPredicate[] filter) {
+ @Nullable CacheEntryPredicate[] filter, boolean evictOffheap) {
assert false;
return false;
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtEntrySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtEntrySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtEntrySelfTest.java
index bc7fffe..58c3841 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtEntrySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtEntrySelfTest.java
@@ -280,7 +280,7 @@ public class GridCacheDhtEntrySelfTest extends GridCommonAbstractTest {
assert e0.readers().contains(other.id());
assert e1 == null || e1.readers().isEmpty();
- assert !e0.evictInternal(dht0.context().versions().next(), null);
+ assert !e0.evictInternal(dht0.context().versions().next(), null, false);
assertEquals(1, near0.localSize(CachePeekMode.ALL));
assertEquals(1, dht0.localSize(null));
@@ -288,7 +288,7 @@ public class GridCacheDhtEntrySelfTest extends GridCommonAbstractTest {
assertEquals(1, near1.localSize(CachePeekMode.ALL));
assertEquals(0, dht1.localSize(null));
- assert !e0.evictInternal(dht0.context().versions().next(), null);
+ assert !e0.evictInternal(dht0.context().versions().next(), null, false);
assertEquals(1, near0.localSize(CachePeekMode.ALL));
assertEquals(1, dht0.localSize(null));
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionAbstractTest.java
new file mode 100644
index 0000000..bf05146
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionAbstractTest.java
@@ -0,0 +1,124 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+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.junits.common.GridCommonAbstractTest;
+
+/**
+ *
+ */
+public class PageEvictionAbstractTest extends GridCommonAbstractTest {
+ /** */
+ protected static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** Offheap size for memory policy. */
+ private static final int SIZE = 256 * 1024 * 1024;
+
+ /** Page size. */
+ static final int PAGE_SIZE = 2048;
+
+ /** Number of entries. */
+ static final int ENTRIES = 400_000;
+
+ /** Empty pages pool size. */
+ private static final int EMPTY_PAGES_POOL_SIZE = 100;
+
+ /** Eviction threshold. */
+ private static final double EVICTION_THRESHOLD = 0.9;
+
+ /** Default policy name. */
+ private static final String DEFAULT_POLICY_NAME = "dfltPlc";
+
+ /**
+ * @param mode Eviction mode.
+ * @param configuration Configuration.
+ * @return Configuration with given eviction mode set.
+ */
+ static IgniteConfiguration setEvictionMode(DataPageEvictionMode mode, IgniteConfiguration configuration) {
+ MemoryPolicyConfiguration[] policies = configuration.getMemoryConfiguration().getMemoryPolicies();
+
+ for (MemoryPolicyConfiguration plcCfg : policies)
+ plcCfg.setPageEvictionMode(mode);
+
+ return configuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+ MemoryConfiguration dbCfg = new MemoryConfiguration();
+
+ MemoryPolicyConfiguration plc = new MemoryPolicyConfiguration();
+
+ plc.setSize(SIZE);
+ plc.setEmptyPagesPoolSize(EMPTY_PAGES_POOL_SIZE);
+ plc.setEvictionThreshold(EVICTION_THRESHOLD);
+ plc.setName(DEFAULT_POLICY_NAME);
+
+ dbCfg.setMemoryPolicies(plc);
+ dbCfg.setPageSize(PAGE_SIZE);
+ dbCfg.setDefaultMemoryPolicyName(DEFAULT_POLICY_NAME);
+
+ cfg.setMemoryConfiguration(dbCfg);
+
+ return cfg;
+ }
+
+ /**
+ * @param name Name.
+ * @param cacheMode Cache mode.
+ * @param atomicityMode Atomicity mode.
+ * @param writeSynchronizationMode Write synchronization mode.
+ * @param memoryPlcName Memory policy name.
+ * @return Cache configuration.
+ */
+ protected static CacheConfiguration<Object, Object> cacheConfig(
+ String name,
+ String memoryPlcName,
+ CacheMode cacheMode,
+ CacheAtomicityMode atomicityMode,
+ CacheWriteSynchronizationMode writeSynchronizationMode
+ ) {
+ CacheConfiguration<Object, Object> cacheConfiguration = new CacheConfiguration<>()
+ .setName(name)
+ .setAffinity(new RendezvousAffinityFunction(false, 32))
+ .setCacheMode(cacheMode)
+ .setAtomicityMode(atomicityMode)
+ .setMemoryPolicyName(memoryPlcName)
+ .setWriteSynchronizationMode(writeSynchronizationMode);
+
+ if (cacheMode == CacheMode.PARTITIONED)
+ cacheConfiguration.setBackups(1);
+
+ return cacheConfiguration;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMultinodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMultinodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMultinodeTest.java
new file mode 100644
index 0000000..2302de1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMultinodeTest.java
@@ -0,0 +1,110 @@
+/*
+* 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.eviction.paged;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+
+/**
+ *
+ */
+public abstract class PageEvictionMultinodeTest extends PageEvictionAbstractTest {
+ /** Cache modes. */
+ private static final CacheMode[] CACHE_MODES = {CacheMode.PARTITIONED, CacheMode.REPLICATED};
+
+ /** Atomicity modes. */
+ private static final CacheAtomicityMode[] ATOMICITY_MODES = {
+ CacheAtomicityMode.ATOMIC, CacheAtomicityMode.TRANSACTIONAL};
+
+ /** Write modes. */
+ private static final CacheWriteSynchronizationMode[] WRITE_MODES = {CacheWriteSynchronizationMode.PRIMARY_SYNC,
+ CacheWriteSynchronizationMode.FULL_SYNC, CacheWriteSynchronizationMode.FULL_ASYNC};
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ startGridsMultiThreaded(4, false);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return 10 * 60 * 1000;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testPageEviction() throws Exception {
+ for (int i = 0; i < CACHE_MODES.length; i++) {
+ for (int j = 0; j < ATOMICITY_MODES.length; j++) {
+ for (int k = 0; k < WRITE_MODES.length; k++) {
+ if (i + j + Math.min(k, 1) <= 1) {
+ CacheConfiguration<Object, Object> cfg = cacheConfig(
+ "evict" + i + j + k, null, CACHE_MODES[i], ATOMICITY_MODES[j], WRITE_MODES[k]);
+
+ createCacheAndTestEvcition(cfg);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param cfg Config.
+ * @throws Exception If failed.
+ */
+ private void createCacheAndTestEvcition(CacheConfiguration<Object, Object> cfg) throws Exception {
+ IgniteCache<Object, Object> cache = ignite(0).getOrCreateCache(cfg);
+
+ for (int i = 1; i <= ENTRIES; i++) {
+ ThreadLocalRandom r = ThreadLocalRandom.current();
+
+ if (r.nextInt() % 5 == 0)
+ cache.put(i, new TestObject(PAGE_SIZE / 4 - 50 + r.nextInt(5000))); // Fragmented object.
+ else
+ cache.put(i, new TestObject(r.nextInt(PAGE_SIZE / 4 - 50))); // Fits in one page.
+
+ if (r.nextInt() % 7 == 0)
+ cache.get(r.nextInt(i)); // Touch.
+ else if (r.nextInt() % 11 == 0)
+ cache.remove(r.nextInt(i)); // Remove.
+ else if (r.nextInt() % 13 == 0)
+ cache.put(r.nextInt(i), new TestObject(r.nextInt(PAGE_SIZE / 2))); // Update.
+
+ if (i % (ENTRIES / 10) == 0)
+ System.out.println(">>> Entries put: " + i);
+ }
+
+ int resultingSize = cache.size(CachePeekMode.PRIMARY);
+
+ System.out.println(">>> Resulting size: " + resultingSize);
+
+ // More than half of entries evicted, no OutOfMemory occurred, success.
+ assertTrue(resultingSize < ENTRIES / 2);
+
+ ignite(0).destroyCache(cfg.getName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
new file mode 100644
index 0000000..c8cd7c9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
@@ -0,0 +1,140 @@
+/*
+* 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.eviction.paged;
+
+import java.util.concurrent.ThreadLocalRandom;
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import javax.cache.integration.CacheLoaderException;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class PageEvictionReadThroughTest extends PageEvictionAbstractTest {
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(DataPageEvictionMode.RANDOM_LRU, super.getConfiguration(gridName));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEvictionWithReadThroughAtomicReplicated() throws Exception {
+ testEvictionWithReadThrough(CacheAtomicityMode.ATOMIC, CacheMode.REPLICATED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEvictionWithReadThroughAtomicLocal() throws Exception {
+ testEvictionWithReadThrough(CacheAtomicityMode.ATOMIC, CacheMode.LOCAL);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEvictionWithReadThroughTxReplicated() throws Exception {
+ testEvictionWithReadThrough(CacheAtomicityMode.TRANSACTIONAL, CacheMode.REPLICATED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEvictionWithReadThroughTxLocal() throws Exception {
+ testEvictionWithReadThrough(CacheAtomicityMode.TRANSACTIONAL, CacheMode.LOCAL);
+ }
+
+ /**
+ * @param atomicityMode Atomicity mode.
+ * @param cacheMode Cache mode.
+ * @throws Exception If failed.
+ */
+ private void testEvictionWithReadThrough(CacheAtomicityMode atomicityMode, CacheMode cacheMode) throws Exception {
+ startGridsMultiThreaded(4);
+
+ CacheConfiguration<Object, Object> cfg = cacheConfig("evict-rebalance", null, cacheMode, atomicityMode,
+ CacheWriteSynchronizationMode.PRIMARY_SYNC);
+ cfg.setReadThrough(true);
+ cfg.setCacheStoreFactory(new TestStoreFactory());
+
+ IgniteCache<Object, Object> cache = ignite(0).getOrCreateCache(cfg);
+
+ for (int i = 1; i <= ENTRIES; i++) {
+ cache.get(i);
+
+ if (i % (ENTRIES / 10) == 0)
+ System.out.println(">>> Entries: " + i);
+ }
+
+ int size = cache.size(CachePeekMode.PRIMARY);
+
+ System.out.println(">>> Resulting size: " + size);
+
+ assertTrue(size > 0);
+
+ assertTrue(size < ENTRIES);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+
+ /**
+ *
+ */
+ private static class TestStoreFactory implements Factory<TestCacheStore> {
+ /** {@inheritDoc} */
+ @Override public TestCacheStore create() {
+ return new TestCacheStore();
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TestCacheStore extends CacheStoreAdapter<Object, Object> {
+ /** {@inheritDoc} */
+ @Override public Object load(Object key) throws CacheLoaderException {
+ ThreadLocalRandom r = ThreadLocalRandom.current();
+
+ if (r.nextInt() % 5 == 0)
+ return new TestObject(PAGE_SIZE / 4 - 50 + r.nextInt(5000)); // Fragmented object.
+ else
+ return new TestObject(r.nextInt(PAGE_SIZE / 4 - 50)); // Fits in one page.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void write(Cache.Entry<?, ?> entry) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void delete(Object key) {
+ // No-op.
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
new file mode 100644
index 0000000..4335649
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
@@ -0,0 +1,109 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class PageEvictionTouchOrderTest extends PageEvictionAbstractTest {
+ /** Test entries number. */
+ private static final int SAFE_ENTRIES = 1000;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(/* Overriden by FairFifoPageEvictionTracker */DataPageEvictionMode.RANDOM_LRU,
+ super.getConfiguration(gridName));
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ System.setProperty("override.fair.fifo.page.eviction.tracker", "true");
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTouchOrderWithFairFifoEvictionAtomicReplicated() throws Exception {
+ testTouchOrderWithFairFifoEviction(CacheAtomicityMode.ATOMIC, CacheMode.REPLICATED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTouchOrderWithFairFifoEvictionAtomicLocal() throws Exception {
+ testTouchOrderWithFairFifoEviction(CacheAtomicityMode.ATOMIC, CacheMode.LOCAL);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTouchOrderWithFairFifoEvictionTxReplicated() throws Exception {
+ testTouchOrderWithFairFifoEviction(CacheAtomicityMode.TRANSACTIONAL, CacheMode.REPLICATED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTouchOrderWithFairFifoEvictionTxLocal() throws Exception {
+ testTouchOrderWithFairFifoEviction(CacheAtomicityMode.TRANSACTIONAL, CacheMode.LOCAL);
+ }
+
+ /**
+ * @param atomicityMode Atomicity mode.
+ * @param cacheMode Cache mode.
+ * @throws Exception If failed.
+ */
+ private void testTouchOrderWithFairFifoEviction(CacheAtomicityMode atomicityMode, CacheMode cacheMode)
+ throws Exception {
+ startGrid(0);
+
+ CacheConfiguration<Object, Object> cfg = cacheConfig("evict-fair", null, cacheMode, atomicityMode,
+ CacheWriteSynchronizationMode.PRIMARY_SYNC);
+
+ IgniteCache<Object, Object> cache = ignite(0).getOrCreateCache(cfg);
+
+ for (int i = 1; i <= ENTRIES; i++) {
+ cache.put(i, new TestObject(PAGE_SIZE / 6));
+ // Row size is between PAGE_SIZE / 2 and PAGE_SIZE. Enforces "one row - one page".
+
+ if (i % (ENTRIES / 10) == 0)
+ System.out.println(">>> Entries put: " + i);
+ }
+
+ for (int i = ENTRIES - SAFE_ENTRIES + 1; i <= ENTRIES; i++)
+ assertNotNull(cache.get(i));
+
+ for (int i = 1; i <= SAFE_ENTRIES; i++)
+ assertNull(cache.get(i));
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ System.setProperty("override.fair.fifo.page.eviction.tracker", "false");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceTest.java
new file mode 100644
index 0000000..fd80201
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceTest.java
@@ -0,0 +1,81 @@
+/*
+* 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.eviction.paged;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+
+/**
+ *
+ */
+public abstract class PageEvictionWithRebalanceTest extends PageEvictionAbstractTest {
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEvictionWithRebalance() throws Exception {
+ startGridsMultiThreaded(4);
+
+ CacheConfiguration<Object, Object> cfg = cacheConfig("evict-rebalance", null, CacheMode.PARTITIONED,
+ CacheAtomicityMode.ATOMIC, CacheWriteSynchronizationMode.PRIMARY_SYNC);
+
+ IgniteCache<Object, Object> cache = ignite(0).getOrCreateCache(cfg);
+
+ for (int i = 1; i <= ENTRIES; i++) {
+ ThreadLocalRandom r = ThreadLocalRandom.current();
+
+ if (r.nextInt() % 5 == 0)
+ cache.put(i, new TestObject(PAGE_SIZE / 4 - 50 + r.nextInt(5000))); // Fragmented object.
+ else
+ cache.put(i, new TestObject(r.nextInt(PAGE_SIZE / 4 - 50))); // Fits in one page.
+
+ if (i % (ENTRIES / 10) == 0)
+ System.out.println(">>> Entries put: " + i);
+ }
+
+ int size = cache.size(CachePeekMode.PRIMARY);
+
+ System.out.println(">>> Resulting size: " + size);
+
+ assertTrue(size < ENTRIES);
+
+ for (int i = 3; i >= 1; i--) {
+ stopGrid(i);
+
+ cache.rebalance().get();
+
+ awaitPartitionMapExchange();
+
+ int rebalanceSize = cache.size(CachePeekMode.PRIMARY);
+
+ System.out.println(">>> Size after rebalance: " + rebalanceSize);
+
+ assertTrue(rebalanceSize < size);
+
+ size = rebalanceSize;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionMultinodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionMultinodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionMultinodeTest.java
new file mode 100644
index 0000000..b05ec43
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionMultinodeTest.java
@@ -0,0 +1,30 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class Random2LruPageEvictionMultinodeTest extends PageEvictionMultinodeTest {
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(DataPageEvictionMode.RANDOM_2_LRU, super.getConfiguration(gridName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionWithRebalanceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionWithRebalanceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionWithRebalanceTest.java
new file mode 100644
index 0000000..56698fb
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/Random2LruPageEvictionWithRebalanceTest.java
@@ -0,0 +1,30 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class Random2LruPageEvictionWithRebalanceTest extends PageEvictionWithRebalanceTest {
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(DataPageEvictionMode.RANDOM_2_LRU, super.getConfiguration(gridName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionMultinodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionMultinodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionMultinodeTest.java
new file mode 100644
index 0000000..38ca2af
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionMultinodeTest.java
@@ -0,0 +1,30 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class RandomLruPageEvictionMultinodeTest extends PageEvictionMultinodeTest {
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(DataPageEvictionMode.RANDOM_LRU, super.getConfiguration(gridName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionWithRebalanceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionWithRebalanceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionWithRebalanceTest.java
new file mode 100644
index 0000000..d961360
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/RandomLruPageEvictionWithRebalanceTest.java
@@ -0,0 +1,30 @@
+/*
+* 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.eviction.paged;
+
+import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class RandomLruPageEvictionWithRebalanceTest extends PageEvictionWithRebalanceTest {
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return setEvictionMode(DataPageEvictionMode.RANDOM_LRU, super.getConfiguration(gridName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/TestObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/TestObject.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/TestObject.java
new file mode 100644
index 0000000..baf2414
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/TestObject.java
@@ -0,0 +1,78 @@
+/*
+* 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.eviction.paged;
+
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ *
+ */
+class TestObject {
+ /** */
+ private int b;
+
+ /** */
+ private String c;
+
+ /** */
+ private int[] arr;
+
+ /**
+ * @param intArrSize Int array size.
+ */
+ public TestObject(int intArrSize) {
+ this.b = intArrSize;
+
+ this.c = String.valueOf(2 * intArrSize);
+
+ arr = new int[intArrSize];
+
+ for (int i = 0; i < intArrSize; i++)
+ arr[i] = ThreadLocalRandom.current().nextInt();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestObject testObj = (TestObject)o;
+
+ if (b != testObj.b)
+ return false;
+
+ if (c != null ? !c.equals(testObj.c) : testObj.c != null)
+ return false;
+
+ return Arrays.equals(arr, testObj.arr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = b;
+
+ res = 31 * res + (c != null ? c.hashCode() : 0);
+
+ res = 31 * res + Arrays.hashCode(arr);
+
+ return res;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
index 7fccef1..d5011a8 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
@@ -39,6 +39,8 @@ import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl;
+import org.apache.ignite.internal.processors.cache.database.MemoryPolicy;
+import org.apache.ignite.internal.processors.cache.database.evict.NoOpPageEvictionTracker;
import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
import org.apache.ignite.internal.processors.cache.database.freelist.FreeListImpl;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -334,7 +336,11 @@ public class FreeListImplSelfTest extends GridCommonAbstractTest {
long metaPageId = pageMem.allocatePage(1, 1, PageIdAllocator.FLAG_DATA);
- return new FreeListImpl(1, "freelist", pageMem, new MemoryMetricsImpl(null), null, null, metaPageId, true);
+ MemoryMetricsImpl metrics = new MemoryMetricsImpl(null);
+
+ MemoryPolicy memPlc = new MemoryPolicy(pageMem, null, metrics, new NoOpPageEvictionTracker());
+
+ return new FreeListImpl(1, "freelist", metrics, memPlc, null, null, metaPageId, true);
}
/**
@@ -407,6 +413,11 @@ public class FreeListImplSelfTest extends GridCommonAbstractTest {
@Override public int hash() {
throw new UnsupportedOperationException();
}
+
+ /** {@inheritDoc} */
+ @Override public int cacheId() {
+ return 0;
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheEvictionSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheEvictionSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheEvictionSelfTestSuite.java
index 94e1447..1bdfdd1 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheEvictionSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheEvictionSelfTestSuite.java
@@ -33,6 +33,12 @@ import org.apache.ignite.internal.processors.cache.eviction.fifo.FifoEvictionPol
import org.apache.ignite.internal.processors.cache.eviction.lru.LruEvictionPolicySelfTest;
import org.apache.ignite.internal.processors.cache.eviction.lru.LruNearEvictionPolicySelfTest;
import org.apache.ignite.internal.processors.cache.eviction.lru.LruNearOnlyNearEvictionPolicySelfTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.PageEvictionReadThroughTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.PageEvictionTouchOrderTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.Random2LruPageEvictionMultinodeTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.Random2LruPageEvictionWithRebalanceTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.RandomLruPageEvictionMultinodeTest;
+import org.apache.ignite.internal.processors.cache.eviction.paged.RandomLruPageEvictionWithRebalanceTest;
import org.apache.ignite.internal.processors.cache.eviction.sorted.SortedEvictionPolicySelfTest;
/**
@@ -63,6 +69,13 @@ public class IgniteCacheEvictionSelfTestSuite extends TestSuite {
suite.addTest(new TestSuite(GridCacheEmptyEntriesLocalSelfTest.class));
suite.addTest(new TestSuite(GridCacheEvictableEntryEqualsSelfTest.class));
+ suite.addTest(new TestSuite(RandomLruPageEvictionMultinodeTest.class));
+ suite.addTest(new TestSuite(Random2LruPageEvictionMultinodeTest.class));
+ suite.addTest(new TestSuite(RandomLruPageEvictionWithRebalanceTest.class));
+ suite.addTest(new TestSuite(Random2LruPageEvictionWithRebalanceTest.class));
+ suite.addTest(new TestSuite(PageEvictionTouchOrderTest.class));
+ suite.addTest(new TestSuite(PageEvictionReadThroughTest.class));
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
index ce10cdb..042e163 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
@@ -174,4 +174,9 @@ public abstract class GridH2Row extends Row implements GridSearchRowPointer, Cac
@Override public int hash() {
throw new UnsupportedOperationException();
}
+
+ /** {@inheritDoc} */
+ @Override public int cacheId() {
+ return 0;
+ }
}
\ No newline at end of file
[2/2] ignite git commit: IGNITE-4534 - Added offheap evictions
Posted by ag...@apache.org.
IGNITE-4534 - Added offheap evictions
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ff5b3e16
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ff5b3e16
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ff5b3e16
Branch: refs/heads/ignite-3477-master
Commit: ff5b3e16850e503b79a13c44b667140d23c1f080
Parents: baa3835
Author: Ivan Rakov <iv...@gmail.com>
Authored: Mon Apr 10 19:23:43 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Apr 10 19:23:43 2017 +0300
----------------------------------------------------------------------
.../configuration/DataPageEvictionMode.java | 32 +++
.../MemoryPolicyConfiguration.java | 70 ++++++
.../ignite/internal/pagemem/PageSupport.java | 10 +
.../pagemem/impl/PageMemoryNoStoreImpl.java | 8 +
.../internal/pagemem/impl/PageNoStoreImpl.java | 0
.../cache/CacheOffheapEvictionManager.java | 6 +-
.../processors/cache/GridCacheAdapter.java | 2 +
.../processors/cache/GridCacheEntryEx.java | 5 +-
.../cache/GridCacheEvictionManager.java | 2 +-
.../processors/cache/GridCacheMapEntry.java | 32 ++-
.../cache/IgniteCacheOffheapManagerImpl.java | 34 ++-
.../processors/cache/database/CacheDataRow.java | 5 +
.../cache/database/CacheDataRowAdapter.java | 116 ++++++++-
.../IgniteCacheDatabaseSharedManager.java | 126 ++++++++--
.../processors/cache/database/MemoryPolicy.java | 19 +-
.../evict/FairFifoPageEvictionTracker.java | 74 ++++++
.../database/evict/NoOpPageEvictionTracker.java | 50 ++++
.../evict/PageAbstractEvictionTracker.java | 243 +++++++++++++++++++
.../database/evict/PageEvictionTracker.java | 52 ++++
.../evict/Random2LruPageEvictionTracker.java | 180 ++++++++++++++
.../evict/RandomLruPageEvictionTracker.java | 157 ++++++++++++
.../cache/database/freelist/FreeListImpl.java | 62 +++--
.../cache/database/tree/io/DataPageIO.java | 110 ++++++++-
.../dht/atomic/GridDhtAtomicCache.java | 2 +
.../cache/distributed/near/GridNearTxLocal.java | 2 +
.../distributed/near/GridNearTxRemote.java | 4 +-
.../local/atomic/GridLocalAtomicCache.java | 6 +-
.../cacheobject/IgniteCacheObjectProcessor.java | 7 -
.../IgniteCacheObjectProcessorImpl.java | 16 --
.../processors/cache/GridCacheTestEntryEx.java | 2 +-
.../dht/GridCacheDhtEntrySelfTest.java | 4 +-
.../paged/PageEvictionAbstractTest.java | 124 ++++++++++
.../paged/PageEvictionMultinodeTest.java | 110 +++++++++
.../paged/PageEvictionReadThroughTest.java | 140 +++++++++++
.../paged/PageEvictionTouchOrderTest.java | 109 +++++++++
.../paged/PageEvictionWithRebalanceTest.java | 81 +++++++
.../Random2LruPageEvictionMultinodeTest.java | 30 +++
...Random2LruPageEvictionWithRebalanceTest.java | 30 +++
.../RandomLruPageEvictionMultinodeTest.java | 30 +++
.../RandomLruPageEvictionWithRebalanceTest.java | 30 +++
.../cache/eviction/paged/TestObject.java | 78 ++++++
.../database/FreeListImplSelfTest.java | 13 +-
.../IgniteCacheEvictionSelfTestSuite.java | 13 +
.../processors/query/h2/opt/GridH2Row.java | 5 +
44 files changed, 2130 insertions(+), 101 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java b/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
new file mode 100644
index 0000000..bada68e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
@@ -0,0 +1,32 @@
+/*
+* 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.configuration;
+
+/**
+ * Enumeration defines data page eviction modes.
+ */
+public enum DataPageEvictionMode {
+ /** Disabled. */
+ DISABLED,
+
+ /** Random lru. */
+ RANDOM_LRU,
+
+ /** Random 2-lru. */
+ RANDOM_2_LRU
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
index 2add64f..d6203c6 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
@@ -19,6 +19,8 @@ package org.apache.ignite.configuration;
import java.io.Serializable;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.processors.cache.database.MemoryPolicy;
+import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
+import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO;
/**
* Configuration bean used for creating {@link MemoryPolicy} instances.
@@ -43,6 +45,18 @@ public final class MemoryPolicyConfiguration implements Serializable {
return name;
}
+ /** Algorithm for per-page eviction. If {@link DataPageEvictionMode#DISABLED} set, eviction is not performed. */
+ private DataPageEvictionMode pageEvictionMode = DataPageEvictionMode.DISABLED;
+
+ /** Allocation of new {@link DataPageIO} pages is stopped when this percentage of pages are allocated. */
+ private double evictionThreshold = 0.9;
+
+ /** Allocation of new {@link DataPageIO} pages is stopped by maintaining this amount of empty pages in
+ * corresponding {@link FreeList} bucket. Pages get into the bucket through evicting all data entries one by one.
+ * Higher load and contention require larger pool size.
+ */
+ private int emptyPagesPoolSize = 100;
+
/**
* @param name Unique name of MemoryPolicy.
*/
@@ -83,4 +97,60 @@ public final class MemoryPolicyConfiguration implements Serializable {
return this;
}
+
+ /**
+ * Gets data page eviction mode.
+ */
+ public DataPageEvictionMode getPageEvictionMode() {
+ return pageEvictionMode;
+ }
+
+ /**
+ * Sets data page eviction mode.
+ *
+ * @param evictionMode Eviction mode.
+ */
+ public MemoryPolicyConfiguration setPageEvictionMode(DataPageEvictionMode evictionMode) {
+ pageEvictionMode = evictionMode;
+
+ return this;
+ }
+
+ /**
+ * Gets data page eviction threshold.
+ *
+ * @return Data page eviction threshold.
+ */
+ public double getEvictionThreshold() {
+ return evictionThreshold;
+ }
+
+ /**
+ * Sets data page eviction threshold.
+ *
+ * @param evictionThreshold Eviction threshold.
+ */
+ public MemoryPolicyConfiguration setEvictionThreshold(double evictionThreshold) {
+ this.evictionThreshold = evictionThreshold;
+
+ return this;
+ }
+
+ /**
+ * Gets empty pages pool size.
+ */
+ public int getEmptyPagesPoolSize() {
+ return emptyPagesPoolSize;
+ }
+
+ /**
+ * Sets empty pages pool size.
+ *
+ * @param emptyPagesPoolSize Empty pages pool size.
+ */
+ public MemoryPolicyConfiguration setEmptyPagesPoolSize(int emptyPagesPoolSize) {
+ this.emptyPagesPoolSize = emptyPagesPoolSize;
+
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageSupport.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageSupport.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageSupport.java
index 8076f28..0f39058 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageSupport.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageSupport.java
@@ -53,6 +53,16 @@ public interface PageSupport {
public long readLock(int cacheId, long pageId, long page);
/**
+ * Obtains read lock without checking page tag.
+ *
+ * @param cacheId Cache ID.
+ * @param pageId Page ID.
+ * @param page Page pointer.
+ * @return Pointer for reading the page.
+ */
+ public long readLockForce(int cacheId, long pageId, long page);
+
+ /**
* Releases locked page.
*
* @param cacheId Cache ID.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
index f24113c..7134cff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
@@ -416,6 +416,14 @@ public class PageMemoryNoStoreImpl implements PageMemory {
}
/** {@inheritDoc} */
+ public long readLockForce(int cacheId, long pageId, long page) {
+ if (rwLock.readLock(page + LOCK_OFFSET, -1))
+ return page + PAGE_OVERHEAD;
+
+ return 0L;
+ }
+
+ /** {@inheritDoc} */
@Override public void readUnlock(int cacheId, long pageId, long page) {
rwLock.readUnlock(page + LOCK_OFFSET);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageNoStoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageNoStoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageNoStoreImpl.java
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
index 99df39d..f8e9f32 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
@@ -27,10 +27,6 @@ import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
/**
- * TODO GG-11140.
- *
- * Temporary implementation, ignores configured EvictionPolicy, evictions to be reconsidered as
- * part of GG-11140.
*
*/
public class CacheOffheapEvictionManager extends GridCacheManagerAdapter implements CacheEvictionManager {
@@ -51,7 +47,7 @@ public class CacheOffheapEvictionManager extends GridCacheManagerAdapter impleme
return;
}
- boolean evicted = e.evictInternal(GridCacheVersionManager.EVICT_VER, null);
+ boolean evicted = e.evictInternal(GridCacheVersionManager.EVICT_VER, null, false);
if (evicted)
cctx.cache().removeEntry(e);
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 9a6ff11..d791b7c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -2073,6 +2073,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
GridCacheEntryEx entry = null;
try {
+ ctx.shared().database().ensureFreeSpace(ctx.memoryPolicy());
+
entry = entryEx(key);
entry.unswap();
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
index 99f9744..2066342 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
@@ -213,11 +213,12 @@ public interface GridCacheEntryEx {
/**
* @param obsoleteVer Version for eviction.
* @param filter Optional filter.
+ * @param evictOffheap Evict offheap value flag.
* @return {@code True} if entry could be evicted.
* @throws IgniteCheckedException In case of error.
*/
- public boolean evictInternal(GridCacheVersion obsoleteVer, @Nullable CacheEntryPredicate[] filter)
- throws IgniteCheckedException;
+ public boolean evictInternal(GridCacheVersion obsoleteVer, @Nullable CacheEntryPredicate[] filter,
+ boolean evictOffheap) throws IgniteCheckedException;
/**
* Evicts entry when batch evict is performed. When called, does not write entry data to swap, but instead
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
index 26f37a7..0deae07 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
@@ -135,7 +135,7 @@ public class GridCacheEvictionManager extends GridCacheManagerAdapter implements
boolean hasVal = recordable && entry.hasValue();
- boolean evicted = entry.evictInternal(obsoleteVer, filter);
+ boolean evicted = entry.evictInternal(obsoleteVer, filter, false);
if (evicted) {
// Remove manually evicted entry from policy.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/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 7fad9f5..9e2cd70 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
@@ -43,6 +43,7 @@ import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult.UpdateOutcome;
import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
import org.apache.ignite.internal.processors.cache.database.CacheDataRowAdapter;
+import org.apache.ignite.internal.processors.cache.database.MemoryPolicy;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicAbstractUpdateFuture;
@@ -809,6 +810,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
boolean touch = false;
try {
+ ensureFreeSpace();
+
synchronized (this) {
long ttl = ttlExtras();
@@ -908,6 +911,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
long updateCntr0;
+ ensureFreeSpace();
+
synchronized (this) {
checkObsolete();
@@ -1641,6 +1646,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
AtomicCacheUpdateClosure c;
+ if (!primary && !isNear())
+ ensureFreeSpace();
+
synchronized (this) {
checkObsolete();
@@ -2567,6 +2575,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
GridDrType drType,
boolean fromStore
) throws IgniteCheckedException, GridCacheEntryRemovedException {
+ ensureFreeSpace();
+
synchronized (this) {
checkObsolete();
@@ -3378,6 +3388,16 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
}
/**
+ * Evicts necessary number of data pages if per-page eviction is configured in current {@link MemoryPolicy}.
+ */
+ private void ensureFreeSpace() throws IgniteCheckedException {
+ // Deadlock alert: evicting data page causes removing (and locking) all entries on the page one by one.
+ assert !Thread.holdsLock(this);
+
+ cctx.shared().database().ensureFreeSpace(cctx.memoryPolicy());
+ }
+
+ /**
* @return Entry which holds key, value and version.
*/
private synchronized <K, V> CacheEntryImplEx<K, V> wrapVersionedWithValue() {
@@ -3387,8 +3407,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
}
/** {@inheritDoc} */
- @Override public boolean evictInternal(GridCacheVersion obsoleteVer, @Nullable CacheEntryPredicate[] filter)
+ @Override public boolean evictInternal(
+ GridCacheVersion obsoleteVer,
+ @Nullable CacheEntryPredicate[] filter,
+ boolean evictOffheap)
throws IgniteCheckedException {
+
boolean marked = false;
try {
@@ -3411,6 +3435,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
// Nullify value after swap.
value(null);
+ if (evictOffheap)
+ removeValue();
+
marked = true;
return true;
@@ -3451,6 +3478,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
// Nullify value after swap.
value(null);
+ if (evictOffheap)
+ removeValue();
+
marked = true;
return true;
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index e022e57..73edbe1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -28,6 +28,7 @@ import javax.cache.Cache;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.DataPageEvictionMode;
import org.apache.ignite.internal.NodeStoppingException;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageIdUtils;
@@ -37,7 +38,6 @@ import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
import org.apache.ignite.internal.processors.cache.database.CacheDataRowAdapter;
import org.apache.ignite.internal.processors.cache.database.CacheSearchRow;
-import org.apache.ignite.internal.processors.cache.database.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.cache.database.RootPage;
import org.apache.ignite.internal.processors.cache.database.RowStore;
import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
@@ -965,8 +965,12 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
CacheObject val,
GridCacheVersion ver,
long expireTime,
- @Nullable CacheDataRow oldRow) throws IgniteCheckedException {
- DataRow dataRow = new DataRow(key, val, ver, partId, expireTime);
+ @Nullable CacheDataRow oldRow) throws IgniteCheckedException
+ {
+ int cacheId = cctx.memoryPolicy().config().getPageEvictionMode() == DataPageEvictionMode.DISABLED ?
+ 0 : cctx.cacheId();
+
+ DataRow dataRow = new DataRow(key, val, ver, partId, expireTime, cacheId);
if (canUpdateOldRow(oldRow, dataRow) && rowStore.updateRow(oldRow.link(), dataRow))
dataRow.link(oldRow.link());
@@ -997,7 +1001,10 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
throw new NodeStoppingException("Operation has been cancelled (node is stopping).");
try {
- DataRow dataRow = new DataRow(key, val, ver, p, expireTime);
+ int cacheId = cctx.memoryPolicy().config().getPageEvictionMode() != DataPageEvictionMode.DISABLED ?
+ cctx.cacheId() : 0;
+
+ DataRow dataRow = new DataRow(key, val, ver, p, expireTime, cacheId);
CacheObjectContext coCtx = cctx.cacheObjectContext();
@@ -1140,9 +1147,12 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
CacheDataRow row = dataTree.findOne(new SearchRow(key), CacheDataRowAdapter.RowData.NO_KEY);
- if (row != null)
+ if (row != null) {
row.key(key);
+ cctx.memoryPolicy().evictionTracker().touchPage(row.link());
+ }
+
return row;
}
@@ -1345,7 +1355,7 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
* @param part Partition.
* @param expireTime Expire time.
*/
- DataRow(KeyCacheObject key, CacheObject val, GridCacheVersion ver, int part, long expireTime) {
+ DataRow(KeyCacheObject key, CacheObject val, GridCacheVersion ver, int part, long expireTime, int cacheId) {
super(0);
this.hash = key.hashCode();
@@ -1354,6 +1364,7 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
this.ver = ver;
this.part = part;
this.expireTime = expireTime;
+ this.cacheId = cacheId;
}
/** {@inheritDoc} */
@@ -1473,6 +1484,9 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
if (data.nextLink() == 0) {
long addr = pageAddr + data.offset();
+ if (cctx.memoryPolicy().config().getPageEvictionMode() != DataPageEvictionMode.DISABLED)
+ addr += 4; // Skip cache id.
+
final int len = PageUtils.getInt(addr, 0);
int lenCmp = Integer.compare(len, bytes.length);
@@ -1672,6 +1686,14 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
@Override public int getHash(long pageAddr, int idx) {
return PageUtils.getInt(pageAddr, offset(idx) + 8);
}
+
+ /** {@inheritDoc} */
+ @Override public void visit(long pageAddr, IgniteInClosure<CacheSearchRow> c) {
+ int cnt = getCount(pageAddr);
+
+ for (int i = 0; i < cnt; i++)
+ c.apply(new CacheDataRowAdapter(getLink(pageAddr, i)));
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java
index cc26b21..e0076d5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java
@@ -36,6 +36,11 @@ public interface CacheDataRow extends CacheSearchRow {
public GridCacheVersion version();
/**
+ * @return Cache id. Stored only if memory policy with configured per-page eviction is used.
+ */
+ public int cacheId();
+
+ /**
* @return Expire time.
*/
public long expireTime();
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRowAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRowAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRowAdapter.java
index eca59d6..afeada5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRowAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRowAdapter.java
@@ -19,12 +19,14 @@ package org.apache.ignite.internal.processors.cache.database;
import java.nio.ByteBuffer;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.DataPageEvictionMode;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.PageUtils;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.IncompleteCacheObject;
import org.apache.ignite.internal.processors.cache.IncompleteObject;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
@@ -36,6 +38,7 @@ import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.internal.pagemem.PageIdUtils.itemId;
import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId;
@@ -63,6 +66,10 @@ public class CacheDataRowAdapter implements CacheDataRow {
@GridToStringInclude
protected GridCacheVersion ver;
+ /** */
+ @GridToStringInclude
+ protected int cacheId;
+
/**
* @param link Link.
*/
@@ -92,14 +99,35 @@ public class CacheDataRowAdapter implements CacheDataRow {
* @throws IgniteCheckedException If failed.
*/
public final void initFromLink(GridCacheContext<?, ?> cctx, RowData rowData) throws IgniteCheckedException {
- assert cctx != null : "cctx";
+ initFromLink(cctx, cctx.shared(), cctx.memoryPolicy().pageMemory(), rowData);
+ }
+
+ /**
+ * Read row from data pages.
+ * Can be called with cctx == null, if cache instance is unknown, but its ID is stored in the data row.
+ *
+ * @param cctx Cctx.
+ * @param sharedCtx Shared context.
+ * @param pageMem Page memory.
+ * @param rowData Row data.
+ */
+ public final void initFromLink(
+ @Nullable GridCacheContext<?, ?> cctx,
+ GridCacheSharedContext<?, ?> sharedCtx,
+ PageMemory pageMem,
+ RowData rowData)
+ throws IgniteCheckedException {
assert link != 0 : "link";
assert key == null : "key";
- final CacheObjectContext coctx = cctx.cacheObjectContext();
- final PageMemory pageMem = cctx.memoryPolicy().pageMemory();
+ CacheObjectContext coctx = null;
+
+ if (cctx != null) {
+ cacheId = cctx.memoryPolicy().config().getPageEvictionMode() == DataPageEvictionMode.DISABLED ?
+ cctx.cacheId() : 0; // Force cacheId reading for evictable memory policies.
- final int cacheId = cctx.cacheId();
+ coctx = cctx.cacheObjectContext();
+ }
long nextLink = link;
IncompleteObject<?> incomplete = null;
@@ -126,7 +154,7 @@ public class CacheDataRowAdapter implements CacheDataRow {
if (first) {
if (nextLink == 0) {
// Fast path for a single page row.
- readFullRow(coctx, pageAddr + data.offset(), rowData);
+ readFullRow(sharedCtx, coctx, pageAddr + data.offset(), rowData);
return;
}
@@ -141,7 +169,7 @@ public class CacheDataRowAdapter implements CacheDataRow {
boolean keyOnly = rowData == RowData.KEY_ONLY;
- incomplete = readFragment(coctx, buf, keyOnly, incomplete);
+ incomplete = readFragment(sharedCtx, coctx, buf, keyOnly, incomplete);
if (keyOnly && key != null)
return;
@@ -168,11 +196,24 @@ public class CacheDataRowAdapter implements CacheDataRow {
* @return Read object.
*/
private IncompleteObject<?> readFragment(
+ GridCacheSharedContext<?, ?> sharedCtx,
CacheObjectContext coctx,
ByteBuffer buf,
boolean keyOnly,
IncompleteObject<?> incomplete
) throws IgniteCheckedException {
+ if (cacheId == 0) {
+ incomplete = readIncompleteCacheId(buf, incomplete);
+
+ if (cacheId == 0)
+ return incomplete;
+
+ incomplete = null;
+ }
+
+ if (coctx == null)
+ coctx = sharedCtx.cacheContext(cacheId).cacheObjectContext();
+
// Read key.
if (key == null) {
incomplete = readIncompleteKey(coctx, buf, (IncompleteCacheObject)incomplete);
@@ -215,9 +256,23 @@ public class CacheDataRowAdapter implements CacheDataRow {
* @param rowData Required row data.
* @throws IgniteCheckedException If failed.
*/
- private void readFullRow(CacheObjectContext coctx, long addr, RowData rowData) throws IgniteCheckedException {
+ private void readFullRow(
+ GridCacheSharedContext<?, ?> sharedCtx,
+ CacheObjectContext coctx,
+ long addr,
+ RowData rowData)
+ throws IgniteCheckedException {
int off = 0;
+ if (cacheId == 0) {
+ cacheId = PageUtils.getInt(addr, off);
+
+ off += 4;
+ }
+
+ if (coctx == null)
+ coctx = sharedCtx.cacheContext(cacheId).cacheObjectContext();
+
int len = PageUtils.getInt(addr, off);
off += 4;
@@ -255,6 +310,44 @@ public class CacheDataRowAdapter implements CacheDataRow {
}
/**
+ * @param buf Buffer.
+ * @param incomplete Incomplete.
+ */
+ private IncompleteObject<?> readIncompleteCacheId(
+ ByteBuffer buf,
+ IncompleteObject<?> incomplete
+ ) {
+ if (incomplete == null) {
+ int remaining = buf.remaining();
+
+ if (remaining == 0)
+ return null;
+
+ int size = 4;
+
+ if (remaining >= size) {
+ cacheId = buf.getInt();
+
+ return null;
+ }
+
+ incomplete = new IncompleteObject<>(new byte[size]);
+ }
+
+ incomplete.readData(buf);
+
+ if (incomplete.isReady()) {
+ final ByteBuffer timeBuf = ByteBuffer.wrap(incomplete.data());
+
+ timeBuf.order(buf.order());
+
+ cacheId = timeBuf.getInt();
+ }
+
+ return incomplete;
+ }
+
+ /**
* @param coctx Cache object context.
* @param buf Buffer.
* @param incomplete Incomplete object.
@@ -313,7 +406,7 @@ public class CacheDataRowAdapter implements CacheDataRow {
private IncompleteObject<?> readIncompleteExpireTime(
ByteBuffer buf,
IncompleteObject<?> incomplete
- ) throws IgniteCheckedException {
+ ) {
if (incomplete == null) {
int remaining = buf.remaining();
@@ -414,13 +507,18 @@ public class CacheDataRowAdapter implements CacheDataRow {
/**
* @param key Key.
*/
- public void key(KeyCacheObject key) {
+ @Override public void key(KeyCacheObject key) {
assert key != null;
this.key = key;
}
/** {@inheritDoc} */
+ @Override public int cacheId() {
+ return cacheId;
+ }
+
+ /** {@inheritDoc} */
@Override public CacheObject value() {
assert val != null : "Value is not ready: " + this;
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
index d61130b..2d2295c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
@@ -29,6 +29,7 @@ import org.apache.ignite.IgniteLogger;
import org.apache.ignite.MemoryMetrics;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.DataPageEvictionMode;
import org.apache.ignite.configuration.MemoryConfiguration;
import org.apache.ignite.configuration.MemoryPolicyConfiguration;
import org.apache.ignite.internal.GridKernalContext;
@@ -40,7 +41,13 @@ import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.snapshot.StartFullSnapshotAckDiscoveryMessage;
import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheMapEntry;
import org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter;
+import org.apache.ignite.internal.processors.cache.database.evict.FairFifoPageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.database.evict.NoOpPageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.database.evict.PageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.database.evict.Random2LruPageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.database.evict.RandomLruPageEvictionTracker;
import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
import org.apache.ignite.internal.processors.cache.database.freelist.FreeListImpl;
import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
@@ -102,7 +109,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
initPageMemoryPolicies(dbCfg);
- startPageMemoryPools();
+ startMemoryPolicies();
initPageMemoryDataStructures(dbCfg);
}
@@ -123,8 +130,8 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
FreeListImpl freeList = new FreeListImpl(0,
cctx.igniteInstanceName(),
- memPlc.pageMemory(),
memMetrics,
+ memPlc,
null,
cctx.wal(),
0L,
@@ -148,9 +155,12 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
/**
*
*/
- private void startPageMemoryPools() {
- for (MemoryPolicy memPlc : memPlcMap.values())
+ private void startMemoryPolicies() {
+ for (MemoryPolicy memPlc : memPlcMap.values()) {
memPlc.pageMemory().start();
+
+ memPlc.evictionTracker().start();
+ }
}
/**
@@ -205,9 +215,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
for (MemoryPolicyConfiguration memPlcCfg : memPlcsCfgs) {
MemoryMetricsImpl memMetrics = new MemoryMetricsImpl(memPlcCfg);
- PageMemory pageMem = initMemory(dbCfg, memPlcCfg, memMetrics);
-
- MemoryPolicy memPlc = new MemoryPolicy(pageMem, memMetrics, memPlcCfg);
+ MemoryPolicy memPlc = initMemory(dbCfg, memPlcCfg, memMetrics);
memPlcMap.put(memPlcCfg.getName(), memPlc);
@@ -222,7 +230,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
MemoryMetricsImpl sysMemMetrics = new MemoryMetricsImpl(sysPlcCfg);
- memPlcMap.put(SYSTEM_MEMORY_POLICY_NAME, new MemoryPolicy(initMemory(dbCfg, sysPlcCfg, sysMemMetrics), sysMemMetrics, sysPlcCfg));
+ memPlcMap.put(SYSTEM_MEMORY_POLICY_NAME, initMemory(dbCfg, sysPlcCfg, sysMemMetrics));
memMetricsMap.put(SYSTEM_MEMORY_POLICY_NAME, sysMemMetrics);
}
@@ -253,9 +261,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
* @param memMetrics MemoryMetrics instance.
*/
private MemoryPolicy createDefaultMemoryPolicy(MemoryConfiguration dbCfg, MemoryPolicyConfiguration memPlcCfg, MemoryMetricsImpl memMetrics) {
- PageMemory pageMem = initMemory(dbCfg, memPlcCfg, memMetrics);
-
- return new MemoryPolicy(pageMem, memMetrics, memPlcCfg);
+ return initMemory(dbCfg, memPlcCfg, memMetrics);
}
/**
@@ -285,6 +291,8 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
checkPolicyName(plcCfg.getName(), plcNames);
checkPolicySize(plcCfg);
+
+ checkPolicyEvictionProperties(plcCfg, dbCfg);
}
}
@@ -307,6 +315,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
/**
* @param plcCfg MemoryPolicyConfiguration to validate.
+ * @throws IgniteCheckedException If config is invalid.
*/
private static void checkPolicySize(MemoryPolicyConfiguration plcCfg) throws IgniteCheckedException {
if (plcCfg.getSize() < MIN_PAGE_MEMORY_SIZE)
@@ -314,8 +323,35 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
}
/**
+ * @param plcCfg MemoryPolicyConfiguration to validate.
+ * @param dbCfg Memory configuration.
+ * @throws IgniteCheckedException If config is invalid.
+ */
+ protected void checkPolicyEvictionProperties(MemoryPolicyConfiguration plcCfg, MemoryConfiguration dbCfg)
+ throws IgniteCheckedException {
+ if (plcCfg.getPageEvictionMode() == DataPageEvictionMode.DISABLED)
+ return;
+
+ if (plcCfg.getEvictionThreshold() < 0.5 || plcCfg.getEvictionThreshold() > 0.999) {
+ throw new IgniteCheckedException("Page eviction threshold must be between 0.5 and 0.999: " +
+ plcCfg.getName());
+ }
+
+ if (plcCfg.getEmptyPagesPoolSize() <= 10)
+ throw new IgniteCheckedException("Evicted pages pool size should be greater than 10: " + plcCfg.getName());
+
+ long maxPoolSize = plcCfg.getSize() / dbCfg.getPageSize() / 10;
+
+ if (plcCfg.getEmptyPagesPoolSize() >= maxPoolSize) {
+ throw new IgniteCheckedException("Evicted pages pool size should be lesser than " + maxPoolSize +
+ ": " + plcCfg.getName());
+ }
+ }
+
+ /**
* @param plcName MemoryPolicy name to validate.
* @param observedNames Names of MemoryPolicies observed before.
+ * @throws IgniteCheckedException If config is invalid.
*/
private static void checkPolicyName(String plcName, Set<String> observedNames) throws IgniteCheckedException {
if (plcName == null || plcName.isEmpty())
@@ -406,8 +442,11 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
/** {@inheritDoc} */
@Override protected void stop0(boolean cancel) {
if (memPlcMap != null) {
- for (MemoryPolicy memPlc : memPlcMap.values())
+ for (MemoryPolicy memPlc : memPlcMap.values()) {
memPlc.pageMemory().stop();
+
+ memPlc.evictionTracker().stop();
+ }
}
}
@@ -512,12 +551,49 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
}
/**
+ * See {@link GridCacheMapEntry#ensureFreeSpace()}
+ *
+ * @param memPlc Memory policy.
+ */
+ public void ensureFreeSpace(MemoryPolicy memPlc) throws IgniteCheckedException {
+ if (memPlc == null)
+ return;
+
+ MemoryPolicyConfiguration plcCfg = memPlc.config();
+
+ if (plcCfg.getPageEvictionMode() == DataPageEvictionMode.DISABLED)
+ return;
+
+ long memorySize = plcCfg.getSize();
+
+ PageMemory pageMem = memPlc.pageMemory();
+
+ int sysPageSize = pageMem.systemPageSize();
+
+ FreeListImpl freeListImpl = freeListMap.get(plcCfg.getName());
+
+ for (;;) {
+ long allocatedPagesCnt = pageMem.loadedPages();
+
+ int emptyDataPagesCnt = freeListImpl.emptyDataPages();
+
+ boolean shouldEvict = allocatedPagesCnt > (memorySize / sysPageSize * plcCfg.getEvictionThreshold()) &&
+ emptyDataPagesCnt < plcCfg.getEmptyPagesPoolSize();
+
+ if (shouldEvict)
+ memPlc.evictionTracker().evictDataPage();
+ else
+ break;
+ }
+ }
+
+ /**
* @param dbCfg memory configuration with common parameters.
* @param plc memory policy with PageMemory specific parameters.
* @param memMetrics {@link MemoryMetrics} object to collect memory usage metrics.
- * @return Page memory instance.
+ * @return Memory policy instance.
*/
- private PageMemory initMemory(MemoryConfiguration dbCfg, MemoryPolicyConfiguration plc, MemoryMetricsImpl memMetrics) {
+ private MemoryPolicy initMemory(MemoryConfiguration dbCfg, MemoryPolicyConfiguration plc, MemoryMetricsImpl memMetrics) {
long[] sizes = calculateFragmentSizes(
dbCfg.getConcurrencyLevel(),
plc.getSize());
@@ -532,7 +608,27 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
true,
sizes);
- return createPageMemory(memProvider, dbCfg.getPageSize(), memMetrics);
+ PageMemory pageMem = createPageMemory(memProvider, dbCfg.getPageSize(), memMetrics);
+
+ return new MemoryPolicy(pageMem, plc, memMetrics, createPageEvictionTracker(plc, pageMem));
+ }
+
+ /**
+ * @param plc Memory Policy Configuration.
+ * @param pageMem Page memory.
+ */
+ private PageEvictionTracker createPageEvictionTracker(MemoryPolicyConfiguration plc, PageMemory pageMem) {
+ if (Boolean.getBoolean("override.fair.fifo.page.eviction.tracker"))
+ return new FairFifoPageEvictionTracker(pageMem, plc, cctx);
+
+ switch (plc.getPageEvictionMode()) {
+ case RANDOM_LRU:
+ return new RandomLruPageEvictionTracker(pageMem, plc, cctx);
+ case RANDOM_2_LRU:
+ return new Random2LruPageEvictionTracker(pageMem, plc, cctx);
+ default:
+ return new NoOpPageEvictionTracker();
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MemoryPolicy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MemoryPolicy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MemoryPolicy.java
index be23b38..90e5ac1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MemoryPolicy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MemoryPolicy.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.database;
import org.apache.ignite.MemoryMetrics;
import org.apache.ignite.configuration.MemoryPolicyConfiguration;
import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.database.evict.PageEvictionTracker;
/**
* Memory policy provides access to objects configured with {@link MemoryPolicyConfiguration} configuration.
@@ -33,15 +34,24 @@ public class MemoryPolicy {
/** */
private final MemoryPolicyConfiguration cfg;
+ /** */
+ private final PageEvictionTracker evictionTracker;
+
/**
* @param pageMem PageMemory instance.
* @param memMetrics MemoryMetrics instance.
* @param cfg Configuration of given MemoryPolicy.
+ * @param evictionTracker Eviction tracker.
*/
- public MemoryPolicy(PageMemory pageMem, MemoryMetrics memMetrics, MemoryPolicyConfiguration cfg) {
+ public MemoryPolicy(
+ PageMemory pageMem,
+ MemoryPolicyConfiguration cfg,
+ MemoryMetrics memMetrics,
+ PageEvictionTracker evictionTracker) {
this.pageMem = pageMem;
this.memMetrics = memMetrics;
this.cfg = cfg;
+ this.evictionTracker = evictionTracker;
}
/**
@@ -64,4 +74,11 @@ public class MemoryPolicy {
public MemoryMetrics memoryMetrics() {
return memMetrics;
}
+
+ /**
+ *
+ */
+ public PageEvictionTracker evictionTracker() {
+ return evictionTracker;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/FairFifoPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/FairFifoPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/FairFifoPageEvictionTracker.java
new file mode 100644
index 0000000..8847013
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/FairFifoPageEvictionTracker.java
@@ -0,0 +1,74 @@
+/*
+* 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.database.evict;
+
+import java.util.LinkedList;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+
+/**
+ * On-heap FIFO page eviction tracker. Only for test purposes.
+ */
+public class FairFifoPageEvictionTracker extends PageAbstractEvictionTracker {
+ /** Page usage deque. */
+ private final LinkedList<Integer> pageUsageList = new LinkedList<>();
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Memory policy configuration.
+ * @param sharedCtx Shared context.
+ */
+ public FairFifoPageEvictionTracker(PageMemory pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext sharedCtx) {
+ super(pageMem, plcCfg, sharedCtx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void touchPage(long pageId) throws IgniteCheckedException {
+ pageUsageList.addLast(PageIdUtils.pageIndex(pageId));
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void evictDataPage() throws IgniteCheckedException {
+ evictDataPage(pageUsageList.pollFirst());
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void forgetPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected synchronized boolean checkTouch(long pageId) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/NoOpPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/NoOpPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/NoOpPageEvictionTracker.java
new file mode 100644
index 0000000..ba466bf
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/NoOpPageEvictionTracker.java
@@ -0,0 +1,50 @@
+/*
+* 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.database.evict;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+
+/**
+ *
+ */
+public class NoOpPageEvictionTracker implements PageEvictionTracker {
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void touchPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void evictDataPage() throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void forgetPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageAbstractEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageAbstractEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageAbstractEvictionTracker.java
new file mode 100644
index 0000000..88de545
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageAbstractEvictionTracker.java
@@ -0,0 +1,243 @@
+/*
+* 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.database.evict;
+
+import java.util.List;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.database.CacheDataRowAdapter;
+import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersionManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public abstract class PageAbstractEvictionTracker implements PageEvictionTracker {
+ /** This number of least significant bits is dropped from timestamp. */
+ private static final int COMPACT_TS_SHIFT = 8; // Enough if grid works for less than 17 years.
+
+ /** Millis in day. */
+ private final static int DAY = 24 * 60 * 60 * 1000;
+
+ /** Page memory. */
+ protected final PageMemory pageMem;
+
+ /** Tracking array size. */
+ final int trackingSize;
+
+ /** Base compact timestamp. */
+ private final long baseCompactTs;
+
+ /** Shared context. */
+ private final GridCacheSharedContext sharedCtx;
+
+ /* TODO: IGNITE-4921: Will be removed after segments refactoring >>>> */
+ protected final int segBits;
+ protected final int idxBits;
+ protected final int segMask;
+ protected final int idxMask;
+ protected final int segmentPageCount;
+ /* <<<< */
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Memory policy configuration.
+ * @param sharedCtx Shared context.
+ */
+ PageAbstractEvictionTracker(
+ PageMemory pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext sharedCtx
+ ) {
+ this.pageMem = pageMem;
+
+ this.sharedCtx = sharedCtx;
+
+ MemoryConfiguration memCfg = sharedCtx.kernalContext().config().getMemoryConfiguration();
+
+ /* TODO: IGNITE-4921: Will be removed after segments refactoring >>>> */
+ int concurrencyLevel = memCfg.getConcurrencyLevel();
+
+ if (concurrencyLevel < 1)
+ concurrencyLevel = Runtime.getRuntime().availableProcessors();
+
+ int pageSize = memCfg.getPageSize();
+
+ long segSize = plcCfg.getSize() / concurrencyLevel;
+
+ if (segSize < 1024 * 1024)
+ segSize = 1024 * 1024;
+
+ segmentPageCount = (int)(segSize / pageSize);
+
+ segBits = Integer.SIZE - Integer.numberOfLeadingZeros(concurrencyLevel - 1);
+
+ idxBits = PageIdUtils.PAGE_IDX_SIZE - segBits;
+
+ segMask = ~(-1 << segBits);
+
+ idxMask = ~(-1 << idxBits);
+ /* <<<< */
+
+ trackingSize = segmentPageCount << segBits;
+
+ baseCompactTs = (U.currentTimeMillis() - DAY) >> COMPACT_TS_SHIFT;
+ // We subtract day to avoid fail in case of daylight shift or timezone change.
+ }
+
+ /**
+ * @param pageIdx Page index.
+ * @return true if at least one data row has been evicted
+ * @throws IgniteCheckedException If failed.
+ */
+ final boolean evictDataPage(int pageIdx) throws IgniteCheckedException {
+ long fakePageId = PageIdUtils.pageId(0, (byte)0, pageIdx);
+
+ long page = pageMem.acquirePage(0, fakePageId);
+
+ List<CacheDataRowAdapter> rowsToEvict;
+
+ try {
+ long pageAddr = pageMem.readLockForce(0, fakePageId, page);
+
+ try {
+ if (PageIO.getType(pageAddr) != PageIO.T_DATA)
+ return false; // Can't evict: page has been recycled into non-data page.
+
+ DataPageIO io = DataPageIO.VERSIONS.forPage(pageAddr);
+
+ long realPageId = PageIO.getPageId(pageAddr);
+
+ if (!checkTouch(realPageId))
+ return false; // Can't evict: another thread concurrently invoked forgetPage()
+
+ rowsToEvict = io.forAllItems(pageAddr, new DataPageIO.CC<CacheDataRowAdapter>() {
+ @Override public CacheDataRowAdapter apply(long link) throws IgniteCheckedException {
+ CacheDataRowAdapter row = new CacheDataRowAdapter(link);
+
+ row.initFromLink(null, sharedCtx, pageMem, CacheDataRowAdapter.RowData.KEY_ONLY);
+
+ assert row.cacheId() != 0 : "Cache ID should be stored in rows of evictable cache";
+
+ return row;
+ }
+ });
+ }
+ finally {
+ pageMem.readUnlock(0, fakePageId, page);
+ }
+ }
+ finally {
+ pageMem.releasePage(0, fakePageId, page);
+ }
+
+ boolean evictionDone = false;
+
+ for (CacheDataRowAdapter dataRow : rowsToEvict) {
+ GridCacheContext<?, ?> cacheCtx = sharedCtx.cacheContext(dataRow.cacheId());
+
+ if (!cacheCtx.userCache())
+ continue;
+
+ GridCacheEntryEx entryEx = cacheCtx.cache().entryEx(dataRow.key());
+
+ evictionDone |= entryEx.evictInternal(GridCacheVersionManager.EVICT_VER, null, true);
+ }
+
+ return evictionDone;
+ }
+
+ /**
+ * @param pageId Page ID.
+ * @return true if page was touched at least once.
+ */
+ protected abstract boolean checkTouch(long pageId);
+
+ /**
+ * @param epochMilli Time millis.
+ * @return Compact timestamp. Comparable and fits in 4 bytes.
+ */
+ final long compactTimestamp(long epochMilli) {
+ return (epochMilli >> COMPACT_TS_SHIFT) - baseCompactTs;
+ }
+
+ /**
+ * Resolves position in tracking array by page index.
+ *
+ * @param pageIdx Page index.
+ * @return Position of page in tracking array.
+ */
+ int trackingIdx(int pageIdx) {
+ int inSegmentPageIdx = inSegmentPageIdx(pageIdx);
+
+ assert inSegmentPageIdx < segmentPageCount : inSegmentPageIdx;
+
+ int trackingIdx = segmentIdx(pageIdx) * segmentPageCount + inSegmentPageIdx;
+
+ assert trackingIdx < trackingSize : trackingIdx;
+
+ return trackingIdx;
+ }
+
+ /**
+ * Reverse of {@link #trackingIdx(int)}.
+ *
+ * @param trackingIdx Tracking index.
+ * @return Page index.
+ */
+ int pageIdx(int trackingIdx) {
+ assert trackingIdx < trackingSize;
+
+ long res = 0;
+
+ long segIdx = trackingIdx / segmentPageCount;
+ long pageIdx = trackingIdx % segmentPageCount;
+
+ res = (res << segBits) | (segIdx & segMask);
+ res = (res << idxBits) | (pageIdx & idxMask);
+
+ assert (res & (-1L << 32)) == 0 : res;
+
+ return (int)res;
+ }
+
+ /* TODO: IGNITE-4921: Will be removed after segments refactoring >>>> */
+ /**
+ * @param pageIdx Page index.
+ * @return Number of segment.
+ */
+ private int segmentIdx(int pageIdx) {
+ return (pageIdx >> idxBits) & segMask;
+ }
+
+ /**
+ * @param pageIdx Page index.
+ * @return Number of page inside segment.
+ */
+ private int inSegmentPageIdx(int pageIdx) {
+ return pageIdx & idxMask;
+ }
+ /* <<<< */
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageEvictionTracker.java
new file mode 100644
index 0000000..b13dcf8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/PageEvictionTracker.java
@@ -0,0 +1,52 @@
+/*
+* 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.database.evict;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.lifecycle.LifecycleAware;
+
+/**
+ * Entry point for per-page eviction. Accepts information about touching data pages,
+ * capable of evicting "the least needed" page (according to implemented eviction algorithm).
+ */
+public interface PageEvictionTracker extends LifecycleAware {
+ /**
+ * Call this method when data page is accessed.
+ *
+ * @param pageId Page id.
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void touchPage(long pageId) throws IgniteCheckedException;
+
+ /**
+ * Evicts one data page.
+ * In most cases, all entries will be removed from the page.
+ * Method guarantees removing at least one entry from "evicted" data page. Removing all entries may be
+ * not possible, as some of them can be used by active transactions.
+ *
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void evictDataPage() throws IgniteCheckedException;
+
+ /**
+ * Call this method when last entry is removed from data page.
+ *
+ * @param pageId Page id.
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void forgetPage(long pageId) throws IgniteCheckedException;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/Random2LruPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/Random2LruPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/Random2LruPageEvictionTracker.java
new file mode 100644
index 0000000..f0ad813
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/Random2LruPageEvictionTracker.java
@@ -0,0 +1,180 @@
+/*
+* 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.database.evict;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.internal.LT;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public class Random2LruPageEvictionTracker extends PageAbstractEvictionTracker {
+ /** Evict attempts limit. */
+ private static final int EVICT_ATTEMPTS_LIMIT = 30;
+
+ /** LRU Sample size. */
+ private static final int SAMPLE_SIZE = 5;
+
+ /** Maximum sample search spin count */
+ private static final int SAMPLE_SPIN_LIMIT = SAMPLE_SIZE * 1000;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /** Tracking array ptr. */
+ private long trackingArrPtr;
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Policy config.
+ * @param sharedCtx Shared context.
+ */
+ public Random2LruPageEvictionTracker(
+ PageMemory pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext<?, ?> sharedCtx
+ ) {
+ super(pageMem, plcCfg, sharedCtx);
+
+ MemoryConfiguration memCfg = sharedCtx.kernalContext().config().getMemoryConfiguration();
+
+ assert plcCfg.getSize() / memCfg.getPageSize() < Integer.MAX_VALUE;
+
+ log = sharedCtx.logger(getClass());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ trackingArrPtr = GridUnsafe.allocateMemory(trackingSize * 8);
+
+ GridUnsafe.setMemory(trackingArrPtr, trackingSize * 8, (byte)0);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ GridUnsafe.freeMemory(trackingArrPtr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void touchPage(long pageId) throws IgniteCheckedException {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ long latestTs = compactTimestamp(U.currentTimeMillis());
+
+ assert latestTs >= 0 && latestTs < Integer.MAX_VALUE;
+
+ boolean success;
+
+ do {
+ int trackingIdx = trackingIdx(pageIdx);
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ int secondTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8 + 4);
+
+ if (firstTs <= secondTs)
+ success = GridUnsafe.compareAndSwapInt(null, trackingArrPtr + trackingIdx * 8, firstTs, (int)latestTs);
+ else {
+ success = GridUnsafe.compareAndSwapInt(
+ null, trackingArrPtr + trackingIdx * 8 + 4, secondTs, (int)latestTs);
+ }
+ } while (!success);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void evictDataPage() throws IgniteCheckedException {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ int evictAttemptsCnt = 0;
+
+ while (evictAttemptsCnt < EVICT_ATTEMPTS_LIMIT) {
+ int lruTrackingIdx = -1;
+
+ int lruCompactTs = Integer.MAX_VALUE;
+
+ int dataPagesCnt = 0;
+
+ int sampleSpinCnt = 0;
+
+ while (dataPagesCnt < SAMPLE_SIZE) {
+ int trackingIdx = rnd.nextInt(trackingSize);
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ int secondTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8 + 4);
+
+ int minTs = Math.min(firstTs, secondTs);
+
+ int maxTs = Math.max(firstTs, secondTs);
+
+ if (maxTs != 0) {
+ // We chose data page with at least one touch.
+ if (minTs < lruCompactTs) {
+ lruTrackingIdx = trackingIdx;
+
+ lruCompactTs = minTs;
+ }
+
+ dataPagesCnt++;
+ }
+
+ sampleSpinCnt++;
+
+ if (sampleSpinCnt > SAMPLE_SPIN_LIMIT) {
+ LT.warn(log, "Too many attempts to choose data page: " + SAMPLE_SPIN_LIMIT);
+
+ return;
+ }
+ }
+
+ if (evictDataPage(pageIdx(lruTrackingIdx)))
+ return;
+
+ evictAttemptsCnt++;
+ }
+
+ LT.warn(log, "Too many failed attempts to evict page: " + EVICT_ATTEMPTS_LIMIT);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean checkTouch(long pageId) {
+ int trackingIdx = trackingIdx(PageIdUtils.pageIndex(pageId));
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ return firstTs != 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void forgetPage(long pageId) {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ int trackingIdx = trackingIdx(pageIdx);
+
+ GridUnsafe.putLongVolatile(null, trackingArrPtr + trackingIdx * 8, 0L);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/RandomLruPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/RandomLruPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/RandomLruPageEvictionTracker.java
new file mode 100644
index 0000000..8818b1c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/evict/RandomLruPageEvictionTracker.java
@@ -0,0 +1,157 @@
+/*
+* 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.database.evict;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.internal.LT;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public class RandomLruPageEvictionTracker extends PageAbstractEvictionTracker {
+ /** Evict attempts limit. */
+ private static final int EVICT_ATTEMPTS_LIMIT = 30;
+
+ /** LRU Sample size. */
+ private static final int SAMPLE_SIZE = 5;
+
+ /** Maximum sample search spin count */
+ private static final int SAMPLE_SPIN_LIMIT = SAMPLE_SIZE * 1000;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /** Tracking array ptr. */
+ private long trackingArrPtr;
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Policy config.
+ * @param sharedCtx Shared context.
+ */
+ public RandomLruPageEvictionTracker(
+ PageMemory pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext<?, ?> sharedCtx
+ ) {
+ super(pageMem, plcCfg, sharedCtx);
+
+ MemoryConfiguration memCfg = sharedCtx.kernalContext().config().getMemoryConfiguration();
+
+ assert plcCfg.getSize() / memCfg.getPageSize() < Integer.MAX_VALUE;
+
+ log = sharedCtx.logger(getClass());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ trackingArrPtr = GridUnsafe.allocateMemory(trackingSize * 4);
+
+ GridUnsafe.setMemory(trackingArrPtr, trackingSize * 4, (byte)0);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ GridUnsafe.freeMemory(trackingArrPtr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void touchPage(long pageId) throws IgniteCheckedException {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ long res = compactTimestamp(U.currentTimeMillis());
+
+ assert res >= 0 && res < Integer.MAX_VALUE;
+
+ GridUnsafe.putIntVolatile(null, trackingArrPtr + trackingIdx(pageIdx) * 4, (int)res);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void evictDataPage() throws IgniteCheckedException {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ int evictAttemptsCnt = 0;
+
+ while (evictAttemptsCnt < EVICT_ATTEMPTS_LIMIT) {
+ int lruTrackingIdx = -1;
+
+ int lruCompactTs = Integer.MAX_VALUE;
+
+ int dataPagesCnt = 0;
+
+ int sampleSpinCnt = 0;
+
+ while (dataPagesCnt < SAMPLE_SIZE) {
+ int sampleTrackingIdx = rnd.nextInt(trackingSize);
+
+ int compactTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + sampleTrackingIdx * 4);
+
+ if (compactTs != 0) {
+ // We chose data page with at least one touch.
+ if (compactTs < lruCompactTs) {
+ lruTrackingIdx = sampleTrackingIdx;
+
+ lruCompactTs = compactTs;
+ }
+
+ dataPagesCnt++;
+ }
+
+ sampleSpinCnt++;
+
+ if (sampleSpinCnt > SAMPLE_SPIN_LIMIT) {
+ LT.warn(log, "Too many attempts to choose data page: " + SAMPLE_SPIN_LIMIT);
+
+ return;
+ }
+ }
+
+ if (evictDataPage(pageIdx(lruTrackingIdx)))
+ return;
+
+ evictAttemptsCnt++;
+ }
+
+ LT.warn(log, "Too many failed attempts to evict page: " + EVICT_ATTEMPTS_LIMIT);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean checkTouch(long pageId) {
+ int trackingIdx = trackingIdx(PageIdUtils.pageIndex(pageId));
+
+ int ts = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 4);
+
+ return ts != 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void forgetPage(long pageId) {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ GridUnsafe.putIntVolatile(null, trackingArrPtr + trackingIdx(pageIdx) * 4, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ff5b3e16/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeListImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeListImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeListImpl.java
index d433172..cb68f7b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeListImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeListImpl.java
@@ -22,7 +22,6 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.pagemem.PageIdUtils;
-import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.PageUtils;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertFragmentRecord;
@@ -31,6 +30,8 @@ import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageRemoveRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageUpdateRecord;
import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl;
+import org.apache.ignite.internal.processors.cache.database.MemoryPolicy;
+import org.apache.ignite.internal.processors.cache.database.evict.PageEvictionTracker;
import org.apache.ignite.internal.processors.cache.database.tree.io.CacheVersionIO;
import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO;
import org.apache.ignite.internal.processors.cache.database.tree.io.DataPagePayload;
@@ -71,17 +72,22 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
private final int MIN_SIZE_FOR_DATA_PAGE;
/** */
+ private final int emptyDataPagesBucket;
+
+ /** */
private final PageHandler<CacheDataRow, Boolean> updateRow = new UpdateRowHandler();
/** */
private final MemoryMetricsImpl memMetrics;
+ /** */
+ private final PageEvictionTracker evictionTracker;
+
/**
*
*/
private final class UpdateRowHandler extends PageHandler<CacheDataRow, Boolean> {
- @Override
- public Boolean run(
+ @Override public Boolean run(
int cacheId,
long pageId,
long page,
@@ -97,6 +103,8 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
boolean updated = io.updateRow(pageAddr, itemId, pageSize(), null, row, rowSize);
+ evictionTracker.touchPage(pageId);
+
if (updated && needWalDeltaRecord(pageId, page, walPlc)) {
// TODO This record must contain only a reference to a logical WAL record with the actual data.
byte[] payload = new byte[rowSize];
@@ -125,8 +133,7 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
*
*/
private final class WriteRowHandler extends PageHandler<CacheDataRow, Integer> {
- @Override
- public Integer run(
+ @Override public Integer run(
int cacheId,
long pageId,
long page,
@@ -156,6 +163,9 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
put(null, pageId, page, pageAddr, bucket);
}
+ if (written == rowSize)
+ evictionTracker.touchPage(pageId);
+
// Avoid boxing with garbage generation for usual case.
return written == rowSize ? COMPLETE : written;
}
@@ -287,6 +297,9 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
}
else
put(null, pageId, page, pageAddr, newBucket);
+
+ if (io.isEmpty(pageAddr))
+ evictionTracker.forgetPage(pageId);
}
// For common case boxed 0L will be cached inside of Long, so no garbage will be produced.
@@ -297,8 +310,8 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
/**
* @param cacheId Cache ID.
* @param name Name (for debug purpose).
- * @param pageMem Page memory.
* @param memMetrics Memory metrics.
+ * @param memPlc Memory policy.
* @param reuseList Reuse list or {@code null} if this free list will be a reuse list for itself.
* @param wal Write ahead log manager.
* @param metaPageId Metadata page ID.
@@ -308,13 +321,14 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
public FreeListImpl(
int cacheId,
String name,
- PageMemory pageMem,
MemoryMetricsImpl memMetrics,
+ MemoryPolicy memPlc,
ReuseList reuseList,
IgniteWriteAheadLogManager wal,
long metaPageId,
boolean initNew) throws IgniteCheckedException {
- super(cacheId, name, pageMem, BUCKETS, wal, metaPageId);
+ super(cacheId, name, memPlc.pageMemory(), BUCKETS, wal, metaPageId);
+ this.evictionTracker = memPlc.evictionTracker();
this.reuseList = reuseList == null ? this : reuseList;
int pageSize = pageMem.pageSize();
@@ -337,6 +351,8 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
this.memMetrics = memMetrics;
+ emptyDataPagesBucket = bucket(MIN_SIZE_FOR_DATA_PAGE, false);
+
init(metaPageId, initNew);
}
@@ -446,25 +462,26 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
int freeSpace = Math.min(MIN_SIZE_FOR_DATA_PAGE, rowSize - written);
- int bucket = bucket(freeSpace, false);
+ long pageId = 0L;
+
+ if (freeSpace == MIN_SIZE_FOR_DATA_PAGE)
+ pageId = takeEmptyPage(emptyDataPagesBucket, DataPageIO.VERSIONS);
- long pageId = 0;
boolean reuseBucket = false;
// TODO: properly handle reuse bucket.
- for (int b = bucket + 1; b < BUCKETS - 1; b++) {
- pageId = takeEmptyPage(b, DataPageIO.VERSIONS);
+ if (pageId == 0L) {
+ for (int b = bucket(freeSpace, false) + 1; b < BUCKETS - 1; b++) {
+ pageId = takeEmptyPage(b, DataPageIO.VERSIONS);
- if (pageId != 0L) {
- reuseBucket = isReuseBucket(b);
+ if (pageId != 0L) {
+ reuseBucket = isReuseBucket(b);
- break;
+ break;
+ }
}
}
- if (pageId == 0L)
- pageId = takeEmptyPage(bucket, DataPageIO.VERSIONS);
-
boolean allocated = pageId == 0L;
if (allocated)
@@ -531,6 +548,13 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
return bucket == REUSE_BUCKET;
}
+ /**
+ * @return Number of empty data pages in free list.
+ */
+ public int emptyDataPages() {
+ return bucketsSize[emptyDataPagesBucket].intValue();
+ }
+
/** {@inheritDoc} */
@Override public void addForRecycle(ReuseBag bag) throws IgniteCheckedException {
assert reuseList == this: "not allowed to be a reuse list";
@@ -561,7 +585,7 @@ public class FreeListImpl extends PagesList implements FreeList, ReuseList {
int keyLen = row.key().valueBytesLength(null);
int valLen = row.value().valueBytesLength(null);
- return keyLen + valLen + CacheVersionIO.size(row.version(), false) + 8;
+ return keyLen + valLen + CacheVersionIO.size(row.version(), false) + 8 + (row.cacheId() == 0 ? 0 : 4);
}
/** {@inheritDoc} */