示例#1
0
 public FileCopyReport(ReportType reportType, FileCopyOperation operation, int streamIndex, long chunkOffset, long chunkSize)
 {
     this._reportType      = reportType;
     this._operation       = operation;
     this._streamIndex     = streamIndex;
     this._chunkOffset     = chunkOffset;
     this._chunkSize       = chunkSize;
     this._source          = operation.Source;
     this._target          = operation.Target;
     this._streamOffset    = 0;
     this._streamSize      = operation.BytesToTransfer;
     this.ContinuationType = reportType == ReportType.AbortedOperation ? ContinuationType.AbortOperation : ContinuationType.Proceed;
 }
        private FileOperation NewFileCopyOperation()
        {
            var fileCopy = new FileCopyOperation(
                new DirectoryInfo(Source),
                new DirectoryInfo(Destination),
                GetFileFilters(),
                GetDirectoryFilters(),
                GetOptions())
            {
                BufferSize = BufferSize, Credentials = GetCredentials(), WhatToCopy = GetWhatToCopy(),
                RetryCount = RetryCount, RetryInterval = TimeSpan.FromSeconds(RetryIntervalSeconds)
            };

            return(ThreadCount.HasValue ? (FileOperation)fileCopy.MakeMultiThreaded(ThreadCount.Value ?? 8) : fileCopy);
        }
示例#3
0
        /// <summary>
        /// Copies a symbolic link if needed.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="target">The target.</param>
        /// <param name="callback">The callback.</param>
        /// <returns>The last report or <c>null</c>.</returns>
        private static IFileReport _CopySymbolicLinkIfNeeded(FileInfo source, FileInfo target, Action <IFileSystemReport> callback)
        {
            if (!source.IsSymbolicLink())
            {
                return(null);
            }

            var operation = new FileCopyOperation(source, target, callback, false);

            operation.OperationStarted();
            try {
                var targets = source.GetSymbolicLinkTarget();
                target.CreateSymbolicLinkAt(targets);
                operation.CreatedLink();
                return(operation.OperationFinished());
            } catch (Exception e) {
                return(operation.OperationAborted(e));
            }
        }
示例#4
0
        /// <summary>
        /// Copies the file asynchronous.
        /// This reads one chunk at a time and when the OS signals that a read is done, it starts writing that chunk while, possibly at the same time, reading the next.
        /// </summary>
        /// <param name="This">This source file.</param>
        /// <param name="target">The target file.</param>
        /// <param name="overwrite">if set to <c>true</c> overwrites existing; otherwise throws IOException.</param>
        /// <param name="allowHardLinks">if set to <c>true</c> allows creation of hard links.</param>
        /// <param name="dontResolveSymbolicLinks">if set to <c>true</c> [dont resolve symbolic links].</param>
        /// <param name="callback">The callback, if any.</param>
        /// <param name="allowedStreams">The allowed number of streams.</param>
        /// <param name="bufferSize">Size of the buffer.</param>
        /// <returns></returns>
        /// <exception cref="System.IO.FileNotFoundException">When source file does not exist</exception>
        /// <exception cref="System.IO.IOException">When target file exists and should not overwrite</exception>
        public static IFileReport CopyToAsync(this FileInfo This, FileInfo target, bool overwrite = false, bool allowHardLinks = false, bool dontResolveSymbolicLinks = false, Action <IFileSystemReport> callback = null, int allowedStreams = 1, int bufferSize = -1)
        {
            Contract.Requires(This != null);
            Contract.Requires(target != null);

            if (!File.Exists(This.FullName))
            {
                throw new FileNotFoundException(string.Format(_EX_SOURCE_FILE_DOES_NOT_EXIST, This.FullName));
            }

            // special hard link handling
            var sourceIsHardLink = This.IsHardLink();

            if (sourceIsHardLink)
            {
                var targets = This.GetHardLinkTargets();

                // if target file is already a hard link of the source, don't copy
                if (targets.Any(t => t.FullName == target.FullName))
                {
                    var operation = new FileCopyOperation(This, target, callback, false);
                    operation.OperationStarted();
                    return(operation.OperationFinished());
                }
            }

            if (File.Exists(target.FullName))
            {
                if (!overwrite)
                {
                    throw new IOException(string.Format(_EX_TARGET_FILE_ALREADY_EXISTS, target.FullName));
                }

                File.Delete(target.FullName);
            }

            // create symlink at target with the same source
            if (dontResolveSymbolicLinks)
            {
                var copySymlink = _CopySymbolicLinkIfNeeded(This, target, callback);
                if (copySymlink != null)
                {
                    return(copySymlink);
                }
            }

            var mainToken = new FileCopyOperation(This, target, callback, !This.IsOnSamePhysicalDrive(target), bufferSize);

            // create link if possible and allowed
            if (allowHardLinks && This.TryCreateHardLinkAt(target))
            {
                // link creation successful
                mainToken.OperationStarted();
                mainToken.CreatedLink();
                return(mainToken.OperationFinished());
            }

            // do copy
            var result = mainToken.OperationStarted();

            // open streams
            try {
                mainToken.SourceStream = new FileStream(This.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, mainToken.ChunkSize, FileOptions.Asynchronous | FileOptions.SequentialScan);

                // set target size first to avoid fragmentation
                _SetFileSize(target, Math.Min(mainToken.TotalSize, _MAX_PREALLOCATION_SIZE));

                mainToken.TargetStream = new FileStream(target.FullName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, mainToken.ChunkSize, FileOptions.Asynchronous | (mainToken.TotalSize < _MAX_CACHED_SIZE ? FileOptions.None : FileOptions.WriteThrough));
            } catch (Exception e) {
                return(mainToken.OperationAborted(e));
            }

            // trigger start reading
            if (mainToken.BytesToTransfer > 0)
            {
                mainToken.StartReading();
            }
            else
            {
                result = mainToken.OperationFinished();
            }
            return(result);
        }