예제 #1
0
        /// <summary>
        /// Read a single state provider metadata from the stream.
        /// </summary>
        /// <param name="reader">Stream to read from.</param>
        /// <param name="traceType">Tracing type information.</param>
        /// <param name="deserializeTypes">Should the types be deserialized.</param>
        /// <returns>The read state provider metadata.</returns>
        private static SerializableMetadata ReadMetadata(InMemoryBinaryReader reader, string traceType, bool deserializeTypes = true)
        {
            var startPosition = reader.BaseStream.Position;

            var recordSize = reader.ReadInt32();
            var name       = reader.ReadUri();

            Utility.Assert(name != null, "{0}: Name for the State Provider cannot be null.", traceType);

            string typeName = null;
            var    type     = reader.ReadType(out typeName);

            Utility.Assert(type != null, SR.Assert_SM_TypeNotFound, traceType, typeName, name.ToString());

            var createLsn = reader.ReadInt64();
            var deleteLsn = reader.ReadInt64();
            var initializationParameters = reader.ReadNullableBytes();
            var metadataMode             = (MetadataMode)reader.ReadInt32();
            var stateProviderId          = reader.ReadInt64();
            var parentStateProviderId    = reader.ReadInt64();

            var endPosition    = reader.BaseStream.Position;
            var readRecordSize = checked ((int)(endPosition - startPosition));

            if (readRecordSize != recordSize)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_RecordSize));
            }

            if (deserializeTypes)
            {
                // Re-create the state provider metadata.
                return(new SerializableMetadata(
                           name,
                           type,
                           initializationParameters,
                           stateProviderId,
                           parentStateProviderId,
                           metadataMode,
                           createLsn,
                           deleteLsn));
            }

            // Test only.
            return(new SerializableMetadata(
                       name,
                       typeName,
                       initializationParameters,
                       stateProviderId,
                       parentStateProviderId,
                       metadataMode,
                       createLsn,
                       deleteLsn));
        }
예제 #2
0
        /// <summary>
        /// Reads the state provider metadata from the next chunk of copy data.
        /// </summary>
        /// <param name="operationData">The next chunk of copy data.</param>
        /// <param name="traceType">Tracing type information.</param>
        /// <returns>The copied set of state providers' metadata.</returns>
        internal static IEnumerable <SerializableMetadata> ReadCopyData(OperationData operationData, string traceType)
        {
            if (operationData == null)
            {
                throw new ArgumentNullException("operationData");
            }

            if (operationData.Count <= 0)
            {
                throw new ArgumentException("OperationData contains zero data.", "operationData");
            }

            // The state manager currently sends a single array segment per operation data.
            var itemData      = operationData[0];
            var operationType =
                (StateManagerCopyOperation)itemData.Array[itemData.Offset + itemData.Count - 1];

            using (var itemStream = new MemoryStream(itemData.Array, itemData.Offset, itemData.Count - 1))
                using (var itemReader = new InMemoryBinaryReader(itemStream))
                {
                    if (operationType == StateManagerCopyOperation.Version)
                    {
                        // Verify the copy protocol version is known.
                        var copyProtocolVersion = itemReader.ReadInt32();
                        if (copyProtocolVersion != CopyProtocolVersion)
                        {
                            throw new InvalidDataException(
                                      string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_UnknownCopyProtocol_OneArg, copyProtocolVersion));
                        }
                    }
                    else if (operationType == StateManagerCopyOperation.StateProviderMetadata)
                    {
                        // Read the chunk of state provider metadata.
                        while (itemStream.Position < itemStream.Length)
                        {
                            yield return(ReadMetadata(itemReader, traceType, true));
                        }
                    }
                    else
                    {
                        throw new InvalidDataException(
                                  string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_UnknownSMCopyOperation_OneArg, operationType));
                    }
                }
        }
