Variants - invariant segments, property values

This commit is contained in:
Stephan
2017-12-27 15:10:52 +01:00
parent 26f02ea6f2
commit 3be8f9f645
6 changed files with 145 additions and 108 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using Umbraco.Core.Cache;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web.PublishedCache.NuCache.DataSource;
@@ -21,12 +22,15 @@ namespace Umbraco.Web.PublishedCache.NuCache
private readonly object _locko = new object();
// the invariant-neutral source and inter values
private readonly object _sourceValue;
private bool _interInitialized;
private object _interValue;
private List<PropertyValue> _sourceVValues;
// the variant source and inter values
private Dictionary<CompositeIntStringKey, SourceInterValue> _sourceValues;
// the variant and non-variant object values
private CacheValues _cacheValues;
private string _valuesCacheKey;
@@ -51,9 +55,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
}
else
{
if (_sourceVValues == null)
_sourceVValues = new List<PropertyValue>();
_sourceVValues.Add(new PropertyValue { LanguageId = sourceValue.LanguageId, Segment = sourceValue.Segment, SourceValue = sourceValue.Value });
if (_sourceValues == null)
_sourceValues = new Dictionary<CompositeIntStringKey, SourceInterValue>();
_sourceValues[new CompositeIntStringKey(sourceValue.LanguageId, sourceValue.Segment)]
= new SourceInterValue { LanguageId = sourceValue.LanguageId, Segment = sourceValue.Segment, SourceValue = sourceValue.Value };
}
}
}
@@ -70,7 +75,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
: base(origin.PropertyType, origin.ReferenceCacheLevel)
{
_sourceValue = origin._sourceValue;
_sourceVValues = origin._sourceVValues;
_sourceValues = origin._sourceValues;
_contentUid = origin._contentUid;
_content = content;
@@ -143,22 +148,19 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (languageId == null && segment == null)
{
if (_interInitialized) return _interValue;
_interValue = PropertyType.ConvertSourceToInter(_content, _sourceValue, _isPreviewing);
_interInitialized = true;
return _interValue;
}
if (_sourceVValues == null)
_sourceVValues = new List<PropertyValue>();
if (_sourceValues == null)
_sourceValues = new Dictionary<CompositeIntStringKey, SourceInterValue>();
var vvalue = _sourceVValues.FirstOrDefault(x => x.LanguageId == languageId && x.Segment == segment);
if (vvalue == null)
_sourceVValues.Add(vvalue = new PropertyValue { LanguageId = languageId, Segment = segment });
var k = new CompositeIntStringKey(languageId, segment);
if (!_sourceValues.TryGetValue(k, out var vvalue))
_sourceValues[k] = vvalue = new SourceInterValue { LanguageId = languageId, Segment = segment };
if (vvalue.InterInitialized) return vvalue.InterValue;
vvalue.InterValue = PropertyType.ConvertSourceToInter(_content, vvalue.SourceValue, _isPreviewing);
vvalue.InterInitialized = true;
return vvalue.InterValue;
@@ -169,13 +171,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (languageId == null && segment == null)
return _sourceValue;
List<PropertyValue> vvalues;
lock (_locko)
{
vvalues = _sourceVValues;
if (_sourceValues == null) return null;
return _sourceValues.TryGetValue(new CompositeIntStringKey(languageId, segment), out var sourceValue) ? sourceValue.SourceValue : null;
}
return vvalues?.FirstOrDefault(x => x.LanguageId == languageId && x.Segment == segment);
}
public override object GetValue(int? languageId = null, string segment = null)
@@ -183,10 +183,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
lock (_locko)
{
var cacheValues = GetCacheValues(PropertyType.CacheLevel).For(languageId, segment);
if (cacheValues.ObjectInitialized) return cacheValues.ObjectValue;
// initial reference cache level always is .Content
cacheValues.ObjectValue = PropertyType.ConvertInterToObject(_content, PropertyCacheLevel.Element, GetInterValue(languageId, segment), _isPreviewing);
const PropertyCacheLevel initialCacheLevel = PropertyCacheLevel.Element;
if (cacheValues.ObjectInitialized) return cacheValues.ObjectValue;
cacheValues.ObjectValue = PropertyType.ConvertInterToObject(_content, initialCacheLevel, GetInterValue(languageId, segment), _isPreviewing);
cacheValues.ObjectInitialized = true;
return cacheValues.ObjectValue;
}
@@ -197,10 +199,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
lock (_locko)
{
var cacheValues = GetCacheValues(PropertyType.CacheLevel).For(languageId, segment);
if (cacheValues.XPathInitialized) return cacheValues.XPathValue;
// initial reference cache level always is .Content
cacheValues.XPathValue = PropertyType.ConvertInterToXPath(_content, PropertyCacheLevel.Element, GetInterValue(languageId, segment), _isPreviewing);
const PropertyCacheLevel initialCacheLevel = PropertyCacheLevel.Element;
if (cacheValues.XPathInitialized) return cacheValues.XPathValue;
cacheValues.XPathValue = PropertyType.ConvertInterToXPath(_content, initialCacheLevel, GetInterValue(languageId, segment), _isPreviewing);
cacheValues.XPathInitialized = true;
return cacheValues.XPathValue;
}
@@ -208,40 +212,45 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region Classes
private class CacheValues
private class CacheValue
{
private int? _languageId;
private string _segment;
public bool ObjectInitialized { get; set; }
public object ObjectValue { get; set; }
public bool XPathInitialized { get; set; }
public object XPathValue { get; set; }
}
public bool ObjectInitialized;
public object ObjectValue;
public bool XPathInitialized;
public object XPathValue;
private List<CacheValues> _values;
private class CacheValues : CacheValue
{
private Dictionary<CompositeIntStringKey, CacheValue> _values;
// this is always invoked from within a lock, so does not require its own lock
public CacheValues For(int? languageId, string segment)
public CacheValue For(int? languageId, string segment)
{
if (languageId == null && segment == null)
return this;
if (_values == null)
_values = new List<CacheValues>();
_values = new Dictionary<CompositeIntStringKey, CacheValue>();
var values = _values.FirstOrDefault(x => x._languageId == languageId && x._segment == segment);
var k = new CompositeIntStringKey(languageId, segment);
if (!_values.TryGetValue(k, out var value))
_values[k] = value = new CacheValue();
if (values == null)
_values.Add(values = new CacheValues { _languageId = languageId, _segment = segment });
return values;
return value;
}
}
private class PropertyValue
private class SourceInterValue
{
private string _segment;
public int? LanguageId { get; set; }
public string Segment { get; set; }
public string Segment
{
get => _segment;
internal set => _segment = value?.ToLowerInvariant();
}
public object SourceValue { get; set; }
public bool InterInitialized { get; set; }
public object InterValue { get; set; }