예제 #1
0
        /// <summary>
        ///    Copies one file in one or more chunks, if need be.
        ///    Currently a chunk can be up to 4MB in size.
        /// </summary>
        /// <remarks>
        ///    Before the file is copied, a check is performed if sending the file
        ///    is necessary. If the file already exists on the target system (and the content
        ///    is identical), then nothing more is done.
        /// </remarks>
        /// <param name="sourceFilePath"></param>
        /// <param name="destinationFilePath"></param>
        /// <param name="expectedFileSize"></param>
        private void CopyFileChunked(string sourceFilePath, string destinationFilePath, long expectedFileSize, bool forceCopy)
        {
            var thisHash = HashCodeCalculator.MD5(sourceFilePath);

            if (!forceCopy && Exists(destinationFilePath, expectedFileSize, thisHash))
            {
                Log.InfoFormat("Skipping copy of '{0}' to '{1}' because the target file is already present", sourceFilePath,
                               destinationFilePath);
                return;
            }

            Log.InfoFormat("Copying '{0}' to '{1}'...", sourceFilePath, destinationFilePath);

            using (var sourceStream = File.OpenRead(sourceFilePath))
            {
                var fileSize = sourceStream.Length;
                var tasks    = new TaskList(maxPending: MaxParallelCopyTasks);
                tasks.Add(_files.OpenFileAsync(destinationFilePath, fileSize));

                var buffer = new byte[FilePacketBufferSize];

                while (true)
                {
                    var position  = sourceStream.Position;
                    var bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
                    if (bytesRead <= 0)
                    {
                        break;
                    }

                    tasks.Add(WriteAsync(bytesRead, position, buffer, destinationFilePath));
                }

                tasks.Add(_files.CloseFileAsync(destinationFilePath));

                tasks.WaitAll();
                var clientHash = _files.CalculateMD5(destinationFilePath);
                if (!HashCodeCalculator.AreEqual(thisHash, clientHash))
                {
                    throw new
                          NotImplementedException($"There has been an error while copying '{sourceFilePath}' to '{destinationFilePath}', the resulting hashes should be identical, but are not!");
                }
            }
        }
예제 #2
0
        public bool Exists(string filePath, long expectedFileSize, byte[] expectedHash)
        {
            filePath = NormalizeAndEvaluate(filePath);

            var info = _filesystem.GetFileInfo(filePath);

            if (!info.Exists)
            {
                Log.DebugFormat("The file '{0}' does not exist", filePath);
                return(false);
            }

            if (info.Length != expectedFileSize)
            {
                Log.DebugFormat("The file '{0}' exists, but has a different '{1}' filesize than the expected '{2}'",
                                filePath, info.Length, expectedFileSize);
                return(false);
            }

            var hash = HashCodeCalculator.MD5(filePath);

            if (!HashCodeCalculator.AreEqual(hash, expectedHash))
            {
                Log.DebugFormat(
                    "The file '{0}' exists, has the expected size '{1}', but it's hash '{2}' differs from the expected one '{3}'",
                    filePath,
                    info.Length,
                    HashCodeCalculator.ToString(hash),
                    HashCodeCalculator.ToString(expectedHash));
                return(false);
            }

            Log.DebugFormat(
                "The file '{0}' exists, has the expected size '{1}' and hash '{2}'",
                filePath,
                info.Length,
                HashCodeCalculator.ToString(hash));
            return(true);
        }