Пример #1
0
        /// <summary>
        /// Serialize the block into the given stream.
        /// </summary>
        /// <param name="stream">Stream to write to.</param>
        /// <param name="serializer"></param>
        public static async Task <BlockHandle> WriteBlockAsync(Stream stream, Action <BinaryWriter> serializer)
        {
            using (var memoryStream = new MemoryStream(DefaultMemoryStreamSize))
                using (var memoryWriter = new BinaryWriter(memoryStream))
                {
                    // Serialize the table section.
                    serializer.Invoke(memoryWriter);

                    var blockSize = checked ((int)memoryStream.Position);

                    // Calculate the checksum.
                    var checksum = CRC64.ToCRC64(memoryStream.GetBuffer(), 0, blockSize);

                    // Get the position and size of this section within the stream.
                    var sectionHandle = new BlockHandle(stream.Position, blockSize);

                    // Write the checksum.
                    memoryWriter.Write(checksum);

                    var blockSizeWithChecksum = checked ((int)memoryStream.Position);
                    Utility.Assert((blockSizeWithChecksum - blockSize) == 8, "unexpected block size.");

                    // Write the buffer and checksum to the stream.
                    await stream.WriteAsync(memoryStream.GetBuffer(), 0, blockSizeWithChecksum).ConfigureAwait(false);

                    return(sectionHandle);
                }
        }
Пример #2
0
 /// <summary>
 /// Create a new <see cref="LogRecordBlockAsyncEnumerator"/> class.
 /// </summary>
 /// <param name="stream">Backup log stream.</param>
 /// <param name="logRecordHandle">Location in the backup log stream of the log record chunks.</param>
 public LogRecordBlockAsyncEnumerator(Stream stream, BlockHandle logRecordHandle)
 {
     stream.Position      = logRecordHandle.Offset;
     this.backupLogStream = stream;
     this.logRecordHandle = logRecordHandle;
     this.blockStream     = new MemoryStream();
 }
Пример #3
0
        /// <summary>
        /// Deserialize a <see cref="FileFooter"/> from the given stream.
        /// </summary>
        /// <param name="reader">Stream to read from.</param>
        /// <param name="handle">Starting offset and size within the stream for the file footer.</param>
        /// <returns>The <see cref="FileFooter"/> read from the stream.</returns>
        public static FileFooter Read(BinaryReader reader, BlockHandle handle)
        {
            var propertiesHandle = BlockHandle.Read(reader);
            var version          = reader.ReadInt32();

            return(new FileFooter(propertiesHandle, version));
        }
