private memmove ( byte dest, byte src, |
||
dest | byte | |
src | byte | |
count | ||
Результат | int |
public bool ReadKey(BTreeValue *pEntry, ushort keyType, out TangleKey key) { if (keyType == 0) { key = default(TangleKey); return(false); } var buffer = ImmutableArrayPool <byte> .Allocate(pEntry->KeyLength); if (pEntry->KeyLength <= BTreeValue.KeyPrefixSize) { fixed(byte *pBuffer = buffer.Array) Native.memmove(pBuffer + buffer.Offset, pEntry->KeyPrefix, new UIntPtr(pEntry->KeyLength)); } else { using (var keyRange = KeyStream.AccessRange( pEntry->KeyOffset, pEntry->KeyLength, MemoryMappedFileAccess.Read )) Unsafe.ReadBytes(keyRange.Pointer, 0, buffer.Array, buffer.Offset, pEntry->KeyLength); } key = new TangleKey(buffer, keyType); return(true); }
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); }
/// <summary> /// Prepares a BTree node for the insertion of a value by moving existing values/leaves out of the way. /// The node is flagged as invalid and its value count is incremented. /// </summary> /// <param name="nodeIndex">The index of the node.</param> /// <param name="valueIndex">The index of the value within the node that will be moved forward to make room for the new value.</param> /// <returns>A StreamRange that can be used to access the specified BTree node.</returns> public StreamRange PrepareForInsert(long nodeIndex, uint valueIndex) { var range = AccessNode(nodeIndex, true); var pNode = (BTreeNode *)range.Pointer; var pValues = (BTreeValue *)(range.Pointer + BTreeNode.OffsetOfValues); var pLeaves = (BTreeLeaf *)(range.Pointer + BTreeNode.OffsetOfLeaves); if (pNode->NumValues >= BTreeNode.MaxValues) { throw new InvalidDataException(); } if (valueIndex < pNode->NumValues) { var destPtr = (byte *)(&pValues[valueIndex + 1]); var copyLength = (byte *)pLeaves - destPtr; if (copyLength < 0) { throw new InvalidDataException(); } Native.memmove( destPtr, (byte *)(&pValues[valueIndex]), new UIntPtr((uint)copyLength) ); } if (pNode->HasLeaves == 1) { var pEnd = (byte *)range.Pointer + BTreeNode.TotalSize; var destPtr = (byte *)(&pLeaves[valueIndex + 2]); var copyLength = (byte *)pEnd - destPtr; if (copyLength < 0) { throw new InvalidDataException(); } Native.memmove( destPtr, (byte *)(&pLeaves[valueIndex + 1]), new UIntPtr((uint)copyLength) ); } // If we don't mark the now-empty spot as invalid, later attempts to lock it will fail pValues[valueIndex].KeyType = 0; pNode->NumValues += 1; return(range); }
/// <summary> /// Splits a BTree leaf node into two nodes. The median value from the node moves upward into the parent, with the two new nodes each recieving half of the remaining values and leaves. /// </summary> /// <param name="parentNodeIndex">The index of the node's parent node.</param> /// <param name="leafValueIndex">The index within the parent node's values where the median value should be inserted.</param> /// <param name="leafNodeIndex">The index of the leaf node to split.</param> public void SplitLeafNode(long parentNodeIndex, uint leafValueIndex, long leafNodeIndex) { const int tMinus1 = BTreeNode.T - 1; long newIndex = CreateNode(); using (var leafRange = AccessNode(leafNodeIndex, true)) using (var newRange = AccessNode(newIndex, true)) { var pLeaf = (BTreeNode *)leafRange.Pointer; var pLeafValues = (BTreeValue *)(leafRange.Pointer + BTreeNode.OffsetOfValues); var pLeafLeaves = (BTreeLeaf *)(leafRange.Pointer + BTreeNode.OffsetOfLeaves); var pNew = (BTreeNode *)newRange.Pointer; var pNewValues = (BTreeValue *)(newRange.Pointer + BTreeNode.OffsetOfValues); var pNewLeaves = (BTreeLeaf *)(newRange.Pointer + BTreeNode.OffsetOfLeaves); if (pLeaf->NumValues != BTreeNode.MaxValues) { throw new InvalidDataException(); } *pNew = new BTreeNode { NumValues = (ushort)tMinus1, HasLeaves = pLeaf->HasLeaves, IsValid = 0 }; pLeaf->NumValues = (ushort)tMinus1; Native.memmove((byte *)pNewValues, (byte *)&pLeafValues[BTreeNode.T], new UIntPtr(tMinus1 * BTreeValue.Size)); if (pLeaf->HasLeaves == 1) { Native.memmove((byte *)pNewLeaves, (byte *)&pLeafLeaves[BTreeNode.T], new UIntPtr(BTreeNode.T * BTreeLeaf.Size)); } var newLeaf = new BTreeLeaf(newIndex); Insert( parentNodeIndex, leafValueIndex, ref pLeafValues[tMinus1], ref newLeaf ); UnlockNode(newRange); UnlockNode(leafRange); } }
public static void WriteBytes(byte *ptr, long offset, byte[] source, int sourceOffset, int count) { fixed(byte *pSource = &source[sourceOffset]) Native.memmove(ptr + offset, pSource, new UIntPtr((uint)count)); }
public static void ReadBytes(byte *ptr, long offset, byte[] buffer, long bufferOffset, uint count) { fixed(byte *pDest = &buffer[bufferOffset]) Native.memmove(pDest, ptr + offset, new UIntPtr((uint)count)); }