Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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;
                }
            }
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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;
                }
            }
        }
Exemple #6
0
        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;
        }
Exemple #7
0
        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;
        }
Exemple #8
0
        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;
        }
Exemple #9
0
        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;
        }
Exemple #10
0
        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;
        }
Exemple #11
0
 public override void PrepareForSearching()
 {
     if (Prefix == null && NewPrefix != null)
     {
         Prefix = new PrefixNode(new PrefixNodeHeader
         {
             PrefixLength = NewPrefix.KeyLength
         }, NewPrefix.Array, -1);
     }
 }