public override void Claim(FileSystemCommandConnection connection) { if (!connection.Socket.RemoteEndPoint.Equals(this.OwnerEndPoint)) { connection.WriteError(ErrorCodes.INVALID_PARAM, "ticket"); connection.RunLevel = DisconnectedRunLevel.Default; return; } var src = this.file.GetContent().GetInputStream(this.fileShare); if (this.offset > 0 || this.length != -1) { src = new PartialStream(src, this.offset, this.length); } connection.WriteOk("length", src.Length.ToString(CultureInfo.InvariantCulture)); connection.Flush(); var des = connection.WriteStream; var pump = new StreamCopier(src, des); pump.Run(); connection.RunLevel = DisconnectedRunLevel.Default; }
public override void DoRun() { IFile destinationTemp; Stream destinationTempStream; string sourceHash; try { lock (this) { SetTransferState(TransferState.Preparing); } Action<IFile> transferAttributes = delegate(IFile dest) { using (dest.Attributes.AquireUpdateContext()) { foreach (string s in this.serviceType.AttributesToTransfer) { dest.Attributes[s] = this.source.Attributes[s]; } } }; Stream sourceStream = null; for (var i = 0; i < 4; i++) { try { sourceStream = this.OperatingNode.GetContent().GetInputStream(FileMode.Open, FileShare.Read); break; } catch (NodeNotFoundException) { throw; } catch (Exception) { if (i == 3) { throw; } } ProcessTaskStateRequest(); } using (sourceStream) { var sourceHashingService = (IHashingService)this.OperatingNode.GetService(new StreamHashingServiceType(sourceStream, this.HashAlgorithmName)); // Compute the hash of the source file SetTransferState(TransferState.Comparing); ProcessTaskStateRequest(); sourceHash = sourceHashingService.ComputeHash().TextValue; // Try to open the destination file ProcessTaskStateRequest(); var destinationHashingService = (IHashingService)this.TargetNode.GetService(new FileHashingServiceType(this.HashAlgorithmName)); string destinationHash; try { destinationHash = destinationHashingService.ComputeHash().TextValue; } catch (DirectoryNodeNotFoundException) { this.TargetNode.ParentDirectory.Create(true); try { destinationHash = destinationHashingService.ComputeHash().TextValue; } catch (NodeNotFoundException) { destinationHash = null; } } catch (NodeNotFoundException) { destinationHash = null; } ProcessTaskStateRequest(); // Source and destination are identical if (sourceHash == destinationHash) { SetTransferState(TransferState.Transferring); this.progress.RaiseValueChanged(0, GetBytesToTransfer()); SetTransferState(TransferState.Tidying); // Transfer attributes try { transferAttributes((IFile) this.TargetNode); } catch (FileNotFoundException) { } // Done SetTransferState(TransferState.Finished); ProcessTaskStateRequest(); return; } // Get a temp file for the destination based on the source's hash destinationTemp = ((ITempIdentityFileService)this.destination.GetService(new TempIdentityFileServiceType(sourceHash))).GetTempFile(); // Get the stream for the destination temp file try { if (!destinationTemp.ParentDirectory.Exists) { destinationTemp.ParentDirectory.Create(true); } } catch (IOException) { } using (destinationTempStream = destinationTemp.GetContent().OpenStream(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { Action finishUp = delegate { SetTransferState(TransferState.Tidying); destinationTempStream.Close(); for (int i = 0; i < 4; i++) { try { // Save hash value StandardFileHashingService.SaveHashToCache((IFile) destinationTemp, this.HashAlgorithmName, sourceHash, (IFile) this.TargetNode); try { // Transfer attributes transferAttributes(destinationTemp); } catch (FileNotFoundException e) { Console.WriteLine(e); } // Move destination temp to destination destinationTemp.MoveTo(this.TargetNode, true); break; } catch (Exception) { if (i == 3) { throw; } } ProcessTaskStateRequest(); } // Done SetTransferState(TransferState.Finished); ProcessTaskStateRequest(); }; // Get the hash for the destination temp file var destinationTempHashingService = (IHashingService) destinationTemp.GetService(new StreamHashingServiceType(destinationTempStream)); // If the destination temp and the source aren't the same // then complete the destination temp string destinationTempHash; if (destinationTempStream.Length >= sourceStream.Length) { // Destination is longer than source but starts source (unlikely) destinationTempHash = destinationTempHashingService.ComputeHash(0, sourceStream.Length).TextValue; if (destinationTempHash == sourceHash) { if (destinationTempStream.Length != sourceStream.Length) { destinationTempStream.SetLength(sourceStream.Length); } finishUp(); return; } destinationTempStream.SetLength(0); } if (destinationTempStream.Length > 0) { destinationTempHash = destinationTempHashingService.ComputeHash().TextValue; // Destination shorter than the source but is a partial copy of source sourceHash = sourceHashingService.ComputeHash(0, destinationTempStream.Length).TextValue; if (sourceHash == destinationTempHash) { this.offset = destinationTempStream.Length; } else { this.offset = 0; destinationTempStream.SetLength(0); } } else { this.offset = 0; } this.progress.RaiseValueChanged(0, this.offset); // Transfer over the remaining part needed (or everything if offset is 0) this.offset = destinationTempStream.Length; Stream sourcePartialStream = new PartialStream(sourceStream, destinationTempStream.Length); Stream destinationTempPartialStream = new PartialStream(destinationTempStream, destinationTempStream.Length); this.copier = new StreamCopier(new BufferedStream(sourcePartialStream, this.serviceType.BufferSize), destinationTempPartialStream, false, false, this.serviceType.ChunkSize); this.copier.TaskStateChanged += delegate(object sender, TaskEventArgs eventArgs) { if (eventArgs.TaskState == TaskState.Running || eventArgs.TaskState == TaskState.Paused || eventArgs.TaskState == TaskState.Stopped) { SetTaskState(eventArgs.TaskState); } }; SetTransferState(TransferState.Transferring); ProcessTaskStateRequest(); this.copier.Run(); if (this.copier.TaskState == TaskState.Stopped) { throw new StopRequestedException(); } finishUp(); } } } catch (StopRequestedException) { } finally { if (this.TransferState != TransferState.Finished) { SetTransferState(TransferState.Stopped); } } }
public override void Run() { long x; string id; IFile destTemp; ITempIdentityFileService destTempService; IFile dest; Stream srcStream = null, destStream = null; IFileHashingService hasher; string sourceHash, destTempHash; try { lock (this.SyncLock) { m_TaskThread = Thread.CurrentThread; if (m_TransferState != TransferState.NotStarted) { throw new InvalidOperationException(); } SetTransferState(TransferState.Preparing); ProcessTaskStateRequest(); } id = m_Source.Address.Uri + m_Source.Length.ToString() + (m_Source.Attributes.CreationTime ?? DateTime.MinValue).ToBinary().ToString(); destTempService = (ITempIdentityFileService)m_Destination.GetService(new TempIdentityFileServiceType(id)); destTemp = destTempService.GetTempFile(); for (;;) { try { x = destTemp.Length; } catch (FileNotFoundException) { x = 0; } dest = m_Destination.ParentDirectory.ResolveFile("$TMP_" + m_Destination.Address.Name + "_" + Guid.NewGuid().ToString("N")); try { if (x == m_Source.Length) { try { if (m_Source.IdenticalTo(destTemp, FileComparingFlags.CompareContents)) { SetTransferState(TransferState.Copying); ProcessTaskStateRequest(); m_Progress.RaiseValueChanged(m_Progress.CurrentValue, 0); destTemp.MoveTo(dest, true); if (!m_Source.IdenticalTo(dest, FileComparingFlags.CompareContents)) { continue; } dest.RenameTo(m_Destination.Address.NameAndQuery, true); m_BytesTransferred = m_Destination.Length; m_Progress.RaiseValueChanged(m_Progress.CurrentValue, m_BytesTransferred); SetTransferState(TransferState.Finished); ProcessTaskStateRequest(); return; } } catch (IOException) { } } srcStream = m_Source.GetContent().GetInputStream(FileShare.Read); if (!srcStream.CanSeek) { destStream = destTemp.GetContent().GetOutputStream(FileMode.Create, FileShare.Read); } else { destStream = destTemp.GetContent().GetOutputStream(FileMode.Append, FileShare.Read); SetTransferState(TransferState.Comparing); ProcessTaskStateRequest(); hasher = (IFileHashingService)m_Source.GetService(new FileHashingServiceType("md5")); sourceHash = hasher.ComputeHash(0, destStream.Length).TextValue; hasher = (IFileHashingService)destTemp.GetService(new FileHashingServiceType("md5")); destTempHash = hasher.ComputeHash().TextValue; if (sourceHash != destTempHash) { destStream.Close(); destStream = destTemp.GetContent().GetOutputStream(FileMode.Create, FileShare.Read); } else { m_Offset = destStream.Length; if (m_Offset > 0) { srcStream = new PartialStream(srcStream, m_Offset); } } } m_Progress.RaiseValueChanged(0, m_Offset); ProcessTaskStateRequest(); m_Pump = new StreamPump(srcStream, destStream, true, false, m_ServiceType.BufferSize); m_Pump.TaskStateChanged += new TaskEventHandler(Pump_TaskStateChanged); SetTransferState(TransferState.Transferring); ProcessTaskStateRequest(); m_Pump.Run(); if (m_Pump.TaskState == TaskState.Stopped) { throw new StopRequestedException(); } SetTransferState(TransferState.Copying); ProcessTaskStateRequest(); } finally { if (srcStream != null) { Routines.IgnoreExceptions(delegate { srcStream.Close(); }); } if (destStream != null) { Routines.IgnoreExceptions(delegate { destStream.Close(); }); } } break; } SetTransferState(TransferState.Tidying); destTemp.MoveTo(dest, true); /// /// Aquire an UpdateContext for the attributes /// so that all updates to the attributes are /// commited in a single operation /// using (dest.Attributes.AquireUpdateContext()) { foreach (string s in this.m_ServiceType.AttributesToTransfer) { dest.Attributes[s] = m_Source.Attributes[s]; } } dest.RenameTo(m_Destination.Address.Name, true); SetTransferState(TransferState.Finished); } finally { if (m_TransferState != TransferState.Stopped) { SetTransferState(TransferState.Finished); } } }