Пример #1
0
        /// <summary>
        /// Adds the Object to Disk and Database
        /// </summary>
        /// <param name='localFile'>
        /// Local file.
        /// </param>
        /// <param name='remoteId'>
        /// Remote Object (already fetched).
        /// </param>
        /// <param name="localContent">Hint if the local content has been changed.</param>
        /// <param name="remoteContent">Information if the remote content has been changed.</param>
        /// <exception cref='ArgumentException'>
        /// Is thrown when remoteId is not prefetched.
        /// </exception>
        public override void Solve(
            IFileSystemInfo localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFile is IDirectoryInfo)
            {
                if (!(remoteId is IFolder))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Folder");
                }

                var            remoteFolder = remoteId as IFolder;
                IDirectoryInfo localFolder  = localFile as IDirectoryInfo;
                localFolder.Create();

                Guid uuid = Guid.Empty;
                if (localFolder.IsExtendedAttributeAvailable())
                {
                    uuid = Guid.NewGuid();
                    try {
                        localFolder.Uuid = uuid;
                    } catch (RestoreModificationDateException) {
                    }
                }

                if (remoteFolder.LastModificationDate != null)
                {
                    try {
                        localFolder.LastWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
                    } catch (IOException e) {
                        Logger.Info("Directory modification date could not be synced", e);
                    }
                }

                var mappedObject = new MappedObject(remoteFolder);
                mappedObject.Guid = uuid;
                mappedObject.LastRemoteWriteTimeUtc = remoteFolder.LastModificationDate;
                mappedObject.LastLocalWriteTimeUtc  = localFolder.LastWriteTimeUtc;
                mappedObject.Ignored = remoteFolder.AreAllChildrenIgnored();
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local folder {0} created and mapped to remote folder {1}", localFolder.FullName, remoteId.Id));
            }
            else if (localFile is IFileInfo)
            {
                if (!(remoteId is IDocument))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Document");
                }

                Guid     guid          = Guid.NewGuid();
                byte[]   localFileHash = null;
                DateTime?lastLocalFileModificationDate = null;
                var      file = localFile as IFileInfo;
                if (file.Exists)
                {
                    Guid?uuid = file.Uuid;
                    if (uuid != null)
                    {
                        if (this.Storage.GetObjectByGuid((Guid)uuid) != null)
                        {
                            throw new ArgumentException("This file has already been synced => force crawl sync");
                        }
                    }

                    lastLocalFileModificationDate = file.LastWriteTimeUtc;
                    if (this.MergeExistingFileWithRemoteFile(file, remoteId as IDocument, guid, out localFileHash))
                    {
                        return;
                    }

                    Logger.Debug(string.Format("This file {0} conflicts with remote file => conflict file will could be produced after download", file.FullName));
                }

                var cacheFile = this.fsFactory.CreateDownloadCacheFileInfo(guid);

                IDocument remoteDoc    = remoteId as IDocument;
                var       transmission = this.manager.CreateTransmission(TransmissionType.DOWNLOAD_NEW_FILE, localFile.FullName, cacheFile.FullName);
                byte[]    hash         = DownloadCacheFile(cacheFile, remoteDoc, transmission, this.fsFactory);

                try {
                    cacheFile.Uuid = guid;
                } catch (RestoreModificationDateException e) {
                    Logger.Debug("Could not retore the last modification date of " + cacheFile.FullName, e);
                }

                try {
                    cacheFile.MoveTo(file.FullName);
                } catch (IOException e) {
                    file.Refresh();
                    if (file.Exists)
                    {
                        if (localFileHash == null ||
                            lastLocalFileModificationDate == null ||
                            !lastLocalFileModificationDate.Equals(file.LastWriteTimeUtc))
                        {
                            lastLocalFileModificationDate = file.LastWriteTimeUtc;
                            using (var f = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                                localFileHash = SHA1Managed.Create().ComputeHash(f);
                            }
                        }

                        if (localFileHash.SequenceEqual(hash))
                        {
                            file.Uuid = guid;
                            try {
                                cacheFile.Delete();
                            } catch (IOException) {
                            }
                        }
                        else
                        {
                            IFileInfo conflictFile = this.fsFactory.CreateConflictFileInfo(file);
                            try {
                                IFileInfo targetFile = cacheFile.Replace(file, conflictFile, true);
                                try {
                                    targetFile.Uuid = guid;
                                } catch (RestoreModificationDateException restoreException) {
                                    Logger.Debug("Could not retore the last modification date of " + targetFile.FullName, restoreException);
                                }
                            } catch (Exception ex) {
                                transmission.FailedException = ex;
                                throw;
                            }

                            try {
                                conflictFile.Uuid = null;
                            } catch (RestoreModificationDateException restoreException) {
                                Logger.Debug("Could not retore the last modification date of " + conflictFile.FullName, restoreException);
                            }
                        }
                    }
                    else
                    {
                        transmission.FailedException = e;
                        throw;
                    }
                }

                file.Refresh();
                if (remoteDoc.LastModificationDate != null)
                {
                    try {
                        file.LastWriteTimeUtc = (DateTime)remoteDoc.LastModificationDate;
                    } catch (IOException e) {
                        Logger.Debug("Cannot set last modification date", e);
                    }
                }

                MappedObject mappedObject = new MappedObject(
                    file.Name,
                    remoteDoc.Id,
                    MappedObjectType.File,
                    remoteDoc.Parents[0].Id,
                    remoteDoc.ChangeToken,
                    remoteDoc.ContentStreamLength ?? 0)
                {
                    Guid = guid,
                    LastLocalWriteTimeUtc  = file.LastWriteTimeUtc,
                    LastRemoteWriteTimeUtc = remoteDoc.LastModificationDate,
                    LastChecksum           = hash,
                    ChecksumAlgorithmName  = "SHA-1"
                };
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local file {0} created and mapped to remote file {1}", file.FullName, remoteId.Id));
                transmission.Status = TransmissionStatus.FINISHED;
            }
        }
