Skip to content

Commit b867d25

Browse files
NH-2176 - Locking the rollback case too. Fixing a bad catch in locking. Adjusted naming for ceasing implying "distributed" while just using system transaction.
1 parent 72a9db9 commit b867d25

15 files changed

+112
-112
lines changed

src/NHibernate.Test/DebugSessionFactory.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using System.Data.Common;
5-
using System.Threading;
65
using log4net;
76
using NHibernate.Cache;
87
using NHibernate.Cfg;
@@ -59,18 +58,6 @@ public bool CheckSessionsWereClosed()
5958
if (!session.IsOpen)
6059
continue;
6160

62-
if (txContext?.ShouldCloseSessionOnDistributedTransactionCompleted ?? false)
63-
{
64-
// Delayed rollback not having lock from prepare phase? Give it a chance to complete.
65-
Thread.Sleep(100);
66-
txContext.WaitOne();
67-
if (!session.IsOpen)
68-
{
69-
_log.Warn($"Test case had a delayed close of session {session.SessionId}.");
70-
continue;
71-
}
72-
}
73-
7461
_log.Error($"Test case didn't close session {session.SessionId}, closing");
7562
allClosed = false;
7663
(session as ISession)?.Close();

src/NHibernate.Test/NHSpecificTest/DtcFailures/DtcFailuresFixture.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,6 @@ public void CanDeleteItemInDtc([Values(false, true)] bool explicitFlush)
444444
Assert.AreEqual(1, s.Query<Person>().Count(), "Entity not found in database.");
445445
}
446446

447-
// Dodging "latency" due to db still haven't actually committed a distributed tx after scope disposal.
448-
Thread.Sleep(100);
449-
450447
using (var tx = new TransactionScope())
451448
{
452449
using (var s = OpenSession())

src/NHibernate.Test/NHSpecificTest/NH1054/DummyTransactionFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public ITransaction CreateTransaction(ISessionImplementor session)
1818
throw new NotImplementedException();
1919
}
2020

21-
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
21+
public void EnlistInSystemTransactionIfNeeded(ISessionImplementor session)
2222
{
2323
throw new NotImplementedException();
2424
}
2525

26-
public bool IsInDistributedActiveTransaction(ISessionImplementor session)
26+
public bool IsInActiveSystemTransaction(ISessionImplementor session)
2727
{
2828
return false;
2929
}

src/NHibernate.Test/NHSpecificTest/NH1054/NH1054Fixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public void AdoNetWithDistributedTransactionFactoryIsDefaultTransactionFactory()
2626
Configuration configuration = new Configuration();
2727
ISessionFactoryImplementor sessionFactory = (ISessionFactoryImplementor)configuration.BuildSessionFactory();
2828

29-
Assert.That(sessionFactory.Settings.TransactionFactory, Is.InstanceOf<NHibernate.Transaction.AdoNetWithDistributedTransactionFactory>());
29+
Assert.That(sessionFactory.Settings.TransactionFactory, Is.InstanceOf<NHibernate.Transaction.AdoNetWithSystemTransactionFactory>());
3030
}
3131
}
3232
}

src/NHibernate/AdoNet/ConnectionManager.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public bool IsInActiveExplicitTransaction
6969
=> _transaction != null && _transaction.IsActive;
7070

7171
public bool IsInActiveTransaction
72-
=> IsInActiveExplicitTransaction || Factory.TransactionFactory.IsInDistributedActiveTransaction(_session);
72+
=> IsInActiveExplicitTransaction || Factory.TransactionFactory.IsInActiveSystemTransaction(_session);
7373

7474
public bool IsConnected
7575
=> _connection != null || _ownConnection;
@@ -399,51 +399,49 @@ public void EnlistIfRequired(System.Transactions.Transaction transaction)
399399
_connectionAmbientTransaction = transaction;
400400
}
401401

402-
private bool RequireConnectionSwapInDtc
403-
=> _ownConnection && Factory.Dialect.SupportsConcurrentWritingConnectionsInSameTransaction;
404-
405-
public IDisposable FlushingFromDtcTransaction
402+
public IDisposable BeginsFlushingFromSystemTransaction(bool isDistributed)
406403
{
407-
get
404+
var needSwapping = _ownConnection && isDistributed &&
405+
Factory.Dialect.SupportsConcurrentWritingConnectionsInSameTransaction;
406+
if (needSwapping)
408407
{
409-
if (RequireConnectionSwapInDtc)
410-
{
411-
if (Batcher.HasOpenResources)
412-
throw new InvalidOperationException("Batcher still has opened ressources at time of Flush from DTC.");
413-
// Swap out current connection for avoiding using it concurrently to its own 2PC
414-
_dtcBackupConnection = _connection;
415-
_dtcBackupConnectionAmbientTransaction = _connectionAmbientTransaction;
416-
_connection = null;
417-
_connectionAmbientTransaction = null;
418-
}
419-
_flushingFromDtcTransaction = true;
420-
return new StopFlushingFromDtcTransaction(this);
408+
if (Batcher.HasOpenResources)
409+
throw new InvalidOperationException("Batcher still has opened ressources at time of Flush from DTC.");
410+
// Swap out current connection for avoiding using it concurrently to its own 2PC
411+
_dtcBackupConnection = _connection;
412+
_dtcBackupConnectionAmbientTransaction = _connectionAmbientTransaction;
413+
_connection = null;
414+
_connectionAmbientTransaction = null;
421415
}
416+
_flushingFromDtcTransaction = true;
417+
return new EndFlushingFromSystemTransaction(this, needSwapping);
422418
}
423419

