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
This commit is contained in:
Louis DeJardin
2010-06-30 12:38:21 -07:00
parent 01f8617078
commit 2b1dd7d3b0
15 changed files with 133 additions and 46 deletions

View File

@@ -21,7 +21,7 @@
<add name="CaptureTraceMessages" /> <add name="CaptureTraceMessages" />
</listeners> </listeners>
</source> </source>
<source name="Orchard.Mvc.ViewEngines.WebFormsViewEngineProvider" switchValue="Warning"> <source name="Orchard.Mvc.ViewEngines.WebFormViewEngineProvider" switchValue="Warning">
<listeners> <listeners>
<add name="CaptureTraceMessages" /> <add name="CaptureTraceMessages" />
</listeners> </listeners>

View File

@@ -1,7 +1,7 @@
<system.diagnostics> <system.diagnostics>
<trace autoflush="true"/> <trace autoflush="true"/>
<sources> <sources>
<source name="Default" switchValue="Verbose"> <source name="Default" switchValue="Warning">
<listeners> <listeners>
<add name="OrchardDebugTextLog" /> <add name="OrchardDebugTextLog" />
<add name="WebPageTrace"/> <add name="WebPageTrace"/>

View File

@@ -56,6 +56,7 @@
<ItemGroup> <ItemGroup>
<Content Include="Module.txt" /> <Content Include="Module.txt" />
<Content Include="Views\Admin\Index.ascx" /> <Content Include="Views\Admin\Index.ascx" />
<Content Include="Views\DefinitionTemplates\TypeIndexing.ascx" />
<Content Include="Web.config" /> <Content Include="Web.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -77,6 +78,8 @@
<Compile Include="Models\LuceneSearchHit.cs" /> <Compile Include="Models\LuceneSearchHit.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\IndexService.cs" /> <Compile Include="Services\IndexService.cs" />
<Compile Include="Settings\ContentDefinitionEditorEvents.cs" />
<Compile Include="Settings\TypeIndexing.cs" />
<Compile Include="ViewModels\IndexViewModel.cs" /> <Compile Include="ViewModels\IndexViewModel.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -5,6 +5,7 @@ using JetBrains.Annotations;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Data; using Orchard.Data;
using Orchard.Indexing.Models; using Orchard.Indexing.Models;
using Orchard.Indexing.Settings;
using Orchard.Logging; using Orchard.Logging;
using Orchard.Services; using Orchard.Services;
using Orchard.Tasks.Indexing; using Orchard.Tasks.Indexing;
@@ -45,7 +46,7 @@ namespace Orchard.Indexing.Services {
public void UpdateIndex(string indexName) { public void UpdateIndex(string indexName) {
var synLock = _indexSynLock.GetSynLock(SearchIndexName); 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"); Logger.Information("Index was requested but was already running");
return; return;
} }
@@ -70,10 +71,15 @@ namespace Orchard.Indexing.Services {
// get every existing content item to index it // get every existing content item to index it
foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) { foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) {
try { 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); _contentManager.Index(contentItem, documentIndex);
if(documentIndex.IsDirty) { if (documentIndex.IsDirty) {
updateIndexDocuments.Add(documentIndex); updateIndexDocuments.Add(documentIndex);
} }
} }
@@ -91,8 +97,10 @@ namespace Orchard.Indexing.Services {
_indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow); _indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow);
// retrieve not yet processed tasks // retrieve not yet processed tasks
var taskRecords = _repository.Fetch(x => x.CreatedUtc > lastIndexing) var taskRecords = lastIndexing == DateTime.MinValue
.ToArray(); ? _repository.Fetch(x => true).ToArray()
: _repository.Fetch(x => x.CreatedUtc > lastIndexing).ToArray();
// nothing to do ? // nothing to do ?
if (taskRecords.Length + updateIndexDocuments.Count == 0) 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)) { foreach (var taskRecord in taskRecords.Where(t => t.Action == IndexingTaskRecord.Update)) {
var task = new IndexingTask(_contentManager, taskRecord); var task = new IndexingTask(_contentManager, taskRecord);
// skip items which are not indexed
var settings = GetTypeIndexingSettings(task.ContentItem);
if (!settings.Included)
continue;
try { try {
var documentIndex = _indexProvider.New(task.ContentItem.Id); var documentIndex = _indexProvider.New(task.ContentItem.Id);
_contentManager.Index(task.ContentItem, documentIndex); _contentManager.Index(task.ContentItem, documentIndex);
if ( documentIndex.IsDirty ) { if (documentIndex.IsDirty) {
updateIndexDocuments.Add(documentIndex); updateIndexDocuments.Add(documentIndex);
} }
@@ -143,5 +155,14 @@ namespace Orchard.Indexing.Services {
System.Threading.Monitor.Exit(synLock); 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<TypeIndexing>();
}
} }
} }

View File

@@ -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<TemplateViewModel> TypeEditor(ContentTypeDefinition definition) {
var model = definition.Settings.GetModel<TypeIndexing>();
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> 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);
}
}
}

View File

