diff --git a/src/Umbraco.Core/MainDom.cs b/src/Umbraco.Core/MainDom.cs
index fb8ad06999..8e7efc5171 100644
--- a/src/Umbraco.Core/MainDom.cs
+++ b/src/Umbraco.Core/MainDom.cs
@@ -1,18 +1,21 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO.MemoryMappedFiles;
-using System.Text;
using System.Threading;
-using System.Threading.Tasks;
using System.Web.Hosting;
using Umbraco.Core.Logging;
-using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core
{
- // represents the main domain
- class MainDom : IRegisteredObject
+ ///
+ /// Represents the main AppDomain running for a given application.
+ ///
+ ///
+ /// There can be only one "main" AppDomain running for a given application at a time.
+ /// When an AppDomain starts, it tries to acquire the main domain status.
+ /// When an AppDomain stops (eg the application is restarting) it should release the main domain status.
+ /// It is possible to register against the MainDom and be notified when it is released.
+ ///
+ internal class MainDom : IRegisteredObject
{
#region Vars
@@ -34,16 +37,26 @@ namespace Umbraco.Core
private volatile bool _signaled; // we have been signaled
// actions to run before releasing the main domain
- private readonly SortedList _callbacks = new SortedList();
+ private readonly SortedList _callbacks = new SortedList(new WeightComparer());
private const int LockTimeoutMilliseconds = 90000; // (1.5 * 60 * 1000) == 1 min 30 seconds
+ private class WeightComparer : IComparer
+ {
+ public int Compare(int x, int y)
+ {
+ var result = x.CompareTo(y);
+ // return "equal" as "greater than"
+ return result == 0 ? 1 : result;
+ }
+ }
+
#endregion
#region Ctor
// initializes a new instance of MainDom
- public MainDom(ILogger logger)
+ internal MainDom(ILogger logger)
{
_logger = logger;
@@ -52,22 +65,47 @@ namespace Umbraco.Core
if (HostingEnvironment.ApplicationID != null)
appId = HostingEnvironment.ApplicationID.ReplaceNonAlphanumericChars(string.Empty);
- var lockName = "UMBRACO-" + appId + "-MAINDOM-LCK";
+ // combining with the physical path because if running on eg IIS Express,
+ // two sites could have the same appId even though they are different.
+ //
+ // now what could still collide is... two sites, running in two different processes
+ // and having the same appId, and running on the same app physical path
+ //
+ // we *cannot* use the process ID here because when an AppPool restarts it is
+ // a new process for the same application path
+
+ var appPath = HostingEnvironment.ApplicationPhysicalPath;
+ var hash = (appId + ":::" + appPath).ToSHA1();
+
+ var lockName = "UMBRACO-" + hash + "-MAINDOM-LCK";
_asyncLock = new AsyncLock(lockName);
- var eventName = "UMBRACO-" + appId + "-MAINDOM-EVT";
+ var eventName = "UMBRACO-" + hash + "-MAINDOM-EVT";
_signal = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
}
#endregion
- // register a main domain consumer
+ ///
+ /// Registers a resource that requires the current AppDomain to be the main domain to function.
+ ///
+ /// An action to execute before the AppDomain releases the main domain status.
+ /// An optional weight (lower goes first).
+ /// A value indicating whether it was possible to register.
public bool Register(Action release, int weight = 100)
{
return Register(null, release, weight);
}
- // register a main domain consumer
+ ///
+ /// Registers a resource that requires the current AppDomain to be the main domain to function.
+ ///
+ /// An action to execute when registering.
+ /// An action to execute before the AppDomain releases the main domain status.
+ /// An optional weight (lower goes first).
+ /// A value indicating whether it was possible to register.
+ /// If registering is successful, then the action
+ /// is guaranteed to execute before the AppDomain releases the main domain status.
public bool Register(Action install, Action release, int weight = 100)
{
lock (_locko)
@@ -123,7 +161,7 @@ namespace Umbraco.Core
}
// acquires the main domain
- public bool Acquire()
+ internal bool Acquire()
{
lock (_locko) // we don't want the hosting environment to interfere by signaling
{
@@ -174,7 +212,7 @@ namespace Umbraco.Core
}
// IRegisteredObject
- public void Stop(bool immediate)
+ void IRegisteredObject.Stop(bool immediate)
{
try
{