Search in sources :

Example 1 with GridConcurrentHashSet

use of org.apache.ignite.internal.util.GridConcurrentHashSet in project ignite by apache.

the class TxOptimisticDeadlockDetectionTest method doTestDeadlock.

/**
     * @throws Exception If failed.
     */
private void doTestDeadlock(final int txCnt, final boolean loc, boolean lockPrimaryFirst, final boolean clientTx, final IgniteClosure<Integer, Object> transformer) throws Exception {
    log.info(">>> Test deadlock [txCnt=" + txCnt + ", loc=" + loc + ", lockPrimaryFirst=" + lockPrimaryFirst + ", clientTx=" + clientTx + ", transformer=" + transformer.getClass().getName() + ']');
    TestCommunicationSpi.init(txCnt);
    final AtomicInteger threadCnt = new AtomicInteger();
    final CyclicBarrier barrier = new CyclicBarrier(txCnt);
    final AtomicReference<TransactionDeadlockException> deadlockErr = new AtomicReference<>();
    final List<List<Integer>> keySets = generateKeys(txCnt, loc, !lockPrimaryFirst);
    final Set<Integer> involvedKeys = new GridConcurrentHashSet<>();
    final Set<Integer> involvedLockedKeys = new GridConcurrentHashSet<>();
    final Set<IgniteInternalTx> involvedTxs = new GridConcurrentHashSet<>();
    IgniteInternalFuture<Long> fut = GridTestUtils.runMultiThreadedAsync(new Runnable() {

        @Override
        public void run() {
            int threadNum = threadCnt.incrementAndGet();
            Ignite ignite = loc ? ignite(0) : ignite(clientTx ? threadNum - 1 + txCnt : threadNum - 1);
            IgniteCache<Object, Integer> cache = ignite.cache(CACHE_NAME);
            List<Integer> keys = keySets.get(threadNum - 1);
            int txTimeout = 500 + txCnt * 100;
            try (Transaction tx = ignite.transactions().txStart(OPTIMISTIC, REPEATABLE_READ, txTimeout, 0)) {
                IgniteInternalTx tx0 = ((TransactionProxyImpl) tx).tx();
                involvedTxs.add(tx0);
                Integer key = keys.get(0);
                involvedKeys.add(key);
                Object k;
                log.info(">>> Performs put [node=" + ((IgniteKernal) ignite).localNode().id() + ", tx=" + tx.xid() + ", key=" + transformer.apply(key) + ']');
                cache.put(transformer.apply(key), 0);
                involvedLockedKeys.add(key);
                barrier.await();
                key = keys.get(1);
                ClusterNode primaryNode = ((IgniteCacheProxy) cache).context().affinity().primaryByKey(key, NONE);
                List<Integer> primaryKeys = primaryKeys(grid(primaryNode).cache(CACHE_NAME), 5, key + (100 * threadNum));
                Map<Object, Integer> entries = new HashMap<>();
                involvedKeys.add(key);
                entries.put(transformer.apply(key), 0);
                for (Integer i : primaryKeys) {
                    involvedKeys.add(i);
                    entries.put(transformer.apply(i), 1);
                    k = transformer.apply(i + 13);
                    involvedKeys.add(i + 13);
                    entries.put(k, 2);
                }
                log.info(">>> Performs put [node=" + ((IgniteKernal) ignite).localNode().id() + ", tx=" + tx.xid() + ", entries=" + entries + ']');
                cache.putAll(entries);
                tx.commit();
            } catch (Throwable e) {
                log.info("Expected exception: " + e);
                e.printStackTrace(System.out);
                // At least one stack trace should contain TransactionDeadlockException.
                if (hasCause(e, TransactionTimeoutException.class) && hasCause(e, TransactionDeadlockException.class)) {
                    if (deadlockErr.compareAndSet(null, cause(e, TransactionDeadlockException.class))) {
                        log.info("At least one stack trace should contain " + TransactionDeadlockException.class.getSimpleName());
                        e.printStackTrace(System.out);
                    }
                }
            }
        }
    }, loc ? 2 : txCnt, "tx-thread");
    try {
        fut.get();
    } catch (IgniteCheckedException e) {
        U.error(null, "Unexpected exception", e);
        fail();
    }
    U.sleep(1000);
    TransactionDeadlockException deadlockE = deadlockErr.get();
    assertNotNull("Failed to detect deadlock", deadlockE);
    boolean fail = false;
    // Check transactions, futures and entry locks state.
    for (int i = 0; i < NODES_CNT * 2; i++) {
        Ignite ignite = ignite(i);
        int cacheId = ((IgniteCacheProxy) ignite.cache(CACHE_NAME)).context().cacheId();
        GridCacheSharedContext<Object, Object> cctx = ((IgniteKernal) ignite).context().cache().context();
        IgniteTxManager txMgr = cctx.tm();
        Collection<IgniteInternalTx> activeTxs = txMgr.activeTransactions();
        for (IgniteInternalTx tx : activeTxs) {
            Collection<IgniteTxEntry> entries = tx.allEntries();
            for (IgniteTxEntry entry : entries) {
                if (entry.cacheId() == cacheId) {
                    fail = true;
                    U.error(log, "Transaction still exists: " + "\n" + tx.xidVersion() + "\n" + tx.nearXidVersion() + "\n nodeId=" + cctx.localNodeId() + "\n tx=" + tx);
                }
            }
        }
        Collection<IgniteInternalFuture<?>> futs = txMgr.deadlockDetectionFutures();
        assertTrue(futs.isEmpty());
        GridCacheAdapter<Object, Integer> intCache = internalCache(i, CACHE_NAME);
        GridCacheConcurrentMap map = intCache.map();
        for (Integer key : involvedKeys) {
            Object key0 = transformer.apply(key);
            KeyCacheObject keyCacheObj = intCache.context().toCacheKeyObject(key0);
            GridCacheMapEntry entry = map.getEntry(keyCacheObj);
            if (entry != null)
                assertNull("Entry still has locks " + entry, entry.mvccAllLocal());
        }
    }
    if (fail)
        fail("Some transactions still exist");
    // Check deadlock report
    String msg = deadlockE.getMessage();
    for (IgniteInternalTx tx : involvedTxs) assertTrue(msg.contains("[txId=" + tx.xidVersion() + ", nodeId=" + tx.nodeId() + ", threadId=" + tx.threadId() + ']'));
    for (Integer key : involvedKeys) {
        if (involvedLockedKeys.contains(key))
            assertTrue(msg.contains("[key=" + transformer.apply(key) + ", cache=" + CACHE_NAME + ']'));
        else
            assertFalse(msg.contains("[key=" + transformer.apply(key)));
    }
}
Also used : TransactionDeadlockException(org.apache.ignite.transactions.TransactionDeadlockException) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) List(java.util.List) ArrayList(java.util.ArrayList) Ignite(org.apache.ignite.Ignite) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteKernal(org.apache.ignite.internal.IgniteKernal) GridCacheConcurrentMap(org.apache.ignite.internal.processors.cache.GridCacheConcurrentMap) IgniteCache(org.apache.ignite.IgniteCache) AtomicReference(java.util.concurrent.atomic.AtomicReference) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Transaction(org.apache.ignite.transactions.Transaction) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionTimeoutException(org.apache.ignite.transactions.TransactionTimeoutException) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) GridCacheMapEntry(org.apache.ignite.internal.processors.cache.GridCacheMapEntry) Map(java.util.Map) GridCacheConcurrentMap(org.apache.ignite.internal.processors.cache.GridCacheConcurrentMap) HashMap(java.util.HashMap)

