diff --git a/src/Umbraco.Core/ApplicationEventHandler.cs b/src/Umbraco.Core/ApplicationEventHandler.cs index a725a08a8e..8d97baac95 100644 --- a/src/Umbraco.Core/ApplicationEventHandler.cs +++ b/src/Umbraco.Core/ApplicationEventHandler.cs @@ -74,7 +74,7 @@ namespace Umbraco.Core /// private bool ShouldExecute(ApplicationContext applicationContext) { - if (applicationContext.IsConfigured && applicationContext.DatabaseContext.CanConnect) + if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured) { return true; } @@ -84,7 +84,7 @@ namespace Umbraco.Core return true; } - if (!applicationContext.DatabaseContext.CanConnect && ExecuteWhenDatabaseNotConfigured) + if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured) { return true; } diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index f5dbdcf957..c5d3e2a4c7 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Web; using AutoMapper; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.Mapping; @@ -261,6 +263,9 @@ namespace Umbraco.Core FreezeResolution(); + //Here we need to make sure the db can be connected to + EnsureDatabaseConnection(); + using (DisposableTimer.DebugDuration( () => string.Format("Executing {0} IApplicationEventHandler.OnApplicationStarted", ApplicationEventsResolver.Current.ApplicationEventHandlers.Count()), () => "Finished executing IApplicationEventHandler.OnApplicationStarted")) @@ -299,6 +304,32 @@ namespace Umbraco.Core return this; } + /// + /// We cannot continue if the db cannot be connected to + /// + private void EnsureDatabaseConnection() + { + if (ApplicationContext.IsConfigured == false) return; + if (ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) return; + + var currentTry = 0; + while (currentTry < 5) + { + if (ApplicationContext.DatabaseContext.CanConnect) + break; + + //wait and retry + Thread.Sleep(1000); + currentTry++; + } + + if (currentTry == 5) + { + throw new UmbracoStartupFailedException("Umbraco cannot start. A connection string is configured but the Umbraco cannot connect to the database."); + } + + } + /// /// Freeze resolution to not allow Resolvers to be modified /// diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index fad96b849d..dfaebb0315 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -26,8 +26,6 @@ namespace Umbraco.Core { private readonly IDatabaseFactory _factory; private bool _configured; - private bool _canConnect; - private volatile bool _connectCheck = false; private readonly object _locker = new object(); private string _connectionString; private string _providerName; @@ -67,21 +65,9 @@ namespace Umbraco.Core get { if (IsDatabaseConfigured == false) return false; - - //double check lock so that it is only checked once and is fast - if (_connectCheck == false) - { - lock (_locker) - { - if (_canConnect == false) - { - _canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider); - _connectCheck = true; - } - } - } - - return _canConnect; + var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider); + LogHelper.Info("CanConnect = " + canConnect); + return canConnect; } } diff --git a/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs b/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs new file mode 100644 index 0000000000..d27d38de9a --- /dev/null +++ b/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs @@ -0,0 +1,18 @@ +using System; + +namespace Umbraco.Core.Exceptions +{ + /// + /// An exception that is thrown if the umbraco application cannnot boot + /// + public class UmbracoStartupFailedException : Exception + { + /// + /// Initializes a new instance of the class with a specified error message. + /// + /// The message that describes the error. + public UmbracoStartupFailedException(string message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs index 962f0e3d91..abaf5ae5e0 100644 --- a/src/Umbraco.Core/TypeFinder.cs +++ b/src/Umbraco.Core/TypeFinder.cs @@ -700,7 +700,11 @@ namespace Umbraco.Core #endregion - public static Type GetTypeByName(string typeName) + //TODO: This isn't very elegant, and will have issues since the AppDomain.CurrentDomain + // doesn't actualy load in all assemblies, only the types that have been referenced so far. + // However, in a web context, the BuildManager will have executed which will force all assemblies + // to be loaded so it's fine for now. + internal static Type GetTypeByName(string typeName) { var type = Type.GetType(typeName); if (type != null) return type; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 67ce55b8f1..4e155e1b3d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -312,6 +312,7 @@ +