mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Fix dynaic compilation
When a new set of assemblies is enabled, we need to invalidate the nhibernate serialized configuration (since it contains not only types names for records, but also assembly names) --HG-- branch : dev
This commit is contained in:
parent
12b9e87948
commit
ea6d5849ec
@ -1,18 +1,31 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Data;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.FileSystems.Dependencies;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
[TestFixture]
|
||||
public class DependenciesFolderTests {
|
||||
public IContainer BuildContainer() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<StubClock>().As<IClock>().SingleInstance();
|
||||
builder.RegisterType<StubAppDataFolder>().As<IAppDataFolder>().SingleInstance();
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>().SingleInstance();
|
||||
builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>().SingleInstance();
|
||||
builder.RegisterType<DefaultDependenciesFolder>().As<IDependenciesFolder>();
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LoadDescriptorsShouldReturnEmptyList() {
|
||||
var clock = new StubClock();
|
||||
var appDataFolder = new StubAppDataFolder(clock);
|
||||
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var dependenciesFolder = BuildContainer().Resolve<IDependenciesFolder>();
|
||||
|
||||
var e = dependenciesFolder.LoadDescriptors();
|
||||
Assert.That(e, Is.Empty);
|
||||
@ -20,9 +33,7 @@ namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
|
||||
[Test]
|
||||
public void StoreDescriptorsShouldWork() {
|
||||
var clock = new StubClock();
|
||||
var appDataFolder = new StubAppDataFolder(clock);
|
||||
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var dependenciesFolder = BuildContainer().Resolve<IDependenciesFolder>();
|
||||
|
||||
var d = new DependencyDescriptor {
|
||||
Name = "name",
|
||||
@ -40,9 +51,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
|
||||
[Test]
|
||||
public void StoreDescriptorsShouldNoOpIfNoChanges() {
|
||||
var clock = new StubClock();
|
||||
var appDataFolder = new StubAppDataFolder(clock);
|
||||
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var container = BuildContainer();
|
||||
var clock = (StubClock)container.Resolve<IClock>();
|
||||
var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
|
||||
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
|
||||
|
||||
var d1 = new DependencyDescriptor {
|
||||
Name = "name1",
|
||||
@ -67,9 +79,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
|
||||
[Test]
|
||||
public void StoreDescriptorsShouldStoreIfChanges() {
|
||||
var clock = new StubClock();
|
||||
var appDataFolder = new StubAppDataFolder(clock);
|
||||
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var container = BuildContainer();
|
||||
var clock = (StubClock)container.Resolve<IClock>();
|
||||
var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
|
||||
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
|
||||
|
||||
var d1 = new DependencyDescriptor {
|
||||
Name = "name1",
|
||||
@ -96,9 +109,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
|
||||
[Test]
|
||||
public void LoadDescriptorsShouldWorkAcrossInstances() {
|
||||
var clock = new StubClock();
|
||||
var appDataFolder = new StubAppDataFolder(clock);
|
||||
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var container = BuildContainer();
|
||||
var clock = (StubClock)container.Resolve<IClock>();
|
||||
var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
|
||||
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
|
||||
|
||||
var d1 = new DependencyDescriptor {
|
||||
Name = "name1",
|
||||
@ -115,7 +129,8 @@ namespace Orchard.Tests.FileSystems.Dependencies {
|
||||
dependenciesFolder.StoreDescriptors(new[] { d1, d2 });
|
||||
|
||||
// Create a new instance over the same appDataFolder
|
||||
var dependenciesFolder2 = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
|
||||
var dependenciesFolder2 = container.Resolve<IDependenciesFolder>();
|
||||
Assert.That(dependenciesFolder2, Is.Not.SameAs(dependenciesFolder));
|
||||
|
||||
// Ensure descriptors were persisted properly
|
||||
var result = dependenciesFolder2.LoadDescriptors();
|
||||
|
@ -97,6 +97,10 @@ namespace Orchard.Tests.Stubs {
|
||||
_fileSystem.CreateDirectoryEntry(path);
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string path) {
|
||||
return _fileSystem.GetDirectoryEntry(path) != null;
|
||||
}
|
||||
|
||||
public IVolatileToken WhenPathChanges(string path) {
|
||||
return _fileSystem.WhenPathChanges(path);
|
||||
}
|
||||
|
8
src/Orchard/Data/ISessionConfigurationCache.cs
Normal file
8
src/Orchard/Data/ISessionConfigurationCache.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using NHibernate.Cfg;
|
||||
using Orchard.Environment.ShellBuilders.Models;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public interface ISessionConfigurationCache {
|
||||
Configuration GetConfiguration(ShellBlueprint shellBlueprint);
|
||||
}
|
||||
}
|
50
src/Orchard/Data/SessionConfigurationCache.cs
Normal file
50
src/Orchard/Data/SessionConfigurationCache.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using NHibernate.Cfg;
|
||||
using Orchard.FileSystems.AppData;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public class SessionConfigurationCache : ISessionConfigurationCache {
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
public SessionConfigurationCache(IAppDataFolder appDataFolder) {
|
||||
_appDataFolder = appDataFolder;
|
||||
}
|
||||
|
||||
public void StoreConfiguration(string shellName, Configuration config) {
|
||||
var pathName = GetPathName(shellName);
|
||||
|
||||
using (var stream = _appDataFolder.CreateFile(pathName)) {
|
||||
new BinaryFormatter().Serialize(stream, config);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteConfiguration(string shellName) {
|
||||
var pathName = GetPathName(shellName);
|
||||
_appDataFolder.DeleteFile(pathName);
|
||||
}
|
||||
|
||||
public void DeleteAll() {
|
||||
if (!_appDataFolder.DirectoryExists("Sites"))
|
||||
return;
|
||||
|
||||
foreach (var shellName in _appDataFolder.ListDirectories("Sites"))
|
||||
DeleteConfiguration(shellName);
|
||||
}
|
||||
|
||||
public Configuration GetConfiguration(string shellName) {
|
||||
var pathName = GetPathName(shellName);
|
||||
|
||||
if (!_appDataFolder.FileExists(pathName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var stream = _appDataFolder.OpenFile(pathName)) {
|
||||
return new BinaryFormatter().Deserialize(stream) as Configuration;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetPathName(string shellName) {
|
||||
return _appDataFolder.Combine("Sites", shellName, "mappings.bin");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using NHibernate;
|
||||
using NHibernate.Cfg;
|
||||
using Orchard.Data;
|
||||
@ -18,51 +16,6 @@ namespace Orchard.Data {
|
||||
SessionFactoryParameters GetSessionFactoryParameters();
|
||||
}
|
||||
|
||||
public interface ISessionConfigurationCache {
|
||||
void StoreConfig(string shellName, Configuration config);
|
||||
void DeleteConfig(string shellName);
|
||||
Configuration GetConfiguration(string shellName);
|
||||
}
|
||||
|
||||
public class SessionConfigurationCache : ISessionConfigurationCache {
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
public SessionConfigurationCache(IAppDataFolder appDataFolder) {
|
||||
_appDataFolder = appDataFolder;
|
||||
}
|
||||
|
||||
public void StoreConfig(string shellName, Configuration config) {
|
||||
var filename = GetFileName(shellName);
|
||||
|
||||
using ( var stream = File.OpenWrite(filename) ) {
|
||||
new BinaryFormatter().Serialize(stream, config);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteConfig(string shellName) {
|
||||
var filename = GetFileName(shellName);
|
||||
if(File.Exists(filename)) {
|
||||
File.Delete(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public Configuration GetConfiguration(string shellName) {
|
||||
var filename = GetFileName(shellName);
|
||||
|
||||
if (!_appDataFolder.FileExists(filename)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var stream = File.OpenRead(filename)) {
|
||||
return new BinaryFormatter().Deserialize(stream) as Configuration;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFileName(string shellName) {
|
||||
return _appDataFolder.MapPath(_appDataFolder.Combine("Sites", shellName, "mappings.bin"));
|
||||
}
|
||||
}
|
||||
|
||||
public class SessionFactoryHolder : ISessionFactoryHolder {
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly ShellBlueprint _shellBlueprint;
|
||||
@ -127,7 +80,7 @@ namespace Orchard.Data {
|
||||
.CreateProvider(parameters)
|
||||
.BuildConfiguration(parameters);
|
||||
|
||||
_sessionConfigurationCache.StoreConfig(_shellSettings.Name, config);
|
||||
_sessionConfigurationCache.StoreConfiguration(_shellSettings.Name, config);
|
||||
}
|
||||
|
||||
return config;
|
||||
|
@ -74,7 +74,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber) {
|
||||
Logger.Information("Newer descriptor obtained. Rebuilding shell container.");
|
||||
|
||||
_sessionConfigurationCache.DeleteConfig(settings.Name);
|
||||
_sessionConfigurationCache.DeleteConfiguration(settings.Name);
|
||||
_shellDescriptorCache.Store(settings.Name, currentDescriptor);
|
||||
blueprint = _compositionStrategy.Compose(settings, currentDescriptor);
|
||||
shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);
|
||||
|
@ -138,6 +138,10 @@ namespace Orchard.FileSystems.AppData {
|
||||
return File.Exists(CombineToPhysicalPath(path));
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string path) {
|
||||
return Directory.Exists(CombineToPhysicalPath(path));
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListFiles(string path) {
|
||||
var directoryPath = CombineToPhysicalPath(path);
|
||||
if (!Directory.Exists(directoryPath))
|
||||
|
@ -26,6 +26,7 @@ namespace Orchard.FileSystems.AppData {
|
||||
DateTime GetFileLastWriteTimeUtc(string path);
|
||||
|
||||
void CreateDirectory(string path);
|
||||
bool DirectoryExists(string path);
|
||||
|
||||
IVolatileToken WhenPathChanges(string path);
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Data;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.Localization;
|
||||
|
||||
@ -12,11 +13,13 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
private const string FileName = "dependencies.xml";
|
||||
private readonly ICacheManager _cacheManager;
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
private readonly ISessionConfigurationCache _sessionConfigurationCache;
|
||||
private readonly InvalidationToken _writeThroughToken;
|
||||
|
||||
public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder) {
|
||||
public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder, ISessionConfigurationCache sessionConfigurationCache) {
|
||||
_cacheManager = cacheManager;
|
||||
_appDataFolder = appDataFolder;
|
||||
_sessionConfigurationCache = sessionConfigurationCache;
|
||||
_writeThroughToken = new InvalidationToken();
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@ -50,6 +53,7 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
var existingDescriptors = LoadDescriptors().OrderBy(d => d.Name);
|
||||
var newDescriptors = dependencyDescriptors.OrderBy(d => d.Name);
|
||||
if (!newDescriptors.SequenceEqual(existingDescriptors, new DependencyDescriptorComparer())) {
|
||||
_sessionConfigurationCache.DeleteAll();
|
||||
WriteDependencies(PersistencePath, dependencyDescriptors);
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +360,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" />
|
||||
<Compile Include="Data\ISessionConfigurationCache.cs" />
|
||||
<Compile Include="Data\Migration\Generator\ISchemaCommandGenerator.cs" />
|
||||
<Compile Include="Data\Migration\Interpreters\AbstractDataMigrationInterpreter.cs" />
|
||||
<Compile Include="Data\Migration\Interpreters\ICommandInterpreter.cs" />
|
||||
@ -398,6 +399,7 @@
|
||||
<Compile Include="Data\Providers\DataServiceParameters.cs" />
|
||||
<Compile Include="Data\Providers\IDataServicesProvider.cs" />
|
||||
<Compile Include="Data\Providers\SessionFactoryParameters.cs" />
|
||||
<Compile Include="Data\SessionConfigurationCache.cs" />
|
||||
<Compile Include="Data\SessionLocator.cs" />
|
||||
<Compile Include="Data\IRepository.cs" />
|
||||
<Compile Include="Data\ISessionLocator.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user