Example 2 with GridConcurrentHashSet

use of org.apache.ignite.internal.util.GridConcurrentHashSet in project ignite by apache.

the class TxPessimisticDeadlockDetectionTest method doTestDeadlock.

/**
     * @throws Exception If failed.
     */
private void doTestDeadlock(final int txCnt, final boolean loc, boolean lockPrimaryFirst, final boolean clientTx, final IgniteClosure<Integer, Object> transformer) throws Exception {
    log.info(">>> Test deadlock [txCnt=" + txCnt + ", loc=" + loc + ", lockPrimaryFirst=" + lockPrimaryFirst + ", clientTx=" + clientTx + ", transformer=" + transformer.getClass().getName() + ']');
    final AtomicInteger threadCnt = new AtomicInteger();
    final CyclicBarrier barrier = new CyclicBarrier(txCnt);
    final AtomicReference<TransactionDeadlockException> deadlockErr = new AtomicReference<>();
    final List<List<Integer>> keySets = generateKeys(txCnt, loc, !lockPrimaryFirst);
    final Set<Integer> involvedKeys = new GridConcurrentHashSet<>();
    final Set<Integer> involvedLockedKeys = new GridConcurrentHashSet<>();
    final Set<IgniteInternalTx> involvedTxs = new GridConcurrentHashSet<>();
    IgniteInternalFuture<Long> fut = GridTestUtils.runMultiThreadedAsync(new Runnable() {

        @Override
        public void run() {
            int threadNum = threadCnt.incrementAndGet();
            Ignite ignite = loc ? ignite(0) : ignite(clientTx ? threadNum - 1 + txCnt : threadNum - 1);
            IgniteCache<Object, Integer> cache = ignite.cache(CACHE_NAME);
            List<Integer> keys = keySets.get(threadNum - 1);
            int txTimeout = 500 + txCnt * 100;
            try (Transaction tx = ignite.transactions().txStart(PESSIMISTIC, REPEATABLE_READ, txTimeout, 0)) {
                involvedTxs.add(((TransactionProxyImpl) tx).tx());
                Integer key = keys.get(0);
                involvedKeys.add(key);
                Object k;
                log.info(">>> Performs put [node=" + ((IgniteKernal) ignite).localNode() + ", tx=" + tx + ", key=" + transformer.apply(key) + ']');
                cache.put(transformer.apply(key), 0);
                involvedLockedKeys.add(key);
                barrier.await();
                key = keys.get(1);
                ClusterNode primaryNode = ((IgniteCacheProxy) cache).context().affinity().primaryByKey(key, NONE);
                List<Integer> primaryKeys = primaryKeys(grid(primaryNode).cache(CACHE_NAME), 5, key + (100 * threadNum));
                Map<Object, Integer> entries = new HashMap<>();
                involvedKeys.add(key);
                entries.put(transformer.apply(key), 0);
                for (Integer i : primaryKeys) {
                    involvedKeys.add(i);
                    entries.put(transformer.apply(i), 1);
                    k = transformer.apply(i + 13);
                    involvedKeys.add(i + 13);
                    entries.put(k, 2);
                }
                log.info(">>> Performs put [node=" + ((IgniteKernal) ignite).localNode() + ", tx=" + tx + ", entries=" + entries + ']');
                cache.putAll(entries);
                tx.commit();
            } catch (Throwable e) {
                // At least one stack trace should contain TransactionDeadlockException.
                if (hasCause(e, TransactionTimeoutException.class) && hasCause(e, TransactionDeadlockException.class)) {
                    if (deadlockErr.compareAndSet(null, cause(e, TransactionDeadlockException.class)))
                        U.error(log, "At least one stack trace should contain " + TransactionDeadlockException.class.getSimpleName(), e);
                }
            }
        }
    }, loc ? 2 : txCnt, "tx-thread");
    try {
        fut.get();
    } catch (IgniteCheckedException e) {
        U.error(null, "Unexpected exception", e);
        fail();
    }
    U.sleep(1000);
    TransactionDeadlockException deadlockE = deadlockErr.get();
    assertNotNull(deadlockE);
    boolean fail = false;
    // Check transactions, futures and entry locks state.
    for (int i = 0; i < NODES_CNT * 2; i++) {
        Ignite ignite = ignite(i);
        int cacheId = ((IgniteCacheProxy) ignite.cache(CACHE_NAME)).context().cacheId();
        GridCacheSharedContext<Object, Object> cctx = ((IgniteKernal) ignite).context().cache().context();
        IgniteTxManager txMgr = cctx.tm();
        Collection<IgniteInternalTx> activeTxs = txMgr.activeTransactions();
        for (IgniteInternalTx tx : activeTxs) {
            Collection<IgniteTxEntry> entries = tx.allEntries();
            for (IgniteTxEntry entry : entries) {
                if (entry.cacheId() == cacheId) {
                    fail = true;
                    U.error(log, "Transaction still exists: " + "\n" + tx.xidVersion() + "\n" + tx.nearXidVersion() + "\n nodeId=" + cctx.localNodeId() + "\n tx=" + tx);
                }
            }
        }
        Collection<IgniteInternalFuture<?>> futs = txMgr.deadlockDetectionFutures();
        assertTrue(futs.isEmpty());
        GridCacheAdapter<Object, Integer> intCache = internalCache(i, CACHE_NAME);
        GridCacheConcurrentMap map = intCache.map();
        for (Integer key : involvedKeys) {
            Object key0 = transformer.apply(key);
            KeyCacheObject keyCacheObj = intCache.context().toCacheKeyObject(key0);
            GridCacheMapEntry entry = map.getEntry(keyCacheObj);
            if (entry != null)
                assertNull("Entry still has locks " + entry, entry.mvccAllLocal());
        }
    }
    if (fail)
        fail("Some transactions still exist");
    // Check deadlock report
    String msg = deadlockE.getMessage();
    for (IgniteInternalTx tx : involvedTxs) assertTrue(msg.contains("[txId=" + tx.xidVersion() + ", nodeId=" + tx.nodeId() + ", threadId=" + tx.threadId() + ']'));
    for (Integer key : involvedKeys) {
        if (involvedLockedKeys.contains(key))
            assertTrue(msg.contains("[key=" + transformer.apply(key) + ", cache=" + CACHE_NAME + ']'));
        else
            assertFalse(msg.contains("[key=" + transformer.apply(key)));
    }
}
Also used : TransactionDeadlockException(org.apache.ignite.transactions.TransactionDeadlockException) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) ArrayList(java.util.ArrayList) List(java.util.List) Ignite(org.apache.ignite.Ignite) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteKernal(org.apache.ignite.internal.IgniteKernal) GridCacheConcurrentMap(org.apache.ignite.internal.processors.cache.GridCacheConcurrentMap) IgniteCache(org.apache.ignite.IgniteCache) AtomicReference(java.util.concurrent.atomic.AtomicReference) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Transaction(org.apache.ignite.transactions.Transaction) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionTimeoutException(org.apache.ignite.transactions.TransactionTimeoutException) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) GridCacheMapEntry(org.apache.ignite.internal.processors.cache.GridCacheMapEntry) HashMap(java.util.HashMap) Map(java.util.Map) GridCacheConcurrentMap(org.apache.ignite.internal.processors.cache.GridCacheConcurrentMap)

