From 53b96f32482f2393da0b4de0036f28cd99ad2f23 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Mon, 15 Feb 2010 12:06:05 -0800 Subject: [PATCH] Snapshot of incremental work Sequence of events during setup functions at this point Committing this point prior to cleaning up changes to ensure a working arrangement isn't lost --HG-- branch : dev --- ...anagerTests.cs => DatabaseManagerTests.cs} | 53 +++++++--------- src/Orchard.Tests/DataUtility.cs | 2 +- src/Orchard.Tests/Orchard.Tests.csproj | 2 +- src/Orchard.Web/Global.asax.cs | 11 +++- .../Controllers/SetupController.cs | 4 +- .../Data/Migrations/DatabaseManager.cs | 8 +-- .../Migrations/SQLiteSessionFactoryBuilder.cs | 4 +- .../SqlServerSessionFactoryBuilder.cs | 4 +- src/Orchard/Data/SessionFactoryHolder.cs | 13 +++- src/Orchard/Data/SessionLocator.cs | 14 ++++- src/Orchard/Environment/DefaultOrchardHost.cs | 63 ++++++++++++------- src/Orchard/Environment/IOrchardHost.cs | 15 +++-- .../SafeModeShellContainerFactory.cs | 2 +- src/Orchard/Orchard.csproj | 12 ++-- 14 files changed, 121 insertions(+), 86 deletions(-) rename src/Orchard.Tests/Data/Migrations/{DatabaseMigrationManagerTests.cs => DatabaseManagerTests.cs} (62%) diff --git a/src/Orchard.Tests/Data/Migrations/DatabaseMigrationManagerTests.cs b/src/Orchard.Tests/Data/Migrations/DatabaseManagerTests.cs similarity index 62% rename from src/Orchard.Tests/Data/Migrations/DatabaseMigrationManagerTests.cs rename to src/Orchard.Tests/Data/Migrations/DatabaseManagerTests.cs index 760012851..2e1207841 100644 --- a/src/Orchard.Tests/Data/Migrations/DatabaseMigrationManagerTests.cs +++ b/src/Orchard.Tests/Data/Migrations/DatabaseManagerTests.cs @@ -1,7 +1,5 @@ -using System; -using System.Data.SqlClient; +using System.Data.SqlClient; using System.IO; -using System.Threading; using NUnit.Framework; using Orchard.Data.Migrations; using Orchard.Environment; @@ -9,7 +7,7 @@ using Orchard.Tests.Records; namespace Orchard.Tests.Data.Migrations { [TestFixture] - public class DatabaseMigrationManagerTests { + public class DatabaseManagerTests { private string _tempDataFolder; [SetUp] @@ -45,41 +43,28 @@ namespace Orchard.Tests.Data.Migrations { } } - [Test] - public void MigrationManagerShouldCreateEmptySQLiteDatabaseAtGivenLocation() { - var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager(); - var coordinator = manager.CreateCoordinator("SQLite", _tempDataFolder, ""); - - coordinator.CreateDatabase(); - - Assert.That(File.Exists(Path.Combine(_tempDataFolder, "Orchard.db")), Is.True); - } - - [Test, ExpectedException(typeof(NotImplementedException))] - public void MigrationManagerShouldNotImplementTheCreationOfSqlServer() { - var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager(); - var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, ""); - - coordinator.CreateDatabase(); - - } [Test] public void SQLiteSchemaShouldBeGeneratedAndUsable() { - var manager = (IDatabaseMigrationManager) new DatabaseMigrationManager(); - var coordinator = manager.CreateCoordinator("SQLite", _tempDataFolder, ""); + var manager = (IDatabaseManager)new DatabaseManager(); + var coordinator = manager.CreateCoordinator(new DatabaseParameters { + Provider = "SQLite", + DataFolder = _tempDataFolder + }); var recordDescriptors = new[] { new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)} }; - coordinator.UpdateSchema(recordDescriptors); + var sessionFactory = coordinator.BuildSessionFactory(new SessionFactoryBuilderParameters { + UpdateSchema = true, + RecordDescriptors = recordDescriptors + }); - var sessionFactory = coordinator.BuildSessionFactory(recordDescriptors); var session = sessionFactory.OpenSession(); - var foo = new Foo {Name = "hi there"}; + var foo = new Foo { Name = "hi there" }; session.Save(foo); session.Flush(); session.Close(); @@ -95,16 +80,22 @@ namespace Orchard.Tests.Data.Migrations { var databasePath = Path.Combine(_tempDataFolder, "Orchard.mdf"); CreateSqlServerDatabase(databasePath); - var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager(); - var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;"); + var manager = (IDatabaseManager)new DatabaseManager(); + var coordinator = manager.CreateCoordinator(new DatabaseParameters { + Provider = "SQLite", + DataFolder = _tempDataFolder, + ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;", + }); var recordDescriptors = new[] { new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)} }; - coordinator.UpdateSchema(recordDescriptors); - var sessionFactory = coordinator.BuildSessionFactory(recordDescriptors); + var sessionFactory = coordinator.BuildSessionFactory(new SessionFactoryBuilderParameters { + UpdateSchema = true, + RecordDescriptors = recordDescriptors + }); var session = sessionFactory.OpenSession(); var foo = new Foo { Name = "hi there" }; diff --git a/src/Orchard.Tests/DataUtility.cs b/src/Orchard.Tests/DataUtility.cs index fabace2ff..d512be4b5 100644 --- a/src/Orchard.Tests/DataUtility.cs +++ b/src/Orchard.Tests/DataUtility.cs @@ -19,7 +19,7 @@ namespace Orchard.Tests { //var persistenceModel = AutoMap.Source(new Types(types)) // .Alterations(alt => AddAlterations(alt, types)) // .Conventions.AddFromAssemblyOf(); - var persistenceModel = DatabaseCoordinatorBase.CreatePersistenceModel(types.Select(t => new RecordDescriptor { Prefix = "Test", Type = t })); + var persistenceModel = AbstractSessionFactoryBuilder.CreatePersistenceModel(types.Select(t => new RecordDescriptor { Prefix = "Test", Type = t })); return Fluently.Configure() .Database(SQLiteConfiguration.Standard.UsingFile(fileName).ShowSql()) diff --git a/src/Orchard.Tests/Orchard.Tests.csproj b/src/Orchard.Tests/Orchard.Tests.csproj index 7f1120125..b17aec404 100644 --- a/src/Orchard.Tests/Orchard.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Tests.csproj @@ -135,7 +135,7 @@ Code - + diff --git a/src/Orchard.Web/Global.asax.cs b/src/Orchard.Web/Global.asax.cs index 52122471f..5e1cafc01 100644 --- a/src/Orchard.Web/Global.asax.cs +++ b/src/Orchard.Web/Global.asax.cs @@ -36,6 +36,14 @@ namespace Orchard.Web { //TODO: what's the failed initialization story - IoC failure in app start can leave you with a zombie appdomain } + protected void Application_BeginRequest() { + _host.BeginRequest(); + } + + protected void Application_EndRequest() { + _host.EndRequest(); + } + private void CheckMvcVersion(Version requiredVersion) { Assembly loadedMvcAssembly = typeof(System.Web.Mvc.Controller).Assembly; Version loadedMvcVersion = ReadAssemblyFileVersion(loadedMvcAssembly); @@ -81,9 +89,6 @@ namespace Orchard.Web { return new Version(attribute.Version); } - protected void Application_EndRequest() { - _host.EndRequest(); - } protected void MvcSingletons(ContainerBuilder builder) { builder.Register(ControllerBuilder.Current); diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs index 481f031a3..5883da4d3 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs @@ -82,7 +82,7 @@ namespace Orchard.Setup.Controllers { String.Empty, String.Empty, String.Empty, true)); - /* + // set site name and settings var siteService = finiteEnvironment.Resolve(); var siteSettings = siteService.GetSiteSettings().As(); @@ -105,7 +105,7 @@ namespace Orchard.Setup.Controllers { var authenticationService = finiteEnvironment.Resolve(); authenticationService.SignIn(user, true); - */ + } catch { finiteEnvironment.Resolve().Cancel(); diff --git a/src/Orchard/Data/Migrations/DatabaseManager.cs b/src/Orchard/Data/Migrations/DatabaseManager.cs index 054a7a5a2..d7426fd79 100644 --- a/src/Orchard/Data/Migrations/DatabaseManager.cs +++ b/src/Orchard/Data/Migrations/DatabaseManager.cs @@ -2,10 +2,10 @@ namespace Orchard.Data.Migrations { public class DatabaseManager : IDatabaseManager { - public ISessionFactoryBuilder CreateCoordinator(string provider, string dataFolder, string connectionString) { - if (string.Equals(provider, "SQLite", StringComparison.InvariantCultureIgnoreCase)) - return new SQLiteSessionFactoryBuilder(dataFolder, connectionString); - return new SqlServerSessionFactoryBuilder(dataFolder, connectionString); + public ISessionFactoryBuilder CreateCoordinator(DatabaseParameters databaseParameters) { + if (string.Equals(databaseParameters.Provider, "SQLite", StringComparison.InvariantCultureIgnoreCase)) + return new SQLiteSessionFactoryBuilder(databaseParameters.DataFolder, databaseParameters.ConnectionString); + return new SqlServerSessionFactoryBuilder(databaseParameters.DataFolder, databaseParameters.ConnectionString); } } } diff --git a/src/Orchard/Data/Migrations/SQLiteSessionFactoryBuilder.cs b/src/Orchard/Data/Migrations/SQLiteSessionFactoryBuilder.cs index 955552c95..0c6b38461 100644 --- a/src/Orchard/Data/Migrations/SQLiteSessionFactoryBuilder.cs +++ b/src/Orchard/Data/Migrations/SQLiteSessionFactoryBuilder.cs @@ -2,11 +2,11 @@ using System.IO; using FluentNHibernate.Cfg.Db; namespace Orchard.Data.Migrations { - public class SQLiteDatabaseCoordinator : DatabaseCoordinatorBase { + public class SQLiteSessionFactoryBuilder : AbstractSessionFactoryBuilder { private readonly string _dataFolder; private readonly string _connectionString; - public SQLiteDatabaseCoordinator(string dataFolder, string connectionString) { + public SQLiteSessionFactoryBuilder(string dataFolder, string connectionString) { _dataFolder = dataFolder; _connectionString = connectionString; } diff --git a/src/Orchard/Data/Migrations/SqlServerSessionFactoryBuilder.cs b/src/Orchard/Data/Migrations/SqlServerSessionFactoryBuilder.cs index 0df8cb0bd..71382b182 100644 --- a/src/Orchard/Data/Migrations/SqlServerSessionFactoryBuilder.cs +++ b/src/Orchard/Data/Migrations/SqlServerSessionFactoryBuilder.cs @@ -2,11 +2,11 @@ using System; using FluentNHibernate.Cfg.Db; namespace Orchard.Data.Migrations { - public class SqlServerDatabaseCoordinator : DatabaseCoordinatorBase { + public class SqlServerSessionFactoryBuilder : AbstractSessionFactoryBuilder { private readonly string _dataFolder; private readonly string _connectionString; - public SqlServerDatabaseCoordinator(string dataFolder, string connectionString) { + public SqlServerSessionFactoryBuilder(string dataFolder, string connectionString) { _dataFolder = dataFolder; _connectionString = connectionString; } diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index f17edc549..f02b1c39c 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -4,6 +4,7 @@ using NHibernate; using Orchard.Data.Migrations; using Orchard.Environment; using Orchard.Environment.Configuration; +using Orchard.Logging; namespace Orchard.Data { public interface ISessionFactoryHolder : ISingletonDependency { @@ -28,14 +29,19 @@ namespace Orchard.Data { _compositionStrategy = compositionStrategy; _databaseManager = databaseManager; _appDataFolder = appDataFolder; + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } public void UpdateSchema() { lock (this) { - if (_sessionFactory == null) { - _sessionFactory = BuildSessionFactory(true); + if (_sessionFactory != null) { + Logger.Error("UpdateSchema can not be called after a session factory was created"); + throw new OrchardException("UpdateSchema can not be called after a session factory was created"); } + + _sessionFactory = BuildSessionFactory(true); } } @@ -49,8 +55,9 @@ namespace Orchard.Data { } private ISessionFactory BuildSessionFactory(bool updateSchema) { - var shellPath = _appDataFolder.CreateDirectory(Path.Combine("Sites", _shellSettings.Name)); + Logger.Debug("Building session factory"); + var shellPath = _appDataFolder.CreateDirectory(Path.Combine("Sites", _shellSettings.Name)); var coordinator = _databaseManager.CreateCoordinator(new DatabaseParameters { Provider = _shellSettings.DataProvider, diff --git a/src/Orchard/Data/SessionLocator.cs b/src/Orchard/Data/SessionLocator.cs index c74667152..dc0d37cb2 100644 --- a/src/Orchard/Data/SessionLocator.cs +++ b/src/Orchard/Data/SessionLocator.cs @@ -1,5 +1,6 @@ using System; using NHibernate; +using Orchard.Logging; namespace Orchard.Data { public class SessionLocator : ISessionLocator { @@ -12,13 +13,22 @@ namespace Orchard.Data { ITransactionManager transactionManager) { _sessionFactoryHolder = sessionFactoryHolder; _transactionManager = transactionManager; + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } + public ISession For(Type entityType) { - if (_session==null) { - _transactionManager.Demand(); + Logger.Debug("Acquiring session for {0}", entityType); + + if (_session == null) { + var sessionFactory = _sessionFactoryHolder.GetSessionFactory(); + + _transactionManager.Demand(); + + Logger.Information("Openning database session"); _session = sessionFactory.OpenSession(); } return _session; diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index 877db4513..ac5c021ca 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -42,11 +42,17 @@ namespace Orchard.Environment { _controllerBuilder.SetControllerFactory(new OrchardControllerFactory()); ServiceLocator.SetLocator(t => _containerProvider.RequestContainer.Resolve(t)); - Initialize(); + CreateAndActivateShell(); } void IOrchardHost.Reinitialize() { - Initialize(); + _current = null; + //CreateAndActivateShell(); + } + + + void IOrchardHost.BeginRequest() { + BeginRequest(); } void IOrchardHost.EndRequest() { @@ -58,19 +64,30 @@ namespace Orchard.Environment { return new StandaloneEnvironment(shellContainer); } - protected virtual void Initialize() { - var shellContainer = CreateShellContainer(); - var shell = shellContainer.Resolve(); - shell.Activate(); - _current = shell; + protected virtual void CreateAndActivateShell() { + lock (this) { + if (_current != null) { + return; + } - // Fire off one-time install events on an alternate container - HackInstallSimulation(); + var shellContainer = CreateShellContainer(); + var shell = shellContainer.Resolve(); + shell.Activate(); + _current = shell; - // Activate extensions inside shell container - HackSimulateExtensionActivation(shellContainer); + // Fire off one-time install events on an alternate container + HackInstallSimulation(); + + // Activate extensions inside shell container + HackSimulateExtensionActivation(shellContainer); + } } + protected virtual void BeginRequest() { + if (_current == null) { + CreateAndActivateShell(); + } + } protected virtual void EndRequest() { _containerProvider.DisposeRequestContainer(); @@ -103,19 +120,19 @@ namespace Orchard.Environment { } private void HackInstallSimulation() { - //var tempContainer = CreateShellContainer(); - //var containerProvider = new FiniteContainerProvider(tempContainer); - //try { - // var requestContainer = containerProvider.RequestContainer; + var tempContainer = CreateShellContainer(); + var containerProvider = new FiniteContainerProvider(tempContainer); + try { + var requestContainer = containerProvider.RequestContainer; - // var hackInstallationGenerator = requestContainer.Resolve(); - // hackInstallationGenerator.GenerateInstallEvents(); - //} - //finally { - // // shut everything down again - // containerProvider.DisposeRequestContainer(); - // tempContainer.Dispose(); - //} + var hackInstallationGenerator = requestContainer.Resolve(); + hackInstallationGenerator.GenerateInstallEvents(); + } + finally { + // shut everything down again + containerProvider.DisposeRequestContainer(); + tempContainer.Dispose(); + } } private void HackSimulateExtensionActivation(IContainer shellContainer) { diff --git a/src/Orchard/Environment/IOrchardHost.cs b/src/Orchard/Environment/IOrchardHost.cs index 0e0b62a3a..c8d4c1f7d 100644 --- a/src/Orchard/Environment/IOrchardHost.cs +++ b/src/Orchard/Environment/IOrchardHost.cs @@ -7,16 +7,21 @@ namespace Orchard.Environment { /// void Initialize(); - /// - /// Called each time a request ends to deterministically commit and dispose outstanding activity - /// - void EndRequest(); - /// /// Called when configuration changes requires the shell topology to be reloaded and applied /// void Reinitialize(); + /// + /// Called each time a request begins to offer a just-in-time reinitialization point + /// + void BeginRequest(); + + /// + /// Called each time a request ends to deterministically commit and dispose outstanding activity + /// + void EndRequest(); + /// /// Can be used to build an temporary self-contained instance of a shell's configured code. /// Services may be resolved from within this instance to configure and initialize it's storage. diff --git a/src/Orchard/Environment/ShellBuilders/SafeModeShellContainerFactory.cs b/src/Orchard/Environment/ShellBuilders/SafeModeShellContainerFactory.cs index 64db3b7da..e08ec12ac 100644 --- a/src/Orchard/Environment/ShellBuilders/SafeModeShellContainerFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/SafeModeShellContainerFactory.cs @@ -52,7 +52,7 @@ namespace Orchard.Environment.ShellBuilders { builder.Register().As().ContainerScoped(); builder.Register().As().ContainerScoped(); builder.Register().As().ContainerScoped(); - builder.Register().As().ContainerScoped(); + builder.Register().As().ContainerScoped(); // safe mode specific implementations of needed service interfaces builder.Register().As().ContainerScoped(); diff --git a/src/Orchard/Orchard.csproj b/src/Orchard/Orchard.csproj index c16b5de53..4fa50cd84 100644 --- a/src/Orchard/Orchard.csproj +++ b/src/Orchard/Orchard.csproj @@ -133,12 +133,12 @@ - - - - - - + + + + + +