Пример #1
0
        private static async Task FlushMemoryBufferAsync(Stream fileStream, InMemoryBinaryWriter memoryBuffer)
        {
            // Write the chunk length at the beginning of the stream.
            var chunkSize = checked ((int)memoryBuffer.BaseStream.Position);

            memoryBuffer.BaseStream.Position = 0;
            var propertyChunkMetadata = new PropertyChunkMetadata(chunkSize);

            propertyChunkMetadata.Write(memoryBuffer);

            // Move to end.
            memoryBuffer.BaseStream.Position = chunkSize;

            // Checksum the chunk.
            var checksum = memoryBuffer.GetChecksum();

            memoryBuffer.Write(checksum);

            // Write to disk.
            await memoryBuffer.WriteAsync(fileStream).ConfigureAwait(false);

            // Reset the memory buffer.
            memoryBuffer.BaseStream.Position = 0;
        }
Пример #2
0
        /// <summary>
        /// Read all file metadata from the metadata file.
        /// </summary>
        /// <param name="metadataTable">The metadata table.</param>
        /// <param name="filestream">The file stream to read from.</param>
        /// <param name="properties">The metadata manager file properties.</param>
        /// <param name="traceType">Tracing information.</param>
        /// <returns></returns>
        private static async Task <int> ReadDiskMetadataAsync(
            Dictionary <uint, FileMetadata> metadataTable, Stream filestream, MetadataManagerFileProperties properties, string traceType)
        {
            var startOffset   = properties.MetadataHandle.Offset;
            var endOffset     = properties.MetadataHandle.EndOffset;
            var metadataCount = 0;
            var fileId        = 0;

            // No metadata to read (there are no metadata chunks).
            if (startOffset + sizeof(int) >= endOffset)
            {
                return(fileId);
            }

            filestream.Position = startOffset;

            using (var metadataStream = new MemoryStream(capacity: 64 * 1024))
                using (var metadataReader = new InMemoryBinaryReader(metadataStream))
                {
                    // Read the first key chunk size into memory.
                    metadataStream.SetLength(64 * 1024);
                    await filestream.ReadAsync(metadataStream.GetBuffer(), 0, PropertyChunkMetadata.Size).ConfigureAwait(false);

                    var propertyChunkMetadata = PropertyChunkMetadata.Read(metadataReader);
                    var chunkSize             = propertyChunkMetadata.BlockSize;
                    filestream.Position -= PropertyChunkMetadata.Size;

                    while (filestream.Position + chunkSize + sizeof(ulong) <= endOffset)
                    {
                        // Consistency checks.
                        if (chunkSize < 0)
                        {
                            throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_Metadata_Corrupt_NegativeSize_OneArgs, chunkSize));
                        }

                        // Read the entire chunk (plus the checksum and next chunk size) into memory.
                        metadataStream.SetLength(chunkSize + sizeof(ulong) + sizeof(int));
                        await filestream.ReadAsync(metadataStream.GetBuffer(), 0, chunkSize + sizeof(ulong) + sizeof(int)).ConfigureAwait(false);

                        // Read the checksum.
                        metadataStream.Position = chunkSize;
                        var checksum = metadataReader.ReadUInt64();

                        // Re-compute the checksum.
                        var expectedChecksum = CRC64.ToCRC64(metadataStream.GetBuffer(), 0, chunkSize);
                        if (checksum != expectedChecksum)
                        {
                            throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_Metadata_Corrupt_ChecksumMismatch_TwoArgs, checksum, expectedChecksum));
                        }

                        // Deserialize the value into memory.
                        metadataStream.Position = sizeof(int);
                        metadataReader.ReadPaddingUntilAligned(true);
                        while (metadataStream.Position < chunkSize)
                        {
                            var fileMetadata = FileMetadata.Read(metadataReader, traceType);
                            if (metadataTable.ContainsKey(fileMetadata.FileId))
                            {
                                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_DuplicateFileId_Found_OneArgs, fileMetadata.FileId));
                            }

                            metadataTable.Add(fileMetadata.FileId, fileMetadata);
                            metadataCount++;
                        }

                        // Read the next chunk size.
                        chunkSize            = BitConverter.ToInt32(metadataStream.GetBuffer(), chunkSize + sizeof(ulong));
                        filestream.Position -= sizeof(int);
                    }

                    // Consistency checks.
                    if (filestream.Position != endOffset)
                    {
                        throw new InvalidDataException(SR.Error_Metadata_Corrupt_IncorrectSize);
                    }

                    if (metadataCount != properties.FileCount)
                    {
                        throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_Metadata_Corrupt_FileCountMismatch_TwoArgs, metadataCount, properties.FileCount));
                    }

                    return(fileId);
                }
        }