CopyFrom( NativeLog.IKIoBuffer IoBuffer, UInt32 SrcOffset, UInt32 Size, byte *ResultPtr) { // Compute current source location var src = new KIoBufferStream(IoBuffer, SrcOffset); // NOTE: ctor will fast path for single element KIoBuffers // and code is inlined here if (src._TotalSize < (SrcOffset + Size)) { return(false); // Out of range request } if (src.GetBufferPointerRange() >= Size) { // Optimize for moving totally within current element Memcopy(src._CurrentElementBufferBase + src._CurrentElementOffset, ResultPtr, Size); return(true); } // Will be crossing element boundary return(src.Pull(ResultPtr, Size)); }
CopyTo( NativeLog.IKIoBuffer IoBuffer, UInt32 DestOffset, UInt32 Size, byte *SrcPtr) { // Compute current destination location var dest = new KIoBufferStream(IoBuffer, DestOffset); // NOTE: ctor will fast path for single element KIoBuffers // and code is inlined here if (dest._TotalSize < (DestOffset + Size)) { return(false); // Out of range request } if (dest.GetBufferPointerRange() >= Size) { // Optimize for moving totally within current element Memcopy(SrcPtr, dest._CurrentElementBufferBase + dest._CurrentElementOffset, Size); return(true); } // Will be crossing element boundary return(dest.Put(SrcPtr, Size)); }
CreateReadBuffer( uint blockMetadataSize, long startingStreamPosition, NativeLog.IKIoBuffer metadataBuffer, NativeLog.IKIoBuffer pageAlignedKIoBuffer, string traceType) { return(new Buffer(blockMetadataSize, startingStreamPosition, metadataBuffer, pageAlignedKIoBuffer, traceType)); }
WriteAsync( KTL_LOG_ASN Asn, UInt64 Version, UInt32 MetatdataSize, NativeLog.IKIoBuffer MetadataBuffer, NativeLog.IKIoBuffer IoPageAlignedBuffer, CancellationToken Token) { return(Utility.WrapNativeAsyncInvokeInMTA( (Callback) => this.WriteBeginWrapper(Asn, Version, MetatdataSize, MetadataBuffer, IoPageAlignedBuffer, Callback), (Context) => this.WriteEndWrapper(Context), Token, "NativeLog.WriteStream")); }
WriteBeginWrapper( KTL_LOG_ASN Asn, UInt64 Version, UInt32 MetatdataSize, NativeLog.IKIoBuffer MetadataBuffer, NativeLog.IKIoBuffer IoPageAlignedBuffer, NativeCommon.IFabricAsyncOperationCallback Callback) { NativeCommon.IFabricAsyncOperationContext context; // CONSIDER: Does native code need to AddRef MetadataBuffer and IoPageAlignedBuffer ? this._NativeStream.BeginWrite(Asn, Version, MetatdataSize, MetadataBuffer, IoPageAlignedBuffer, Callback, out context); return(context); }
Buffer( uint blockMetadataSize, long startingStreamPosition, NativeLog.IKIoBuffer metadataBuffer, NativeLog.IKIoBuffer pageAlignedKIoBuffer, string traceType) { this._MetadataSize = blockMetadataSize; this._MetadataKIoBuffer = metadataBuffer; this._PageAlignedKIoBuffer = pageAlignedKIoBuffer; unsafe { this._StreamBlockHeader = null; } this._PageAlignedKIoBufferView = null; this._OffsetToData = uint.MaxValue; NativeLog.CreateEmptyKIoBuffer(out this._CombinedKIoBuffer); this.OpenForRead(startingStreamPosition, traceType); }
KIoBufferStream(NativeLog.IKIoBuffer IoBuffer = null, UInt32 InitialOffset = 0, UInt32 TotalSizeLimit = 0) { this._Buffer = null; this._ElementsDescArray = null; this._ElementsDescs = null; this._MoveInteratorState = null; this._CurrentElementBufferBase = null; this._Position = 0; this._TotalSize = 0; this._NumberOfElements = 0; this._CurrentElement = UInt32.MaxValue; this._CurrentElementOffset = 0; this._CurrentElementSize = 0; this._IsInitialized = false; if ((IoBuffer != null) && (!this.Reuse(IoBuffer, InitialOffset, TotalSizeLimit))) { throw new ArgumentOutOfRangeException(SR.Error_InitialOffset); } }
Reuse(NativeLog.IKIoBuffer IoBuffer, UInt32 InitialOffset = 0, UInt32 TotalSizeLimit = 0) { this._IsInitialized = true; IoBuffer.GetElements(out this._NumberOfElements, out this._ElementsDescArray); { void *arrayBase; this._ElementsDescArray.GetArrayBase(out arrayBase); this._ElementsDescs = (NativeLog.KIOBUFFER_ELEMENT_DESCRIPTOR *)arrayBase; } if (this._NumberOfElements == 1) { // Optimize for single buffer case this._Buffer = IoBuffer; this._CurrentElement = 0; this._CurrentElementOffset = InitialOffset; this._CurrentElementSize = this._ElementsDescs[0].Size; this._CurrentElementBufferBase = this._ElementsDescs[0].ElementBaseAddress; this._Position = InitialOffset; this._TotalSize = this._CurrentElementSize; if (TotalSizeLimit > 0) { this._TotalSize = Math.Min(this._TotalSize, TotalSizeLimit); this._CurrentElementSize = this._TotalSize; } return(InitialOffset < this._CurrentElementSize); } this._Buffer = IoBuffer; IoBuffer.QuerySize(out this._TotalSize); if (TotalSizeLimit > 0) { this._TotalSize = Math.Min(this._TotalSize, TotalSizeLimit); } this.InternalClear(); return(this.PositionTo(InitialOffset)); }
SealForWrite( long currentHeadTruncationPoint, bool IsBarrier, out NativeLog.IKIoBuffer metadataBuffer, out uint metadataSize, out NativeLog.IKIoBuffer pageAlignedBuffer, out long userSizeOfStreamData, out long AsnOfRecord, out long OpOfRecord) { unsafe { uint trimSize = 0; uint dataResidingOutsideMetadata = 0; UInt64 dataCrc = 0; this._MetadataBlockHeader->Flags = IsBarrier ? (uint)KLogicalLogInformation.MetadatBlockHeaderFlags.IsEndOfLogicalRecord : 0; this._StreamBlockHeader->DataSize = this._CombinedBufferStream.GetPosition() - this._OffsetToData; this._StreamBlockHeader->HeadTruncationPoint = currentHeadTruncationPoint; this._PageAlignedKIoBufferView.Clear(); // Compute CRC64 for record data if ((this._OffsetToData < KLogicalLogInformation.FixedMetadataSize) && ((this._OffsetToData + this._StreamBlockHeader->DataSize) <= KLogicalLogInformation.FixedMetadataSize)) { // no data outside the metadata buffer metadataSize = this._OffsetToData + this._StreamBlockHeader->DataSize; } else { // // Compute how much of the metadata is being used. It should be the entire 4K block minus the // space reserved by the physical logger // metadataSize = (uint)KLogicalLogInformation.FixedMetadataSize - this._MetadataSize; ReleaseAssert.AssertIfNot(this._CombinedBufferStream.PositionTo(this._OffsetToData), "Unexpected PositionTo failure"); KIoBufferStream.InterationCallback LocalHashFunc = (( byte *ioBufferFragment, ref UInt32 fragmentSize) => { dataCrc = NativeLog.KCrc64(ioBufferFragment, fragmentSize, dataCrc); return(0); }); ReleaseAssert.AssertIfNot( this._CombinedBufferStream.Iterate(LocalHashFunc, this._StreamBlockHeader->DataSize) == 0, "Unexpected Iterate failure"); // // Compute the number of data blocks that are needed to hold the data that is within the payload // data buffer. This excludes the payload data in the metadata portion // ReleaseAssert.AssertIf(this._OffsetToData > MetadataBlockSize, "Unexpected size for _OffsetToData"); dataResidingOutsideMetadata = this._StreamBlockHeader->DataSize - (MetadataBlockSize - this._OffsetToData); trimSize = ((((dataResidingOutsideMetadata) + (MetadataBlockSize - 1)) / MetadataBlockSize) * MetadataBlockSize); this._PageAlignedKIoBufferView.AddIoBufferReference( this._PageAlignedKIoBuffer, 0, (uint)trimSize); } this._StreamBlockHeader->DataCRC64 = dataCrc; // Now compute block header CRC this._StreamBlockHeader->HeaderCRC64 = NativeLog.KCrc64( this._StreamBlockHeader, (uint)sizeof(KLogicalLogInformation.StreamBlockHeader), 0); // Build results metadataBuffer = this._MetadataKIoBuffer; pageAlignedBuffer = this._PageAlignedKIoBufferView; userSizeOfStreamData = this._StreamBlockHeader->DataSize; AsnOfRecord = this._StreamBlockHeader->StreamOffsetPlusOne; OpOfRecord = this._StreamBlockHeader->HighestOperationId; } }