From 2b1dd7d3b00f1e6dbe1652ee6699eae2e73dd67f Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Wed, 30 Jun 2010 12:38:21 -0700 Subject: [PATCH] Per-content type indexing settings and debug-time performance Added type definition template and settings to indexing project Indexing task check setting per content type while working WebFormViewEngine provider and cache components moved to dedicated namespace Subclass of MVC2 wfve created to use a new asp.net 4 api (avoiding FileExists exception improves performance when debugger is attached) --HG-- branch : dev --- .../Orchard.Web/Config/Diagnostics.config | 2 +- src/Orchard.Web/Config/Diagnostics.config | 2 +- .../Orchard.Indexing/Orchard.Indexing.csproj | 3 ++ .../Services/IndexingTaskExecutor.cs | 37 ++++++++++++---- .../Settings/ContentDefinitionEditorEvents.cs | 24 ++++++++++ .../Orchard.Indexing/Settings/TypeIndexing.cs | 5 +++ .../DefinitionTemplates/TypeIndexing.ascx | 7 +++ .../Modules/Orchard.Setup/SetupMode.cs | 3 +- .../Environment/DefaultOrchardShell.cs | 2 +- .../Mvc/ViewEngines/LayoutViewEngine.cs | 5 --- .../Mvc/ViewEngines/ViewEngineFilter.cs | 10 ++++- .../{ => WebForms}/ThemeViewLocationCache.cs | 5 +-- .../WebForms/WebFormViewEngineForAspNet4.cs | 25 +++++++++++ .../WebFormViewEngineProvider.cs} | 44 +++++++++---------- src/Orchard/Orchard.Framework.csproj | 5 ++- 15 files changed, 133 insertions(+), 46 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Settings/ContentDefinitionEditorEvents.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Settings/TypeIndexing.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/TypeIndexing.ascx rename src/Orchard/Mvc/ViewEngines/{ => WebForms}/ThemeViewLocationCache.cs (88%) create mode 100644 src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineForAspNet4.cs rename src/Orchard/Mvc/ViewEngines/{WebFormsViewEngineProvider.cs => WebForms/WebFormViewEngineProvider.cs} (71%) diff --git a/src/Orchard.Specs/Hosting/Orchard.Web/Config/Diagnostics.config b/src/Orchard.Specs/Hosting/Orchard.Web/Config/Diagnostics.config index a44c108d4..e3bc6cb6f 100644 --- a/src/Orchard.Specs/Hosting/Orchard.Web/Config/Diagnostics.config +++ b/src/Orchard.Specs/Hosting/Orchard.Web/Config/Diagnostics.config @@ -21,7 +21,7 @@ - + diff --git a/src/Orchard.Web/Config/Diagnostics.config b/src/Orchard.Web/Config/Diagnostics.config index 124536a7d..ee34eaabf 100644 --- a/src/Orchard.Web/Config/Diagnostics.config +++ b/src/Orchard.Web/Config/Diagnostics.config @@ -1,7 +1,7 @@  - + diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index 179e2bb84..f2d43e5c2 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -56,6 +56,7 @@ + @@ -77,6 +78,8 @@ + + diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs index 27e48f6bd..2bc384b61 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs @@ -5,6 +5,7 @@ using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.Data; using Orchard.Indexing.Models; +using Orchard.Indexing.Settings; using Orchard.Logging; using Orchard.Services; using Orchard.Tasks.Indexing; @@ -23,7 +24,7 @@ namespace Orchard.Indexing.Services { private readonly IContentManager _contentManager; private readonly IIndexSynLock _indexSynLock; private const string SearchIndexName = "Search"; - + public IndexingTaskExecutor( IClock clock, IRepository repository, @@ -45,7 +46,7 @@ namespace Orchard.Indexing.Services { public void UpdateIndex(string indexName) { var synLock = _indexSynLock.GetSynLock(SearchIndexName); - if ( !System.Threading.Monitor.TryEnter(synLock) ) { + if (!System.Threading.Monitor.TryEnter(synLock)) { Logger.Information("Index was requested but was already running"); return; } @@ -70,10 +71,15 @@ namespace Orchard.Indexing.Services { // get every existing content item to index it foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) { try { - var documentIndex = _indexProvider.New(contentItem.Id); + // skip items which are not indexed + var settings = GetTypeIndexingSettings(contentItem); + if (!settings.Included) + continue; + + var documentIndex = _indexProvider.New(contentItem.Id); _contentManager.Index(contentItem, documentIndex); - if(documentIndex.IsDirty) { + if (documentIndex.IsDirty) { updateIndexDocuments.Add(documentIndex); } } @@ -91,8 +97,10 @@ namespace Orchard.Indexing.Services { _indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow); // retrieve not yet processed tasks - var taskRecords = _repository.Fetch(x => x.CreatedUtc > lastIndexing) - .ToArray(); + var taskRecords = lastIndexing == DateTime.MinValue + ? _repository.Fetch(x => true).ToArray() + : _repository.Fetch(x => x.CreatedUtc > lastIndexing).ToArray(); + // nothing to do ? if (taskRecords.Length + updateIndexDocuments.Count == 0) @@ -116,11 +124,15 @@ namespace Orchard.Indexing.Services { foreach (var taskRecord in taskRecords.Where(t => t.Action == IndexingTaskRecord.Update)) { var task = new IndexingTask(_contentManager, taskRecord); + // skip items which are not indexed + var settings = GetTypeIndexingSettings(task.ContentItem); + if (!settings.Included) + continue; + try { var documentIndex = _indexProvider.New(task.ContentItem.Id); - _contentManager.Index(task.ContentItem, documentIndex); - if ( documentIndex.IsDirty ) { + if (documentIndex.IsDirty) { updateIndexDocuments.Add(documentIndex); } @@ -143,5 +155,14 @@ namespace Orchard.Indexing.Services { System.Threading.Monitor.Exit(synLock); } } + + static TypeIndexing GetTypeIndexingSettings(ContentItem contentItem) { + if (contentItem == null || + contentItem.TypeDefinition == null || + contentItem.TypeDefinition.Settings == null) { + return new TypeIndexing { Included = false }; + } + return contentItem.TypeDefinition.Settings.GetModel(); + } } } diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/ContentDefinitionEditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/ContentDefinitionEditorEvents.cs new file mode 100644 index 000000000..5fd7d9cbd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/ContentDefinitionEditorEvents.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.ViewModels; + +namespace Orchard.Indexing.Settings { + public class ContentDefinitionEditorEvents : ContentDefinitionEditorEventsBase { + public override IEnumerable TypeEditor(ContentTypeDefinition definition) { + var model = definition.Settings.GetModel(); + yield return DefinitionTemplate(model); + } + + public override IEnumerable TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) { + var model = new TypeIndexing(); + updateModel.TryUpdateModel(model, "TypeIndexing", null, null); + builder + .WithSetting("TypeIndexing.Included", model.Included ? true.ToString() : null); + + yield return DefinitionTemplate(model); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/TypeIndexing.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/TypeIndexing.cs new file mode 100644 index 000000000..45e90a4e7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/TypeIndexing.cs @@ -0,0 +1,5 @@ +namespace Orchard.Indexing.Settings { + public class TypeIndexing { + public bool Included { get; set; } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/TypeIndexing.ascx b/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/TypeIndexing.ascx new file mode 100644 index 000000000..2dc8a7721 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/TypeIndexing.ascx @@ -0,0 +1,7 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Mvc.Html" %> +
+ <%:Html.EditorFor(m=>m.Included) %> + + <%:Html.ValidationMessageFor(m=>m.Included) %> +
diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index 4c27ad19d..4f763a9cb 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -16,6 +16,7 @@ using Orchard.Mvc.Filters; using Orchard.Mvc.ModelBinders; using Orchard.Mvc.Routes; using Orchard.Mvc.ViewEngines; +using Orchard.Mvc.ViewEngines.WebForms; using Orchard.Settings; using Orchard.Setup.Commands; using Orchard.Themes; @@ -33,7 +34,7 @@ namespace Orchard.Setup { builder.RegisterModule(new CommandModule()); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); diff --git a/src/Orchard/Environment/DefaultOrchardShell.cs b/src/Orchard/Environment/DefaultOrchardShell.cs index c4b30cb8c..2a09c992c 100644 --- a/src/Orchard/Environment/DefaultOrchardShell.cs +++ b/src/Orchard/Environment/DefaultOrchardShell.cs @@ -41,7 +41,7 @@ namespace Orchard.Environment { _routePublisher.Publish(_routeProviders.SelectMany(provider => provider.GetRoutes())); _modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders())); - AddOrchardLocationsFormats(); + //AddOrchardLocationsFormats(); using (var events = _eventsFactory()) { events.Value.Activated(); diff --git a/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs b/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs index 8ce81a97e..de6401aa6 100644 --- a/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs +++ b/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs @@ -31,7 +31,6 @@ namespace Orchard.Mvc.ViewEngines { if (skipLayoutViewEngine) return new ViewEngineResult(Enumerable.Empty()); - var bodyView = _viewEngines.FindPartialView(controllerContext, viewName); ViewEngineResult layoutView = null; @@ -109,7 +108,6 @@ namespace Orchard.Mvc.ViewEngines { return new ViewEngineResult(Enumerable.Empty()); } - public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { var scope = Scope.From(controllerContext); if (scope != null && scope.LayoutViewEngine != null) { @@ -120,10 +118,7 @@ namespace Orchard.Mvc.ViewEngines { return new ViewEngineResult(Enumerable.Empty()); } - - public void ReleaseView(ControllerContext controllerContext, IView view) { - throw new NotImplementedException(); } } diff --git a/src/Orchard/Mvc/ViewEngines/ViewEngineFilter.cs b/src/Orchard/Mvc/ViewEngines/ViewEngineFilter.cs index 832eec526..c1fd4b19b 100644 --- a/src/Orchard/Mvc/ViewEngines/ViewEngineFilter.cs +++ b/src/Orchard/Mvc/ViewEngines/ViewEngineFilter.cs @@ -63,7 +63,7 @@ namespace Orchard.Mvc.ViewEngines { var requestViewEngines = new ViewEngineCollection( themeViewEngines .Concat(moduleViewEngines) - .Concat(_viewEngines.Where(x => x.GetType().Assembly != typeof(LayoutViewEngine).Assembly)) + .Concat(_viewEngines.Where(ViewEngineIsForwarded)) .ToArray()); var layoutViewEngine = new LayoutViewEngine(requestViewEngines); @@ -72,6 +72,14 @@ namespace Orchard.Mvc.ViewEngines { viewResultBase.ViewEngineCollection.Insert(0, layoutViewEngine); } + static bool ViewEngineIsForwarded(IViewEngine x) { + // default view engine, and layout view engine, are not forwarded to + // be used for resolving partials + return + x.GetType().Assembly != typeof(LayoutViewEngine).Assembly && + x.GetType() != typeof(WebFormViewEngine); + } + public void OnResultExecuted(ResultExecutedContext filterContext) { } diff --git a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs b/src/Orchard/Mvc/ViewEngines/WebForms/ThemeViewLocationCache.cs similarity index 88% rename from src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs rename to src/Orchard/Mvc/ViewEngines/WebForms/ThemeViewLocationCache.cs index a5a39f1eb..16e4e76c4 100644 --- a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs +++ b/src/Orchard/Mvc/ViewEngines/WebForms/ThemeViewLocationCache.cs @@ -1,13 +1,10 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Web.Mvc; using System.Web.Caching; using System.Web; using System.Web.Hosting; -namespace Orchard.Mvc.ViewEngines { +namespace Orchard.Mvc.ViewEngines.WebForms { public class ThemeViewLocationCache : IViewLocationCache { private readonly string _requestTheme; diff --git a/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineForAspNet4.cs b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineForAspNet4.cs new file mode 100644 index 000000000..1af79428f --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineForAspNet4.cs @@ -0,0 +1,25 @@ +using System.Web; +using System.Web.Compilation; +using System.Web.Mvc; + +namespace Orchard.Mvc.ViewEngines.WebForms { + public class WebFormViewEngineForAspNet4 : WebFormViewEngine { + protected override bool FileExists(ControllerContext controllerContext, string virtualPath) { + try { + + return BuildManager.GetObjectFactory(virtualPath, false) != null; + } + catch (HttpException exception) { + // Reproducing base class behavior, however these this code path should + // not be followed for "not found" cases + if (exception is HttpParseException) { + throw; + } + if ((exception.GetHttpCode() != 0x194) || base.FileExists(controllerContext, virtualPath)) { + throw; + } + return false; + } + } + } +} diff --git a/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs similarity index 71% rename from src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs rename to src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs index 6192160fb..28c69eb0c 100644 --- a/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs +++ b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs @@ -2,9 +2,9 @@ using System.Web.Mvc; using Orchard.Logging; -namespace Orchard.Mvc.ViewEngines { - public class WebFormsViewEngineProvider : IViewEngineProvider { - public WebFormsViewEngineProvider() { +namespace Orchard.Mvc.ViewEngines.WebForms { + public class WebFormViewEngineProvider : IViewEngineProvider { + public WebFormViewEngineProvider() { Logger = NullLogger.Instance; } static string[] DisabledFormats = new[] { "~/Disabled" }; @@ -22,35 +22,35 @@ namespace Orchard.Mvc.ViewEngines { // Partial Paths - // {area}/{controller}/ - - var viewEngine = new WebFormViewEngine { - MasterLocationFormats = DisabledFormats, - ViewLocationFormats = DisabledFormats, - AreaMasterLocationFormats = DisabledFormats, - AreaViewLocationFormats = DisabledFormats, - AreaPartialViewLocationFormats = DisabledFormats, - }; - - viewEngine.ViewLocationCache = new ThemeViewLocationCache(parameters.VirtualPath); + // for "routed" request views... + // enable /Views/{area}/{controller}/{viewName} // enable /Views/{partialName} // enable /Views/"DisplayTemplates/"+{templateName} // enable /Views/"EditorTemplates/+{templateName} - viewEngine.PartialViewLocationFormats = new[] { + var partialViewLocationFormats = new[] { parameters.VirtualPath + "/Views/{0}.ascx", parameters.VirtualPath + "/Views/{0}.aspx", }; - Logger.Debug("PartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", viewEngine.PartialViewLocationFormats)); + //Logger.Debug("PartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", partialViewLocationFormats)); - // for "routed" request views... - // enable /Views/{area}/{controller}/{viewName} - viewEngine.AreaPartialViewLocationFormats = new[] { + var areaPartialViewLocationFormats = new[] { parameters.VirtualPath + "/Views/{2}/{1}/{0}.ascx", parameters.VirtualPath + "/Views/{2}/{1}/{0}.aspx", }; - Logger.Debug("AreaPartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", viewEngine.AreaPartialViewLocationFormats)); + //Logger.Debug("AreaPartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", areaPartialViewLocationFormats)); + + var viewEngine = new WebFormViewEngineForAspNet4 { + MasterLocationFormats = DisabledFormats, + ViewLocationFormats = DisabledFormats, + PartialViewLocationFormats = partialViewLocationFormats, + AreaMasterLocationFormats = DisabledFormats, + AreaViewLocationFormats = DisabledFormats, + AreaPartialViewLocationFormats = areaPartialViewLocationFormats, + ViewLocationCache = new ThemeViewLocationCache(parameters.VirtualPath), + }; return viewEngine; } @@ -63,7 +63,7 @@ namespace Orchard.Mvc.ViewEngines { "~/Modules/{2}/Views/{1}/{0}.aspx", }; - Logger.Debug("AreaFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", areaFormats)); + //Logger.Debug("AreaFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", areaFormats)); var universalFormats = parameters.VirtualPaths .SelectMany(x => new[] { @@ -72,9 +72,9 @@ namespace Orchard.Mvc.ViewEngines { }) .ToArray(); - Logger.Debug("UniversalFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", universalFormats)); + //Logger.Debug("UniversalFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", universalFormats)); - var viewEngine = new WebFormViewEngine { + var viewEngine = new WebFormViewEngineForAspNet4 { MasterLocationFormats = DisabledFormats, ViewLocationFormats = universalFormats, PartialViewLocationFormats = universalFormats, diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 2edd3eaaf..e8355d76c 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -463,6 +463,7 @@ + @@ -557,7 +558,7 @@ - + ASPXCodeBehind @@ -644,7 +645,7 @@ - +