424-
private class StopFlushingFromDtcTransaction : IDisposable
420+
private class EndFlushingFromSystemTransaction : IDisposable
425421
{
426422
private readonly ConnectionManager _manager;
423+
private readonly bool _hasSwappedConnection;
427424

428-
public StopFlushingFromDtcTransaction(ConnectionManager manager)
425+
public EndFlushingFromSystemTransaction(ConnectionManager manager, bool hasSwappedConnection)
429426
{
430427
_manager = manager;
428+
_hasSwappedConnection = hasSwappedConnection;
431429
}
432430

433431
public void Dispose()
434432
{
435433
_manager._flushingFromDtcTransaction = false;
436434

437-
if (_manager.RequireConnectionSwapInDtc)
438-
{
439-
// Release the connection potentially acquired for flushing from DTC.
440-
_manager.DisconnectOwnConnection();
441-
// Swap back current connection
442-
_manager._connection = _manager._dtcBackupConnection;
443-
_manager._connectionAmbientTransaction = _manager._dtcBackupConnectionAmbientTransaction;
444-
_manager._dtcBackupConnection = null;
445-
_manager._dtcBackupConnectionAmbientTransaction = null;
446-
}
435+
if (!_hasSwappedConnection)
436+
return;
437+
438+
// Release the connection potentially acquired for flushing from DTC.
439+
_manager.DisconnectOwnConnection();
440+
// Swap back current connection
441+
_manager._connection = _manager._dtcBackupConnection;
442+
_manager._connectionAmbientTransaction = _manager._dtcBackupConnectionAmbientTransaction;
443+
_manager._dtcBackupConnection = null;
444+
_manager._dtcBackupConnectionAmbientTransaction = null;
447445
}
448446
}
449447
}

src/NHibernate/Cfg/SettingsFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ private static System.Type CreateLinqQueryProviderType(IDictionary<string, strin
393393
private static ITransactionFactory CreateTransactionFactory(IDictionary<string, string> properties)
394394
{
395395
string className = PropertiesHelper.GetString(
396-
Environment.TransactionStrategy, properties, typeof(AdoNetWithDistributedTransactionFactory).FullName);
396+
Environment.TransactionStrategy, properties, typeof(AdoNetWithSystemTransactionFactory).FullName);
397397
log.Info("Transaction factory: " + className);
398398

399399
try

src/NHibernate/Driver/SqlClientDriver.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,11 @@ public override bool SupportsMultipleQueries
201201
{
202202
get { return true; }
203203
}
204+
205+
/// <summary>
206+
/// With read committed snapshot or lower, SQL Server may have not actually already committed the transaction
207+
/// right after the scope disposal.
208+
/// </summary>
209+
public override bool HasDelayedDistributedTransactionCompletion => true;
204210
}
205211
}

src/NHibernate/Impl/AbstractSessionImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ protected void AfterOperation(bool success)
437437

438438
protected void EnlistInAmbientTransactionIfNeeded()
439439
{
440-
_factory.TransactionFactory.EnlistInDistributedTransactionIfNeeded(this);
440+
_factory.TransactionFactory.EnlistInSystemTransactionIfNeeded(this);
441441
}
442442

443443
internal IOuterJoinLoadable GetOuterJoinLoadable(string entityName)

src/NHibernate/Impl/SessionImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1560,7 +1560,7 @@ public void Dispose()
15601560
log.Debug(string.Format("[session-id={0}] running ISession.Dispose()", SessionId));
15611561
if (TransactionContext != null)
15621562
{
1563-
TransactionContext.ShouldCloseSessionOnDistributedTransactionCompleted = true;
1563+
TransactionContext.ShouldCloseSessionOnSystemTransactionCompleted = true;
15641564
return;
15651565
}
15661566
Dispose(true);

src/NHibernate/Impl/StatelessSessionImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ public void Dispose()
859859
log.Debug("running IStatelessSession.Dispose()");
860860
if (TransactionContext != null)
861861
{
862-
TransactionContext.ShouldCloseSessionOnDistributedTransactionCompleted = true;
862+
TransactionContext.ShouldCloseSessionOnSystemTransactionCompleted = true;
863863
return;
864864
}
865865
Dispose(true);

src/NHibernate/NHibernate.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
<Compile Include="ISessionBuilder.cs" />
152152
<Compile Include="Impl\ISessionCreationOptions.cs" />
153153
<Compile Include="Tool\hbm2ddl\IDatabaseMetadata.cs" />
154+
<Compile Include="Transaction\AdoNetWithSystemTransactionFactory.cs" />
154155
<Compile Include="Util\DelegateHelper.cs" />
155156
<Compile Include="Dialect\BitwiseFunctionOperation.cs" />
156157
<Compile Include="Dialect\DB2Dialect.cs" />
@@ -673,7 +674,6 @@
673674
<Compile Include="StaleObjectStateException.cs" />
674675
<Compile Include="Tool\hbm2ddl\SchemaExport.cs" />
675676
<Compile Include="TransactionException.cs" />
676-
<Compile Include="Transaction\AdoNetWithDistributedTransactionFactory.cs" />
677677
<Compile Include="Transaction\AdoTransaction.cs" />
678678
<Compile Include="Transaction\AfterTransactionCompletes.cs" />
679679
<Compile Include="Transaction\ITransactionFactory.cs" />

src/NHibernate/Transaction/AdoNetTransactionFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ public ITransaction CreateTransaction(ISessionImplementor session)
2020
return new AdoTransaction(session);
2121
}
2222

23-
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
23+
public void EnlistInSystemTransactionIfNeeded(ISessionImplementor session)
2424
{
2525
// nothing need to do here, we only support local transactions with this factory
2626
}
2727

28-
public bool IsInDistributedActiveTransaction(ISessionImplementor session)
28+
public bool IsInActiveSystemTransaction(ISessionImplementor session)
2929
{
3030
return false;
3131
}

0 commit comments

Comments
 (0)