Пример #2
0
        /// <summary>
        /// Adds the Object to Disk and Database
        /// </summary>
        /// <param name='localFile'>
        /// Local file.
        /// </param>
        /// <param name='remoteId'>
        /// Remote Object (already fetched).
        /// </param>
        /// <param name="localContent">Hint if the local content has been changed.</param>
        /// <param name="remoteContent">Information if the remote content has been changed.</param>
        /// <exception cref='ArgumentException'>
        /// Is thrown when remoteId is not prefetched.
        /// </exception>
        public override void Solve(
            IFileSystemInfo localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFile is IDirectoryInfo)
            {
                if (!(remoteId is IFolder))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Folder");
                }

                var            remoteFolder = remoteId as IFolder;
                IDirectoryInfo localFolder  = localFile as IDirectoryInfo;
                localFolder.Create();

                Guid uuid = Guid.Empty;
                if (localFolder.IsExtendedAttributeAvailable())
                {
                    uuid = Guid.NewGuid();
                    try {
                        localFolder.Uuid = uuid;
                    } catch (RestoreModificationDateException) {
                    }
                }

                if (remoteFolder.LastModificationDate != null)
                {
                    localFolder.LastWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
                }

                var mappedObject = new MappedObject(remoteFolder);
                mappedObject.Guid = uuid;
                mappedObject.LastRemoteWriteTimeUtc = remoteFolder.LastModificationDate;
                mappedObject.LastLocalWriteTimeUtc  = localFolder.LastWriteTimeUtc;
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local folder {0} created and mapped to remote folder {1}", localFolder.FullName, remoteId.Id));
            }
            else if (localFile is IFileInfo)
            {
                Guid guid = Guid.NewGuid();
                var  file = localFile as IFileInfo;
                if (!(remoteId is IDocument))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Document");
                }

                if (file.Exists)
                {
                    Guid?uuid = file.Uuid;
                    if (uuid != null)
                    {
                        if (this.Storage.GetObjectByGuid((Guid)uuid) != null)
                        {
                            throw new ArgumentException("This file has already been synced => force crawl sync");
                        }
                    }

                    Logger.Debug(string.Format("This file {0} conflicts with remote file => conflict file will be produced after download", file.FullName));
                }

                var cacheFile = this.fsFactory.CreateDownloadCacheFileInfo(guid);

                IDocument remoteDoc         = remoteId as IDocument;
                var       transmissionEvent = new FileTransmissionEvent(FileTransmissionType.DOWNLOAD_NEW_FILE, localFile.FullName, cacheFile.FullName);
                this.manager.AddTransmission(transmissionEvent);
                byte[] hash = null;
                using (var hashAlg = new SHA1Managed())
                    using (var fileStream = cacheFile.Open(FileMode.Create, FileAccess.Write, FileShare.Read))
                        using (var downloader = FileTransmission.ContentTaskUtils.CreateDownloader())
                        {
                            try {
                                downloader.DownloadFile(remoteDoc, fileStream, transmissionEvent, hashAlg);
                            } catch (Exception ex) {
                                transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                                    FailedException = ex
                                });
                                throw;
                            }

                            hash = hashAlg.Hash;
                        }

                cacheFile.Uuid = guid;
                try {
                    cacheFile.MoveTo(file.FullName);
                } catch (IOException e) {
                    file.Refresh();
                    if (file.Exists)
                    {
                        IFileInfo conflictFile = this.fsFactory.CreateConflictFileInfo(file);
                        IFileInfo targetFile   = cacheFile.Replace(file, conflictFile, true);
                        targetFile.SetExtendedAttribute(MappedObject.ExtendedAttributeKey, guid.ToString(), true);
                        conflictFile.SetExtendedAttribute(MappedObject.ExtendedAttributeKey, null, true);
                    }
                    else
                    {
                        transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                            FailedException = e
                        });
                        throw;
                    }
                }

                file.Refresh();
                if (remoteDoc.LastModificationDate != null)
                {
                    try {
                        file.LastWriteTimeUtc = (DateTime)remoteDoc.LastModificationDate;
                    } catch (IOException e) {
                        Logger.Debug("Cannot set last modification date", e);
                    }
                }

                MappedObject mappedObject = new MappedObject(
                    file.Name,
                    remoteDoc.Id,
                    MappedObjectType.File,
                    remoteDoc.Parents[0].Id,
                    remoteDoc.ChangeToken,
                    remoteDoc.ContentStreamLength ?? 0)
                {
                    Guid = guid,
                    LastLocalWriteTimeUtc  = file.LastWriteTimeUtc,
                    LastRemoteWriteTimeUtc = remoteDoc.LastModificationDate,
                    LastChecksum           = hash,
                    ChecksumAlgorithmName  = "SHA-1"
                };
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local file {0} created and mapped to remote file {1}", file.FullName, remoteId.Id));
                transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                    Completed = true
                });
            }
        }