diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/LazyCompressedString.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/LazyCompressedString.cs index 3e0e796d36..2be2568f7e 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/LazyCompressedString.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/LazyCompressedString.cs @@ -1,5 +1,6 @@ using K4os.Compression.LZ4; using System; +using System.Diagnostics; using System.Text; using Umbraco.Core.Exceptions; @@ -8,6 +9,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource /// /// Lazily decompresses a LZ4 Pickler compressed UTF8 string /// + [DebuggerDisplay("{Display}")] internal struct LazyCompressedString { private byte[] _bytes; @@ -22,29 +24,85 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource { _locker = new object(); _bytes = bytes; - _str = null; + _str = null; } public byte[] GetBytes() { if (_bytes == null) + { throw new InvalidOperationException("The bytes have already been expanded"); + } + return _bytes; } - public override string ToString() + /// + /// Returns the decompressed string from the bytes. This methods can only be called once. + /// + /// + /// Throws if this is called more than once + public string DecompressString() { - if (_str != null) return _str; + if (_str != null) + { + return _str; + } + lock (_locker) { - if (_str != null) return _str; // double check - if (_bytes == null) throw new PanicException("Bytes have already been cleared"); + if (_str != null) + { + // double check + return _str; + } + + if (_bytes == null) + { + throw new InvalidOperationException("Bytes have already been cleared"); + } + _str = Encoding.UTF8.GetString(LZ4Pickler.Unpickle(_bytes)); _bytes = null; } return _str; } + /// + /// Used to display debugging output since ToString() can only be called once + /// + private string Display + { + get + { + if (_str != null) + { + return $"Decompressed: {_str}"; + } + + lock (_locker) + { + if (_str != null) + { + // double check + return $"Decompressed: {_str}"; + } + + if (_bytes == null) + { + // This shouldn't happen + throw new PanicException("Bytes have already been cleared"); + } + else + { + return $"Compressed Bytes: {_bytes.Length}"; + } + } + } + } + + public override string ToString() => DecompressString(); + public static implicit operator string(LazyCompressedString l) => l.ToString(); }