IGNITE-8920 - Fixed transaction hanging on Runtime exceptions during commit. - 
Unified StorageException and PersistentStorageIOException. - BPlus tree 
behavior is overridable in tests. - Refactored AccountTransferAmountTest to 
make it possible to develop any transaction failover based on it. - Fixes #4432.

Signed-off-by: Dmitriy Pavlov <dpav...@apache.org>


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

Branch: refs/heads/ignite-9273
Commit: dde936ace5eb0618edc360ca05006d76e810add8
Parents: 0020e41
Author: Pavel Kovalenko <jokse...@gmail.com>
Authored: Wed Aug 22 17:24:27 2018 +0300
Committer: Dmitriy Pavlov <dpav...@apache.org>
Committed: Wed Aug 22 17:24:27 2018 +0300

----------------------------------------------------------------------
 .../ignite/internal/NodeStoppingException.java  |   2 +-
 .../pagemem/wal/IgniteWriteAheadLogManager.java |   1 +
 .../internal/pagemem/wal/StorageException.java  |  53 --
 .../processors/cache/GridCacheMapEntry.java     |   2 +-
 .../cache/IgniteCacheOffheapManagerImpl.java    |   4 +-
 .../GridDistributedTxRemoteAdapter.java         |  43 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |   5 +-
 .../dht/atomic/GridDhtAtomicCache.java          |   2 +-
 .../GridCacheDatabaseSharedManager.java         |  18 +-
 .../persistence/GridCacheOffheapManager.java    |   1 -
 .../cache/persistence/StorageException.java     |  53 ++
 .../cache/persistence/file/FilePageStore.java   |  48 +-
 .../persistence/file/FilePageStoreManager.java  |  23 +-
 .../file/PersistentStorageIOException.java      |  47 --
 .../persistence/metastorage/MetaStorage.java    |   2 +-
 .../cache/persistence/pagemem/PageMemoryEx.java |   2 +-
 .../persistence/pagemem/PageMemoryImpl.java     |   2 +-
 .../cache/persistence/tree/BPlusTree.java       | 111 ++--
 .../tree/CorruptedTreeException.java            |  38 ++
 .../tree/util/PageHandlerWrapper.java           |  36 ++
 .../wal/FileWriteAheadLogManager.java           |   2 +-
 .../wal/FsyncModeFileWriteAheadLogManager.java  |   2 +-
 .../cache/transactions/IgniteTxAdapter.java     |  37 +-
 .../transactions/IgniteTxLocalAdapter.java      |  59 +-
 .../resources/META-INF/classnames.properties    |   2 +-
 .../failure/AccountTransferTransactionTest.java | 331 -----------
 .../IgnitePdsCorruptedStoreTest.java            |   1 -
 .../db/wal/IgniteWalFormatFileFailoverTest.java |   2 +-
 .../persistence/pagemem/NoOpWALManager.java     |   2 +-
 .../AbstractTransactionIntergrityTest.java      | 595 +++++++++++++++++++
 ...IntegrityWithPrimaryIndexCorruptionTest.java | 238 ++++++++
 ...ctionIntegrityWithSystemWorkerDeathTest.java | 106 ++++
 .../ignite/testsuites/IgniteBasicTestSuite.java |   5 +-
 .../IgniteBasicWithPersistenceTestSuite.java    |   5 +-
 .../testsuites/IgniteCacheTestSuite6.java       |   4 +-
 .../testsuites/IgniteCacheTestSuite7.java       |   6 +-
 36 files changed, 1265 insertions(+), 625 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java
index cc39b14..75447a1 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java
@@ -22,7 +22,7 @@ import org.apache.ignite.IgniteCheckedException;
 /**
  *
  */
