Incremental Diffs?

Dave Dykstra dwd at bell-labs.com
Wed Mar 20 07:21:31 EST 2002


On Mon, Mar 18, 2002 at 11:22:40AM -0600, Kim Scarborough wrote:
> > it looks like you're correct in your assesment of the problem
> > (i.e. the whole file is copied).  You don't say what version of rsync
> > you're running, but there may be a bug in the current version introduced
> > recently with the addition of the --no-whole-file option.
> > See the following message for a description of the problem and a patch:
> >
> >    http://lists.samba.org/pipermail/rsync/2002-March/006526.html
> 
> Ah, glad I'm not crazy.
> 
> I was running 2.5.2 client-side and 2.5.3pre1 server-side. I upgraded both
> to 2.5.4, but the behavior persists. I tried it both with and without that
> patch.
> 
> Is there anything else I can try?


The whole-file bug was introduced just after 2.5.2 (by me, I'm sorry!) and
Only the server side version matters and I'm pretty sure it's only when
sending files to the server as opposed to receiving files from it.  The
patch in the above message should workaround the problem if you've got the
same version on both sides; are you absolutely sure that you were running
the patch against 2.5.4 on both sides?

Below is a patch against 2.5.4 more like what's been put into CVS.  This
should only require the server side to be patched.

- Dave Dykstra


--- options.c.O	Tue Mar 19 13:37:18 2002
+++ options.c	Tue Mar 19 14:05:50 2002
@@ -22,7 +22,20 @@
 #include "popt.h"
 
 int make_backups = 0;
-int whole_file = -1;
+
+/**
+ * Should we send the whole file as literal data rather than trying to
+ * create an incremental diff?  This is on by default when both source
+ * and destination are local and we're not doing a batch delta,
+ * because there it's no cheaper to read the whole basis file than to
+ * just rewrite it.
+ *
+ * If both are 0, then look at whether we're local or remote and go by
+ * that.
+ **/
+int whole_file = 0;
+int no_whole_file = 0;
+
 int copy_links = 0;
 int preserve_links = 0;
 int preserve_hard_links = 0;
@@ -265,7 +278,7 @@
       OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
       OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, 
       OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
-      OPT_NO_BLOCKING_IO, OPT_NO_WHOLE_FILE,
+      OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE,
       OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING};
 
 static struct poptOption long_options[] = {
@@ -298,7 +311,7 @@
   {"update",          'u', POPT_ARG_NONE,   &update_only},
   {"links",           'l', POPT_ARG_NONE,   &preserve_links},
   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links},
-  {"whole-file",      'W', POPT_ARG_NONE,   &whole_file},
+  {"whole-file",      'W', POPT_ARG_NONE,   0,               OPT_WHOLE_FILE},
   {"no-whole-file",    0,  POPT_ARG_NONE,   0, 		     OPT_NO_WHOLE_FILE},
   {"copy-unsafe-links", 0, POPT_ARG_NONE,   &copy_unsafe_links},
   {"perms",           'p', POPT_ARG_NONE,   &preserve_perms},
@@ -463,7 +476,13 @@
 			add_exclude_file(poptGetOptArg(pc), 1, 1);
 			break;
 
+		case OPT_WHOLE_FILE:
+			whole_file = 1;
+			no_whole_file = 0;
+			break;
+
 		case OPT_NO_WHOLE_FILE:
+			no_whole_file = 1;
 			whole_file = 0;
 			break;
 
@@ -590,8 +609,6 @@
 
 	int i, x;
 
-	if (whole_file == -1)
-		whole_file = 0;
 	if (blocking_io == -1)
 		blocking_io = 0;
 
--- generator.c.O	Tue Mar 19 13:43:23 2002
+++ generator.c	Tue Mar 19 14:02:27 2002
@@ -32,7 +32,6 @@
 extern int preserve_hard_links;
 extern int update_only;
 extern int opt_ignore_existing;
-extern int whole_file;
 extern int block_size;
 extern int csum_length;
 extern int ignore_times;
@@ -127,6 +126,35 @@
 	}
 }
 
+
+/**
+ * Perhaps we want to just send an empty checksum set for this file,
+ * which will force the whole thing to be literally transferred.
+ *
+ * When do we do this?  If the user's explicitly said they
+ * want the whole thing, or if { they haven't explicitly
+ * requested a delta, and it's local but not batch mode.}
+ *
+ * Whew. */
+static BOOL disable_deltas_p(void)
+{
+	extern int whole_file, no_whole_file;
+	extern int local_server;
+	extern int write_batch;
+
+	/* whole_file and no_whole_file are never both on at the same time */
+
+	if (whole_file)
+		return True;
+	else if (no_whole_file)
+		return False;
+	else if (write_batch)
+		return False;
+	else
+		return local_server;
+}
+
+
 /*
   generate a stream of signatures/checksums that describe a buffer
 
@@ -403,7 +431,7 @@
 		return;
 	}
 
-	if (whole_file) {
+	if (disable_deltas_p()) {
 		write_int(f_out,i);
 		send_sums(NULL,f_out);    
 		return;




More information about the rsync mailing list