Beispiel #1
0
                OpenForRead(long streamPosition, string traceType)
                {
                    // Combine the metadata and page-align IoBuffers
                    uint mdBufferSize;
                    uint paBufferSize;

                    this._MetadataKIoBuffer.QuerySize(out mdBufferSize);
                    this._PageAlignedKIoBuffer.QuerySize(out paBufferSize);

                    this._AllocationReportedToGC = mdBufferSize + paBufferSize;
                    AddGCMemoryPressure(this._AllocationReportedToGC);

                    this._CombinedKIoBuffer.Clear();
                    this._CombinedKIoBuffer.AddIoBufferReference(this._MetadataKIoBuffer, 0, mdBufferSize);
                    this._CombinedKIoBuffer.AddIoBufferReference(this._PageAlignedKIoBuffer, 0, paBufferSize);

                    this._CombinedBufferStream.Reuse(this._CombinedKIoBuffer, this._MetadataSize);

                    // Parse the log stream physical record
                    unsafe
                    {
                        KLogicalLogInformation.MetadataBlockHeader *mdHdr = null;

                        mdHdr = (KLogicalLogInformation.MetadataBlockHeader *) this._CombinedBufferStream.GetBufferPointer();

                        ReleaseAssert.AssertIfNot(
                            this._CombinedBufferStream.PositionTo(mdHdr->OffsetToStreamHeader),
                            "Unexpected PositionTo failure");

                        this._StreamBlockHeader = (KLogicalLogInformation.StreamBlockHeader *) this._CombinedBufferStream.GetBufferPointer();

                        // Position the stream at 1st byte of user record
                        ReleaseAssert.AssertIfNot(
                            this._CombinedBufferStream.Skip((uint)sizeof(KLogicalLogInformation.StreamBlockHeader)),
                            "Unexpected Skip failure");

                        this._OffsetToData = mdHdr->OffsetToStreamHeader + (uint)sizeof(KLogicalLogInformation.StreamBlockHeader);

#if false
                        // TODO: Start: DebugOnly
                        UInt64 savedCrc = _StreamBlockHeader->HeaderCRC64;
                        _StreamBlockHeader->HeaderCRC64 = 0;
                        if (NativeLog.KCrc64(_StreamBlockHeader, (uint)sizeof(KLogicalLogInformation.StreamBlockHeader), 0) != savedCrc)
                        {
                            throw new InvalidDataException();
                        }

                        _StreamBlockHeader->HeaderCRC64 = 0;    // NOTE: Leave HeaderCRC64 0 - this is the unsealed condition

                        if ((_OffsetToData + _StreamBlockHeader->DataSize) > mdBufferSize)
                        {
                            savedCrc = 0;
                            KIoBufferStream.InterationCallback LocalHashFunc = ((
                                                                                    byte *ioBufferFragment,
                                                                                    ref UInt32 fragmentSize) =>
                            {
                                savedCrc = NativeLog.KCrc64(ioBufferFragment, fragmentSize, savedCrc);
                                return(0);
                            });

                            ReleaseAssert.AssertIfNot(
                                _CombinedBufferStream.Iterate(LocalHashFunc, _StreamBlockHeader->DataSize) == 0,
                                "Unexpected Iterate failure");

                            if (_StreamBlockHeader->DataCRC64 != savedCrc)
                            {
                                throw new InvalidDataException();
                            }
                        }
                        // TODO: END: DebugOnly
#endif

                        // Compute position and limits of the KIoBufferStream
                        System.Diagnostics.Debug.Assert(this._StreamBlockHeader->StreamOffsetPlusOne > 0);
                        var recordOffsetToDesiredPosition = streamPosition - (this._StreamBlockHeader->StreamOffsetPlusOne - 1);

                        if ((recordOffsetToDesiredPosition < 0) || (recordOffsetToDesiredPosition >= this._StreamBlockHeader->DataSize))
                        {
                            var s =
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    "OpenForRead: streamPosition {0}, StreamOffsetPlusOne {1}, DataSize {2}, recordOffsetToDesiredPosition {3}, HeadTruncationPoint {4}, HighestOperationId {5} ",
                                    streamPosition,
                                    this._StreamBlockHeader->StreamOffsetPlusOne,
                                    this._StreamBlockHeader->DataSize,
                                    recordOffsetToDesiredPosition,
                                    this._StreamBlockHeader->HeadTruncationPoint,
                                    this._StreamBlockHeader->HighestOperationId);

                            AppTrace.TraceSource.WriteInfo(
                                traceType,
                                s
                                );
                        }

                        System.Diagnostics.Debug.Assert(recordOffsetToDesiredPosition <= uint.MaxValue);
                        this._CombinedBufferStream.Reuse(
                            this._CombinedKIoBuffer,
                            (uint)recordOffsetToDesiredPosition + this._OffsetToData,
                            this._OffsetToData + this._StreamBlockHeader->DataSize);
                    }
                }
Beispiel #2
0
                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;
                    }
                }