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);
				}
			}
		}