Example 3 with GridConcurrentHashSet

use of org.apache.ignite.internal.util.GridConcurrentHashSet in project ignite by apache.

the class IgniteHadoopFileSystemAbstractSelfTest method testMultithreadedCreate.

/**
 * Ensure that when running in multithreaded mode only one create() operation succeed.
 *
 * @throws Exception If failed.
 */
public void testMultithreadedCreate() throws Exception {
    Path dir = new Path(new Path(PRIMARY_URI), "/dir");
    assert fs.mkdirs(dir);
    final Path file = new Path(dir, "file");
    fs.create(file).close();
    final AtomicInteger cnt = new AtomicInteger();
    final Collection<Integer> errs = new GridConcurrentHashSet<>(THREAD_CNT, 1.0f, THREAD_CNT);
    final AtomicBoolean err = new AtomicBoolean();
    multithreaded(new Runnable() {

        @Override
        public void run() {
            int idx = cnt.getAndIncrement();
            byte[] data = new byte[256];
            Arrays.fill(data, (byte) idx);
            FSDataOutputStream os = null;
            try {
                os = fs.create(file, true);
            } catch (IOException ignore) {
                errs.add(idx);
            }
            U.awaitQuiet(barrier);
            try {
                if (os != null)
                    os.write(data);
            } catch (IOException ignore) {
                err.set(true);
            } finally {
                U.closeQuiet(os);
            }
        }
    }, THREAD_CNT);
    assert !err.get();
    // Only one thread could obtain write lock on the file.
    assert errs.size() == THREAD_CNT - 1;
    int idx = -1;
    for (int i = 0; i < THREAD_CNT; i++) {
        if (!errs.remove(i)) {
            idx = i;
            break;
        }
    }
    byte[] expData = new byte[256];
    Arrays.fill(expData, (byte) idx);
    FSDataInputStream is = fs.open(file);
    byte[] data = new byte[256];
    is.read(data);
    is.close();
    assert Arrays.equals(expData, data) : "Expected=" + Arrays.toString(expData) + ", actual=" + Arrays.toString(data);
}
Also used : Path(org.apache.hadoop.fs.Path) IgfsPath(org.apache.ignite.igfs.IgfsPath) IOException(java.io.IOException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) FSDataInputStream(org.apache.hadoop.fs.FSDataInputStream) FSDataOutputStream(org.apache.hadoop.fs.FSDataOutputStream)

