/// <summary>
        /// Write a single state provider metadata to the stream.
        /// </summary>
        /// <param name="writer">Stream to write to.</param>
        /// <param name="metadata">State provider metadata to serialize.</param>
        /// <returns>The record size written.</returns>
        private static int WriteMetadata(InMemoryBinaryWriter writer, SerializableMetadata metadata)
        {
            var startPosition = writer.BaseStream.Position;

            // Reserve an 'int' for the record size at the beginning.
            writer.BaseStream.Position += sizeof(int);

            // Serialize the metadata.
            writer.Write(metadata.Name);
            writer.Write(metadata.Type);
            writer.Write(metadata.CreateLsn);
            writer.Write(metadata.DeleteLsn);
            writer.WriteNullable(metadata.InitializationContext);
            writer.Write((int)metadata.MetadataMode);
            writer.Write(metadata.StateProviderId);
            writer.Write(metadata.ParentStateProviderId);

            // Get the size of the record.
            var endPosition = writer.BaseStream.Position;
            var recordSize  = checked ((int)(endPosition - startPosition));

            // Write the record size at the start of the block.
            writer.BaseStream.Position = startPosition;
            writer.Write(recordSize);

            // Restore the end position.
            writer.BaseStream.Position = endPosition;

            return(recordSize);
        }
        /// <summary>
        /// Create the header for the OperationData
        /// </summary>
        internal OperationData CreateContext()
        {
            OperationData context;

            const int streamSize = sizeof(int)     // version
                                   + sizeof(long)  // stateProviderId
                                   + sizeof(bool); // boolean indicating if the state provider data is null.

            using (InMemoryBinaryWriter writer = new InMemoryBinaryWriter(new MemoryStream(streamSize)))
            {
                writer.Write(this.Version);
                writer.Write(this.StateProviderId);
                writer.Write(this.OperationData == null);

                Utility.Assert(
                    writer.BaseStream.Position == streamSize,
                    "{0}: CreateContext: Size is not correct, Position: {1}.",
                    this.TraceType, writer.BaseStream.Position);

                context = new OperationData(new ArraySegment <byte>(
                                                writer.BaseStream.GetBuffer(),
                                                0,
                                                checked ((int)writer.BaseStream.Position)));
            }

            return(context);
        }
        /// <summary>
        /// Write the state provider metadata to the output stream.
        /// </summary>
        /// <param name="outputstream">Output stream.</param>
        /// <param name="metadataList">The state providers' metadata.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>Task that represents the asynchronous operation.</returns>
        private async Task <StateManagerFileBlocks> WriteMetadataAsync(
            Stream outputstream,
            IEnumerable <SerializableMetadata> metadataList,
            CancellationToken cancellationToken)
        {
            // Track blocks of records, to improve sequential reads.
            var recordBlockSizes = new List <int>();
            var recordBlockSize  = 0;

            using (var itemStream = new MemoryStream(DesiredBlockSize * 2))
                using (var itemWriter = new InMemoryBinaryWriter(itemStream))
                {
                    foreach (var metadata in metadataList)
                    {
                        // Write each state provider metadata into the memory stream.
                        var recordPosition = checked ((int)itemStream.Position);
                        var recordSize     = WriteMetadata(itemWriter, metadata);

                        // Checksum this metadata record (with the record size included).
                        var recordChecksum = CRC64.ToCRC64(itemStream.GetBuffer(), recordPosition, recordSize);

                        // Add the checksum at the end of the memory stream.
                        itemWriter.Write(recordChecksum);

                        // Track record block sizes.  After enough bytes are buffered in memory, flush to disk.
                        recordBlockSize = checked ((int)itemStream.Position);
                        if (recordBlockSize >= DesiredBlockSize)
                        {
                            // Flush the metadata records to the output stream.
                            await outputstream.WriteAsync(itemStream.GetBuffer(), 0, recordBlockSize, cancellationToken).ConfigureAwait(false);

                            recordBlockSizes.Add(recordBlockSize);
                            itemStream.Position = 0;
                        }

                        // Update properties.
                        this.Properties.StateProviderCount++;
                        if (metadata.ParentStateProviderId == DynamicStateManager.EmptyStateProviderId)
                        {
                            this.Properties.RootStateProviderCount++;
                        }
                    }

                    // Flush any remaining bytes to disk, and add the last record block size (if any).
                    recordBlockSize = checked ((int)itemStream.Position);
                    if (recordBlockSize > 0)
                    {
                        await outputstream.WriteAsync(itemStream.GetBuffer(), 0, recordBlockSize, cancellationToken).ConfigureAwait(false);

                        recordBlockSizes.Add(recordBlockSize);
                    }
                }

            // Return the record block sizes.
            var blocks = new StateManagerFileBlocks(recordBlockSizes.ToArray());

            return(blocks);
        }
        /// <summary>
        /// Gets the next chunk of copy data from the in-memory state provider metadata enumerator.
        /// </summary>
        /// <param name="stateEnumerator">State provider metadata enumerator.</param>
        /// <param name="traceType">Tracing type information.</param>
        /// <returns>The next chunk of copy data.</returns>
        internal static IEnumerable <OperationData> GetCopyData(
            IEnumerator <SerializableMetadata> stateEnumerator,
            string traceType)
        {
            var metadataCount = 0;

            // Create a single re-usable memory stream for Copy.
            using (var itemStream = new MemoryStream(DesiredBlockSize))
                using (var itemWriter = new InMemoryBinaryWriter(itemStream))
                {
                    // Send the copy operation protocol version number first.
                    itemWriter.Write(CopyProtocolVersion);
                    itemWriter.Write((byte)StateManagerCopyOperation.Version);
                    yield return
                        (new OperationData(
                             new ArraySegment <byte>(itemStream.GetBuffer(), 0, checked ((int)itemStream.Position))));

                    // Send the state provider metadata in chunks.
                    itemStream.Position = 0;
                    while (stateEnumerator.MoveNext())
                    {
                        WriteMetadata(itemWriter, stateEnumerator.Current);
                        metadataCount++;

                        if (itemStream.Position >= DesiredBlockSize)
                        {
                            // Send a chunk of state provider metadata.
                            itemWriter.Write((byte)StateManagerCopyOperation.StateProviderMetadata);
                            yield return
                                (new OperationData(
                                     new ArraySegment <byte>(itemStream.GetBuffer(), 0, checked ((int)itemStream.Position))));

                            // Reset the item memory stream for the next chunk.
                            itemStream.Position = 0;
                        }
                    }

                    // Send the last chunk, if any exists.
                    if (itemStream.Position > 0)
                    {
                        itemWriter.Write((byte)StateManagerCopyOperation.StateProviderMetadata);
                        yield return
                            (new OperationData(
                                 new ArraySegment <byte>(itemStream.GetBuffer(), 0, checked ((int)itemStream.Position))));
                    }

                    // End of Copy.
                    FabricEvents.Events.StateManagerCopyStreamGetNext(traceType, metadataCount);
                }
        }
 public static void SerializeRedoData(
     ReplicationMetadata replicationMetadata,
     string traceType,
     InMemoryBinaryWriter writer)
 {
     try
     {
         writer.Write(replicationMetadata.Type);
         writer.WriteNullable(replicationMetadata.InitializationContext);
         writer.Write(replicationMetadata.ParentStateProviderId);
     }
     catch (Exception e)
     {
         StateManagerStructuredEvents.TraceException(traceType, "ReplicationMetadata.Serialize", string.Empty, e);
         throw;
     }
 }
 /// <summary>
 /// Serializes replication metadata.
 /// </summary>
 public static void SerializeMetaData(
     ReplicationMetadata replicationMetadata,
     string traceType,
     InMemoryBinaryWriter writer)
 {
     try
     {
         writer.Write(replicationMetadata.Version);
         writer.Write(replicationMetadata.StateProviderId);
         writer.Write(replicationMetadata.Name);
         writer.Write((byte)replicationMetadata.StateManagerApplyType);
     }
     catch (Exception e)
     {
         StateManagerStructuredEvents.TraceException(traceType, "ReplicationMetadata.Serialize", string.Empty, e);
         throw;
     }
 }