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:
Renaud Paquay
2010-07-15 13:43:11 -07:00
parent 12b9e87948
commit ea6d5849ec
10 changed files with 107 additions and 66 deletions

View File

@@ -1,18 +1,31 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Autofac;
using NUnit.Framework; using NUnit.Framework;
using Orchard.Caching;
using Orchard.Data;
using Orchard.FileSystems.AppData;
using Orchard.FileSystems.Dependencies; using Orchard.FileSystems.Dependencies;
using Orchard.Services;
using Orchard.Tests.Stubs; using Orchard.Tests.Stubs;
namespace Orchard.Tests.FileSystems.Dependencies { namespace Orchard.Tests.FileSystems.Dependencies {
[TestFixture] [TestFixture]
public class DependenciesFolderTests { 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] [Test]
public void LoadDescriptorsShouldReturnEmptyList() { public void LoadDescriptorsShouldReturnEmptyList() {
var clock = new StubClock(); var dependenciesFolder = BuildContainer().Resolve<IDependenciesFolder>();
var appDataFolder = new StubAppDataFolder(clock);
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
var e = dependenciesFolder.LoadDescriptors(); var e = dependenciesFolder.LoadDescriptors();
Assert.That(e, Is.Empty); Assert.That(e, Is.Empty);
@@ -20,9 +33,7 @@ namespace Orchard.Tests.FileSystems.Dependencies {
[Test] [Test]
public void StoreDescriptorsShouldWork() { public void StoreDescriptorsShouldWork() {
var clock = new StubClock(); var dependenciesFolder = BuildContainer().Resolve<IDependenciesFolder>();
var appDataFolder = new StubAppDataFolder(clock);
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder);
var d = new DependencyDescriptor { var d = new DependencyDescriptor {
Name = "name", Name = "name",
@@ -40,9 +51,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
[Test] [Test]
public void StoreDescriptorsShouldNoOpIfNoChanges() { public void StoreDescriptorsShouldNoOpIfNoChanges() {
var clock = new StubClock(); var container = BuildContainer();
var appDataFolder = new StubAppDataFolder(clock); var clock = (StubClock)container.Resolve<IClock>();
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
var d1 = new DependencyDescriptor { var d1 = new DependencyDescriptor {
Name = "name1", Name = "name1",
@@ -67,9 +79,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
[Test] [Test]
public void StoreDescriptorsShouldStoreIfChanges() { public void StoreDescriptorsShouldStoreIfChanges() {
var clock = new StubClock(); var container = BuildContainer();
var appDataFolder = new StubAppDataFolder(clock); var clock = (StubClock)container.Resolve<IClock>();
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
var d1 = new DependencyDescriptor { var d1 = new DependencyDescriptor {
Name = "name1", Name = "name1",
@@ -96,9 +109,10 @@ namespace Orchard.Tests.FileSystems.Dependencies {
[Test] [Test]
public void LoadDescriptorsShouldWorkAcrossInstances() { public void LoadDescriptorsShouldWorkAcrossInstances() {
var clock = new StubClock(); var container = BuildContainer();
var appDataFolder = new StubAppDataFolder(clock); var clock = (StubClock)container.Resolve<IClock>();
var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); var appDataFolder = (StubAppDataFolder)container.Resolve<IAppDataFolder>();
var dependenciesFolder = container.Resolve<IDependenciesFolder>();
var d1 = new DependencyDescriptor { var d1 = new DependencyDescriptor {
Name = "name1", Name = "name1",
@@ -115,7 +129,8 @@ namespace Orchard.Tests.FileSystems.Dependencies {
dependenciesFolder.StoreDescriptors(new[] { d1, d2 }); dependenciesFolder.StoreDescriptors(new[] { d1, d2 });
// Create a new instance over the same appDataFolder // 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 // Ensure descriptors were persisted properly
var result = dependenciesFolder2.LoadDescriptors(); var result = dependenciesFolder2.LoadDescriptors();

View File

@@ -97,6 +97,10 @@ namespace Orchard.Tests.Stubs {
_fileSystem.CreateDirectoryEntry(path); _fileSystem.CreateDirectoryEntry(path);
} }
public bool DirectoryExists(string path) {
return _fileSystem.GetDirectoryEntry(path) != null;
}
public IVolatileToken WhenPathChanges(string path) { public IVolatileToken WhenPathChanges(string path) {
return _fileSystem.WhenPathChanges(path); return _fileSystem.WhenPathChanges(path);
} }

View File

@@ -0,0 +1,8 @@
using NHibernate.Cfg;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Data {
public interface ISessionConfigurationCache {
Configuration GetConfiguration(ShellBlueprint shellBlueprint);
}
}

View 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");
}
}
}

View File

@@ -1,6 +1,4 @@
using System; using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using NHibernate; using NHibernate;
using NHibernate.Cfg; using NHibernate.Cfg;
using Orchard.Data; using Orchard.Data;
@@ -18,51 +16,6 @@ namespace Orchard.Data {
SessionFactoryParameters GetSessionFactoryParameters(); 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 { public class SessionFactoryHolder : ISessionFactoryHolder {
private readonly ShellSettings _shellSettings; private readonly ShellSettings _shellSettings;
private readonly ShellBlueprint _shellBlueprint; private readonly ShellBlueprint _shellBlueprint;
@@ -127,7 +80,7 @@ namespace Orchard.Data {
.CreateProvider(parameters) .CreateProvider(parameters)
.BuildConfiguration(parameters); .BuildConfiguration(parameters);
_sessionConfigurationCache.StoreConfig(_shellSettings.Name, config); _sessionConfigurationCache.StoreConfiguration(_shellSettings.Name, config);
} }
return config; return config;

View File

@@ -74,7 +74,7 @@ namespace Orchard.Environment.ShellBuilders {
if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber) { if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber) {
Logger.Information("Newer descriptor obtained. Rebuilding shell container."); Logger.Information("Newer descriptor obtained. Rebuilding shell container.");
_sessionConfigurationCache.DeleteConfig(settings.Name); _sessionConfigurationCache.DeleteConfiguration(settings.Name);
_shellDescriptorCache.Store(settings.Name, currentDescriptor); _shellDescriptorCache.Store(settings.Name, currentDescriptor);
blueprint = _compositionStrategy.Compose(settings, currentDescriptor); blueprint = _compositionStrategy.Compose(settings, currentDescriptor);
shellScope = _shellContainerFactory.CreateContainer(settings, blueprint); shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);

View File

@@ -138,6 +138,10 @@ namespace Orchard.FileSystems.AppData {
return File.Exists(CombineToPhysicalPath(path)); return File.Exists(CombineToPhysicalPath(path));
} }
public bool DirectoryExists(string path) {
return Directory.Exists(CombineToPhysicalPath(path));
}
public IEnumerable<string> ListFiles(string path) { public IEnumerable<string> ListFiles(string path) {
var directoryPath = CombineToPhysicalPath(path); var directoryPath = CombineToPhysicalPath(path);
if (!Directory.Exists(directoryPath)) if (!Directory.Exists(directoryPath))

View File

@@ -26,6 +26,7 @@ namespace Orchard.FileSystems.AppData {
DateTime GetFileLastWriteTimeUtc(string path); DateTime GetFileLastWriteTimeUtc(string path);
void CreateDirectory(string path); void CreateDirectory(string path);
bool DirectoryExists(string path);
IVolatileToken WhenPathChanges(string path); IVolatileToken WhenPathChanges(string path);

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.Caching; using Orchard.Caching;
using Orchard.Data;
using Orchard.FileSystems.AppData; using Orchard.FileSystems.AppData;
using Orchard.Localization; using Orchard.Localization;
@@ -12,11 +13,13 @@ namespace Orchard.FileSystems.Dependencies {
private const string FileName = "dependencies.xml"; private const string FileName = "dependencies.xml";
private readonly ICacheManager _cacheManager; private readonly ICacheManager _cacheManager;
private readonly IAppDataFolder _appDataFolder; private readonly IAppDataFolder _appDataFolder;
private readonly ISessionConfigurationCache _sessionConfigurationCache;
private readonly InvalidationToken _writeThroughToken; private readonly InvalidationToken _writeThroughToken;
public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder) { public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder, ISessionConfigurationCache sessionConfigurationCache) {
_cacheManager = cacheManager; _cacheManager = cacheManager;
_appDataFolder = appDataFolder; _appDataFolder = appDataFolder;
_sessionConfigurationCache = sessionConfigurationCache;
_writeThroughToken = new InvalidationToken(); _writeThroughToken = new InvalidationToken();
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
} }
@@ -50,6 +53,7 @@ namespace Orchard.FileSystems.Dependencies {
var existingDescriptors = LoadDescriptors().OrderBy(d => d.Name); var existingDescriptors = LoadDescriptors().OrderBy(d => d.Name);
var newDescriptors = dependencyDescriptors.OrderBy(d => d.Name); var newDescriptors = dependencyDescriptors.OrderBy(d => d.Name);
if (!newDescriptors.SequenceEqual(existingDescriptors, new DependencyDescriptorComparer())) { if (!newDescriptors.SequenceEqual(existingDescriptors, new DependencyDescriptorComparer())) {
_sessionConfigurationCache.DeleteAll();
WriteDependencies(PersistencePath, dependencyDescriptors); WriteDependencies(PersistencePath, dependencyDescriptors);
} }
} }

View File

@@ -360,6 +360,7 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" /> <Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" />
<Compile Include="Data\ISessionConfigurationCache.cs" />
<Compile Include="Data\Migration\Generator\ISchemaCommandGenerator.cs" /> <Compile Include="Data\Migration\Generator\ISchemaCommandGenerator.cs" />
<Compile Include="Data\Migration\Interpreters\AbstractDataMigrationInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\AbstractDataMigrationInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\ICommandInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\ICommandInterpreter.cs" />
@@ -398,6 +399,7 @@
<Compile Include="Data\Providers\DataServiceParameters.cs" /> <Compile Include="Data\Providers\DataServiceParameters.cs" />
<Compile Include="Data\Providers\IDataServicesProvider.cs" /> <Compile Include="Data\Providers\IDataServicesProvider.cs" />
<Compile Include="Data\Providers\SessionFactoryParameters.cs" /> <Compile Include="Data\Providers\SessionFactoryParameters.cs" />
<Compile Include="Data\SessionConfigurationCache.cs" />
<Compile Include="Data\SessionLocator.cs" /> <Compile Include="Data\SessionLocator.cs" />
<Compile Include="Data\IRepository.cs" /> <Compile Include="Data\IRepository.cs" />
<Compile Include="Data\ISessionLocator.cs" /> <Compile Include="Data\ISessionLocator.cs" />