예제 #3
0
        /// <summary>
        /// Deserialize the header for the OperationData
        /// </summary>
        internal void DeserializeContext(
            OperationData operationData,
            int version,
            string traceType)
        {
            Utility.Assert(
                operationData != null,
                "{0}: DeserializeContext: Null named operation data during create",
                this.TraceType);

            Utility.Assert(
                operationData.Count > 0,
                "{0}:DeserializeContext: Named operation data should have atleast one buffer during create",
                this.TraceType);

            var  headerBufferSPtr = operationData[operationData.Count - 1];
            bool isStateProviderDataNull;

            using (InMemoryBinaryReader reader = new InMemoryBinaryReader(new MemoryStream(
                                                                              headerBufferSPtr.Array,
                                                                              headerBufferSPtr.Offset,
                                                                              headerBufferSPtr.Count)))
            {
                this.Version = reader.ReadInt32();

                if (this.Version != version)
                {
                    FabricEvents.Events.OnApplyVersionError(traceType, this.Version, version);
                    throw new NotSupportedException(
                              string.Format(
                                  CultureInfo.InvariantCulture,
                                  "Unsupported version {0} on deserialization, current version is {1}",
                                  this.Version,
                                  version));
                }

                this.StateProviderId    = reader.ReadInt64();
                isStateProviderDataNull = reader.ReadBoolean();
            }

            // Remove state manager metadata from data.
            operationData.RemoveAt(operationData.Count - 1);

            this.OperationData = isStateProviderDataNull ? null : operationData;
        }
예제 #4
0
        /// <summary>
        /// Deserializes replication metadata.
        /// </summary>
        public static void DeserializeMetadataForUndoOperation(
            InMemoryBinaryReader metaDataReader,
            string traceType,
            int currentVersion,
            out long stateProviderId,
            out Uri stateProviderName,
            out StateManagerApplyType applyType)
        {
            try
            {
                // Read meta data.
                int version;
                DeserializeMetadata(
                    metaDataReader,
                    traceType,
                    currentVersion,
                    out stateProviderId,
                    out stateProviderName,
                    out applyType,
                    out version);

                Utility.Assert(applyType != StateManagerApplyType.Invalid, "Invalid apply type");
                if (applyType == StateManagerApplyType.Delete)
                {
                    applyType = StateManagerApplyType.Insert;
                }
                else
                {
                    applyType = StateManagerApplyType.Delete;
                }
            }
            catch (Exception e)
            {
                StateManagerStructuredEvents.TraceException(
                    traceType,
                    "ReplicationMetadata.Deserialize",
                    string.Empty,
                    e);
                throw;
            }
        }
예제 #5
0
        /// <summary>
        /// Deserializes replication metadata.
        /// </summary>
        private static void DeserializeMetadata(
            InMemoryBinaryReader metaDataReader,
            string traceType,
            int currentVersion,
            out long stateProviderId,
            out Uri stateProviderName,
            out StateManagerApplyType applyType,
            out int version)
        {
            try
            {
                version = metaDataReader.ReadInt32();
                if (version != currentVersion)
                {
                    var errorMessage = string.Format(
                        CultureInfo.InvariantCulture,
                        SR.Error_Unsupported_Version_Deserialization,
                        version,
                        currentVersion);
                    FabricEvents.Events.ReplicationMetadataDeserializeError(traceType, errorMessage);
                    throw new NotSupportedException(errorMessage);
                }

                stateProviderId   = metaDataReader.ReadInt64();
                stateProviderName = metaDataReader.ReadUri();
                applyType         = (StateManagerApplyType)metaDataReader.ReadByte();
                Utility.Assert(applyType != StateManagerApplyType.Invalid, "Invalid apply type");
            }
            catch (Exception e)
            {
                StateManagerStructuredEvents.TraceException(
                    traceType,
                    "ReplicationMetadata.Deserialize",
                    string.Empty,
                    e);
                throw;
            }
        }
