public DecompressedLeafPage DecompressPage(TreePage p, DecompressionUsage usage = DecompressionUsage.Read, bool skipCache = false) { var input = new DecompressionInput(p.CompressionHeader, p); DecompressedLeafPage decompressedPage; DecompressedLeafPage cached = null; if (skipCache == false && DecompressionsCache.TryGet(p.PageNumber, usage, out cached)) { decompressedPage = ReuseCachedPage(cached, usage, ref input); if (usage == DecompressionUsage.Read) { return(decompressedPage); } } else { decompressedPage = DecompressFromBuffer(usage, ref input); } Debug.Assert(decompressedPage.NumberOfEntries > 0); try { if (p.NumberOfEntries == 0) { return(decompressedPage); } HandleUncompressedNodes(decompressedPage, p, usage); return(decompressedPage); } finally { decompressedPage.DebugValidate(this, State.RootPageNumber); if (skipCache == false && decompressedPage != cached) { DecompressionsCache.Invalidate(p.PageNumber, usage); DecompressionsCache.Add(decompressedPage); } } }
private DecompressedLeafPage DecompressFromBuffer(DecompressionUsage usage, ref DecompressionInput input) { var result = _llt.Environment.DecompressionBuffers.GetPage(_llt, input.DecompressedPageSize, usage, input.Page); var decompressedNodesOffset = (ushort)(result.PageSize - input.DecompressedSize); LZ4.Decode64LongBuffers( input.Data, input.CompressedSize, result.Base + decompressedNodesOffset, input.DecompressedSize, true); result.Lower += input.KeysOffsetsSize; result.Upper = decompressedNodesOffset; for (var i = 0; i < input.NumberOfEntries; i++) { result.KeysOffsets[i] = (ushort)(input.KeysOffsets[i] + result.Upper); } return(result); }
private DecompressedLeafPage ReuseCachedPage(DecompressedLeafPage cached, DecompressionUsage usage, ref DecompressionInput input) { DecompressedLeafPage result; var sizeDiff = input.DecompressedPageSize - cached.PageSize; if (sizeDiff > 0) { result = _llt.Environment.DecompressionBuffers.GetPage(_llt, input.DecompressedPageSize, usage, input.Page); Memory.Copy(result.Base, cached.Base, cached.Lower); Memory.Copy(result.Base + cached.Upper + sizeDiff, cached.Base + cached.Upper, cached.PageSize - cached.Upper); result.Upper += (ushort)sizeDiff; for (var i = 0; i < result.NumberOfEntries; i++) { result.KeysOffsets[i] += (ushort)sizeDiff; } } else { result = cached; } return(result); }