You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2016/08/31 06:33:16 UTC

[26/38] ignite git commit: Merge ignite-1.7.2 to master

Merge ignite-1.7.2 to master


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

Branch: refs/heads/ignite-3443
Commit: f89375bdd6159134fae5d0b7b28b876b6e335a32
Parents: 2d5d5bc fea3eea
Author: agura <ag...@gridgain.com>
Authored: Mon Aug 29 20:35:08 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Mon Aug 29 20:35:08 2016 +0300

----------------------------------------------------------------------
 .../local/LocalIgfsSecondaryFileSystem.java     |   38 +-
 .../processors/cache/GridCacheMapEntry.java     |   19 +-
 .../GridCachePartitionExchangeManager.java      |    7 +
 .../GridDistributedTxPrepareRequest.java        |    4 +-
 .../distributed/dht/GridDhtLockFuture.java      |   53 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |    4 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |   26 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |  101 +-
 .../dht/GridDhtTxPrepareRequest.java            |    4 +-
 .../GridNearAtomicAbstractUpdateFuture.java     |   69 ++
 .../GridNearAtomicSingleUpdateFuture.java       |   70 +-
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |   68 +-
 .../colocated/GridDhtColocatedLockFuture.java   |   37 +-
 .../distributed/near/GridNearLockFuture.java    |   90 +-
 ...arOptimisticSerializableTxPrepareFuture.java |   13 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |  263 +++--
 ...ridNearOptimisticTxPrepareFutureAdapter.java |    5 +-
 .../GridNearPessimisticTxPrepareFuture.java     |    8 +-
 .../near/GridNearTxFinishFuture.java            |    5 +-
 .../cache/distributed/near/GridNearTxLocal.java |   16 +-
 .../near/GridNearTxPrepareRequest.java          |    4 +-
 .../cache/transactions/IgniteInternalTx.java    |    3 +-
 .../cache/transactions/IgniteTxAdapter.java     |   37 +-
 .../cache/transactions/IgniteTxHandler.java     |   11 +-
 .../transactions/IgniteTxLocalAdapter.java      |   19 +-
 .../cache/transactions/IgniteTxManager.java     |   86 +-
 .../cache/transactions/IgniteTxStateImpl.java   |   11 +-
 .../cache/transactions/TxDeadlockDetection.java |   51 +-
 .../processors/odbc/OdbcNioListener.java        |    2 +-
 .../processors/odbc/OdbcRequestHandler.java     |   36 +-
 .../odbc/escape/OdbcEscapeParseResult.java      |   73 ++
 .../processors/odbc/escape/OdbcEscapeToken.java |   61 +
 .../processors/odbc/escape/OdbcEscapeType.java  |  105 ++
 .../processors/odbc/escape/OdbcEscapeUtils.java |  361 ++++++
 .../service/GridServiceProcessor.java           |   18 +-
 .../util/future/GridCompoundFuture.java         |   10 +
 .../ignite/spi/discovery/tcp/ClientImpl.java    |    7 +-
 .../cache/IgniteTxConfigCacheSelfTest.java      |   91 +-
 .../IgniteTxTimeoutAbstractTest.java            |    8 +-
 ...tionedMultiNodeLongTxTimeoutFullApiTest.java |   34 +
 ...nabledMultiNodeLongTxTimeoutFullApiTest.java |   41 +
 .../local/GridCacheLocalTxTimeoutSelfTest.java  |    5 +-
 .../transactions/DepthFirstSearchTest.java      |  100 +-
 .../TxDeadlockDetectionNoHangsTest.java         |  246 ++++
 .../transactions/TxDeadlockDetectionTest.java   |   13 +-
 ...timisticDeadlockDetectionCrossCacheTest.java |  257 +++++
 .../TxOptimisticDeadlockDetectionTest.java      |  574 ++++++++++
 ...simisticDeadlockDetectionCrossCacheTest.java |  165 ++-
 .../TxPessimisticDeadlockDetectionTest.java     |   50 +-
 .../igfs/IgfsAbstractBaseSelfTest.java          | 1067 ++++++++++++++++++
 .../processors/igfs/IgfsAbstractSelfTest.java   | 1012 +----------------
 ...SecondaryFileSystemDualAbstractSelfTest.java |  143 +++
 .../odbc/OdbcEscapeSequenceSelfTest.java        |  420 +++++++
 .../ignite/testsuites/IgniteBasicTestSuite.java |    2 +
 .../IgniteCacheFullApiSelfTestSuite.java        |    4 +
 .../TxDeadlockDetectionTestSuite.java           |    6 +
 .../cpp/common/include/ignite/common/utils.h    |    7 +
 .../cpp/common/os/win/src/common/utils.cpp      |   20 +
 .../cpp/common/src/common/big_integer.cpp       |    1 -
 .../cpp/core/include/ignite/ignition.h          |    2 +-
 modules/platforms/cpp/core/src/ignition.cpp     |    8 +-
 modules/platforms/cpp/odbc-test/Makefile.am     |    9 +
 .../platforms/cpp/odbc-test/include/Makefile.am |    4 +-
 .../odbc-test/include/sql_test_suite_fixture.h  |  191 ++++
 .../cpp/odbc-test/include/test_utils.h          |   45 +
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |   11 +
 .../project/vs/odbc-test.vcxproj.filters        |   33 +
 .../cpp/odbc-test/src/configuration_test.cpp    |    6 +-
 .../cpp/odbc-test/src/queries_test.cpp          |   78 +-
 .../src/sql_aggregate_functions_test.cpp        |  249 ++++
 .../src/sql_numeric_functions_test.cpp          |  309 +++++
 .../cpp/odbc-test/src/sql_operators_test.cpp    |  214 ++++
 .../odbc-test/src/sql_string_functions_test.cpp |  291 +++++
 .../odbc-test/src/sql_system_functions_test.cpp |   47 +
 .../odbc-test/src/sql_test_suite_fixture.cpp    |  271 +++++
 .../cpp/odbc-test/src/sql_types_test.cpp        |   60 +
 .../src/sql_value_expressions_test.cpp          |   94 ++
 .../platforms/cpp/odbc-test/src/test_utils.cpp  |   36 +
 modules/platforms/cpp/odbc/Makefile.am          |    1 +
 modules/platforms/cpp/odbc/include/Makefile.am  |    1 +
 .../platforms/cpp/odbc/include/ignite/odbc.h    |    1 -
 .../include/ignite/odbc/config/configuration.h  |   93 +-
 .../ignite/odbc/diagnostic/diagnostic_record.h  |    2 +-
 .../cpp/odbc/include/ignite/odbc/dsn_config.h   |   61 +
 .../odbc/include/ignite/odbc/protocol_version.h |   20 +-
 .../include/ignite/odbc/system/odbc_constants.h |    4 -
 .../odbc/system/ui/dsn_configuration_window.h   |  152 +++
 .../ignite/odbc/system/ui/custom_window.h       |  189 ++++
 .../win/include/ignite/odbc/system/ui/window.h  |  201 ++++
 .../odbc/os/win/src/system/ui/custom_window.cpp |  184 +++
 .../src/system/ui/dsn_configuration_window.cpp  |  305 +++++
 .../cpp/odbc/os/win/src/system/ui/window.cpp    |  192 ++++
 .../cpp/odbc/os/win/src/system_dsn.cpp          |  218 ++++
 .../platforms/cpp/odbc/project/vs/odbc.vcxproj  |   25 +-
 .../cpp/odbc/project/vs/odbc.vcxproj.filters    |   30 +
 .../cpp/odbc/src/config/configuration.cpp       |   17 +-
 .../cpp/odbc/src/config/connection_info.cpp     |   57 +-
 modules/platforms/cpp/odbc/src/connection.cpp   |    2 +-
 .../odbc/src/diagnostic/diagnostic_record.cpp   |    2 +-
 .../diagnostic/diagnostic_record_storage.cpp    |    2 +-
 modules/platforms/cpp/odbc/src/dsn_config.cpp   |  115 ++
 modules/platforms/cpp/odbc/src/entry_points.cpp |    8 -
 modules/platforms/cpp/odbc/src/odbc.cpp         |   88 +-
 .../platforms/cpp/odbc/src/protocol_version.cpp |   23 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp |    6 +-
 modules/platforms/cpp/odbc/src/utility.cpp      |   14 +-
 .../commands/cache/VisorCacheStopCommand.scala  |    5 +-
 107 files changed, 8330 insertions(+), 1707 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
