Search in sources :

Example 1 with ClientServerError

use of org.apache.ignite.internal.client.thin.ClientServerError in project ignite by apache.

the class FunctionalTest method testTransactions.

/**
 * Test transactions.
 */
@Test
public void testTransactions() throws Exception {
    try (Ignite ignite = Ignition.start(Config.getServerConfiguration());
        IgniteClient client = Ignition.startClient(getClientConfiguration())) {
        ClientCache<Integer, String> cache = client.createCache(new ClientCacheConfiguration().setName("cache").setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
        cache.put(0, "value0");
        cache.put(1, "value1");
        // Test nested transactions is not possible.
        try (ClientTransaction tx = client.transactions().txStart()) {
            try (ClientTransaction tx1 = client.transactions().txStart()) {
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
        }
        // Test implicit rollback when transaction closed.
        try (ClientTransaction tx = client.transactions().txStart()) {
            cache.put(1, "value2");
        }
        assertEquals("value1", cache.get(1));
        // Test explicit rollback.
        try (ClientTransaction tx = client.transactions().txStart()) {
            cache.put(1, "value2");
            tx.rollback();
        }
        assertEquals("value1", cache.get(1));
        // Test commit.
        try (ClientTransaction tx = client.transactions().txStart()) {
            cache.put(1, "value2");
            tx.commit();
        }
        assertEquals("value2", cache.get(1));
        // Test end of already completed transaction.
        ClientTransaction tx0 = client.transactions().txStart();
        tx0.close();
        try {
            tx0.commit();
            fail();
        } catch (ClientException expected) {
        // No-op.
        }
        // Test end of outdated transaction.
        try (ClientTransaction tx = client.transactions().txStart()) {
            try {
                tx0.commit();
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            tx.commit();
        }
        // Test transaction with a timeout.
        long TX_TIMEOUT = 200L;
        try (ClientTransaction tx = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED, TX_TIMEOUT)) {
            long txStartedTime = U.currentTimeMillis();
            cache.put(1, "value3");
            while (txStartedTime + TX_TIMEOUT >= U.currentTimeMillis()) U.sleep(100L);
            try {
                cache.put(1, "value4");
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            try {
                tx.commit();
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
        }
        assertEquals("value2", cache.get(1));
        cache.put(1, "value5");
        // Test failover.
        ClientProcessorMXBean mxBean = getMxBean(ignite.name(), "Clients", ClientListenerProcessor.class, ClientProcessorMXBean.class);
        try (ClientTransaction tx = client.transactions().txStart()) {
            cache.put(1, "value6");
            mxBean.dropAllConnections();
            try {
                cache.put(1, "value7");
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            // Start new transaction doesn't recover cache operations on failed channel.
            try (ClientTransaction tx1 = client.transactions().txStart()) {
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            try {
                cache.get(1);
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            // Close outdated transaction doesn't recover cache operations on failed channel.
            tx0.close();
            try {
                cache.get(1);
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
        }
        assertEquals("value5", cache.get(1));
        // Test concurrent transactions in different connections.
        try (IgniteClient client1 = Ignition.startClient(getClientConfiguration())) {
            ClientCache<Integer, String> cache1 = client1.cache("cache");
            try (ClientTransaction tx = client.transactions().txStart(OPTIMISTIC, READ_COMMITTED)) {
                cache.put(0, "value8");
                try (ClientTransaction tx1 = client1.transactions().txStart(OPTIMISTIC, READ_COMMITTED)) {
                    assertEquals("value8", cache.get(0));
                    assertEquals("value0", cache1.get(0));
                    cache1.put(1, "value9");
                    assertEquals("value5", cache.get(1));
                    assertEquals("value9", cache1.get(1));
                    tx1.commit();
                    assertEquals("value9", cache.get(1));
                }
                assertEquals("value0", cache1.get(0));
                tx.commit();
                assertEquals("value8", cache1.get(0));
            }
        }
        // Check different types of cache operations.
        try (ClientTransaction tx = client.transactions().txStart()) {
            // Operations: put, putAll, putIfAbsent.
            cache.put(2, "value10");
            cache.putAll(F.asMap(1, "value11", 3, "value12"));
            cache.putIfAbsent(4, "value13");
            // Operations: get, getAll, getAndPut, getAndRemove, getAndReplace, getAndPutIfAbsent.
            assertEquals("value10", cache.get(2));
            assertEquals(F.asMap(1, "value11", 2, "value10"), cache.getAll(new HashSet<>(Arrays.asList(1, 2))));
            assertEquals("value13", cache.getAndPut(4, "value14"));
            assertEquals("value14", cache.getAndPutIfAbsent(4, "valueDiscarded"));
            assertEquals("value14", cache.get(4));
            assertEquals("value14", cache.getAndReplace(4, "value15"));
            assertEquals("value15", cache.getAndRemove(4));
            assertNull(cache.getAndPutIfAbsent(10, "valuePutIfAbsent"));
            assertEquals("valuePutIfAbsent", cache.get(10));
            // Operations: contains.
            assertTrue(cache.containsKey(2));
            assertFalse(cache.containsKey(4));
            assertTrue(cache.containsKeys(ImmutableSet.of(2, 10)));
            assertFalse(cache.containsKeys(ImmutableSet.of(2, 4)));
            // Operations: replace.
            cache.put(4, "");
            assertTrue(cache.replace(4, "value16"));
            assertTrue(cache.replace(4, "value16", "value17"));
            // Operations: remove, removeAll
            cache.putAll(F.asMap(5, "", 6, ""));
            assertTrue(cache.remove(5));
            assertTrue(cache.remove(4, "value17"));
            cache.removeAll(new HashSet<>(Arrays.asList(3, 6)));
            assertFalse(cache.containsKey(3));
            assertFalse(cache.containsKey(6));
            tx.rollback();
        }
        assertEquals(F.asMap(0, "value8", 1, "value9"), cache.getAll(new HashSet<>(Arrays.asList(0, 1))));
        assertFalse(cache.containsKey(2));
        // Test concurrent transactions started by different threads.
        try (ClientTransaction tx = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED)) {
            CyclicBarrier barrier = new CyclicBarrier(2);
            cache.put(0, "value18");
            IgniteInternalFuture<?> fut = GridTestUtils.runAsync(() -> {
                try (ClientTransaction tx1 = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED)) {
                    cache.put(1, "value19");
                    barrier.await();
                    assertEquals("value8", cache.get(0));
                    barrier.await();
                    tx1.commit();
                    barrier.await();
                    assertEquals("value18", cache.get(0));
                } catch (InterruptedException | BrokenBarrierException ignore) {
                // No-op.
                }
            });
            barrier.await();
            assertEquals("value9", cache.get(1));
            barrier.await();
            tx.commit();
            barrier.await();
            assertEquals("value19", cache.get(1));
            fut.get();
        }
        // Test transaction usage by different threads.
        try (ClientTransaction tx = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED)) {
            cache.put(0, "value20");
            GridTestUtils.runAsync(() -> {
                // Implicit transaction started here.
                cache.put(1, "value21");
                assertEquals("value18", cache.get(0));
                try {
                    // Transaction can't be commited by another thread.
                    tx.commit();
                    fail();
                } catch (ClientException expected) {
                // No-op.
                }
                // Transaction can be closed by another thread.
                tx.close();
                assertEquals("value18", cache.get(0));
            }).get();
            assertEquals("value21", cache.get(1));
            try {
                // Transaction can't be commited after another thread close this transaction.
                tx.commit();
                fail();
            } catch (ClientException expected) {
            // No-op.
            }
            assertEquals("value18", cache.get(0));
            // Start implicit transaction after explicit transaction has been closed by another thread.
            cache.put(0, "value22");
            GridTestUtils.runAsync(() -> assertEquals("value22", cache.get(0))).get();
            // New explicit transaction can be started after current transaction has been closed by another thread.
            try (ClientTransaction tx1 = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED)) {
                cache.put(0, "value23");
                tx1.commit();
            }
            assertEquals("value23", cache.get(0));
        }
        // Test active transactions limit.
        int txLimit = ignite.configuration().getClientConnectorConfiguration().getThinClientConfiguration().getMaxActiveTxPerConnection();
        List<ClientTransaction> txs = new ArrayList<>(txLimit);
        for (int i = 0; i < txLimit; i++) {
            Thread t = new Thread(() -> txs.add(client.transactions().txStart()));
            t.start();
            t.join();
        }
        try (ClientTransaction ignored = client.transactions().txStart()) {
            fail();
        } catch (ClientException e) {
            ClientServerError cause = (ClientServerError) e.getCause();
            assertEquals(ClientStatus.TX_LIMIT_EXCEEDED, cause.getCode());
        }
        for (ClientTransaction tx : txs) tx.close();
        // Test that new transaction can be started after commit of the previous one without closing.
        ClientTransaction tx = client.transactions().txStart();
        tx.commit();
        tx = client.transactions().txStart();
        tx.rollback();
        // Test that new transaction can be started after rollback of the previous one without closing.
        tx = client.transactions().txStart();
        tx.commit();
        // Test that implicit transaction started after commit of previous one without closing.
        cache.put(0, "value24");
        GridTestUtils.runAsync(() -> assertEquals("value24", cache.get(0))).get();
    }
}
Also used : BrokenBarrierException(java.util.concurrent.BrokenBarrierException) ArrayList(java.util.ArrayList) ClientProcessorMXBean(org.apache.ignite.mxbean.ClientProcessorMXBean) CyclicBarrier(java.util.concurrent.CyclicBarrier) ClientServerError(org.apache.ignite.internal.client.thin.ClientServerError) Ignite(org.apache.ignite.Ignite) HashSet(java.util.HashSet) AbstractBinaryArraysTest(org.apache.ignite.internal.binary.AbstractBinaryArraysTest) Test(org.junit.Test)

Aggregations

ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 BrokenBarrierException (java.util.concurrent.BrokenBarrierException)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1 Ignite (org.apache.ignite.Ignite)1 AbstractBinaryArraysTest (org.apache.ignite.internal.binary.AbstractBinaryArraysTest)1 ClientServerError (org.apache.ignite.internal.client.thin.ClientServerError)1 ClientProcessorMXBean (org.apache.ignite.mxbean.ClientProcessorMXBean)1 Test (org.junit.Test)1