-public class NodeStoppingException extends IgniteCheckedException implements 
InvalidEnvironmentException {
+public class NodeStoppingException extends IgniteCheckedException {
     /** */
     private static final long serialVersionUID = 0L;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java
index a43fd0d..b5282ff 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java
@@ -21,6 +21,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedManager;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import 
org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 
 /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java
deleted file mode 100644
index debc391..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.pagemem.wal;
-
-import java.io.IOException;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.InvalidEnvironmentException;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Exception is needed to distinguish WAL manager & page store critical I/O 
errors.
- */
-public class StorageException extends IgniteCheckedException implements 
InvalidEnvironmentException {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /**
-     * @param msg Error message.
-     * @param cause Error cause.
-     */
-    public StorageException(String msg, @NotNull IOException cause) {
-        super(msg, cause);
-    }
-
-    /**
-     * @param e Cause exception.
-     */
-    public StorageException(IOException e) {
-        super(e);
-    }
-
-    /**
-     * @param msg Error message
-     */
-    public StorageException(String msg) {
-        super(msg);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 53c3945..a1722db 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -37,7 +37,7 @@ import org.apache.ignite.cache.eviction.EvictableEntry;
 import org.apache.ignite.internal.NodeStoppingException;
 import org.apache.ignite.internal.UnregisteredBinaryTypeException;
 import org.apache.ignite.internal.UnregisteredClassException;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
 import org.apache.ignite.internal.pagemem.wal.record.DataRecord;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index 5482b3a..a8ad32d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -1584,7 +1584,7 @@ public class IgniteCacheOffheapManagerImpl implements 
IgniteCacheOffheapManager
                         rowStore.removeRow(row.link());
                     }
                     catch (IgniteCheckedException e) {
-                        U.error(log, "Fail remove row [link=" + row.link() + 
"]");
+                        U.error(log, "Failed to remove row [link=" + 
row.link() + "]");
 
                         IgniteCheckedException ex = exception.get();
 
@@ -1597,7 +1597,7 @@ public class IgniteCacheOffheapManagerImpl implements 
IgniteCacheOffheapManager
             });
 
             if (exception.get() != null)
-                throw new IgniteCheckedException("Fail destroy store", 
exception.get());
+                throw new IgniteCheckedException("Failed to destroy store", 
exception.get());
         }
 
         /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
index 1b9b3a8..c1293fc 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
@@ -29,9 +29,11 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.InvalidEnvironmentException;
+import org.apache.ignite.failure.FailureContext;
+import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import org.apache.ignite.internal.InvalidEnvironmentException;
+import org.apache.ignite.internal.NodeStoppingException;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
 import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
@@ -49,6 +51,7 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import 
org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import 
org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import 
org.apache.ignite.internal.processors.cache.transactions.IgniteTxAdapter;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
@@ -744,26 +747,46 @@ public abstract class GridDistributedTxRemoteAdapter 
extends IgniteTxAdapter
                                     }
                                 }
                                 catch (Throwable ex) {
-                                    boolean hasIOIssue = X.hasCause(ex, 
InvalidEnvironmentException.class);
+                                    boolean isNodeStopping = X.hasCause(ex, 
NodeStoppingException.class);
+                                    boolean hasInvalidEnvironmentIssue = 
X.hasCause(ex, InvalidEnvironmentException.class);
 
                                     // In case of error, we still make the 
best effort to commit,
                                     // as there is no way to rollback at this 
point.
                                     err = new 
IgniteTxHeuristicCheckedException("Commit produced a runtime exception " +
                                         "(all transaction entries will be 
invalidated): " + CU.txString(this), ex);
 
-                                    if (hasIOIssue) {
+                                    if (isNodeStopping) {
                                         U.warn(log, "Failed to commit 
transaction, node is stopping [tx=" + this +
                                             ", err=" + ex + ']');
                                     }
+                                    else if (hasInvalidEnvironmentIssue) {
+                                        U.warn(log, "Failed to commit 
transaction, node is in invalid state and will be stopped [tx=" + this +
+                                            ", err=" + ex + ']');
+                                    }
                                     else
                                         U.error(log, "Commit failed.", err);
 
-                                    uncommit(hasIOIssue);
-
                                     state(UNKNOWN);
 
+                                    if (hasInvalidEnvironmentIssue)
+                                        
cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, ex));
+                                    else if (!isNodeStopping) { // Skip fair 
uncommit in case of node stopping or invalidation.
+                                        try {
+                                            // Courtesy to minimize damage.
+                                            uncommit();
+                                        }
+                                        catch (Throwable ex1) {
+                                            U.error(log, "Failed to uncommit 
transaction: " + this, ex1);
+
+                                            if (ex1 instanceof Error)
+                                                throw ex1;
+                                        }
+                                    }
+
                                     if (ex instanceof Error)
-                                        throw (Error)ex;
+                                        throw (Error) ex;
+
+                                    throw err;
                                 }
                             }
 
@@ -792,12 +815,6 @@ public abstract class GridDistributedTxRemoteAdapter 
extends IgniteTxAdapter
                     }
                 }
 
-                if (err != null) {
-                    state(UNKNOWN);
-
-                    throw err;
-                }
-
                 cctx.tm().commitTx(this);
 
                 state(COMMITTED);

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
index 0ed8419..2f36053 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.InvalidEnvironmentException;
 import org.apache.ignite.internal.IgniteDiagnosticAware;
 import org.apache.ignite.internal.IgniteDiagnosticPrepareContext;
 import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.NodeStoppingException;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import 
