Repository: incubator-ignite Updated Branches: refs/heads/ignite-1 03c17b8f3 -> e248ca73f
Merged GG-9090 into ignite-1 Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/e248ca73 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/e248ca73 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/e248ca73 Branch: refs/heads/ignite-1 Commit: e248ca73f12fddabb5cdd552df25cdbe2817225a Parents: 03c17b8 Author: Alexey Goncharuk <agoncha...@gridgain.com> Authored: Tue Dec 16 18:31:15 2014 -0800 Committer: Alexey Goncharuk <agoncha...@gridgain.com> Committed: Tue Dec 16 18:31:15 2014 -0800 ---------------------------------------------------------------------- .../processors/cache/GridCacheMapEntry.java | 19 ++- .../cache/GridCacheProjectionImpl.java | 12 +- .../distributed/dht/GridDhtCacheEntry.java | 60 ++++++-- .../dht/atomic/GridDhtAtomicCache.java | 63 +++++++- .../cache/GridCacheAbstractFullApiSelfTest.java | 102 +++++++++++++ .../GridCacheNearPartitionedClearSelfTest.java | 142 +++++++++++++++++++ .../bamboo/GridDataGridTestSuite.java | 1 + 7 files changed, 377 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java index eb131fd..bc6e120 100644 --- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java +++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java @@ -1334,10 +1334,18 @@ public abstract class GridCacheMapEntry<K, V> implements GridCacheEntryEx<K, V> } if (cctx.deferredDelete() && !detached() && !isInternal()) { - if (!deletedUnlocked()) + if (!deletedUnlocked()) { deletedUnlocked(true); - enqueueVer = newVer; + if (tx != null) { + GridCacheMvcc<K> mvcc = mvccExtras(); + + if (mvcc == null || mvcc.isEmpty(tx.xidVersion())) + clearReaders(); + else + clearReader(tx.originatingNodeId()); + } + } } drReplicate(drType, null, null, newVer); @@ -2039,6 +2047,13 @@ public abstract class GridCacheMapEntry<K, V> implements GridCacheEntryEx<K, V> // No-op. } + /** + * @param nodeId Node ID to clear. + */ + protected void clearReader(UUID nodeId) throws GridCacheEntryRemovedException { + // No-op. + } + /** {@inheritDoc} */ @Override public boolean clear(GridCacheVersion ver, boolean readers, @Nullable IgnitePredicate<GridCacheEntry<K, V>>[] filter) throws IgniteCheckedException { http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheProjectionImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheProjectionImpl.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheProjectionImpl.java index 67eb9e8..0e7c21c 100644 --- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheProjectionImpl.java +++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheProjectionImpl.java @@ -1045,7 +1045,7 @@ public class GridCacheProjectionImpl<K, V> implements GridCacheProjectionEx<K, V /** {@inheritDoc} */ @Override public IgniteFuture<V> removeAsync(K key, @Nullable GridCacheEntryEx<K, V> entry, @Nullable IgnitePredicate<GridCacheEntry<K, V>>... filter) { - return cache.removeAsync(key, entry, and(filter, true)); + return cache.removeAsync(key, entry, and(filter, false)); } /** {@inheritDoc} */ @@ -1079,7 +1079,7 @@ public class GridCacheProjectionImpl<K, V> implements GridCacheProjectionEx<K, V /** {@inheritDoc} */ @Override public IgniteFuture<Boolean> removexAsync(K key, @Nullable GridCacheEntryEx<K, V> entry, @Nullable IgnitePredicate<GridCacheEntry<K, V>>... filter) { - return cache.removexAsync(key, entry, and(filter, true)); + return cache.removexAsync(key, entry, and(filter, false)); } /** {@inheritDoc} */ @@ -1123,24 +1123,24 @@ public class GridCacheProjectionImpl<K, V> implements GridCacheProjectionEx<K, V /** {@inheritDoc} */ @Override public void removeAll(@Nullable Collection<? extends K> keys, @Nullable IgnitePredicate<GridCacheEntry<K, V>>... filter) throws IgniteCheckedException { - cache.removeAll(keys, and(filter, true)); + cache.removeAll(keys, and(filter, false)); } /** {@inheritDoc} */ @Override public IgniteFuture<?> removeAllAsync(@Nullable Collection<? extends K> keys, @Nullable IgnitePredicate<GridCacheEntry<K, V>>[] filter) { - return cache.removeAllAsync(keys, and(filter, true)); + return cache.removeAllAsync(keys, and(filter, false)); } /** {@inheritDoc} */ @Override public void removeAll(@Nullable IgnitePredicate<GridCacheEntry<K, V>>... filter) throws IgniteCheckedException { - cache.removeAll(and(filter, true)); + cache.removeAll(and(filter, false)); } /** {@inheritDoc} */ @Override public IgniteFuture<?> removeAllAsync(@Nullable IgnitePredicate<GridCacheEntry<K, V>>... filter) { - return cache.removeAllAsync(and(filter, true)); + return cache.removeAllAsync(and(filter, false)); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtCacheEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtCacheEntry.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtCacheEntry.java index be2596d..978b60b 100644 --- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtCacheEntry.java +++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtCacheEntry.java @@ -393,12 +393,13 @@ public class GridDhtCacheEntry<K, V> extends GridDistributedCacheEntry<K, V> { if (reader == null) { reader = new ReaderId<>(nodeId, msgId); - rdrs = new LinkedList<>(rdrs); + List<ReaderId<K, V>> rdrs = new ArrayList<>(this.rdrs.size() + 1); + rdrs.addAll(this.rdrs); rdrs.add(reader); // Seal. - rdrs = Collections.unmodifiableList(rdrs); + this.rdrs = Collections.unmodifiableList(rdrs); // No transactions in ATOMIC cache. if (!cctx.atomic()) { @@ -472,15 +473,18 @@ public class GridDhtCacheEntry<K, V> extends GridDistributedCacheEntry<K, V> { ReaderId reader = readerId(nodeId); - if (reader == null || reader.messageId() > msgId) + if (reader == null || (reader.messageId() > msgId && msgId >= 0)) return false; - rdrs = new LinkedList<>(rdrs); + List<ReaderId<K, V>> rdrs = new ArrayList<>(this.rdrs.size()); - rdrs.remove(reader); + for (ReaderId<K, V> rdr : this.rdrs) { + if (!rdr.equals(reader)) + rdrs.add(rdr); + } // Seal. - rdrs = Collections.unmodifiableList(rdrs); + this.rdrs = rdrs.isEmpty() ? Collections.<ReaderId<K, V>>emptyList() : Collections.unmodifiableList(rdrs); return true; } @@ -492,6 +496,11 @@ public class GridDhtCacheEntry<K, V> extends GridDistributedCacheEntry<K, V> { rdrs = Collections.emptyList(); } + /** {@inheritDoc} */ + @Override public synchronized void clearReader(UUID nodeId) throws GridCacheEntryRemovedException { + removeReader(nodeId, -1); + } + /** * Marks entry as obsolete and, if possible or required, removes it * from swap storage. @@ -553,24 +562,28 @@ public class GridDhtCacheEntry<K, V> extends GridDistributedCacheEntry<K, V> { checkObsolete(); if (!rdrs.isEmpty()) { - List<ReaderId> rmv = null; + Collection<ReaderId> rmv = null; for (ReaderId reader : rdrs) { if (!cctx.discovery().alive(reader.nodeId())) { if (rmv == null) - rmv = new LinkedList<>(); + rmv = new HashSet<>(); rmv.add(reader); } } if (rmv != null) { - rdrs = new LinkedList<>(rdrs); + List<ReaderId<K, V>> rdrs = new ArrayList<>(this.rdrs.size() - rmv.size()); - for (ReaderId rdr : rmv) - rdrs.remove(rdr); + for (ReaderId<K, V> rdr : this.rdrs) { + if (!rmv.contains(rdr)) + rdrs.add(rdr); + } - rdrs = Collections.unmodifiableList(rdrs); + // Seal. + this.rdrs = rdrs.isEmpty() ? Collections.<ReaderId<K, V>>emptyList() : + Collections.unmodifiableList(rdrs); } } @@ -707,6 +720,29 @@ public class GridDhtCacheEntry<K, V> extends GridDistributedCacheEntry<K, V> { return txFut; } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof ReaderId)) + return false; + + ReaderId readerId = (ReaderId)o; + + return msgId == readerId.msgId && nodeId.equals(readerId.nodeId); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = nodeId.hashCode(); + + res = 31 * res + (int)(msgId ^ (msgId >>> 32)); + + return res; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(ReaderId.class, this); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java index 4991adb..b8998e2 100644 --- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java +++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java @@ -13,8 +13,6 @@ import org.apache.ignite.*; import org.apache.ignite.cluster.*; import org.apache.ignite.lang.*; import org.apache.ignite.plugin.security.*; -import org.apache.ignite.portables.*; -import org.gridgain.grid.*; import org.gridgain.grid.cache.*; import org.gridgain.grid.kernal.managers.communication.*; import org.gridgain.grid.kernal.processors.cache.*; @@ -1002,6 +1000,17 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> { // Cannot update in batches during DR due to possible conflicts. assert !req.returnValue(); // Should not request return values for putAll. + if (!F.isEmpty(req.filter())) { + try { + reloadIfNeeded(locked); + } + catch (IgniteCheckedException e) { + res.addFailedKeys(req.keys(), e); + + return new UpdateBatchResult<>(); + } + } + int size = req.keys().size(); Map<K, V> putMap = null; @@ -1244,6 +1253,56 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> { } /** + * @param entries Entries. + * @throws IgniteCheckedException If failed. + */ + private void reloadIfNeeded(final List<GridDhtCacheEntry<K, V>> entries) throws IgniteCheckedException { + Map<K, Integer> needReload = null; + + for (int i = 0; i < entries.size(); i++) { + GridDhtCacheEntry<K, V> entry = entries.get(i); + + if (entry == null) + continue; + + V val = entry.rawGetOrUnmarshal(false); + + if (val == null) { + if (needReload == null) + needReload = new HashMap<>(entries.size(), 1.0f); + + needReload.put(entry.key(), i); + } + } + + if (needReload != null) { + final Map<K, Integer> idxMap = needReload; + + ctx.store().loadAllFromStore(null, needReload.keySet(), new CI2<K, V>() { + @Override public void apply(K k, V v) { + Integer idx = idxMap.get(k); + + if (idx != null) { + GridDhtCacheEntry<K, V> entry = entries.get(idx); + try { + GridCacheVersion ver = entry.version(); + + entry.versionedValue(v, null, ver); + } + catch (GridCacheEntryRemovedException e) { + assert false : "Entry should not get obsolete while holding lock [entry=" + entry + + ", e=" + e + ']'; + } + catch (IgniteCheckedException e) { + throw new IgniteException(e); + } + } + } + }); + } + } + + /** * Updates locked entries one-by-one. * * @param node Originating node. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFullApiSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFullApiSelfTest.java b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFullApiSelfTest.java index a5e5c82..406440b 100644 --- a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFullApiSelfTest.java +++ b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFullApiSelfTest.java @@ -17,6 +17,7 @@ import org.apache.ignite.lang.*; import org.gridgain.grid.*; import org.gridgain.grid.cache.*; import org.apache.ignite.spi.swapspace.inmemory.*; +import org.gridgain.grid.kernal.*; import org.gridgain.grid.util.lang.*; import org.gridgain.grid.util.typedef.*; import org.gridgain.grid.util.typedef.internal.*; @@ -2932,6 +2933,107 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract } /** + * @throws Exception If failed. + */ + public void testRemoveAfterClear() throws Exception { + GridEx grid = grid(0); + + GridCacheDistributionMode distroMode = grid.cache(null).configuration().getDistributionMode(); + + if (distroMode == GridCacheDistributionMode.NEAR_ONLY || distroMode == GridCacheDistributionMode.CLIENT_ONLY) { + if (gridCount() < 2) + return; + + grid = grid(1); + } + + GridCacheProjection<Integer, Integer> cache = grid.cache(null) + .projection(Integer.class, Integer.class); + + int key = 0; + + List<Integer> keys = new ArrayList<>(); + + for (int k = 0; k < 2; k++) { + while (!grid.cache(null).affinity().isPrimary(grid.localNode(), key)) + key++; + + keys.add(key); + + key++; + } + + System.out.println(keys); + + for (Integer k : keys) + cache.put(k, k); + + cache.clear(keys.get(0)); + cache.clear(keys.get(1)); + + for (int g = 0; g < gridCount(); g++) { + Ignite grid0 = grid(g); + + grid0.cache(null).projection(Integer.class, Integer.class).removeAll(); + + assertTrue(grid0.cache(null).isEmpty()); + } + } + + /** + * @throws Exception If failed. + */ + public void testRemoveFilteredAfterClear() throws Exception { + GridEx grid = grid(0); + + GridCacheDistributionMode distroMode = grid.cache(null).configuration().getDistributionMode(); + + if (distroMode == GridCacheDistributionMode.NEAR_ONLY || distroMode == GridCacheDistributionMode.CLIENT_ONLY) { + if (gridCount() < 2) + return; + + grid = grid(1); + } + + GridCacheProjection<Integer, Integer> cache = grid.cache(null); + + List<Integer> keys = new ArrayList<>(); + + int key = 0; + + for (int k = 0; k < 2; k++) { + while (!grid.cache(null).affinity().isPrimary(grid.localNode(), key)) + key++; + + keys.add(key); + + key++; + } + + System.out.println(keys); + + for (Integer k : keys) + cache.put(k, k + 1); + + cache.clear(keys.get(0)); + cache.clear(keys.get(1)); + + for (int g = 0; g < gridCount(); g++) { + Ignite grid0 = grid(g); + + grid0.cache(null).removeAll(new IgnitePredicate<GridCacheEntry<Object,Object>>() { + @Override public boolean apply(GridCacheEntry<Object, Object> e) { + Object val = e.peek(); + + return val instanceof Integer && (Integer)val > 0; + } + }); + + assertTrue(grid0.cache(null).isEmpty()); + } + } + + /** * @throws Exception In case of error. */ public void testClear() throws Exception { http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheNearPartitionedClearSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheNearPartitionedClearSelfTest.java b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheNearPartitionedClearSelfTest.java new file mode 100644 index 0000000..429ff69 --- /dev/null +++ b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheNearPartitionedClearSelfTest.java @@ -0,0 +1,142 @@ +/* @java.file.header */ + +/* _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +package org.gridgain.grid.kernal.processors.cache.distributed.near; + +import org.apache.ignite.*; +import org.apache.ignite.cluster.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.spi.discovery.tcp.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*; +import org.gridgain.grid.cache.*; +import org.gridgain.grid.cache.store.*; +import org.gridgain.grid.kernal.processors.cache.*; +import org.gridgain.grid.util.typedef.*; +import org.gridgain.testframework.junits.common.*; + +import static org.gridgain.grid.cache.GridCacheMode.*; +import static org.gridgain.grid.cache.GridCacheAtomicityMode.*; +import static org.gridgain.grid.cache.GridCacheDistributionMode.*; +import static org.gridgain.grid.cache.GridCachePreloadMode.*; +import static org.gridgain.grid.cache.GridCacheWriteSynchronizationMode.*; + +/** + * Test clear operation in NEAR_PARTITIONED transactional cache. + */ +@SuppressWarnings("unchecked") +public class GridCacheNearPartitionedClearSelfTest extends GridCommonAbstractTest { + /** Grid count. */ + private static final int GRID_CNT = 3; + + /** Backup count. */ + private static final int BACKUP_CNT = 1; + + /** Cache name. */ + private static final String CACHE_NAME = "cache"; + + /** */ + private static GridCacheStore<Object, Object> store = new GridCacheGenericTestStore<>(); + + /** Shared IP finder. */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + startGrids(GRID_CNT); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + G.stopAll(true); + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + cfg.setLocalHost("127.0.0.1"); + + TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); + + discoSpi.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(discoSpi); + + GridCacheConfiguration ccfg = new GridCacheConfiguration(); + + ccfg.setName(CACHE_NAME); + ccfg.setCacheMode(PARTITIONED); + ccfg.setAtomicityMode(TRANSACTIONAL); + ccfg.setDistributionMode(NEAR_PARTITIONED); + ccfg.setPreloadMode(SYNC); + ccfg.setWriteSynchronizationMode(FULL_SYNC); + ccfg.setBackups(BACKUP_CNT); + ccfg.setStore(store); + + cfg.setCacheConfiguration(ccfg); + + return cfg; + } + + /** + * Test clear. + * + * @throws Exception If failed. + */ + public void testClear() throws Exception { + GridCache cache = cacheForIndex(0); + + int key = primaryKey0(grid(0), cache); + + cache.putx(key, 1); + cache.clear(key); + + for (int i = 0; i < GRID_CNT; i++) { + GridCache cache0 = cacheForIndex(i); + + cache0.removeAll(); + + assert cache0.isEmpty(); + } + + cache.putx(key, 1); + cache.clear(key); + + assertEquals(0, cache.size()); + } + + /** + * Gets primary key for the given cache. + * + * @param cache Cache. + * @return Primary key. + * @throws Exception If failed. + */ + private int primaryKey0(Ignite ignite, GridCache cache) throws Exception { + ClusterNode locNode = ignite.cluster().localNode(); + + for (int i = 0; i < Integer.MAX_VALUE; i++) { + if (cache.affinity().isPrimary(locNode, i)) + return i; + } + + throw new Exception("Cannot determine affinity key."); + } + + /** + * Gets cache for the node with the given index. + * + * @param idx Index. + * @return Cache. + */ + private GridCache cacheForIndex(int idx) { + return grid(idx).cache(CACHE_NAME); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e248ca73/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java b/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java index 3059c4e..ea7f77d 100644 --- a/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java +++ b/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java @@ -184,6 +184,7 @@ public class GridDataGridTestSuite extends TestSuite { suite.addTest(new TestSuite(GridCachePartitionedAffinityHashIdResolverSelfTest.class)); suite.addTest(new TestSuite(GridCacheColocatedOptimisticTransactionSelfTest.class)); suite.addTestSuite(GridCacheAtomicMessageCountSelfTest.class); + suite.addTest(new TestSuite(GridCacheNearPartitionedClearSelfTest.class)); suite.addTest(new TestSuite(GridCacheDhtExpiredEntriesPreloadSelfTest.class)); suite.addTest(new TestSuite(GridCacheNearExpiredEntriesPreloadSelfTest.class));