Fixing feature enabling and adding ContextState

This commit is contained in:
Sebastien Ros
2013-11-20 15:54:19 -08:00
parent 5193ba7b0c
commit 372579d9c8
5 changed files with 88 additions and 31 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Security.Cryptography;
using Orchard.Caching;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
@@ -13,6 +14,7 @@ using Orchard.Logging;
using Orchard.Utility.Extensions;
namespace Orchard.Environment {
// All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
private readonly IHostLocalRestart _hostLocalRestart;
private readonly IShellSettingsManager _shellSettingsManager;
@@ -25,10 +27,8 @@ namespace Orchard.Environment {
private readonly static object _syncLock = new object();
private IEnumerable<ShellContext> _shellContexts;
[ThreadStatic]
private static IList<ShellSettings> _tenantsToRestart;
private readonly ContextState<IList<ShellSettings>> _tenantsToRestart;
public DefaultOrchardHost(
IShellSettingsManager shellSettingsManager,
IShellContextFactory shellContextFactory,
@@ -47,6 +47,8 @@ namespace Orchard.Environment {
_cacheManager = cacheManager;
_hostLocalRestart = hostLocalRestart;
_tenantsToRestart = new ContextState<IList<ShellSettings>>("DefaultOrchardHost.TenantsToRestart", () => new List<ShellSettings>());
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
}
@@ -109,9 +111,9 @@ namespace Orchard.Environment {
}
void StartUpdatedShells() {
while (_tenantsToRestart != null && _tenantsToRestart.Any()) {
var settings = _tenantsToRestart.First();
_tenantsToRestart.Remove(settings);
while (_tenantsToRestart.GetState().Any()) {
var settings = _tenantsToRestart.GetState().First();
_tenantsToRestart.GetState().Remove(settings);
Logger.Debug("Updating shell: " + settings.Name);
lock (_syncLock) {
ActivateShell(settings);
@@ -244,11 +246,9 @@ namespace Orchard.Environment {
// if a tenant has been created
if (settings.State != TenantState.Invalid) {
_tenantsToRestart = _tenantsToRestart ?? new List<ShellSettings>();
if (!_tenantsToRestart.Any(t => t.Name.Equals(settings.Name))) {
if (!_tenantsToRestart.GetState().Any(t => t.Name.Equals(settings.Name))) {
Logger.Debug("Adding tenant to restart: " + settings.Name + " " + settings.State);
_tenantsToRestart.Add(settings);
_tenantsToRestart.GetState().Add(settings);
}
}
}
@@ -291,7 +291,7 @@ namespace Orchard.Environment {
if (_shellContexts == null) {
return;
}
Logger.Debug("Shell changed: " + tenant);
var context = _shellContexts.FirstOrDefault(x => x.Settings.Name == tenant);
@@ -300,13 +300,18 @@ namespace Orchard.Environment {
return;
}
// don't restart when tenant is in setup
if (context.Settings.State != TenantState.Running) {
return;
}
// don't flag the tenant if already listed
if (_tenantsToRestart.Any(x => x.Name == tenant)) {
if (_tenantsToRestart.GetState().Any(x => x.Name == tenant)) {
return;
}
Logger.Debug("Adding tenant to restart: " + tenant);
_tenantsToRestart.Add(context.Settings);
_tenantsToRestart.GetState().Add(context.Settings);
}
}
}

View File

@@ -77,7 +77,10 @@ namespace Orchard.Environment {
RegisterVolatileProvider<DefaultVirtualPathProvider, IVirtualPathProvider>(builder);
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().As<IEventHandler>().Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name).SingleInstance();
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().As<IEventHandler>()
.Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name)
.Named<IEventHandler>(typeof(IShellDescriptorManagerEventHandler).Name)
.SingleInstance();
{
builder.RegisterType<ShellSettingsManager>().As<IShellSettingsManager>().SingleInstance();

View File

@@ -0,0 +1,56 @@
using System;
using System.Runtime.Remoting.Messaging;
using System.Web;
namespace Orchard.Environment.State {
/// <summary>
/// Holds some state for the current HttpContext or thread
/// </summary>
/// <typeparam name="T">The type of data to store</typeparam>
public class ContextState<T> where T : class {
private readonly string _name;
private readonly Func<T> _defaultValue;
public ContextState(string name) {
_name = name;
}
public ContextState(string name, Func<T> defaultValue) {
_name = name;
_defaultValue = defaultValue;
}
public T GetState() {
if (HttpContext.Current == null) {
var data = CallContext.GetData(_name);
if (data == null) {
if (_defaultValue != null) {
CallContext.SetData(_name, data = _defaultValue());
return data as T;
}
}
return data as T;
}
if (HttpContext.Current.Items[_name] == null) {
HttpContext.Current.Items[_name] = _defaultValue == null ? null : _defaultValue();
}
return HttpContext.Current.Items[_name] as T;
}
public void SetState(T state) {
if (HttpContext.Current == null) {
CallContext.SetData(_name, state);
}
else {
HttpContext.Current.Items[_name] = state;
}
}
}
}

View File

@@ -13,15 +13,16 @@ namespace Orchard.Environment.State {
private readonly IShellContextFactory _shellContextFactory;
private readonly Func<IOrchardHost> _orchardHost;
[ThreadStatic] private static IList<Entry> _entries;
private readonly ContextState<IList<Entry>> _entries;
public DefaultProcessingEngine(IShellContextFactory shellContextFactory, Func<IOrchardHost> orchardHost) {
_shellContextFactory = shellContextFactory;
_orchardHost = orchardHost;
_entries = new ContextState<IList<Entry>>("DefaultProcessingEngine.Entries", () => new List<Entry>());
}
public string AddTask(ShellSettings shellSettings, ShellDescriptor shellDescriptor, string eventName, Dictionary<string, object> parameters) {
EnsureEntries();
var entry = new Entry {
ShellSettings = shellSettings,
@@ -35,7 +36,7 @@ namespace Orchard.Environment.State {
eventName,
entry.ProcessId,
shellSettings.Name);
_entries.Add(entry);
_entries.GetState().Add(entry);
return entry.ProcessId;
}
@@ -52,28 +53,19 @@ namespace Orchard.Environment.State {
public bool AreTasksPending() {
return EnsureEntries().Any();
return _entries.GetState().Any();
}
public void ExecuteNextTask() {
EnsureEntries();
Entry entry;
if (!_entries.Any())
if (!_entries.GetState().Any())
return;
entry = _entries.First();
_entries.Remove(entry);
entry = _entries.GetState().First();
_entries.GetState().Remove(entry);
Execute(entry);
}
private IList<Entry> EnsureEntries() {
if (_entries == null) {
_entries = new List<Entry>();
}
return _entries;
}
private void Execute(Entry entry) {
// Force reloading extensions if there were extensions installed
// See http://orchard.codeplex.com/workitem/17465

View File

@@ -238,6 +238,7 @@
<Compile Include="Environment\Extensions\ICriticalErrorProvider.cs" />
<Compile Include="Environment\IOrchardFrameworkAssemblies.cs" />
<Compile Include="Environment\IWorkContextEvents.cs" />
<Compile Include="Environment\State\ContextState.cs" />
<Compile Include="Environment\ViewsBackgroundCompilation.cs" />
<Compile Include="Environment\Warmup\WarmupUtility.cs" />
<Compile Include="Environment\WorkContextImplementation.cs" />