/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.processors.cache; import com.google.common.collect.Lists; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.cache.Cache; import javax.cache.expiry.CreatedExpiryPolicy; import javax.cache.expiry.Duration; import javax.cache.integration.CacheLoaderException; import javax.cache.integration.CacheWriterException; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.CachePeekMode; import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction; import org.apache.ignite.cache.store.CacheStore; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; import org.apache.ignite.events.Event; import org.apache.ignite.events.EventType; import org.apache.ignite.internal.processors.cache.store.CacheLocalStore; import org.apache.ignite.internal.util.lang.GridAbsPredicate; import org.apache.ignite.internal.util.typedef.G; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteBiInClosure; import org.apache.ignite.lang.IgniteBiTuple; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.transactions.Transaction; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOCAL_STORE_KEEPS_PRIMARY_ONLY; import static org.apache.ignite.cache.CacheMode.REPLICATED; import static org.apache.ignite.cache.CacheRebalanceMode.SYNC; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC; /** * */ public abstract class GridCacheAbstractLocalStoreSelfTest extends GridCommonAbstractTest { /** */ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_1 = new TestLocalStore<>(); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_2 = new TestLocalStore<>(); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_3 = new TestLocalStore<>(); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_4 = new TestLocalStore<>(); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_5 = new TestLocalStore<>(); /** */ public static final TestLocalStore<Integer, Integer> LOCAL_STORE_6 = new TestLocalStore<>(); /** */ public static final int KEYS = 1025; /** */ public static final String BACKUP_CACHE_1 = "backup_1"; /** */ public static final String BACKUP_CACHE_2 = "backup_2"; /** */ public static volatile boolean near = false; /** * */ public GridCacheAbstractLocalStoreSelfTest() { super(false /* doesn't start grid */); } /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); CacheConfiguration cacheCfg = cache(igniteInstanceName, DEFAULT_CACHE_NAME, 0); cacheCfg.setAffinity(new RendezvousAffinityFunction()); CacheConfiguration cacheBackup1Cfg = cache(igniteInstanceName, BACKUP_CACHE_1, 1); cacheBackup1Cfg.setAffinity(new RendezvousAffinityFunction()); CacheConfiguration cacheBackup2Cfg = cache(igniteInstanceName, BACKUP_CACHE_2, 2); cacheBackup2Cfg.setAffinity(new RendezvousAffinityFunction()); cfg.setCacheConfiguration(cacheCfg, cacheBackup1Cfg, cacheBackup2Cfg); TcpDiscoverySpi spi = new TcpDiscoverySpi(); spi.setIpFinder(IP_FINDER); cfg.setDiscoverySpi(spi); return cfg; } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { super.afterTest(); stopAllGrids(); LOCAL_STORE_1.clear(); LOCAL_STORE_2.clear(); LOCAL_STORE_3.clear(); LOCAL_STORE_4.clear(); LOCAL_STORE_5.clear(); LOCAL_STORE_6.clear(); } /** * @param igniteInstanceName Ignite instance name. * @param cacheName Cache name. * @param backups Number of backups. * @return Configuration. */ @SuppressWarnings("unchecked") private CacheConfiguration cache(String igniteInstanceName, String cacheName, int backups) { CacheConfiguration cacheCfg = new CacheConfiguration(); cacheCfg.setName(cacheName); cacheCfg.setCacheMode(getCacheMode()); cacheCfg.setAtomicityMode(getAtomicMode()); cacheCfg.setNearConfiguration(nearConfiguration()); cacheCfg.setWriteSynchronizationMode(FULL_SYNC); cacheCfg.setRebalanceMode(SYNC); if (igniteInstanceName.endsWith("1")) cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_1)); else if (igniteInstanceName.endsWith("2")) cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_2)); else if (igniteInstanceName.endsWith("3")) cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_3)); else if (igniteInstanceName.endsWith("4")) cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_4)); else if (igniteInstanceName.endsWith("5")) cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_5)); else cacheCfg.setCacheStoreFactory(singletonFactory(LOCAL_STORE_6)); cacheCfg.setWriteThrough(true); cacheCfg.setReadThrough(true); cacheCfg.setBackups(backups); return cacheCfg; } /** * @return Distribution mode. */ protected NearCacheConfiguration nearConfiguration() { return near ? new NearCacheConfiguration() : null; } /** * @return Cache atomicity mode. */ protected abstract CacheAtomicityMode getAtomicMode(); /** * @return Cache mode. */ protected abstract CacheMode getCacheMode(); /** {@inheritDoc} */ @Override protected void afterTestsStopped() throws Exception { stopAllGrids(); } /** * @throws Exception If failed. */ public void testEvict() throws Exception { Ignite ignite1 = startGrid(1); IgniteCache<Object, Object> cache = ignite1.cache(DEFAULT_CACHE_NAME).withExpiryPolicy(new CreatedExpiryPolicy( new Duration(TimeUnit.MILLISECONDS, 100L))); // Putting entry. for (int i = 0; i < KEYS; i++) cache.put(i, i); // Wait when entry U.sleep(200); // Check that entry is evicted from cache, but local store does contain it. for (int i = 0; i < KEYS; i++) { cache.localEvict(Arrays.asList(i)); assertNull(cache.localPeek(i)); assertEquals(i, (int)LOCAL_STORE_1.load(i).get1()); assertEquals(i, cache.get(i)); } } /** * @throws Exception If failed. */ public void testPrimaryNode() throws Exception { Ignite ignite1 = startGrid(1); IgniteCache<Object, Object> cache = ignite1.cache(DEFAULT_CACHE_NAME); // Populate cache and check that local store has all value. for (int i = 0; i < KEYS; i++) cache.put(i, i); checkLocalStore(ignite1, LOCAL_STORE_1, DEFAULT_CACHE_NAME); final AtomicInteger evtCnt = new AtomicInteger(0); if (getCacheMode() != REPLICATED) { ignite1.events().localListen(new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { evtCnt.incrementAndGet(); return true; } }, EventType.EVT_CACHE_REBALANCE_PART_UNLOADED); } final Ignite ignite2 = startGrid(2); if (getCacheMode() != REPLICATED) { boolean wait = GridTestUtils.waitForCondition(new GridAbsPredicate() { @Override public boolean apply() { // Partition count which must be transferred to 2'nd node. int parts = ignite2.affinity(DEFAULT_CACHE_NAME).allPartitions(ignite2.cluster().localNode()).length; return evtCnt.get() >= parts; } }, 5000); assertTrue(wait); } assertEquals(Ignition.allGrids().size(), 2); checkLocalStore(ignite1, LOCAL_STORE_1, DEFAULT_CACHE_NAME); checkLocalStore(ignite2, LOCAL_STORE_2, DEFAULT_CACHE_NAME); } /** * @throws Exception If failed. */ public void testBackupRestorePrimary() throws Exception { testBackupRestore(); } /** * @throws Exception If failed. */ public void testBackupRestore() throws Exception { Ignite ignite1 = startGrid(1); Ignite ignite2 = startGrid(2); awaitPartitionMapExchange(); final String name = BACKUP_CACHE_2; int key1 = -1; int key2 = -1; for (int i = 0; i < KEYS; i++) { if (ignite1.affinity(name).isPrimary(ignite1.cluster().localNode(), i)) { key1 = i; break; } } for (int i = 0; i < KEYS; i++) { if (!ignite1.affinity(name).isPrimary(ignite1.cluster().localNode(), i)) { key2 = i; break; } } assertTrue(key1 >= 0); assertTrue(key2 >= 0); assertNotSame(key1, key2); assertEquals(0, ignite1.cache(name).size()); assertEquals(0, LOCAL_STORE_1.map.size()); assertEquals(0, LOCAL_STORE_2.map.size()); try (Transaction tx = ignite1.transactions().txStart()) { ignite1.cache(name).put(key1, key1); ignite1.cache(name).put(key2, key2); Map<Integer, Integer> m = new HashMap<>(); for (int i = KEYS; i < KEYS + 100; i++) m.put(i, i); ignite1.cache(name).putAll(m); tx.commit(); } assertEquals(102, LOCAL_STORE_1.map.size()); assertEquals(102, LOCAL_STORE_2.map.size()); stopGrid(1); assertEquals(1, G.allGrids().size()); assertEquals(key1, ignite2.cache(name).get(key1)); assertEquals(key2, ignite2.cache(name).get(key2)); for (int i = KEYS; i < KEYS + 100; i++) assertEquals(i, ignite2.cache(name).get(i)); assertEquals(102, LOCAL_STORE_1.map.size()); assertEquals(102, LOCAL_STORE_2.map.size()); assert GridTestUtils.waitForCondition(new GridAbsPredicate() { @Override public boolean apply() { return ignite(2).cache(name).size() == 102; } }, 5000); stopGrid(2); assertEquals(0, G.allGrids().size()); assertEquals(102, LOCAL_STORE_1.map.size()); assertEquals(102, LOCAL_STORE_2.map.size()); // Node restart. One node should have everything at local store. ignite2 = startGrid(2); assertEquals(1, G.allGrids().size()); assertEquals(key1, ignite2.cache(name).get(key1)); assertEquals(key2, ignite2.cache(name).get(key2)); for (int i = KEYS; i < KEYS + 100; i++) assertEquals(i, ignite2.cache(name).get(i)); assertEquals(102, ignite2.cache(name).size()); assertEquals(102, LOCAL_STORE_1.map.size()); assertEquals(102, LOCAL_STORE_2.map.size()); } /** * @throws Exception If failed. */ public void testLocalStoreCorrespondsAffinityWithBackups() throws Exception { testLocalStoreCorrespondsAffinity(BACKUP_CACHE_2); } /** * @throws Exception If failed. */ public void testLocalStoreCorrespondsAffinityWithBackup() throws Exception { testLocalStoreCorrespondsAffinity(BACKUP_CACHE_1); } /** * @throws Exception If failed. */ public void testLocalStoreCorrespondsAffinityNoBackups() throws Exception { testLocalStoreCorrespondsAffinity(DEFAULT_CACHE_NAME); } /** * @throws Exception If failed. */ private void testLocalStoreCorrespondsAffinity(String name) throws Exception { near = true; try { for (int i = 1; i <= 6; i++) startGrid(i); assertTrue(((IgniteCacheProxy)grid(1).cache(name)).context().isNear() || getCacheMode() == REPLICATED); awaitPartitionMapExchange(); Random rn = new Random(); for (int i = 1; i <= 6; i++) assertEquals(0, grid(i).cache(name).localSize(CachePeekMode.NEAR)); for (int i = 0; i < KEYS; i++) { Ignite ignite = grid(rn.nextInt(6) + 1); try (Transaction tx = ignite.transactions().txStart()) { ignite.cache(name).put(i, i); for (int j = 0; j < 5; j++) ignite.cache(name).get(rn.nextInt(KEYS)); Map<Integer, Integer> m = new HashMap<>(5); for (int j = 0; j < 5; j++) { Integer key = rn.nextInt(KEYS); m.put(key, key); } ignite.cache(name).putAll(m); tx.commit(); } } for (int i = 1; i <= 6; i++) { assertTrue(grid(i).cache(name).localSize(CachePeekMode.NEAR) > 0 || getCacheMode() == REPLICATED); } checkLocalStore(grid(1), LOCAL_STORE_1, name); checkLocalStore(grid(2), LOCAL_STORE_2, name); checkLocalStore(grid(3), LOCAL_STORE_3, name); checkLocalStore(grid(4), LOCAL_STORE_4, name); checkLocalStore(grid(5), LOCAL_STORE_5, name); checkLocalStore(grid(6), LOCAL_STORE_6, name); int fullStoreSize = LOCAL_STORE_1.map.size() + LOCAL_STORE_2.map.size() + LOCAL_STORE_3.map.size() + LOCAL_STORE_4.map.size() + LOCAL_STORE_5.map.size() + LOCAL_STORE_6.map.size(); CacheConfiguration ccfg = grid(1).cache(name).getConfiguration(CacheConfiguration.class); assertEquals( getCacheMode() == REPLICATED ? KEYS * 6 : ccfg.getBackups() * KEYS + KEYS, fullStoreSize); } finally { near = false; } } /** * @throws Exception If failed. */ public void testLocalStoreWithNearKeysPrimary() throws Exception { try { System.setProperty(IGNITE_LOCAL_STORE_KEEPS_PRIMARY_ONLY, "true"); testLocalStoreWithNearKeys(); } finally { System.setProperty(IGNITE_LOCAL_STORE_KEEPS_PRIMARY_ONLY, "false"); } } /** * @throws Exception If failed. */ public void testLocalStoreWithNearKeysPrimaryAndBackups() throws Exception { testLocalStoreWithNearKeys(); } /** * @throws Exception If failed. */ public void testLocalStoreWithNearKeys() throws Exception { if (getCacheMode() == REPLICATED) return; near = true; try { for (int i = 1; i <= 3; i++) startGrid(i); awaitPartitionMapExchange(); Ignite ignite = grid(1); int k = 0; for (int i = 1; i <= 3; i++) { int kP = -1; int kB = -1; int kN = -1; while (kP == -1 || kB == -1 || kN == -1) { if (ignite.affinity(BACKUP_CACHE_1).isPrimary(grid(1).cluster().localNode(), k)) kP = k; if (ignite.affinity(BACKUP_CACHE_1).isBackup(grid(1).cluster().localNode(), k) && ignite.affinity(BACKUP_CACHE_1).isPrimary(grid(2).cluster().localNode(), k)) kB = k; if (!ignite.affinity(BACKUP_CACHE_1).isPrimaryOrBackup(grid(1).cluster().localNode(), k) && ignite.affinity(BACKUP_CACHE_1).isPrimary(grid(3).cluster().localNode(), k)) kN = k; k++; } assertTrue(kP != kB && kB != kN && kN != kP); Map<Integer, Integer> m = new HashMap<>(3); m.put(kP, kP); m.put(kB, kB); m.put(kN, kN); try (Transaction tx = grid(i).transactions().txStart()) { grid(i).cache(BACKUP_CACHE_1).putAll(m); tx.commit(); } boolean locStoreBackups = !IgniteSystemProperties.getBoolean(IGNITE_LOCAL_STORE_KEEPS_PRIMARY_ONLY); checkLocalStore(grid(1), LOCAL_STORE_1, BACKUP_CACHE_1, m.keySet(), locStoreBackups); checkLocalStore(grid(2), LOCAL_STORE_2, BACKUP_CACHE_1, m.keySet(), locStoreBackups); checkLocalStore(grid(3), LOCAL_STORE_3, BACKUP_CACHE_1, m.keySet(), locStoreBackups); } grid(1).cache(BACKUP_CACHE_1).removeAll(); Random rn = new Random(); for (int i = 1; i <= 3; i++) { try (Transaction tx = grid(i).transactions().txStart()) { Map<Integer, Integer> m = new HashMap<>(3); for (int j = 0; j < 50; j++) { m.put(rn.nextInt(1000), 1000); } grid(i).cache(BACKUP_CACHE_1).withSkipStore().putAll(m); tx.commit(); } assertTrue(LOCAL_STORE_1.map.isEmpty()); assertTrue(LOCAL_STORE_2.map.isEmpty()); assertTrue(LOCAL_STORE_3.map.isEmpty()); } } finally { near = false; } } /** * @throws Exception If failed. */ public void testBackupNode() throws Exception { Ignite ignite1 = startGrid(1); IgniteCache<Object, Object> cache = ignite1.cache(BACKUP_CACHE_2); for (int i = 0; i < KEYS; i++) cache.put(i, i); for (int i = 0; i < KEYS; i++) { assertEquals(LOCAL_STORE_1.load(i).get1().intValue(), i); assertNull(LOCAL_STORE_2.load(i)); assertNull(LOCAL_STORE_3.load(i)); } startGrid(2); assertEquals(2, Ignition.allGrids().size()); for (int i = 0; i < KEYS; i++) { assertEquals(LOCAL_STORE_1.load(i).get1().intValue(), i); assertEquals(LOCAL_STORE_2.load(i).get1().intValue(), i); assertNull(LOCAL_STORE_3.load(i)); } startGrid(3); assertEquals(Ignition.allGrids().size(), 3); for (int i = 0; i < KEYS; i++) cache.put(i, i * 3); for (int i = 0; i < KEYS; i++) { assertEquals(LOCAL_STORE_1.load(i).get1().intValue(), i * 3); assertEquals(LOCAL_STORE_2.load(i).get1().intValue(), i * 3); assertEquals(LOCAL_STORE_3.load(i).get1().intValue(), i * 3); } // Stop 3'nd node. stopGrid(3, true); for (int i = 0; i < KEYS; i++) cache.put(i, i * 7); assertEquals(Ignition.allGrids().size(), 2); for (int i = 0; i < KEYS; i++) { assertEquals(LOCAL_STORE_1.load(i).get1().intValue(), i * 7); assertEquals(LOCAL_STORE_2.load(i).get1().intValue(), i * 7); assertEquals(LOCAL_STORE_3.load(i).get1().intValue(), i * 3); } startGrid(3); assertEquals(Ignition.allGrids().size(), 3); for (int i = 0; i < KEYS; i++) { assertEquals(LOCAL_STORE_1.load(i).get1().intValue(), i * 7); assertEquals(LOCAL_STORE_2.load(i).get1().intValue(), i * 7); assertEquals(LOCAL_STORE_3.load(i).get1().intValue(), i * 7); } } /** * @throws Exception If failed. */ public void testSwap() throws Exception { Ignite ignite1 = startGrid(1); IgniteCache<Object, Object> cache = ignite1.cache(DEFAULT_CACHE_NAME); // Populate cache and check that local store has all value. for (int i = 0; i < KEYS; i++) cache.put(i, i); checkLocalStore(ignite1, LOCAL_STORE_1, DEFAULT_CACHE_NAME); // Push entry to swap. for (int i = 0; i < KEYS; i++) cache.localEvict(Lists.newArrayList(i)); for (int i = 0; i < KEYS; i++) assertNull(cache.localPeek(i, CachePeekMode.ONHEAP)); final AtomicInteger evtCnt = new AtomicInteger(0); if (getCacheMode() != REPLICATED) { ignite1.events().localListen(new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { evtCnt.incrementAndGet(); return true; } }, EventType.EVT_CACHE_REBALANCE_PART_UNLOADED); } final Ignite ignite2 = startGrid(2); if (getCacheMode() != REPLICATED) { boolean wait = GridTestUtils.waitForCondition(new GridAbsPredicate() { @Override public boolean apply() { // Partition count which must be transferred to 2'nd node. int parts = ignite2.affinity(DEFAULT_CACHE_NAME).allPartitions(ignite2.cluster().localNode()).length; return evtCnt.get() >= parts; } }, 5000); assertTrue(wait); } assertEquals(Ignition.allGrids().size(), 2); checkLocalStore(ignite1, LOCAL_STORE_1, DEFAULT_CACHE_NAME); checkLocalStore(ignite2, LOCAL_STORE_2, DEFAULT_CACHE_NAME); } /** * Checks that local stores contains only primary entry. * @param ignite Ignite. * @param store Store. * @param name Cache name. */ private void checkLocalStore(Ignite ignite, CacheStore<Integer, IgniteBiTuple<Integer, ?>> store, String name) { for (int i = 0; i < KEYS; i++) { if (ignite.affinity(name).isPrimaryOrBackup(ignite.cluster().localNode(), i)) assertEquals(store.load(i).get1().intValue(), i); else assertNull(store.load(i)); } } /** * Checks that local stores contains primary and backup entries. * @param ignite Ignite. * @param store Store. * @param name Cache name. * @param keys keys. */ private void checkLocalStore(Ignite ignite, CacheStore<Integer, IgniteBiTuple<Integer, ?>> store, String name, Set<Integer> keys) { checkLocalStore(ignite, store, name, keys, true); } /** * Checks that local stores contains primary and backup or only primary entries. * * @param ignite Ignite. * @param store Store. * @param name Cache name. * @param keys keys. */ private void checkLocalStore(Ignite ignite, CacheStore<Integer, IgniteBiTuple<Integer, ?>> store, String name, Set<Integer> keys, boolean withBackups) { for (int key : keys) { if (withBackups) { if (ignite.affinity(name).isPrimaryOrBackup(ignite.cluster().localNode(), key)) assertEquals(store.load(key).get1().intValue(), key); else assertNull(store.load(key)); } else { if (ignite.affinity(name).isPrimary(ignite.cluster().localNode(), key)) assertEquals(store.load(key).get1().intValue(), key); else assertNull(store.load(key)); } } } /** * */ @CacheLocalStore public static class TestLocalStore<K, V> implements CacheStore<K, IgniteBiTuple<V, ?>> { /** */ private final Map<K, IgniteBiTuple<V, ?>> map = new ConcurrentHashMap<>(); /** {@inheritDoc} */ @Override public void loadCache(IgniteBiInClosure<K, IgniteBiTuple<V, ?>> clo, @Nullable Object... args) throws CacheLoaderException { // No-op. } /** {@inheritDoc} */ @Override public void sessionEnd(boolean commit) throws CacheWriterException { // No-op. } /** {@inheritDoc} */ @Override public IgniteBiTuple<V, ?> load(K key) throws CacheLoaderException { return map.get(key); } /** {@inheritDoc} */ @Override public Map<K, IgniteBiTuple<V, ?>> loadAll(Iterable<? extends K> keys) throws CacheLoaderException { Map<K, IgniteBiTuple<V, ?>> res = new HashMap<>(); for (K key : keys) { IgniteBiTuple<V, ?> val = map.get(key); if (val != null) res.put(key, val); } return res; } /** {@inheritDoc} */ @Override public void write(Cache.Entry<? extends K, ? extends IgniteBiTuple<V, ?>> entry) throws CacheWriterException { map.put(entry.getKey(), entry.getValue()); } /** {@inheritDoc} */ @Override public void writeAll(Collection<Cache.Entry<? extends K, ? extends IgniteBiTuple<V, ?>>> entries) throws CacheWriterException { for (Cache.Entry<? extends K, ? extends IgniteBiTuple<V, ?>> e : entries) map.put(e.getKey(), e.getValue()); } /** {@inheritDoc} */ @Override public void delete(Object key) throws CacheWriterException { map.remove(key); } /** {@inheritDoc} */ @Override public void deleteAll(Collection<?> keys) throws CacheWriterException { for (Object key : keys) map.remove(key); } /** * Clear store. */ public void clear(){ map.clear(); } } }