Cleans up some code, adds code comments

This commit is contained in:
Shannon
2020-08-13 22:15:09 +10:00
parent 0d159751b9
commit 07de0876e7
12 changed files with 135 additions and 68 deletions

View File

@@ -3,18 +3,21 @@ using CSharpTest.Net.Serialization;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
class ContentDataSerializer : ISerializer<ContentData>
/// <summary>
/// Serializes/Deserializes data to BTree data source for <see cref="ContentData"/>
/// </summary>
internal class ContentDataSerializer : ISerializer<ContentData>
{
public ContentDataSerializer(IDictionaryOfPropertyDataSerializer dictionaryOfPropertyDataSerializer = null)
{
_dictionaryOfPropertyDataSerializer = dictionaryOfPropertyDataSerializer;
if(_dictionaryOfPropertyDataSerializer == null)
{
_dictionaryOfPropertyDataSerializer = PropertiesSerializer;
_dictionaryOfPropertyDataSerializer = DefaultPropertiesSerializer;
}
}
private static readonly DictionaryOfPropertyDataSerializer PropertiesSerializer = new DictionaryOfPropertyDataSerializer();
private static readonly DictionaryOfCultureVariationSerializer CultureVariationsSerializer = new DictionaryOfCultureVariationSerializer();
private static readonly DictionaryOfPropertyDataSerializer DefaultPropertiesSerializer = new DictionaryOfPropertyDataSerializer();
private static readonly DictionaryOfCultureVariationSerializer DefaultCultureVariationsSerializer = new DictionaryOfCultureVariationSerializer();
private readonly IDictionaryOfPropertyDataSerializer _dictionaryOfPropertyDataSerializer;
public ContentData ReadFrom(Stream stream)
@@ -29,7 +32,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
WriterId = PrimitiveSerializer.Int32.ReadFrom(stream),
TemplateId = PrimitiveSerializer.Int32.ReadFrom(stream),
Properties = _dictionaryOfPropertyDataSerializer.ReadFrom(stream), // TODO: We don't want to allocate empty arrays
CultureInfos = CultureVariationsSerializer.ReadFrom(stream) // TODO: We don't want to allocate empty arrays
CultureInfos = DefaultCultureVariationsSerializer.ReadFrom(stream) // TODO: We don't want to allocate empty arrays
};
}
@@ -46,7 +49,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
PrimitiveSerializer.Int32.WriteTo(value.TemplateId.Value, stream);
}
_dictionaryOfPropertyDataSerializer.WriteTo(value.Properties, stream);
CultureVariationsSerializer.WriteTo(value.CultureInfos, stream);
DefaultCultureVariationsSerializer.WriteTo(value.CultureInfos, stream);
}
}
}

View File

