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/master Commit: f89375bdd6159134fae5d0b7b28b876b6e335a32 Parents: 2d5d5bc fea3eea Author: agura <[email protected]> Authored: Mon Aug 29 20:35:08 2016 +0300 Committer: agura <[email protected]> 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);
