internal async ValueTask <MatchResult> FindBestMatch(ReadOnlyMemory <byte> key) { LTrieNodeStruct gn = await ReadNodeStruct(); LTrieNodeStruct prev = default; if (key.Length == 0) { return(await CreateMatchResult(0, gn.GetInternalLinkObject(), gn, prev)); } for (int i = 0; i < key.Length; i++) { LTrieNodeExternalLinkStruct externalLink = default; if (key.Span[i] == gn.FirstExternalLink.Value) { externalLink = gn.FirstExternalLink; } else if (gn.ExternalLinkSlotCount > 1) { externalLink = await GetRemainingExternalLink(gn, key.Span[i]); } if (externalLink.Pointer == 0) { var result = await CreateMatchResult(i, null, gn, prev); result.MissingValue = key.Span[i]; result.KeyIndex = i; return(result); } if (!externalLink.LinkToNode) { var result = await CreateMatchResult(i, externalLink.ToLinkObject(), gn, prev); result.KeyIndex = i; return(result); } prev = gn; gn = await ReadNodeStruct(externalLink.Pointer); } return(await CreateMatchResult(key.Length, gn.GetInternalLinkObject(), gn, prev)); }
private async ValueTask <LTrieNode> ToLTrieNodeObject(LTrieNodeStruct nodeStruct, int minKeyLength) { LTrieNode?cached = null; NodeCache?.TryGetValue(nodeStruct.OwnPointer, out cached); if (cached is LTrieNode) { if (cached.MinKeyLength != minKeyLength) { throw new InvalidOperationException("Inconsistent depth, bug in DBTrie"); } if (cached.OwnPointer != nodeStruct.OwnPointer) { throw new InvalidOperationException("Inconsistent pointer in cache, bug in DBTrie"); } await cached.AssertConsistency(); return(cached); } var node = await FetchNodeFromStruct(nodeStruct, minKeyLength); NodeCache?.Add(nodeStruct.OwnPointer, node); return(node); }
private async ValueTask <LTrieNodeExternalLinkStruct> GetRemainingExternalLink(LTrieNodeStruct gn, byte value) { IMemoryOwner <byte>?owner = null; var restLength = gn.GetRestLength(); var secondLinkPointer = gn.GetSecondExternalLinkOwnPointer(); if (!Storage.TryDirectRead(secondLinkPointer, restLength, out var memory)) { owner = MemoryPool.Rent(restLength); var outputMemory = owner.Memory.Slice(0, restLength); await Storage.Read(secondLinkPointer, outputMemory); memory = outputMemory; } for (int linkIndex = 0; linkIndex < gn.ExternalLinkSlotCount - 1; linkIndex++) { var linkOwnPointer = secondLinkPointer + linkIndex * Sizes.ExternalLinkLength; var l = new LTrieNodeExternalLinkStruct(linkOwnPointer, memory.Span.Slice(linkIndex * Sizes.ExternalLinkLength, Sizes.ExternalLinkLength)); if (l.Pointer != 0 && l.Value == value) { owner?.Dispose(); return(l); } } owner?.Dispose(); return(default);