IGNITE-10262: MVCC TX: Client operation may hangs if all data nodes left the 
grid. This closes #5693.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/7b6e17b2
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/7b6e17b2
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/7b6e17b2

Branch: refs/heads/ignite-1741
Commit: 7b6e17b216d82e69610da0432b1b37b70a5b8492
Parents: 664fb93
Author: rkondakov <kondako...@mail.ru>
Authored: Wed Dec 19 15:50:31 2018 +0300
Committer: Igor Seliverstov <gvvinbl...@gmail.com>
Committed: Wed Dec 19 15:50:31 2018 +0300

----------------------------------------------------------------------
 .../near/GridNearTxEnlistFuture.java            |   3 +-
 .../near/GridNearTxQueryEnlistFuture.java       |   5 +
 .../GridNearTxQueryResultsEnlistFuture.java     |   3 +-
 .../IgniteClientCacheStartFailoverTest.java     |   4 +-
 .../processors/query/h2/IgniteH2Indexing.java   |  12 +-
 ...eMvccAbstractSqlCoordinatorFailoverTest.java | 161 +++++++++++++++++++
 6 files changed, 181 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxEnlistFuture.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxEnlistFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxEnlistFuture.java
index 789cd3c..8cbe93e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxEnlistFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxEnlistFuture.java
@@ -31,6 +31,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import 
org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheMessage;
@@ -217,7 +218,7 @@ public class GridNearTxEnlistFuture extends 
GridNearTxAbstractEnlistFuture<GridC
                 ClusterNode node = cctx.affinity().primaryByKey(key, topVer);
 
                 if (node == null)
-                    throw new ClusterTopologyCheckedException("Failed to get 
primary node " +
+                    throw new ClusterTopologyServerNotFoundException("Failed 
to get primary node " +
                         "[topVer=" + topVer + ", key=" + key + ']');
 
                 tx.markQueryEnlisted(null);

http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistFuture.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistFuture.java
index 030a432..245ef39 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistFuture.java
@@ -23,6 +23,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import 
org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.affinity.AffinityAssignment;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheMessage;
@@ -119,6 +120,10 @@ public class GridNearTxQueryEnlistFuture extends 
GridNearTxQueryAbstractEnlistFu
                     updateMappings(pNode);
             }
 
