AccessRange() public method

Accesses a range of bytes within the stream.
public AccessRange ( long offset, uint size, MemoryMappedFileAccess access = MemoryMappedFileAccess.ReadWrite ) : StreamRange
offset long The offset within the stream, relative to the end of the stream header.
size uint The size of the range to access, in bytes.
access MemoryMappedFileAccess
return StreamRange
示例#1
0
        public StreamRange AccessNode(long index, bool forWrite)
        {
            unchecked {
                long position = BTreeHeader.Size + (index * BTreeNode.TotalSize);
                var  range    = IndexStream.AccessRange(position, BTreeNode.TotalSize, MemoryMappedFileAccess.ReadWrite);

                var pNode = (BTreeNode *)range.Pointer;

                if (pNode->IsValid != 1)
                {
                    // If the node is fully uninitialized, locking it for write is okay
                    if ((pNode->NumValues != 0) || (pNode->HasLeaves != 0))
                    {
                        throw new InvalidDataException();
                    }
                }

                if (forWrite)
                {
                    pNode->IsValid = 0;
                }

                return(range);
            }
        }
示例#2
0
        public StreamRange LockValue(long nodeIndex, uint valueIndex, long?minimumSize, out BTreeValue *pValue, out ushort keyType)
        {
            var result = AccessNode(nodeIndex, true);

            unchecked {
                pValue = (BTreeValue *)(result.Pointer + BTreeNode.OffsetOfValues + (valueIndex * BTreeValue.Size));

                keyType         = pValue->KeyType;
                pValue->KeyType = 0;
            }

            var lockLength = pValue->DataLength;

            if ((minimumSize.HasValue) && (minimumSize.Value > lockLength))
            {
                lockLength = (uint)minimumSize.Value;

                var oldPosition = pValue->DataOffset;
                var oldLength   = pValue->DataLength + pValue->ExtraDataBytes;

                pValue->DataOffset     = (uint)AllocateDataSpace(ref lockLength).Value;
                pValue->ExtraDataBytes = (uint)(lockLength - oldLength);

                using (var oldDataRange = DataStream.AccessRange(oldPosition, oldLength))
                    using (var dataRange = DataStream.AccessRange(pValue->DataOffset, pValue->DataLength)) {
                        Native.memmove(dataRange.Pointer, oldDataRange.Pointer, new UIntPtr(pValue->DataLength));
                        Native.memset(oldDataRange.Pointer, 0, new UIntPtr(pValue->DataLength));
                    }

                FreelistPut(oldPosition, oldLength);
            }

            return(result);
        }
示例#3
0
        /// <summary>
        /// Performs a binary search of the values stored within a BTree node.
        /// </summary>
        /// <param name="entries">Pointer to the first value within the node.</param>
        /// <param name="entryCount">The number of values within the node.</param>
        /// <param name="pSearchKey">Pointer to the first byte of the key to search for.</param>
        /// <param name="searchKeyLength">The number of bytes in the key to search for.</param>
        /// <param name="resultIndex">The index of the value within the node that matches the provided key, if any, otherwise the index of the leaf that should contain the provided key.</param>
        /// <returns>True if one of the node's values matches the provided key. False if the provided key was not found.</returns>
        private bool SearchValues(BTreeValue *entries, ushort entryCount, byte *pSearchKey, uint searchKeyLength, out uint resultIndex)
        {
            int  min = 0, max = entryCount - 1;
            int  delta = 0, pivot;
            uint compareLength;

            while (min <= max)
            {
                unchecked {
                    pivot = min + ((max - min) >> 1);
                }

                var pEntry = &entries[pivot];
                if (pEntry->KeyType == 0)
                {
                    throw new InvalidDataException();
                }

                compareLength = Math.Min(Math.Min(pEntry->KeyLength, searchKeyLength), BTreeValue.KeyPrefixSize);

                // Calling out to a function here introduces unnecessary overhead since the prefix is so small
                for (uint i = 0; i < compareLength; i++)
                {
                    delta = pEntry->KeyPrefix[i] - pSearchKey[i];
                    if (delta != 0)
                    {
                        break;
                    }
                }

                if ((delta == 0) && (pEntry->KeyLength > BTreeValue.KeyPrefixSize))
                {
                    using (var keyRange = KeyStream.AccessRange(
                               pEntry->KeyOffset, pEntry->KeyLength, MemoryMappedFileAccess.Read
                               )) {
                        var pLhs = keyRange.Pointer;

                        compareLength = Math.Min(pEntry->KeyLength, searchKeyLength);
                        delta         = Native.memcmp(pLhs, pSearchKey, new UIntPtr(compareLength));
                    }
                }

                if (delta == 0)
                {
                    if (pEntry->KeyLength > searchKeyLength)
                    {
                        delta = 1;
                    }
                    else if (searchKeyLength > pEntry->KeyLength)
                    {
                        delta = -1;
                    }
                }

                if (delta == 0)
                {
                    resultIndex = (uint)pivot;
                    return(true);
                }
                else if (delta < 0)
                {
                    min = pivot + 1;
                }
                else
                {
                    max = pivot - 1;
                }
            }

            resultIndex = (uint)min;
            return(false);
        }