Example 4 with GridConcurrentHashSet

use of org.apache.ignite.internal.util.GridConcurrentHashSet in project ignite by apache.

the class HadoopIgfs20FileSystemAbstractSelfTest method testMultithreadedCreate.

/**
 * Ensure that when running in multithreaded mode only one create() operation succeed.
 *
 * @throws Exception If failed.
 */
public void testMultithreadedCreate() throws Exception {
    Path dir = new Path(new Path(primaryFsUri), "/dir");
    fs.mkdir(dir, FsPermission.getDefault(), true);
    final Path file = new Path(dir, "file");
    fs.create(file, EnumSet.noneOf(CreateFlag.class), Options.CreateOpts.perms(FsPermission.getDefault())).close();
    final AtomicInteger cnt = new AtomicInteger();
    final Collection<Integer> errs = new GridConcurrentHashSet<>(THREAD_CNT, 1.0f, THREAD_CNT);
    multithreaded(new Runnable() {

        @Override
        public void run() {
            int idx = cnt.getAndIncrement();
            byte[] data = new byte[256];
            Arrays.fill(data, (byte) idx);
            FSDataOutputStream os = null;
            try {
                os = fs.create(file, EnumSet.of(CreateFlag.OVERWRITE), Options.CreateOpts.perms(FsPermission.getDefault()));
                os.write(data);
            } catch (IOException ignore) {
                errs.add(idx);
            } finally {
                U.awaitQuiet(barrier);
                U.closeQuiet(os);
            }
        }
    }, THREAD_CNT);
    // Only one thread could obtain write lock on the file.
    assert errs.size() == THREAD_CNT - 1 : "Invalid errors count [expected=" + (THREAD_CNT - 1) + ", actual=" + errs.size() + ']';
    int idx = -1;
    for (int i = 0; i < THREAD_CNT; i++) {
        if (!errs.remove(i)) {
            idx = i;
            break;
        }
    }
    byte[] expData = new byte[256];
    Arrays.fill(expData, (byte) idx);
    FSDataInputStream is = fs.open(file);
    byte[] data = new byte[256];
    is.read(data);
    is.close();
    assert Arrays.equals(expData, data);
}
Also used : Path(org.apache.hadoop.fs.Path) IgfsPath(org.apache.ignite.igfs.IgfsPath) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) FSDataInputStream(org.apache.hadoop.fs.FSDataInputStream) FSDataOutputStream(org.apache.hadoop.fs.FSDataOutputStream) IOException(java.io.IOException)