+            if (primary.isEmpty())
+                throw new ClusterTopologyServerNotFoundException("Failed to 
find data nodes for cache (all partition " +
+                    "nodes left the grid).");
+
             boolean locallyMapped = primary.contains(cctx.localNode());
 
             if (locallyMapped)

http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
index 316aae5..e4d74f2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
@@ -31,6 +31,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import 
org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheMessage;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
@@ -203,7 +204,7 @@ public class GridNearTxQueryResultsEnlistFuture extends 
GridNearTxQueryAbstractE
                 ClusterNode node = 
cctx.affinity().primaryByPartition(key.partition(), topVer);
 
                 if (node == null)
-                    throw new ClusterTopologyCheckedException("Failed to get 
primary node " +
+                    throw new ClusterTopologyServerNotFoundException("Failed 
to get primary node " +
                         "[topVer=" + topVer + ", key=" + key + ']');
 
                 if (!sequential)

http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheStartFailoverTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheStartFailoverTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheStartFailoverTest.java
index de18c44..69df748 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheStartFailoverTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheStartFailoverTest.java
@@ -41,8 +41,8 @@ import org.apache.ignite.internal.IgniteNodeAttributes;
 import org.apache.ignite.internal.TestRecordingCommunicationSpi;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import 
org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtAffinityAssignmentResponse;
-import 
org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology;
 import 
org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsFullMessage;
+import 
org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiPredicate;
@@ -192,8 +192,6 @@ public class IgniteClientCacheStartFailoverTest extends 
GridCommonAbstractTest {
      */
     @Test
     public void testClientStartLastServerFailsMvccTx() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10262";);
-
         clientStartLastServerFails(TRANSACTIONAL_SNAPSHOT);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index c2f3f89..29f39b9 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -1140,8 +1140,16 @@ public class IgniteH2Indexing implements 
GridQueryIndexing {
             return new Iterable<List<?>>() {
                 @SuppressWarnings("NullableProblems")
                 @Override public Iterator<List<?>> iterator() {
-                    return rdcQryExec.query(schemaName, qry, keepCacheObj, 
enforceJoinOrder, opTimeout,
-                        cancel, params, parts, lazy, tracker);
+                    try {
+                        return rdcQryExec.query(schemaName, qry, keepCacheObj, 
enforceJoinOrder, opTimeout,
+                            cancel, params, parts, lazy, tracker);
+                    }
+                    catch (Throwable e) {
+                        if (tracker != null)
+                            tracker.onDone();
+
+                        throw e;
+                    }
                 }
             };
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7b6e17b2/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccAbstractSqlCoordinatorFailoverTest.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccAbstractSqlCoordinatorFailoverTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccAbstractSqlCoordinatorFailoverTest.java
index b14dc07..e986f44 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccAbstractSqlCoordinatorFailoverTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccAbstractSqlCoordinatorFailoverTest.java
@@ -17,10 +17,26 @@
 
 package org.apache.ignite.internal.processors.cache.mvcc;
 
+import java.util.concurrent.Callable;
+import javax.cache.CacheException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheServerNotFoundException;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.IgniteNodeAttributes;
+import org.apache.ignite.internal.TestRecordingCommunicationSpi;
+import 
org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtAffinityAssignmentResponse;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static 
org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.ReadMode.SCAN;
 import static 
org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.ReadMode.SQL;
 import static 
org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.WriteMode.DML;
@@ -152,4 +168,149 @@ public abstract class 
CacheMvccAbstractSqlCoordinatorFailoverTest extends CacheM
     public void testCoordinatorChangeActiveQueryClientFails_SimpleScan() 
throws Exception {
         checkCoordinatorChangeActiveQueryClientFails_Simple(new 
InitIndexing(Integer.class, Integer.class), SCAN, DML);
     }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartLastServerFails() throws Exception {
+        testSpi = true;
+
+        startGrids(3);
+
+        CacheConfiguration<Object, Object> cfg = 
cacheConfiguration(cacheMode(), FULL_SYNC, 0, DFLT_PARTITION_COUNT)
+            .setIndexedTypes(Integer.class, Integer.class);
+
+        cfg.setNodeFilter(new TestNodeFilter(getTestIgniteInstanceName(1)));
+
+        Ignite srv1 = ignite(1);
+
+        srv1.createCache(cfg);
+
+        client = true;
+
+        final Ignite c = startGrid(3);
+
+        client = false;
+
+        
TestRecordingCommunicationSpi.spi(srv1).blockMessages(GridDhtAffinityAssignmentResponse.class,
 c.name());
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new 
Callable<Void>() {
+            @Override public Void call() throws Exception {
+                c.cache(DEFAULT_CACHE_NAME);
+
+                return null;
+            }
+        }, "start-cache");
+
+        U.sleep(1000);
+
+        assertFalse(fut.isDone());
+
+        stopGrid(1);
+
+        fut.get();
+
+        final IgniteCache<Object, Object> clientCache = 
c.cache(DEFAULT_CACHE_NAME);
+
+        for (int i = 0; i < 10; i++) {
+            final int k = i;
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.get(k);
+
+                    return null;
+                }
+            }, CacheServerNotFoundException.class, null);
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.put(k, k);
+
+                    return null;
+                }
+            }, CacheServerNotFoundException.class, null);
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.remove(k);
+
+                    return null;
+                }
+            }, CacheServerNotFoundException.class, null);
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.query(new SqlFieldsQuery("SELECT * FROM 
INTEGER")).getAll();
+
+                    return null;
+                }
+            }, CacheException.class, "Failed to find data nodes for cache"); 
// TODO IGNITE-10377 should be CacheServerNotFoundException.
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.query(new SqlFieldsQuery("SELECT * FROM 
INTEGER ORDER BY _val")).getAll();
+
+                    return null;
+                }
+            }, CacheException.class, "Failed to find data nodes for cache"); 
// TODO IGNITE-10377 should be CacheServerNotFoundException.
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.query(new SqlFieldsQuery("DELETE FROM Integer 
WHERE 1 = 1")).getAll();
+
+                    return null;
+                }
+            }, CacheException.class, "Failed to find data nodes for cache"); 
// TODO IGNITE-10377 should be CacheServerNotFoundException.
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.query(new SqlFieldsQuery("INSERT INTO Integer 
(_key, _val) VALUES (1, 2)")).getAll();
+
+                    return null;
+                }
+            }, CacheException.class, "Failed to get primary node"); // TODO 
IGNITE-10377 should be CacheServerNotFoundException.
+
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    clientCache.query(new SqlFieldsQuery("UPDATE Integer SET 
_val=42 WHERE _key IN (SELECT DISTINCT _val FROM INTEGER)")).getAll();
+
+                    return null;
+                }
+            }, CacheException.class, "Failed to find data nodes for cache"); 
// TODO IGNITE-10377 should be CacheServerNotFoundException.
+        }
+
+        startGrid(1);
+
+        awaitPartitionMapExchange();
+
+        for (int i = 0; i < 100; i++) {
+            assertNull(clientCache.get(i));
+
+            clientCache.put(i, i);
+
+            assertEquals(i, clientCache.get(i));
+        }
+    }
+
+    /**
+     *
+     */
+    private static class TestNodeFilter implements 
IgnitePredicate<ClusterNode> {
+        /** */
+        private final String includeName;
+
+        /**
+         * @param includeName Node to include.
+         */
+        public TestNodeFilter(String includeName) {
+            this.includeName = includeName;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(ClusterNode node) {
+            return 
includeName.equals(node.attribute(IgniteNodeAttributes.ATTR_IGNITE_INSTANCE_NAME));
+        }
+    }
 }

Reply via email to