Пример #4
0
        /// <summary>
        /// Deserialize a block from the given stream.
        /// </summary>
        /// <param name="stream">Stream to read from.</param>
        /// <param name="blockHandle"></param>
        /// <param name="deserializer"></param>
        /// <returns>The block read from the stream.</returns>
        public static async Task <TBlock> ReadBlockAsync <TBlock>(
            Stream stream,
            BlockHandle blockHandle,
            Func <BinaryReader, BlockHandle, TBlock> deserializer)
        {
            // Data validation.
            if (blockHandle.Offset < 0)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_FileBlock_Corrupt, SR.Error_Negative_StreamOffset));
            }

            if (blockHandle.Size < 0)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_FileBlock_Corrupt, SR.Error_Negative_BlockSize));
            }

            if (blockHandle.EndOffset + sizeof(ulong) > stream.Length)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_FileBlock_Corrupt, SR.Error_Block_Beyond_Stream));
            }

            // Move the stream to the block's position within the stream.
            stream.Position = blockHandle.Offset;
            var blockSize             = checked ((int)blockHandle.Size);
            var blockSizeWithChecksum = blockSize + sizeof(ulong);

            // Read the bytes for the block, to calculate the checksum.
            var blockBytes = new byte[blockSizeWithChecksum];
            await stream.ReadAsync(blockBytes, 0, blockBytes.Length).ConfigureAwait(false);

            // Calculate the checksum.
            var blockChecksum = CRC64.ToCRC64(blockBytes, 0, blockSize);

            // Read the actual checksum (checksum is after the block bytes).
            var checksum = BitConverter.ToUInt64(blockBytes, blockSize);

            // Verify the checksum.
            if (checksum != blockChecksum)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_FileBlock_Corrupt, SR.Error_Checksum_Mismatch));
            }

            // Deserialize the actual file block.
            using (var memoryStream = new MemoryStream(blockBytes, 0, blockSize, writable: false))
                using (var memoryReader = new BinaryReader(memoryStream))
                {
                    return(deserializer.Invoke(memoryReader, new BlockHandle(0, blockHandle.Size)));
                }
        }
        /// <summary>
        /// Read the given property value.
        /// </summary>
        /// <param name="reader">Stream to read from.</param>
        /// <param name="property">Property to read.</param>
        /// <param name="valueSize">The size in bytes of the value.</param>
        protected override void ReadProperty(BinaryReader reader, string property, int valueSize)
        {
            switch (property)
            {
            case MetadataHandlePropertyName:
                this.MetadataHandle = BlockHandle.Read(reader);
                break;

            case BlocksHandlePropertyName:
                this.BlocksHandle = BlockHandle.Read(reader);
                break;

            case StateProviderCountPropertyName:
                this.StateProviderCount = reader.ReadUInt32();
                break;

            case RootStateProviderCountPropertyName:
                this.RootStateProviderCount = reader.ReadUInt32();
                break;

            case PartitionIdPropertyName:
                this.PartitionId = new Guid(reader.ReadBytes(valueSize));
                break;

            case ReplicaIdPropertyName:
                this.ReplicaId = reader.ReadInt64();
                break;

            case PrepareCheckpointLSNPropertyName:
                if (this.test_Ignore)
                {
                    // If test ignore set to true, we need to jump over the value block.
                    base.ReadProperty(reader, property, valueSize);
                    break;
                }

                this.PrepareCheckpointLSN = reader.ReadInt64();
                Utility.Assert(
                    PrepareCheckpointLSN >= StateManagerConstants.ZeroLSN,
                    "StateManagerFileProperties::ReadProperty If the file has PrepareCheckpointLSN property, it must larger than or equal to 0, PrepareCheckpointLSN: {0}.",
                    prepareCheckpointLSN);
                break;

            default:
                base.ReadProperty(reader, property, valueSize);
                break;
            }
        }
Пример #6
0
        /// <summary>
        /// Deserialize the <see cref="FileProperties"/> from the given stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="handle">Starting offset and size within the stream for the file properties.</param>
        /// <returns>The deserialized <see cref="FileProperties"/> section.</returns>
        public static TProperties Read <TProperties>(BinaryReader reader, BlockHandle handle)
            where TProperties : FileProperties, new()
        {
            var properties = new TProperties();

            if (handle.Size == 0)
            {
                return(properties);
            }

            // The FileProperties start at the given 'offset' within the stream, and contains properties up to 'offset' + 'size'.
            reader.BaseStream.Position = handle.Offset;
            while (reader.BaseStream.Position < handle.EndOffset)
            {
                // Read the property name.
                var property = reader.ReadString();

                // Read the size in bytes of the property's value.
                var valueSize = VarInt.ReadInt32(reader);
                if (valueSize < 0)
                {
                    throw new InvalidDataException(string.Format(SR.Error_FileProperties_Corrupt, SR.Error_FileProperties_NegativeSize));
                }

                if (reader.BaseStream.Position + valueSize > handle.EndOffset)
                {
                    throw new InvalidDataException(
                              string.Format(SR.Error_FileProperties_Corrupt, SR.Error_FileProperties_LargeSize));
                }

                // Read the property's value.
                properties.ReadProperty(reader, property, valueSize);
            }

            // Validate the properties section ended exactly where expected.
            if (reader.BaseStream.Position != handle.EndOffset)
            {
                throw new InvalidDataException(string.Format(SR.Error_FileProperties_Corrupt, SR.Error_FileProperties_SectionSize));
            }

            return(properties);
        }
