ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agoncha...@apache.org
Subject [18/47] ignite git commit: IGNITE-5267 - Moved ignite-ps module to ignite-core
Date Sun, 11 Jun 2017 20:03:44 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
new file mode 100644
index 0000000..6ba3a20
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
@@ -0,0 +1,356 @@
+/*
+ * 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.persistence.standbycluster.join;
+
+import java.util.Map;
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
+import org.junit.Assert;
+
+/**
+ *
+ */
+public class JoinInActiveNodeToActiveCluster extends AbstractNodeJoinTemplate {
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder withOutConfigurationTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0)).setActiveOnStart(true),
+            cfg(name(1)).setActiveOnStart(true),
+            cfg(name(2)).setActiveOnStart(true)
+        ).afterClusterStarted(
+            b.checkCacheOnlySystem()
+        ).nodeConfiguration(
+            cfg(name(3)).setActiveOnStart(false)
+        ).afterNodeJoin(
+            b.checkCacheOnlySystem()
+        ).stateAfterJoin(
+            true
+        ).afterDeActivate(
+            b.checkCacheEmpty()
+        ).setEnd(
+            b.checkCacheOnlySystem()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationOnJoinTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0)).setActiveOnStart(true),
+            cfg(name(1)).setActiveOnStart(true),
+            cfg(name(2)).setActiveOnStart(true)
+        ).afterClusterStarted(
+            b.checkCacheOnlySystem()
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations())
+        ).afterNodeJoin(
+            b.checkCacheNotEmpty()
+        ).stateAfterJoin(
+            true
+        ).afterDeActivate(
+            b.checkCacheEmpty()
+        ).setEnd(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationInClusterTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(true)
+                .setCacheConfiguration(allCacheConfigurations()),
+            cfg(name(1)).setActiveOnStart(true),
+            cfg(name(2)).setActiveOnStart(true)
+        ).afterClusterStarted(
+            b.checkCacheNotEmpty()
+        ).nodeConfiguration(
+            cfg(name(3)).setActiveOnStart(false)
+        ).afterNodeJoin(
+            b.checkCacheNotEmpty()
+        ).stateAfterJoin(
+            true
+        ).afterDeActivate(
+            b.checkCacheEmpty()
+        ).setEnd(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationSameOnBothTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(true)
+                .setCacheConfiguration(allCacheConfigurations()),
+            cfg(name(1)).setActiveOnStart(true),
+            cfg(name(2)).setActiveOnStart(true)
+        ).afterClusterStarted(
+            b.checkCacheNotEmpty()
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations())
+        ).afterNodeJoin(
+            b.checkCacheNotEmpty()
+        ).stateAfterJoin(
+            true
+        ).afterDeActivate(
+            b.checkCacheEmpty()
+        ).setEnd(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(true)
+                .setCacheConfiguration(atomicCfg()),
+            cfg(name(1)).setActiveOnStart(true),
+            cfg(name(2)).setActiveOnStart(true)
+        ).afterClusterStarted(
+            new Runnable() {
+                @Override public void run() {
+                    for (int i = 0; i < 3; i++) {
+                        IgniteEx ig = grid(name(i));
+
+                        Map<String, DynamicCacheDescriptor> desc = cacheDescriptors(ig);
+
+                        Assert.assertEquals(3, desc.size());
+
+                        Assert.assertNotNull(ig.context().cache().cache(cache1));
+                        Assert.assertNull(ig.context().cache().cache(cache2));
+
+                        Map<String, GridCacheAdapter> caches = caches(ig);
+
+                        Assert.assertEquals(3, caches.size());
+                    }
+                }
+            }
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(transactionCfg())
+        ).afterNodeJoin(
+            b.checkCacheNotEmpty()
+        ).stateAfterJoin(
+            true
+        ).afterDeActivate(
+            b.checkCacheEmpty()
+        ).setEnd(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    // Server node join.
+
+    /** {@inheritDoc} */
+    @Override public void testJoinWithOutConfiguration() throws Exception {
+        withOutConfigurationTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationOnJoin() throws Exception {
+        staticCacheConfigurationOnJoinTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationInCluster() throws Exception {
+        staticCacheConfigurationInClusterTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationSameOnBoth() throws Exception {
+        staticCacheConfigurationSameOnBothTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationDifferentOnBoth() throws Exception {
+        staticCacheConfigurationDifferentOnBothTemplate().execute();
+    }
+
+    // Client node join.
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientWithOutConfiguration() throws Exception {
+        joinClientWithOutConfigurationTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationOnJoin() throws Exception {
+        joinClientStaticCacheConfigurationOnJoinTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationInCluster() throws Exception {
+        joinClientStaticCacheConfigurationInClusterTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationSameOnBoth() throws Exception {
+        joinClientStaticCacheConfigurationSameOnBothTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
+        joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientWithOutConfigurationTemplate() throws Exception {
+        return withOutConfigurationTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationOnJoinTemplate() throws Exception {
+        return staticCacheConfigurationOnJoinTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationInClusterTemplate() throws Exception {
+        return staticCacheConfigurationInClusterTemplate()
+            .nodeConfiguration(setClient)
+            .afterNodeJoin(new Runnable() {
+                @Override public void run() {
+                    for (int i = 0; i < 3; i++) {
+                        IgniteEx ig = grid(name(i));
+
+                        Map<String, DynamicCacheDescriptor> desc = cacheDescriptors(ig);
+
+                        Assert.assertEquals(4, desc.size());
+
+                        if (!ig.context().discovery().localNode().isClient()) {
+                            Assert.assertNotNull(ig.context().cache().cache(cache1));
+                            Assert.assertNotNull(ig.context().cache().cache(cache2));
+                        }
+                        else {
+                            Assert.assertNull(ig.context().cache().cache(cache1));
+                            Assert.assertNull(ig.context().cache().cache(cache2));
+                        }
+
+                        Map<String, GridCacheAdapter> caches = caches(ig);
+
+                        Assert.assertEquals(4, caches.size());
+                    }
+                }
+            }).setEnd(new Runnable() {
+                @Override public void run() {
+                    for (int i = 0; i < 3; i++) {
+                        IgniteEx ig = grid(name(i));
+
+                        Map<String, DynamicCacheDescriptor> desc = cacheDescriptors(ig);
+
+                        Assert.assertEquals(4, desc.size());
+
+                        if (!ig.context().discovery().localNode().isClient()) {
+                            Assert.assertNotNull(ig.context().cache().cache(cache1));
+                            Assert.assertNotNull(ig.context().cache().cache(cache2));
+                        }
+                        else {
+                            Assert.assertNull(ig.context().cache().cache(cache1));
+                            Assert.assertNull(ig.context().cache().cache(cache2));
+                        }
+
+                        Map<String, GridCacheAdapter> caches = caches(ig);
+
+                        Assert.assertEquals(4, caches.size());
+                    }
+                }
+            });
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationSameOnBothTemplate() throws Exception {
+        return staticCacheConfigurationSameOnBothTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return  staticCacheConfigurationDifferentOnBothTemplate()
+            .nodeConfiguration(setClient)
+            .afterNodeJoin(
+                new Runnable() {
+                    @Override public void run() {
+                        for (int i = 0; i < 4; i++) {
+                            IgniteEx ig = grid(name(i));
+
+                            Map<String, DynamicCacheDescriptor> desc = cacheDescriptors(ig);
+
+                            Assert.assertEquals(4, desc.size());
+
+                            if (!ig.context().discovery().localNode().isClient())
+                                Assert.assertNotNull(ig.context().cache().cache(cache1));
+
+                            Assert.assertNotNull(ig.context().cache().cache(cache2));
+
+                            Map<String, GridCacheAdapter> caches = caches(ig);
+
+                            if (!ig.context().discovery().localNode().isClient())
+                                Assert.assertEquals(4, caches.size());
+                            else
+                                Assert.assertEquals(3, caches.size());
+                        }
+                    }
+                }
+            ).setEnd(
+                new Runnable() {
+                    @Override public void run() {
+                        for (int i = 0; i < 4; i++) {
+                            IgniteEx ig = grid(name(i));
+
+                            Map<String, DynamicCacheDescriptor> desc = cacheDescriptors(ig);
+
+                            Assert.assertEquals(4, desc.size());
+
+                            if (!ig.context().discovery().localNode().isClient())
+                                Assert.assertNotNull(ig.context().cache().cache(cache1));
+
+                            Assert.assertNotNull(ig.context().cache().cache(cache2));
+
+                            Map<String, GridCacheAdapter> caches = caches(ig);
+
+                            if (!ig.context().discovery().localNode().isClient())
+                                Assert.assertEquals(4, caches.size());
+                            else
+                                Assert.assertEquals(3, caches.size());
+                        }
+                    }
+                }
+            );
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
new file mode 100644
index 0000000..244001b
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
@@ -0,0 +1,226 @@
+/*
+ * 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.persistence.standbycluster.join;
+
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+
+/**
+ *
+ */
+public class JoinInActiveNodeToInActiveCluster extends AbstractNodeJoinTemplate {
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder withOutConfigurationTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0)).setActiveOnStart(false),
+            cfg(name(1)).setActiveOnStart(false),
+            cfg(name(2)).setActiveOnStart(false)
+        ).afterClusterStarted(
+            b.checkCacheEmpty()
+        ).nodeConfiguration(
+            cfg(name(3)).setActiveOnStart(false)
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterActivate(
+            b.checkCacheOnlySystem()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationOnJoinTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0)).setActiveOnStart(false),
+            cfg(name(1)).setActiveOnStart(false),
+            cfg(name(2)).setActiveOnStart(false)
+        ).afterClusterStarted(
+            b.checkCacheEmpty()
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations())
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationInClusterTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations()),
+            cfg(name(1)).setActiveOnStart(false),
+            cfg(name(2)).setActiveOnStart(false)
+        ).afterClusterStarted(
+            b.checkCacheEmpty()
+        ).nodeConfiguration(
+            cfg(name(3)).setActiveOnStart(false)
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationSameOnBothTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations()),
+            cfg(name(1)).setActiveOnStart(false),
+            cfg(name(2)).setActiveOnStart(false)
+        ).afterClusterStarted(
+            b.checkCacheEmpty()
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(allCacheConfigurations())
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override public JoinNodeTestPlanBuilder staticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        JoinNodeTestPlanBuilder b = builder();
+
+        b.clusterConfiguration(
+            cfg(name(0))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(transactionCfg()),
+            cfg(name(1)).setActiveOnStart(false),
+            cfg(name(2)).setActiveOnStart(false)
+        ).afterClusterStarted(
+            b.checkCacheEmpty()
+        ).nodeConfiguration(
+            cfg(name(3))
+                .setActiveOnStart(false)
+                .setCacheConfiguration(atomicCfg())
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    // Server node join.
+
+    /** {@inheritDoc} */
+    @Override public void testJoinWithOutConfiguration() throws Exception {
+        withOutConfigurationTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationOnJoin() throws Exception {
+        staticCacheConfigurationOnJoinTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationInCluster() throws Exception {
+        staticCacheConfigurationInClusterTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationSameOnBoth() throws Exception {
+        staticCacheConfigurationSameOnBothTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testStaticCacheConfigurationDifferentOnBoth() throws Exception {
+        staticCacheConfigurationDifferentOnBothTemplate().execute();
+    }
+
+    // Client node join.
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientWithOutConfiguration() throws Exception {
+        joinClientWithOutConfigurationTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationOnJoin() throws Exception {
+        joinClientStaticCacheConfigurationOnJoinTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationInCluster() throws Exception {
+        joinClientStaticCacheConfigurationInClusterTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationSameOnBoth() throws Exception {
+        joinClientStaticCacheConfigurationSameOnBothTemplate().execute();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
+        joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientWithOutConfigurationTemplate() throws Exception {
+        return withOutConfigurationTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationOnJoinTemplate() throws Exception {
+        return staticCacheConfigurationOnJoinTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationInClusterTemplate() throws Exception {
+        return staticCacheConfigurationInClusterTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationSameOnBothTemplate() throws Exception {
+        return staticCacheConfigurationSameOnBothTemplate().nodeConfiguration(setClient);
+    }
+
+    @Override public JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return staticCacheConfigurationDifferentOnBothTemplate().nodeConfiguration(setClient);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToActiveClusterWithPersistence.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToActiveClusterWithPersistence.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToActiveClusterWithPersistence.java
new file mode 100644
index 0000000..54087ba
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToActiveClusterWithPersistence.java
@@ -0,0 +1,98 @@
+/*
+ * 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.persistence.standbycluster.join.persistence;
+
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.join.JoinActiveNodeToActiveCluster;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+
+/**
+ *
+ */
+public class JoinActiveNodeToActiveClusterWithPersistence extends JoinActiveNodeToActiveCluster {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration cfg(String name) throws Exception {
+        return persistentCfg(super.cfg(name));
+    }
+
+    private AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder persistent(AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b) {
+        b.afterClusterStarted(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder withOutConfigurationTemplate() throws Exception {
+        AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b = persistent(super.withOutConfigurationTemplate());
+
+        b.afterActivate(b.checkCacheOnlySystem());
+
+        return b;
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientWithOutConfigurationTemplate() throws Exception {
+        AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b = persistent(super.joinClientWithOutConfigurationTemplate());
+
+        b.afterActivate(b.checkCacheOnlySystem());
+
+        return b;
+    }
+
+    @Override public void testJoinWithOutConfiguration() throws Exception {
+        withOutConfigurationTemplate().execute();
+    }
+
+    @Override public void testJoinClientWithOutConfiguration() throws Exception {
+        joinClientWithOutConfigurationTemplate().execute();
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationOnJoinTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationOnJoinTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationInClusterTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationInClusterTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationSameOnBothTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationSameOnBothTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationDifferentOnBothTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationOnJoinTemplate() throws Exception {
+        return persistent(super.joinClientStaticCacheConfigurationOnJoinTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationInClusterTemplate() throws Exception {
+        return persistent(super.joinClientStaticCacheConfigurationInClusterTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return persistent(super.joinClientStaticCacheConfigurationDifferentOnBothTemplate());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToInActiveClusterWithPersistence.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToInActiveClusterWithPersistence.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToInActiveClusterWithPersistence.java
new file mode 100644
index 0000000..305255c
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinActiveNodeToInActiveClusterWithPersistence.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.standbycluster.join.persistence;
+
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.join.JoinActiveNodeToInActiveCluster;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class JoinActiveNodeToInActiveClusterWithPersistence extends JoinActiveNodeToInActiveCluster {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration cfg(String name) throws Exception {
+        return persistentCfg(super.cfg(name));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToActiveClusterWithPersistence.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToActiveClusterWithPersistence.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToActiveClusterWithPersistence.java
new file mode 100644
index 0000000..a138d8d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToActiveClusterWithPersistence.java
@@ -0,0 +1,86 @@
+/*
+ * 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.persistence.standbycluster.join.persistence;
+
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.join.JoinInActiveNodeToActiveCluster;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+
+/**
+ *
+ */
+public class JoinInActiveNodeToActiveClusterWithPersistence extends JoinInActiveNodeToActiveCluster {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration cfg(String name) throws Exception {
+        return persistentCfg(super.cfg(name));
+    }
+
+    private AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder persistent(AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b) {
+        b.afterClusterStarted(
+            b.checkCacheEmpty()
+        ).stateAfterJoin(
+            false
+        ).afterNodeJoin(
+            b.checkCacheEmpty()
+        ).afterActivate(
+            b.checkCacheNotEmpty()
+        );
+
+        return b;
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder withOutConfigurationTemplate() throws Exception {
+        AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b = persistent(super.withOutConfigurationTemplate());
+
+        b.afterActivate(b.checkCacheOnlySystem());
+
+        return b;
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientWithOutConfigurationTemplate() throws Exception {
+        AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder b = persistent(super.joinClientWithOutConfigurationTemplate());
+
+        b.afterActivate(b.checkCacheOnlySystem());
+
+        return b;
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationInClusterTemplate() throws Exception{
+        return persistent(super.joinClientStaticCacheConfigurationInClusterTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder joinClientStaticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return persistent(super.joinClientStaticCacheConfigurationDifferentOnBothTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationOnJoinTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationOnJoinTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationInClusterTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationInClusterTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationSameOnBothTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationSameOnBothTemplate());
+    }
+
+    @Override public AbstractNodeJoinTemplate.JoinNodeTestPlanBuilder staticCacheConfigurationDifferentOnBothTemplate() throws Exception {
+        return persistent(super.staticCacheConfigurationDifferentOnBothTemplate());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToInActiveClusterWithPersistence.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToInActiveClusterWithPersistence.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToInActiveClusterWithPersistence.java
new file mode 100644
index 0000000..b3db10d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/persistence/JoinInActiveNodeToInActiveClusterWithPersistence.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.standbycluster.join.persistence;
+
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.join.JoinInActiveNodeToInActiveCluster;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ *
+ */
+public class JoinInActiveNodeToInActiveClusterWithPersistence extends JoinInActiveNodeToInActiveCluster {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration cfg(String name) throws Exception {
+        return persistentCfg(super.cfg(name));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteAbstractStandByClientReconnectTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteAbstractStandByClientReconnectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteAbstractStandByClientReconnectTest.java
new file mode 100644
index 0000000..eec267b
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteAbstractStandByClientReconnectTest.java
@@ -0,0 +1,336 @@
+/*
+ * 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.persistence.standbycluster.reconnect;
+
+import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.PersistentStoreConfiguration;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.events.EventType;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage;
+import org.apache.ignite.spi.discovery.DiscoverySpiListener;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+
+import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_DISCONNECTED;
+
+/**
+ *
+ */
+public abstract class IgniteAbstractStandByClientReconnectTest extends GridCommonAbstractTest {
+
+    private static final TcpDiscoveryVmIpFinder vmIpFinder = new TcpDiscoveryVmIpFinder(true);
+
+    private static final TcpDiscoveryVmIpFinder clientIpFinder = new TcpDiscoveryVmIpFinder(true);
+
+    protected final String node1 = "node1";
+    protected final String node2 = "node2";
+    protected final String nodeClient = "nodeClient";
+
+    protected final String ccfg1staticName = "cache1static";
+    protected final String ccfg2staticName = "cache2static";
+    protected final String ccfg3staticName = "cache3static";
+
+    protected final String ccfg1staticWithFilterName = "ccfg1staticWithFilter";
+    protected final String ccfg2staticWithFilterName = "ccfg2staticWithFilter";
+    protected final String ccfg3staticWithFilterName = "ccfg3staticWithFilter";
+
+    protected final String ccfgDynamicName = "ccfgDynamic";
+    protected final String ccfgDynamicWithFilterName = "ccfgDynamicWithFilter";
+
+    protected final CacheConfiguration ccfg1static = new CacheConfiguration(ccfg1staticName);
+    protected final CacheConfiguration ccfg2static = new CacheConfiguration(ccfg2staticName);
+    protected final CacheConfiguration ccfg3static = new CacheConfiguration(ccfg3staticName);
+
+    protected final CacheConfiguration ccfg1staticWithFilter =
+        new CacheConfiguration(ccfg1staticWithFilterName).setNodeFilter(new FilterNode(node2));
+
+    protected final CacheConfiguration ccfg2staticWithFilter =
+        new CacheConfiguration(ccfg2staticWithFilterName).setNodeFilter(new FilterNode(nodeClient));
+
+    protected final CacheConfiguration ccfg3staticWithFilter =
+        new CacheConfiguration(ccfg3staticWithFilterName).setNodeFilter(new FilterNode(node1));
+
+    protected final CacheConfiguration ccfgDynamic = new CacheConfiguration(ccfgDynamicName);
+
+    protected final CacheConfiguration ccfgDynamicWithFilter =
+        new CacheConfiguration(ccfgDynamicWithFilterName).setNodeFilter(new FilterNode(node2));
+
+    protected final Set<String> staticCacheNames = Sets.newHashSet(
+        ccfg1staticName, ccfg2staticName, ccfg3staticName,
+        ccfg1staticWithFilterName, ccfg2staticWithFilterName, ccfg3staticWithFilterName
+    );
+
+    protected final Set<String> allCacheNames = Sets.newHashSet(
+        ccfg1staticName, ccfg2staticName, ccfg3staticName,
+        ccfg1staticWithFilterName, ccfg2staticWithFilterName, ccfg3staticWithFilterName,
+        ccfgDynamicName, ccfgDynamicWithFilterName
+    );
+
+    @Override protected IgniteConfiguration getConfiguration(String name) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(name);
+
+        if (!nodeClient.equals(name))
+            cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(vmIpFinder));
+        else {
+            clientIpFinder.setAddresses(Collections.singletonList("127.0.0.1:47501"));
+
+            cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(clientIpFinder));
+        }
+
+        cfg.setPersistentStoreConfiguration(new PersistentStoreConfiguration());
+        cfg.setConsistentId(name);
+
+        return cfg;
+    }
+
+    protected void addDisconnectListener(
+        final CountDownLatch disconnectedLatch,
+        final CountDownLatch reconnectedLatch
+    ) {
+        grid(nodeClient).events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event event) {
+                switch (event.type()) {
+                    case EventType.EVT_CLIENT_NODE_DISCONNECTED:
+                        info("Client disconnected");
+
+                        disconnectedLatch.countDown();
+
+                        break;
+                    case EventType.EVT_CLIENT_NODE_RECONNECTED:
+                        info("Client reconnected");
+
+                        reconnectedLatch.countDown();
+                }
+
+                return true;
+            }
+        }, EventType.EVT_CLIENT_NODE_DISCONNECTED, EventType.EVT_CLIENT_NODE_RECONNECTED);
+    }
+
+    protected void checkDescriptors(IgniteEx ig, Set<String> cacheNames) {
+        Collection<DynamicCacheDescriptor> descs = ig.context().cache().cacheDescriptors().values();
+
+        assertEquals("Node name: " + ig.name(), cacheNames.size() + 2, descs.size());
+
+        int systemCnt = 0;
+
+        for (DynamicCacheDescriptor desc : descs)
+            if (!CU.isSystemCache(desc.cacheName()))
+                assertTrue(desc.cacheName(), cacheNames.contains(desc.cacheName()));
+            else
+                systemCnt++;
+
+        assertEquals(2, systemCnt);
+    }
+
+    protected void startNodes(CountDownLatch activateLatch) throws Exception {
+        IgniteConfiguration cfg1 = getConfiguration(node1)
+            .setCacheConfiguration(ccfg1static, ccfg1staticWithFilter);
+
+        IgniteConfiguration cfg2 = getConfiguration(node2)
+            .setCacheConfiguration(ccfg2static, ccfg2staticWithFilter);
+
+        IgniteConfiguration cfg3 = getConfiguration(nodeClient)
+            .setCacheConfiguration(ccfg3static, ccfg3staticWithFilter);
+
+        if (activateLatch != null)
+            cfg3.setDiscoverySpi(
+                new AwaitTcpDiscoverySpi(activateLatch)
+                    .setIpFinder(clientIpFinder)
+            );
+
+        cfg3.setClientMode(true);
+
+        IgniteEx ig1 = startGrid(cfg1);
+        IgniteEx ig2 = startGrid(cfg2);
+        IgniteEx client = startGrid(cfg3);
+    }
+
+    protected void checkStaticCaches() {
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        Assert.assertNotNull(ig1.cache(ccfg1staticName));
+        Assert.assertNotNull(ig1.cache(ccfg2staticName));
+        Assert.assertNotNull(ig1.cache(ccfg3staticName));
+
+        Assert.assertNotNull(ig1.cache(ccfg1staticWithFilterName));
+        Assert.assertNotNull(ig1.cache(ccfg2staticWithFilterName));
+
+        Assert.assertNotNull(ig2.cache(ccfg1staticName));
+        Assert.assertNotNull(ig2.cache(ccfg2staticName));
+        Assert.assertNotNull(ig2.cache(ccfg3staticName));
+
+        Assert.assertNotNull(ig2.cache(ccfg3staticWithFilterName));
+        Assert.assertNotNull(ig2.cache(ccfg2staticWithFilterName));
+
+        Assert.assertNotNull(client.cache(ccfg1staticName));
+        Assert.assertNotNull(client.cache(ccfg2staticName));
+        Assert.assertNotNull(client.cache(ccfg3staticName));
+
+        Assert.assertNotNull(client.cache(ccfg3staticWithFilterName));
+        Assert.assertNotNull(client.cache(ccfg1staticWithFilterName));
+    }
+
+    protected void checkAllCaches() {
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        checkStaticCaches();
+
+        Assert.assertNotNull(ig1.cache(ccfgDynamicName));
+        Assert.assertNotNull(ig1.cache(ccfgDynamicWithFilterName));
+
+        Assert.assertNotNull(ig2.cache(ccfgDynamicName));
+
+        Assert.assertNotNull(client.cache(ccfgDynamicName));
+        Assert.assertNotNull(client.cache(ccfgDynamicWithFilterName));
+    }
+
+    protected void checkOnlySystemCaches() {
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        Assert.assertNull(ig1.cache(ccfg1staticName));
+        Assert.assertNull(ig1.cache(ccfg2staticName));
+        Assert.assertNull(ig1.cache(ccfg3staticName));
+
+        Assert.assertNull(ig1.cache(ccfg1staticWithFilterName));
+        Assert.assertNull(ig1.cache(ccfg2staticWithFilterName));
+
+        Assert.assertNull(ig2.cache(ccfg1staticName));
+        Assert.assertNull(ig2.cache(ccfg2staticName));
+        Assert.assertNull(ig2.cache(ccfg3staticName));
+
+        Assert.assertNull(ig2.cache(ccfg3staticWithFilterName));
+        Assert.assertNull(ig2.cache(ccfg2staticWithFilterName));
+
+        Assert.assertNull(client.cache(ccfg1staticName));
+        Assert.assertNull(client.cache(ccfg2staticName));
+        Assert.assertNull(client.cache(ccfg3staticName));
+
+        Assert.assertNull(client.cache(ccfg3staticWithFilterName));
+        Assert.assertNull(client.cache(ccfg1staticWithFilterName));
+
+        checkDescriptors(ig1,Collections.<String>emptySet());
+        checkDescriptors(ig2,Collections.<String>emptySet());
+        checkDescriptors(client, Collections.<String>emptySet());
+    }
+
+    private static class FilterNode implements IgnitePredicate<ClusterNode> {
+
+        private final String consistentId;
+
+        private FilterNode(String id) {
+            consistentId = id;
+        }
+
+        @Override public boolean apply(ClusterNode node) {
+            return !consistentId.equals(node.consistentId());
+        }
+    }
+
+    private static class AwaitTcpDiscoverySpi extends TcpDiscoverySpi {
+
+        private final CountDownLatch latch;
+
+        private AwaitTcpDiscoverySpi(CountDownLatch latch) {
+            this.latch = latch;
+        }
+
+        @Override public void setListener(@Nullable DiscoverySpiListener lsnr) {
+            super.setListener(new AwaitDiscoverySpiListener(latch, lsnr));
+        }
+    }
+
+    private static class AwaitDiscoverySpiListener implements DiscoverySpiListener {
+
+        private final CountDownLatch latch;
+
+        private final DiscoverySpiListener delegate;
+
+        private AwaitDiscoverySpiListener(
+            CountDownLatch latch,
+            DiscoverySpiListener delegate
+        ) {
+            this.latch = latch;
+            this.delegate = delegate;
+        }
+
+        @Override public void onLocalNodeInitialized(ClusterNode locNode) {
+            delegate.onLocalNodeInitialized(locNode);
+        }
+
+        @Override public void onDiscovery(
+            int type,
+            long topVer,
+            ClusterNode node,
+            Collection<ClusterNode> topSnapshot,
+            @Nullable Map<Long, Collection<ClusterNode>> topHist,
+            @Nullable DiscoverySpiCustomMessage data
+        ) {
+            delegate.onDiscovery(type, topVer, node, topSnapshot, topHist, data);
+
+            if (type == EVT_CLIENT_NODE_DISCONNECTED)
+                try {
+                    System.out.println("Await cluster change state");
+
+                    latch.await();
+                }
+                catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+        }
+    }
+
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        stopAllGrids();
+
+        deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", true));
+    }
+
+    @Override protected void afterTest() throws Exception {
+        super.beforeTest();
+
+        stopAllGrids();
+
+        deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", true));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectTest.java
new file mode 100644
index 0000000..02f7d00
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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.persistence.standbycluster.reconnect;
+
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.internal.IgniteEx;
+
+/**
+ *
+ */
+public class IgniteStandByClientReconnectTest extends IgniteAbstractStandByClientReconnectTest {
+
+    public void testActiveClientReconnectToActiveCluster() throws Exception {
+        CountDownLatch activateLatch = new CountDownLatch(1);
+
+        startNodes(activateLatch);
+
+        info(">>>> star grid");
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        client.active(true);
+
+        info(">>>> activate grid");
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+        checkDescriptors(client, staticCacheNames);
+
+        checkStaticCaches();
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        info(">>>> dynamic start [" + ccfgDynamicName + ", " + ccfgDynamicWithFilterName + "]");
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        info(">>>> stop servers");
+
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig2 = startGrid(getConfiguration(node2));
+
+        info(">>>> activate new servers");
+
+        ig1.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+
+        activateLatch.countDown();
+
+        info(">>>> reconnect client");
+
+        reconnectedLatch.await();
+
+        info(">>>> client reconnected");
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        checkAllCaches();
+    }
+
+    public void testActiveClientReconnectToInActiveCluster() throws Exception {
+        CountDownLatch activateLatch = new CountDownLatch(1);
+
+        startNodes(activateLatch);
+
+        info(">>>> star grid");
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        info(">>>> activate grid");
+
+        client.active(true);
+
+        checkStaticCaches();
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+        checkDescriptors(client, staticCacheNames);
+
+        info(">>>> dynamic start [" + ccfgDynamicName + ", " + ccfgDynamicWithFilterName + "]");
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        info(">>>> stop " + node2);
+
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig1.active(false);
+
+        activateLatch.countDown();
+
+        info(">>>> restart " + node2);
+
+        ig2 = startGrid(getConfiguration(node2));
+
+        reconnectedLatch.await();
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        client.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        checkAllCaches();
+    }
+
+    public void testInActiveClientReconnectToActiveCluster() throws Exception {
+        CountDownLatch activateLatch = new CountDownLatch(1);
+
+        startNodes(activateLatch);
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig2 = startGrid(getConfiguration(node2));
+
+        ig1.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+
+        activateLatch.countDown();
+
+        reconnectedLatch.await();
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        checkAllCaches();
+    }
+
+    public void testInActiveClientReconnectToInActiveCluster() throws Exception {
+        startNodes(null);
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig2 = startGrid(getConfiguration(node2));
+
+        reconnectedLatch.await();
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        client.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkStaticCaches();
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        checkAllCaches();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectToNewClusterTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectToNewClusterTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectToNewClusterTest.java
new file mode 100644
index 0000000..2bcc177
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/reconnect/IgniteStandByClientReconnectToNewClusterTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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.persistence.standbycluster.reconnect;
+
+import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.internal.IgniteEx;
+
+/**
+ *
+ */
+public class IgniteStandByClientReconnectToNewClusterTest extends IgniteAbstractStandByClientReconnectTest {
+
+    public void testActiveClientReconnectToActiveCluster() throws Exception {
+        CountDownLatch activateLatch = new CountDownLatch(1);
+
+        startNodes(activateLatch);
+
+        info(">>>> star grid");
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        info(">>>> activate grid");
+
+        client.active(true);
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+        checkDescriptors(client, staticCacheNames);
+
+        checkStaticCaches();
+
+        info(">>>> dynamic start [" + ccfgDynamicName + ", " + ccfgDynamicWithFilterName + "]");
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        info(">>>> stop servers");
+
+        stopGrid(node1);
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig1 = startGrid(getConfiguration(node1));
+        ig2 = startGrid(getConfiguration(node2));
+
+        info(">>>> activate new servers");
+
+        ig1.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+
+        activateLatch.countDown();
+
+        info(">>>> reconnect client");
+
+        reconnectedLatch.await();
+
+        info(">>>> client reconnected");
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkAllCaches();
+    }
+
+    public void testActiveClientReconnectToInActiveCluster() throws Exception {
+        startNodes(null);
+
+        info(">>>> star grid");
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        info(">>>> activate grid");
+
+        client.active(true);
+
+        checkStaticCaches();
+
+        checkDescriptors(ig1, staticCacheNames);
+        checkDescriptors(ig2, staticCacheNames);
+        checkDescriptors(client, staticCacheNames);
+
+        info(">>>> dynamic start [" + ccfgDynamicName + ", " + ccfgDynamicWithFilterName + "]");
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        checkDescriptors(ig1, allCacheNames);
+        checkDescriptors(ig2, allCacheNames);
+        checkDescriptors(client, allCacheNames);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        info(">>>> stop servers");
+
+        stopGrid(node1);
+        stopGrid(node2);
+
+        assertTrue(client.active());
+
+        System.out.println("Await disconnected");
+
+        disconnectedLatch.await();
+
+        ig1 = startGrid(getConfiguration("node1"));
+        ig2 = startGrid(getConfiguration("node2"));
+
+        info(">>>> reconnect client");
+
+        reconnectedLatch.await();
+
+        info(">>>> client reconnected");
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        info(">>>> activate new servers");
+
+        client.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkAllCaches();
+    }
+
+    public void testInActiveClientReconnectToActiveCluster() throws Exception {
+        CountDownLatch activateLatch = new CountDownLatch(1);
+
+        startNodes(activateLatch);
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        stopGrid(node1);
+        stopGrid(node2);
+
+        disconnectedLatch.await();
+
+        ig1 = startGrid(getConfiguration(node1));
+        ig2 = startGrid(getConfiguration(node2));
+
+        ig1.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+
+        checkDescriptors(ig1, Collections.<String>emptySet());
+        checkDescriptors(ig2, Collections.<String>emptySet());
+
+        activateLatch.countDown();
+
+        reconnectedLatch.await();
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkOnlySystemCaches();
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        Set<String> exp2 = Sets.newHashSet(ccfgDynamicName, ccfgDynamicWithFilterName);
+
+        checkDescriptors(ig1, exp2);
+        checkDescriptors(ig2, exp2);
+        checkDescriptors(client, exp2);
+    }
+
+    public void testInActiveClientReconnectToInActiveCluster() throws Exception {
+        startNodes(null);
+
+        IgniteEx ig1 = grid(node1);
+        IgniteEx ig2 = grid(node2);
+        IgniteEx client = grid(nodeClient);
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        final CountDownLatch disconnectedLatch = new CountDownLatch(1);
+        final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+
+        addDisconnectListener(disconnectedLatch, reconnectedLatch);
+
+        stopGrid(node1);
+        stopGrid(node2);
+
+        assertTrue(!client.active());
+
+        disconnectedLatch.await();
+
+        ig1 = startGrid(getConfiguration(node1));
+        ig2 = startGrid(getConfiguration(node2));
+
+        reconnectedLatch.await();
+
+        assertTrue(!ig1.active());
+        assertTrue(!ig2.active());
+        assertTrue(!client.active());
+
+        client.active(true);
+
+        assertTrue(ig1.active());
+        assertTrue(ig2.active());
+        assertTrue(client.active());
+
+        checkOnlySystemCaches();
+
+        client.createCache(ccfgDynamic);
+
+        client.createCache(ccfgDynamicWithFilter);
+
+        Set<String> exp2 = Sets.newHashSet(ccfgDynamicName, ccfgDynamicWithFilterName);
+
+        checkDescriptors(ig1, exp2);
+        checkDescriptors(ig2, exp2);
+        checkDescriptors(client, exp2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIOTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIOTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIOTest.java
new file mode 100644
index 0000000..b50f026
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIOTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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.persistence.tree.io;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ThreadLocalRandom;
+import junit.framework.TestCase;
+import org.apache.ignite.internal.util.GridUnsafe;
+
+/**
+ *
+ */
+public class TrackingPageIOTest extends TestCase {
+    /** Page size. */
+    public static final int PAGE_SIZE = 2048;
+
+    /** */
+    private final TrackingPageIO io = TrackingPageIO.VERSIONS.latest();
+
+    /**
+     *
+     */
+    public void testBasics() {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        io.markChanged(buf, 2, 0, -1, PAGE_SIZE);
+
+        assertTrue(io.wasChanged(buf, 2, 0, -1, PAGE_SIZE));
+
+        assertFalse(io.wasChanged(buf, 1, 0, -1, PAGE_SIZE));
+        assertFalse(io.wasChanged(buf, 3, 0, -1, PAGE_SIZE));
+        assertFalse(io.wasChanged(buf, 2, 1,  0, PAGE_SIZE));
+    }
+
+    /**
+     *
+     */
+    public void testMarkingRandomly() {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        int cntOfPageToTrack = io.countOfPageToTrack(PAGE_SIZE);
+
+        for (int i = 0; i < 1001; i++)
+            checkMarkingRandomly(buf, i, false);
+    }
+
+    /**
+     *
+     */
+    public void testZeroingRandomly() {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        for (int i = 0; i < 1001; i++)
+            checkMarkingRandomly(buf, i, true);
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param backupId Backup id.
+     */
+    private void checkMarkingRandomly(ByteBuffer buf, int backupId, boolean testZeroing) {
+        ThreadLocalRandom rand = ThreadLocalRandom.current();
+
+        int track = io.countOfPageToTrack(PAGE_SIZE);
+
+        long basePageId = io.trackingPageFor(Math.max(rand.nextLong(Integer.MAX_VALUE - track), 0), PAGE_SIZE);
+
+        long maxId = testZeroing ? basePageId + rand.nextInt(1, track) : basePageId + track;
+
+        assert basePageId >= 0;
+
+        PageIO.setPageId(GridUnsafe.bufferAddress(buf), basePageId);
+
+        Map<Long, Boolean> map = new HashMap<>();
+
+        int cntOfChanged = 0;
+
+        try {
+            for (long i = basePageId; i < basePageId + track; i++) {
+                boolean changed =  (i == basePageId || rand.nextDouble() < 0.5) && i < maxId;
+
+                map.put(i, changed);
+
+                if (changed) {
+                    io.markChanged(buf, i, backupId, backupId - 1, PAGE_SIZE);
+
+                    cntOfChanged++;
+                }
+
+                assertEquals(basePageId, PageIO.getPageId(buf));
+                assertEquals(cntOfChanged, io.countOfChangedPage(buf, backupId,  PAGE_SIZE));
+            }
+
+            assertEquals(cntOfChanged, io.countOfChangedPage(buf, backupId, PAGE_SIZE));
+
+            for (Map.Entry<Long, Boolean> e : map.entrySet())
+                assertEquals(
+                    e.getValue().booleanValue(),
+                    io.wasChanged(buf, e.getKey(), backupId, backupId -1, PAGE_SIZE));
+        }
+        catch (Throwable e) {
+            System.out.println("snapshotId = " + backupId + ", basePageId = " + basePageId);
+            throw e;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFindNextChangedPage() throws Exception {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        for (int i = 0; i < 101; i++)
+            checkFindingRandomly(buf, i);
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param backupId Backup id.
+     */
+    private void checkFindingRandomly(ByteBuffer buf, int backupId) {
+        ThreadLocalRandom rand = ThreadLocalRandom.current();
+
+        int track = io.countOfPageToTrack(PAGE_SIZE);
+
+        long basePageId = io.trackingPageFor(Math.max(rand.nextLong(Integer.MAX_VALUE - track), 0), PAGE_SIZE);
+
+        long maxId = basePageId + rand.nextInt(1, track);
+
+        assert basePageId >= 0;
+
+        PageIO.setPageId(GridUnsafe.bufferAddress(buf), basePageId);
+
+        try {
+            TreeSet<Long> setIdx = new TreeSet<>();
+
+            generateMarking(buf, track, basePageId, maxId, setIdx, backupId, backupId -1);
+
+            for (long pageId = basePageId; pageId < basePageId + track; pageId++) {
+                Long foundNextChangedPage = io.findNextChangedPage(buf, pageId, backupId, backupId - 1, PAGE_SIZE);
+
+                if (io.trackingPageFor(pageId, PAGE_SIZE) == pageId)
+                    assertEquals((Long) pageId, foundNextChangedPage);
+
+                else if (setIdx.contains(pageId))
+                    assertEquals((Long) pageId, foundNextChangedPage);
+
+                else {
+                    NavigableSet<Long> tailSet = setIdx.tailSet(pageId, false);
+                    Long next = tailSet.isEmpty() ? null : tailSet.first();
+
+                    assertEquals(next, foundNextChangedPage);
+                }
+            }
+        }
+        catch (Throwable e) {
+            System.out.println("snapshotId = " + backupId + ", basePageId = " + basePageId);
+            throw e;
+        }
+    }
+
+    /**
+     *
+     */
+    public void testMerging() {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        ThreadLocalRandom rand = ThreadLocalRandom.current();
+
+        int track = io.countOfPageToTrack(PAGE_SIZE);
+
+        long basePageId = io.trackingPageFor(Math.max(rand.nextLong(Integer.MAX_VALUE - track), 0), PAGE_SIZE);
+
+        assert basePageId >= 0;
+
+        PageIO.setPageId(GridUnsafe.bufferAddress(buf), basePageId);
+
+        TreeSet<Long> setIdx = new TreeSet<>();
+
+        for (int i = 0; i < 4; i++)
+            generateMarking(buf, track, basePageId, basePageId + rand.nextInt(1, track), setIdx, i, -1);
+
+        TreeSet<Long> setIdx2 = new TreeSet<>();
+
+        generateMarking(buf, track, basePageId, basePageId + rand.nextInt(1, track), setIdx2, 4, -1);
+
+        assertEquals(setIdx2.size(), io.countOfChangedPage(buf, 4, PAGE_SIZE));
+        assertEquals(setIdx.size(), io.countOfChangedPage(buf, 3, PAGE_SIZE));
+
+        for (long i = basePageId; i < basePageId + track; i++)
+            assertEquals("pageId = " + i, setIdx.contains(i), io.wasChanged(buf, i, 3, -1, PAGE_SIZE));
+
+        for (long i = basePageId; i < basePageId + track; i++)
+            assertEquals("pageId = " + i, setIdx2.contains(i), io.wasChanged(buf, i, 4, 3, PAGE_SIZE));
+
+        for (long i = basePageId; i < basePageId + track; i++)
+            assertFalse(io.wasChanged(buf, i, 5, 4, PAGE_SIZE));
+    }
+
+    /**
+     *
+     */
+    public void testMerging_MarksShouldBeDropForSuccessfulBackup() {
+        ByteBuffer buf = ByteBuffer.allocateDirect(PAGE_SIZE);
+        buf.order(ByteOrder.nativeOrder());
+
+        ThreadLocalRandom rand = ThreadLocalRandom.current();
+
+        int track = io.countOfPageToTrack(PAGE_SIZE);
+
+        long basePageId = io.trackingPageFor(Math.max(rand.nextLong(Integer.MAX_VALUE - track), 0), PAGE_SIZE);
+
+        assert basePageId >= 0;
+
+        PageIO.setPageId(GridUnsafe.bufferAddress(buf), basePageId);
+
+        TreeSet<Long> setIdx = new TreeSet<>();
+
+        for (int i = 0; i < 4; i++)
+            generateMarking(buf, track, basePageId, basePageId + rand.nextInt(1, track), setIdx, i, -1);
+
+        setIdx.clear();
+
+        generateMarking(buf, track, basePageId, basePageId + rand.nextInt(1, track), setIdx, 4, -1);
+
+        TreeSet<Long> setIdx2 = new TreeSet<>();
+
+        generateMarking(buf, track, basePageId, basePageId + rand.nextInt(1, track), setIdx2, 5, 3);
+
+        assertEquals(setIdx.size(), io.countOfChangedPage(buf, 4, PAGE_SIZE));
+        assertEquals(setIdx2.size(), io.countOfChangedPage(buf, 5, PAGE_SIZE));
+
+        for (long i = basePageId; i < basePageId + track; i++)
+            assertEquals("pageId = " + i, setIdx2.contains(i), io.wasChanged(buf, i, 5, 4, PAGE_SIZE));
+    }
+
+    private void generateMarking(
+        ByteBuffer buf,
+        int track,
+        long basePageId,
+        long maxPageId,
+        Set<Long> setIdx,
+        int backupId, int successfulBackupId
+    ) {
+        ThreadLocalRandom rand = ThreadLocalRandom.current();
+
+        for (long i = basePageId; i < basePageId + track; i++) {
+            boolean changed = (i == basePageId || rand.nextDouble() < 0.1) && i < maxPageId;
+
+            if (changed) {
+                io.markChanged(buf, i, backupId, successfulBackupId, PAGE_SIZE);
+
+                setIdx.add(i);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
index 83a07ab..cab54a4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
@@ -20,8 +20,8 @@ package org.apache.ignite.internal.processors.database;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.pagemem.PageMemory;
-import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseBag;
-import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 
 /**
  *

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
index e5375f7..d12c92f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
@@ -22,9 +22,9 @@ import java.util.Set;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
-import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
-import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseListImpl;
 
 import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
index a46242c..fadfc23 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
@@ -41,15 +41,15 @@ import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.PageUtils;
 import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
-import org.apache.ignite.internal.processors.cache.database.DataStructure;
-import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl;
-import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
-import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO;
-import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO;
-import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusLeafIO;
-import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions;
-import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
-import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.DataStructure;
+import org.apache.ignite.internal.processors.cache.persistence.MemoryMetricsImpl;
+import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusInnerIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeafIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.GridRandom;
 import org.apache.ignite.internal.util.GridStripedLock;
@@ -65,7 +65,7 @@ import org.jsr166.ConcurrentHashMap8;
 import org.jsr166.ConcurrentLinkedHashMap;
 
 import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId;
-import static org.apache.ignite.internal.processors.cache.database.tree.BPlusTree.rnd;
+import static org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.rnd;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.NOOP;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.PUT;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.REMOVE;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
index 7ccddb7..d650ac1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/FreeListImplSelfTest.java
@@ -39,12 +39,12 @@ import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
-import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
-import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl;
-import org.apache.ignite.internal.processors.cache.database.MemoryPolicy;
-import org.apache.ignite.internal.processors.cache.database.evict.NoOpPageEvictionTracker;
-import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
-import org.apache.ignite.internal.processors.cache.database.freelist.FreeListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
+import org.apache.ignite.internal.processors.cache.persistence.MemoryMetricsImpl;
+import org.apache.ignite.internal.processors.cache.persistence.MemoryPolicy;
+import org.apache.ignite.internal.processors.cache.persistence.evict.NoOpPageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeListImpl;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;


Mime
View raw message