@@ -6,6 +6,9 @@ using Umbraco.Core;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// Serializes/Deserializes culture variant data as a dictionary for BTree
/// </summary>
internal class DictionaryOfCultureVariationSerializer : SerializerBase, ISerializer<IReadOnlyDictionary<string, CultureVariation>>
{
public IReadOnlyDictionary<string, CultureVariation> ReadFrom(Stream stream)

View File

@@ -6,6 +6,9 @@ using Umbraco.Core;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// Serializes/Deserializes property data as a dictionary for BTree
/// </summary>
internal class DictionaryOfPropertyDataSerializer : SerializerBase, ISerializer<IDictionary<string, PropertyData[]>>, IDictionaryOfPropertyDataSerializer
{
public IDictionary<string, PropertyData[]> ReadFrom(Stream stream)

View File

@@ -3,7 +3,9 @@ using System.Collections.Generic;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
// represents everything that is specific to edited or published version
/// <summary>
/// Represents everything that is specific to an edited or published content version
/// </summary>
internal class ContentData
{
public string Name { get; set; }

View File

@@ -1,19 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
// TODO: We need a better name, not sure why the class is called ContentNested in the first place
// TODO: We need better names if possible, not sure why the class is called ContentNested in the first place
/// <summary>
/// Serializes/Deserializes <see cref="ContentNestedData"/> document to the SQL Database as bytes
/// </summary>
public interface IContentNestedDataByteSerializer : IContentNestedDataSerializer
{
ContentNestedData DeserializeBytes(byte[] data);
byte[] SerializeBytes(ContentNestedData nestedData);
}
// TODO: We need a better name, not sure why the class is called ContentNested in the first place
/// <summary>
/// Serializes/Deserializes <see cref="ContentNestedData"/> document to the SQL Database as a string
/// </summary>
public interface IContentNestedDataSerializer
{
ContentNestedData Deserialize(string data);

View File

@@ -13,6 +13,8 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
/// </summary>
internal class LazyCompressedString
{
// TODO: This could be a struct
private byte[] _bytes;
private string _str;

View File

@@ -9,26 +9,10 @@ using K4os.Compression.LZ4;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// If/where to compress custom properties for nucache
/// </summary>
public enum NucachePropertyCompressionLevel
{
None = 0,
SQLDatabase = 1,
NuCacheDatabase = 2
}
/// <summary>
/// If/where to decompress custom properties for nucache
/// </summary>
public enum NucachePropertyDecompressionLevel
{
NotCompressed = 0,
Immediate = 1,
Lazy = 2
}
/// <summary>
/// Serializes/Deserializes property data as a dictionary for BTree with Lz4 compression options
/// </summary>
internal class Lz4DictionaryOfPropertyDataSerializer : SerializerBase, ISerializer<IDictionary<string, PropertyData[]>>, IDictionaryOfPropertyDataSerializer
{
private readonly IReadOnlyDictionary<string, NuCacheCompressionOptions> _compressProperties;
@@ -58,7 +42,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
// read property alias
var alias = PrimitiveSerializer.String.ReadFrom(stream);
var map = GetDeSerializationMap(alias);
var map = GetDeserializationMap(alias);
var key = string.Intern(map.MappedAlias ?? alias);
// read values count
@@ -82,23 +66,30 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
pdata.Segment = ReadStringObject(stream, true) ?? string.Empty;
pdata.Value = ReadObject(stream);
if ((map.CompressLevel.Equals(NucachePropertyCompressionLevel.NuCacheDatabase) || map.CompressLevel.Equals(NucachePropertyCompressionLevel.SQLDatabase))
&& pdata.Value != null && pdata.Value is byte[] byteArrayValue)
{
//Compressed string
switch (map.DecompressLevel)
{
case NucachePropertyDecompressionLevel.Lazy:
pdata.Value = new LazyCompressedString(byteArrayValue);
break;
case NucachePropertyDecompressionLevel.NotCompressed:
break;//Shouldn't be any not compressed
case NucachePropertyDecompressionLevel.Immediate:
default:
pdata.Value = Encoding.UTF8.GetString(LZ4Pickler.Unpickle(byteArrayValue));
break;
}
}
switch (map.CompressLevel)
{
case NucachePropertyCompressionLevel.SQLDatabase:
case NucachePropertyCompressionLevel.NuCacheDatabase:
if (!(pdata.Value is null) && pdata.Value is byte[] byteArrayValue)
{
//Compressed string
switch (map.DecompressLevel)
{
case NucachePropertyDecompressionLevel.Lazy:
pdata.Value = new LazyCompressedString(byteArrayValue);
break;
case NucachePropertyDecompressionLevel.NotCompressed:
//Shouldn't be any not compressed
// TODO: Do we need to throw here?
break;
case NucachePropertyDecompressionLevel.Immediate:
default:
pdata.Value = Encoding.UTF8.GetString(LZ4Pickler.Unpickle(byteArrayValue));
break;
}
}
break;
}
}
dict[key] = pdatas.ToArray();
@@ -131,17 +122,30 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
WriteObject(pdata.Culture ?? string.Empty, stream);
WriteObject(pdata.Segment ?? string.Empty, stream);
//Only compress strings
if (pdata.Value is string stringValue && pdata.Value != null && map.CompressLevel.Equals(NucachePropertyCompressionLevel.NuCacheDatabase)
&& (_nucachePropertyOptions.MinimumCompressibleStringLength == null
|| !_nucachePropertyOptions.MinimumCompressibleStringLength.HasValue
|| stringValue.Length > _nucachePropertyOptions.MinimumCompressibleStringLength.Value))
//Only compress strings
switch (map.CompressLevel)
{
var stringBytes = Encoding.UTF8.GetBytes(stringValue);
var compressedBytes = LZ4Pickler.Pickle(stringBytes, _nucachePropertyOptions.LZ4CompressionLevel);
WriteObject(compressedBytes, stream);
// If we're compressing into btree at the property level
case NucachePropertyCompressionLevel.NuCacheDatabase:
if (pdata.Value is string stringValue && !(pdata.Value is null)
&& (_nucachePropertyOptions.MinimumCompressibleStringLength is null
|| !_nucachePropertyOptions.MinimumCompressibleStringLength.HasValue
|| stringValue.Length > _nucachePropertyOptions.MinimumCompressibleStringLength.Value))
{
var stringBytes = Encoding.UTF8.GetBytes(stringValue);
var compressedBytes = LZ4Pickler.Pickle(stringBytes, _nucachePropertyOptions.LZ4CompressionLevel);
WriteObject(compressedBytes, stream);
}
else
{
WriteObject(pdata.Value, stream);
}
break;
default:
WriteObject(pdata.Value, stream);
break;
}
WriteObject(pdata.Value, stream);
}
}
}
@@ -150,7 +154,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
public NuCacheCompressionOptions GetSerializationMap(string propertyAlias)
{
if (_compressProperties == null)
if (_compressProperties is null)
{
return DefaultMap;
}
@@ -161,9 +165,9 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
return DefaultMap;
}
public NuCacheCompressionOptions GetDeSerializationMap(string propertyAlias)
public NuCacheCompressionOptions GetDeserializationMap(string propertyAlias)
{
if (_uncompressProperties == null)
if (_uncompressProperties is null)
{
return DefaultMap;
}

View File

@@ -9,6 +9,9 @@ using System.Text;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// Serializes/Deserializes <see cref="ContentNestedData"/> document to the SQL Database as bytes using MessagePack
/// </summary>
internal class MsgPackContentNestedDataSerializer : IContentNestedDataByteSerializer
{
private MessagePackSerializerOptions _options;
@@ -65,7 +68,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
/// <param name="nestedData"></param>
private void Optimize(ContentNestedData nestedData)
{
if (_propertyOptions.PropertyMap != null && _propertyOptions.PropertyMap.Any())
if (_propertyOptions.PropertyMap != null && _propertyOptions.PropertyMap.Count > 0)
{
foreach (var map in _propertyOptions.PropertyMap)
{
@@ -79,10 +82,13 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
}
}
}
// if there is an alias map for this property then use that instead of the real property alias
// (used to save memory, the mapped alias is normally a single char or at least a smaller string)
if (map.Value.MappedAlias != null && !map.Key.Equals(map.Value.MappedAlias)
&& nestedData.PropertyData.Remove(map.Key) && nestedData.PropertyData.TryGetValue(map.Key, out PropertyData[] properties2))
&& nestedData.PropertyData.Remove(map.Key)
&& nestedData.PropertyData.TryGetValue(map.Key, out PropertyData[] properties2))
{
nestedData.PropertyData.Remove(map.Key);
nestedData.PropertyData.Add(map.Value.MappedAlias, properties2);
}
}

View File

@@ -14,6 +14,13 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
public NucachePropertyCompressionLevel CompressLevel { get; private set; }
public NucachePropertyDecompressionLevel DecompressLevel { get; private set; }
/// <summary>
/// Used to map a real property alias to a shorter moniker in memory
/// </summary>
/// <remarks>
/// This is simply a memory saving mechanism
/// </remarks>
public string MappedAlias { get; private set; }
public override bool Equals(object obj)

View File

@@ -0,0 +1,23 @@
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// If/where to compress custom properties for nucache
/// </summary>
public enum NucachePropertyCompressionLevel
{
None = 0,
/// <summary>
/// Compress property data at the nucache SQL DB table level
/// </summary>
/// <remarks>
/// Only necessary if the document in the nucache SQL DB table isn't stored as compressed bytes
/// </remarks>
SQLDatabase = 1,
/// <summary>
/// Compress property data at the nucache BTree level
/// </summary>
NuCacheDatabase = 2
}
}

View File

@@ -0,0 +1,12 @@
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
/// <summary>
/// If/where to decompress custom properties for nucache
/// </summary>
public enum NucachePropertyDecompressionLevel
{
NotCompressed = 0,
Immediate = 1,
Lazy = 2
}
}