/// <summary> /// Initializes a new instance of the <see cref="StateManagerCopyStream"/> class. /// </summary> internal StateManagerCopyStream(IEnumerable <SerializableMetadata> state, string traceType) { this.stateEnumerator = state.GetEnumerator(); this.stateManagerFileCopyData = StateManagerFile.GetCopyData(this.stateEnumerator, traceType).GetEnumerator(); this.traceType = traceType; }
/// <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); } }
/// <summary> /// Create a new <see cref="StateManagerFile"/> and write it to the given file. /// </summary> /// <param name="filePath">Path to the checkpoint file.</param> /// <param name="partitionId">Service partition Id.</param> /// <param name="replicaId">Service replica Id.</param> /// <param name="metadataList">The state providers' metadata.</param> /// <param name="allowPrepareCheckpointLSNToBeInvalid"> /// Allow the prepare checkpoint LSN to be invalid. If it is invalid, do not write it. /// </param> /// <param name="prepareCheckpointLSN">The PrepareCheckpointLSN.</param> /// <param name="cancellationToken">Token used to signal cancellation.</param> /// <returns>The new <see cref="BackupLogFile"/>.</returns> public static async Task <StateManagerFile> CreateAsync( string filePath, Guid partitionId, long replicaId, List <SerializableMetadata> metadataList, bool allowPrepareCheckpointLSNToBeInvalid, long prepareCheckpointLSN, CancellationToken cancellationToken) { // #12249219: Without the "allowPrepareCheckpointLSNToBeInvalid" being set to true in the backup code path, // It is possible for all backups before the first checkpoint after the upgrade to fail. // If the code has the PrepareCheckpointLSN property, it must be larger than or equal to ZeroLSN(0). Utility.Assert( allowPrepareCheckpointLSNToBeInvalid || prepareCheckpointLSN >= StateManagerConstants.ZeroLSN, "{0}:{1} CreateAsync: In the write path, prepareCheckpointLSN must be larger or equal to 0. PrepareCheckpointLSN: {2}.", partitionId, replicaId, prepareCheckpointLSN); // Create the file with asynchronous flag and 4096 cache size (C# default). // MCoskun: Default IoPriorityHint is used. // Reason: Used during backup and checkpoint (user operation and life-cycle operation respectively). using (var filestream = FabricFile.Open( filePath, FileMode.Create, FileAccess.Write, FileShare.Write, 4096, FileOptions.Asynchronous)) { var stateManagerFile = new StateManagerFile(filePath); stateManagerFile.StateProviderMetadata = metadataList; bool shouldNotWritePrepareCheckpointLSN = prepareCheckpointLSN == StateManagerConstants.InvalidLSN ? true : false; stateManagerFile.properties = new StateManagerFileProperties(shouldNotWritePrepareCheckpointLSN); stateManagerFile.properties.PartitionId = partitionId; stateManagerFile.properties.ReplicaId = replicaId; if (shouldNotWritePrepareCheckpointLSN == false) { stateManagerFile.properties.PrepareCheckpointLSN = prepareCheckpointLSN; } // Write the state provider metadata. var blocks = await stateManagerFile.WriteMetadataAsync(filestream, metadataList, cancellationToken).ConfigureAwait(false); stateManagerFile.properties.MetadataHandle = new BlockHandle(offset: 0, size: filestream.Position); cancellationToken.ThrowIfCancellationRequested(); // Write the blocks and update the properties. stateManagerFile.properties.BlocksHandle = await FileBlock.WriteBlockAsync(filestream, (sectionWriter) => blocks.Write(sectionWriter)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Write the properties. var propertiesHandle = await FileBlock.WriteBlockAsync(filestream, writer => stateManagerFile.properties.Write(writer)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Write the footer. stateManagerFile.footer = new FileFooter(propertiesHandle, Version); await FileBlock.WriteBlockAsync(filestream, writer => stateManagerFile.footer.Write(writer)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Ensure we fully flush the data to disk before returning. await filestream.FlushAsync().ConfigureAwait(false); stateManagerFile.FileSize = filestream.Length; return(stateManagerFile); } }