diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Models/WorkflowDefinitionRecord.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Models/WorkflowDefinitionRecord.cs index ab585ca4d..ebb7ec26d 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Models/WorkflowDefinitionRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Models/WorkflowDefinitionRecord.cs @@ -43,7 +43,7 @@ namespace Orchard.Workflows.Models { /// /// List of associated with this workflow definition. /// - [CascadeAllDeleteOrphan, Aggregate] + [CascadeAllDeleteOrphan] public virtual IList WorkflowRecords { get; set; } } } \ No newline at end of file diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index ceafd25af..f7587a841 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -11,7 +11,6 @@ using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.Localization; using Orchard.Logging; -using Orchard.Utility.Extensions; namespace Orchard.Environment { public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler { @@ -23,7 +22,7 @@ namespace Orchard.Environment { private readonly IExtensionLoaderCoordinator _extensionLoaderCoordinator; private readonly IExtensionMonitoringCoordinator _extensionMonitoringCoordinator; private readonly ICacheManager _cacheManager; - private readonly object _syncLock = new object(); + private readonly static object _syncLock = new object(); private IEnumerable _shellContexts; private IEnumerable _tenantsToRestart; @@ -54,13 +53,8 @@ namespace Orchard.Environment { public Localizer T { get; set; } public ILogger Logger { get; set; } - public IList Current { - get { return BuildCurrent().ToReadOnlyCollection(); } - } - public ShellContext GetShellContext(ShellSettings shellSettings) { - return Current - .Single(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name)); + return BuildCurrent().SingleOrDefault(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name)); } void IOrchardHost.Initialize() { @@ -112,7 +106,7 @@ namespace Orchard.Environment { void StartUpdatedShells() { lock (_syncLock) { if (_tenantsToRestart.Any()) { - foreach (var settings in _tenantsToRestart.Distinct().ToList()) { + foreach (var settings in _tenantsToRestart.ToList()) { ActivateShell(settings); } @@ -155,7 +149,11 @@ namespace Orchard.Environment { Logger.Debug("Activating context for tenant {0}", context.Settings.Name); context.Shell.Activate(); - _shellContexts = (_shellContexts ?? Enumerable.Empty()).Union(new [] {context}); + _shellContexts = (_shellContexts ?? Enumerable.Empty()) + .Where(c => c.Settings.Name != context.Settings.Name) + .Concat(new[] { context }) + .ToArray(); + _runningShellTable.Add(context.Settings); } @@ -199,9 +197,13 @@ namespace Orchard.Environment { Logger.Information("Disposing active shell contexts"); if (_shellContexts != null) { - foreach (var shellContext in _shellContexts) { - shellContext.Shell.Terminate(); - shellContext.LifetimeScope.Dispose(); + lock (_syncLock) { + if (_shellContexts != null) { + foreach (var shellContext in _shellContexts) { + shellContext.Shell.Terminate(); + shellContext.LifetimeScope.Dispose(); + } + } } _shellContexts = null; } @@ -232,7 +234,9 @@ namespace Orchard.Environment { // if a tenant has been altered, and is not invalid, reload it if (settings.State != TenantState.Invalid) { - _tenantsToRestart = _tenantsToRestart.Where(x => x.Name != settings.Name).Union(new[] { settings }); + _tenantsToRestart = _tenantsToRestart + .Where(x => x.Name != settings.Name) + .Concat(new[] { settings }); } } } @@ -284,12 +288,14 @@ namespace Orchard.Environment { context = _shellContexts.First(x => x.Settings.Name == tenant); } - // don't update the settings themselves here + // don't flag the tenant if already listed if(_tenantsToRestart.Any(x => x.Name == tenant)) { return; } - _tenantsToRestart = _tenantsToRestart.Union(new[] { context.Settings }); + _tenantsToRestart = _tenantsToRestart + .Concat(new[] { context.Settings }) + .ToArray(); } } } diff --git a/src/Orchard/Environment/RunningShellTable.cs b/src/Orchard/Environment/RunningShellTable.cs index c0700a392..7713543a4 100644 --- a/src/Orchard/Environment/RunningShellTable.cs +++ b/src/Orchard/Environment/RunningShellTable.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Web; using Orchard.Environment.Configuration; @@ -17,34 +18,53 @@ namespace Orchard.Environment { private IEnumerable _shells = Enumerable.Empty(); private IEnumerable> _shellsByHost = Enumerable.Empty().GroupBy(x => default(string)); private ShellSettings _fallback; + private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); public void Add(ShellSettings settings) { - _shells = _shells - .Where(s => s.Name != settings.Name) - .Concat(new[] { settings }) - .ToArray(); + _lock.EnterWriteLock(); + try { + _shells = _shells + .Where(s => s.Name != settings.Name) + .Concat(new[] {settings}) + .ToArray(); - Organize(); + Organize(); + } + finally { + _lock.ExitWriteLock(); + } } public void Remove(ShellSettings settings) { - _shells = _shells - .Where(s => s.Name != settings.Name) - .ToArray(); + _lock.EnterWriteLock(); + try { + _shells = _shells + .Where(s => s.Name != settings.Name) + .ToArray(); - Organize(); + Organize(); + } + finally { + _lock.ExitWriteLock(); + } } public void Update(ShellSettings settings) { - _shells = _shells - .Where(s => s.Name != settings.Name) - .ToArray(); + _lock.EnterWriteLock(); + try { + _shells = _shells + .Where(s => s.Name != settings.Name) + .ToArray(); - _shells = _shells - .Concat(new[] { settings }) - .ToArray(); + _shells = _shells + .Concat(new[] {settings}) + .ToArray(); - Organize(); + Organize(); + } + finally { + _lock.ExitWriteLock(); + } } private void Organize() { @@ -86,19 +106,21 @@ namespace Orchard.Environment { } public ShellSettings Match(string host, string appRelativePath) { - // optimized path when only one tenant (Default) - if (!_shellsByHost.Any()) { - return _fallback; - } + _lock.EnterReadLock(); + try { + // optimized path when only one tenant (Default), configured with no custom host + if (!_shellsByHost.Any() && _fallback != null) { + return _fallback; + } - var hostLength = host.IndexOf(':'); - if (hostLength != -1) - host = host.Substring(0, hostLength); + var hostLength = host.IndexOf(':'); + if (hostLength != -1) + host = host.Substring(0, hostLength); - var mostQualifiedMatch = _shellsByHost - .Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase)) - .SelectMany(group => group - .OrderByDescending(settings => (settings.RequestUrlPrefix ?? string.Empty).Length)) + var mostQualifiedMatch = _shellsByHost + .Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase)) + .SelectMany(group => group + .OrderByDescending(settings => (settings.RequestUrlPrefix ?? string.Empty).Length)) .FirstOrDefault(settings => { if (settings.State == TenantState.Disabled) { return false; @@ -112,7 +134,11 @@ namespace Orchard.Environment { || appRelativePath.Equals("~/" + settings.RequestUrlPrefix, StringComparison.OrdinalIgnoreCase); }); - return mostQualifiedMatch ?? _fallback; + return mostQualifiedMatch ?? _fallback; + } + finally { + _lock.ExitReadLock(); + } } } }