|
From: <jul...@us...> - 2010-09-21 15:00:26
|
Revision: 5198
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5198&view=rev
Author: julian-maughan
Date: 2010-09-21 15:00:19 +0000 (Tue, 21 Sep 2010)
Log Message:
-----------
Port of HHH-4545 - Allow IExecutable to register for before or after transaction completion callbacks. Note that the Hibernate revision affects a lot more files because of an errant find/replace.
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Action/BulkOperationCleanupAction.cs
trunk/nhibernate/src/NHibernate/Action/CollectionAction.cs
trunk/nhibernate/src/NHibernate/Action/CollectionUpdateAction.cs
trunk/nhibernate/src/NHibernate/Action/EntityAction.cs
trunk/nhibernate/src/NHibernate/Action/EntityDeleteAction.cs
trunk/nhibernate/src/NHibernate/Action/EntityIdentityInsertAction.cs
trunk/nhibernate/src/NHibernate/Action/EntityInsertAction.cs
trunk/nhibernate/src/NHibernate/Action/EntityUpdateAction.cs
trunk/nhibernate/src/NHibernate/Action/IExecutable.cs
trunk/nhibernate/src/NHibernate/Cache/CacheLock.cs
trunk/nhibernate/src/NHibernate/Cache/ICacheConcurrencyStrategy.cs
trunk/nhibernate/src/NHibernate/Cache/NonstrictReadWriteCache.cs
trunk/nhibernate/src/NHibernate/Cache/ReadOnlyCache.cs
trunk/nhibernate/src/NHibernate/Cache/ReadWriteCache.cs
trunk/nhibernate/src/NHibernate/Engine/ActionQueue.cs
trunk/nhibernate/src/NHibernate/Event/Default/AbstractLockUpgradeEventListener.cs
trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs
trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate.Test/CacheTest/CacheFixture.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Cache/Access/
trunk/nhibernate/src/NHibernate/Cache/Access/ISoftLock.cs
Removed Paths:
-------------
trunk/nhibernate/src/NHibernate/Cache/ISoftLock.cs
Modified: trunk/nhibernate/src/NHibernate/Action/BulkOperationCleanupAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/BulkOperationCleanupAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/BulkOperationCleanupAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -112,15 +112,24 @@
// nothing to do
}
- public bool HasAfterTransactionCompletion()
+ public BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess
{
- return true;
+ get
+ {
+ return null;
+ }
}
- public void AfterTransactionCompletion(bool success)
+ public AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess
{
- EvictEntityRegions();
- EvictCollectionRegions();
+ get
+ {
+ return new AfterTransactionCompletionProcessDelegate((success) =>
+ {
+ this.EvictEntityRegions();
+ this.EvictCollectionRegions();
+ });
+ }
}
private void EvictCollectionRegions()
@@ -136,7 +145,7 @@
private void EvictEntityRegions()
{
- if(affectedEntityNames!=null)
+ if (affectedEntityNames != null)
{
foreach (string entityName in affectedEntityNames)
{
Modified: trunk/nhibernate/src/NHibernate/Action/CollectionAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/CollectionAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/CollectionAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,7 @@
using System;
using System.Runtime.Serialization;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NHibernate.Collection;
using NHibernate.Engine;
using NHibernate.Impl;
@@ -100,30 +101,32 @@
}
}
- /// <summary> Execute this action</summary>
+ /// <summary>Execute this action</summary>
public abstract void Execute();
- /// <summary>
- /// Do we need to retain this instance until after the transaction completes?
- /// </summary>
- /// <returns>
- /// False if this class defines a no-op has after transaction completion.
- /// </returns>
- public bool HasAfterTransactionCompletion()
+ public virtual BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess
{
- return persister.HasCache;
+ get
+ {
+ return null;
+ }
}
- /// <summary> Called after the transaction completes</summary>
- public virtual void AfterTransactionCompletion(bool success)
+ public virtual AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess
{
- if (persister.HasCache)
+ get
{
- CacheKey ck = new CacheKey(key, persister.KeyType, persister.Role, session.EntityMode, session.Factory);
- persister.Cache.Release(ck, softLock);
+ return new AfterTransactionCompletionProcessDelegate((success) =>
+ {
+ if (persister.HasCache)
+ {
+ CacheKey ck = new CacheKey(key, persister.KeyType, persister.Role, Session.EntityMode, Session.Factory);
+ persister.Cache.Release(ck, softLock);
+ }
+ });
}
}
-
+
#endregion
public ISoftLock Lock
Modified: trunk/nhibernate/src/NHibernate/Action/CollectionUpdateAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/CollectionUpdateAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/CollectionUpdateAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -113,32 +113,46 @@
}
}
- public override void AfterTransactionCompletion(bool success)
+ public override BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess
{
- // NH Different behavior: to support unlocking collections from the cache.(r3260)
- if (Persister.HasCache)
+ get
+ {
+ return null;
+ }
+ }
+
+ public override AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess
+ {
+ get
{
- CacheKey ck = new CacheKey(Key, Persister.KeyType, Persister.Role, Session.EntityMode, Session.Factory);
-
- if (success)
+ return new AfterTransactionCompletionProcessDelegate((success) =>
{
- // we can't disassemble a collection if it was uninitialized
- // or detached from the session
- if (Collection.WasInitialized && Session.PersistenceContext.ContainsCollection(Collection))
+ // NH Different behavior: to support unlocking collections from the cache.(r3260)
+ if (Persister.HasCache)
{
- CollectionCacheEntry entry = new CollectionCacheEntry(Collection, Persister);
- bool put = Persister.Cache.AfterUpdate(ck, entry, null, Lock);
+ CacheKey ck = new CacheKey(Key, Persister.KeyType, Persister.Role, Session.EntityMode, Session.Factory);
- if (put && Session.Factory.Statistics.IsStatisticsEnabled)
+ if (success)
{
- Session.Factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
+ // we can't disassemble a collection if it was uninitialized
+ // or detached from the session
+ if (Collection.WasInitialized && Session.PersistenceContext.ContainsCollection(Collection))
+ {
+ CollectionCacheEntry entry = new CollectionCacheEntry(Collection, Persister);
+ bool put = Persister.Cache.AfterUpdate(ck, entry, null, Lock);
+
+ if (put && Session.Factory.Statistics.IsStatisticsEnabled)
+ {
+ Session.Factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
+ }
+ }
}
+ else
+ {
+ Persister.Cache.Release(ck, Lock);
+ }
}
- }
- else
- {
- Persister.Cache.Release(ck, Lock);
- }
+ });
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Action/EntityAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/EntityAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/EntityAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -102,13 +102,37 @@
public abstract void Execute();
- public bool HasAfterTransactionCompletion()
+ public virtual BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess
{
+ get
+ {
+ return new BeforeTransactionCompletionProcessDelegate(BeforeTransactionCompletionProcessImpl);
+ }
+ }
+
+ public virtual AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess
+ {
+ get
+ {
+ return NeedsAfterTransactionCompletion()
+ ? new AfterTransactionCompletionProcessDelegate(AfterTransactionCompletionProcessImpl)
+ : null;
+ }
+ }
+
+ private bool NeedsAfterTransactionCompletion()
+ {
return persister.HasCache || HasPostCommitEventListeners;
}
+
+ protected virtual void BeforeTransactionCompletionProcessImpl()
+ {
+ }
+
+ protected virtual void AfterTransactionCompletionProcessImpl(bool success)
+ {
+ }
- public abstract void AfterTransactionCompletion(bool success);
-
#endregion
#region IComparable<EntityAction> Members
Modified: trunk/nhibernate/src/NHibernate/Action/EntityDeleteAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/EntityDeleteAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/EntityDeleteAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NHibernate.Engine;
using NHibernate.Event;
using NHibernate.Persister.Entity;
@@ -125,8 +126,8 @@
}
return veto;
}
-
- public override void AfterTransactionCompletion(bool success)
+
+ protected override void AfterTransactionCompletionProcessImpl(bool success)
{
if (Persister.HasCache)
{
Modified: trunk/nhibernate/src/NHibernate/Action/EntityIdentityInsertAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/EntityIdentityInsertAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/EntityIdentityInsertAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -82,7 +82,6 @@
persister.SetIdentifier(instance, generatedId, Session.EntityMode);
}
-
//TODO from H3.2 : this bit actually has to be called after all cascades!
// but since identity insert is called *synchronously*,
// instead of asynchronously as other actions, it isn't
@@ -144,9 +143,9 @@
return veto;
}
- //Make 100% certain that this is called before any subsequent ScheduledUpdate.afterTransactionCompletion()!!
- public override void AfterTransactionCompletion(bool success)
+ protected override void AfterTransactionCompletionProcessImpl(bool success)
{
+ //TODO Make 100% certain that this is called before any subsequent ScheduledUpdate.afterTransactionCompletion()!!
//TODO from H3.2: reenable if we also fix the above todo
/*EntityPersister persister = getEntityPersister();
if ( success && persister.hasCache() && !persister.isCacheInvalidationRequired() ) {
Modified: trunk/nhibernate/src/NHibernate/Action/EntityInsertAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/EntityInsertAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/EntityInsertAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -102,7 +102,7 @@
}
}
- public override void AfterTransactionCompletion(bool success)
+ protected override void AfterTransactionCompletionProcessImpl(bool success)
{
//Make 100% certain that this is called before any subsequent ScheduledUpdate.afterTransactionCompletion()!!
IEntityPersister persister = Persister;
Modified: trunk/nhibernate/src/NHibernate/Action/EntityUpdateAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/EntityUpdateAction.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/EntityUpdateAction.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
using NHibernate.Engine;
using NHibernate.Event;
@@ -134,7 +135,7 @@
}
}
- public override void AfterTransactionCompletion(bool success)
+ protected override void AfterTransactionCompletionProcessImpl(bool success)
{
IEntityPersister persister = Persister;
if (persister.HasCache)
@@ -160,7 +161,7 @@
PostCommitUpdate();
}
}
-
+
private void PostUpdate()
{
IPostUpdateEventListener[] postListeners = Session.Listeners.PostUpdateEventListeners;
Modified: trunk/nhibernate/src/NHibernate/Action/IExecutable.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Action/IExecutable.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Action/IExecutable.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,29 @@
+using NHibernate.Engine;
+
namespace NHibernate.Action
{
/// <summary>
+ /// Delegate representing some process that needs to occur before transaction completion.
+ /// </summary>
+ /// <remarks>
+ /// NH specific: C# does not support dynamic interface proxies so a delegate is used in
+ /// place of the Hibernate interface (see Action/BeforeTransactionCompletionProcess). The
+ /// delegate omits the <see cref="ISessionImplementor" /> parameter as it is not used.
+ /// </remarks>
+ public delegate void BeforeTransactionCompletionProcessDelegate();
+
+ /// <summary>
+ /// Delegate representing some process that needs to occur after transaction completion.
+ /// </summary>
+ /// <param name="success"> Did the transaction complete successfully? True means it did.</param>
+ /// <remarks>
+ /// NH specific: C# does not support dynamic interface proxies so a delegate is used in
+ /// place of the Hibernate interface (see Action/AfterTransactionCompletionProcess). The
+ /// delegate omits the <see cref="ISessionImplementor" /> parameter as it is not used.
+ /// </remarks>
+ public delegate void AfterTransactionCompletionProcessDelegate(bool success);
+
+ /// <summary>
/// An operation which may be scheduled for later execution.
/// Usually, the operation is a database insert/update/delete,
/// together with required second-level cache management.
@@ -10,7 +33,7 @@
/// <summary>
/// What spaces (tables) are affected by this action?
/// </summary>
- string[] PropertySpaces { get;}
+ string[] PropertySpaces { get; }
/// <summary> Called before executing any actions</summary>
void BeforeExecutions();
@@ -18,15 +41,14 @@
/// <summary> Execute this action</summary>
void Execute();
- /// <summary>
- /// Do we need to retain this instance until after the transaction completes?
+ /// <summary>
+ /// Get the before-transaction-completion process, if any, for this action.
/// </summary>
- /// <returns>
- /// False if this class defines a no-op has after transaction completion.
- /// </returns>
- bool HasAfterTransactionCompletion();
-
- /// <summary> Called after the transaction completes</summary>
- void AfterTransactionCompletion(bool success);
+ BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess { get; }
+
+ /// <summary>
+ /// Get the after-transaction-completion process, if any, for this action.
+ /// </summary>
+ AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess { get; }
}
}
Property changes on: trunk/nhibernate/src/NHibernate/Cache/Access
___________________________________________________________________
Added: bugtraq:url
+ http://jira.nhibernate.org/browse/%BUGID%
Added: bugtraq:logregex
+ NH-\d+
Copied: trunk/nhibernate/src/NHibernate/Cache/Access/ISoftLock.cs (from rev 5197, trunk/nhibernate/src/NHibernate/Cache/ISoftLock.cs)
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/Access/ISoftLock.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Cache/Access/ISoftLock.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Cache.Access
+{
+ /// <summary>
+ /// Marker interface, denoting a client-visible "soft lock" on a cached item.
+ /// </summary>
+ public interface ISoftLock
+ {
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Cache/CacheLock.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/CacheLock.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/CacheLock.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using NHibernate.Cache.Access;
namespace NHibernate.Cache
{
Modified: trunk/nhibernate/src/NHibernate/Cache/ICacheConcurrencyStrategy.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/ICacheConcurrencyStrategy.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/ICacheConcurrencyStrategy.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,4 +1,5 @@
using System.Collections;
+using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
namespace NHibernate.Cache
Deleted: trunk/nhibernate/src/NHibernate/Cache/ISoftLock.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/ISoftLock.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/ISoftLock.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,11 +0,0 @@
-using System;
-
-namespace NHibernate.Cache
-{
- /// <summary>
- /// Marker interface, denoting a client-visible "soft lock" on a cached item.
- /// </summary>
- public interface ISoftLock
- {
- }
-}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Cache/NonstrictReadWriteCache.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/NonstrictReadWriteCache.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/NonstrictReadWriteCache.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,7 +1,7 @@
using System;
using System.Collections;
+using NHibernate.Cache.Access;
-
namespace NHibernate.Cache
{
/// <summary>
Modified: trunk/nhibernate/src/NHibernate/Cache/ReadOnlyCache.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/ReadOnlyCache.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/ReadOnlyCache.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,7 +1,7 @@
using System;
using System.Collections;
+using NHibernate.Cache.Access;
-
namespace NHibernate.Cache
{
/// <summary>
Modified: trunk/nhibernate/src/NHibernate/Cache/ReadWriteCache.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cache/ReadWriteCache.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Cache/ReadWriteCache.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,7 +1,7 @@
using System;
using System.Collections;
+using NHibernate.Cache.Access;
-
namespace NHibernate.Cache
{
/// <summary>
Modified: trunk/nhibernate/src/NHibernate/Engine/ActionQueue.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/ActionQueue.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Engine/ActionQueue.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using Iesi.Collections.Generic;
@@ -39,7 +40,8 @@
private readonly List<CollectionUpdateAction> collectionUpdates;
private readonly List<CollectionRemoveAction> collectionRemovals;
- private readonly List<IExecutable> executions;
+ private readonly AfterTransactionCompletionProcessQueue afterTransactionProcesses;
+ private readonly BeforeTransactionCompletionProcessQueue beforeTransactionProcesses;
public ActionQueue(ISessionImplementor session)
{
@@ -52,7 +54,8 @@
collectionUpdates = new List<CollectionUpdateAction>(InitQueueListSize);
collectionRemovals = new List<CollectionRemoveAction>(InitQueueListSize);
- executions = new List<IExecutable>(InitQueueListSize * 3);
+ afterTransactionProcesses = new AfterTransactionCompletionProcessQueue(session);
+ beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue(session);
}
public virtual void Clear()
@@ -103,10 +106,19 @@
public void AddAction(BulkOperationCleanupAction cleanupAction)
{
- // Add these directly to the executions queue
- executions.Add(cleanupAction);
+ RegisterCleanupActions(cleanupAction);
}
-
+
+ public void RegisterProcess(AfterTransactionCompletionProcessDelegate process)
+ {
+ afterTransactionProcesses.Register(process);
+ }
+
+ public void RegisterProcess(BeforeTransactionCompletionProcessDelegate process)
+ {
+ beforeTransactionProcesses.Register(process);
+ }
+
private void ExecuteActions(IList list)
{
int size = list.Count;
@@ -119,17 +131,27 @@
public void Execute(IExecutable executable)
{
- bool lockQueryCache = session.Factory.Settings.IsQueryCacheEnabled;
- if (executable.HasAfterTransactionCompletion() || lockQueryCache)
+ try
{
- executions.Add(executable);
+ executable.Execute();
}
- if (lockQueryCache)
+ finally
{
- session.Factory.UpdateTimestampsCache.PreInvalidate(executable.PropertySpaces);
+ RegisterCleanupActions(executable);
}
- executable.Execute();
}
+
+ private void RegisterCleanupActions(IExecutable executable)
+ {
+ beforeTransactionProcesses.Register(executable.BeforeTransactionCompletionProcess);
+ if (session.Factory.Settings.IsQueryCacheEnabled)
+ {
+ string[] spaces = executable.PropertySpaces;
+ afterTransactionProcesses.AddSpacesToInvalidate(spaces);
+ session.Factory.UpdateTimestampsCache.PreInvalidate(spaces);
+ }
+ afterTransactionProcesses.Register(executable.AfterTransactionCompletionProcess);
+ }
/// <summary>
/// Perform all currently queued entity-insertion actions.
@@ -168,42 +190,23 @@
PrepareActions(collectionCreations);
}
+ /// <summary>
+ /// Execute any registered <see cref="BeforeTransactionCompletionProcessDelegate" />
+ /// </summary>
+ public void BeforeTransactionCompletion()
+ {
+ beforeTransactionProcesses.BeforeTransactionCompletion();
+ }
+
/// <summary>
/// Performs cleanup of any held cache softlocks.
/// </summary>
/// <param name="success">Was the transaction successful.</param>
public void AfterTransactionCompletion(bool success)
{
- bool invalidateQueryCache = session.Factory.Settings.IsQueryCacheEnabled;
- foreach (IExecutable exec in executions)
- {
- try
- {
- try
- {
- exec.AfterTransactionCompletion(success);
- }
- finally
- {
- if (invalidateQueryCache)
- {
- session.Factory.UpdateTimestampsCache.Invalidate(exec.PropertySpaces);
- }
- }
- }
- catch (CacheException ce)
- {
- log.Error("could not release a cache lock", ce);
- // continue loop
- }
- catch (Exception e)
- {
- throw new HibernateException("Exception releasing cache locks", e);
- }
- }
- executions.Clear();
+ afterTransactionProcesses.AfterTransactionCompletion(success);
}
-
+
/// <summary>
/// Check whether the given tables/query-spaces are to be executed against
/// given the currently queued actions.
@@ -212,12 +215,13 @@
/// <returns> True if we contain pending actions against any of the given tables; false otherwise.</returns>
public virtual bool AreTablesToBeUpdated(ISet<string> tables)
{
- return AreTablesToUpdated(updates, tables) ||
- AreTablesToUpdated(insertions, tables) ||
- AreTablesToUpdated(deletions, tables) ||
- AreTablesToUpdated(collectionUpdates, tables) ||
- AreTablesToUpdated(collectionCreations, tables) ||
- AreTablesToUpdated(collectionRemovals, tables);
+ return
+ AreTablesToUpdated(updates, tables)
+ || AreTablesToUpdated(insertions, tables)
+ || AreTablesToUpdated(deletions, tables)
+ || AreTablesToUpdated(collectionUpdates, tables)
+ || AreTablesToUpdated(collectionCreations, tables)
+ || AreTablesToUpdated(collectionRemovals, tables);
}
/// <summary>
@@ -407,13 +411,27 @@
}
}
+ public bool HasBeforeTransactionActions()
+ {
+ return beforeTransactionProcesses.HasActions;
+ }
+
+ public bool HasAfterTransactionActions()
+ {
+ return afterTransactionProcesses.HasActions;
+ }
+
public bool HasAnyQueuedActions
{
get
{
return
- updates.Count > 0 || insertions.Count > 0 || deletions.Count > 0 || collectionUpdates.Count > 0
- || collectionRemovals.Count > 0 || collectionCreations.Count > 0;
+ updates.Count > 0
+ || insertions.Count > 0
+ || deletions.Count > 0
+ || collectionUpdates.Count > 0
+ || collectionRemovals.Count > 0
+ || collectionCreations.Count > 0;
}
}
@@ -435,5 +453,127 @@
.Append(collectionUpdates)
.Append("]").ToString();
}
+
+ [Serializable]
+ private class BeforeTransactionCompletionProcessQueue
+ {
+ private ISessionImplementor session;
+ private IList<BeforeTransactionCompletionProcessDelegate> processes = new List<BeforeTransactionCompletionProcessDelegate>();
+
+ public bool HasActions
+ {
+ get { return processes.Count > 0; }
+ }
+
+ public BeforeTransactionCompletionProcessQueue(ISessionImplementor session)
+ {
+ this.session = session;
+ }
+
+ public void Register(BeforeTransactionCompletionProcessDelegate process)
+ {
+ if (process == null)
+ {
+ return;
+ }
+ processes.Add(process);
+ }
+
+ public void BeforeTransactionCompletion()
+ {
+ int size = processes.Count;
+ for (int i = 0; i < size; i++)
+ {
+ try
+ {
+ BeforeTransactionCompletionProcessDelegate process = processes[i];
+ process();
+ }
+ catch (HibernateException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new AssertionFailure("Unable to perform BeforeTransactionCompletion callback", e);
+ }
+ }
+ processes.Clear();
+ }
+ }
+
+ [Serializable]
+ private class AfterTransactionCompletionProcessQueue
+ {
+ private ISessionImplementor session;
+ private ISet<string> querySpacesToInvalidate = new HashedSet<string>();
+ private IList<AfterTransactionCompletionProcessDelegate> processes = new List<AfterTransactionCompletionProcessDelegate>(InitQueueListSize * 3);
+
+ public bool HasActions
+ {
+ get { return processes.Count > 0; }
+ }
+
+ public AfterTransactionCompletionProcessQueue(ISessionImplementor session)
+ {
+ this.session = session;
+ }
+
+ public void AddSpacesToInvalidate(string[] spaces)
+ {
+ if (spaces == null)
+ {
+ return;
+ }
+ for (int i = 0, max = spaces.Length; i < max; i++)
+ {
+ this.AddSpaceToInvalidate(spaces[i]);
+ }
+ }
+
+ public void AddSpaceToInvalidate(string space)
+ {
+ querySpacesToInvalidate.Add(space);
+ }
+
+ public void Register(AfterTransactionCompletionProcessDelegate process)
+ {
+ if (process == null)
+ {
+ return;
+ }
+ processes.Add(process);
+ }
+
+ public void AfterTransactionCompletion(bool success)
+ {
+ int size = processes.Count;
+
+ for (int i = 0; i < size; i++)
+ {
+ try
+ {
+ AfterTransactionCompletionProcessDelegate process = processes[i];
+ process(success);
+ }
+ catch (CacheException e)
+ {
+ log.Error( "could not release a cache lock", e);
+ // continue loop
+ }
+ catch (Exception e)
+ {
+ throw new AssertionFailure("Exception releasing cache locks", e);
+ }
+ }
+ processes.Clear();
+
+ if (session.Factory.Settings.IsQueryCacheEnabled)
+ {
+ session.Factory.UpdateTimestampsCache.Invalidate(querySpacesToInvalidate.ToArray());
+ }
+ querySpacesToInvalidate.Clear();
+ }
+ }
}
}
Modified: trunk/nhibernate/src/NHibernate/Event/Default/AbstractLockUpgradeEventListener.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Event/Default/AbstractLockUpgradeEventListener.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Event/Default/AbstractLockUpgradeEventListener.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -1,6 +1,7 @@
using System;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NHibernate.Engine;
using NHibernate.Impl;
using NHibernate.Persister.Entity;
Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -2,6 +2,7 @@
using System.Diagnostics;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
using NHibernate.Engine;
using NHibernate.Impl;
Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -2278,6 +2278,7 @@
using (new SessionIdLoggingContext(SessionId))
{
log.Debug("before transaction completion");
+ actionQueue.BeforeTransactionCompletion();
if (rootSession == null)
{
try
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-09-21 15:00:19 UTC (rev 5198)
@@ -72,6 +72,7 @@
<Compile Include="ADOException.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="AssertionFailure.cs" />
+ <Compile Include="Cache\Access\ISoftLock.cs" />
<Compile Include="Cache\CachedItem.cs" />
<Compile Include="Cache\CacheException.cs" />
<Compile Include="Cache\CacheFactory.cs" />
@@ -83,7 +84,6 @@
<Compile Include="Cache\ICacheProvider.cs" />
<Compile Include="Cache\IQueryCache.cs" />
<Compile Include="Cache\IQueryCacheFactory.cs" />
- <Compile Include="Cache\ISoftLock.cs" />
<Compile Include="Cache\NonstrictReadWriteCache.cs" />
<Compile Include="Cache\QueryKey.cs" />
<Compile Include="Cache\ReadOnlyCache.cs" />
@@ -1554,6 +1554,9 @@
<ItemGroup>
<Service Include="{B4F97281-0DBD-4835-9ED8-7DFB966E87FF}" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Cache\Access" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Modified: trunk/nhibernate/src/NHibernate.Test/CacheTest/CacheFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/CacheTest/CacheFixture.cs 2010-09-20 15:13:25 UTC (rev 5197)
+++ trunk/nhibernate/src/NHibernate.Test/CacheTest/CacheFixture.cs 2010-09-21 15:00:19 UTC (rev 5198)
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading;
using NHibernate.Cache;
+using NHibernate.Cache.Access;
using NUnit.Framework;
namespace NHibernate.Test.CacheTest
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|