Search in sources :

Example 11 with TransactionProxyImpl

use of org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl in project ignite by apache.

the class IgniteTxPessimisticOriginatingNodeFailureAbstractSelfTest method checkPrimaryNodeCrash.

/**
 * Checks tx data consistency in case when primary node crashes.
 *
 * @param commmit Whether to commit or rollback a transaction.
 * @throws Exception If failed.
 */
private void checkPrimaryNodeCrash(final boolean commmit) throws Exception {
    Set<Integer> keys = new HashSet<>();
    for (int i = 0; i < 20; i++) keys.add(i);
    final Collection<IgniteKernal> grids = new ArrayList<>();
    ClusterNode primaryNode = grid(1).localNode();
    for (int i = 0; i < gridCount(); i++) {
        if (i != 1)
            grids.add((IgniteKernal) grid(i));
    }
    failingNodeId = primaryNode.id();
    final Map<Integer, String> map = new HashMap<>();
    final String initVal = "initialValue";
    for (Integer key : keys) {
        grid(originatingNode()).cache(DEFAULT_CACHE_NAME).put(key, initVal);
        map.put(key, String.valueOf(key));
    }
    Map<Integer, Collection<ClusterNode>> nodeMap = new HashMap<>();
    IgniteCache<Integer, String> cache = grid(0).cache(DEFAULT_CACHE_NAME);
    info("Failing node ID: " + grid(1).localNode().id());
    for (Integer key : keys) {
        Collection<ClusterNode> nodes = new ArrayList<>();
        nodes.addAll(affinity(cache).mapKeyToPrimaryAndBackups(key));
        nodes.remove(primaryNode);
        nodeMap.put(key, nodes);
    }
    info("Starting tx [values=" + map + ", topVer=" + grid(1).context().discovery().topologyVersion() + ']');
    assertNotNull(cache);
    try (Transaction tx = grid(0).transactions().txStart()) {
        cache.getAll(keys);
        // Should not send any messages.
        cache.putAll(map);
        TransactionProxyImpl txProxy = (TransactionProxyImpl) tx;
        GridNearTxLocal txEx = txProxy.tx();
        assertTrue(txEx.pessimistic());
        if (commmit) {
            txEx.prepare(true);
            // Fail the node in the middle of transaction.
            info(">>> Stopping primary node " + primaryNode);
            G.stop(Ignition.ignite(primaryNode.id()).name(), true);
            info(">>> Stopped originating node, finishing transaction: " + primaryNode.id());
            tx.commit();
        } else {
            // Fail the node in the middle of transaction.
            info(">>> Stopping primary node " + primaryNode);
            G.stop(G.ignite(primaryNode.id()).name(), true);
            info(">>> Stopped originating node, finishing transaction: " + primaryNode.id());
            tx.rollback();
        }
    }
    boolean txFinished = GridTestUtils.waitForCondition(new GridAbsPredicate() {

        @Override
        public boolean apply() {
            for (IgniteKernal g : grids) {
                GridCacheAdapter<?, ?> cache = g.internalCache(DEFAULT_CACHE_NAME);
                IgniteTxManager txMgr = cache.isNear() ? ((GridNearCacheAdapter) cache).dht().context().tm() : cache.context().tm();
                int txNum = txMgr.idMapSize();
                if (txNum != 0)
                    return false;
            }
            return true;
        }
    }, 10000);
    assertTrue(txFinished);
    info("Transactions finished.");
    for (Map.Entry<Integer, Collection<ClusterNode>> e : nodeMap.entrySet()) {
        final Integer key = e.getKey();
        final String val = map.get(key);
        assertFalse(e.getValue().isEmpty());
        if (atomicityMode() == TRANSACTIONAL_SNAPSHOT)
            continue;
        for (ClusterNode node : e.getValue()) {
            final UUID checkNodeId = node.id();
            compute(G.ignite(checkNodeId).cluster().forNode(node)).call(new IgniteCallable<Void>() {

                /**
                 */
                @IgniteInstanceResource
                private Ignite ignite;

                @Override
                public Void call() throws Exception {
                    IgniteCache<Integer, String> cache = ignite.cache(DEFAULT_CACHE_NAME);
                    assertNotNull(cache);
                    assertEquals("Failed to check entry value on node: " + checkNodeId, !commmit ? initVal : val, cache.localPeek(key));
                    return null;
                }
            });
        }
    }
    awaitPartitionMapExchange();
    for (Map.Entry<Integer, String> e : map.entrySet()) {
        long cntr0 = -1;
        for (Ignite g : G.allGrids()) {
            Integer key = e.getKey();
            assertEquals(!commmit ? initVal : e.getValue(), g.cache(DEFAULT_CACHE_NAME).get(key));
            if (g.affinity(DEFAULT_CACHE_NAME).isPrimaryOrBackup(((IgniteEx) g).localNode(), key)) {
                long nodeCntr = updateCoutner(g, key);
                if (cntr0 == -1)
                    cntr0 = nodeCntr;
                assertEquals(cntr0, nodeCntr);
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) IgniteInstanceResource(org.apache.ignite.resources.IgniteInstanceResource) GridCacheAdapter(org.apache.ignite.internal.processors.cache.GridCacheAdapter) GridNearCacheAdapter(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter) Ignite(org.apache.ignite.Ignite) UUID(java.util.UUID) HashSet(java.util.HashSet) ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteKernal(org.apache.ignite.internal.IgniteKernal) GridAbsPredicate(org.apache.ignite.internal.util.lang.GridAbsPredicate) IgniteCache(org.apache.ignite.IgniteCache) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) IgniteTxManager(org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager) IgniteSpiException(org.apache.ignite.spi.IgniteSpiException) IgniteFutureTimeoutException(org.apache.ignite.lang.IgniteFutureTimeoutException) IgniteException(org.apache.ignite.IgniteException) Transaction(org.apache.ignite.transactions.Transaction) Collection(java.util.Collection) HashMap(java.util.HashMap) Map(java.util.Map) TransactionProxyImpl(org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl)

Example 12 with TransactionProxyImpl

use of org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl in project ignite by apache.

the class IgniteTxOriginatingNodeFailureAbstractSelfTest method testTxOriginatingNodeFails.

/**
 * @param keys Keys to update.
 * @param partial Flag indicating whether to simulate partial prepared state.
 * @throws Exception If failed.
 */
protected void testTxOriginatingNodeFails(Collection<Integer> keys, final boolean partial) throws Exception {
    assertFalse(keys.isEmpty());
    final Collection<IgniteKernal> grids = new ArrayList<>();
    ClusterNode txNode = grid(originatingNode()).localNode();
    for (int i = 1; i < gridCount(); i++) grids.add((IgniteKernal) grid(i));
    final Map<Integer, String> map = new HashMap<>();
    final String initVal = "initialValue";
    for (Integer key : keys) {
        grid(originatingNode()).cache(DEFAULT_CACHE_NAME).put(key, initVal);
        map.put(key, String.valueOf(key));
    }
    Map<Integer, Collection<ClusterNode>> nodeMap = new HashMap<>();
    info("Node being checked: " + grid(1).localNode().id());
    for (Integer key : keys) {
        Collection<ClusterNode> nodes = new ArrayList<>();
        nodes.addAll(grid(1).affinity(DEFAULT_CACHE_NAME).mapKeyToPrimaryAndBackups(key));
        nodes.remove(txNode);
        nodeMap.put(key, nodes);
    }
    info("Starting optimistic tx " + "[values=" + map + ", topVer=" + (grid(1)).context().discovery().topologyVersion() + ']');
    if (partial)
        ignoreMessages(grid(1).localNode().id(), ignoreMessageClass());
    final Ignite txIgniteNode = G.ignite(txNode.id());
    GridTestUtils.runAsync(new Callable<Object>() {

        @Override
        public Object call() throws Exception {
            IgniteCache<Integer, String> cache = txIgniteNode.cache(DEFAULT_CACHE_NAME);
            assertNotNull(cache);
            TransactionProxyImpl tx = (TransactionProxyImpl) txIgniteNode.transactions().txStart();
            GridNearTxLocal txEx = tx.tx();
            assertTrue(txEx.optimistic());
            cache.putAll(map);
            try {
                txEx.prepareNearTxLocal().get(3, TimeUnit.SECONDS);
            } catch (IgniteFutureTimeoutCheckedException ignored) {
                info("Failed to wait for prepare future completion: " + partial);
            }
            return null;
        }
    }).get();
    info("Stopping originating node " + txNode);
    G.stop(G.ignite(txNode.id()).name(), true);
    info("Stopped grid, waiting for transactions to complete.");
    boolean txFinished = GridTestUtils.waitForCondition(new GridAbsPredicate() {

        @Override
        public boolean apply() {
            for (IgniteKernal g : grids) {
                GridCacheSharedContext<Object, Object> ctx = g.context().cache().context();
                int txNum = ctx.tm().idMapSize();
                if (txNum != 0)
                    return false;
            }
            return true;
        }
    }, 10000);
    assertTrue(txFinished);
    info("Transactions finished.");
    for (Map.Entry<Integer, Collection<ClusterNode>> e : nodeMap.entrySet()) {
        final Integer key = e.getKey();
        final String val = map.get(key);
        assertFalse(e.getValue().isEmpty());
        for (ClusterNode node : e.getValue()) {
            compute(G.ignite(node.id()).cluster().forNode(node)).call(new IgniteCallable<Void>() {

                /**
                 */
                @IgniteInstanceResource
                private Ignite ignite;

                @Override
                public Void call() throws Exception {
                    IgniteCache<Integer, String> cache = ignite.cache(DEFAULT_CACHE_NAME);
                    assertNotNull(cache);
                    assertEquals(partial ? initVal : val, cache.localPeek(key));
                    return null;
                }
            });
        }
    }
    for (Map.Entry<Integer, String> e : map.entrySet()) {
        for (Ignite g : G.allGrids()) {
            UUID locNodeId = g.cluster().localNode().id();
            assertEquals("Check failed for node: " + locNodeId, partial ? initVal : e.getValue(), g.cache(DEFAULT_CACHE_NAME).get(e.getKey()));
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) GridCacheSharedContext(org.apache.ignite.internal.processors.cache.GridCacheSharedContext) Callable(java.util.concurrent.Callable) IgniteCallable(org.apache.ignite.lang.IgniteCallable) IgniteInstanceResource(org.apache.ignite.resources.IgniteInstanceResource) IgniteFutureTimeoutCheckedException(org.apache.ignite.internal.IgniteFutureTimeoutCheckedException) Ignite(org.apache.ignite.Ignite) UUID(java.util.UUID) ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteKernal(org.apache.ignite.internal.IgniteKernal) GridAbsPredicate(org.apache.ignite.internal.util.lang.GridAbsPredicate) IgniteCache(org.apache.ignite.IgniteCache) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) IgniteSpiException(org.apache.ignite.spi.IgniteSpiException) IgniteException(org.apache.ignite.IgniteException) IgniteFutureTimeoutCheckedException(org.apache.ignite.internal.IgniteFutureTimeoutCheckedException) Collection(java.util.Collection) HashMap(java.util.HashMap) Map(java.util.Map) TransactionProxyImpl(org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl)

Example 13 with TransactionProxyImpl

use of org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl in project ignite by apache.

the class GridExchangeFreeCellularSwitchIsolationTest method testOnlyAffectedNodesWaitForRecovery.

/**
 * Test checks than non-affected nodes (alive cells) finishes the switch asap,
 * that they wait only for the recovery related to these nodes (eg. replicated caches recovery that affects every node).
 */
@Test
public void testOnlyAffectedNodesWaitForRecovery() throws Exception {
    int nodes = 6;
    String recoveryStatusMsg = "TxRecovery Status and Timings [txs=";
    // Any.
    LogListener lsnrAny = matches(recoveryStatusMsg).build();
    LogListener lsnrBrokenCell = matches(recoveryStatusMsg).times((nodes / 2) - 1).build();
    LogListener lsnrAliveCell = matches(recoveryStatusMsg).times((nodes / 2)).build();
    listeningLog.registerListener(lsnrAny);
    startGridsMultiThreaded(nodes);
    blockRecoveryMessages();
    CellularCluster cluster = resolveCellularCluster(nodes, startFrom);
    Ignite orig = cluster.orig;
    Ignite failed = cluster.failed;
    List<Ignite> brokenCellNodes = cluster.brokenCellNodes;
    List<Ignite> aliveCellNodes = cluster.aliveCellNodes;
    List<Integer> partKeys = new ArrayList<>();
    List<Integer> replKeys = new ArrayList<>();
    for (Ignite node : G.allGrids()) {
        if (!node.configuration().isClientMode()) {
            partKeys.add(primaryKey(node.getOrCreateCache(PART_CACHE_NAME)));
            replKeys.add(primaryKey(node.getOrCreateCache(REPL_CACHE_NAME)));
        }
    }
    CountDownLatch partPreparedLatch = new CountDownLatch(nodes);
    CountDownLatch replPreparedLatch = new CountDownLatch(nodes);
    CountDownLatch partCommitLatch = new CountDownLatch(1);
    CountDownLatch replCommitLatch = new CountDownLatch(1);
    AtomicInteger partKeyIdx = new AtomicInteger();
    AtomicInteger replKeyIdx = new AtomicInteger();
    Set<GridCacheVersion> partTxVers = new GridConcurrentHashSet<>();
    Set<GridCacheVersion> replTxVers = new GridConcurrentHashSet<>();
    IgniteInternalFuture<?> partFut = multithreadedAsync(() -> {
        try {
            int idx = partKeyIdx.getAndIncrement();
            Transaction tx = orig.transactions().txStart();
            partTxVers.add(((TransactionProxyImpl<?, ?>) tx).tx().nearXidVersion());
            int key = partKeys.get(idx);
            orig.getOrCreateCache(PART_CACHE_NAME).put(key, key);
            ((TransactionProxyImpl<?, ?>) tx).tx().prepare(true);
            partPreparedLatch.countDown();
            partCommitLatch.await();
            if (orig != failed)
                ((TransactionProxyImpl<?, ?>) tx).commit();
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    }, nodes);
    IgniteInternalFuture<?> replFut = multithreadedAsync(() -> {
        try {
            int idx = replKeyIdx.getAndIncrement();
            Transaction tx = orig.transactions().txStart();
            replTxVers.add(((TransactionProxyImpl<?, ?>) tx).tx().nearXidVersion());
            int key = replKeys.get(idx);
            orig.getOrCreateCache(REPL_CACHE_NAME).put(key, key);
            ((TransactionProxyImpl<?, ?>) tx).tx().prepare(true);
            replPreparedLatch.countDown();
            replCommitLatch.await();
            if (orig != failed)
                ((TransactionProxyImpl<?, ?>) tx).commit();
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    }, nodes);
    partPreparedLatch.await();
    replPreparedLatch.await();
    checkTransactionsCount(orig, nodes, brokenCellNodes, nodes / 2, aliveCellNodes, nodes / 2, partTxVers);
    checkTransactionsCount(orig, nodes, brokenCellNodes, nodes, aliveCellNodes, nodes, replTxVers);
    assertFalse(lsnrAny.check());
    listeningLog.registerListener(lsnrAliveCell);
    // Stopping node.
    failed.close();
    awaitForSwitchOnNodeLeft(failed);
    // In case of originating node failed all alive primaries will recover (commit) txs on tx cordinator falure.
    // Txs with failed primary will start recovery, but can't finish it since recovery messages are blocked.
    // Broken cell's nodes will have 1 unrecovered tx for partitioned cache.
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    nodes, brokenCellNodes, orig == failed ? 1 : nodes / 2, aliveCellNodes, orig == failed ? 0 : nodes / 2, partTxVers);
    // All cell's nodes will have 1 unrecovered tx for replicated cache.
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    nodes, brokenCellNodes, orig == failed ? 1 : nodes, aliveCellNodes, orig == failed ? 1 : nodes, replTxVers);
    // Counts tx's creations and preparations.
    BiConsumer<T2<Ignite, String>, T3<CountDownLatch, CountDownLatch, CountDownLatch>> txRun = (T2<Ignite, String> pair, T3</*create*/
    CountDownLatch, /*put*/
    CountDownLatch, /*commit*/
    CountDownLatch> latches) -> {
        try {
            Ignite ignite = pair.get1();
            String cacheName = pair.get2();
            IgniteCache<Integer, Integer> cache = ignite.getOrCreateCache(cacheName);
            try (Transaction tx = ignite.transactions().txStart()) {
                // Create.
                latches.get1().countDown();
                // Avoiding intersection with prepared keys.
                cache.put(primaryKeys(cache, 1, 1_000).get(0), 42);
                // Put.
                latches.get2().countDown();
                tx.commit();
                // Commit.
                latches.get3().countDown();
            }
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    };
    CountDownLatch partBrokenCellCreateLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch partBrokenCellPutLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch partBrokenCellCommitLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch partAliveCellCreateLatch = new CountDownLatch(aliveCellNodes.size());
    CountDownLatch partAliveCellPutLatch = new CountDownLatch(aliveCellNodes.size());
    CountDownLatch partAliveCellCommitLatch = new CountDownLatch(aliveCellNodes.size());
    CountDownLatch replBrokenCellCreateLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch replBrokenCellPutLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch replBrokenCellCommitLatch = new CountDownLatch(brokenCellNodes.size());
    CountDownLatch replAliveCellCreateLatch = new CountDownLatch(aliveCellNodes.size());
    CountDownLatch replAliveCellPutLatch = new CountDownLatch(aliveCellNodes.size());
    CountDownLatch replAliveCellCommitLatch = new CountDownLatch(aliveCellNodes.size());
    List<IgniteInternalFuture<?>> futs = new ArrayList<>();
    for (Ignite brokenCellNode : brokenCellNodes) {
        futs.add(multithreadedAsync(() -> txRun.accept(new T2<>(brokenCellNode, REPL_CACHE_NAME), new T3<>(replBrokenCellCreateLatch, replBrokenCellPutLatch, replBrokenCellCommitLatch)), 1));
        futs.add(multithreadedAsync(() -> txRun.accept(new T2<>(brokenCellNode, PART_CACHE_NAME), new T3<>(partBrokenCellCreateLatch, partBrokenCellPutLatch, partBrokenCellCommitLatch)), 1));
    }
    for (Ignite aliveCellNode : aliveCellNodes) {
        futs.add(multithreadedAsync(() -> txRun.accept(new T2<>(aliveCellNode, REPL_CACHE_NAME), new T3<>(replAliveCellCreateLatch, replAliveCellPutLatch, replAliveCellCommitLatch)), 1));
        futs.add(multithreadedAsync(() -> txRun.accept(new T2<>(aliveCellNode, PART_CACHE_NAME), new T3<>(partAliveCellCreateLatch, partAliveCellPutLatch, partAliveCellCommitLatch)), 1));
    }
    // Switch in progress cluster-wide.
    // Alive nodes switch blocked until replicated caches recovery happen.
    checkUpcomingTransactionsState(// Started.
    partBrokenCellCreateLatch, // Started.
    0, partBrokenCellPutLatch, brokenCellNodes.size(), partBrokenCellCommitLatch, brokenCellNodes.size(), // Started. Blocked by replicated cache recovery.
    partAliveCellCreateLatch, // Started. Blocked by replicated cache recovery.
    0, partAliveCellPutLatch, aliveCellNodes.size(), partAliveCellCommitLatch, aliveCellNodes.size());
    checkUpcomingTransactionsState(// Started.
    replBrokenCellCreateLatch, // Started.
    0, replBrokenCellPutLatch, brokenCellNodes.size(), replBrokenCellCommitLatch, brokenCellNodes.size(), // Started. Blocked by replicated cache recovery.
    replAliveCellCreateLatch, // Started. Blocked by replicated cache recovery.
    0, replAliveCellPutLatch, aliveCellNodes.size(), replAliveCellCommitLatch, aliveCellNodes.size());
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    nodes, brokenCellNodes, orig == failed ? 1 : nodes / 2, aliveCellNodes, orig == failed ? 0 : nodes / 2, partTxVers);
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    nodes, brokenCellNodes, orig == failed ? 1 : nodes, aliveCellNodes, orig == failed ? 1 : nodes, replTxVers);
    // Replicated recovery.
    for (Ignite ignite : G.allGrids()) {
        TestRecordingCommunicationSpi spi = (TestRecordingCommunicationSpi) ignite.configuration().getCommunicationSpi();
        spi.stopBlock(true, blockedMsg -> {
            Message msg = blockedMsg.ioMessage().message();
            return replTxVers.contains(((GridCacheTxRecoveryRequest) msg).nearXidVersion());
        });
    }
    replCommitLatch.countDown();
    replFut.get();
    // Switch partially finished.
    // Broken cell still in switch.
    // Alive cell finished the switch.
    checkUpcomingTransactionsState(// Started.
    partBrokenCellCreateLatch, // Started.
    0, partBrokenCellPutLatch, brokenCellNodes.size(), partBrokenCellCommitLatch, brokenCellNodes.size(), // Started.
    partAliveCellCreateLatch, // Started.
    0, // Alive cell nodes's able to start transactions on primaries,
    partAliveCellPutLatch, // Alive cell nodes's able to start transactions on primaries,
    0, partAliveCellCommitLatch, // Able to commit, since all primaries and backups are inside the alive cell.
    0);
    checkUpcomingTransactionsState(// Started.
    replBrokenCellCreateLatch, // Started.
    0, replBrokenCellPutLatch, brokenCellNodes.size(), replBrokenCellCommitLatch, brokenCellNodes.size(), // Started.
    replAliveCellCreateLatch, // Started.
    0, // Alive cell's nodes able to start transactions on primaries,
    replAliveCellPutLatch, // Alive cell's nodes able to start transactions on primaries,
    0, replAliveCellCommitLatch, // But not able to commit, since broken cell's nodes still in switch.
    aliveCellNodes.size());
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    nodes, brokenCellNodes, orig == failed ? 1 : nodes / 2, // New txs able to start while previous are in progress.
    aliveCellNodes, // New txs able to start while previous are in progress.
    orig == failed ? 0 : nodes / 2, /*to be committed*/
    partTxVers);
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    0, brokenCellNodes, 0, aliveCellNodes, 0, replTxVers);
    // Recovery finished on alive cell.
    assertTrue(waitForCondition(lsnrAliveCell::check, 5000));
    listeningLog.registerListener(lsnrBrokenCell);
    // Partitioned recovery.
    for (Ignite ignite : G.allGrids()) {
        TestRecordingCommunicationSpi spi = (TestRecordingCommunicationSpi) ignite.configuration().getCommunicationSpi();
        spi.stopBlock(true, blockedMsg -> {
            Message msg = blockedMsg.ioMessage().message();
            return partTxVers.contains(((GridCacheTxRecoveryRequest) msg).nearXidVersion());
        });
    }
    partCommitLatch.countDown();
    partFut.get();
    // Switches finished cluster-wide, all transactions can be committed.
    checkUpcomingTransactionsState(replBrokenCellCreateLatch, 0, replBrokenCellPutLatch, 0, replBrokenCellCommitLatch, 0, replAliveCellCreateLatch, 0, replAliveCellPutLatch, 0, replAliveCellCommitLatch, 0);
    checkUpcomingTransactionsState(partBrokenCellCreateLatch, 0, partBrokenCellPutLatch, 0, partBrokenCellCommitLatch, 0, partAliveCellCreateLatch, 0, partAliveCellPutLatch, 0, partAliveCellCommitLatch, 0);
    // Check that pre-failure transactions are absent.
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    0, brokenCellNodes, 0, aliveCellNodes, 0, partTxVers);
    checkTransactionsCount(orig != failed ? orig : null, /*stopped*/
    0, brokenCellNodes, 0, aliveCellNodes, 0, replTxVers);
    // Recovery finished on broken cell.
    assertTrue(waitForCondition(lsnrBrokenCell::check, 5000));
    for (IgniteInternalFuture<?> fut : futs) fut.get();
    for (Ignite node : G.allGrids()) {
        for (int key : partKeys) assertEquals(key, node.getOrCreateCache(PART_CACHE_NAME).get(key));
        for (int key : replKeys) assertEquals(key, node.getOrCreateCache(REPL_CACHE_NAME).get(key));
    }
    // Final check that any transactions are absent.
    checkTransactionsCount(null, 0, brokenCellNodes, 0, aliveCellNodes, 0, null);
}
Also used : Message(org.apache.ignite.plugin.extensions.communication.Message) ArrayList(java.util.ArrayList) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) GridConcurrentHashSet(org.apache.ignite.internal.util.GridConcurrentHashSet) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) Ignite(org.apache.ignite.Ignite) T2(org.apache.ignite.internal.util.typedef.T2) T3(org.apache.ignite.internal.util.typedef.T3) LogListener(org.apache.ignite.testframework.LogListener) IgniteCache(org.apache.ignite.IgniteCache) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestRecordingCommunicationSpi(org.apache.ignite.internal.TestRecordingCommunicationSpi) Transaction(org.apache.ignite.transactions.Transaction) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionProxyImpl(org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl) Test(org.junit.Test)

