From 18e65fd4c3d2df99294804fca9bfc8986e52b13d Mon Sep 17 00:00:00 2001 From: "kenneth.skovhede@gmail.com" Date: Tue, 7 Oct 2008 23:02:55 +0000 Subject: [PATCH] Fixed the header value for delta files so they are compatible with RDiff. Fixed a bug where the delta file would be wrong in special cases. Added an optimization so SharpRSync now produces smaller delta files than librsync for some cases (and the same size for all others). Added comments to identify optimizations. git-svn-id: https://duplicati.googlecode.com/svn/trunk@49 59da171f-624f-0410-aa54-27559c288bec --- Duplicati/CommandLine/UnitTest.cs | 2 +- Duplicati/Main/Interface.cs | 1 + Duplicati/Main/RSyncDir.cs | 17 ++++++++++++++--- Duplicati/SharpRSync/DeltaFile.cs | 22 ++++++++++++++++++++++ Duplicati/SharpRSync/RDiffBinary.cs | 2 +- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Duplicati/CommandLine/UnitTest.cs b/Duplicati/CommandLine/UnitTest.cs index e7b969dab..a86f1d573 100644 --- a/Duplicati/CommandLine/UnitTest.cs +++ b/Duplicati/CommandLine/UnitTest.cs @@ -125,7 +125,7 @@ namespace Duplicati.CommandLine string relpath = s.Substring(f1.Length); string target = System.IO.Path.Combine(f2, relpath); if (!files2.Contains(target)) - Console.WriteLine("Missing folder: " + relpath); + Console.WriteLine("Missing file: " + relpath); else { files2.Remove(target); diff --git a/Duplicati/Main/Interface.cs b/Duplicati/Main/Interface.cs index 9c91840fd..02db28600 100644 --- a/Duplicati/Main/Interface.cs +++ b/Duplicati/Main/Interface.cs @@ -85,6 +85,7 @@ namespace Duplicati.Main long totalmax = options.ContainsKey("totalsize") ? Core.Sizeparser.ParseSize(options["totalsize"], "mb") : long.MaxValue; totalmax = Math.Max(volumesize, totalmax); + //TODO: Just pass the dir list to the zip, don't stress the disk using (new Logging.Timer("Creating folders for signature file")) dir.CreateFolders(); diff --git a/Duplicati/Main/RSyncDir.cs b/Duplicati/Main/RSyncDir.cs index ee70236ec..c3a647e54 100644 --- a/Duplicati/Main/RSyncDir.cs +++ b/Duplicati/Main/RSyncDir.cs @@ -174,6 +174,7 @@ namespace Duplicati.Main.RSync string s = m_unproccesed[next]; m_unproccesed.RemoveAt(next); + //TODO: Add the delta to zip, don't use temp file if (ProccessDiff(s)) totalSize = AddFileToCompression(s, c); @@ -456,9 +457,19 @@ namespace Duplicati.Main.RSync //string source = System.IO.Path.Combine(sourcefolder, relpath) string tempfile = System.IO.Path.GetTempFileName(); - SharpRSync.Interface.PatchFile(target, s, tempfile); - System.IO.File.Delete(target); - System.IO.File.Move(tempfile, target); + try + { + SharpRSync.Interface.PatchFile(target, s, tempfile); + System.IO.File.Delete(target); + System.IO.File.Move(tempfile, target); + } + catch (Exception ex) + { + Logging.Log.WriteMessage("Failed to restore file " + relpath, Duplicati.Logging.LogMessageType.Error, ex); + System.IO.File.Delete(target); + System.IO.File.Delete(tempfile); + } + } } diff --git a/Duplicati/SharpRSync/DeltaFile.cs b/Duplicati/SharpRSync/DeltaFile.cs index 91e83c668..c708938e8 100644 --- a/Duplicati/SharpRSync/DeltaFile.cs +++ b/Duplicati/SharpRSync/DeltaFile.cs @@ -147,6 +147,7 @@ namespace Duplicati.SharpRSync long unmatched = 0; long matched = 0; long matched_offset = 0; + long next_match_key = 0; do { @@ -168,6 +169,17 @@ namespace Duplicati.SharpRSync tmp = md4buffer; } + //If there are two identical blocks, we try the next first as that produces the smallest delta file + //NOTE: RDiff does not seem to have this optimization + if (matched > 0 && strong[0].Key != next_match_key) + foreach (KeyValuePair k in strong) + if (k.Key == next_match_key) + { + strong.Remove(k); + strong.Insert(0, k); + break; + } + foreach (KeyValuePair k in strong) { if (!md4.CanReuseTransform) @@ -192,8 +204,18 @@ namespace Duplicati.SharpRSync buffer.DropTail(unmatched); unmatched = 0; } + if (matched == 0) matched_offset = k.Key * m_checksum.BlockLength; + else if (k.Key != next_match_key) + { + WriteCopy(matched_offset, matched, output); + matched = 0; + matched_offset = k.Key * m_checksum.BlockLength; + } + + next_match_key = k.Key + 1; + matched += buffer.Count; foundMatch = true; diff --git a/Duplicati/SharpRSync/RDiffBinary.cs b/Duplicati/SharpRSync/RDiffBinary.cs index 86645254c..04061672a 100644 --- a/Duplicati/SharpRSync/RDiffBinary.cs +++ b/Duplicati/SharpRSync/RDiffBinary.cs @@ -40,7 +40,7 @@ namespace Duplicati.SharpRSync /// /// The magic header value in an RDiff delta file /// - public static readonly byte[] DELTA_MAGIC = { (byte)'r', (byte)'s', 0x1, (byte)'6' }; + public static readonly byte[] DELTA_MAGIC = { (byte)'r', (byte)'s', 0x2, (byte)'6' }; /// /// Denotes the end of a delta stream.