ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agoncha...@apache.org
Subject [4/4] ignite git commit: Merged 4.ea2 into 5267
Date Wed, 07 Jun 2017 18:09:12 GMT
Merged 4.ea2 into 5267


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

Branch: refs/heads/ignite-5267-merge-ea
Commit: 518238473c0a12380cb9ed96c67597d1fe42652c
Parents: fffad68
Author: Alexey Goncharuk <alexey.goncharuk@gmail.com>
Authored: Wed Jun 7 21:08:36 2017 +0300
Committer: Alexey Goncharuk <alexey.goncharuk@gmail.com>
Committed: Wed Jun 7 21:08:36 2017 +0300

----------------------------------------------------------------------
 assembly/release-fabric-base.xml                |   1 +
 examples/pom-standalone-lgpl.xml                |  19 -
 examples/pom-standalone.xml                     |  19 -
 examples/pom.xml                                |  30 -
 .../apache/ignite/IgniteSystemProperties.java   |   6 +
 .../rendezvous/RendezvousAffinityFunction.java  |   1 -
 .../org/apache/ignite/internal/GridTopic.java   |   6 +-
 .../ignite/internal/IgniteDiagnosticAware.java  |  28 +
 .../internal/IgniteDiagnosticMessage.java       | 490 +++++++++++++++
 .../apache/ignite/internal/IgniteKernal.java    |  46 +-
 .../managers/communication/GridIoManager.java   |   2 +-
 .../communication/GridIoMessageFactory.java     |   6 +
 .../pagemem/snapshot/SnapshotOperation.java     |   4 +-
 .../pagemem/snapshot/SnapshotOperationType.java |   2 +
 ...artSnapshotOperationAckDiscoveryMessage.java |   8 +
 .../internal/pagemem/wal/record/CacheState.java | 133 ++--
 .../wal/record/delta/MetaPageInitRecord.java    |   6 +-
 .../cache/DynamicCacheChangeBatch.java          |  37 ++
 .../cache/DynamicCacheChangeRequest.java        |  11 +-
 .../processors/cache/GridCacheGateway.java      |   5 +-
 .../processors/cache/GridCacheIoManager.java    |  41 ++
 .../GridCachePartitionExchangeManager.java      |  49 +-
 .../processors/cache/GridCacheProcessor.java    |  27 +-
 .../IgniteCacheDatabaseSharedManager.java       |   7 +
 .../cache/database/freelist/PagesList.java      |  57 +-
 .../cache/database/tree/BPlusTree.java          |  11 +-
 .../cache/database/tree/io/PageMetaIO.java      |   7 +-
 .../database/tree/io/PagePartitionMetaIO.java   |  28 +-
 .../dht/GridClientPartitionTopology.java        |  14 +-
 .../distributed/dht/GridDhtCacheEntry.java      |   6 +-
 .../distributed/dht/GridDhtLocalPartition.java  |   2 +-
 .../dht/GridDhtPartitionTopology.java           |   6 +
 .../dht/GridDhtPartitionTopologyImpl.java       | 501 +++++++++------
 .../distributed/dht/GridDhtTxPrepareFuture.java |  30 +-
 .../dht/GridPartitionedSingleGetFuture.java     |  24 +-
 .../colocated/GridDhtColocatedLockFuture.java   |  49 +-
 .../dht/preloader/GridDhtPartitionMap.java      |  23 +-
 .../GridDhtPartitionsExchangeFuture.java        | 214 +++----
 .../dht/preloader/GridDhtPreloader.java         |  27 +-
 .../processors/cluster/ClusterProcessor.java    | 354 +++++++++++
 .../datastructures/DataStructuresProcessor.java |  22 +-
 .../internal/util/GridPartitionStateMap.java    | 174 ++++++
 .../ignite/internal/util/IgniteUtils.java       |  12 +
 .../internal/util/OffheapReadWriteLock.java     |   4 +
 .../ignite/internal/util/nio/GridNioServer.java | 246 ++++++--
 .../communication/tcp/TcpCommunicationSpi.java  | 152 +++--
 .../resources/META-INF/classnames.properties    |  29 +
 ...agnosticMessagesMultipleConnectionsTest.java |  35 ++
 .../managers/IgniteDiagnosticMessagesTest.java  | 152 +++++
 .../CacheClientsConcurrentStartTest.java        | 250 ++++++++
 ...idCacheNearOnlyMultiNodeFullApiSelfTest.java |   4 +-
 .../testframework/junits/GridAbstractTest.java  |   7 +
 .../ignite/testsuites/IgniteCacheTestSuite.java |   4 +
 .../query/h2/database/H2TreeIndex.java          |  10 +-
 .../GridCacheDatabaseSharedManager.java         | 610 +++++++------------
 .../cache/database/GridCacheOffheapManager.java |  30 +-
 .../cache/database/pagemem/PageMemoryImpl.java  |  14 +-
 .../cache/database/wal/FileWALPointer.java      |  22 +
 .../database/wal/FileWriteAheadLogManager.java  |  21 +-
 .../wal/serializer/RecordV1Serializer.java      |  14 +-
 .../IgniteWalHistoryReservationsSelfTest.java   |   1 -
 .../yardstick/IgniteBenchmarkArguments.java     |  33 +
 62 files changed, 3122 insertions(+), 1061 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/assembly/release-fabric-base.xml
----------------------------------------------------------------------
diff --git a/assembly/release-fabric-base.xml b/assembly/release-fabric-base.xml
index 5007785..7484dfa 100644
--- a/assembly/release-fabric-base.xml
+++ b/assembly/release-fabric-base.xml
@@ -239,6 +239,7 @@
             <excludes>
                 <exclude>**/package.html</exclude>
                 <exclude>src/test/**</exclude>
+                <exclude>src/main/ml/**</exclude>
             </excludes>
         </fileSet>
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/examples/pom-standalone-lgpl.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone-lgpl.xml b/examples/pom-standalone-lgpl.xml
index 4798d03..e7eca1e 100644
--- a/examples/pom-standalone-lgpl.xml
+++ b/examples/pom-standalone-lgpl.xml
@@ -33,7 +33,6 @@
         <lgpl.folder>src/main/java</lgpl.folder>
         <java8.folder>src/main/java</java8.folder>
         <spark.folder>src/main/java</spark.folder>
-        <ml.folder>src/main/java</ml.folder>
         <java.ver>1.7</java.ver>
     </properties>
 
@@ -106,23 +105,6 @@
         </profile>
 
         <profile>
-            <id>ml</id>
-
-            <properties>
-                <ml.folder>src/main/ml</ml.folder>
-                <java.ver>1.8</java.ver>
-            </properties>
-
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.ignite</groupId>
-                    <artifactId>ignite-ml</artifactId>
-                    <version>to_be_replaced_by_ignite_version</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
             <id>scala</id>
 
             <properties>
@@ -248,7 +230,6 @@
                                 <source>${lgpl.folder}</source>
                                 <source>${java8.folder}</source>
                                 <source>${spark.folder}</source>
-                                <source>${ml.folder}</source>
                             </sources>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/examples/pom-standalone.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone.xml b/examples/pom-standalone.xml
index e74082c..65b5402 100644
--- a/examples/pom-standalone.xml
+++ b/examples/pom-standalone.xml
@@ -33,7 +33,6 @@
         <lgpl.folder>src/main/java</lgpl.folder>
         <java8.folder>src/main/java</java8.folder>
         <spark.folder>src/main/java</spark.folder>
-        <ml.folder>src/main/java</ml.folder>
         <java.ver>1.7</java.ver>
     </properties>
 
@@ -106,23 +105,6 @@
         </profile>
 
         <profile>
-            <id>ml</id>
-
-            <properties>
-                <ml.folder>src/main/ml</ml.folder>
-                <java.ver>1.8</java.ver>
-            </properties>
-
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.ignite</groupId>
-                    <artifactId>ignite-ml</artifactId>
-                    <version>to_be_replaced_by_ignite_version</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
             <id>scala</id>
 
             <properties>
@@ -249,7 +231,6 @@
                                 <source>${lgpl.folder}</source>
                                 <source>${java8.folder}</source>
                                 <source>${spark.folder}</source>
-                                <source>${ml.folder}</source>
                             </sources>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index 4768270..f749d7c 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -107,7 +107,6 @@
         <lgpl.folder>src/main/java</lgpl.folder>
         <java8.folder>src/main/java</java8.folder>
         <spark.folder>src/main/java</spark.folder>
-        <ml.folder>src/main/java</ml.folder>
         <spark.test.folder>src/test/java</spark.test.folder>
         <lgpl.test.folder>src/test/java</lgpl.test.folder>
         <java8.test.folder>src/test/java</java8.test.folder>
@@ -242,34 +241,6 @@
         </profile>
 
         <profile>
-            <id>ml</id>
-
-            <properties>
-                <ml.folder>src/main/ml</ml.folder>
-            </properties>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <source>1.8</source>
-                            <target>1.8</target>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.ignite</groupId>
-                    <artifactId>ignite-ml</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
             <id>lgpl</id>
 
             <properties>
@@ -328,7 +299,6 @@
                                 <source>${lgpl.folder}</source>
                                 <source>${java8.folder}</source>
                                 <source>${spark.folder}</source>
-                                <source>${ml.folder}</source>
                             </sources>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 8606175..3eec361 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -448,6 +448,12 @@ public final class IgniteSystemProperties {
     /** If this property is set to {@code true} then Ignite will log thread dump in case of partition exchange timeout. */
     public static final String IGNITE_THREAD_DUMP_ON_EXCHANGE_TIMEOUT = "IGNITE_THREAD_DUMP_ON_EXCHANGE_TIMEOUT";
 
