コード例 #1
0
        internal static void WriteToSync <T>(this Stream stream, Stream toStream, long?copyLength, long?maxLength, ChecksumRequested calculateChecksum, bool syncRead, ExecutionState <T> executionState, StreamDescriptor streamCopyState)
        {
            if (copyLength.HasValue && maxLength.HasValue)
            {
                throw new ArgumentException(SR.StreamLengthMismatch);
            }

            if (stream.CanSeek && maxLength.HasValue && stream.Length - stream.Position > maxLength)
            {
                throw new InvalidOperationException(SR.StreamLengthError);
            }

            if (stream.CanSeek && copyLength.HasValue && stream.Length - stream.Position < copyLength)
            {
                throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
            }

            byte[] buffer = new byte[GetBufferSize(stream)];

            if (streamCopyState != null && calculateChecksum.HasAny && streamCopyState.ChecksumWrapper == null)
            {
                streamCopyState.ChecksumWrapper = new ChecksumWrapper(calculateChecksum.MD5, calculateChecksum.CRC64);
            }

            RegisteredWaitHandle waitHandle     = null;
            ManualResetEvent     completedEvent = null;

            if (!syncRead && executionState.OperationExpiryTime.HasValue)
            {
                completedEvent = new ManualResetEvent(false);
                waitHandle     = ThreadPool.RegisterWaitForSingleObject(
                    completedEvent,
                    StreamExtensions.MaximumCopyTimeCallback <T>,
                    executionState,
                    executionState.RemainingTimeout,
                    true);
            }

            try
            {
                long?bytesRemaining = copyLength;
                int  readCount;
                do
                {
                    if (executionState.OperationExpiryTime.HasValue && DateTime.Now.CompareTo(executionState.OperationExpiryTime.Value) > 0)
                    {
                        throw Exceptions.GenerateTimeoutException(executionState.Cmd != null ? executionState.Cmd.CurrentResult : null, null);
                    }

                    // Determine how many bytes to read this time so that no more than copyLength bytes are read
                    int bytesToRead = MinBytesToRead(bytesRemaining, buffer.Length);

                    if (bytesToRead == 0)
                    {
                        break;
                    }

                    // Read synchronously or asynchronously
                    readCount = syncRead
                                    ? stream.Read(buffer, 0, bytesToRead)
                                    : stream.EndRead(stream.BeginRead(buffer, 0, bytesToRead, null /* Callback */, null /* State */));

                    // Decrement bytes to write from bytes read
                    if (bytesRemaining.HasValue)
                    {
                        bytesRemaining -= readCount;
                    }

                    // Write
                    if (readCount > 0)
                    {
                        toStream.Write(buffer, 0, readCount);

                        // Update the StreamDescriptor after the bytes are successfully committed to the output stream
                        if (streamCopyState != null)
                        {
                            streamCopyState.Length += readCount;

                            if (maxLength.HasValue && streamCopyState.Length > maxLength.Value)
                            {
                                throw new InvalidOperationException(SR.StreamLengthError);
                            }

                            if (streamCopyState.ChecksumWrapper != null)
                            {
                                streamCopyState.ChecksumWrapper.UpdateHash(buffer, 0, readCount);
                            }
                        }
                    }
                }while (readCount != 0);

                if (bytesRemaining.HasValue && bytesRemaining != 0)
                {
                    throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
                }
            }
            catch (Exception)
            {
                if (executionState.OperationExpiryTime.HasValue && DateTime.Now.CompareTo(executionState.OperationExpiryTime.Value) > 0)
                {
                    throw Exceptions.GenerateTimeoutException(executionState.Cmd != null ? executionState.Cmd.CurrentResult : null, null);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (waitHandle != null)
                {
                    waitHandle.Unregister(null);
                }

                if (completedEvent != null)
                {
                    completedEvent.Close();
                }
            }

            if (streamCopyState != null && streamCopyState.ChecksumWrapper != null)
            {
                if (streamCopyState.ChecksumWrapper.CRC64 != null)
                {
                    streamCopyState.Crc64 = streamCopyState.ChecksumWrapper.CRC64.ComputeHash();
                }
                if (streamCopyState.ChecksumWrapper.MD5 != null)
                {
                    streamCopyState.Md5 = streamCopyState.ChecksumWrapper.MD5.ComputeHash();
                }
                streamCopyState.ChecksumWrapper = null;
            }
        }
コード例 #2
0
        internal static Task WriteToAsync <T>(this Stream stream, Stream toStream, IBufferManager bufferManager, long?copyLength, long?maxLength, ChecksumRequested calculateChecksum, ExecutionState <T> executionState, StreamDescriptor streamCopyState, CancellationToken cancellationToken, Action <ExecutionState <T> > completed = null)
        {
            AsyncStreamCopier <T> copier = new AsyncStreamCopier <T>(stream, toStream, executionState, bufferManager, GetBufferSize(stream), calculateChecksum, streamCopyState);

            return(copier.StartCopyStream(completed, copyLength, maxLength, cancellationToken));
        }
コード例 #3
0
        /// <summary>
        /// Constructs a web request to return a specified range of the file's content, together with its properties and metadata.
        /// </summary>
        /// <param name="uri">The absolute URI to the file.</param>
        /// <param name="timeout">The server timeout interval, in seconds.</param>
        /// <param name="offset">The byte offset at which to begin returning content.</param>
        /// <param name="count">The number of bytes to return, or null to return all bytes through the end of the file.</param>
        /// <param name="shareSnapshot">A <see cref="DateTimeOffset"/> specifying the share snapshot timestamp, if the share is a snapshot.</param>
        /// <param name="accessCondition">The access condition to apply to the request.</param>
        /// <returns>A web request to use to perform the operation.</returns>
        public static StorageRequestMessage Get(Uri uri, int?timeout, long?offset, long?count, ChecksumRequested rangeContentChecksumRequested, DateTimeOffset?shareSnapshot, AccessCondition accessCondition, HttpContent content, OperationContext operationContext, ICanonicalizer canonicalizer, StorageCredentials credentials)
        {
            if (offset.HasValue && offset.Value < 0)
            {
                CommonUtility.ArgumentOutOfRange("offset", offset);
            }

            rangeContentChecksumRequested.AssertInBounds(offset, count, Constants.MaxRangeGetContentMD5Size, Constants.MaxRangeGetContentCRC64Size);

            StorageRequestMessage request = Get(uri, timeout, shareSnapshot, accessCondition, content, operationContext, canonicalizer, credentials);

            AddRange(request, offset, count);

            request.ApplyRangeContentChecksumRequested(offset, rangeContentChecksumRequested);

            return(request);
        }
コード例 #4
0
        /// <summary>
        /// Asynchronously reads the entire content of the stream and writes it to the given output stream.
        /// </summary>
        /// <param name="stream">The origin stream.</param>
        /// <param name="toStream">The destination stream.</param>
        /// <param name="bufferManager">IBufferManager instance to use. May be null.</param>
        /// <param name="copyLength">Number of bytes to copy from source stream to destination stream. Cannot be passed with a value for maxLength.</param>
        /// <param name="maxLength">Maximum length of the source stream. Cannot be passed with a value for copyLength.</param>
        /// <param name="calculateChecksum">A value indicating whether the checksums should be calculated.</param>
        /// <param name="executionState">An object that stores state of the operation.</param>
        /// <param name="streamCopyState">An object that represents the current state for the copy operation.</param>
        /// <param name="token">A CancellationToken to observe while waiting for the copy to complete.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        internal static async Task WriteToAsync <T>(this Stream stream, Stream toStream, IBufferManager bufferManager, long?copyLength, long?maxLength, ChecksumRequested calculateChecksum, ExecutionState <T> executionState, StreamDescriptor streamCopyState, CancellationToken token)
        {
            if (copyLength.HasValue && maxLength.HasValue)
            {
                throw new ArgumentException(SR.StreamLengthMismatch);
            }

            if (stream.CanSeek && maxLength.HasValue && stream.Length - stream.Position > maxLength)
            {
                throw new InvalidOperationException(SR.StreamLengthError);
            }

            if (stream.CanSeek && copyLength.HasValue && stream.Length - stream.Position < copyLength)
            {
                throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
            }

            if (streamCopyState != null && calculateChecksum.HasAny && streamCopyState.ChecksumWrapper == null)
            {
                streamCopyState.ChecksumWrapper = new ChecksumWrapper(calculateChecksum.MD5, calculateChecksum.CRC64);
            }

            CancellationTokenSource cts = null;

            byte[] buffer = bufferManager != null?bufferManager.TakeBuffer(GetBufferSize(stream)) : new byte[GetBufferSize(stream)];

            try
            {
                if (executionState.OperationExpiryTime.HasValue)
                {
                    // Setup token for timeout
                    cts = CancellationTokenSource.CreateLinkedTokenSource(token);
                    cts.CancelAfter(executionState.RemainingTimeout);

                    // Switch tokens
                    token = cts.Token;
                }

                long?bytesRemaining = copyLength;
                int  readCount;
                do
                {
                    // Determine how many bytes to read this time so that no more than count bytes are read
                    int bytesToRead = bytesRemaining.HasValue && bytesRemaining < buffer.Length ? (int)bytesRemaining : buffer.Length;

                    if (bytesToRead == 0)
                    {
                        break;
                    }

                    readCount = await stream.ReadAsync(buffer, 0, bytesToRead, token).ConfigureAwait(false);

                    if (bytesRemaining.HasValue)
                    {
                        bytesRemaining -= readCount;
                    }

                    if (readCount > 0)
                    {
                        await toStream.WriteAsync(buffer, 0, readCount, token).ConfigureAwait(false);

                        // Update the StreamDescriptor after the bytes are successfully committed to the output stream
                        if (streamCopyState != null)
                        {
                            streamCopyState.Length += readCount;

                            if (maxLength.HasValue && streamCopyState.Length > maxLength.Value)
                            {
                                throw new InvalidOperationException(SR.StreamLengthError);
                            }

                            if (streamCopyState.ChecksumWrapper != null)
                            {
                                streamCopyState.ChecksumWrapper.UpdateHash(buffer, 0, readCount);
                            }
                        }
                    }
                }while (readCount > 0);

                if (bytesRemaining.HasValue && bytesRemaining != 0)
                {
                    throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
                }
            }
            finally
            {
                if (cts != null)
                {
                    cts.Dispose();
                    cts = null;
                }

                if (buffer != null && bufferManager != null)
                {
                    bufferManager.ReturnBuffer(buffer);
                }
            }

            // Streams opened with AsStreamForWrite extension need to be flushed
            // to write all buffered data to the underlying Windows Runtime stream.
            await toStream.FlushAsync().ConfigureAwait(false);

            if (streamCopyState != null && streamCopyState.ChecksumWrapper != null)
            {
                if (streamCopyState.ChecksumWrapper.CRC64 != null)
                {
                    streamCopyState.Crc64 = streamCopyState.ChecksumWrapper.CRC64.ComputeHash();
                }
                if (streamCopyState.ChecksumWrapper.MD5 != null)
                {
                    streamCopyState.Md5 = streamCopyState.ChecksumWrapper.MD5.ComputeHash();
                }
                streamCopyState.ChecksumWrapper = null;
            }
        }
コード例 #5
0
        /// <summary>
        /// Creates and initializes a new asynchronous copy operation.
        /// </summary>
        /// <param name="src">The source stream.</param>
        /// <param name="dest">The destination stream.</param>
        /// <param name="state">An ExecutionState used to coordinate copy operation.</param>
        /// <param name="bufferManager">IBufferManager instance to use.  May be null.</param>
        /// <param name="buffSize">Size of read and write buffers used to move data.  Overrides the default buffer size of bufferManager.</param>
        /// <param name="calculateChecksum">A value indicating whether the checksums should be calculated.</param>
        /// <param name="streamCopyState">An object that represents the state for the current operation.</param>
        public AsyncStreamCopier(Stream src, Stream dest, ExecutionState <T> state, IBufferManager bufferManager, int?buffSize, ChecksumRequested calculateChecksum, StreamDescriptor streamCopyState)
        {
            this.src             = src;
            this.dest            = dest;
            this.state           = state;
            this.bufferManager   = bufferManager;
            this.buffSize        = buffSize ?? (bufferManager != null ? bufferManager.GetDefaultBufferSize() : Constants.DefaultBufferSize);
            this.streamCopyState = streamCopyState;

            if (streamCopyState != null && calculateChecksum.HasAny && streamCopyState.ChecksumWrapper == null)
            {
                streamCopyState.ChecksumWrapper = new ChecksumWrapper(calculateChecksum.MD5, calculateChecksum.CRC64);
            }
        }