private bool TryUseExistingPrefix(MemorySlice key, out PrefixedSlice prefixedSlice) { if (_prefixSection->NextPrefixId < 1) { prefixedSlice = null; return(false); } var prefix = new PrefixNode(); BestPrefixMatch bestMatch = null; for (byte prefixId = 0; prefixId < _prefixSection->NextPrefixId; prefixId++) { AssertPrefixNode(prefixId); prefix.Set(_base + _prefixSection->PrefixOffsets[prefixId], PageNumber); var length = key.FindPrefixSize(new Slice(prefix.ValuePtr, prefix.PrefixLength)); if (length == 0) { continue; } if (length == prefix.PrefixLength) // full prefix usage { prefixedSlice = new PrefixedSlice(prefixId, length, key.Skip(length)); return(true); } // keep on looking for a better prefix if (bestMatch == null) { bestMatch = new BestPrefixMatch { PrefixId = prefixId, PrefixUsage = length }; } else if (length > bestMatch.PrefixUsage) { bestMatch.PrefixId = prefixId; bestMatch.PrefixUsage = length; } } if (bestMatch != null && bestMatch.PrefixUsage > MinPrefixLength(key)) { prefixedSlice = new PrefixedSlice(bestMatch.PrefixId, bestMatch.PrefixUsage, key.Skip(bestMatch.PrefixUsage)); return(true); } prefixedSlice = null; return(false); }
public PrefixNode[] GetPrefixes() { var prefixes = new PrefixNode[_prefixSection->NextPrefixId]; for (byte prefixId = 0; prefixId < _prefixSection->NextPrefixId; prefixId++) { var prefix = new PrefixNode(); prefix.Set(_base + _prefixSection->PrefixOffsets[prefixId], PageNumber); prefixes[prefixId] = prefix; } return(prefixes); }
private void Defrag(Transaction tx) { TemporaryPage tmp; using (tx.Environment.GetTemporaryPage(tx, out tmp)) { var tempPage = tmp.GetTempPage(KeysPrefixed); MemoryUtils.Copy(tempPage.Base, Base, _pageSize); var numberOfEntries = NumberOfEntries; Upper = KeysPrefixed ? (ushort)(_pageSize - Constants.PrefixInfoSectionSize) : _pageSize; for (int i = 0; i < numberOfEntries; i++) { var node = tempPage.GetNode(i); var size = node->GetNodeSize() - Constants.NodeOffsetSize; size += size & 1; MemoryUtils.Copy(Base + Upper - size, (byte *)node, size); Upper -= (ushort)size; KeysOffsets[i] = Upper; } if (KeysPrefixed == false) { return; } var prefixNode = new PrefixNode(); for (byte i = 0; i < _prefixSection->NextPrefixId; i++) { tempPage.AssertPrefixNode(i); prefixNode.Set(tempPage._base + tempPage._prefixSection->PrefixOffsets[i], tempPage.PageNumber); var prefixNodeSize = Constants.PrefixNodeHeaderSize + prefixNode.PrefixLength; prefixNodeSize += prefixNodeSize & 1; MemoryUtils.Copy(Base + Upper - prefixNodeSize, prefixNode.Base, prefixNodeSize); Upper -= (ushort)prefixNodeSize; _prefixSection->PrefixOffsets[i] = Upper; } } }
public int CalcSizeUsed() { var size = 0; for (int i = 0; i < NumberOfEntries; i++) { var node = GetNode(i); var nodeSize = node->GetNodeSize(); size += nodeSize + (nodeSize & 1); } if (KeysPrefixed) { PrefixNode prefixNode = null; for (byte i = 0; i < _prefixSection->NextPrefixId; i++) { if (prefixNode == null) { prefixNode = new PrefixNode(); } AssertPrefixNode(i); prefixNode.Set(_base + _prefixSection->PrefixOffsets[i], PageNumber); var prefixNodeSize = Constants.PrefixNodeHeaderSize + prefixNode.PrefixLength; size += prefixNodeSize + (prefixNodeSize & 1); } size += Constants.PrefixInfoSectionSize; } Debug.Assert(size <= _pageSize); Debug.Assert(SizeUsed >= size); return(size); }
private void Defrag(Transaction tx) { TemporaryPage tmp; using (tx.Environment.GetTemporaryPage(tx, out tmp)) { var tempPage = tmp.GetTempPage(KeysPrefixed); Memory.Copy(tempPage.Base, Base, _pageSize); var numberOfEntries = NumberOfEntries; Upper = KeysPrefixed ? (ushort) (_pageSize - Constants.PrefixInfoSectionSize) : _pageSize; for (int i = 0; i < numberOfEntries; i++) { var node = tempPage.GetNode(i); var size = node->GetNodeSize() - Constants.NodeOffsetSize; size += size & 1; Memory.Copy(Base + Upper - size, (byte*)node, size); Upper -= (ushort) size; KeysOffsets[i] = Upper; } if (KeysPrefixed == false) return; var prefixNode = new PrefixNode(); for (byte i = 0; i < _prefixSection->NextPrefixId; i++) { tempPage.AssertPrefixNode(i); prefixNode.Set(tempPage._base + tempPage._prefixSection->PrefixOffsets[i], tempPage.PageNumber); var prefixNodeSize = Constants.PrefixNodeHeaderSize + prefixNode.PrefixLength; prefixNodeSize += prefixNodeSize & 1; Memory.Copy(Base + Upper - prefixNodeSize, prefixNode.Base, prefixNodeSize); Upper -= (ushort) prefixNodeSize; _prefixSection->PrefixOffsets[i] = Upper; } } }
private bool TryUseExistingPrefix(MemorySlice key, out PrefixedSlice prefixedSlice) { if (_prefixSection->NextPrefixId < 1) { prefixedSlice = null; return false; } BestPrefixMatch bestMatch = null; for (byte prefixId = 0; prefixId < _prefixSection->NextPrefixId; prefixId++) { AssertPrefixNode(prefixId); var prefix = new PrefixNode(); prefix.Set(_base + _prefixSection->PrefixOffsets[prefixId], PageNumber); var length = key.FindPrefixSize(new Slice(prefix.ValuePtr, prefix.PrefixLength)); if (length == 0) continue; if (length == prefix.PrefixLength) // full prefix usage { prefixedSlice = new PrefixedSlice(prefixId, length, key.Skip(length)) { Prefix = prefix }; return true; } // keep on looking for a better prefix if (bestMatch == null) { bestMatch = new BestPrefixMatch { PrefixId = prefixId, PrefixUsage = length, PrefixNode = prefix }; } else if (length > bestMatch.PrefixUsage) { bestMatch.PrefixId = prefixId; bestMatch.PrefixUsage = length; bestMatch.PrefixNode = prefix; } } if (bestMatch != null && bestMatch.PrefixUsage > MinPrefixLength(key)) { prefixedSlice = new PrefixedSlice(bestMatch.PrefixId, bestMatch.PrefixUsage, key.Skip(bestMatch.PrefixUsage)) { Prefix = bestMatch.PrefixNode }; return true; } prefixedSlice = null; return false; }
public PrefixNode[] GetPrefixes() { var prefixes = new PrefixNode[_prefixSection->NextPrefixId]; for (byte prefixId = 0; prefixId < _prefixSection->NextPrefixId; prefixId++) { var prefix = new PrefixNode(); prefix.Set(_base + _prefixSection->PrefixOffsets[prefixId], PageNumber); prefixes[prefixId] = prefix; } return prefixes; }
public int CalcSizeUsed() { var size = 0; for (int i = 0; i < NumberOfEntries; i++) { var node = GetNode(i); var nodeSize = node->GetNodeSize(); size += nodeSize + (nodeSize & 1); } if (KeysPrefixed) { PrefixNode prefixNode = null; for (byte i = 0; i < _prefixSection->NextPrefixId; i++) { if (prefixNode == null) prefixNode = new PrefixNode(); AssertPrefixNode(i); prefixNode.Set(_base + _prefixSection->PrefixOffsets[i], PageNumber); var prefixNodeSize = Constants.PrefixNodeHeaderSize + prefixNode.PrefixLength; size += prefixNodeSize + (prefixNodeSize & 1); } size += Constants.PrefixInfoSectionSize; } Debug.Assert(size <= _pageSize); Debug.Assert(SizeUsed >= size); return size; }
private int AdjustSplitPosition(int currentIndex, int splitIndex, PrefixNode[] prefixes, ref bool newPosition) { MemorySlice keyToInsert; if (_tree.KeysPrefixing) keyToInsert = new PrefixedSlice(_newKey); // let's assume that _newkey won't be prefixed to ensure the destination page will have enough space else keyToInsert = _newKey; var pageSize = SizeOf.NodeEntry(AbstractPager.PageMaxSpace, keyToInsert , _len) + Constants.NodeOffsetSize; if (prefixes != null) { // we are going to copy all existing prefixes so we need to take into account their sizes for (var i = 0; i < prefixes.Length; i++) { pageSize += (Constants.PrefixNodeHeaderSize + prefixes[i].Header.PrefixLength) & 1; // & 1 because we need 2-byte alignment } } if (currentIndex <= splitIndex) { newPosition = false; for (int i = 0; i < splitIndex; i++) { NodeHeader* node = _page.GetNode(i); pageSize += node->GetNodeSize(); pageSize += pageSize & 1; if (pageSize > AbstractPager.PageMaxSpace) { if (i <= currentIndex) { if (i < currentIndex) newPosition = true; return currentIndex; } return (ushort) i; } } } else { for (int i = _page.NumberOfEntries - 1; i >= splitIndex; i--) { NodeHeader* node = _page.GetNode(i); pageSize += node->GetNodeSize(); pageSize += pageSize & 1; if (pageSize > AbstractPager.PageMaxSpace) { if (i >= currentIndex) { newPosition = false; return currentIndex; } return (ushort) (i + 1); } } } return splitIndex; }
private int AdjustSplitPosition(int currentIndex, int splitIndex, PrefixNode[] prefixes, ref bool toRight) { MemorySlice keyToInsert; int pageSize = 0; if (_tree.KeysPrefixing) { keyToInsert = new PrefixedSlice(_newKey); // let's assume that _newkey won't match any of the existing prefixes pageSize += Constants.PrefixInfoSectionSize; pageSize += Constants.PrefixNodeHeaderSize + 1; // possible new prefix, + 1 because of possible 2-byte alignment } else keyToInsert = _newKey; pageSize += SizeOf.NodeEntry(AbstractPager.PageMaxSpace, keyToInsert , _len) + Constants.NodeOffsetSize; if (prefixes != null) { // we are going to copy all existing prefixes so we need to take into account their sizes for (var i = 0; i < prefixes.Length; i++) { var prefixNodeSize = Constants.PrefixNodeHeaderSize + prefixes[i].Header.PrefixLength; pageSize += prefixNodeSize + (prefixNodeSize & 1); // & 1 because we need 2-byte alignment } } if (toRight == false) { for (int i = 0; i < splitIndex; i++) { NodeHeader* node = _page.GetNode(i); pageSize += node->GetNodeSize(); pageSize += pageSize & 1; if (pageSize > AbstractPager.PageMaxSpace) { if (i <= currentIndex) { if (i < currentIndex) toRight = true; return currentIndex; } return i; } } } else { for (int i = _page.NumberOfEntries - 1; i >= splitIndex; i--) { NodeHeader* node = _page.GetNode(i); pageSize += node->GetNodeSize(); pageSize += pageSize & 1; if (pageSize > AbstractPager.PageMaxSpace) { if (i >= currentIndex) { toRight = false; return currentIndex; } return i + 1; } } } return splitIndex; }
public override void PrepareForSearching() { if (Prefix == null && NewPrefix != null) { Prefix = new PrefixNode(new PrefixNodeHeader { PrefixLength = NewPrefix.KeyLength }, NewPrefix.Array, -1); } }