@@ -0,0 +1,5 @@
namespace Orchard.Indexing.Settings {
public class TypeIndexing {
public bool Included { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Indexing.Settings.TypeIndexing>" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<fieldset>
<%:Html.EditorFor(m=>m.Included) %>
<label for="<%:Html.FieldIdFor(m => m.Included) %>" class="forcheckbox"><%:T("Index this content type for search") %></label>
<%:Html.ValidationMessageFor(m=>m.Included) %>
</fieldset>

View File

@@ -16,6 +16,7 @@ using Orchard.Mvc.Filters;
using Orchard.Mvc.ModelBinders; using Orchard.Mvc.ModelBinders;
using Orchard.Mvc.Routes; using Orchard.Mvc.Routes;
using Orchard.Mvc.ViewEngines; using Orchard.Mvc.ViewEngines;
using Orchard.Mvc.ViewEngines.WebForms;
using Orchard.Settings; using Orchard.Settings;
using Orchard.Setup.Commands; using Orchard.Setup.Commands;
using Orchard.Themes; using Orchard.Themes;
@@ -33,7 +34,7 @@ namespace Orchard.Setup {
builder.RegisterModule(new CommandModule()); builder.RegisterModule(new CommandModule());
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope(); builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope(); builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
builder.RegisterType<WebFormsViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope(); builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
builder.RegisterType<ViewEngineFilter>().As<IFilterProvider>().InstancePerLifetimeScope(); builder.RegisterType<ViewEngineFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope(); builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope(); builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope();

View File

@@ -41,7 +41,7 @@ namespace Orchard.Environment {
_routePublisher.Publish(_routeProviders.SelectMany(provider => provider.GetRoutes())); _routePublisher.Publish(_routeProviders.SelectMany(provider => provider.GetRoutes()));
_modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders())); _modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders()));
AddOrchardLocationsFormats(); //AddOrchardLocationsFormats();
using (var events = _eventsFactory()) { using (var events = _eventsFactory()) {
events.Value.Activated(); events.Value.Activated();

View File

@@ -31,7 +31,6 @@ namespace Orchard.Mvc.ViewEngines {
if (skipLayoutViewEngine) if (skipLayoutViewEngine)
return new ViewEngineResult(Enumerable.Empty<string>()); return new ViewEngineResult(Enumerable.Empty<string>());
var bodyView = _viewEngines.FindPartialView(controllerContext, viewName); var bodyView = _viewEngines.FindPartialView(controllerContext, viewName);
ViewEngineResult layoutView = null; ViewEngineResult layoutView = null;
@@ -109,7 +108,6 @@ namespace Orchard.Mvc.ViewEngines {
return new ViewEngineResult(Enumerable.Empty<string>()); return new ViewEngineResult(Enumerable.Empty<string>());
} }
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
var scope = Scope.From(controllerContext); var scope = Scope.From(controllerContext);
if (scope != null && scope.LayoutViewEngine != null) { if (scope != null && scope.LayoutViewEngine != null) {
@@ -120,10 +118,7 @@ namespace Orchard.Mvc.ViewEngines {
return new ViewEngineResult(Enumerable.Empty<string>()); return new ViewEngineResult(Enumerable.Empty<string>());
} }
public void ReleaseView(ControllerContext controllerContext, IView view) { public void ReleaseView(ControllerContext controllerContext, IView view) {
throw new NotImplementedException();
} }
} }

View File

@@ -63,7 +63,7 @@ namespace Orchard.Mvc.ViewEngines {
var requestViewEngines = new ViewEngineCollection( var requestViewEngines = new ViewEngineCollection(
themeViewEngines themeViewEngines
.Concat(moduleViewEngines) .Concat(moduleViewEngines)
.Concat(_viewEngines.Where(x => x.GetType().Assembly != typeof(LayoutViewEngine).Assembly)) .Concat(_viewEngines.Where(ViewEngineIsForwarded))
.ToArray()); .ToArray());
var layoutViewEngine = new LayoutViewEngine(requestViewEngines); var layoutViewEngine = new LayoutViewEngine(requestViewEngines);
@@ -72,6 +72,14 @@ namespace Orchard.Mvc.ViewEngines {
viewResultBase.ViewEngineCollection.Insert(0, layoutViewEngine); 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) { public void OnResultExecuted(ResultExecutedContext filterContext) {
} }

View File

@@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Caching; using System.Web.Caching;
using System.Web; using System.Web;
using System.Web.Hosting; using System.Web.Hosting;
namespace Orchard.Mvc.ViewEngines { namespace Orchard.Mvc.ViewEngines.WebForms {
public class ThemeViewLocationCache : IViewLocationCache { public class ThemeViewLocationCache : IViewLocationCache {
private readonly string _requestTheme; private readonly string _requestTheme;

View File

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

View File

@@ -2,9 +2,9 @@
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.Logging; using Orchard.Logging;
namespace Orchard.Mvc.ViewEngines { namespace Orchard.Mvc.ViewEngines.WebForms {
public class WebFormsViewEngineProvider : IViewEngineProvider { public class WebFormViewEngineProvider : IViewEngineProvider {
public WebFormsViewEngineProvider() { public WebFormViewEngineProvider() {
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
static string[] DisabledFormats = new[] { "~/Disabled" }; static string[] DisabledFormats = new[] { "~/Disabled" };
@@ -22,35 +22,35 @@ namespace Orchard.Mvc.ViewEngines {
// Partial Paths - // Partial Paths -
// {area}/{controller}/ // {area}/{controller}/
// for "routed" request views...
var viewEngine = new WebFormViewEngine { // enable /Views/{area}/{controller}/{viewName}
MasterLocationFormats = DisabledFormats,
ViewLocationFormats = DisabledFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = DisabledFormats,
AreaPartialViewLocationFormats = DisabledFormats,
};
viewEngine.ViewLocationCache = new ThemeViewLocationCache(parameters.VirtualPath);
// enable /Views/{partialName} // enable /Views/{partialName}
// enable /Views/"DisplayTemplates/"+{templateName} // enable /Views/"DisplayTemplates/"+{templateName}
// enable /Views/"EditorTemplates/+{templateName} // enable /Views/"EditorTemplates/+{templateName}
viewEngine.PartialViewLocationFormats = new[] { var partialViewLocationFormats = new[] {
parameters.VirtualPath + "/Views/{0}.ascx", parameters.VirtualPath + "/Views/{0}.ascx",
parameters.VirtualPath + "/Views/{0}.aspx", 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... var areaPartialViewLocationFormats = new[] {
// enable /Views/{area}/{controller}/{viewName}
viewEngine.AreaPartialViewLocationFormats = new[] {
parameters.VirtualPath + "/Views/{2}/{1}/{0}.ascx", parameters.VirtualPath + "/Views/{2}/{1}/{0}.ascx",
parameters.VirtualPath + "/Views/{2}/{1}/{0}.aspx", 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; return viewEngine;
} }
@@ -63,7 +63,7 @@ namespace Orchard.Mvc.ViewEngines {
"~/Modules/{2}/Views/{1}/{0}.aspx", "~/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 var universalFormats = parameters.VirtualPaths
.SelectMany(x => new[] { .SelectMany(x => new[] {
@@ -72,9 +72,9 @@ namespace Orchard.Mvc.ViewEngines {
}) })
.ToArray(); .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, MasterLocationFormats = DisabledFormats,
ViewLocationFormats = universalFormats, ViewLocationFormats = universalFormats,
PartialViewLocationFormats = universalFormats, PartialViewLocationFormats = universalFormats,

View File

@@ -463,6 +463,7 @@
<Compile Include="Environment\DefaultOrchardHost.cs" /> <Compile Include="Environment\DefaultOrchardHost.cs" />
<Compile Include="Mvc\OrchardControllerFactory.cs" /> <Compile Include="Mvc\OrchardControllerFactory.cs" />
<Compile Include="Environment\IOrchardHost.cs" /> <Compile Include="Environment\IOrchardHost.cs" />
<Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineForAspNet4.cs" />
<Compile Include="OrchardCoreException.cs" /> <Compile Include="OrchardCoreException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Indexing\IIndexDocument.cs" /> <Compile Include="Indexing\IIndexDocument.cs" />
@@ -557,7 +558,7 @@
<Compile Include="Mvc\Routes\UrlPrefix.cs" /> <Compile Include="Mvc\Routes\UrlPrefix.cs" />
<Compile Include="Mvc\Routes\UrlPrefixAdjustedHttpContext.cs" /> <Compile Include="Mvc\Routes\UrlPrefixAdjustedHttpContext.cs" />
<Compile Include="Mvc\Routes\ShellRoute.cs" /> <Compile Include="Mvc\Routes\ShellRoute.cs" />
<Compile Include="Mvc\ViewEngines\ThemeViewLocationCache.cs" /> <Compile Include="Mvc\ViewEngines\WebForms\ThemeViewLocationCache.cs" />
<Compile Include="Mvc\ViewModels\AdaptedViewModel.cs" /> <Compile Include="Mvc\ViewModels\AdaptedViewModel.cs" />
<Compile Include="Mvc\ViewUserControl.cs"> <Compile Include="Mvc\ViewUserControl.cs">
<SubType>ASPXCodeBehind</SubType> <SubType>ASPXCodeBehind</SubType>
@@ -644,7 +645,7 @@
<Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" /> <Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" />
<Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" /> <Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" />
<Compile Include="Mvc\ViewEngines\ViewEngineFilter.cs" /> <Compile Include="Mvc\ViewEngines\ViewEngineFilter.cs" />
<Compile Include="Mvc\ViewEngines\WebFormsViewEngineProvider.cs" /> <Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineProvider.cs" />
<Compile Include="Mvc\ViewModels\BaseViewModel.cs" /> <Compile Include="Mvc\ViewModels\BaseViewModel.cs" />
<Compile Include="UI\Admin\AdminThemeSelector.cs" /> <Compile Include="UI\Admin\AdminThemeSelector.cs" />
<Compile Include="UI\Navigation\INavigationManager.cs" /> <Compile Include="UI\Navigation\INavigationManager.cs" />