org.apache.ignite.internal.processors.cache.GridCacheCompoundIdentityFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheFuture;
@@ -168,7 +169,7 @@ public final class GridDhtTxFinishFuture<K, V> extends 
GridCacheCompoundIdentity
         if (ERR_UPD.compareAndSet(this, null, e)) {
             tx.setRollbackOnly();
 
-            if (X.hasCause(e, InvalidEnvironmentException.class))
+            if (X.hasCause(e, InvalidEnvironmentException.class, 
NodeStoppingException.class))
                 onComplete();
             else
                 finish(false);
@@ -225,7 +226,7 @@ public final class GridDhtTxFinishFuture<K, V> extends 
GridCacheCompoundIdentity
 
             if (this.tx.onePhaseCommit() && (this.tx.state() == COMMITTING)) {
                 try {
-                    boolean hasInvalidEnvironmentIssue = X.hasCause(err, 
InvalidEnvironmentException.class);
+                    boolean hasInvalidEnvironmentIssue = X.hasCause(err, 
InvalidEnvironmentException.class, NodeStoppingException.class);
 
                     this.tx.tmFinish(err == null, hasInvalidEnvironmentIssue, 
false);
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index fbb4359..2e77b52 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -41,7 +41,7 @@ import 
org.apache.ignite.internal.UnregisteredBinaryTypeException;
 import org.apache.ignite.internal.UnregisteredClassException;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.processors.affinity.AffinityAssignment;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
index ce914e4..f955231 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
@@ -88,7 +88,6 @@ import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.PageUtils;
 import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.pagemem.store.PageStore;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.CacheState;
@@ -119,7 +118,6 @@ import 
org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStore;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
-import 
org.apache.ignite.internal.processors.cache.persistence.file.PersistentStorageIOException;
 import 
org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage;
 import 
org.apache.ignite.internal.processors.cache.persistence.metastorage.MetastorageLifecycleListener;
 import 
org.apache.ignite.internal.processors.cache.persistence.pagemem.CheckpointMetricsTracker;
@@ -604,7 +602,7 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
                 Files.delete(endFile);
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to delete stale 
checkpoint files: " + cpEntry, e);
+            throw new StorageException("Failed to delete stale checkpoint 
files: " + cpEntry, e);
         }
     }
 
@@ -855,7 +853,7 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
             notifyMetastorageReadyForReadWrite();
         }
         catch (IgniteCheckedException e) {
-            if (X.hasCause(e, StorageException.class, 
PersistentStorageIOException.class, IOException.class))
+            if (X.hasCause(e, StorageException.class, IOException.class))
                 cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -901,7 +899,7 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
             Files.move(Paths.get(cpDir.getAbsolutePath(), tmpFileName), 
Paths.get(cpDir.getAbsolutePath(), fileName));
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to write node start 
marker: " + ptr, e);
+            throw new StorageException("Failed to write node start marker: " + 
ptr, e);
         }
     }
 
