U4-8447 - prepare for NuCache (work-in-progress)
This commit is contained in:
@@ -6,13 +6,10 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Examine;
|
||||
using Examine.LuceneEngine;
|
||||
using Examine.LuceneEngine.Providers;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.Providers;
|
||||
using Lucene.Net.Documents;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -22,8 +19,7 @@ using Umbraco.Web.Models;
|
||||
using UmbracoExamine;
|
||||
using umbraco;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
@@ -33,83 +29,156 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
/// <remarks>
|
||||
/// NOTE: In the future if we want to properly cache all media this class can be extended or replaced when these classes/interfaces are exposed publicly.
|
||||
/// </remarks>
|
||||
internal class PublishedMediaCache : IPublishedMediaCache
|
||||
internal class PublishedMediaCache : PublishedCacheBase, IPublishedMediaCache
|
||||
{
|
||||
public PublishedMediaCache(ApplicationContext applicationContext)
|
||||
{
|
||||
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
|
||||
_applicationContext = applicationContext;
|
||||
}
|
||||
private readonly IMediaService _mediaService;
|
||||
|
||||
// by default these are null unless specified by the ctor dedicated to tests
|
||||
// when they are null the cache derives them from the ExamineManager, see
|
||||
// method GetExamineManagerSafe().
|
||||
//
|
||||
private readonly ILuceneSearcher _searchProvider;
|
||||
private readonly BaseIndexProvider _indexProvider;
|
||||
private readonly XmlStore _xmlStore;
|
||||
private readonly PublishedContentTypeCache _contentTypeCache;
|
||||
|
||||
// must be specified by the ctor
|
||||
private readonly ICacheProvider _cacheProvider;
|
||||
|
||||
public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache)
|
||||
: base(false)
|
||||
{
|
||||
if (mediaService == null) throw new ArgumentNullException(nameof(mediaService));
|
||||
_mediaService = mediaService;
|
||||
_cacheProvider = cacheProvider;
|
||||
_xmlStore = xmlStore;
|
||||
_contentTypeCache = contentTypeCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generally used for unit testing to use an explicit examine searcher
|
||||
/// </summary>
|
||||
/// <param name="applicationContext"></param>
|
||||
/// <param name="mediaService"></param>
|
||||
/// <param name="searchProvider"></param>
|
||||
/// <param name="indexProvider"></param>
|
||||
internal PublishedMediaCache(ApplicationContext applicationContext, ILuceneSearcher searchProvider, BaseIndexProvider indexProvider)
|
||||
/// <param name="cacheProvider"></param>
|
||||
/// <param name="contentTypeCache"></param>
|
||||
internal PublishedMediaCache(IMediaService mediaService, ILuceneSearcher searchProvider, BaseIndexProvider indexProvider, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache)
|
||||
: base(false)
|
||||
{
|
||||
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
|
||||
if (searchProvider == null) throw new ArgumentNullException("searchProvider");
|
||||
if (indexProvider == null) throw new ArgumentNullException("indexProvider");
|
||||
if (mediaService == null) throw new ArgumentNullException(nameof(mediaService));
|
||||
if (searchProvider == null) throw new ArgumentNullException(nameof(searchProvider));
|
||||
if (indexProvider == null) throw new ArgumentNullException(nameof(indexProvider));
|
||||
|
||||
_applicationContext = applicationContext;
|
||||
_mediaService = mediaService;
|
||||
_searchProvider = searchProvider;
|
||||
_indexProvider = indexProvider;
|
||||
}
|
||||
_cacheProvider = cacheProvider;
|
||||
_contentTypeCache = contentTypeCache;
|
||||
}
|
||||
|
||||
static PublishedMediaCache()
|
||||
{
|
||||
InitializeCacheConfig();
|
||||
}
|
||||
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly ILuceneSearcher _searchProvider;
|
||||
private readonly BaseIndexProvider _indexProvider;
|
||||
|
||||
public virtual IPublishedContent GetById(UmbracoContext umbracoContext, bool preview, int nodeId)
|
||||
public override IPublishedContent GetById(bool preview, int nodeId)
|
||||
{
|
||||
return GetUmbracoMedia(nodeId);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IPublishedContent> GetAtRoot(UmbracoContext umbracoContext, bool preview)
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return GetUmbracoMedia(contentId) != null;
|
||||
}
|
||||
|
||||
public override IEnumerable<IPublishedContent> GetAtRoot(bool preview)
|
||||
{
|
||||
//TODO: We should be able to look these ids first in Examine!
|
||||
|
||||
var rootMedia = _applicationContext.Services.MediaService.GetRootMedia();
|
||||
var rootMedia = _mediaService.GetRootMedia();
|
||||
return rootMedia.Select(m => GetUmbracoMedia(m.Id));
|
||||
}
|
||||
|
||||
public virtual IPublishedContent GetSingleByXPath(UmbracoContext umbracoContext, bool preview, string xpath, XPathVariable[] vars)
|
||||
public override IPublishedContent GetSingleByXPath(bool preview, string xpath, XPathVariable[] vars)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//var navigator = CreateNavigator(preview);
|
||||
//var iterator = navigator.Select(xpath, vars);
|
||||
//return GetSingleByXPath(iterator);
|
||||
}
|
||||
|
||||
public virtual IPublishedContent GetSingleByXPath(UmbracoContext umbracoContext, bool preview, XPathExpression xpath, XPathVariable[] vars)
|
||||
public override IPublishedContent GetSingleByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//var navigator = CreateNavigator(preview);
|
||||
//var iterator = navigator.Select(xpath, vars);
|
||||
//return GetSingleByXPath(iterator);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IPublishedContent> GetByXPath(UmbracoContext umbracoContext, bool preview, string xpath, XPathVariable[] vars)
|
||||
private IPublishedContent GetSingleByXPath(XPathNodeIterator iterator)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//if (iterator.MoveNext() == false) return null;
|
||||
//var idAttr = iterator.Current.GetAttribute("id", "");
|
||||
//int id;
|
||||
//return int.TryParse(idAttr, out id) ? GetUmbracoMedia(id) : null;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IPublishedContent> GetByXPath(UmbracoContext umbracoContext, bool preview, XPathExpression xpath, XPathVariable[] vars)
|
||||
public override IEnumerable<IPublishedContent> GetByXPath(bool preview, string xpath, XPathVariable[] vars)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//var navigator = CreateNavigator(preview);
|
||||
//var iterator = navigator.Select(xpath, vars);
|
||||
//return GetByXPath(iterator);
|
||||
}
|
||||
|
||||
public virtual XPathNavigator GetXPathNavigator(UmbracoContext umbracoContext, bool preview)
|
||||
public override IEnumerable<IPublishedContent> GetByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//var navigator = CreateNavigator(preview);
|
||||
//var iterator = navigator.Select(xpath, vars);
|
||||
//return GetByXPath(iterator);
|
||||
}
|
||||
|
||||
public bool XPathNavigatorIsNavigable { get { return false; } }
|
||||
private IEnumerable<IPublishedContent> GetByXPath(XPathNodeIterator iterator)
|
||||
{
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
var idAttr = iterator.Current.GetAttribute("id", "");
|
||||
int id;
|
||||
if (int.TryParse(idAttr, out id))
|
||||
yield return GetUmbracoMedia(id);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool HasContent(UmbracoContext context, bool preview) { throw new NotImplementedException(); }
|
||||
public override XPathNavigator CreateNavigator(bool preview)
|
||||
{
|
||||
throw new NotImplementedException("PublishedMediaCache does not support XPath.");
|
||||
//var doc = _xmlStore.GetMediaXml();
|
||||
//return doc.CreateNavigator();
|
||||
}
|
||||
|
||||
private ExamineManager GetExamineManagerSafe()
|
||||
public override XPathNavigator CreateNodeNavigator(int id, bool preview)
|
||||
{
|
||||
// preview is ignored for media cache
|
||||
|
||||
// this code is mostly used when replacing old media.ToXml() code, and that code
|
||||
// stored the XML attached to the media itself - so for some time in memory - so
|
||||
// unless we implement some sort of cache here, we're probably degrading perfs.
|
||||
|
||||
XPathNavigator navigator = null;
|
||||
var node = _xmlStore.GetMediaXmlNode(id);
|
||||
if (node != null)
|
||||
{
|
||||
navigator = node.CreateNavigator();
|
||||
}
|
||||
return navigator;
|
||||
}
|
||||
|
||||
public override bool HasContent(bool preview) { throw new NotImplementedException(); }
|
||||
|
||||
private static ExamineManager GetExamineManagerSafe()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -127,25 +196,24 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
return _indexProvider;
|
||||
|
||||
var eMgr = GetExamineManagerSafe();
|
||||
if (eMgr != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//by default use the InternalSearcher
|
||||
var indexer = eMgr.IndexProviderCollection["InternalIndexer"];
|
||||
if (indexer.IndexerData.IncludeNodeTypes.Any() || indexer.IndexerData.ExcludeNodeTypes.Any())
|
||||
{
|
||||
LogHelper.Warn<PublishedMediaCache>("The InternalIndexer for examine is configured incorrectly, it should not list any include/exclude node types or field names, it should simply be configured as: " + "<IndexSet SetName=\"InternalIndexSet\" IndexPath=\"~/App_Data/TEMP/ExamineIndexes/Internal/\" />");
|
||||
}
|
||||
return indexer;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<PublishedMediaCache>("Could not retrieve the InternalIndexer", ex);
|
||||
//something didn't work, continue returning null.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
if (eMgr == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
//by default use the InternalSearcher
|
||||
var indexer = eMgr.IndexProviderCollection["InternalIndexer"];
|
||||
if (indexer.IndexerData.IncludeNodeTypes.Any() || indexer.IndexerData.ExcludeNodeTypes.Any())
|
||||
{
|
||||
LogHelper.Warn<PublishedMediaCache>("The InternalIndexer for examine is configured incorrectly, it should not list any include/exclude node types or field names, it should simply be configured as: " + "<IndexSet SetName=\"InternalIndexSet\" IndexPath=\"~/App_Data/TEMP/ExamineIndexes/Internal/\" />");
|
||||
}
|
||||
return indexer;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<PublishedMediaCache>("Could not retrieve the InternalIndexer", ex);
|
||||
//something didn't work, continue returning null.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ILuceneSearcher GetSearchProviderSafe()
|
||||
@@ -154,28 +222,27 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
return _searchProvider;
|
||||
|
||||
var eMgr = GetExamineManagerSafe();
|
||||
if (eMgr != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//by default use the InternalSearcher
|
||||
return eMgr.GetSearcher(Constants.Examine.InternalIndexer);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
|
||||
//See this thread: http://examine.cdodeplex.com/discussions/264341
|
||||
//Catch the exception here for the time being, and just fallback to GetMedia
|
||||
//TODO: Need to fix examine in LB scenarios!
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
//This will occur when the search provider cannot be initialized. In newer examine versions the initialization is lazy and therefore
|
||||
// the manager will return the singleton without throwing initialization errors, however if examine isn't configured correctly a null
|
||||
// reference error will occur because the examine settings are null.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
if (eMgr == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
//by default use the InternalSearcher
|
||||
return eMgr.GetSearcher(Constants.Examine.InternalIndexer);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
|
||||
//See this thread: http://examine.cdodeplex.com/discussions/264341
|
||||
//Catch the exception here for the time being, and just fallback to GetMedia
|
||||
//TODO: Need to fix examine in LB scenarios!
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
//This will occur when the search provider cannot be initialized. In newer examine versions the initialization is lazy and therefore
|
||||
// the manager will return the singleton without throwing initialization errors, however if examine isn't configured correctly a null
|
||||
// reference error will occur because the examine settings are null.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IPublishedContent GetUmbracoMedia(int id)
|
||||
@@ -202,7 +269,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
//first check in Examine as this is WAY faster
|
||||
var criteria = searchProvider.CreateSearchCriteria("media");
|
||||
|
||||
var filter = criteria.Id(id).Not().Field(UmbracoContentIndexer.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
|
||||
var filter = criteria.Id(id).Not().Field(BaseUmbracoIndexer.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
|
||||
//the above filter will create a query like this, NOTE: That since the use of the wildcard, it automatically escapes it in Lucene.
|
||||
//+(+__NodeId:3113 -__Path:-1,-21,*) +__IndexType:media
|
||||
|
||||
@@ -226,14 +293,14 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
"Could not retrieve media {0} from Examine index, reverting to looking up media via legacy library.GetMedia method",
|
||||
() => id);
|
||||
|
||||
var media = global::umbraco.library.GetMedia(id, false);
|
||||
var media = library.GetMedia(id, false);
|
||||
|
||||
return ConvertFromXPathNodeIterator(media, id);
|
||||
}
|
||||
|
||||
internal CacheValues ConvertFromXPathNodeIterator(XPathNodeIterator media, int id)
|
||||
{
|
||||
if (media != null && media.Current != null)
|
||||
if (media?.Current != null)
|
||||
{
|
||||
return media.Current.Name.InvariantEquals("error")
|
||||
? null
|
||||
@@ -249,8 +316,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
internal CacheValues ConvertFromSearchResult(SearchResult searchResult)
|
||||
{
|
||||
// note: fixing fields in 7.x, removed by Shan for 8.0
|
||||
var values = new Dictionary<string, string>(searchResult.Fields);
|
||||
|
||||
|
||||
return new CacheValues
|
||||
{
|
||||
Values = values,
|
||||
@@ -260,7 +328,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
internal CacheValues ConvertFromXPathNavigator(XPathNavigator xpath, bool forceNav = false)
|
||||
{
|
||||
if (xpath == null) throw new ArgumentNullException("xpath");
|
||||
if (xpath == null) throw new ArgumentNullException(nameof(xpath));
|
||||
|
||||
var values = new Dictionary<string, string> {{"nodeName", xpath.GetAttribute("nodeName", "")}};
|
||||
values["nodeTypeAlias"] = xpath.Name;
|
||||
@@ -272,13 +340,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
if (result.Current.MoveToFirstAttribute())
|
||||
{
|
||||
//checking for duplicate keys because of the 'nodeTypeAlias' might already be added above.
|
||||
if (!values.ContainsKey(result.Current.Name))
|
||||
if (values.ContainsKey(result.Current.Name) == false)
|
||||
{
|
||||
values[result.Current.Name] = result.Current.Value;
|
||||
}
|
||||
while (result.Current.MoveToNextAttribute())
|
||||
{
|
||||
if (!values.ContainsKey(result.Current.Name))
|
||||
if (values.ContainsKey(result.Current.Name) == false)
|
||||
{
|
||||
values[result.Current.Name] = result.Current.Value;
|
||||
}
|
||||
@@ -292,9 +360,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
//add the user props
|
||||
while (result.MoveNext())
|
||||
{
|
||||
if (result.Current != null && !result.Current.HasAttributes)
|
||||
if (result.Current != null && result.Current.HasAttributes == false)
|
||||
{
|
||||
string value = result.Current.Value;
|
||||
var value = result.Current.Value;
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (result.Current.HasAttributes || result.Current.SelectChildren(XPathNodeType.Element).Count > 0)
|
||||
@@ -311,16 +379,6 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
Values = values,
|
||||
XPath = forceNav ? xpath : null // outside of tests we do NOT want to cache the navigator!
|
||||
};
|
||||
|
||||
//var content = new DictionaryPublishedContent(values,
|
||||
// d => d.ParentId != -1 //parent should be null if -1
|
||||
// ? GetUmbracoMedia(d.ParentId)
|
||||
// : null,
|
||||
// //callback to return the children of the current node based on the xml structure already found
|
||||
// d => GetChildrenMedia(d.Id, xpath),
|
||||
// GetProperty,
|
||||
// false);
|
||||
//return content.CreateModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -344,7 +402,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
//We are going to check for a special field however, that is because in some cases we store a 'Raw'
|
||||
//value in the index such as for xml/html.
|
||||
var rawValue = dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(UmbracoContentIndexer.RawFieldPrefix + alias));
|
||||
var rawValue = dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(BaseUmbracoIndexer.RawFieldPrefix + alias));
|
||||
return rawValue
|
||||
?? dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias));
|
||||
}
|
||||
@@ -378,7 +436,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
//the above filter will create a query like this, NOTE: That since the use of the wildcard, it automatically escapes it in Lucene.
|
||||
//+(+parentId:3113 -__Path:-1,-21,*) +__IndexType:media
|
||||
|
||||
//sort with the Sort field
|
||||
// sort with the Sort field (updated for 8.0)
|
||||
var results = searchProvider.Find(
|
||||
filter.And().OrderBy(new SortableField("sortOrder", SortType.Int)).Compile());
|
||||
|
||||
@@ -396,14 +454,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
return medias;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if there's no result then return null. Previously we defaulted back to library.GetMedia below
|
||||
//but this will always get called for when we are getting descendents since many items won't have
|
||||
//children and then we are hitting the database again!
|
||||
//So instead we're going to rely on Examine to have the correct results like it should.
|
||||
return Enumerable.Empty<IPublishedContent>();
|
||||
}
|
||||
|
||||
//if there's no result then return null. Previously we defaulted back to library.GetMedia below
|
||||
//but this will always get called for when we are getting descendents since many items won't have
|
||||
//children and then we are hitting the database again!
|
||||
//So instead we're going to rely on Examine to have the correct results like it should.
|
||||
return Enumerable.Empty<IPublishedContent>();
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
@@ -416,7 +472,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
//falling back to get media
|
||||
|
||||
var media = library.GetMedia(parentId, true);
|
||||
if (media != null && media.Current != null)
|
||||
if (media?.Current != null)
|
||||
{
|
||||
xpath = media.Current;
|
||||
}
|
||||
@@ -496,27 +552,33 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
Func<int, IPublishedContent> getParent,
|
||||
Func<int, XPathNavigator, IEnumerable<IPublishedContent>> getChildren,
|
||||
Func<DictionaryPublishedContent, string, IPublishedProperty> getProperty,
|
||||
ICacheProvider cacheProvider,
|
||||
PublishedContentTypeCache contentTypeCache,
|
||||
XPathNavigator nav,
|
||||
bool fromExamine)
|
||||
{
|
||||
if (valueDictionary == null) throw new ArgumentNullException("valueDictionary");
|
||||
if (getParent == null) throw new ArgumentNullException("getParent");
|
||||
if (getProperty == null) throw new ArgumentNullException("getProperty");
|
||||
if (valueDictionary == null) throw new ArgumentNullException(nameof(valueDictionary));
|
||||
if (getParent == null) throw new ArgumentNullException(nameof(getParent));
|
||||
if (getProperty == null) throw new ArgumentNullException(nameof(getProperty));
|
||||
|
||||
_getParent = new Lazy<IPublishedContent>(() => getParent(ParentId));
|
||||
_getChildren = new Lazy<IEnumerable<IPublishedContent>>(() => getChildren(Id, nav));
|
||||
_getProperty = getProperty;
|
||||
_cacheProvider = cacheProvider;
|
||||
|
||||
LoadedFromExamine = fromExamine;
|
||||
|
||||
ValidateAndSetProperty(valueDictionary, val => _id = int.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int!
|
||||
ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key");
|
||||
ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key");
|
||||
//ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId");
|
||||
ValidateAndSetProperty(valueDictionary, val => _sortOrder = int.Parse(val), "sortOrder");
|
||||
ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", LuceneIndexer.NodeTypeAliasFieldName);
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeId = int.Parse(val), "nodeType");
|
||||
//ValidateAndSetProperty(valueDictionary, val => _writerName = val, "writerName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _creatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132
|
||||
//ValidateAndSetProperty(valueDictionary, val => _writerId = int.Parse(val), "writerID");
|
||||
ValidateAndSetProperty(valueDictionary, val => _creatorId = int.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132
|
||||
ValidateAndSetProperty(valueDictionary, val => _path = val, "path", "__Path");
|
||||
ValidateAndSetProperty(valueDictionary, val => _createDate = ParseDateTimeValue(val), "createDate");
|
||||
@@ -532,7 +594,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
}, "parentID");
|
||||
|
||||
_contentType = PublishedContentType.Get(PublishedItemType.Media, _documentTypeAlias);
|
||||
_contentType = contentTypeCache.Get(PublishedItemType.Media, _documentTypeAlias);
|
||||
_properties = new Collection<IPublishedProperty>();
|
||||
|
||||
//handle content type properties
|
||||
@@ -570,194 +632,111 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
private DateTime ParseDateTimeValue(string val)
|
||||
{
|
||||
if (LoadedFromExamine)
|
||||
{
|
||||
//we need to parse the date time using Lucene converters
|
||||
var ticks = long.Parse(val);
|
||||
return new DateTime(ticks);
|
||||
}
|
||||
if (LoadedFromExamine == false)
|
||||
return DateTime.Parse(val);
|
||||
|
||||
return DateTime.Parse(val);
|
||||
//we need to parse the date time using Lucene converters
|
||||
var ticks = long.Parse(val);
|
||||
return new DateTime(ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to get/set if this was laoded from examine cache
|
||||
/// </summary>
|
||||
internal bool LoadedFromExamine { get; private set; }
|
||||
internal bool LoadedFromExamine { get; }
|
||||
|
||||
//private readonly Func<DictionaryPublishedContent, IPublishedContent> _getParent;
|
||||
private readonly Lazy<IPublishedContent> _getParent;
|
||||
//private readonly Func<DictionaryPublishedContent, IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Lazy<IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Func<DictionaryPublishedContent, string, IPublishedProperty> _getProperty;
|
||||
private readonly ICacheProvider _cacheProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Returns 'Media' as the item type
|
||||
/// </summary>
|
||||
public override PublishedItemType ItemType
|
||||
{
|
||||
get { return PublishedItemType.Media; }
|
||||
}
|
||||
public override PublishedItemType ItemType => PublishedItemType.Media;
|
||||
|
||||
public override IPublishedContent Parent
|
||||
{
|
||||
get { return _getParent.Value; }
|
||||
}
|
||||
public override IPublishedContent Parent => _getParent.Value;
|
||||
|
||||
public int ParentId { get; private set; }
|
||||
public override int Id
|
||||
{
|
||||
get { return _id; }
|
||||
}
|
||||
public int ParentId { get; private set; }
|
||||
|
||||
public override Guid Key { get { return _key; } }
|
||||
public override int Id => _id;
|
||||
|
||||
public override int TemplateId
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
public override Guid Key => _key;
|
||||
|
||||
public override int SortOrder
|
||||
{
|
||||
get { return _sortOrder; }
|
||||
}
|
||||
public override int TemplateId => 0;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
public override int SortOrder => _sortOrder;
|
||||
|
||||
public override string UrlName
|
||||
{
|
||||
get { return _urlName; }
|
||||
}
|
||||
public override string Name => _name;
|
||||
|
||||
public override string DocumentTypeAlias
|
||||
{
|
||||
get { return _documentTypeAlias; }
|
||||
}
|
||||
public override string UrlName => _urlName;
|
||||
|
||||
public override int DocumentTypeId
|
||||
{
|
||||
get { return _documentTypeId; }
|
||||
}
|
||||
public override string DocumentTypeAlias => _documentTypeAlias;
|
||||
|
||||
public override string WriterName
|
||||
{
|
||||
get { return _creatorName; }
|
||||
}
|
||||
public override int DocumentTypeId => _documentTypeId;
|
||||
|
||||
public override string CreatorName
|
||||
{
|
||||
get { return _creatorName; }
|
||||
}
|
||||
public override string WriterName => _creatorName;
|
||||
|
||||
public override int WriterId
|
||||
{
|
||||
get { return _creatorId; }
|
||||
}
|
||||
public override string CreatorName => _creatorName;
|
||||
|
||||
public override int CreatorId
|
||||
{
|
||||
get { return _creatorId; }
|
||||
}
|
||||
public override int WriterId => _creatorId;
|
||||
|
||||
public override string Path
|
||||
{
|
||||
get { return _path; }
|
||||
}
|
||||
public override int CreatorId => _creatorId;
|
||||
|
||||
public override DateTime CreateDate
|
||||
{
|
||||
get { return _createDate; }
|
||||
}
|
||||
public override string Path => _path;
|
||||
|
||||
public override DateTime UpdateDate
|
||||
{
|
||||
get { return _updateDate; }
|
||||
}
|
||||
public override DateTime CreateDate => _createDate;
|
||||
|
||||
public override Guid Version
|
||||
{
|
||||
get { return Guid.Empty; }
|
||||
}
|
||||
public override DateTime UpdateDate => _updateDate;
|
||||
|
||||
public override int Level
|
||||
{
|
||||
get { return _level; }
|
||||
}
|
||||
public override Guid Version => Guid.Empty;
|
||||
|
||||
public override bool IsDraft
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public override int Level => _level;
|
||||
|
||||
public override ICollection<IPublishedProperty> Properties
|
||||
{
|
||||
get { return _properties; }
|
||||
}
|
||||
public override bool IsDraft => false;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children
|
||||
{
|
||||
get { return _getChildren.Value; }
|
||||
}
|
||||
public override ICollection<IPublishedProperty> Properties => _properties;
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
public override IEnumerable<IPublishedContent> Children => _getChildren.Value;
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return _getProperty(this, alias);
|
||||
}
|
||||
|
||||
public override PublishedContentType ContentType
|
||||
{
|
||||
get { return _contentType; }
|
||||
}
|
||||
public override PublishedContentType ContentType => _contentType;
|
||||
|
||||
// override to implement cache
|
||||
// override to implement cache
|
||||
// cache at context level, ie once for the whole request
|
||||
// but cache is not shared by requests because we wouldn't know how to clear it
|
||||
public override IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
if (recurse == false) return GetProperty(alias);
|
||||
|
||||
IPublishedProperty property;
|
||||
string key = null;
|
||||
var cache = UmbracoContextCache.Current;
|
||||
|
||||
if (cache != null)
|
||||
{
|
||||
key = string.Format("RECURSIVE_PROPERTY::{0}::{1}", Id, alias.ToLowerInvariant());
|
||||
object o;
|
||||
if (cache.TryGetValue(key, out o))
|
||||
{
|
||||
property = o as IPublishedProperty;
|
||||
if (property == null)
|
||||
throw new InvalidOperationException("Corrupted cache.");
|
||||
return property;
|
||||
}
|
||||
}
|
||||
|
||||
// else get it for real, no cache
|
||||
property = base.GetProperty(alias, true);
|
||||
|
||||
if (cache != null)
|
||||
cache[key] = property;
|
||||
|
||||
return property;
|
||||
var key = $"XmlPublishedCache.PublishedMediaCache:RecursiveProperty-{Id}-{alias.ToLowerInvariant()}";
|
||||
var cacheProvider = _cacheProvider;
|
||||
return cacheProvider.GetCacheItem<IPublishedProperty>(key, () => base.GetProperty(alias, true));
|
||||
}
|
||||
|
||||
private readonly List<string> _keysAdded = new List<string>();
|
||||
private int _id;
|
||||
private Guid _key;
|
||||
//private int _templateId;
|
||||
private int _sortOrder;
|
||||
private string _name;
|
||||
private string _urlName;
|
||||
private string _documentTypeAlias;
|
||||
private int _documentTypeId;
|
||||
private int _documentTypeId;
|
||||
//private string _writerName;
|
||||
private string _creatorName;
|
||||
//private int _writerId;
|
||||
private int _creatorId;
|
||||
private string _path;
|
||||
private DateTime _createDate;
|
||||
private DateTime _updateDate;
|
||||
//private Guid _version;
|
||||
private int _level;
|
||||
private readonly ICollection<IPublishedProperty> _properties;
|
||||
private readonly PublishedContentType _contentType;
|
||||
@@ -775,6 +754,34 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
internal void Resync()
|
||||
{
|
||||
// clear recursive properties cached by XmlPublishedContent.GetProperty
|
||||
// assume that nothing else is going to cache IPublishedProperty items (else would need to do ByKeySearch)
|
||||
// NOTE all properties cleared when clearing the content cache (see content cache)
|
||||
//_cacheProvider.ClearCacheObjectTypes<IPublishedProperty>();
|
||||
//_cacheProvider.ClearCacheByKeySearch("XmlPublishedCache.PublishedMediaCache:RecursiveProperty-");
|
||||
}
|
||||
|
||||
#region Content types
|
||||
|
||||
public override PublishedContentType GetContentType(int id)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Media, id);
|
||||
}
|
||||
|
||||
public override PublishedContentType GetContentType(string alias)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Media, alias);
|
||||
}
|
||||
|
||||
public override IEnumerable<IPublishedContent> GetByContentType(PublishedContentType contentType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// REFACTORING
|
||||
|
||||
// caching the basic atomic values - and the parent id
|
||||
@@ -817,6 +824,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
parentId => parentId < 0 ? null : GetUmbracoMedia(parentId),
|
||||
GetChildrenMedia,
|
||||
GetProperty,
|
||||
_cacheProvider,
|
||||
_contentTypeCache,
|
||||
cacheValues.XPath, // though, outside of tests, that should be null
|
||||
cacheValues.FromExamine
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user