예제 #6
0
        /// <summary>
        /// Read the list of state providers' metadata from the <see cref="StateManagerFile"/>.
        /// </summary>
        /// <param name="stream">Stream to read from.</param>
        /// <param name="traceType">Tracing type information.</param>
        /// <param name="deserializeTypes">Should the types be deserialized.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>The list of state providers' metadata read.</returns>
        private async Task <List <SerializableMetadata> > ReadMetadataAsync(
            Stream stream,
            string traceType,
            bool deserializeTypes,
            CancellationToken cancellationToken)
        {
            var metadataList = new List <SerializableMetadata>((int)this.properties.StateProviderCount);

            // Read the blocks, to improve sequential reads.
            var blocks = await FileBlock.ReadBlockAsync(
                stream,
                this.properties.BlocksHandle,
                (sectionReader, sectionHandle) => StateManagerFileBlocks.Read(sectionReader, sectionHandle)).ConfigureAwait(false);

            // Currently, we expect the block sizes to always be present.
            if (blocks == null || blocks.RecordBlockSizes == null)
            {
                throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_BlockSizesMissing));
            }

            var recordBlockSizes = blocks.RecordBlockSizes;

            // Read blocks from the file.  Each state provider metadata is checksummed individually.
            using (var itemStream = new MemoryStream(DesiredBlockSize * 2))
                using (var itemReader = new InMemoryBinaryReader(itemStream))
                {
                    stream.Position = this.properties.MetadataHandle.Offset;
                    var endOffset = this.properties.MetadataHandle.EndOffset;

                    // Each block has one or more state provider metadata records.
                    foreach (var recordBlockSize in recordBlockSizes)
                    {
                        if (stream.Position + recordBlockSize > endOffset)
                        {
                            throw new InvalidDataException(
                                      string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_BlockExtendPastFile));
                        }

                        // Read the block into memory.
                        itemStream.Position = 0;
                        itemStream.SetLength(recordBlockSize);
                        await stream.ReadAsync(itemStream.GetBuffer(), 0, recordBlockSize, cancellationToken).ConfigureAwait(false);

                        // Read to the end of the metadata section.
                        var endBlockOffset = itemStream.Length;
                        while (itemStream.Position < endBlockOffset)
                        {
                            var position = itemStream.Position;

                            // Read the record size and validate it is not obviously corrupted.
                            if (position + sizeof(int) > endBlockOffset)
                            {
                                throw new InvalidDataException(
                                          string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_MissingRecordSize));
                            }

                            var recordSize             = itemReader.ReadInt32();
                            var recordSizeWithChecksum = recordSize + sizeof(ulong);

                            // We need to do extra validation on the recordSize, because we haven't validated the bits
                            // against the checksum and we need the recordSize to locate the checksum.
                            if (recordSize < 0)
                            {
                                throw new InvalidDataException(
                                          string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_NegativeRecordSize));
                            }

                            if (position + recordSize > endBlockOffset)
                            {
                                throw new InvalidDataException(
                                          string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_RecordExtendsPastFile));
                            }

                            if (position + recordSizeWithChecksum > endBlockOffset)
                            {
                                throw new InvalidDataException(
                                          string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_MissingChecksum));
                            }

                            // Compute the checksum.
                            var computedChecksum = CRC64.ToCRC64(
                                itemStream.GetBuffer(),
                                checked ((int)position),
                                recordSize);

                            // Read the checksum (checksum is after the record bytes).
                            itemStream.Position = position + recordSize;
                            var checksum = itemReader.ReadUInt64();

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

                            // Read and re-create the state provider metadata, now that the checksum is validated.
                            itemStream.Position = position;
                            var metadata = ReadMetadata(itemReader, traceType, deserializeTypes);
                            metadataList.Add(metadata);
                            itemStream.Position = position + recordSizeWithChecksum;
                        }
                    }
                }

            // Post-validation.
            if (metadataList.Count != (int)this.Properties.StateProviderCount)
            {
                throw new InvalidDataException(
                          string.Format(CultureInfo.CurrentCulture, SR.Error_SMFile_Corrupt_MetadataCountMismatch));
            }

            return(metadataList);
        }
예제 #7
0
        /// <summary>
        /// Deserializes replication metadata and the redodata.
        /// </summary>
        public static ReplicationMetadata Deserialize(
            InMemoryBinaryReader metaDataReader,
            InMemoryBinaryReader redoDataReader,
            string traceType,
            int currentVersion)
        {
            try
            {
                // Read meta data first
                long stateProviderId;
                Uri  name;
                StateManagerApplyType operationType;
                int version;

                DeserializeMetadata(
                    metaDataReader,
                    traceType,
                    currentVersion,
                    out stateProviderId,
                    out name,
                    out operationType,
                    out version);

                if (redoDataReader == null)
                {
                    return(new ReplicationMetadata(
                               name,
                               stateProviderId,
                               DynamicStateManager.StateManagerId,
                               version,
                               operationType));
                }

                // Read Data Next
                string typeName;
                Type   type = redoDataReader.ReadType(out typeName);
                Utility.Assert(type != null, SR.Assert_SM_TypeNotFound, traceType, typeName, name.ToString());

                byte[] initializationParameters = redoDataReader.ReadNullableBytes();
                long   parentStateProviderId    = redoDataReader.ReadInt64();

                // Since this is used in redo only scenarios, it is safe to assuem apply type is same as the original opeartion type.
                ReplicationMetadata replicationMetadata = new ReplicationMetadata(
                    name,
                    type,
                    initializationParameters,
                    stateProviderId,
                    parentStateProviderId,
                    version,
                    operationType);

                return(replicationMetadata);
            }
            catch (Exception e)
            {
                StateManagerStructuredEvents.TraceException(
                    traceType,
                    "ReplicationMetadata.Deserialize",
                    string.Empty,
                    e);
                throw;
            }
        }