Esempio n. 1
0
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                this.CloseOwnStream();

                if (null != this.md5HashStream)
                {
                    this.md5HashStream.Dispose();
                    this.md5HashStream = null;
                }
            }
        }
        private void CloseOwnedOutputStream()
        {
            if (null != this.md5HashStream)
            {
                this.md5HashStream.Dispose();
                this.md5HashStream = null;
            }

            if (this.ownsStream)
            {
                if (null != this.outputStream)
                {
                    this.outputStream.Close();
                    this.outputStream = null;
                }
            }
        }
        private void CloseOwnedOutputStream()
        {
            if (null != this.md5HashStream)
            {
                this.md5HashStream.Dispose();
                this.md5HashStream = null;
            }

            if (this.ownsStream)
            {
                if (null != this.outputStream)
                {
#if DOTNET5_4
                    this.outputStream.Dispose();
#else
                    this.outputStream.Close();
#endif
                    this.outputStream = null;
                }
            }
        }
        private async Task HandleOutputStreamAsync()
        {
            this.hasWork = false;

            await Task.Run(async() =>
            {
                // Only do calculation related to transfer window when the file contains multiple chunks.
                if (!this.EnableOneChunkFileOptimization)
                {
                    // We do check point consistancy validation in reader, and directly use it in writer.
                    if ((null != this.TransferJob.CheckPoint.TransferWindow) &&
                        this.TransferJob.CheckPoint.TransferWindow.Any())
                    {
                        this.TransferJob.CheckPoint.TransferWindow.Sort();
                        this.expectOffset = this.TransferJob.CheckPoint.TransferWindow[0];
                    }
                    else
                    {
                        this.expectOffset = this.TransferJob.CheckPoint.EntryTransferOffset;
                    }
                }

                if (TransferLocationType.Stream == this.TransferJob.Destination.Type)
                {
                    Stream streamInDestination = (this.TransferJob.Destination as StreamLocation).Stream;
                    if (!streamInDestination.CanWrite)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportWriteException,
                                                            "outputStream"));
                    }

                    if (!streamInDestination.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportSeekException,
                                                            "outputStream"));
                    }

                    this.outputStream = streamInDestination;
                }
                else
                {
                    string filePath = (this.TransferJob.Destination as FileLocation).FilePath;

                    if (!this.Controller.IsForceOverwrite)
                    {
                        await this.Controller.CheckOverwriteAsync(
                            LongPathFile.Exists(filePath),
                            this.TransferJob.Source.Instance,
                            filePath);
                    }

                    this.Controller.CheckCancellation();

                    try
                    {
                        FileMode fileMode = 0 == this.expectOffset ? FileMode.OpenOrCreate : FileMode.Open;

#if DOTNET5_4
                        string longFilePath = filePath;
                        if (Interop.CrossPlatformHelpers.IsWindows)
                        {
                            longFilePath = LongPath.ToUncPath(longFilePath);
                        }

                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.outputStream = new FileStream(
                            longFilePath,
                            fileMode,
                            FileAccess.ReadWrite,
                            FileShare.None);
#else
                        this.outputStream = LongPathFile.Open(
                            filePath,
                            fileMode,
                            FileAccess.ReadWrite,
                            FileShare.None);
#endif

                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        string exceptionMessage = string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.FailedToOpenFileException,
                            filePath,
                            ex.Message);

                        throw new TransferException(
                            TransferErrorCode.OpenFileFailed,
                            exceptionMessage,
                            ex);
                    }
                }

                this.outputStream.SetLength(this.SharedTransferData.TotalLength);

                this.md5HashStream = new MD5HashStream(
                    this.outputStream,
                    this.expectOffset,
                    !this.SharedTransferData.DisableContentMD5Validation);

                if (this.md5HashStream.FinishedSeparateMd5Calculator)
                {
                    this.state = State.Write;
                }
                else
                {
                    this.state = State.CalculateMD5;
                }

                this.PreProcessed = true;

                // Switch state internal for one chunk small file.
                if (this.EnableOneChunkFileOptimization &&
                    State.Write == this.state &&
                    ((this.SharedTransferData.TotalLength == this.expectOffset) || this.SharedTransferData.AvailableData.ContainsKey(this.expectOffset)))
                {
                    this.isStateSwitchedInternal = true;
                    await this.WriteChunkDataAsync().ConfigureAwait(false);
                }
                else
                {
                    this.hasWork = true;
                }
            });
        }
        private async Task HandleOutputStreamAsync()
        {
            this.hasWork = false;

            await Task.Run(() =>
            {
                if (TransferLocationType.Stream == this.TransferJob.Destination.TransferLocationType)
                {
                    Stream streamInDestination = this.TransferJob.Destination.Stream;
                    if (!streamInDestination.CanWrite)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportWriteException,
                                                            "outputStream"));
                    }

                    if (!streamInDestination.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportSeekException,
                                                            "outputStream"));
                    }

                    this.outputStream = this.TransferJob.Destination.Stream;
                }
                else
                {
                    this.Controller.CheckOverwrite(
                        File.Exists(this.TransferJob.Destination.FilePath),
                        this.SharedTransferData.SourceLocation,
                        this.TransferJob.Destination.FilePath);

                    this.Controller.UpdateProgressAddBytesTransferred(0);

                    this.Controller.CheckCancellation();

                    // We do check point consistancy validation in reader, and directly use it in writer.
                    if ((null != this.TransferJob.CheckPoint.TransferWindow) &&
                        (this.TransferJob.CheckPoint.TransferWindow.Any()))
                    {
                        this.TransferJob.CheckPoint.TransferWindow.Sort();
                        this.expectOffset = this.TransferJob.CheckPoint.TransferWindow[0];
                    }
                    else
                    {
                        this.expectOffset = this.TransferJob.CheckPoint.EntryTransferOffset;
                    }

                    try
                    {
                        FileMode fileMode = 0 == this.expectOffset ? FileMode.OpenOrCreate : FileMode.Open;

                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.outputStream = new FileStream(
                            this.TransferJob.Destination.FilePath,
                            fileMode,
                            FileAccess.ReadWrite,
                            FileShare.None);

                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        string exceptionMessage = string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.FailedToOpenFileException,
                            this.TransferJob.Destination.FilePath,
                            ex.Message);

                        throw new TransferException(
                            TransferErrorCode.OpenFileFailed,
                            exceptionMessage,
                            ex);
                    }
                }

                this.outputStream.SetLength(this.SharedTransferData.TotalLength);

                this.Controller.UpdateProgressAddBytesTransferred(0);

                this.md5HashStream = new MD5HashStream(
                    this.outputStream,
                    this.expectOffset,
                    !this.SharedTransferData.DisableContentMD5Validation);

                if (this.md5HashStream.FinishedSeparateMd5Calculator)
                {
                    this.state = State.Write;
                }
                else
                {
                    this.state = State.CalculateMD5;
                }

                this.PreProcessed = true;
                this.hasWork      = true;
            });
        }
Esempio n. 6
0
        private async Task OpenInputStreamAsync()
        {
            Debug.Assert(
                State.OpenInputStream == this.state,
                "OpenInputStreamAsync called, but state is not OpenInputStream.");

            if (Interlocked.CompareExchange(ref workToken, 0, 1) == 0)
            {
                return;
            }

            await Task.Yield();

            this.NotifyStarting();
            this.Controller.CheckCancellation();

            if (this.transferJob.Source.Type == TransferLocationType.Stream)
            {
                StreamLocation streamLocation = this.transferJob.Source as StreamLocation;
                this.inputStream = streamLocation.Stream;
                this.ownsStream  = false;

                if (!this.inputStream.CanRead)
                {
                    throw new NotSupportedException(string.Format(
                                                        CultureInfo.CurrentCulture,
                                                        Resources.StreamMustSupportReadException,
                                                        "inputStream"));
                }
            }
            else
            {
                FileLocation fileLocation = this.transferJob.Source as FileLocation;
                Debug.Assert(
                    null != fileLocation,
                    "Initializing StreamedReader instance, but source is neither a stream nor a file");

                try
                {
                    if (fileLocation.RelativePath != null &&
                        fileLocation.RelativePath.Length > Constants.MaxRelativePathLength)
                    {
                        string errorMessage = string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.RelativePathTooLong,
                            fileLocation.RelativePath);
                        throw new TransferException(TransferErrorCode.OpenFileFailed, errorMessage);
                    }

                    this.filePath = fileLocation.FilePath.ToLongPath();

#if DOTNET5_4
                    // Attempt to open the file first so that we throw an exception before getting into the async work
                    this.inputStream = new FileStream(
                        filePath,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Read);
#else
                    this.inputStream = LongPathFile.Open(
                        this.filePath,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Read);
#endif
                    this.ownsStream = true;
                }
                catch (Exception ex)
                {
                    if ((ex is NotSupportedException) ||
                        (ex is IOException) ||
                        (ex is UnauthorizedAccessException) ||
                        (ex is SecurityException) ||
                        (ex is ArgumentException && !(ex is ArgumentNullException)))
                    {
                        string exceptionMessage = string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.FailedToOpenFileException,
                            fileLocation.FilePath,
                            ex.Message);

                        throw new TransferException(
                                  TransferErrorCode.OpenFileFailed,
                                  exceptionMessage,
                                  ex);
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            try
            {
                this.SharedTransferData.TotalLength = this.inputStream.Length;
            }
            catch (NotSupportedException)
            {
                this.SharedTransferData.TotalLength = -1;
            }

            // Only do calculation related to transfer window when the file contains multiple chunks.
            if (!this.EnableOneChunkFileOptimization)
            {
                var checkpoint = this.transferJob.CheckPoint;

                checkpoint.TransferWindow.Sort();

                this.readLength = checkpoint.EntryTransferOffset;

                if (checkpoint.TransferWindow.Any())
                {
                    // The size of last block can be smaller than BlockSize.
                    this.readLength -= Math.Min(checkpoint.EntryTransferOffset - checkpoint.TransferWindow.Last(), this.SharedTransferData.BlockSize);
                    this.readLength -= (checkpoint.TransferWindow.Count - 1) * this.SharedTransferData.BlockSize;
                }

                if (this.readLength < 0)
                {
                    throw new InvalidOperationException(Resources.RestartableInfoCorruptedException);
                }
                else if ((checkpoint.EntryTransferOffset > 0) && (!this.inputStream.CanSeek))
                {
                    throw new NotSupportedException(string.Format(
                                                        CultureInfo.CurrentCulture,
                                                        Resources.StreamMustSupportSeekException,
                                                        "inputStream"));
                }

                this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow);
            }

            this.md5HashStream = new MD5HashStream(
                this.inputStream,
                this.transferJob.CheckPoint.EntryTransferOffset,
                true);

            this.PreProcessed = true;

            if (this.readLength != this.SharedTransferData.TotalLength)
            {
                // Change the state to 'ReadStream' before awaiting MD5 calculation task to not block the reader.
                this.state     = State.ReadStream;
                this.workToken = 1;
            }
            else
            {
                Interlocked.Exchange(ref this.readCompleted, 1);
            }

            if (!this.md5HashStream.FinishedSeparateMd5Calculator)
            {
                await Task.Run(() =>
                {
                    this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation);
                });
            }

            this.SetChunkFinish();
        }
        private async Task OpenInputStreamAsync()
        {
            Debug.Assert(
                State.OpenInputStream == this.state,
                "OpenInputStreamAsync called, but state is not OpenInputStream.");

            this.hasWork = false;

            await Task.Run(() =>
            {
                this.NotifyStarting();
                this.Controller.CheckCancellation();

                if (this.transferJob.Source.Type == TransferLocationType.Stream)
                {
                    StreamLocation streamLocation = this.transferJob.Source as StreamLocation;
                    this.inputStream = streamLocation.Stream;
                    this.ownsStream  = false;

                    if (!this.inputStream.CanRead)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportReadException,
                                                            "inputStream"));
                    }

                    if (!this.inputStream.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportSeekException,
                                                            "inputStream"));
                    }
                }
                else
                {
                    FileLocation fileLocation = this.transferJob.Source as FileLocation;
                    Debug.Assert(
                        null != fileLocation,
                        "Initializing StreamedReader instance, but source is neither a stream nor a file");

                    try
                    {
                        if (fileLocation.RelativePath != null &&
                            fileLocation.RelativePath.Length > Constants.MaxRelativePathLength)
                        {
                            string errorMessage = string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.RelativePathTooLong,
                                fileLocation.RelativePath);
                            throw  new TransferException(TransferErrorCode.OpenFileFailed, errorMessage);
                        }
#if DOTNET5_4
                        string filePath = fileLocation.FilePath;
                        if (Interop.CrossPlatformHelpers.IsWindows)
                        {
                            filePath = LongPath.ToUncPath(fileLocation.FilePath);
                        }
                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.inputStream = new FileStream(
                            filePath,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read);
#else
                        this.inputStream = LongPathFile.Open(
                            fileLocation.FilePath,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read);
#endif
                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        if ((ex is NotSupportedException) ||
                            (ex is IOException) ||
                            (ex is UnauthorizedAccessException) ||
                            (ex is SecurityException) ||
                            (ex is ArgumentException && !(ex is ArgumentNullException)))
                        {
                            string exceptionMessage = string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.FailedToOpenFileException,
                                fileLocation.FilePath,
                                ex.Message);

                            throw new TransferException(
                                TransferErrorCode.OpenFileFailed,
                                exceptionMessage,
                                ex);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            });

            this.SharedTransferData.TotalLength = this.inputStream.Length;

            int count = (int)Math.Ceiling((double)(this.SharedTransferData.TotalLength - this.transferJob.CheckPoint.EntryTransferOffset) / this.SharedTransferData.BlockSize);

            if (null != this.transferJob.CheckPoint.TransferWindow)
            {
                count += this.transferJob.CheckPoint.TransferWindow.Count;
            }

            this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow);

            this.md5HashStream = new MD5HashStream(
                this.inputStream,
                this.transferJob.CheckPoint.EntryTransferOffset,
                true);

            this.PreProcessed = true;

            // This reader will come into 'Finish' state after all chunks are read and MD5 calculation completes.
            // So initialize the CountDownEvent to count (number of chunks to read) + 1 (md5 calculation).
            this.countdownEvent = new CountdownEvent(count + 1);

            if (0 != count)
            {
                // Change the state to 'ReadStream' before awaiting MD5 calculation task to not block the reader.
                this.state   = State.ReadStream;
                this.hasWork = true;
            }

            if (!this.md5HashStream.FinishedSeparateMd5Calculator)
            {
                await Task.Run(() =>
                {
                    this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation);
                });
            }

            this.SetChunkFinish();
        }
        private void CloseOwnedOutputStream()
        {
            if (null != this.md5HashStream)
            {
                this.md5HashStream.Dispose();
                this.md5HashStream = null;
            }

            if (this.ownsStream)
            {
                if (null != this.outputStream)
                {
                    this.outputStream.Close();
                    this.outputStream = null;
                }
            }
        }
        private async Task HandleOutputStreamAsync()
        {
            this.hasWork = false;

            await Task.Run(() =>
            {
                if (TransferLocationType.Stream == this.TransferJob.Destination.Type)
                {
                    Stream streamInDestination = (this.TransferJob.Destination as StreamLocation).Stream;
                    if (!streamInDestination.CanWrite)
                    {
                        throw new NotSupportedException(string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.StreamMustSupportWriteException,
                            "outputStream"));
                    }

                    if (!streamInDestination.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.StreamMustSupportSeekException,
                            "outputStream"));
                    }

                    this.outputStream = streamInDestination;
                }
                else
                {
                    string filePath = (this.TransferJob.Destination as FileLocation).FilePath;
                    this.Controller.CheckOverwrite(
                        File.Exists(filePath),
                        this.SharedTransferData.SourceLocation,
                        filePath);

                    this.Controller.UpdateProgressAddBytesTransferred(0);

                    this.Controller.CheckCancellation();

                    // We do check point consistancy validation in reader, and directly use it in writer.
                    if ((null != this.TransferJob.CheckPoint.TransferWindow)
                        && (this.TransferJob.CheckPoint.TransferWindow.Any()))
                    {
                        this.TransferJob.CheckPoint.TransferWindow.Sort();
                        this.expectOffset = this.TransferJob.CheckPoint.TransferWindow[0];
                    }
                    else
                    {
                        this.expectOffset = this.TransferJob.CheckPoint.EntryTransferOffset;
                    }

                    try
                    {
                        FileMode fileMode = 0 == this.expectOffset ? FileMode.OpenOrCreate : FileMode.Open;

                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.outputStream = new FileStream(
                            filePath,
                            fileMode,
                            FileAccess.ReadWrite,
                            FileShare.None);

                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        string exceptionMessage = string.Format(
                                    CultureInfo.CurrentCulture,
                                    Resources.FailedToOpenFileException,
                                    filePath,
                                    ex.Message);

                        throw new TransferException(
                                TransferErrorCode.OpenFileFailed,
                                exceptionMessage,
                                ex);
                    }
                }

                this.outputStream.SetLength(this.SharedTransferData.TotalLength);

                this.Controller.UpdateProgressAddBytesTransferred(0);

                this.md5HashStream = new MD5HashStream(
                    this.outputStream,
                    this.expectOffset,
                    !this.SharedTransferData.DisableContentMD5Validation);

                if (this.md5HashStream.FinishedSeparateMd5Calculator)
                {
                    this.state = State.Write;
                }
                else
                {
                    this.state = State.CalculateMD5;
                }

                this.PreProcessed = true;
                this.hasWork = true;
            });
        }
