From: <ric...@us...> - 2010-05-07 22:44:20
|
Revision: 4979 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4979&view=rev Author: ricbrown Date: 2010-05-07 22:44:13 +0000 (Fri, 07 May 2010) Log Message: ----------- Fix NH-2192 (Thread safety issue with QueryParameters.PrepareParameterTypes) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Model.cs Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2010-05-01 22:22:06 UTC (rev 4978) +++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2010-05-07 22:44:13 UTC (rev 4979) @@ -304,7 +304,7 @@ if (session.EnabledFilters.Count == 0 || sql.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0) { - processedSQL = sql; + processedSQL = sql.Copy(); return; } @@ -393,7 +393,7 @@ processedSQL = result.ToSqlString(); } - private IList<Parameter> ResetParameterLocations(SqlString sqlString) + private IList<Parameter> FindParametersIn(SqlString sqlString) { IList<Parameter> sqlParameters = new List<Parameter>(); @@ -401,9 +401,7 @@ { if (sqlParameter is Parameter) { - Parameter parameter = (Parameter)sqlParameter; - parameter.ParameterPosition = null; - sqlParameters.Add(parameter); + sqlParameters.Add((Parameter)sqlParameter); } } @@ -441,7 +439,7 @@ int parameterIndex = 0; int totalSpan = 0; - IList<Parameter> sqlParameters = ResetParameterLocations(sqlString); + IList<Parameter> sqlParameters = FindParametersIn(sqlString); for (int index = 0; index < PositionalParameterTypes.Length; index++) { Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2010-05-01 22:22:06 UTC (rev 4978) +++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2010-05-07 22:44:13 UTC (rev 4979) @@ -572,6 +572,22 @@ } /// <summary> + /// Make a copy of the SqlString, with new parameter references (Placeholders) + /// </summary> + public SqlString Copy() + { + SqlString clone = Clone(); + + for (int i=0; i<clone.sqlParts.Length; i++) + { + if (clone.sqlParts[i] is Parameter) + clone.sqlParts[i] = SqlCommand.Parameter.Placeholder; + } + + return clone; + } + + /// <summary> /// Returns substring of this SqlString starting with the specified /// <paramref name="text" />. If the text is not found, returns an /// empty, not-null SqlString. Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs 2010-05-07 22:44:13 UTC (rev 4979) @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2192 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void OnSetUp() + { + base.OnSetUp(); + + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Save(new ContentItem() { Name = "Test" }); + s.Save(new ContentItem() { Name = "Test" }); + s.Save(new ContentItem() { Name = "Test2" }); + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Delete("from ContentItem"); + tx.Commit(); + } + + base.OnTearDown(); + } + + private const int _threadCount = 150; + + [Test] + public void HqlIsThreadsafe_UsingThreads() + { + object sync = new object(); + List<int> results = new List<int>(); + List<Exception> exceptions = new List<Exception>(); + + var threads = new List<Thread>(); + + for (int i=0; i<_threadCount; i++) + { + var thread = new Thread(new ThreadStart(() => + { + try + { + int result = FetchRowResults(); + lock (sync) + { + results.Add(result); + } + } + catch (Exception e) + { + lock (sync) + { + exceptions.Add(e); + } + } + })); + + threads.Add(thread); + } + + threads.ForEach(t => t.Start()); + threads.ForEach(t => t.Join()); + + if (exceptions.Count > 0) + throw exceptions[0]; + + results.ForEach(r => Assert.That(r, Is.EqualTo(2))); + } + + [Test] + public void HqlIsThreadsafe_UsingPool() + { + List<Exception> exceptions = new List<Exception>(); + Func<int> result = FetchRowResults; + List<IAsyncResult> results = new List<IAsyncResult>(); + + for (int i=0; i<_threadCount; i++) + results.Add(result.BeginInvoke(null, null)); + + results.ForEach(r => + { + try + { + Assert.That(result.EndInvoke(r), Is.EqualTo(2)); + } + catch (Exception e) + { + exceptions.Add(e); + } + }); + + if (exceptions.Count > 0) + throw exceptions[0]; + } + + private int FetchRowResults() + { + using (var s = Sfi.OpenSession()) + { + var count = + s.CreateQuery("select ci from ContentItem ci where ci.Name = :v1") + .SetParameter("v1", "Test") + .List<ContentItem>() + .Count; + + return count; + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Mappings.hbm.xml 2010-05-07 22:44:13 UTC (rev 4979) @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2192"> + + <class name="ContentItem"> + <id name="Id"> + <generator class="hilo" /> + </id> + <property name="Name" type="String" /> + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2192/Model.cs 2010-05-07 22:44:13 UTC (rev 4979) @@ -0,0 +1,8 @@ +namespace NHibernate.Test.NHSpecificTest.NH2192 +{ + public class ContentItem + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-05-01 22:22:06 UTC (rev 4978) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-05-07 22:44:13 UTC (rev 4979) @@ -710,6 +710,8 @@ <Compile Include="NHSpecificTest\NH2077\Model.cs" /> <Compile Include="NHSpecificTest\NH2113\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2113\Model.cs" /> + <Compile Include="NHSpecificTest\NH2192\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2192\Model.cs" /> <Compile Include="NHSpecificTest\NH473\Child.cs" /> <Compile Include="NHSpecificTest\NH473\Fixture.cs" /> <Compile Include="NHSpecificTest\NH473\Parent.cs" /> @@ -2132,6 +2134,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2192\Mappings.hbm.xml" /> <EmbeddedResource Include="ListIndex\SimpleOneToMany.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\SessionIdLoggingContextTest\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2113\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |