/*
* 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.query.continuous;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.MutableEntry;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
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.apache.ignite.transactions.TransactionConcurrency;
import org.apache.ignite.transactions.TransactionIsolation;
import org.jetbrains.annotations.NotNull;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.PRIMARY_SYNC;
import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC;
import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED;
import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
import static org.apache.ignite.transactions.TransactionIsolation.SERIALIZABLE;
/**
*
*/
public class CacheEntryProcessorExternalizableFailedTest extends GridCommonAbstractTest {
/** */
private static final int EXPECTED_VALUE = 42;
/** */
private static final int WRONG_VALUE = -1;
/** */
private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
/** */
private static final int NODES = 3;
/** */
public static final int ITERATION_CNT = 1;
/** */
public static final int KEYS = 10;
/** */
private boolean client;
/** */
private boolean failOnWrite = false;
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
((TcpCommunicationSpi)cfg.getCommunicationSpi()).setSharedMemoryPort(-1);
cfg.setClientMode(client);
return cfg;
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
startGridsMultiThreaded(getServerNodeCount());
client = true;
startGrid(getServerNodeCount());
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
super.afterTestsStopped();
}
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
super.beforeTest();
failOnWrite = false;
}
/**
* @return Server nodes.
*/
private int getServerNodeCount() {
return NODES;
}
/**
* @throws Exception If failed.
*/
public void testOptimisticFullSync() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 2);
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticOnePhaseCommit() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 1);
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticOnePhaseCommitWithNearCache() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 1)
.setNearConfiguration(new NearCacheConfiguration());
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticOnePhaseCommitFullSync() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 1);
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticOnePhaseCommitFullSyncWithNearCache() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 1)
.setNearConfiguration(new NearCacheConfiguration());
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimistic() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 2);
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticWithNearCache() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 2)
.setNearConfiguration(new NearCacheConfiguration());
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testPessimisticFullSync() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 2);
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testOptimisticOnePhaseCommit() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 1);
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testOptimisticOnePhaseCommitFullSync() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 1);
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testOptimisticOnePhaseCommitFullSyncWithNearCache() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 1)
.setNearConfiguration(new NearCacheConfiguration());
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testOptimistic() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(PRIMARY_SYNC, 2);
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @throws Exception If failed.
*/
public void testOptimisticFullSyncWithNearCache() throws Exception {
CacheConfiguration ccfg = cacheConfiguration(FULL_SYNC, 2);
doTestInvokeTest(ccfg, OPTIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, OPTIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, OPTIMISTIC, REPEATABLE_READ);
failOnWrite = true;
doTestInvokeTest(ccfg, PESSIMISTIC, SERIALIZABLE);
doTestInvokeTest(ccfg, PESSIMISTIC, READ_COMMITTED);
doTestInvokeTest(ccfg, PESSIMISTIC, REPEATABLE_READ);
}
/**
* @param ccfg Cache configuration.
* @throws Exception If failed.
*/
private void doTestInvokeTest(CacheConfiguration ccfg, TransactionConcurrency txConcurrency,
TransactionIsolation txIsolation) throws Exception {
IgniteEx cln = grid(getServerNodeCount());
grid(0).createCache(ccfg);
IgniteCache clnCache;
if (ccfg.getNearConfiguration() != null)
clnCache = cln.createNearCache(ccfg.getName(), ccfg.getNearConfiguration());
else
clnCache = cln.cache(ccfg.getName());
putKeys(clnCache, EXPECTED_VALUE);
try {
// Explicit tx.
for (int i = 0; i < ITERATION_CNT; i++) {
try (final Transaction tx = cln.transactions().txStart(txConcurrency, txIsolation)) {
putKeys(clnCache, WRONG_VALUE);
clnCache.invoke(KEYS, createEntryProcessor());
GridTestUtils.assertThrowsWithCause(new Callable<Object>() {
@Override public Object call() throws Exception {
tx.commit();
return null;
}
}, UnsupportedOperationException.class);
}
assertNull(cln.transactions().tx());
checkKeys(clnCache, EXPECTED_VALUE);
}
// From affinity node.
Ignite grid = grid(ThreadLocalRandom.current().nextInt(NODES));
final IgniteCache cache = grid.cache(ccfg.getName());
// Explicit tx.
for (int i = 0; i < ITERATION_CNT; i++) {
try (final Transaction tx = grid.transactions().txStart(txConcurrency, txIsolation)) {
putKeys(cache, WRONG_VALUE);
cache.invoke(KEYS, createEntryProcessor());
GridTestUtils.assertThrowsWithCause(new Callable<Object>() {
@Override public Object call() throws Exception {
tx.commit();
return null;
}
}, UnsupportedOperationException.class);
}
assertNull(cln.transactions().tx());
checkKeys(cache, EXPECTED_VALUE);
}
final IgniteCache clnCache0 = clnCache;
// Implicit tx.
for (int i = 0; i < ITERATION_CNT; i++) {
GridTestUtils.assertThrowsWithCause(new Callable<Object>() {
@Override public Object call() throws Exception {
clnCache0.invoke(KEYS, createEntryProcessor());
return null;
}
}, UnsupportedOperationException.class);
assertNull(cln.transactions().tx());
}
checkKeys(clnCache, EXPECTED_VALUE);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
grid(0).destroyCache(ccfg.getName());
}
}
/**
* @return Entry processor.
*/
@NotNull private EntryProcessor<Integer, Integer, Integer> createEntryProcessor() {
return failOnWrite ? new ExternalizableFailedWriteEntryProcessor() :
new ExternalizableFailedReadEntryProcessor();
}
/**
* @param cache Cache.
* @param val Value.
*/
private void putKeys(IgniteCache cache, int val) {
cache.put(KEYS, val);
}
/**
* @param cache Cache.
* @param expVal Expected value.
*/
private void checkKeys(IgniteCache cache, int expVal) {
assertEquals(expVal, cache.get(KEYS));
}
/**
* @return Cache configuration.
*/
private CacheConfiguration cacheConfiguration(CacheWriteSynchronizationMode wrMode, int backup) {
return new CacheConfiguration("test-cache-" + wrMode + "-" + backup)
.setAtomicityMode(TRANSACTIONAL)
.setWriteSynchronizationMode(FULL_SYNC)
.setBackups(backup);
}
/**
*
*/
private static class ExternalizableFailedWriteEntryProcessor implements EntryProcessor<Integer, Integer, Integer>,
Externalizable{
/** */
public ExternalizableFailedWriteEntryProcessor() {
// No-op.
}
/** {@inheritDoc} */
@Override public Integer process(MutableEntry<Integer, Integer> entry, Object... arguments)
throws EntryProcessorException {
entry.setValue(42);
return null;
}
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// No-op.
}
}
/**
*
*/
private static class ExternalizableFailedReadEntryProcessor implements EntryProcessor<Integer, Integer, Integer>,
Externalizable {
/** */
public ExternalizableFailedReadEntryProcessor() {
// No-op.
}
/** {@inheritDoc} */
@Override public Integer process(MutableEntry<Integer, Integer> entry, Object... arguments)
throws EntryProcessorException {
entry.setValue(42);
return null;
}
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
// No-op.
}
/** {@inheritDoc} */
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
throw new UnsupportedOperationException();
}
}
}