Esempio n. 10
0
        private async Task OpenInputStreamAsync()
        {
            Debug.Assert(
                State.OpenInputStream == this.state,
                "OpenInputStreamAsync called, but state is not OpenInputStream.");

            this.hasWork = false;

            await Task.Run(() =>
            {
                this.NotifyStarting();
                this.Controller.CheckCancellation();

                if (this.transferJob.Source.Type == TransferLocationType.Stream)
                {
                    StreamLocation streamLocation = this.transferJob.Source as StreamLocation;
                    this.inputStream = streamLocation.Stream;
                    this.ownsStream  = false;

                    if (!this.inputStream.CanRead)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportReadException,
                                                            "inputStream"));
                    }

                    if (!this.inputStream.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                                                            CultureInfo.CurrentCulture,
                                                            Resources.StreamMustSupportSeekException,
                                                            "inputStream"));
                    }
                }
                else
                {
                    FileLocation fileLocation = this.transferJob.Source as FileLocation;
                    Debug.Assert(
                        null != fileLocation,
                        "Initializing StreamedReader instance, but source is neither a stream nor a file");
                    this.SharedTransferData.SourceLocation = fileLocation.ToString();

                    try
                    {
                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.inputStream = new FileStream(
                            fileLocation.FilePath,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read);

                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        if ((ex is NotSupportedException) ||
                            (ex is IOException) ||
                            (ex is UnauthorizedAccessException) ||
                            (ex is SecurityException) ||
                            (ex is ArgumentException && !(ex is ArgumentNullException)))
                        {
                            string exceptionMessage = string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.FailedToOpenFileException,
                                fileLocation.FilePath,
                                ex.Message);

                            throw new TransferException(
                                TransferErrorCode.OpenFileFailed,
                                exceptionMessage,
                                ex);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            });

            this.SharedTransferData.TotalLength = this.inputStream.Length;

            int count = (int)Math.Ceiling((double)(this.SharedTransferData.TotalLength - this.transferJob.CheckPoint.EntryTransferOffset) / this.Scheduler.TransferOptions.BlockSize);

            if (null != this.transferJob.CheckPoint.TransferWindow)
            {
                count += this.transferJob.CheckPoint.TransferWindow.Count;
            }

            this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow);

            this.md5HashStream = new MD5HashStream(
                this.inputStream,
                this.transferJob.CheckPoint.EntryTransferOffset,
                true);

            this.PreProcessed = true;

            if (!this.md5HashStream.FinishedSeparateMd5Calculator)
            {
                await Task.Run(() =>
                {
                    this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation);
                });
            }

            if (0 == count)
            {
                this.countdownEvent = new CountdownEvent(1);
                this.SetChunkFinish();
            }
            else
            {
                this.countdownEvent = new CountdownEvent(count);

                this.state   = State.ReadStream;
                this.hasWork = true;
            }
        }
        private async Task OpenInputStreamAsync()
        {
            Debug.Assert(
                State.OpenInputStream == this.state,
                "OpenInputStreamAsync called, but state is not OpenInputStream.");

            this.hasWork = false;

            await Task.Run(() =>
            {
                this.NotifyStarting();
                this.Controller.CheckCancellation();

                if (this.transferJob.Source.Stream != null)
                {
                    this.inputStream = this.transferJob.Source.Stream;
                    this.ownsStream = false;

                    if (!this.inputStream.CanRead)
                    {
                        throw new NotSupportedException(string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.StreamMustSupportReadException,
                            "inputStream"));
                    }

                    if (!this.inputStream.CanSeek)
                    {
                        throw new NotSupportedException(string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.StreamMustSupportSeekException,
                            "inputStream"));
                    }
                }
                else
                {
                    Debug.Assert(
                        !string.IsNullOrEmpty(this.transferJob.Source.FilePath),
                        "Initializing StreamedReader instance, but source is neither a stream nor a file");
                    this.SharedTransferData.SourceLocation = this.transferJob.Source.FilePath;

                    try
                    {
                        // Attempt to open the file first so that we throw an exception before getting into the async work
                        this.inputStream = new FileStream(
                            this.transferJob.Source.FilePath,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read);

                        this.ownsStream = true;
                    }
                    catch (Exception ex)
                    {
                        if ((ex is NotSupportedException) ||
                            (ex is IOException) ||
                            (ex is UnauthorizedAccessException) ||
                            (ex is SecurityException) ||
                            (ex is ArgumentException && !(ex is ArgumentNullException)))
                        {
                            string exceptionMessage = string.Format(
                                        CultureInfo.CurrentCulture,
                                        Resources.FailedToOpenFileException,
                                        this.transferJob.Source.FilePath,
                                        ex.Message);

                            throw new TransferException(
                                    TransferErrorCode.OpenFileFailed,
                                    exceptionMessage,
                                    ex);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            });

            this.SharedTransferData.TotalLength = this.inputStream.Length;

            int count = (int)Math.Ceiling((double)(this.SharedTransferData.TotalLength - this.transferJob.CheckPoint.EntryTransferOffset) / this.Scheduler.TransferOptions.BlockSize);

            if (null != this.transferJob.CheckPoint.TransferWindow)
            {
                count += this.transferJob.CheckPoint.TransferWindow.Count;
            }

            this.lastTransferWindow = new Queue<long>(this.transferJob.CheckPoint.TransferWindow);

            this.md5HashStream = new MD5HashStream(
                this.inputStream,
                this.transferJob.CheckPoint.EntryTransferOffset,
                true);

            this.PreProcessed = true;

            if (!this.md5HashStream.FinishedSeparateMd5Calculator)
            {
                await Task.Run(() =>
                {
                    this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation);
                });
            }

            if (0 == count)
            {
                this.countdownEvent = new CountdownEvent(1);
                this.SetChunkFinish();
            }
            else
            {
                this.countdownEvent = new CountdownEvent(count);

                this.state = State.ReadStream;
                this.hasWork = true;
            }
        }
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                this.CloseOwnStream();

                if (null != this.md5HashStream)
                {
                    this.md5HashStream.Dispose();
                    this.md5HashStream = null;
                }

                if (null != this.countdownEvent)
                {
                    this.countdownEvent.Dispose();
                }
            }
        }