index 187c8a4,b005b29..f2b5f49
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
@@@ -298,8 -292,10 +292,10 @@@ public final class GridDhtLockFuture ex
      /**
       * @return Entries.
       */
-     public synchronized Collection<GridDhtCacheEntry> entriesCopy() {
-         return new ArrayList<>(entries());
+     public Collection<GridDhtCacheEntry> entriesCopy() {
 -        synchronized (futs) {
++        synchronized (sync) {
+             return new ArrayList<>(entries());
+         }
      }
  
      /**
@@@ -412,7 -408,7 +408,7 @@@
              return null;
          }
  
-         synchronized (this) {
 -        synchronized (futs) {
++        synchronized (sync) {
              entries.add(c == null || c.reentry() ? null : entry);
  
              if (c != null && !c.reentry())
@@@ -614,7 -610,7 +610,7 @@@
       * @param t Error.
       */
      public void onError(Throwable t) {
-         synchronized (this) {
 -        synchronized (futs) {
++        synchronized (sync) {
              if (err != null)
                  return;
  
@@@ -661,8 -657,9 +657,9 @@@
              log.debug("Received onOwnerChanged() callback [entry=" + entry + ", owner=" + owner + "]");
  
          if (owner != null && owner.version().equals(lockVer)) {
-             synchronized (this) {
-                 pendingLocks.remove(entry.key());
 -            synchronized (futs) {
++            synchronized (sync) {
+                 if (!pendingLocks.remove(entry.key()))
+                     return false;
              }
  
              if (checkLocks())
@@@ -677,8 -674,10 +674,10 @@@
      /**
       * @return {@code True} if locks have been acquired.
       */
-     private synchronized boolean checkLocks() {
-         return pendingLocks.isEmpty();
+     private boolean checkLocks() {
 -        synchronized (futs) {
++        synchronized (sync) {
+             return pendingLocks.isEmpty();
+         }
      }
  
      /** {@inheritDoc} */
@@@ -709,7 -708,7 +708,7 @@@
          if (isDone() || (err == null && success && !checkLocks()))
              return false;
  
-         synchronized (this) {
 -        synchronized (futs) {
++        synchronized (sync) {
              if (this.err == null)
                  this.err = err;
          }
@@@ -782,7 -787,7 +787,7 @@@
       * @param entries Entries.
       */
      private void map(Iterable<GridDhtCacheEntry> entries) {
-         synchronized (this) {
 -        synchronized (futs) {
++        synchronized (sync) {
              if (mapped)
                  return;
  
@@@ -1109,7 -1119,14 +1119,14 @@@
              if (log.isDebugEnabled())
                  log.debug("Timed out waiting for lock response: " + this);
  
-             timedOut = true;
 -            synchronized (futs) {
++            synchronized (sync) {
+                 timedOut = true;
+ 
+                 // Stop locks and responses processing.
+                 pendingLocks.clear();
+ 
 -                futs.clear();
++                clear();
+             }
  
              boolean releaseLocks = !(inTx() && cctx.tm().deadlockDetectionEnabled());
  

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index 2800897,1bdd9b8..3cb0fbc
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@@ -269,7 -278,7 +278,7 @@@ public final class GridDhtTxPrepareFutu
  
          boolean rmv;
  
-         synchronized (lockKeys) {
 -        synchronized (futs) {
++        synchronized (sync) {
              rmv = lockKeys.remove(entry.txKey());
          }
  
@@@ -300,7 -309,7 +309,7 @@@
          if (!locksReady)
              return false;
  
-         synchronized (lockKeys) {
 -        synchronized (futs) {
++        synchronized (sync) {
              return lockKeys.isEmpty();
          }
      }
@@@ -583,7 -588,7 +588,7 @@@
              }
  
              if (tx.optimistic() && txEntry.explicitVersion() == null) {
-                 synchronized (lockKeys) {
 -                synchronized (futs) {
++                synchronized (sync) {
                      lockKeys.add(txEntry.txKey());
                  }
              }
@@@ -1284,9 -1303,12 +1303,12 @@@
  
                  for (GridDistributedTxMapping nearMapping : tx.nearMap().values()) {
                      if (!tx.dhtMap().containsKey(nearMapping.node().id())) {
+                         if (tx.remainingTime() == -1)
+                             return;
+ 
                          MiniFuture fut = new MiniFuture(nearMapping.node().id(), null, nearMapping);
  
 -                        add(fut);
 +                        add(fut); // Append new future.
  
                          GridDhtTxPrepareRequest req = new GridDhtTxPrepareRequest(
                              futId,
@@@ -1719,4 -1742,38 +1742,38 @@@
              return S.toString(MiniFuture.class, this, "done", isDone(), "cancelled", isCancelled(), "err", error());
          }
      }
+ 
+     /**
+      *
+      */
+     private class PrepareTimeoutObject extends GridTimeoutObjectAdapter {
+         /** */
+         private final long timeout;
+ 
+         /**
+          * @param timeout Timeout.
+          */
+         PrepareTimeoutObject(long timeout) {
+             super(timeout);
+ 
+             this.timeout = timeout;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void onTimeout() {
 -            synchronized (futs) {
 -                futs.clear();
++            synchronized (sync) {
++                clear();
+ 
+                 lockKeys.clear();
+             }
+ 
+             onError(new IgniteTxTimeoutCheckedException("Failed to acquire lock within " +
+                 "provided timeout for transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']'));
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(PrepareTimeoutObject.class, this);
+         }
+     }
  }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
index 05b4a2b,b0eea01..ddb6500
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
@@@ -443,17 -443,27 +443,27 @@@ public final class GridDhtColocatedLock
      /**
       * @return Keys for which locks requested from remote nodes but response isn't received.
       */
-     public Set<KeyCacheObject> requestedKeys() {
-         Set<KeyCacheObject> requestedKeys = null;
+     public Set<IgniteTxKey> requestedKeys() {
 -        synchronized (futs) {
++        synchronized (sync) {
+             if (timeoutObj != null && timeoutObj.requestedKeys != null)
+                 return timeoutObj.requestedKeys;
+ 
+             return requestedKeys0();
+         }
+     }
  
+     /**
+      * @return Keys for which locks requested from remote nodes but response isn't received.
+      */
+     private Set<IgniteTxKey> requestedKeys0() {
          for (IgniteInternalFuture<Boolean> miniFut : futures()) {
              if (isMini(miniFut) && !miniFut.isDone()) {
-                 if (requestedKeys == null)
-                     requestedKeys = new HashSet<>();
- 
                  MiniFuture mini = (MiniFuture)miniFut;
  
-                 requestedKeys.addAll(mini.keys);
+                 Set<IgniteTxKey> requestedKeys = U.newHashSet(mini.keys.size());
+ 
+                 for (KeyCacheObject key : mini.keys)
+                     requestedKeys.add(new IgniteTxKey(key, cctx.cacheId()));
  
                  return requestedKeys;
              }
@@@ -1318,6 -1331,12 +1331,12 @@@
                  log.debug("Timed out waiting for lock response: " + this);
  
              if (inTx() && cctx.tm().deadlockDetectionEnabled()) {
 -                synchronized (futs) {
++                synchronized (sync) {
+                     requestedKeys = requestedKeys0();
+ 
 -                    futs.clear(); // Stop response processing.
++                    clear(); // Stop response processing.
+                 }
+ 
                  Set<IgniteTxKey> keys = new HashSet<>();
  
                  for (IgniteTxEntry txEntry : tx.allEntries()) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
index 3b53c5e,3d9b6ab..02f6cce
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
@@@ -481,6 -487,38 +487,38 @@@ public final class GridNearLockFuture e
      }
  
      /**
+      * @return Keys for which locks requested from remote nodes but response isn't received.
+      */
+     public Set<IgniteTxKey> requestedKeys() {
 -        synchronized (futs) {
++        synchronized (sync) {
+             if (timeoutObj != null && timeoutObj.requestedKeys != null)
+                 return timeoutObj.requestedKeys;
+ 
+             return requestedKeys0();
+         }
+     }
+ 
+     /**
+      * @return Keys for which locks requested from remote nodes but response isn't received.
+      */
+     private Set<IgniteTxKey> requestedKeys0() {
+         for (IgniteInternalFuture<Boolean> miniFut : futures()) {
+             if (isMini(miniFut) && !miniFut.isDone()) {
+                 MiniFuture mini = (MiniFuture)miniFut;
+ 
+                 Set<IgniteTxKey> requestedKeys = U.newHashSet(mini.keys.size());
+ 
+                 for (KeyCacheObject key : mini.keys)
+                     requestedKeys.add(new IgniteTxKey(key, cctx.cacheId()));
+ 
+                 return requestedKeys;
+             }
+         }
+ 
+         return null;
+     }
+ 
+     /**
       * Finds pending mini future by the given mini ID.
       *
       * @param miniId Mini ID to find.
@@@ -1381,7 -1426,42 +1426,42 @@@
  
              timedOut = true;
  
-             onComplete(false, true);
+             if (inTx() && cctx.tm().deadlockDetectionEnabled()) {
 -                synchronized (futs) {
++                synchronized (sync) {
+                     requestedKeys = requestedKeys0();
+ 
 -                    futs.clear(); // Stop response processing.
++                    clear(); // Stop response processing.
+                 }
+ 
+                 Set<IgniteTxKey> keys = new HashSet<>();
+ 
+                 for (IgniteTxEntry txEntry : tx.allEntries()) {
+                     if (!txEntry.locked())
+                         keys.add(txEntry.txKey());
+                 }
+ 
+                 IgniteInternalFuture<TxDeadlock> fut = cctx.tm().detectDeadlock(tx, keys);
+ 
+                 fut.listen(new IgniteInClosure<IgniteInternalFuture<TxDeadlock>>() {
+                     @Override public void apply(IgniteInternalFuture<TxDeadlock> fut) {
+                         try {
+                             TxDeadlock deadlock = fut.get();
+ 
+                             if (deadlock != null)
+                                 err = new TransactionDeadlockException(deadlock.toString(cctx.shared()));
+                         }
+                         catch (IgniteCheckedException e) {
+                             err = e;
+ 
+                             U.warn(log, "Failed to detect deadlock.", e);
+                         }
+ 
+                         onComplete(false, true);
+                     }
+                 });
+             }
+             else
+                 onComplete(false, true);
          }
  
          /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
index 7a49422,5a300ff..0382b15
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
@@@ -182,6 -198,33 +198,33 @@@ public class GridNearOptimisticTxPrepar
      }
  
      /**
+      * @return Keys for which {@link MiniFuture} isn't completed.
+      */
+     @SuppressWarnings("ForLoopReplaceableByForEach")
+     public Set<IgniteTxKey> requestedKeys() {
 -        synchronized (futs) {
 -            for (int i = 0; i < futs.size(); i++) {
 -                IgniteInternalFuture<GridNearTxPrepareResponse> fut = futs.get(i);
++        synchronized (sync) {
++            for (int i = 0; i < futuresCount(); i++) {
++                IgniteInternalFuture<GridNearTxPrepareResponse> fut = future(i);
+ 
+                 if (isMini(fut) && !fut.isDone()) {
+                     MiniFuture miniFut = (MiniFuture)fut;
+ 
+                     Collection<IgniteTxEntry> entries = miniFut.mapping().entries();
+ 
+                     Set<IgniteTxKey> keys = U.newHashSet(entries.size());
+ 
+                     for (IgniteTxEntry entry : entries)
+                         keys.add(entry.txKey());
+ 
+                     return keys;
+                 }
+             }
+         }
+ 
+         return null;
+     }
+ 
+     /**
       * Finds pending mini future by the given mini ID.
       *
       * @param miniId Mini ID to find.
@@@ -623,6 -674,61 +674,61 @@@
          return cur;
      }
  
+     /**
+      *
+      */
+     @SuppressWarnings("ForLoopReplaceableByForEach")
+     private void onTimeout() {
+         if (cctx.tm().deadlockDetectionEnabled()) {
+             Set<IgniteTxKey> keys = null;
+ 
+             if (keyLockFut != null)
+                 keys = new HashSet<>(keyLockFut.lockKeys);
+             else {
 -                if (futs != null && !futs.isEmpty()) {
 -                    for (int i = 0; i < futs.size(); i++) {
 -                        IgniteInternalFuture<GridNearTxPrepareResponse> fut = futs.get(i);
++                synchronized (sync) {
++                    for (int i = 0; i < futuresCount(); i++) {
++                        IgniteInternalFuture<GridNearTxPrepareResponse> fut = future(i);
+ 
+                         if (isMini(fut) && !fut.isDone()) {
+                             MiniFuture miniFut = (MiniFuture)fut;
+ 
+                             Collection<IgniteTxEntry> entries = miniFut.mapping().entries();
+ 
+                             keys = U.newHashSet(entries.size());
+ 
+                             for (IgniteTxEntry entry : entries)
+                                 keys.add(entry.txKey());
+ 
+                             break;
+                         }
+                     }
+                 }
+             }
+ 
+             add(new GridEmbeddedFuture<>(new IgniteBiClosure<TxDeadlock, Exception, GridNearTxPrepareResponse>() {
+                 @Override public GridNearTxPrepareResponse apply(TxDeadlock deadlock, Exception e) {
+                     if (e != null)
+                         U.warn(log, "Failed to detect deadlock.", e);
+                     else {
+                         e = new IgniteTxTimeoutCheckedException("Failed to acquire lock within provided timeout for " +
+                             "transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']',
+                             deadlock != null ? new TransactionDeadlockException(deadlock.toString(cctx)) : null);
+                     }
+ 
+                     onDone(null, e);
+ 
+                     return null;
+                 }
+             }, cctx.tm().detectDeadlock(tx, keys)));
+         }
+         else {
+             ERR_UPD.compareAndSet(this, null, new IgniteTxTimeoutCheckedException("Failed to acquire lock " +
+                 "within provided timeout for transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']'));
+ 
+             onComplete(false);
+         }
+     }
+ 
      /** {@inheritDoc} */
      @Override public String toString() {
          Collection<String> futs = F.viewReadOnly(futures(), new C1<IgniteInternalFuture<?>, String>() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index f0af551,620d9ae..68b884c
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
@@@ -679,7 -678,7 +678,7 @@@ public class IgniteTxHandler 
  
          IgniteInternalFuture<IgniteInternalTx> fut = finish(nodeId, null, req);
  
--        assert req.txState() != null || fut.error() != null ||
++        assert req.txState() != null || (fut != null && fut.error() != null) ||
              (ctx.tm().tx(req.version()) == null && ctx.tm().nearTx(req.version()) == null);
  
          return fut;

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
index b83133a,3409341..0f7e020
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
@@@ -159,15 -154,9 +159,16 @@@ public class GridCompoundFuture<T, R> e
       *
       * @return Collection of futures.
       */
++    @SuppressWarnings("unchecked")
      public Collection<IgniteInternalFuture<T>> futures() {
 -        synchronized (futs) {
 -            return new ArrayList<>(futs);
 +        synchronized (sync) {
 +            if(futs == null)
 +                return Collections.emptyList();
 +
 +            if (futs instanceof IgniteInternalFuture)
 +                return Collections.singletonList((IgniteInternalFuture<T>)futs);
 +
 +            return new ArrayList<>((Collection<IgniteInternalFuture<T>>)futs);
          }
      }
  
@@@ -240,8 -217,8 +241,17 @@@
      }
  
      /**
 -     * @return {@code True} if this future was initialized. Initialization happens when
 -     *      {@link #markInitialized()} method is called on future.
++     * Clear futures.
++     */
++    protected void clear() {
++        synchronized (sync) {
++            futs = null;
++        }
++    }
++
++    /**
 +     * @return {@code True} if this future was initialized. Initialization happens when {@link #markInitialized()}
 +     * method is called on future.
       */
      public boolean initialized() {
          return initFlag == INIT_FLAG;

http://git-wip-us.apache.org/repos/asf/ignite/blob/f89375bd/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 939e226,6bb2c11..846f6ea
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@@ -127,8 -127,9 +128,9 @@@ public class IgniteBasicTestSuite exten
          suite.addTestSuite(GridNodeMetricsLogSelfTest.class);
  
          suite.addTestSuite(IgniteExceptionInNioWorkerSelfTest.class);
 -
 +        suite.addTestSuite(IgniteLocalNodeMapBeforeStartTest.class);
          suite.addTestSuite(OdbcProcessorValidationSelfTest.class);
+         suite.addTestSuite(OdbcEscapeSequenceSelfTest.class);
  
          GridTestUtils.addTestIfNeeded(suite, DynamicProxySerializationMultiJvmSelfTest.class, ignoredTests);