|
From: <fab...@us...> - 2009-05-14 06:41:15
|
Revision: 4298
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4298&view=rev
Author: fabiomaulo
Date: 2009-05-14 06:41:09 +0000 (Thu, 14 May 2009)
Log Message:
-----------
- Improved log to check Dtc possible problems
- Fix NH-1769 (by Timo Rantanen)
- added some test for Dtc
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs
trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/DtcFailures/DtcFailuresFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-05-14 03:56:57 UTC (rev 4297)
+++ trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-05-14 06:41:09 UTC (rev 4298)
@@ -318,10 +318,13 @@
using (var tx = new TransactionScope(ambientTransation))
{
BeforeTransactionCompletion(null);
- if (FlushMode != FlushMode.Never)
+ if (FlushMode != FlushMode.Never && ConnectionManager.IsConnected)
{
using (ConnectionManager.FlushingFromDtcTransaction)
+ {
+ logger.Debug(string.Format("[session-id={0}] Flushing from Dtc Transaction", sessionId));
Flush();
+ }
}
logger.Debug("prepared for DTC transaction");
@@ -333,7 +336,6 @@
{
logger.Error("DTC transaction prepre phase failed", exception);
preparingEnlistment.ForceRollback(exception);
-
}
}
}
@@ -382,13 +384,21 @@
AfterTransactionBegin(null);
ambientTransation.TransactionCompleted += delegate(object sender, TransactionEventArgs e)
{
- bool wasSuccessful = e.Transaction.TransactionInformation.Status
- == TransactionStatus.Committed;
- AfterTransactionCompletion(wasSuccessful, null);
- if (shouldCloseSessionOnDtcTransactionCompleted)
+ bool wasSuccessful = false;
+ try
{
- Dispose(true);
+ wasSuccessful = e.Transaction.TransactionInformation.Status
+ == TransactionStatus.Committed;
}
+ catch (ObjectDisposedException ode)
+ {
+ logger.Warn("Completed transaction was disposed.", ode);
+ }
+ AfterTransactionCompletion(wasSuccessful, null);
+ if (shouldCloseSessionOnDtcTransactionCompleted)
+ {
+ Dispose(true);
+ }
ambientTransation = null;
};
ambientTransation.EnlistVolatile(this, EnlistmentOptions.EnlistDuringPrepareRequired);
Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-05-14 03:56:57 UTC (rev 4297)
+++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-05-14 06:41:09 UTC (rev 4298)
@@ -226,7 +226,7 @@
if (log.IsDebugEnabled)
{
- log.Debug("opened session at timestamp: " + timestamp);
+ log.Debug(string.Format("[session-id={0}]opened session at timestamp:{1}", sessionId, timestamp));
}
CheckAndUpdateSessionStatus();
@@ -1655,7 +1655,7 @@
{
using (new SessionIdLoggingContext(sessionId))
{
- log.Debug("running ISession.Dispose()");
+ log.Debug(string.Format("[session-id={0}]running ISession.Dispose()",sessionId));
if (TakingPartInDtcTransaction)
{
shouldCloseSessionOnDtcTransactionCompleted = true;
@@ -1684,6 +1684,8 @@
return;
}
+ log.Debug(string.Format("[session-id={0}]executing real Dispose({1})", sessionId, isDisposing));
+
// free managed resources that are being managed by the session if we
// know this call came through Dispose()
if (isDisposing && !IsClosed)
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/DtcFailures/DtcFailuresFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/DtcFailures/DtcFailuresFixture.cs 2009-05-14 03:56:57 UTC (rev 4297)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/DtcFailures/DtcFailuresFixture.cs 2009-05-14 06:41:09 UTC (rev 4298)
@@ -2,6 +2,8 @@
using System.Collections;
using System.Threading;
using System.Transactions;
+using log4net;
+using log4net.Repository.Hierarchy;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.DtcFailures
@@ -9,9 +11,11 @@
[TestFixture]
public class DtcFailuresFixture : TestCase
{
+ private static readonly ILog log = LogManager.GetLogger(typeof(DtcFailuresFixture));
+
protected override IList Mappings
{
- get { return new string[] {"NHSpecificTest.DtcFailures.Mappings.hbm.xml"}; }
+ get { return new[] {"NHSpecificTest.DtcFailures.Mappings.hbm.xml"}; }
}
protected override string MappingsAssembly
@@ -51,7 +55,7 @@
using (ISession s = sessions.OpenSession())
{
new ForceEscalationToDistributedTx(true); //will rollback tx
- s.Save(new Person {CreatedAt = DateTime.Today});
+ s.Save(new Person { CreatedAt = DateTime.Today });
tx.Complete();
}
@@ -67,6 +71,151 @@
}
[Test]
+ [Description("Another action inside the transaction do the rollBack outside nh-session-scope.")]
+ public void RollbackOutsideNh()
+ {
+ try
+ {
+ using (var txscope = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ var person = new Person { CreatedAt = DateTime.Now };
+ s.Save(person);
+ }
+ new ForceEscalationToDistributedTx(true); //will rollback tx
+
+ txscope.Complete();
+ }
+
+ log.DebugFormat("Transaction fail.");
+ Assert.Fail("Expected tx abort");
+ }
+ catch (TransactionAbortedException)
+ {
+ log.DebugFormat("Transaction aborted.");
+ }
+ }
+
+ [Test]
+ [Description("rollback inside nh-session-scope should not commit save and the transaction should be aborted.")]
+ public void TransactionInsertWithRollBackTask()
+ {
+ try
+ {
+ using (var txscope = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ var person = new Person {CreatedAt = DateTime.Now};
+ s.Save(person);
+ new ForceEscalationToDistributedTx(true); //will rollback tx
+ person.CreatedAt = DateTime.Now;
+ s.Update(person);
+ }
+ txscope.Complete();
+ }
+ log.DebugFormat("Transaction fail.");
+ Assert.Fail("Expected tx abort");
+ }
+ catch (TransactionAbortedException)
+ {
+ log.DebugFormat("Transaction aborted.");
+ }
+ }
+
+ [Test, Ignore("Not fixed.")]
+ [Description(@"Two session in two txscope
+(without an explicit NH transaction and without an explicit flush)
+and with a rollback in the second dtc and a ForceRollback outside nh-session-scope.")]
+ public void TransactionInsertLoadWithRollBackTask()
+ {
+ object savedId;
+ using (var txscope = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ var person = new Person {CreatedAt = DateTime.Now};
+ savedId = s.Save(person);
+ }
+ txscope.Complete();
+ }
+ try
+ {
+ using (var txscope = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ var person = s.Get<Person>(savedId);
+ person.CreatedAt = DateTime.Now;
+ s.Update(person);
+ }
+ new ForceEscalationToDistributedTx(true);
+
+ log.Debug("completing the tx scope");
+ txscope.Complete();
+ }
+ log.Debug("Transaction fail.");
+ Assert.Fail("Expected tx abort");
+ }
+ catch (TransactionAbortedException)
+ {
+ log.Debug("Transaction aborted.");
+ }
+ finally
+ {
+ using (var txscope = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ var person = s.Get<Person>(savedId);
+ s.Delete(person);
+ }
+ txscope.Complete();
+ }
+ }
+ }
+
+ private int totalCall;
+
+ [Test, Explicit]
+ public void MultiThreadedTransaction()
+ {
+ // Test added for NH-1709 (trying to recreate the issue... without luck)
+ // If one thread break the test, you can see the result in the console.
+ ((Logger)log.Logger).Level = log4net.Core.Level.Debug;
+ var actions = new MultiThreadRunner<object>.ExecuteAction[]
+ {
+ delegate(object o)
+ {
+ Can_roll_back_transaction();
+ totalCall++;
+ },
+ delegate(object o)
+ {
+ RollbackOutsideNh();
+ totalCall++;
+ },
+ delegate(object o)
+ {
+ TransactionInsertWithRollBackTask();
+ totalCall++;
+ },
+ //delegate(object o)
+ // {
+ // TransactionInsertLoadWithRollBackTask();
+ // totalCall++;
+ // },
+ };
+ var mtr = new MultiThreadRunner<object>(20, actions)
+ {
+ EndTimeout = 5000, TimeoutBetweenThreadStart = 5
+ };
+ mtr.Run(null);
+ log.DebugFormat("{0} calls", totalCall);
+ }
+
+ [Test]
public void CanDeleteItemInDtc()
{
object id;
@@ -95,6 +244,26 @@
}
}
+ [Test]
+ [Description("Open/Close a session inside a TransactionScope fails.")]
+ public void NH1744()
+ {
+ using (var tx = new TransactionScope())
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ s.Flush();
+ }
+
+ using (ISession s = sessions.OpenSession())
+ {
+ s.Flush();
+ }
+
+ //and I always leave the transaction disposed without calling tx.Complete(), I let the database server to rollback all actions in this test.
+ }
+ }
+
public class ForceEscalationToDistributedTx : IEnlistmentNotification
{
private readonly bool shouldRollBack;
@@ -114,6 +283,7 @@
Assert.AreNotEqual(thread, Thread.CurrentThread.ManagedThreadId);
if (shouldRollBack)
{
+ log.Debug(">>>>Force Rollback<<<<<");
preparingEnlistment.ForceRollback();
}
else
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|