Пример #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BackupLogFileAsyncEnumerator"/> class.
        /// </summary>
        /// <param name="backupLogFile">Backup log file.</param>
        /// <param name="logRecordHandle">Start and end offset for the log records.</param>
        public BackupLogFileAsyncEnumerator(BackupLogFile backupLogFile, BlockHandle logRecordHandle)
        {
            Utility.Assert(backupLogFile != null, "backupLogFile != null");

            this.backupLogFile = backupLogFile;

            // Open the file with asynchronous flag and 4096 cache size (C# default).
            // MCoskun: Uses default IOPriorityHint since this operation is called during Restore.
            this.backupLogStream = FabricFile.Open(
                this.backupLogFile.FileName,
                FileMode.Open,
                FileAccess.Read,
                FileShare.Read,
                4096,
                FileOptions.Asynchronous);

            this.logBlockEnumerator = new LogRecordBlockAsyncEnumerator(this.backupLogStream, logRecordHandle);

            this.index = 0;
        }
Пример #8
0
        /// <summary>
        /// Deserialize a <see cref="StateManagerFileBlocks"/> from the given stream.
        /// </summary>
        /// <param name="reader">Stream to deserialize from.</param>
        /// <param name="handle">Starting offset and size within the stream for the table index.</param>
        /// <returns>The deserialized <see cref="StateManagerFileBlocks"/>.</returns>
        public static StateManagerFileBlocks Read(BinaryReader reader, BlockHandle handle)
        {
            if (handle.Size == 0)
            {
                return(null);
            }

            var blocks = new StateManagerFileBlocks();

            reader.BaseStream.Position = handle.Offset;

            // Read the record block sizes.
            blocks.RecordBlockSizes = ReadArray(reader);

            // Validate the section was read correctly.
            if (reader.BaseStream.Position != handle.EndOffset)
            {
                throw new InvalidDataException(SR.Error_SMBlocksCorrupt);
            }

            return(blocks);
        }
Пример #9
0
        /// <summary>
        /// Read the given property value.
        /// </summary>
        /// <param name="reader">Stream to read from.</param>
        /// <param name="property">Property to read.</param>
        /// <param name="valueSize">The size in bytes of the value.</param>
        protected override void ReadProperty(BinaryReader reader, string property, int valueSize)
        {
            switch (property)
            {
            case RecordsHandlePropertyName:
                this.RecordsHandle = BlockHandle.Read(reader);
                break;

            case CountPropertyName:
                this.Count = reader.ReadUInt32();
                break;

            case IndexingRecordEpochPropertyName:
                var indexDataLossNumber      = reader.ReadInt64();
                var indexConfigurationNumber = reader.ReadInt64();
                this.IndexingRecordEpoch = new Epoch(indexDataLossNumber, indexConfigurationNumber);
                break;

            case IndexingRecordLsnPropertyName:
                this.IndexingRecordLsn = new LogicalSequenceNumber(reader.ReadInt64());
                break;

            case LastBackedUpEpochPropertyName:
                var backupDataLossNumber      = reader.ReadInt64();
                var backupConfigurationNumber = reader.ReadInt64();
                this.LastBackedUpEpoch = new Epoch(backupDataLossNumber, backupConfigurationNumber);
                break;

            case LastBackedUpLsnPropertyName:
                this.LastBackedUpLsn = new LogicalSequenceNumber(reader.ReadInt64());
                break;

            default:
                base.ReadProperty(reader, property, valueSize);
                break;
            }
        }
