Updated for rolled-back trunk.
[rsync/rsync-patches.git] / early-checksum.diff
CommitLineData
2d2150f6
WD
1This patch changes the way the --checksum option works by having the
2receiving side perform a checksum-read of every file in the file list
d47d38c7 3as the list is received (if the sizes are equal), marking non-matching
2d2150f6
WD
4items with a flag. The idea is that the checksum pass on the sender and
5the receiver can then happen in parallel instead of having the reciever
6to its checksum pass during its normal find-the-different-files pass.
7
d47d38c7
WD
8I have benchmarked this a little, and it appears to slow things down
9for a local copy, so the old algorithm is used for local copies.
2d2150f6 10
9a7eef96
WD
11--- old/flist.c
12+++ new/flist.c
b5abdf47 13@@ -31,6 +31,7 @@ extern int am_daemon;
2d2150f6
WD
14 extern int am_sender;
15 extern int do_progress;
16 extern int always_checksum;
17+extern int pre_checksum;
18 extern int module_id;
19 extern int ignore_errors;
20 extern int numeric_ids;
60a8bf36 21@@ -693,6 +694,16 @@ static struct file_struct *receive_file_
2d2150f6
WD
22 sum = empty_sum;
23 }
d57e621e 24 read_buf(f, sum, checksum_len);
2d2150f6
WD
25+ if (pre_checksum) {
26+ char sum2[MD4_SUM_LENGTH];
27+ STRUCT_STAT st;
bd68c3c2 28+ char *fname = f_name(file, NULL);
2d2150f6
WD
29+ if (stat(fname, &st) == 0 && st.st_size == file_length) {
30+ file_checksum(fname, sum2, st.st_size);
d57e621e 31+ if (memcmp(sum, sum2, checksum_len) != 0)
2d2150f6
WD
32+ file->flags |= FLAG_SUM_DIFFERS;
33+ }
34+ }
35 }
36
9a7eef96
WD
37 return file;
38--- old/generator.c
39+++ new/generator.c
74eccbb1 40@@ -70,6 +70,7 @@ extern int ignore_timeout;
2d2150f6
WD
41 extern int protocol_version;
42 extern int fuzzy_basis;
43 extern int always_checksum;
44+extern int pre_checksum;
d57e621e 45 extern int checksum_len;
2d2150f6
WD
46 extern char *partial_dir;
47 extern char *basis_dir[];
60a8bf36 48@@ -376,7 +377,8 @@ void itemize(struct file_struct *file, i
2d2150f6
WD
49
50
51 /* Perform our quick-check heuristic for determining if a file is unchanged. */
f20eb450
WD
52-int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
53+int unchanged_file(char *fn, int fnamecmp_type, struct file_struct *file,
54+ STRUCT_STAT *st)
2d2150f6
WD
55 {
56 if (st->st_size != file->length)
57 return 0;
60a8bf36 58@@ -385,6 +387,8 @@ int unchanged_file(char *fn, struct file
2d2150f6
WD
59 of the file time to determine whether to sync */
60 if (always_checksum && S_ISREG(st->st_mode)) {
61 char sum[MD4_SUM_LENGTH];
62+ if (pre_checksum && fnamecmp_type == FNAMECMP_FNAME)
63+ return !(file->flags & FLAG_SUM_DIFFERS);
64 file_checksum(fn, sum, st->st_size);
d57e621e
WD
65 return memcmp(sum, file->u.sum, checksum_len) == 0;
66 }
60a8bf36 67@@ -622,7 +626,7 @@ static int try_dests_reg(struct file_str
f20eb450
WD
68 match_level = 1;
69 /* FALL THROUGH */
70 case 1:
71- if (!unchanged_file(cmpbuf, file, stp))
72+ if (!unchanged_file(cmpbuf, 0, file, stp))
73 continue;
74 best_match = j;
75 match_level = 2;
60a8bf36 76@@ -1210,7 +1214,7 @@ static void recv_generator(char *fname,
2d2150f6
WD
77 ;
78 else if (fnamecmp_type == FNAMECMP_FUZZY)
79 ;
80- else if (unchanged_file(fnamecmp, file, &st)) {
81+ else if (unchanged_file(fnamecmp, fnamecmp_type, file, &st)) {
d57e621e
WD
82 if (partialptr) {
83 do_unlink(partialptr);
84 handle_partial_dir(partialptr, PDIR_DELETE);
9a7eef96
WD
85--- old/hlink.c
86+++ new/hlink.c
60a8bf36 87@@ -220,7 +220,7 @@ int hard_link_check(struct file_struct *
f20eb450
WD
88 itemizing = code = 0;
89 break;
90 }
91- if (!unchanged_file(cmpbuf, file, &st3))
92+ if (!unchanged_file(cmpbuf, 0, file, &st3))
93 continue;
94 statret = 1;
95 st = &st3;
9a7eef96
WD
96--- old/main.c
97+++ new/main.c
b5abdf47 98@@ -47,6 +47,7 @@ extern int copy_dirlinks;
2d2150f6
WD
99 extern int keep_dirlinks;
100 extern int preserve_hard_links;
101 extern int protocol_version;
102+extern int always_checksum;
103 extern int recurse;
104 extern int relative_paths;
b5abdf47 105 extern int sanitize_paths;
60a8bf36
WD
106@@ -71,6 +72,9 @@ extern char *batch_name;
107 extern char curr_dir[MAXPATHLEN];
f4e59d46 108 extern struct filter_list_struct server_filter_list;
2d2150f6 109
af7eb67a
WD
110+extern char curr_dir[MAXPATHLEN];
111+
2d2150f6 112+int pre_checksum = 0;
d9a67109 113 int local_server = 0;
60a8bf36 114 int new_root_dir = 0;
d9a67109 115 mode_t orig_umask = 0;
60a8bf36 116@@ -784,6 +788,7 @@ static void do_server_recv(int f_in, int
2d2150f6
WD
117 struct file_list *flist;
118 char *local_name = NULL;
119 char *dir = NULL;
120+ char olddir[sizeof curr_dir];
121 int save_verbose = verbose;
122
123 if (filesfrom_fd >= 0) {
60a8bf36 124@@ -827,6 +832,10 @@ static void do_server_recv(int f_in, int
2d2150f6
WD
125 filesfrom_fd = -1;
126 }
127
128+ strlcpy(olddir, curr_dir, sizeof olddir);
d47d38c7 129+ if (always_checksum && !local_server && argc > 0)
2d2150f6
WD
130+ pre_checksum = push_dir(argv[0]);
131+
132 flist = recv_file_list(f_in);
133 verbose = save_verbose;
134 if (!flist) {
60a8bf36 135@@ -835,6 +844,9 @@ static void do_server_recv(int f_in, int
2d2150f6
WD
136 }
137 the_file_list = flist;
138
139+ if (pre_checksum)
140+ pop_dir(olddir);
141+
142 if (argc > 0)
143 local_name = get_local_name(flist,argv[0]);
144
60a8bf36 145@@ -916,6 +928,7 @@ int client_run(int f_in, int f_out, pid_
2d2150f6
WD
146 {
147 struct file_list *flist = NULL;
148 int exit_code = 0, exit_code2 = 0;
149+ char olddir[sizeof curr_dir];
150 char *local_name = NULL;
151
152 cleanup_child_pid = pid;
60a8bf36 153@@ -990,11 +1003,18 @@ int client_run(int f_in, int f_out, pid_
2d2150f6
WD
154 filesfrom_fd = -1;
155 }
156
157+ strlcpy(olddir, curr_dir, sizeof olddir);
d47d38c7 158+ if (always_checksum && !local_server)
2d2150f6
WD
159+ pre_checksum = push_dir(argv[0]);
160+
161 if (write_batch && !am_server)
162 start_write_batch(f_in);
163 flist = recv_file_list(f_in);
164 the_file_list = flist;
165
166+ if (pre_checksum)
167+ pop_dir(olddir);
168+
169 if (flist && flist->count > 0) {
170 local_name = get_local_name(flist, argv[0]);
171
9a7eef96
WD
172--- old/rsync.h
173+++ new/rsync.h
74eccbb1 174@@ -65,6 +65,7 @@
2d2150f6 175 #define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
0ca6aebe 176 #define FLAG_NO_FUZZY (1<<5) /* generator */
74eccbb1
WD
177 #define FLAG_MISSING (1<<6) /* generator */
178+#define FLAG_SUM_DIFFERS (1<<7) /* receiver/generator */
2d2150f6
WD
179
180 /* update this if you make incompatible changes */
181 #define PROTOCOL_VERSION 29