@@ -944,12 +942,12 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
                     buf.clear();
                 }
                 catch (IOException e) {
-                    throw new PersistentStorageIOException("Failed to read 
node started marker file: " + f.getAbsolutePath(), e);
+                    throw new StorageException("Failed to read node started 
marker file: " + f.getAbsolutePath(), e);
                 }
             }
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to retreive node 
started files.", e);
+            throw new StorageException("Failed to retreive node started 
files.", e);
         }
 
         // Sort start markers by file timestamp.
@@ -2620,9 +2618,9 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
      * @param entryBuf Checkpoint entry buffer to write.
      * @param cp Checkpoint entry.
      * @param type Checkpoint entry type.
-     * @throws PersistentStorageIOException If failed to write checkpoint 
entry.
+     * @throws StorageException If failed to write checkpoint entry.
      */
-    public void writeCheckpointEntry(ByteBuffer entryBuf, CheckpointEntry cp, 
CheckpointEntryType type) throws PersistentStorageIOException {
+    public void writeCheckpointEntry(ByteBuffer entryBuf, CheckpointEntry cp, 
CheckpointEntryType type) throws StorageException {
         String fileName = checkpointFileName(cp, type);
         String tmpFileName = fileName + FILE_TMP_SUFFIX;
 
@@ -2642,7 +2640,7 @@ public class GridCacheDatabaseSharedManager extends 
IgniteCacheDatabaseSharedMan
                 Files.move(Paths.get(cpDir.getAbsolutePath(), tmpFileName), 
Paths.get(cpDir.getAbsolutePath(), fileName));
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to write checkpoint 
entry [ptr=" + cp.checkpointMark()
+            throw new StorageException("Failed to write checkpoint entry 
[ptr=" + cp.checkpointMark()
                 + ", cpTs=" + cp.timestamp()
                 + ", cpId=" + cp.checkpointId()
                 + ", type=" + type + "]", e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
index 62aadb2..826f619 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
@@ -35,7 +35,6 @@ import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.PageSupport;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.DataEntry;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java
new file mode 100644
index 0000000..509dee6
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.InvalidEnvironmentException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Exception is needed to distinguish WAL manager & page store critical I/O 
errors.
+ */
+public class StorageException extends IgniteCheckedException implements 
InvalidEnvironmentException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * @param msg Error message.
+     * @param cause Error cause.
+     */
+    public StorageException(String msg, @NotNull IOException cause) {
+        super(msg, cause);
+    }
+
+    /**
+     * @param e Cause exception.
+     */
+    public StorageException(IOException e) {
+        super(e);
+    }
+
+    /**
+     * @param msg Error message
+     */
+    public StorageException(String msg) {
+        super(msg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
index c4f90e5..cc4f27b 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
@@ -33,6 +33,7 @@ import 
org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.store.PageStore;
 import 
org.apache.ignite.internal.processors.cache.persistence.AllocatedPageTracker;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.wal.crc.IgniteDataIntegrityViolationException;
 import 
org.apache.ignite.internal.processors.cache.persistence.wal.crc.PureJavaCrc32;
@@ -182,7 +183,7 @@ public class FilePageStore implements PageStore {
      * Checks that file store has correct header and size.
      *
      * @return Next available position in the file to store a data.
-     * @throws IOException If check is failed.
+     * @throws IOException If check has failed.
      */
     private long checkFile(FileIO fileIO) throws IOException {
         ByteBuffer hdr = 
ByteBuffer.allocate(headerSize()).order(ByteOrder.LITTLE_ENDIAN);
@@ -233,10 +234,10 @@ public class FilePageStore implements PageStore {
     }
 
     /**
-     * @param cleanFile {@code True} to delete file.
-     * @throws PersistentStorageIOException If failed.
+     * @param delete {@code True} to delete file.
+     * @throws StorageException If failed in case of underlying I/O exception.
      */
-    public void stop(boolean cleanFile) throws PersistentStorageIOException {
+    public void stop(boolean delete) throws StorageException {
         lock.writeLock().lock();
 
         try {
@@ -249,11 +250,12 @@ public class FilePageStore implements PageStore {
 
             fileIO = null;
 
-            if (cleanFile)
+            if (delete)
                 Files.delete(cfgFile.toPath());
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException(e);
+            throw new StorageException("Failed to stop serving partition file 
[file=" + cfgFile.getPath()
+                + ", delete=" + delete + "]", e);
         }
         finally {
             lock.writeLock().unlock();
@@ -264,9 +266,9 @@ public class FilePageStore implements PageStore {
      * Truncates and deletes partition file.
      *
      * @param tag New partition tag.
-     * @throws PersistentStorageIOException If failed
+     * @throws StorageException If failed in case of underlying I/O exception.
      */
-    public void truncate(int tag) throws PersistentStorageIOException {
+    public void truncate(int tag) throws StorageException {
         init();
 
         lock.writeLock().lock();
@@ -283,7 +285,7 @@ public class FilePageStore implements PageStore {
             Files.delete(cfgFile.toPath());
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to delete partition 
file: " + cfgFile.getPath(), e);
+            throw new StorageException("Failed to truncate partition file 
[file=" + cfgFile.getPath() + "]", e);
         }
         finally {
             allocatedTracker.updateTotalAllocatedPages(-1L * allocated.get() / 
pageSize);
@@ -311,9 +313,9 @@ public class FilePageStore implements PageStore {
     }
 
     /**
-     *
+     * @throws StorageException If failed in case of underlying I/O exception.
      */
-    public void finishRecover() throws PersistentStorageIOException {
+    public void finishRecover() throws StorageException {
         lock.writeLock().lock();
 
         try {
@@ -332,7 +334,7 @@ public class FilePageStore implements PageStore {
             recover = false;
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Failed to finish recover", 
e);
+            throw new StorageException("Failed to finish recover partition 
file [file=" + cfgFile.getAbsolutePath() + "]", e);
         }
         finally {
             lock.writeLock().unlock();
@@ -386,7 +388,7 @@ public class FilePageStore implements PageStore {
                 PageIO.setCrc(pageBuf, savedCrc32);
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Read error", e);
+            throw new StorageException("Failed to read page [file=" + 
cfgFile.getAbsolutePath() + ", pageId=" + pageId + "]", e);
         }
     }
 
@@ -400,14 +402,14 @@ public class FilePageStore implements PageStore {
             readWithFailover(buf, 0);
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Read error", e);
+            throw new StorageException("Failed to read header [file=" + 
cfgFile.getAbsolutePath() + "]", e);
         }
     }
 
     /**
-     * @throws PersistentStorageIOException If failed to initialize store file.
+     * @throws StorageException If failed to initialize store file.
      */
-    private void init() throws PersistentStorageIOException {
+    private void init() throws StorageException {
         if (!inited) {
             lock.writeLock().lock();
 
@@ -415,7 +417,7 @@ public class FilePageStore implements PageStore {
                 if (!inited) {
                     FileIO fileIO = null;
 
-                    PersistentStorageIOException err = null;
+                    StorageException err = null;
 
                     long newSize;
 
@@ -449,8 +451,8 @@ public class FilePageStore implements PageStore {
                         inited = true;
                     }
                     catch (IOException e) {
-                        err = new PersistentStorageIOException(
-                            "Failed to initialize partition file: " + 
cfgFile.getName(), e);
+                        err = new StorageException(
+                            "Failed to initialize partition file: " + 
cfgFile.getAbsolutePath(), e);
 
                         throw err;
                     }
@@ -608,8 +610,8 @@ public class FilePageStore implements PageStore {
                     }
                 }
 
-                throw new PersistentStorageIOException("Failed to write the 
page to the file store [pageId=" + pageId
-                    + ", file=" + cfgFile.getAbsolutePath() + ']', e);
+                throw new StorageException("Failed to write page [file=" + 
cfgFile.getAbsolutePath()
+                    + ", pageId=" + pageId + ", tag=" + tag + "]", e);
             }
         }
     }
@@ -635,7 +637,7 @@ public class FilePageStore implements PageStore {
     }
 
     /** {@inheritDoc} */
-    @Override public void sync() throws IgniteCheckedException {
+    @Override public void sync() throws StorageException {
         lock.writeLock().lock();
 
         try {
@@ -647,7 +649,7 @@ public class FilePageStore implements PageStore {
                 fileIO.force();
         }
         catch (IOException e) {
-            throw new PersistentStorageIOException("Sync error", e);
+            throw new StorageException("Failed to fsync partition file [file=" 
+ cfgFile.getAbsolutePath() + "]", e);
         }
         finally {
             lock.writeLock().unlock();

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
index 3d23d53..c72b0bf 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
@@ -55,6 +55,7 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter
 import org.apache.ignite.internal.processors.cache.StoredCacheData;
 import 
org.apache.ignite.internal.processors.cache.persistence.AllocatedPageTracker;
 import 
org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import 
org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
 import 
org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage;
 import 
org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteCacheSnapshotManager;
@@ -270,7 +271,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
                     partStore.finishRecover();
             }
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -278,8 +279,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
     }
 
     /** {@inheritDoc} */
-    @Override public void initializeForCache(CacheGroupDescriptor grpDesc, 
StoredCacheData cacheData)
-        throws IgniteCheckedException {
+    @Override public void initializeForCache(CacheGroupDescriptor grpDesc, 
StoredCacheData cacheData) throws IgniteCheckedException {
         int grpId = grpDesc.groupId();
 
         if (!idxCacheStores.containsKey(grpId)) {
@@ -292,8 +292,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
     }
 
     /** {@inheritDoc} */
-    @Override public void initializeForMetastorage()
-        throws IgniteCheckedException {
+    @Override public void initializeForMetastorage() throws 
IgniteCheckedException {
         int grpId = MetaStorage.METASTORAGE_CACHE_ID;
 
         if (!idxCacheStores.containsKey(grpId)) {
@@ -399,7 +398,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
         try {
             store.read(pageId, pageBuf, keepCrc);
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -420,7 +419,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
         try {
             store.readHeader(buf);
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -456,7 +455,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
         try {
             store.write(pageId, pageBuf, tag, calculateCrc);
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -542,7 +541,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
 
             return new CacheStoreHolder(idxStore, partStores);
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -634,7 +633,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
         try {
             getStore(grpId, partId).sync();
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -646,7 +645,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
         try {
             getStore(grpId, partId).ensure();
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;
@@ -664,7 +663,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
 
             return PageIdUtils.pageId(partId, flags, (int)pageIdx);
         }
-        catch (PersistentStorageIOException e) {
+        catch (StorageException e) {
             cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
 
             throw e;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java
deleted file mode 100644
index 7b3c303..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.file;
-
-import java.io.IOException;
-import org.apache.ignite.IgniteCheckedException;
-
-/**
- * Exception is needed to distinguish persistent storage I/O errors.
- */
-public class PersistentStorageIOException extends IgniteCheckedException {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /**
-     * Create an instance of exception.
-     *
-     * @param cause Error cause.
-     */
-    public PersistentStorageIOException(IOException cause) {
-        super(cause);
-    }
-
-    /**
-     * Create an instance of exception.
-     *
-     * @param msg Error message.
-     * @param cause Error cause.
-     */
-    public PersistentStorageIOException(String msg, IOException cause) {
-        super(msg, cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
index 4a2549b..c0fba73 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
@@ -29,7 +29,7 @@ import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
 import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java
index ed0d304..af204dd 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java
@@ -23,7 +23,7 @@ import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.PageMemory;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
 import org.jetbrains.annotations.Nullable;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
index 1524150..75cc036 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
@@ -52,7 +52,7 @@ import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageUtils;
 import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
index 141b94f..8a63a00 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
@@ -57,6 +57,7 @@ import 
org.apache.ignite.internal.processors.cache.persistence.tree.reuse.LongLi
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import 
org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandlerWrapper;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.util.GridArrays;
 import org.apache.ignite.internal.util.GridLongList;
@@ -90,6 +91,9 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     /** */
     private static final Object[] EMPTY = {};
 
+    /** Wrapper for tree pages operations. Noop by default. Override for test 
purposes. */
+    public static volatile PageHandlerWrapper<Result> pageHndWrapper = (tree, 
hnd) -> hnd;
+
     /** */
     private static volatile boolean interrupted;
 
@@ -228,7 +232,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     };
 
     /** */
-    private final GetPageHandler<Get> askNeighbor = new AskNeighbor();
+    private final PageHandler<Get, Result> askNeighbor;
 
     /**
      *
@@ -259,12 +263,12 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Get> search = new Search();
+    private final PageHandler<Get, Result> search;
 
     /**
      *
      */
-    private class Search extends GetPageHandler<Get> {
+    public class Search extends GetPageHandler<Get> {
         /** {@inheritDoc} */
         @Override public Result run0(long pageId, long page, long pageAddr, 
BPlusIO<L> io, Get g, int lvl)
             throws IgniteCheckedException {
@@ -348,12 +352,12 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Put> replace = new Replace();
+    private final PageHandler<Put, Result> replace;
 
     /**
      *
      */
-    private class Replace extends GetPageHandler<Put> {
+    public class Replace extends GetPageHandler<Put> {
         /** {@inheritDoc} */
         @SuppressWarnings("unchecked")
         @Override public Result run0(long pageId, long page, long pageAddr, 
BPlusIO<L> io, Put p, int lvl)
@@ -410,12 +414,12 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Put> insert = new Insert();
+    private final PageHandler<Put, Result> insert;
 
     /**
      *
      */
-    private class Insert extends GetPageHandler<Put> {
+    public class Insert extends GetPageHandler<Put> {
         /** {@inheritDoc} */
         @Override public Result run0(long pageId, long page, long pageAddr, 
BPlusIO<L> io, Put p, int lvl)
             throws IgniteCheckedException {
@@ -459,7 +463,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Remove> rmvFromLeaf = new RemoveFromLeaf();
+    private final PageHandler<Remove, Result> rmvFromLeaf;
 
     /**
      *
@@ -534,7 +538,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Remove> lockBackAndRmvFromLeaf = new 
LockBackAndRmvFromLeaf();
+    private final PageHandler<Remove, Result> lockBackAndRmvFromLeaf;
 
     /**
      *
@@ -559,7 +563,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Remove> lockBackAndTail = new 
LockBackAndTail();
+    private final PageHandler<Remove, Result> lockBackAndTail;
 
     /**
      *
@@ -583,7 +587,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Remove> lockTailForward = new 
LockTailForward();
+    private final PageHandler<Remove, Result> lockTailForward;
 
     /**
      *
@@ -599,7 +603,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     }
 
     /** */
-    private final GetPageHandler<Remove> lockTail = new LockTail();
+    private final PageHandler<Remove, Result> lockTail;
 
     /**
      *
@@ -784,6 +788,17 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         this.reuseList = reuseList;
         this.globalRmvId = globalRmvId;
         this.failureProcessor = failureProcessor;
+
+        // Initialize page handlers.
+        askNeighbor = (PageHandler<Get, Result>) pageHndWrapper.wrap(this, new 
AskNeighbor());
+        search = (PageHandler<Get, Result>) pageHndWrapper.wrap(this, new 
Search());
+        lockTail = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new 
LockTail());
+        lockTailForward = (PageHandler<Remove, Result>) 
pageHndWrapper.wrap(this, new LockTailForward());
+        lockBackAndTail = (PageHandler<Remove, Result>) 
pageHndWrapper.wrap(this, new LockBackAndTail());
+        lockBackAndRmvFromLeaf = (PageHandler<Remove, Result>) 
pageHndWrapper.wrap(this, new LockBackAndRmvFromLeaf());
+        rmvFromLeaf = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, 
new RemoveFromLeaf());
+        insert = (PageHandler<Put, Result>) pageHndWrapper.wrap(this, new 
Insert());
+        replace = (PageHandler<Put, Result>) pageHndWrapper.wrap(this, new 
Replace());
     }
 
     /**
@@ -981,11 +996,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on bounds: 
[lower=" + lower + ", upper=" + upper + "]", e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on bounds: [lower=" + 
lower + ", upper=" + upper + "]", e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on bounds: [lower=" + 
lower + ", upper=" + upper + "]", e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on bounds: 
[lower=" + lower + ", upper=" + upper + "]", e);
         }
         finally {
             checkDestroyed();
@@ -1033,11 +1045,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on first row 
lookup", e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on first row lookup", 
e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on first row lookup", e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on first row 
lookup", e);
         }
         finally {
             checkDestroyed();
@@ -1058,12 +1067,9 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on last row 
lookup", e);
         }
-        catch (RuntimeException e) {
+        catch (RuntimeException | AssertionError e) {
             throw new IgniteException("Runtime failure on last row lookup", e);
         }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on last row lookup", e);
-        }
         finally {
             checkDestroyed();
         }
@@ -1089,11 +1095,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on lookup row: " 
+ row, e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on lookup row: " + row, 
e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on lookup row: " + row, 
e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on lookup row: " 
+ row, e);
         }
         finally {
             checkDestroyed();
@@ -1653,11 +1656,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on search row: " 
+ row, e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on search row: " + row, 
e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on search row: " + row, 
e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on search row: " 
+ row, e);
         }
         finally {
             x.releaseAll();
@@ -1813,11 +1813,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on search row: " 
+ row, e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on search row: " + row, 
e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on search row: " + row, 
e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on search row: " 
+ row, e);
         }
         finally {
             r.releaseAll();
@@ -2132,11 +2129,8 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on row: " + row, 
e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on row: " + row, e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on row: " + row, e);
+        catch (RuntimeException | AssertionError e) {
+            throw new CorruptedTreeException("Runtime failure on row: " + row, 
e);
         }
         finally {
             checkDestroyed();
@@ -2427,7 +2421,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     /**
      * Get operation.
      */
-    private abstract class Get {
+    public abstract class Get {
         /** */
         long rmvId;
 
@@ -2542,7 +2536,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
          * @param lvl Level.
          * @return {@code true} If we can release the given page.
          */
-        boolean canRelease(long pageId, int lvl) {
+        public boolean canRelease(long pageId, int lvl) {
             return pageId != 0L;
         }
 
@@ -2592,6 +2586,13 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
 
             lockRetriesCnt--;
         }
+
+        /**
+         * @return Operation row.
+         */
+        public L row() {
+            return row;
+        }
     }
 
     /**
@@ -2665,11 +2666,13 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     /**
      * Put operation.
      */
-    private final class Put extends Get {
+    public final class Put extends Get {
         /** Mark of NULL value of page id. It means valid value can't be equal 
this value. */
         private static final long NULL_PAGE_ID = 0L;
+
         /** Mark of NULL value of page. */
         private static final long NULL_PAGE = 0L;
+
         /** Mark of NULL value of page address. */
         private static final long NULL_PAGE_ADDRESS = 0L;
 
@@ -2754,7 +2757,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         }
 
         /** {@inheritDoc} */
-        @Override boolean canRelease(long pageId, int lvl) {
+        @Override public boolean canRelease(long pageId, int lvl) {
             return pageId != NULL_PAGE_ID && tailId != pageId;
         }
 
@@ -3013,7 +3016,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     /**
      * Invoke operation.
      */
-    private final class Invoke extends Get {
+    public final class Invoke extends Get {
         /** */
         Object x;
 
@@ -3151,7 +3154,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         }
 
         /** {@inheritDoc} */
-        @Override boolean canRelease(long pageId, int lvl) {
+        @Override public boolean canRelease(long pageId, int lvl) {
             if (pageId == 0L)
                 return false;
 
@@ -4128,7 +4131,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         }
 
         /** {@inheritDoc} */
-        @Override boolean canRelease(long pageId, int lvl) {
+        @Override public boolean canRelease(long pageId, int lvl) {
             return pageId != 0L && !isTail(pageId, lvl);
         }
 
@@ -4902,7 +4905,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
     /**
      * Operation result.
      */
-    enum Result {
+    public enum Result {
         /** */
         GO_DOWN,
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
new file mode 100644
index 0000000..a6bfb1f
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.InvalidEnvironmentException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Exception to distinguish {@link BPlusTree} tree broken invariants.
+ */
+public class CorruptedTreeException extends IgniteCheckedException implements 
InvalidEnvironmentException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * @param msg Message.
+     * @param cause Cause.
+     */
+    public CorruptedTreeException(String msg, @Nullable Throwable cause) {
+        super(msg, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java
new file mode 100644
index 0000000..495eba0
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * 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.util;
+
+import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
+
+/**
+ * Wrapper factory for {@link PageHandler} instances.
+ *
+ * @param <R> Result type of actual {@link PageHandler} class.
+ */
+public interface PageHandlerWrapper<R> {
+    /**
+     * Wraps given {@code hnd}.
+     *
+     * @param tree Instance of {@link BPlusTree} where given {@code} is used.
+     * @param hnd Page handler to wrap.
+     * @return Wrapped version of given {@code hnd}.
+     */
+    public PageHandler<?, R> wrap(BPlusTree<?, ?> tree, PageHandler<?, R> hnd);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
index e3f5a52..0525384 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
@@ -77,7 +77,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import 
org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java
index c8224a5..4797f81 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java
@@ -73,7 +73,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import 
org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.MarshalledRecord;

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
index e97b31c..bdd0c53 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
@@ -445,36 +445,27 @@ public abstract class IgniteTxAdapter extends 
GridMetadataAwareAdapter implement
 
     /**
      * Uncommits transaction by invalidating all of its entries. Courtesy to 
minimize inconsistency.
-     *
-     * @param nodeStopping {@code True} if tx was cancelled during node stop.
      */
     @SuppressWarnings({"CatchGenericClass"})
-    protected void uncommit(boolean nodeStopping) {
-        try {
-            if (!nodeStopping) {
-                for (IgniteTxEntry e : writeMap().values()) {
-                    try {
-                        GridCacheEntryEx entry = e.cached();
-
-                        if (e.op() != NOOP)
-                            entry.invalidate(xidVer);
-                    }
-                    catch (Throwable t) {
-                        U.error(log, "Failed to invalidate transaction entries 
while reverting a commit.", t);
+    protected void uncommit() {
+        for (IgniteTxEntry e : writeMap().values()) {
+            try {
+                GridCacheEntryEx entry = e.cached();
 
-                        if (t instanceof Error)
-                            throw (Error)t;
+                if (e.op() != NOOP)
+                    entry.invalidate(xidVer);
+            }
+            catch (Throwable t) {
+                U.error(log, "Failed to invalidate transaction entries while 
reverting a commit.", t);
 
-                        break;
-                    }
-                }
+                if (t instanceof Error)
+                    throw (Error)t;
 
-                cctx.tm().uncommitTx(this);
+                break;
             }
         }
-        catch (Exception ex) {
-            U.error(log, "Failed to do uncommit.", ex);
-        }
+
+        cctx.tm().uncommitTx(this);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index 0f590ff..e6c656e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -30,9 +30,12 @@ import javax.cache.expiry.ExpiryPolicy;
 import javax.cache.processor.EntryProcessor;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.failure.FailureContext;
+import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.InvalidEnvironmentException;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.pagemem.wal.StorageException;
+import org.apache.ignite.internal.NodeStoppingException;
+import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
 import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
@@ -46,7 +49,6 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import 
org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
 import 
org.apache.ignite.internal.processors.cache.GridCacheFilterFailedException;
-import 
org.apache.ignite.internal.processors.cache.GridCacheIndexUpdateException;
 import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheOperation;
 import org.apache.ignite.internal.processors.cache.GridCacheReturn;
@@ -834,39 +836,34 @@ public abstract class IgniteTxLocalAdapter extends 
IgniteTxAdapter implements Ig
                         // Need to remove version from committed list.
                         cctx.tm().removeCommittedTx(this);
 
-                        if (X.hasCause(ex, 
GridCacheIndexUpdateException.class) && cacheCtx.cache().isMongoDataCache()) {
-                            if (log.isDebugEnabled())
-                                log.debug("Failed to update mongo document 
index (transaction entry will " +
-                                    "be ignored): " + txEntry);
+                        boolean isNodeStopping = X.hasCause(ex, 
NodeStoppingException.class);
+                        boolean hasInvalidEnvironmentIssue = X.hasCause(ex, 
InvalidEnvironmentException.class);
 
-                            // Set operation to NOOP.
-                            txEntry.op(NOOP);
+                        IgniteCheckedException err = new 
IgniteTxHeuristicCheckedException("Failed to locally write to cache " +
+                            "(all transaction entries will be invalidated, 
however there was a window when " +
+                            "entries for this transaction were visible to 
others): " + this, ex);
 
-                            errorWhenCommitting();
-
-                            throw ex;
+                        if (isNodeStopping) {
+                            U.warn(log, "Failed to commit transaction, node is 
stopping [tx=" + this +
+                                ", err=" + ex + ']');
                         }
-                        else {
-                            boolean hasInvalidEnvironmentIssue = 
X.hasCause(ex, InvalidEnvironmentException.class);
-
-                            IgniteCheckedException err = new 
IgniteTxHeuristicCheckedException("Failed to locally write to cache " +
-                                "(all transaction entries will be invalidated, 
however there was a window when " +
-                                "entries for this transaction were visible to 
others): " + this, ex);
-
-                            if (hasInvalidEnvironmentIssue) {
-                                U.warn(log, "Failed to commit transaction, 
node is stopping " +
-                                    "[tx=" + this + ", err=" + ex + ']');
-                            }
-                            else
-                                U.error(log, "Heuristic transaction failure.", 
err);
+                        else if (hasInvalidEnvironmentIssue) {
+                            U.warn(log, "Failed to commit transaction, node is 
in invalid state and will be stopped [tx=" + this +
+                                ", err=" + ex + ']');
+                        }
+                        else
+                            U.error(log, "Commit failed.", err);
 
-                            COMMIT_ERR_UPD.compareAndSet(this, null, err);
+                        COMMIT_ERR_UPD.compareAndSet(this, null, err);
 
-                            state(UNKNOWN);
+                        state(UNKNOWN);
 
+                        if (hasInvalidEnvironmentIssue)
+                            cctx.kernalContext().failure().process(new 
FailureContext(FailureType.CRITICAL_ERROR, ex));
+                        else if (!isNodeStopping) { // Skip fair uncommit in 
case of node stopping or invalidation.
                             try {
                                 // Courtesy to minimize damage.
-                                uncommit(hasInvalidEnvironmentIssue);
+                                uncommit();
                             }
                             catch (Throwable ex1) {
                                 U.error(log, "Failed to uncommit transaction: 
" + this, ex1);
@@ -874,12 +871,12 @@ public abstract class IgniteTxLocalAdapter extends 
IgniteTxAdapter implements Ig
                                 if (ex1 instanceof Error)
                                     throw ex1;
                             }
+                        }
 
-                            if (ex instanceof Error)
-                                throw ex;
+                        if (ex instanceof Error)
+                            throw ex;
 
-                            throw err;
-                        }
+                        throw err;
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/resources/META-INF/classnames.properties
----------------------------------------------------------------------
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties 
b/modules/core/src/main/resources/META-INF/classnames.properties
index 27934ad..c105421 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -390,7 +390,7 @@ 
org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager$1
 org.apache.ignite.internal.marshaller.optimized.OptimizedFieldType
 org.apache.ignite.internal.mem.IgniteOutOfMemoryException
 org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl$Segment
-org.apache.ignite.internal.pagemem.wal.StorageException
+org.apache.ignite.internal.processors.cache.persistence.StorageException
 org.apache.ignite.internal.pagemem.wal.WALIterator
 org.apache.ignite.internal.pagemem.wal.WALPointer
 org.apache.ignite.internal.pagemem.wal.record.ExchangeRecord$Type

Reply via email to