Пример #10
0
        /// <summary>
        /// Open an existing <see cref="StateManagerFile"/> from the given file path.
        /// </summary>
        /// <param name="filePath">Path to the checkpoint file.</param>
        /// <param name="traceType">Tracing information.</param>
        /// <param name="deserializeTypes">Should the type information be deserialized.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>The opened <see cref="StateManagerFile"/>.</returns>
        internal static async Task <StateManagerFile> OpenAsync(
            string filePath,
            string traceType,
            bool deserializeTypes,
            CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentException(SR.Error_FilePath_Null_NoArgs);
            }

            if (!FabricFile.Exists(filePath))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, SR.Error_FilePath_Null, filePath));
            }

            // Open the file with asynchronous flag and 4096 cache size (C# default).
            // MCoskun: Default IoPriorityHint is used.
            // Reason: Used during open, restore and complete checkpoint.
            using (var filestream = FabricFile.Open(
                       filePath,
                       FileMode.Open,
                       FileAccess.Read,
                       FileShare.Read,
                       4096,
                       FileOptions.Asynchronous))
            {
                var stateManagerFile = new StateManagerFile(filePath);

                // Read and validate the Footer section.  The footer is always at the end of the stream, minus space for the checksum.
                var footerHandle = new BlockHandle(
                    filestream.Length - FileFooter.SerializedSize - sizeof(ulong),
                    FileFooter.SerializedSize);
                stateManagerFile.footer = await FileBlock.ReadBlockAsync(
                    filestream,
                    footerHandle,
                    (reader, handle) => FileFooter.Read(reader, handle)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                // Verify we know how to deserialize this version of the state manager checkpoint file.
                if (stateManagerFile.footer.Version != Version)
                {
                    throw new InvalidDataException(
                              string.Format(
                                  CultureInfo.CurrentCulture,
                                  "StateManager checkpoint file cannot be deserialized (unknown version number: {0}, expected version number: {1})",
                                  stateManagerFile.footer.Version,
                                  Version));
                }

                // Read and validate the properties section.
                var propertiesHandle = stateManagerFile.footer.PropertiesHandle;
                stateManagerFile.properties = await FileBlock.ReadBlockAsync(
                    filestream,
                    propertiesHandle,
                    (reader, handle) => FileProperties.Read <StateManagerFileProperties>(reader, handle)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                // Read the state provider metadata.
                stateManagerFile.StateProviderMetadata = await stateManagerFile.ReadMetadataAsync(filestream, traceType, deserializeTypes, cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                stateManagerFile.FileSize = filestream.Length;
                return(stateManagerFile);
            }
        }
Пример #11
0
        /// <summary>
        /// Open an existing <see cref="BackupLogFile"/> from the given file path.
        /// </summary>
        /// <param name="fileName">Path to the backup log file.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>The opened <see cref="BackupLogFile"/>.</returns>
        public static async Task <BackupLogFile> OpenAsync(string fileName, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentException(SR.Error_FilePath_Null_NoArgs);
            }

            if (!FabricFile.Exists(fileName))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, SR.Error_FilePath_Null, fileName));
            }

            // Open the file with asynchronous flag and 4096 cache size (C# default).
            // MCoskun: Uses default IOPriorityHint since this operation is called during Restore.
            using (var filestream = FabricFile.Open(
                       fileName,
                       FileMode.Open,
                       FileAccess.Read,
                       FileShare.Read,
                       4096,
                       FileOptions.Asynchronous))
            {
                var backupLogFile = new BackupLogFile(fileName);
                backupLogFile.Size = filestream.Length;

                // Read and validate the Footer section.  The footer is always at the end of the stream, minus space for the checksum.
                var footerHandle = new BlockHandle(
                    filestream.Length - FileFooter.SerializedSize - sizeof(ulong),
                    FileFooter.SerializedSize);
                backupLogFile.footer =
                    await
                    FileBlock.ReadBlockAsync(
                        filestream,
                        footerHandle,
                        (reader, handle) => FileFooter.Read(reader, handle)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                // Verify we know how to deserialize this version of the backup log file.
                if (backupLogFile.footer.Version != Version)
                {
                    throw new InvalidDataException(
                              string.Format(
                                  CultureInfo.CurrentCulture,
                                  SR.Error_BackupLogFile_Deserialized,
                                  backupLogFile.footer.Version,
                                  Version));
                }

                // Read and validate the properties section.
                var propertiesHandle = backupLogFile.footer.PropertiesHandle;
                backupLogFile.properties =
                    await
                    FileBlock.ReadBlockAsync(
                        filestream,
                        propertiesHandle,
                        (reader, handle) => FileProperties.Read <BackupLogFileProperties>(reader, handle)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                return(backupLogFile);
            }
        }
Пример #12
0
 /// <summary>
 /// Create a new <see cref="FileFooter"/>.
 /// </summary>
 /// <param name="propertiesHandle">Stream offset and size to the Properties section.</param>
 /// <param name="version">Serialization version number for the file.</param>
 public FileFooter(BlockHandle propertiesHandle, int version)
 {
     this.PropertiesHandle = propertiesHandle;
     this.Version          = version;
 }