Example 14 with TransactionProxyImpl

use of org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl in project ignite by apache.

the class GridExchangeFreeCellularSwitchTxContinuationTest method testAlreadyStartedTxsContinuationDuringAndAfterTheSwitch.

/**
 * Tests checks that txs started before the switch can be continued after the switch if they are not affected by
 * node fail.
 */
@Test
public void testAlreadyStartedTxsContinuationDuringAndAfterTheSwitch() throws Exception {
    int nodes = 6;
    startGridsMultiThreaded(nodes);
    blockRecoveryMessages();
    CellularCluster cluster = resolveCellularCluster(nodes, startFrom);
    Ignite orig = cluster.orig;
    Ignite failed = cluster.failed;
    int txCnt = 1024;
    // See puts count inside the closure.
    int keysPerTx = 6;
    int prepTxCnt = 100;
    int dataAmount = txCnt * keysPerTx + prepTxCnt;
    int totalDataAmount = dataAmount + prepTxCnt;
    Queue<Integer> keys = new ConcurrentLinkedDeque<>();
    Queue<Integer> primaryOnFailedKeys = new ConcurrentLinkedDeque<>();
    Queue<Integer> keysToCheck = new ConcurrentLinkedDeque<>();
    for (int i = 0; keys.size() < dataAmount; i++) if (// Will not cause node failed exception on put.
    !primaryNode(i, PART_CACHE_NAME).equals(failed))
        keys.add(i);
    for (int i = 0; primaryOnFailedKeys.size() < prepTxCnt; i++) if (// Will cause explicit recovery on node fail.
    primaryNode(i, PART_CACHE_NAME).equals(failed))
        primaryOnFailedKeys.add(i);
    CountDownLatch putInitLatch = new CountDownLatch(txCnt);
    CountDownLatch prepLatch = new CountDownLatch(prepTxCnt * 2);
    CountDownLatch nodeFailedLatch = new CountDownLatch(1);
    CountDownLatch nodesAwareOfFailLatch = new CountDownLatch(1);
    CountDownLatch txsRecoveryAllowedLatch = new CountDownLatch(1);
    CountDownLatch txsRecoveryFinishedLatch = new CountDownLatch(1);
    IgniteInternalFuture<?> txFut = multithreadedAsync(() -> {
        try {
            Transaction tx = orig.transactions().txStart(concurrency, isolation);
            IgniteCache<Integer, Integer> cache = orig.getOrCreateCache(PART_CACHE_NAME);
            // Put before node fail.
            put(cache, keys, keysToCheck);
            long initTopVer = ((IgniteEx) orig).context().cache().context().exchange().readyAffinityVersion().topologyVersion();
            putInitLatch.countDown();
            nodeFailedLatch.await();
            // Put right after node fail.
            put(cache, keys, keysToCheck);
            nodesAwareOfFailLatch.await();
            // Put when nodes are aware of fail.
            put(cache, keys, keysToCheck);
            txsRecoveryAllowedLatch.await();
            // Put right after recovery allowed.
            put(cache, keys, keysToCheck);
            txsRecoveryFinishedLatch.await();
            // Put right after recovery finished.
            put(cache, keys, keysToCheck);
            // Put with some random delay after recovery happen.
            U.sleep(ThreadLocalRandom.current().nextInt(5_000));
            put(cache, keys, keysToCheck);
            ((TransactionProxyImpl<?, ?>) tx).commit();
            long commitTopVer = ((IgniteEx) orig).context().cache().context().exchange().readyAffinityVersion().topologyVersion();
            // Started before the switch, but continued after it.
            assertTrue(commitTopVer > initTopVer);
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    }, txCnt);
    IgniteInternalFuture<?> prepFut1 = multithreadedAsync(() -> {
        // Keys with unaffected primary.
        try {
            putInitLatch.await();
            Transaction tx = failed.transactions().txStart();
            IgniteCache<Integer, Integer> cache = failed.getOrCreateCache(PART_CACHE_NAME);
            put(cache, keys, keysToCheck);
            ((TransactionProxyImpl<?, ?>) tx).tx().prepare(true);
            prepLatch.countDown();
            txsRecoveryFinishedLatch.await();
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    }, prepTxCnt);
    IgniteInternalFuture<?> prepFut2 = multithreadedAsync(() -> {
        // Primary keys of failed primary.
        try {
            putInitLatch.await();
            Transaction tx = failed.transactions().txStart();
            IgniteCache<Integer, Integer> cache = failed.getOrCreateCache(PART_CACHE_NAME);
            put(cache, primaryOnFailedKeys, keysToCheck);
            ((TransactionProxyImpl<?, ?>) tx).tx().prepare(true);
            prepLatch.countDown();
            txsRecoveryFinishedLatch.await();
        } catch (Exception e) {
            fail("Should not happen [exception=" + e + "]");
        }
    }, prepTxCnt);
    prepLatch.await();
    // Stopping node.
    failed.close();
    nodeFailedLatch.countDown();
    awaitForSwitchOnNodeLeft(failed);
    nodesAwareOfFailLatch.countDown();
    // Allowing recovery.
    for (Ignite ignite : G.allGrids()) {
        TestRecordingCommunicationSpi spi = (TestRecordingCommunicationSpi) ignite.configuration().getCommunicationSpi();
        spi.stopBlock(true, blockedMsg -> true);
    }
    txsRecoveryAllowedLatch.countDown();
    for (Ignite ignite : G.allGrids()) {
        for (IgniteInternalTx tx : ((IgniteEx) ignite).context().cache().context().tm().activeTransactions()) {
            while (tx.state() == TransactionState.PREPARED) U.sleep(100);
        }
    }
    txsRecoveryFinishedLatch.countDown();
    prepFut1.get();
    prepFut2.get();
    txFut.get();
    assertTrue(keys.isEmpty());
    assertTrue(primaryOnFailedKeys.isEmpty());
    assertEquals(totalDataAmount, keysToCheck.size());
    IgniteCache<Integer, Integer> cache = orig.getOrCreateCache(PART_CACHE_NAME);
    for (Integer i : keysToCheck) assertEquals(i, cache.get(i));
}
Also used : CountDownLatch(java.util.concurrent.CountDownLatch) ConcurrentLinkedDeque(java.util.concurrent.ConcurrentLinkedDeque) TestRecordingCommunicationSpi(org.apache.ignite.internal.TestRecordingCommunicationSpi) Transaction(org.apache.ignite.transactions.Transaction) IgniteInternalTx(org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx) IgniteEx(org.apache.ignite.internal.IgniteEx) Ignite(org.apache.ignite.Ignite) TransactionProxyImpl(org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl) Test(org.junit.Test)

Example 15 with TransactionProxyImpl

use of org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl in project ignite by apache.

the class WalRecoveryTxLogicalRecordsTest method prepareTx.

/**
 * @param ignite Ignite.
 * @param keys Keys.
 */
private int prepareTx(Ignite ignite, List<Integer> keys) throws IgniteCheckedException {
    try (Transaction tx = ignite.transactions().txStart()) {
        for (Integer key : keys) ignite.cache(CACHE_NAME).put(key, key);
        GridNearTxLocal tx0 = ((TransactionProxyImpl) tx).tx();
        tx0.prepare(true);
        tx0.rollback();
    }
    return keys.size();
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Transaction(org.apache.ignite.transactions.Transaction) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) TransactionProxyImpl(org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl)

Aggregations

TransactionProxyImpl (org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl)19 Transaction (org.apache.ignite.transactions.Transaction)13 GridNearTxLocal (org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal)12 ArrayList (java.util.ArrayList)9 Ignite (org.apache.ignite.Ignite)9 TestRecordingCommunicationSpi (org.apache.ignite.internal.TestRecordingCommunicationSpi)9 IgniteInternalTx (org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx)9 CountDownLatch (java.util.concurrent.CountDownLatch)8 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8 IgniteCache (org.apache.ignite.IgniteCache)8 ClusterNode (org.apache.ignite.cluster.ClusterNode)8 Test (org.junit.Test)8 Collection (java.util.Collection)7 IgniteEx (org.apache.ignite.internal.IgniteEx)6 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)6 GridAbsPredicate (org.apache.ignite.internal.util.lang.GridAbsPredicate)6 List (java.util.List)5 CacheConfiguration (org.apache.ignite.configuration.CacheConfiguration)5 IgniteInterruptedCheckedException (org.apache.ignite.internal.IgniteInterruptedCheckedException)5 Optional (java.util.Optional)4