| /* |
| * 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 java.util.Map; |
| import org.apache.ignite.IgniteCache; |
| import org.apache.ignite.cache.CacheEntry; |
| import org.apache.ignite.cache.query.QueryCursor; |
| import org.apache.ignite.cache.query.ScanQuery; |
| import org.apache.ignite.cluster.ClusterState; |
| import org.apache.ignite.configuration.CacheConfiguration; |
| import org.apache.ignite.lang.IgniteBiTuple; |
| import org.apache.ignite.transactions.Transaction; |
| import org.apache.ignite.transactions.TransactionConcurrency; |
| import org.apache.ignite.transactions.TransactionIsolation; |
| import org.junit.Test; |
| |
| import static java.lang.String.valueOf; |
| import static java.util.Arrays.asList; |
| import static java.util.Collections.singleton; |
| import static java.util.stream.Collectors.toMap; |
| import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT; |
| import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC; |
| |
| /** |
| * Tests most of public API methods of {@link IgniteCache} when cluster in a {@link ClusterState#ACTIVE_READ_ONLY} state. |
| */ |
| public class IgniteCacheClusterReadOnlyModeSelfTest extends IgniteCacheClusterReadOnlyModeAbstractTest { |
| /** */ |
| @Test |
| public void testGetAndPutIfAbsentDeniedIfKeyIsPresented() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutIfAbsent(KEY, VAL)); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndPutIfAbsentDeniedIfKeyIsAbsent() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutIfAbsent(UNKNOWN_KEY, VAL)); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndPutIfAbsentAsyncDeniedIfKeyIsPresented() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutIfAbsentAsync(KEY, VAL).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndPutIfAbsentAsyncDeniedIfKeyIsAbsent() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutIfAbsentAsync(UNKNOWN_KEY, VAL).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testLockDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.lock(KEY).lock(), TX_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testLockAllDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.lockAll(asList(KEY, KEY_2)).lock(), TX_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testScanQueryAllowed() { |
| performAction(cache -> { |
| try (QueryCursor qry = cache.query(new ScanQuery<>())) { |
| for (Object o : qry.getAll()) { |
| IgniteBiTuple<Integer, Integer> tuple = (IgniteBiTuple<Integer, Integer>)o; |
| |
| assertEquals(o.toString(), kvMap.get(tuple.getKey()), tuple.getValue()); |
| } |
| } |
| }); |
| } |
| |
| /** */ |
| @Test |
| public void testSizeAllowed() { |
| performAction(cache -> assertEquals(kvMap.size(), cache.size())); |
| } |
| |
| /** */ |
| @Test |
| public void testSizeAsyncAllowed() { |
| performAction(cache -> assertEquals(kvMap.size(), (long)cache.sizeAsync().get())); |
| } |
| |
| /** */ |
| @Test |
| public void testSizeLongAllowed() { |
| performAction(cache -> assertEquals(kvMap.size(), cache.sizeLong())); |
| } |
| |
| /** */ |
| @Test |
| public void testSizeLongAsyncAllowed() { |
| performAction(cache -> assertEquals(kvMap.size(), (long)cache.sizeLongAsync().get())); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAllowed() { |
| performAction(cache -> assertEquals(VAL, (int)cache.get(KEY))); |
| performAction(cache -> assertNull(cache.get(UNKNOWN_KEY))); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAsyncAllowed() { |
| performAction(cache -> assertEquals(VAL, (int)cache.getAsync(KEY).get())); |
| performAction(cache -> assertNull(cache.getAsync(UNKNOWN_KEY).get())); |
| } |
| |
| /** */ |
| @Test |
| public void testGetEntryAllowed() { |
| performAction(cache -> { |
| CacheEntry entry = cache.getEntry(KEY); |
| |
| assertEquals(KEY, entry.getKey()); |
| assertEquals(VAL, entry.getValue()); |
| }); |
| |
| performAction(cache -> assertNull(cache.getEntry(UNKNOWN_KEY))); |
| } |
| |
| /** */ |
| @Test |
| public void testGetEntryAsyncAllowed() { |
| performAction(cache -> { |
| CacheEntry entry = cache.getEntryAsync(KEY).get(); |
| |
| assertEquals(KEY, entry.getKey()); |
| assertEquals(VAL, entry.getValue()); |
| }); |
| |
| performAction(cache -> assertNull(cache.getEntryAsync(UNKNOWN_KEY).get())); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAllAllowed() { |
| performAction(cache -> assertEquals(kvMap, cache.getAll(kvMap.keySet()))); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAllAsyncAllowed() { |
| performAction(cache -> assertEquals(kvMap, (cache.getAllAsync(kvMap.keySet()).get()))); |
| } |
| |
| /** */ |
| @Test |
| public void testGetEntriesAllowed() { |
| performAction(cache -> { |
| for (Object o : cache.getEntries(kvMap.keySet())) { |
| CacheEntry<Integer, Integer> entry = (CacheEntry<Integer, Integer>)o; |
| |
| assertEquals(kvMap.get(entry.getKey()), entry.getValue()); |
| } |
| }); |
| } |
| |
| /** */ |
| @Test |
| public void testGetEntriesAsyncAllowed() { |
| performAction(cache -> { |
| for (Object o : cache.getEntriesAsync(kvMap.keySet()).get()) { |
| CacheEntry<Integer, Integer> entry = (CacheEntry<Integer, Integer>)o; |
| |
| assertEquals(kvMap.get(entry.getKey()), entry.getValue()); |
| } |
| }); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAllOutTxAllowed() { |
| performAction( |
| (node, cache) -> { |
| for (TransactionConcurrency level : TransactionConcurrency.values()) { |
| for (TransactionIsolation isolation : TransactionIsolation.values()) { |
| CacheConfiguration cfg = cache.getConfiguration(CacheConfiguration.class); |
| |
| if (level == OPTIMISTIC && cfg.getAtomicityMode() == TRANSACTIONAL_SNAPSHOT) { |
| // Only pessimistic transactions are supported when MVCC is enabled. |
| continue; |
| } |
| |
| Transaction tx = node.transactions().txStart(level, isolation); |
| |
| try { |
| cache.get(UNKNOWN_KEY); |
| |
| assertEquals(kvMap, cache.getAllOutTx(kvMap.keySet())); |
| |
| tx.commit(); |
| } |
| catch (Exception e) { |
| RuntimeException ex = new RuntimeException(new AssertionError( |
| "Got exception on node: " + node.name() + " cache: " + cache.getName() + " isolation: " + isolation + |
| " txLevel: " + level, |
| e |
| )); |
| |
| log.error("", ex); |
| |
| tx.rollback(); |
| |
| throw ex; |
| } |
| } |
| } |
| }, |
| TX_CACHES_PRED.or(MVCC_CACHES_PRED) |
| ); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAllOutTxAsyncAllowed() { |
| performAction( |
| (node, cache) -> { |
| for (TransactionConcurrency level : TransactionConcurrency.values()) { |
| for (TransactionIsolation isolation : TransactionIsolation.values()) { |
| CacheConfiguration cfg = cache.getConfiguration(CacheConfiguration.class); |
| |
| if (level == OPTIMISTIC && cfg.getAtomicityMode() == TRANSACTIONAL_SNAPSHOT) { |
| // Only pessimistic transactions are supported when MVCC is enabled. |
| continue; |
| } |
| |
| Transaction tx = node.transactions().txStart(level, isolation); |
| |
| try { |
| cache.get(UNKNOWN_KEY); |
| |
| assertEquals(kvMap, cache.getAllOutTxAsync(kvMap.keySet()).get()); |
| |
| tx.commit(); |
| } |
| catch (Exception e) { |
| RuntimeException ex = new RuntimeException(new AssertionError( |
| "Got exception on node: " + node.name() + " cache: " + cache.getName() + " isolation: " + isolation + |
| " txLevel: " + level, |
| e |
| )); |
| |
| log.error("", ex); |
| |
| tx.rollback(); |
| |
| throw ex; |
| } |
| } |
| } |
| }, |
| TX_CACHES_PRED.or(MVCC_CACHES_PRED) |
| ); |
| } |
| |
| /** */ |
| @Test |
| public void testContainsKeyAllowed() { |
| performAction(cache -> assertTrue(KEY + "", cache.containsKey(KEY))); |
| performAction(cache -> assertFalse(UNKNOWN_KEY + "", cache.containsKey(UNKNOWN_KEY))); |
| } |
| |
| /** */ |
| @Test |
| public void testContainsKeyAsyncAllowed() { |
| performAction(cache -> assertTrue(KEY + "", cache.containsKeyAsync(KEY).get())); |
| performAction(cache -> assertFalse(UNKNOWN_KEY + "", cache.containsKeyAsync(UNKNOWN_KEY).get())); |
| } |
| |
| /** */ |
| @Test |
| public void testContainsKeysAllowed() { |
| performAction(cache -> assertTrue(valueOf(kvMap.keySet()), cache.containsKeys(kvMap.keySet()))); |
| performAction(cache -> assertFalse(UNKNOWN_KEY + "", cache.containsKeys(singleton(UNKNOWN_KEY)))); |
| } |
| |
| /** */ |
| @Test |
| public void testContainsKeysAsyncAllowed() { |
| performAction(cache -> assertTrue(valueOf(kvMap.keySet()), cache.containsKeysAsync(kvMap.keySet()).get())); |
| performAction(cache -> assertFalse(UNKNOWN_KEY + "", cache.containsKeysAsync(singleton(UNKNOWN_KEY)).get())); |
| } |
| |
| /** */ |
| @Test |
| public void testPutDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.put(KEY, VAL + 1)); |
| performActionReadOnlyExceptionExpected(cache -> cache.put(UNKNOWN_KEY, 777)); |
| } |
| |
| /** */ |
| @Test |
| public void testPutAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.putAsync(KEY, VAL + 1).get()); |
| performActionReadOnlyExceptionExpected(cache -> cache.putAsync(UNKNOWN_KEY, 777).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndPutDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPut(KEY, VAL + 1)); |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPut(UNKNOWN_KEY, 777)); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndPutAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutAsync(KEY, VAL + 1).get()); |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndPutAsync(UNKNOWN_KEY, 777).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testPutAllDenied() { |
| Map<Integer, Integer> newMap = kvMap.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> e.getValue() + 1)); |
| |
| performActionReadOnlyExceptionExpected(cache -> cache.putAll(newMap)); |
| } |
| |
| /** */ |
| @Test |
| public void testPutAllAsyncDenied() { |
| Map<Integer, Integer> newMap = kvMap.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> e.getValue() + 1)); |
| |
| performActionReadOnlyExceptionExpected(cache -> cache.putAllAsync(newMap).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testPutIfAbsentDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.putIfAbsent(KEY, VAL + 1)); |
| performActionReadOnlyExceptionExpected(cache -> cache.putIfAbsent(UNKNOWN_KEY, 777)); |
| } |
| |
| /** */ |
| @Test |
| public void testPutIfAbsentAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.putIfAbsentAsync(KEY, VAL + 1).get()); |
| performActionReadOnlyExceptionExpected(cache -> cache.putIfAbsentAsync(UNKNOWN_KEY, 777).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.remove(KEY)); |
| performActionReadOnlyExceptionExpected(cache -> cache.remove(UNKNOWN_KEY)); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAsync(KEY).get()); |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAsync(UNKNOWN_KEY).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveWithOldValueDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.remove(KEY, VAL)); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveWithOldValueAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAsync(KEY, VAL).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndRemoveDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndRemove(KEY)); |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndRemove(UNKNOWN_KEY)); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndRemoveAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndRemoveAsync(KEY).get()); |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndRemoveAsync(UNKNOWN_KEY).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testReplaceWithOldValueDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.replace(KEY, VAL, VAL + 1)); |
| } |
| |
| /** */ |
| @Test |
| public void testReplaceWithOldValueAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.replaceAsync(KEY, VAL, VAL + 1).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testReplaceDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.replace(KEY, VAL + 1)); |
| } |
| |
| /** */ |
| @Test |
| public void testReplaceAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.replaceAsync(KEY, VAL + 1).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndReplaceDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndReplace(KEY, VAL + 1)); |
| } |
| |
| /** */ |
| @Test |
| public void testGetAndReplaceAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.getAndReplaceAsync(KEY, VAL + 1).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveAllWithKeysDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAll(kvMap.keySet())); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveAllWithKeysAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAllAsync(kvMap.keySet()).get()); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveAllDenied() { |
| performActionReadOnlyExceptionExpected(IgniteCache::removeAll); |
| } |
| |
| /** */ |
| @Test |
| public void testRemoveAllAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.removeAllAsync().get()); |
| } |
| |
| /** */ |
| @Test |
| public void testClearDenied() { |
| performActionReadOnlyExceptionExpected(IgniteCache::clear, NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testClearAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.clearAsync().get(), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testClearWithKeyDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.clear(KEY), NO_MVCC_CACHES_PRED); |
| performActionReadOnlyExceptionExpected(cache -> cache.clear(UNKNOWN_KEY), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testClearWithKeyAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.clearAsync(KEY).get(), NO_MVCC_CACHES_PRED); |
| performActionReadOnlyExceptionExpected(cache -> cache.clearAsync(UNKNOWN_KEY).get(), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testClearAllDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.clearAll(kvMap.keySet()), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testClearAllAsyncDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.clearAllAsync(kvMap.keySet()).get(), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testLocalClearDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.localClear(KEY), NO_MVCC_CACHES_PRED); |
| performActionReadOnlyExceptionExpected(cache -> cache.localClear(UNKNOWN_KEY), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testLocalClearAllDenied() { |
| performActionReadOnlyExceptionExpected(cache -> cache.localClearAll(kvMap.keySet()), NO_MVCC_CACHES_PRED); |
| } |
| |
| /** */ |
| @Test |
| public void testCloseAllowed() { |
| performAction((node, cache) -> { |
| assertFalse(cache.isClosed()); |
| |
| cache.close(); |
| |
| assertTrue(cache.isClosed()); |
| }); |
| } |
| } |