+    /** */
+    public static final String IGNITE_IO_DUMP_ON_TIMEOUT = "IGNITE_IO_DUMP_ON_TIMEOUT";
+
+    /** */
+    public static final String IGNITE_DIAGNOSTIC_ENABLED = "IGNITE_DIAGNOSTIC_ENABLED";
+
     /** Cache operations that take more time than value of this property will be output to log. Set to {@code 0} to disable. */
     public static final String IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT = "IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT";
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/cache/affinity/rendezvous/RendezvousAffinityFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/affinity/rendezvous/RendezvousAffinityFunction.java b/modules/core/src/main/java/org/apache/ignite/cache/affinity/rendezvous/RendezvousAffinityFunction.java
index f673e9c..1bd0587 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/affinity/rendezvous/RendezvousAffinityFunction.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/affinity/rendezvous/RendezvousAffinityFunction.java
@@ -163,7 +163,6 @@ public class RendezvousAffinityFunction implements AffinityFunction, Serializabl
     private RendezvousAffinityFunction(boolean exclNeighbors, int parts,
         IgniteBiPredicate<ClusterNode, ClusterNode> backupFilter) {
         A.ensure(parts > 0, "parts > 0");
-        A.ensure(parts <= CacheConfiguration.MAX_PARTITIONS_COUNT, "parts <=" + CacheConfiguration.MAX_PARTITIONS_COUNT);
 
         this.exclNeighbors = exclNeighbors;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
index c382999..abdbf95 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
@@ -96,6 +96,7 @@ public enum GridTopic {
     /** */
     TOPIC_TX,
 
+    /** */
     TOPIC_SNAPSHOT,
 
     /** */
@@ -111,7 +112,10 @@ public enum GridTopic {
     TOPIC_METADATA_REQ,
 
     /** */
-    TOPIC_SCHEMA;
+    TOPIC_SCHEMA,
+
+    /** */
+    TOPIC_INTERNAL_DIAGNOSTIC;
 
     /** Enum values. */
     private static final GridTopic[] VALS = values();

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticAware.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticAware.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticAware.java
new file mode 100644
index 0000000..f41c178
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticAware.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ *
+ */
+public interface IgniteDiagnosticAware {
+    /**
+     *
+     */
+    public void dumpDiagnosticInfo();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticMessage.java
new file mode 100644
index 0000000..4b28806
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteDiagnosticMessage.java
@@ -0,0 +1,490 @@
+/*
+ * 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;
+
+import java.nio.ByteBuffer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.managers.communication.GridIoMessageFactory;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheMapEntry;
+import org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
+import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.future.GridFinishedFuture;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteClosure;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+
+/**
+ *
+ */
+public class IgniteDiagnosticMessage implements Message {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private static final ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
+        @Override protected DateFormat initialValue() {
+            return new SimpleDateFormat("HH:mm:ss.SSS");
+        }
+    };
+
+    /** */
+    private long futId;
+
+    /** */
+    private String msg;
+
+    /** */
+    private byte[] cBytes;
+
+    /**
+     * Required by {@link GridIoMessageFactory}.
+     */
+    public IgniteDiagnosticMessage() {
+        // No-op.
+    }
+
+    /**
+     * @param ctx Context.
+     * @param c Closure to run.
+     * @param futId Future ID.
+     * @return Request message.
+     * @throws IgniteCheckedException If failed.
+     */
+    public static IgniteDiagnosticMessage createRequest(GridKernalContext ctx,
+        IgniteClosure<GridKernalContext, String> c,
+        long futId)
+        throws IgniteCheckedException
+    {
+        byte[] cBytes = U.marshal(ctx.config().getMarshaller(), c);
+
+        IgniteDiagnosticMessage msg = new IgniteDiagnosticMessage();
+
+        msg.futId = futId;
+        msg.cBytes = cBytes;
+
+        return msg;
+    }
+
+    /**
+     * @param msg0 Message.
+     * @param futId Future ID.
+     * @return Response message.
+     */
+    public static IgniteDiagnosticMessage createResponse(String msg0, long futId) {
+        IgniteDiagnosticMessage msg = new IgniteDiagnosticMessage();
+
+        msg.futId = futId;
+        msg.msg = msg0;
+
+        return msg;
+    }
+
+    /**
+     * @param ctx Context.
+     * @return Unmarshalled closure.
+     * @throws IgniteCheckedException If failed.
+     */
+    public IgniteClosure<GridKernalContext, String> unmarshalClosure(GridKernalContext ctx)
+        throws IgniteCheckedException {
+        assert cBytes != null;
+
+        return U.unmarshal(ctx, cBytes, null);
+    }
+
+    /**
+     * @return Future ID.
+     */
+    public long futureId() {
+        return futId;
+    }
+
+    /**
+     * @return {@code True} if this is request message.
+     */
+    public boolean request() {
+        return cBytes != null;
+    }
+
+    /**
+     * @return Message string.
+     */
+    public String message() {
+        return msg;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 0:
+                if (!writer.writeByteArray("cBytes", cBytes))
+                    return false;
+
+                writer.incrementState();
+
+            case 1:
+                if (!writer.writeLong("futId", futId))
+                    return false;
+
+                writer.incrementState();
+
+            case 2:
+                if (!writer.writeString("msg", msg))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        switch (reader.state()) {
+            case 0:
+                cBytes = reader.readByteArray("cBytes");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 1:
+                futId = reader.readLong("futId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 2:
+                msg = reader.readString("msg");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(IgniteDiagnosticMessage.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public short directType() {
+        return -61;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 3;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onAckReceived() {
+        // No-op.
+    }
+
+    /**
+     *
+     */
+    public static class BaseClosure implements IgniteClosure<GridKernalContext, String> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        protected final UUID nodeId;
+
+        /**
+         * @param ctx Local node context.
+         */
+        public BaseClosure(GridKernalContext ctx) {
+            this.nodeId = ctx.localNodeId();
+        }
+
+        /** {@inheritDoc} */
+        @Override public final String apply(GridKernalContext ctx) {
+            try {
+                StringBuilder sb = new StringBuilder();
+
+                IgniteInternalFuture<String> commInfo = dumpCommunicationInfo(ctx, nodeId);
+
+                sb.append(dumpNodeBasicInfo(ctx));
+
+                sb.append(U.nl()).append(dumpExchangeInfo(ctx));
+
+                String moreInfo = dumpInfo(ctx);
+
+                sb.append(U.nl()).append(commInfo.get());
+
+                if (moreInfo != null)
+                    sb.append(U.nl()).append(moreInfo);
+
+                return sb.toString();
+            }
+            catch (Exception e) {
+                ctx.cluster().diagnosticLog().error("Failed to execute diagnostic message closure: " + e, e);
+
+                return "Failed to execute diagnostic message closure: " + e;
+            }
+        }
+
+        /**
+         * @param ctx Context.
+         * @return Message.
+         */
+        protected String dumpInfo(GridKernalContext ctx) {
+            return null;
+        }
+    }
+
+    /**
+     *
+     */
+    public static class TxEntriesInfoClosure extends BaseClosure {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final int cacheId;
+
+        /** */
+        private final Collection<KeyCacheObject> keys;
+
+        /**
+         * @param ctx Context.
+         * @param cacheId Cache ID.
+         * @param keys Keys.
+         */
+        public TxEntriesInfoClosure(GridKernalContext ctx, int cacheId, Collection<KeyCacheObject> keys) {
+            super(ctx);
+
+            this.cacheId = cacheId;
+            this.keys = keys;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected String dumpInfo(GridKernalContext ctx) {
+            GridCacheContext cctx = ctx.cache().context().cacheContext(cacheId);
+
+            if (cctx == null)
+                return "Failed to find cache with id: " + cacheId;
+
+            try {
+                for (KeyCacheObject key : keys)
+                    key.finishUnmarshal(cctx.cacheObjectContext(), null);
+            }
+            catch (IgniteCheckedException e) {
+                ctx.cluster().diagnosticLog().error("Failed to unmarshal key: " + e, e);
+
+                return "Failed to unmarshal key: " + e;
+            }
+
+            StringBuilder sb = new StringBuilder("Cache entries [cacheId=" + cacheId + ", cacheName=" + cctx.name() + "]: ");
+
+            for (KeyCacheObject key : keys) {
+                sb.append(U.nl());
+
+                GridCacheMapEntry e = (GridCacheMapEntry)cctx.cache().peekEx(key);
+
+                sb.append("Key [key=").append(key).append(", entry=").append(e).append("]");
+            }
+
+            return sb.toString();
+        }
+    }
+
+    /**
+     *
+     */
+    public static class ExchangeInfoClosure extends BaseClosure {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final AffinityTopologyVersion topVer;
+
+        /**
+         * @param ctx Context.
+         * @param topVer Exchange version.
+         */
+        public ExchangeInfoClosure(GridKernalContext ctx, AffinityTopologyVersion topVer) {
+            super(ctx);
+
+            this.topVer = topVer;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected String dumpInfo(GridKernalContext ctx) {
+            List<GridDhtPartitionsExchangeFuture> futs = ctx.cache().context().exchange().exchangeFutures();
+
+            for (GridDhtPartitionsExchangeFuture fut : futs) {
+                if (topVer.equals(fut.topologyVersion()))
+                    return "Exchange future: " + fut;
+            }
+
+            return "Failed to find exchange future: " + topVer;
+        }
+    }
+
+    /**
+     *
+     */
+    public static class TxInfoClosure extends BaseClosure {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final GridCacheVersion dhtVer;
+
+        /** */
+        private final GridCacheVersion nearVer;
+
+        /**
+         * @param ctx Context.
+         * @param dhtVer Tx dht version.
+         * @param nearVer Tx near version.
+         */
+        public TxInfoClosure(GridKernalContext ctx,
+            GridCacheVersion dhtVer,
+            GridCacheVersion nearVer) {
+            super(ctx);
+
+            this.dhtVer = dhtVer;
+            this.nearVer = nearVer;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected String dumpInfo(GridKernalContext ctx) {
+            StringBuilder b = new StringBuilder();
+
+            b.append("Related transactions [dhtVer=").append(dhtVer).
+                append(", nearVer=").append(nearVer).append("]: ");
+
+            boolean found = false;
+
+            for (IgniteInternalTx tx : ctx.cache().context().tm().activeTransactions()) {
+                if (dhtVer.equals(tx.xidVersion()) || nearVer.equals(tx.nearXidVersion())) {
+                    found = true;
+
+                    b.append(U.nl());
+                    b.append("Found related ttx [ver=").append(tx.xidVersion()).
+                        append(", nearVer=").append(tx.nearXidVersion()).
+                        append(", topVer=").append(tx.topologyVersion()).
+                        append(", state=").append(tx.state()).
+                        append(", fullTx=").append(tx).
+                        append("]");
+                }
+            }
+
+            if (!found) {
+                b.append(U.nl());
+                b.append("Failed to find related transactions.");
+            }
+
+            return b.toString();
+        }
+    }
+
+    /**
+     * @param ctx Context.
+     * @return Node information string.
+     */
+    static String dumpNodeBasicInfo(GridKernalContext ctx) {
+        StringBuilder sb = new StringBuilder("General node info [id=").append(ctx.localNodeId());
+
+        sb.append(", client=").append(ctx.clientNode());
+        sb.append(", discoTopVer=").append(ctx.discovery().topologyVersionEx());
+        sb.append(", time=").append(formatTime(U.currentTimeMillis()));
+
+        sb.append(']');
+
+        return sb.toString();
+    }
+
+    /**
+     * @param ctx Context.
+     * @return Exchange information string.
+     */
+    static String dumpExchangeInfo(GridKernalContext ctx) {
+        GridCachePartitionExchangeManager exchMgr = ctx.cache().context().exchange();
+
+        StringBuilder sb = new StringBuilder("Partitions exchange info [readyVer=").append(exchMgr.readyAffinityVersion());
+        sb.append("]");
+
+        GridDhtTopologyFuture fut = exchMgr.lastTopologyFuture();
+
+        sb.append(U.nl()).append("Last initialized exchange future: ").append(fut);
+        
+        return sb.toString();
+    }
+
+    /**
+     * @param ctx Context.
+     * @param nodeId Target node ID.
+     * @return Communication information future.
+     */
+    public static IgniteInternalFuture<String> dumpCommunicationInfo(GridKernalContext ctx, UUID nodeId) {
+        if (ctx.config().getCommunicationSpi() instanceof TcpCommunicationSpi)
+            return ((TcpCommunicationSpi) ctx.config().getCommunicationSpi()).dumpNodeStatistics(nodeId);
+        else
+            return new GridFinishedFuture<>("Unexpected communication SPI: " + ctx.config().getCommunicationSpi());
+    }
+    /**
+     * @param time Time.
+     * @return Time string.
+     */
+    private static String formatTime(long time) {
+        return dateFormat.get().format(new Date(time));
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(IgniteDiagnosticMessage.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index bce3032..f092e2b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -921,26 +921,27 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
 
             // Start processors before discovery manager, so they will
             // be able to start receiving messages once discovery completes.
-            try {startProcessor(createComponent(DiscoveryNodeValidationProcessor.class, ctx));
-            startProcessor(new  GridAffinityProcessor(ctx));
-            startProcessor(createComponent(GridSegmentationProcessor.class, ctx));
-            startProcessor(createComponent(IgniteCacheObjectProcessor.class, ctx));
-            startProcessor(new GridCacheProcessor(ctx));startProcessor(new GridClusterStateProcessor(ctx));
-            startProcessor(new GridQueryProcessor(ctx));
-            startProcessor(new SqlListenerProcessor(ctx));
-            startProcessor(new GridServiceProcessor(ctx));
-            startProcessor(new GridTaskSessionProcessor(ctx));
-            startProcessor(new GridJobProcessor(ctx));
-            startProcessor(new GridTaskProcessor(ctx));
-            startProcessor((GridProcessor)SCHEDULE.createOptional(ctx));
-            startProcessor(new GridRestProcessor(ctx));
-            startProcessor(new DataStreamProcessor(ctx));
-            startProcessor((GridProcessor)IGFS.create(ctx, F.isEmpty(cfg.getFileSystemConfiguration())));
-            startProcessor(new GridContinuousProcessor(ctx));
-            startProcessor(createHadoopComponent());
-            startProcessor(new DataStructuresProcessor(ctx));
-            startProcessor(createComponent(PlatformProcessor.class, ctx));
-            startProcessor(new GridMarshallerMappingProcessor(ctx));
+            try {
+                startProcessor(createComponent(DiscoveryNodeValidationProcessor.class, ctx));
+                startProcessor(new  GridAffinityProcessor(ctx));
+                startProcessor(createComponent(GridSegmentationProcessor.class, ctx));
+                startProcessor(createComponent(IgniteCacheObjectProcessor.class, ctx));
+                startProcessor(new GridCacheProcessor(ctx));startProcessor(new GridClusterStateProcessor(ctx));
+                startProcessor(new GridQueryProcessor(ctx));
+                startProcessor(new SqlListenerProcessor(ctx));
+                startProcessor(new GridServiceProcessor(ctx));
+                startProcessor(new GridTaskSessionProcessor(ctx));
+                startProcessor(new GridJobProcessor(ctx));
+                startProcessor(new GridTaskProcessor(ctx));
+                startProcessor((GridProcessor)SCHEDULE.createOptional(ctx));
+                startProcessor(new GridRestProcessor(ctx));
+                startProcessor(new DataStreamProcessor(ctx));
+                startProcessor((GridProcessor)IGFS.create(ctx, F.isEmpty(cfg.getFileSystemConfiguration())));
+                startProcessor(new GridContinuousProcessor(ctx));
+                startProcessor(createHadoopComponent());
+                startProcessor(new DataStructuresProcessor(ctx));
+                startProcessor(createComponent(PlatformProcessor.class, ctx));
+                startProcessor(new GridMarshallerMappingProcessor(ctx));
 
                 // Start plugins.
                 for (PluginProvider provider : ctx.plugins().allProviders()) {
@@ -949,9 +950,12 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
                     provider.start(ctx.plugins().pluginContextForProvider(provider));
                 }
 
+                ctx.cluster().initListeners();
+
                 // Start platform plugins.
                 if (ctx.config().getPlatformConfiguration() != null)
-                    startProcessor(new PlatformPluginProcessor(ctx));fillNodeAttributes(clusterProc.updateNotifierEnabled());}
+                    startProcessor(new PlatformPluginProcessor(ctx));fillNodeAttributes(clusterProc.updateNotifierEnabled());
+            }
             catch (Throwable e) {
                 U.error(
                     log, "Exception during start processors, node will be stopped and close connections", e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
index ea49dbe..3769a9c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
@@ -2296,7 +2296,7 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         CommunicationSpi spi = getSpi();
 
         if (spi instanceof TcpCommunicationSpi)
-            ((TcpCommunicationSpi)spi).dumpStats();
+            ((TcpCommunicationSpi)spi).dumpDiagnosticInfo();
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 4bb9c9f..8f1c66e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.GridJobSiblingsRequest;
 import org.apache.ignite.internal.GridJobSiblingsResponse;
 import org.apache.ignite.internal.GridTaskCancelRequest;
 import org.apache.ignite.internal.GridTaskSessionRequest;
+import org.apache.ignite.internal.IgniteDiagnosticMessage;
 import org.apache.ignite.internal.binary.BinaryEnumObjectImpl;
 import org.apache.ignite.internal.binary.BinaryObjectImpl;
 import org.apache.ignite.internal.managers.checkpoint.GridCheckpointRequest;
@@ -177,6 +178,11 @@ public class GridIoMessageFactory implements MessageFactory {
 
         switch (type) {
             // -54 is reserved for SQL.
+            // -46 ... -51 - snapshot messages.
+            case -61:
+                msg = new IgniteDiagnosticMessage();
+
+                break;
 
             case -53:
                 msg = new SchemaOperationStatusMessage();

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperation.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperation.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperation.java
index bdcc05a..eb07b0d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperation.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperation.java
@@ -124,7 +124,9 @@ public class SnapshotOperation implements Serializable {
      * @param op Op.
      */
     public static Collection<File> getOptionalPathsParameter(SnapshotOperation op) {
-        assert (op.type() == SnapshotOperationType.CHECK || op.type() == SnapshotOperationType.RESTORE)
+        assert (op.type() == SnapshotOperationType.CHECK ||
+                op.type() == SnapshotOperationType.RESTORE ||
+                op.type() == SnapshotOperationType.RESTORE_2_PHASE)
             && (op.extraParameter() == null || op.extraParameter() instanceof Collection);
 
         return (Collection<File>)op.extraParameter();

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperationType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperationType.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperationType.java
index 3fa6d2a..c3b3a2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperationType.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/SnapshotOperationType.java
@@ -23,6 +23,8 @@ public enum SnapshotOperationType {
     CREATE,
     /** Restore. */
     RESTORE,
+    /** Restore 2. */
+    RESTORE_2_PHASE,
     /** Move. */
     MOVE,
     /** Delete. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/StartSnapshotOperationAckDiscoveryMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/StartSnapshotOperationAckDiscoveryMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/StartSnapshotOperationAckDiscoveryMessage.java
index 72defd4..af7648d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/StartSnapshotOperationAckDiscoveryMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/snapshot/StartSnapshotOperationAckDiscoveryMessage.java
@@ -81,6 +81,14 @@ public class StartSnapshotOperationAckDiscoveryMessage implements DiscoveryCusto
     /**
      *
      */
+    public boolean needExchange() {
+        /* exchange for trigger saving cluster state*/
+        return err == null && snapshotOperation.type() == SnapshotOperationType.CREATE;
+    }
+
+    /**
+     *
+     */
     public IgniteUuid operationId() {
         return opId;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/CacheState.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/CacheState.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/CacheState.java
index 638acfa..1c8b04a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/CacheState.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/CacheState.java
@@ -17,19 +17,28 @@
 
 package org.apache.ignite.internal.pagemem.wal.record;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.ignite.internal.util.tostring.GridToStringInclude;
-import org.apache.ignite.internal.util.typedef.internal.S;
+import java.util.Arrays;
 
 /**
  *
  */
 public class CacheState {
     /** */
-    @GridToStringInclude
-    private Map<Integer, PartitionState> parts;
+    private short[] parts;
+
+    /** */
+    private long[] vals;
+
+    /** */
+    private int idx;
+
+    /**
+     * @param partsCnt Partitions count.
+     */
+    public CacheState(int partsCnt) {
+        parts = new short[partsCnt];
+        vals = new long[partsCnt * 2];
+    }
 
     /**
      * @param partId Partition ID to add.
@@ -37,60 +46,88 @@ public class CacheState {
      * @param cntr Partition counter.
      */
     public void addPartitionState(int partId, long size, long cntr) {
-        if (parts == null)
-            parts = new HashMap<>();
+        if (idx == parts.length)
+            throw new IllegalStateException("Failed to add new partition to the partitions state " +
+                "(no enough space reserved) [partId=" + partId + ", reserved=" + parts.length + ']');
+
+        if (idx > 0) {
+            if (parts[idx - 1] >= partId)
+                throw new IllegalStateException("Adding partition in a wrong order [prev=" + parts[idx - 1] +
+                    ", cur=" + partId + ']');
+        }
+
+        parts[idx] = (short)partId;
+        vals[2 * idx] = size;
+        vals[2 * idx + 1] = cntr;
 
-        parts.put(partId, new PartitionState(size, cntr));
+        idx++;
     }
 
     /**
-     * @return Partitions map.
+     * Gets partition size by partition ID.
+     *
+     * @param partId Partition ID.
+     * @return Partition size (will return {@code -1} if partition is not present in the record).
      */
-    public Map<Integer, PartitionState> partitions() {
-        return parts == null ? Collections.<Integer, PartitionState>emptyMap() : parts;
-    }
+    public long sizeByPartition(int partId) {
+        int idx = indexByPartition(partId);
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(CacheState.class, this);
+        return idx >= 0 ? vals[2 * idx] : -1;
     }
 
     /**
+     * Gets partition counter by partition ID.
      *
+     * @param partId Partition ID.
+     * @return Partition update counter (will return {@code -1} if partition is not present in the record).
      */
-    public static class PartitionState {
-        /** */
-        private final long size;
-
-        /** */
-        private final long partCnt;
-
-        /**
-         * @param size Partition size.
-         * @param partCnt Partition counter.
-         */
-        public PartitionState(long size, long partCnt) {
-            this.size = size;
-            this.partCnt = partCnt;
-        }
+    public long counterByPartition(int partId) {
+        int idx = indexByPartition(partId);
 
-        /**
-         * @return Partition size.
-         */
-        public long size() {
-            return size;
-        }
+        return idx >= 0 ? vals[2 * idx + 1] : 0;
+    }
 
-        /**
-         * @return Partition counter.
-         */
-        public long partitionCounter() {
-            return partCnt;
-        }
+    /**
+     * @param idx Index to get.
+     * @return Partition ID.
+     */
+    public int partitionByIndex(int idx) {
+        return parts[idx] & 0xFFFF;
+    }
 
-        /** {@inheritDoc} */
-        @Override public String toString() {
-            return S.toString(PartitionState.class, this);
-        }
+    /**
+     * @param idx Index to get.
+     * @return Partition size by index.
+     */
+    public long partitionSizeByIndex(int idx) {
+        return vals[idx * 2];
+    }
+
+    /**
+     * @param idx Index to get.
+     * @return Partition size by index.
+     */
+    public long partitionCounterByIndex(int idx) {
+        return vals[idx * 2 + 1];
+    }
+
+    /**
+     * @return State size.
+     */
+    public int size() {
+        return idx;
+    }
+
+    /**
+     * @param partId Partition ID to search.
+     * @return Non-negative index of partition if found or negative value if not found.
+     */
+    private int indexByPartition(int partId) {
+        return Arrays.binarySearch(parts, 0, idx, (short)partId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return "CacheState [cap=" + parts.length + ", size=" + idx + ']';
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
index 5c99d54..1daf5a1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
@@ -66,10 +66,8 @@ public class MetaPageInitRecord extends InitNewPageRecord {
         return reuseListRoot;
     }
 
-    /**
-     * @return IO type.
-     */
-    public int ioType() {
+    /** {@inheritDoc} */
+    @Override public int ioType() {
         return ioType;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeBatch.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeBatch.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeBatch.java
index 3c65326..d5c820f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeBatch.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeBatch.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.cache;
 
 import java.util.Collection;
+import java.util.Set;
 import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.F;
@@ -42,6 +43,12 @@ public class DynamicCacheChangeBatch implements DiscoveryCustomMessage {
     /** Cache updates to be executed on exchange. */
     private transient ExchangeActions exchangeActions;
 
+    /** */
+    private boolean startCaches;
+
+    /** Restarting caches. */
+    private Set<String> restartingCaches;
+
     /**
      * @param reqs Requests.
      */
@@ -96,6 +103,36 @@ public class DynamicCacheChangeBatch implements DiscoveryCustomMessage {
         this.exchangeActions = exchangeActions;
     }
 
+    /**
+     * @return {@code True} if required to start all caches on client node.
+     */
+    public boolean startCaches() {
+        return startCaches;
+    }
+
+    /**
+     * @param restartingCaches Restarting caches.
+     */
+    public DynamicCacheChangeBatch restartingCaches(Set<String> restartingCaches) {
+        this.restartingCaches = restartingCaches;
+
+        return this;
+    }
+
+    /**
+     * @return Set of restarting caches.
+     */
+    public Set<String> restartingCaches() {
+        return restartingCaches;
+    }
+
+    /**
+     * @param startCaches {@code True} if required to start all caches on client node.
+     */
+    public void startCaches(boolean startCaches) {
+        this.startCaches = startCaches;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(DynamicCacheChangeBatch.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
index ecd12ba..7c0c55c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
@@ -22,7 +22,6 @@ import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.query.QuerySchema;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
-import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
 import org.jetbrains.annotations.Nullable;
 
@@ -47,6 +46,7 @@ public class DynamicCacheChangeRequest implements Serializable {
     private String cacheName;
 
     /** Cache start configuration. */
+    @GridToStringExclude
     private CacheConfiguration startCfg;
 
     /** Cache type. */
@@ -56,6 +56,7 @@ public class DynamicCacheChangeRequest implements Serializable {
     private UUID initiatingNodeId;
 
     /** Near cache configuration. */
+    @GridToStringExclude
     private NearCacheConfiguration nearCacheCfg;
 
     /** Start only client cache, do not start data nodes. */
@@ -446,6 +447,12 @@ public class DynamicCacheChangeRequest implements Serializable {
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(DynamicCacheChangeRequest.class, this, "cacheName", cacheName());
+        return "DynamicCacheChangeRequest [cacheName=" + cacheName() +
+            ", hasCfg=" + (startCfg != null) +
+            ", nodeId=" + initiatingNodeId +
+            ", clientStartOnly=" + clientStartOnly +
+            ", close=" + close +
+            ", stop=" + stop +
+            ']';
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
index b9a4b25..81c7b6b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
@@ -304,8 +304,11 @@ public class GridCacheGateway<K, V> {
             try {
                 if (rwLock.writeLock().tryLock(200, TimeUnit.MILLISECONDS))
                     break;
-                else
+                else {
                     U.sleep(200);
+
+                    ctx.affinity().cancelFutures();
+                }
             }
             catch (IgniteInterruptedCheckedException | InterruptedException ignore) {
                 interrupted = true;

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
index a251047..ebb6bf2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
@@ -17,12 +17,15 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
@@ -126,6 +129,26 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
     /** Deployment enabled. */
     private boolean depEnabled;
 
+    /** */
+    private final List<GridCacheMessage> pendingMsgs = new ArrayList<>();
+
+    /**
+     *
+     */
+    public void dumpPendingMessages() {
+        synchronized (pendingMsgs) {
+            if (pendingMsgs.isEmpty())
+                return;
+
+            log.info("Pending cache messages waiting for exchange [" +
+                "readyVer=" + cctx.exchange().readyAffinityVersion() +
+                ", discoVer=" + cctx.discovery().topologyVersion() + ']');
+
+            for (GridCacheMessage msg : pendingMsgs)
+                log.info("Message [waitVer=" + msg.topologyVersion() + ", msg=" + msg + ']');
+        }
+    }
+
     /** Message listener. */
     private GridMessageListener lsnr = new GridMessageListener() {
         @Override public void onMessage(final UUID nodeId, final Object msg) {
@@ -218,10 +241,19 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
 
                 final int stripe = curThread instanceof IgniteThread ? ((IgniteThread)curThread).stripe() : -1;
 
+                synchronized (pendingMsgs) {
+                    if (pendingMsgs.size() < 100)
+                        pendingMsgs.add(cacheMsg);
+                }
+
                 fut.listen(new CI1<IgniteInternalFuture<?>>() {
                     @Override public void apply(IgniteInternalFuture<?> t) {
                         Runnable c = new Runnable() {
                             @Override public void run() {
+                                synchronized (pendingMsgs) {
+                                    pendingMsgs.remove(cacheMsg);
+                                }
+
                                 IgniteLogger log = cacheMsg.messageLogger(cctx);
 
                                 if (log.isDebugEnabled()) {
@@ -309,6 +341,15 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
             else
                 U.error(log, msg0.toString());
 
+            try {
+                cacheMsg.onClassError(new IgniteCheckedException("Failed to find message handler for message: " + cacheMsg));
+
+                processFailedMessage(nodeId, cacheMsg, c);
+            }
+            catch (Exception e) {
+                U.error(log, "Failed to process failed message: " + e, e);
+            }
+
             return;
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
index ae4c164..2053c72 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
@@ -49,6 +49,7 @@ import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
+import org.apache.ignite.internal.IgniteDiagnosticAware;
 import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
@@ -119,7 +120,8 @@ import static org.apache.ignite.internal.processors.cache.distributed.dht.preloa
  */
 public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedManagerAdapter<K, V> {
     /** Exchange history size. */
-    private static final int EXCHANGE_HISTORY_SIZE = 1000;
+    private static final int EXCHANGE_HISTORY_SIZE =
+        IgniteSystemProperties.getInteger("IGNITE_EXCHANGE_HISTORY_SIZE", 1000);
 
     /** Atomic reference for pending timeout object. */
     private AtomicReference<ResendTimeoutObject> pendingResend = new AtomicReference<>();
@@ -254,13 +256,12 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                                 exchFut = exchangeFuture(exchId, evt, cache, null, msg);
                             }
                         }
-                        else {
+                        else
                             exchangeFuture(msg.exchangeId(), null, null, null, null)
                                 .onAffinityChangeMessage(evt.eventNode(), msg);
-                        }
                     }
                     else if (customMsg instanceof StartSnapshotOperationAckDiscoveryMessage
-                        && !((StartSnapshotOperationAckDiscoveryMessage)customMsg).hasError()) {
+                        && ((StartSnapshotOperationAckDiscoveryMessage)customMsg).needExchange()) {
                         exchId = exchangeId(n.id(), affinityTopologyVersion(evt), evt.type());
 
                         exchFut = exchangeFuture(exchId, evt, null, null, null);
@@ -1404,7 +1405,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
             int cnt = 0;
 
             for (GridDhtPartitionsExchangeFuture fut : exchFuts.values()) {
-                U.warn(log, ">>> " + fut);
+                U.warn(log, ">>> " + fut.shortInfo());
 
                 if (++cnt == 10)
                     break;
@@ -1418,8 +1419,11 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
 
         cctx.affinity().dumpDebugInfo();
 
+        cctx.io().dumpPendingMessages();
+
         // Dump IO manager statistics.
-        cctx.gridIO().dumpStats();
+        if (IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_IO_DUMP_ON_TIMEOUT, false))
+            cctx.gridIO().dumpStats();
     }
 
     /**
@@ -1464,6 +1468,9 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                         if (longRunningOpsDumpCnt < GridDhtPartitionsExchangeFuture.DUMP_PENDING_OBJECTS_THRESHOLD) {
                             U.warn(log, "Found long running cache future [startTime=" + formatTime(fut.startTime()) +
                                 ", curTime=" + formatTime(curTime) + ", fut=" + fut + ']');
+
+                            if (fut instanceof IgniteDiagnosticAware)
+                                ((IgniteDiagnosticAware)fut).dumpDiagnosticInfo();
                         }
                         else
                             break;
@@ -1477,6 +1484,9 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                         if (longRunningOpsDumpCnt < GridDhtPartitionsExchangeFuture.DUMP_PENDING_OBJECTS_THRESHOLD) {
                             U.warn(log, "Found long running cache future [startTime=" + formatTime(fut.startTime()) +
                                 ", curTime=" + formatTime(curTime) + ", fut=" + fut + ']');
+
+                            if (fut instanceof IgniteDiagnosticAware)
+                                ((IgniteDiagnosticAware)fut).dumpDiagnosticInfo();
                         }
                         else
                             break;
@@ -1484,6 +1494,8 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                 }
             }
 
+            cctx.io().dumpPendingMessages();
+
             if (found) {
                 if (longRunningOpsDumpCnt < GridDhtPartitionsExchangeFuture.DUMP_PENDING_OBJECTS_THRESHOLD) {
                     longRunningOpsDumpCnt++;
@@ -1497,7 +1509,8 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                     U.warn(log, "Found long running cache operations, dump IO statistics.");
 
                     // Dump IO manager statistics.
-                    cctx.gridIO().dumpStats();
+                    if (IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_IO_DUMP_ON_TIMEOUT, false))
+                        cctx.gridIO().dumpStats();
                 }
             }
             else
@@ -1556,14 +1569,22 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
 
             U.warn(log, "Pending cache futures:");
 
-            for (GridCacheFuture<?> fut : mvcc.activeFutures())
+            for (GridCacheFuture<?> fut : mvcc.activeFutures()) {
                 U.warn(log, ">>> " + fut);
 
+                if (fut instanceof IgniteDiagnosticAware)
+                    ((IgniteDiagnosticAware)fut).dumpDiagnosticInfo();
+            }
+
             U.warn(log, "Pending atomic cache futures:");
 
-            for (GridCacheFuture<?> fut : mvcc.atomicFutures())
+            for (GridCacheFuture<?> fut : mvcc.atomicFutures()) {
                 U.warn(log, ">>> " + fut);
 
+                if (fut instanceof IgniteDiagnosticAware)
+                    ((IgniteDiagnosticAware)fut).dumpDiagnosticInfo();
+            }
+
             U.warn(log, "Pending data streamer futures:");
 
             for (IgniteInternalFuture<?> fut : mvcc.dataStreamerFutures())
@@ -1819,6 +1840,8 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                                             U.dumpThreads(log);
 
                                         dumpedObjects++;
+
+                                        exchFut.dumpDiagnosticInfo();
                                     }
                                 }
                                 catch (Exception e) {
@@ -2075,8 +2098,14 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
             GridDhtPartitionsExchangeFuture fut) {
             GridDhtPartitionsExchangeFuture cur = super.addx(fut);
 
-            while (size() > EXCHANGE_HISTORY_SIZE)
+            while (size() > EXCHANGE_HISTORY_SIZE) {
+                GridDhtPartitionsExchangeFuture last = last();
+
+                if (last != null && !last.isDone())
+                    break;
+
                 removeLast();
+            }
 
             // Return the value in the set.
             return cur == null ? fut : cur;

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index e968074..99daafc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -113,6 +113,7 @@ import org.apache.ignite.internal.processors.query.schema.message.SchemaProposeD
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObject;
 import org.apache.ignite.internal.suggestions.GridPerformanceSuggestions;
 import org.apache.ignite.internal.util.F0;
+import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.future.GridCompoundFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -203,6 +204,9 @@ public class GridCacheProcessor extends GridProcessorAdapter {
     /** */
     private ClusterCachesInfo cachesInfo;
 
+    /** Restarting caches */
+    private final Set<String> restartingCaches = new GridConcurrentHashSet<>();
+
     /** */
     private IdentityHashMap<CacheStore, ThreadLocal> sesHolders = new IdentityHashMap<>();
 
@@ -2113,6 +2117,9 @@ public class GridCacheProcessor extends GridProcessorAdapter {
             }
         }
 
+        if (exchActions != null && exchActions.systemCacheStarting())
+            ctx.dataStructures().restoreStructuresState(ctx);
+
         if (exchActions != null && (err == null || forceClose)) {
             Collection<IgniteBiTuple<CacheGroupContext, Boolean>> stoppedGrps = null;
 
@@ -2658,6 +2665,16 @@ public class GridCacheProcessor extends GridProcessorAdapter {
      */
     public IgniteInternalFuture<?> dynamicDestroyCaches(Collection<String> cacheNames, boolean checkThreadTx,
         boolean restart) {
+        return dynamicDestroyCaches(cacheNames, checkThreadTx, restart, true);
+    }
+
+    /**
+     * @param cacheNames Collection of cache names to destroy.
+     * @param checkThreadTx If {@code true} checks that current thread does not have active transactions.
+     * @return Future that will be completed when cache is destroyed.
+     */
+    public IgniteInternalFuture<?> dynamicDestroyCaches(Collection<String> cacheNames, boolean checkThreadTx,
+        boolean restart, boolean destroy) {
         if (checkThreadTx)
             checkEmptyTransactions();
 
@@ -2667,7 +2684,7 @@ public class GridCacheProcessor extends GridProcessorAdapter {
             DynamicCacheChangeRequest req = DynamicCacheChangeRequest.stopRequest(ctx, cacheName, false, true);
 
             req.stop(true);
-            req.destroy(true);
+            req.destroy(destroy);
             req.restart(restart);
 
             reqs.add(req);
@@ -2943,7 +2960,7 @@ public class GridCacheProcessor extends GridProcessorAdapter {
             return sharedCtx.affinity().onCustomEvent(((CacheAffinityChangeMessage)msg));
 
         if (msg instanceof StartSnapshotOperationAckDiscoveryMessage &&
-            ((StartSnapshotOperationAckDiscoveryMessage)msg).error() == null)
+            ((StartSnapshotOperationAckDiscoveryMessage)msg).needExchange())
             return true;
 
         if (msg instanceof DynamicCacheChangeBatch)
@@ -2996,6 +3013,12 @@ public class GridCacheProcessor extends GridProcessorAdapter {
      */
     @Nullable private IgniteNodeValidationResult validateHashIdResolvers(ClusterNode node) {
         if (!node.isClient()) {
+            if (restartingCaches.size() > 0) {
+                String msg = "Joining server node during cache restarting is not allowed";
+
+                return new IgniteNodeValidationResult(node.id(), msg, msg);
+            }
+
             for (DynamicCacheDescriptor desc : cacheDescriptors().values()) {
                 CacheConfiguration cfg = desc.cacheConfiguration();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
index f13532d..27650a2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
@@ -739,6 +739,13 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
     }
 
     /**
+     * Needed action before any cache will stop
+     */
+    public void prepareCachesStop() {
+        // No-op.
+    }
+
+    /**
      * @param stoppedGrps A collection of tuples (cache group, destroy flag).
      */
     public void onCacheGroupsStopped(Collection<IgniteBiTuple<CacheGroupContext, Boolean>> stoppedGrps) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
index d5d4c7c..a8f3037 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
@@ -73,6 +73,9 @@ public abstract class PagesList extends DataStructure {
     /** */
     protected final AtomicLong[] bucketsSize;
 
+    /** */
+    protected volatile boolean changed;
+
     /** Page ID to store list metadata. */
     private final long metaPageId;
 
@@ -124,16 +127,15 @@ public abstract class PagesList extends DataStructure {
      * @param buckets Number of buckets.
      * @param wal Write ahead log manager.
      * @param metaPageId Metadata page ID.
-     * @throws IgniteCheckedException If failed.
      */
-    public PagesList(
+    protected PagesList(
         int cacheId,
         String name,
         PageMemory pageMem,
         int buckets,
         IgniteWriteAheadLogManager wal,
         long metaPageId
-    ) throws IgniteCheckedException {
+    ) {
         super(cacheId, pageMem, wal);
 
         this.name = name;
@@ -244,6 +246,8 @@ public abstract class PagesList extends DataStructure {
                     assert ok;
 
                     bucketsSize[bucket].set(bucketSize);
+
+                    changed = true;
                 }
             }
         }
@@ -263,6 +267,9 @@ public abstract class PagesList extends DataStructure {
 
         long nextPageId = metaPageId;
 
+        if (!changed)
+            return;
+
         try {
             for (int bucket = 0; bucket < buckets; bucket++) {
                 Stripe[] tails = getBucket(bucket);
@@ -340,6 +347,8 @@ public abstract class PagesList extends DataStructure {
                 releasePage(pageId, page);
             }
         }
+
+        changed = false;
     }
 
     /**
@@ -672,7 +681,7 @@ public abstract class PagesList extends DataStructure {
         if (idx == -1)
             handlePageFull(pageId, page, pageAddr, io, dataId, dataPage, dataAddr, bucket);
         else {
-            bucketsSize[bucket].incrementAndGet();
+            incrementBucketSize(bucket);
 
             if (needWalDeltaRecord(pageId, page, null))
                 wal.log(new PagesListAddPageRecord(cacheId, pageId, dataId));
@@ -733,7 +742,7 @@ public abstract class PagesList extends DataStructure {
                     pageId, 0L));
 
             // In reuse bucket the page itself can be used as a free page.
-            bucketsSize[bucket].incrementAndGet();
+            incrementBucketSize(bucket);
 
             updateTail(bucket, pageId, newDataId);
         }
@@ -776,7 +785,7 @@ public abstract class PagesList extends DataStructure {
                     if (needWalDeltaRecord(dataId, data, null))
                         wal.log(new DataPageSetFreeListPageRecord(cacheId, dataId, nextId));
 
-                    bucketsSize[bucket].incrementAndGet();
+                    incrementBucketSize(bucket);
 
                     updateTail(bucket, pageId, nextId);
                 }
@@ -862,7 +871,7 @@ public abstract class PagesList extends DataStructure {
 
                         // In reuse bucket the page itself can be used as a free page.
                         if (isReuseBucket(bucket))
-                            bucketsSize[bucket].incrementAndGet();
+                            incrementBucketSize(bucket);
 
                         // Switch to this new page, which is now a part of our list
                         // to add the rest of the bag to the new page.
@@ -882,7 +891,7 @@ public abstract class PagesList extends DataStructure {
                     if (needWalDeltaRecord(prevId, prevPage, walPlc))
                         wal.log(new PagesListAddPageRecord(cacheId, prevId, nextId));
 
-                    bucketsSize[bucket].incrementAndGet();
+                    incrementBucketSize(bucket);
                 }
             }
         }
@@ -1025,7 +1034,7 @@ public abstract class PagesList extends DataStructure {
                     long pageId = io.takeAnyPage(tailAddr);
 
                     if (pageId != 0L) {
-                        bucketsSize[bucket].decrementAndGet();
+                        decrementBucketSize(bucket);
 
                         if (needWalDeltaRecord(tailId, tailPage, null))
                             wal.log(new PagesListRemovePageRecord(cacheId, tailId, pageId));
@@ -1068,7 +1077,7 @@ public abstract class PagesList extends DataStructure {
 
                         assert ok == TRUE : ok;
 
-                        bucketsSize[bucket].decrementAndGet();
+                        decrementBucketSize(bucket);
 
                         if (initIoVers != null) {
                             dataPageId = PageIdUtils.changeType(tailId, FLAG_DATA);
@@ -1153,7 +1162,7 @@ public abstract class PagesList extends DataStructure {
                 if (!rmvd)
                     return false;
 
-                bucketsSize[bucket].decrementAndGet();
+                decrementBucketSize(bucket);
 
                 if (needWalDeltaRecord(pageId, page, null))
                     wal.log(new PagesListRemovePageRecord(cacheId, pageId, dataId));
@@ -1394,6 +1403,32 @@ public abstract class PagesList extends DataStructure {
     }
 
     /**
+     * Increments bucket size and updates changed flag.
+     *
+     * @param bucket Bucket number.
+     */
+    private void incrementBucketSize(int bucket) {
+        bucketsSize[bucket].incrementAndGet();
+
+        // Ok to have a race here, see the field javadoc.
+        if (!changed)
+            changed = true;
+    }
+
+    /**
+     * Increments bucket size and updates changed flag.
+     *
+     * @param bucket Bucket number.
+     */
+    private void decrementBucketSize(int bucket) {
+        bucketsSize[bucket].decrementAndGet();
+
+        // Ok to have a race here, see the field javadoc.
+        if (!changed)
+            changed = true;
+    }
+
+    /**
      * Singleton reuse bag.
      */
     private static final class SingletonReuseBag implements ReuseBag {

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
index d92f811..98204eb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
@@ -2091,9 +2091,12 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
                     assert pageId != 0;
 
                     do {
-                        long page = acquirePage(pageId);
+                        final long pId = pageId;
+
+                        long page = acquirePage(pId);
+
                         try {
-                            long pageAddr = writeLock(pageId, page); // No checks, we must be out of use.
+                            long pageAddr = writeLock(pId, page); // No checks, we must be out of use.
 
                             try {
                                 BPlusIO<L> io = io(pageAddr);
@@ -2109,11 +2112,11 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
                                 pageId = fwdPageId;
                             }
                             finally {
-                                writeUnlock(pageId, page, pageAddr, true);
+                                writeUnlock(pId, page, pageAddr, true);
                             }
                         }
                         finally {
-                            releasePage(pageId, page);
+                            releasePage(pId, page);
                         }
 
                         if (bag.size() == 128) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageMetaIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageMetaIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageMetaIO.java
index 7a5535c..b04baf3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageMetaIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageMetaIO.java
@@ -204,8 +204,13 @@ public class PageMetaIO extends PageIO {
      * @param pageAddr Page address.
      * @param pageCnt Last page count.
      */
-    public void setCandidatePageCount(long pageAddr, int pageCnt) {
+    public boolean setCandidatePageCount(long pageAddr, int pageCnt) {
+        if (getCandidatePageCount(pageAddr) == pageCnt)
+            return false;
+
         PageUtils.putInt(pageAddr, CANDIDATE_PAGE_COUNT_OFF, pageCnt);
+
+        return true;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PagePartitionMetaIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PagePartitionMetaIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PagePartitionMetaIO.java
index 67cc5a3..ddacf69 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PagePartitionMetaIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PagePartitionMetaIO.java
@@ -74,8 +74,13 @@ public class PagePartitionMetaIO extends PageMetaIO {
      * @param pageAddr Page address.
      * @param size Partition size.
      */
-    public void setSize(long pageAddr, long size) {
+    public boolean setSize(long pageAddr, long size) {
+        if (getSize(pageAddr) == size)
+            return false;
+
         PageUtils.putLong(pageAddr, SIZE_OFF, size);
+
+        return true;
     }
 
     /**
@@ -90,8 +95,13 @@ public class PagePartitionMetaIO extends PageMetaIO {
      * @param pageAddr Page address.
      * @param cntr Partition update counter.
      */
-    public void setUpdateCounter(long pageAddr, long cntr) {
+    public boolean setUpdateCounter(long pageAddr, long cntr) {
+        if (getUpdateCounter(pageAddr) == cntr)
+            return false;
+
         PageUtils.putLong(pageAddr, UPDATE_CNTR_OFF, cntr);
+
+        return true;
     }
 
     /**
@@ -106,8 +116,13 @@ public class PagePartitionMetaIO extends PageMetaIO {
      * @param pageAddr Page address.
      * @param rmvId Global remove ID.
      */
-    public void setGlobalRemoveId(long pageAddr, long rmvId) {
+    public boolean setGlobalRemoveId(long pageAddr, long rmvId) {
+        if (getGlobalRemoveId(pageAddr) == rmvId)
+            return false;
+
         PageUtils.putLong(pageAddr, GLOBAL_RMV_ID_OFF, rmvId);
+
+        return true;
     }
 
     /**
@@ -121,8 +136,13 @@ public class PagePartitionMetaIO extends PageMetaIO {
      * @param pageAddr Page address
      * @param state State.
      */
-    public void setPartitionState(long pageAddr, byte state) {
+    public boolean setPartitionState(long pageAddr, byte state) {
+        if (getPartitionState(pageAddr) == state)
+            return false;
+
         PageUtils.putByte(pageAddr, PARTITION_STATE_OFF, state);
+
+        return true;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
index cace4e8..c00ebca 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
@@ -60,6 +60,9 @@ import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDh
  */
 @GridToStringExclude
 public class GridClientPartitionTopology implements GridDhtPartitionTopology {
+    /** */
+    private static final GridDhtPartitionState[] MOVING_STATES = new GridDhtPartitionState[] {MOVING};
+
     /** If true, then check consistency. */
     private static final boolean CONSISTENCY_CHECK = false;
 
@@ -504,7 +507,7 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
 
     /** {@inheritDoc} */
     @Override public List<ClusterNode> owners(int p, AffinityTopologyVersion topVer) {
-        return nodes(p, topVer, OWNING);
+        return nodes(p, topVer, OWNING, null);
     }
 
     /** {@inheritDoc} */
@@ -514,7 +517,7 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
 
     /** {@inheritDoc} */
     @Override public List<ClusterNode> moving(int p) {
-        return nodes(p, AffinityTopologyVersion.NONE, MOVING);
+        return nodes(p, AffinityTopologyVersion.NONE, MOVING, null);
     }
 
     /**
@@ -523,7 +526,7 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
      * @return List of nodes in state OWNING or MOVING.
      */
     private List<ClusterNode> ownersAndMoving(int p, AffinityTopologyVersion topVer) {
-        return nodes(p, topVer, OWNING, MOVING);
+        return nodes(p, topVer, OWNING, MOVING_STATES);
     }
 
     /** {@inheritDoc} */
@@ -787,6 +790,11 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
     }
 
     /** {@inheritDoc} */
+    @Override public void onExchangeDone(AffinityAssignment assignment) {
+        // no-op
+    }
+
+    /** {@inheritDoc} */
     @Override public boolean detectLostPartitions(DiscoveryEvent discoEvt) {
         assert false : "detectLostPartitions should never be called on client topology";
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
index ebb2cfc..7d29064 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
@@ -41,6 +41,7 @@ import org.apache.ignite.internal.processors.cache.extras.GridCacheObsoleteEntry
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.lang.GridPlainRunnable;
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.CI1;
@@ -70,6 +71,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
     private volatile ReaderId[] rdrs = ReaderId.EMPTY_ARRAY;
 
     /** Local partition. */
+    @GridToStringExclude
     private final GridDhtLocalPartition locPart;
 
     /**
@@ -723,7 +725,9 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
 
     /** {@inheritDoc} */
     @Override public synchronized String toString() {
-        return S.toString(GridDhtCacheEntry.class, this, "super", super.toString());
+        return S.toString(GridDhtCacheEntry.class, this,
+            "part", locPart.id(),
+            "super", super.toString());
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/51823847/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
index a53e864..4480efe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
@@ -737,7 +737,7 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
     /**
      * @param updateSeq Update sequence.
      */
-    void tryEvictAsync(boolean updateSeq) {
+     public void tryEvictAsync(boolean updateSeq) {
         long state = this.state.get();
 
         GridDhtPartitionState partState = getPartState(state);


Mime
View raw message