/// <summary> /// Method that reads source file and places blocks into <paramref name="queue"/>. The receiver must return blocks to blockpool. /// /// This method is to be ran in a concurrent thread. /// /// If cancel is requested, aborts. /// /// If ioexception occurs, then sets op state to error. /// </summary> /// <param name="queue"></param> void ReadFile(BlockingCollection <Block> queue) { try { // CancelToken to monitor CancellationToken token = session.CancelSrc.Token; if (token.IsCancellationRequested) { return; } // Open file Stream s = SrcFileSystem.Open(SrcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, srcOption.OptionIntersection(session.Option)); try { int len = 0; do { // Cancelled, abort if (token.IsCancellationRequested || CurrentState != OperationState.Running) { queue.Add(new Block { data = null, count = -1 /* cancellation */ }); return; } // Allocate block byte[] data = session.BlockPool.Allocate(); // Read data to block len = s.Read(data, 0, data.Length); // Pass block if (len > 0) { queue.Add(new Block { data = data, count = len }); } } while (len > 0); // Notify of eos with 0 length queue.Add(new Block { data = null, count = 0 }); } finally { s.Dispose(); } } // Capture error and set state catch (Exception e) { // Set state of op to error SetError(e); // Notify of error with -2 length queue.Add(new Block { data = null, count = -2 }); } }
/// <summary>Estimate viability of operation.</summary> /// <exception cref="FileNotFoundException">If <see cref="SrcPath"/> is not found.</exception> /// <exception cref="FileSystemExceptionEntryExists">If <see cref="Path"/> already exists.</exception> protected override void InnerEstimate() { // Cannot create if (!FileSystem.CanOpen() || !FileSystem.CanCreateFile()) { throw new NotSupportedException("Copy"); } // Test that source file exists if (SrcFileSystem.CanGetEntry()) { try { IEntry e = SrcFileSystem.GetEntry(SrcPath, srcOption.OptionIntersection(session.Option)); // Src not found if (e == null) { // Throw if (EffectivePolicy.HasFlag(OperationPolicy.SrcThrow)) { throw new FileNotFoundException(SrcPath); } // Skip if (EffectivePolicy.HasFlag(OperationPolicy.SrcSkip)) { SetState(OperationState.Skipped); return; } } // Set length if (e.Length() > 0L) { this.TotalLength = e.Length(); } } catch (NotSupportedException) { // GetEntry is not supported } } // Test that dest file doesn't exist if (FileSystem.CanGetEntry()) { try { IEntry dstEntry = dstFileSystem.GetEntry(Path, Option.OptionIntersection(session.Option)); prevExisted = dstEntry != null; if (dstEntry != null) { // Dst exists if (EffectivePolicy.HasFlag(OperationPolicy.DstThrow)) { if (dstEntry.IsFile()) { throw new FileSystemExceptionFileExists(FileSystem, Path); } else if (dstEntry.IsDirectory()) { throw new FileSystemExceptionDirectoryExists(FileSystem, Path); } else { throw new FileSystemExceptionEntryExists(FileSystem, Path); } } // Skip op else if (EffectivePolicy.HasFlag(OperationPolicy.DstSkip)) { SetState(OperationState.Skipped); // Nothing to rollback, essentially ok CanRollback = true; } // Overwrite else if (EffectivePolicy.HasFlag(OperationPolicy.DstOverwrite)) { // Cannot rollback CanRollback = false; } } else { // Prev file didn't exist, can be rollbacked CanRollback = true; } } catch (NotSupportedException) { // GetEntry is not supported } } }