예제 #1
0
        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);
                }
            }
        }