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.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();

View File

@ -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);
}

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.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;

View File

@ -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);

View File

@ -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))

View File

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

View File

@ -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);
}
}

View File

@ -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" />