Example 5 with GridConcurrentHashSet

use of org.apache.ignite.internal.util.GridConcurrentHashSet in project ignite by apache.

the class IgniteHadoopFileSystemAbstractSelfTest method testMultithreadedAppend.

/**
 * Ensure that when running in multithreaded mode only one append() operation succeed.
 *
 * @throws Exception If failed.
 */
public void testMultithreadedAppend() throws Exception {
    Path dir = new Path(new Path(PRIMARY_URI), "/dir");
    assert fs.mkdirs(dir);
    final Path file = new Path(dir, "file");
    fs.create(file).close();
    final AtomicInteger cnt = new AtomicInteger();
    final Collection<Integer> errs = new GridConcurrentHashSet<>(THREAD_CNT, 1.0f, THREAD_CNT);
    final AtomicBoolean err = new AtomicBoolean();
    multithreaded(new Runnable() {

        @Override
        public void run() {
            int idx = cnt.getAndIncrement();
            byte[] data = new byte[256];
            Arrays.fill(data, (byte) idx);
            U.awaitQuiet(barrier);
            FSDataOutputStream os = null;
            try {
                os = fs.append(file);
            } catch (IOException ignore) {
                errs.add(idx);
            }
            U.awaitQuiet(barrier);
            try {
                if (os != null)
                    os.write(data);
            } catch (IOException ignore) {
                err.set(true);
            } finally {
                U.closeQuiet(os);
            }
        }
    }, THREAD_CNT);
    assert !err.get();
    // Only one thread could obtain write lock on the file.
    assert errs.size() == THREAD_CNT - 1;
    int idx = -1;
    for (int i = 0; i < THREAD_CNT; i++) {
        if (!errs.remove(i)) {
            idx = i;
            break;
        }
    }
    byte[] expData = new byte[256];
    Arrays.fill(expData, (byte) idx);
    FSDataInputStream is = fs.open(file);
    byte[] data = new byte[256];
    is.read(data);
    is.close();
    assert Arrays.equals(expData, data);
}
Also used : Path(org.apache.hadoop.fs.Path) IgfsPath(org.apache.ignite.igfs.IgfsPath) IOException(java.io.IOException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) FSDataInputStream(org.apache.hadoop.fs.FSDataInputStream) FSDataOutputStream(org.apache.hadoop.fs.FSDataOutputStream)

Aggregations

GridConcurrentHashSet (org.apache.ignite.internal.util.GridConcurrentHashSet)42 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)22 Ignite (org.apache.ignite.Ignite)21 Test (org.junit.Test)21 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)16 GridCommonAbstractTest (org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)16 IgniteException (org.apache.ignite.IgniteException)15 IOException (java.io.IOException)12 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)12 CountDownLatch (java.util.concurrent.CountDownLatch)10 UUID (java.util.UUID)9 IgniteCache (org.apache.ignite.IgniteCache)9 ArrayList (java.util.ArrayList)8 List (java.util.List)8 AtomicReference (java.util.concurrent.atomic.AtomicReference)8 IgniteInterruptedException (org.apache.ignite.IgniteInterruptedException)8 IgniteLock (org.apache.ignite.IgniteLock)8 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)8 ExpectedException (org.junit.rules.ExpectedException)8 Transaction (org.apache.ignite.transactions.Transaction)7