예제 #1
0
 private unsafe static void SetBlockHeader(int length, DeltaLogEntryType type, byte *dest)
 {
     ref var header = ref GetHeader((long)dest);
예제 #2
0
        /// <summary>
        /// Get next entry
        /// </summary>
        /// <param name="physicalAddress"></param>
        /// <param name="entryLength"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public unsafe bool GetNext(out long physicalAddress, out int entryLength, out DeltaLogEntryType type)
        {
            while (true)
            {
                physicalAddress = 0;
                entryLength     = 0;
                currentAddress  = nextAddress;
                type            = DeltaLogEntryType.DELTA;

                var _currentPage   = currentAddress >> LogPageSizeBits;
                var _currentFrame  = _currentPage % frameSize;
                var _currentOffset = currentAddress & PageSizeMask;
                var _headAddress   = long.MaxValue;

                if (disposed)
                {
                    return(false);
                }

                var _endAddress = endAddress;
                if (tailAddress > _endAddress)
                {
                    _endAddress = tailAddress;
                }

                if (currentAddress >= _endAddress)
                {
                    return(false);
                }


                if (BufferAndLoad(currentAddress, _currentPage, _currentFrame, _headAddress, _endAddress))
                {
                    continue;
                }
                physicalAddress = frame.GetPhysicalAddress(_currentFrame, _currentOffset);

                // Get and check entry length
                entryLength = GetHeader(physicalAddress).Length;
                type        = GetHeader(physicalAddress).Type;

                if (entryLength == 0)
                {
                    currentAddress = (1 + (currentAddress >> LogPageSizeBits)) << LogPageSizeBits;
                    if (Utility.MonotonicUpdate(ref nextAddress, currentAddress, out _))
                    {
                        return(false);
                    }
                    else
                    {
                        continue;
                    }
                }

                int recordSize = (int)(Align(_currentOffset + HeaderSize + entryLength) - _currentOffset);
                if (entryLength < 0 || (_currentOffset + recordSize > PageSize))
                {
                    currentAddress = (1 + (currentAddress >> LogPageSizeBits)) << LogPageSizeBits;
                    if (Utility.MonotonicUpdate(ref nextAddress, currentAddress, out _))
                    {
                        return(false);
                    }
                    else
                    {
                        continue;
                    }
                }

                // Verify checksum
                if (!VerifyBlockChecksum((byte *)physicalAddress, entryLength))
                {
                    currentAddress = (1 + (currentAddress >> LogPageSizeBits)) << LogPageSizeBits;
                    if (Utility.MonotonicUpdate(ref nextAddress, currentAddress, out _))
                    {
                        return(false);
                    }
                    else
                    {
                        continue;
                    }
                }
                physicalAddress += HeaderSize;

                if ((currentAddress & PageSizeMask) + recordSize == PageSize)
                {
                    currentAddress = (1 + (currentAddress >> LogPageSizeBits)) << LogPageSizeBits;
                }
                else
                {
                    currentAddress += recordSize;
                }

                if (Utility.MonotonicUpdate(ref nextAddress, currentAddress, out long oldCurrentAddress))
                {
                    currentAddress = oldCurrentAddress;
                    return(true);
                }
            }
        }