Fixed failing hunks.
[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
03019e41
WD
11To use this patch, run these commands for a successful build:
12
13 patch -p1 <patches/early-checksum.diff
14 ./configure (optional if already run)
15 make
16
9a7eef96
WD
17--- old/flist.c
18+++ new/flist.c
b5abdf47 19@@ -31,6 +31,7 @@ extern int am_daemon;
2d2150f6
WD
20 extern int am_sender;
21 extern int do_progress;
22 extern int always_checksum;
23+extern int pre_checksum;
24 extern int module_id;
25 extern int ignore_errors;
26 extern int numeric_ids;
7b80cd0e 27@@ -734,6 +735,15 @@ static struct file_struct *recv_file_ent
70891d26 28 bp = tmp_sum;
2d2150f6 29 }
70891d26
WD
30 read_buf(f, bp, checksum_len);
31+ if (pre_checksum && sum_len) {
2d2150f6 32+ STRUCT_STAT st;
bd68c3c2 33+ char *fname = f_name(file, NULL);
2d2150f6 34+ if (stat(fname, &st) == 0 && st.st_size == file_length) {
70891d26
WD
35+ file_checksum(fname, tmp_sum, st.st_size);
36+ if (memcmp(bp, tmp_sum, checksum_len) != 0)
2d2150f6
WD
37+ file->flags |= FLAG_SUM_DIFFERS;
38+ }
39+ }
40 }
41
9a7eef96
WD
42 return file;
43--- old/generator.c
44+++ new/generator.c
1aa236e1 45@@ -70,6 +70,7 @@ extern int ignore_timeout;
2d2150f6
WD
46 extern int protocol_version;
47 extern int fuzzy_basis;
48 extern int always_checksum;
49+extern int pre_checksum;
d57e621e 50 extern int checksum_len;
2d2150f6
WD
51 extern char *partial_dir;
52 extern char *basis_dir[];
7b80cd0e 53@@ -578,7 +579,8 @@ void itemize(struct file_struct *file, i
2d2150f6
WD
54
55
56 /* Perform our quick-check heuristic for determining if a file is unchanged. */
f20eb450
WD
57-int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
58+int unchanged_file(char *fn, int fnamecmp_type, struct file_struct *file,
59+ STRUCT_STAT *st)
2d2150f6 60 {
1aa236e1 61 if (st->st_size != F_LENGTH(file))
2d2150f6 62 return 0;
7b80cd0e 63@@ -587,6 +589,8 @@ int unchanged_file(char *fn, struct file
2d2150f6
WD
64 of the file time to determine whether to sync */
65 if (always_checksum && S_ISREG(st->st_mode)) {
66 char sum[MD4_SUM_LENGTH];
67+ if (pre_checksum && fnamecmp_type == FNAMECMP_FNAME)
68+ return !(file->flags & FLAG_SUM_DIFFERS);
69 file_checksum(fn, sum, st->st_size);
70891d26 70 return memcmp(sum, F_SUM(file), checksum_len) == 0;
d57e621e 71 }
7b80cd0e 72@@ -826,7 +830,7 @@ static int try_dests_reg(struct file_str
f20eb450
WD
73 match_level = 1;
74 /* FALL THROUGH */
75 case 1:
76- if (!unchanged_file(cmpbuf, file, stp))
77+ if (!unchanged_file(cmpbuf, 0, file, stp))
78 continue;
79 best_match = j;
80 match_level = 2;
7b80cd0e 81@@ -1512,7 +1516,7 @@ static void recv_generator(char *fname,
2d2150f6
WD
82 ;
83 else if (fnamecmp_type == FNAMECMP_FUZZY)
84 ;
85- else if (unchanged_file(fnamecmp, file, &st)) {
86+ else if (unchanged_file(fnamecmp, fnamecmp_type, file, &st)) {
d57e621e
WD
87 if (partialptr) {
88 do_unlink(partialptr);
89 handle_partial_dir(partialptr, PDIR_DELETE);
9a7eef96
WD
90--- old/hlink.c
91+++ new/hlink.c
7b80cd0e
WD
92@@ -233,7 +233,7 @@ int hard_link_check(struct file_struct *
93 }
94 break;
95 }
96- if (!unchanged_file(cmpbuf, file, &alt_st))
97+ if (!unchanged_file(cmpbuf, 0, file, &alt_st))
98 continue;
99 statret = 1;
100 *stp = alt_st;
9a7eef96
WD
101--- old/main.c
102+++ new/main.c
b5abdf47 103@@ -47,6 +47,7 @@ extern int copy_dirlinks;
2d2150f6
WD
104 extern int keep_dirlinks;
105 extern int preserve_hard_links;
106 extern int protocol_version;
107+extern int always_checksum;
108 extern int recurse;
109 extern int relative_paths;
b5abdf47 110 extern int sanitize_paths;
60a8bf36
WD
111@@ -71,6 +72,9 @@ extern char *batch_name;
112 extern char curr_dir[MAXPATHLEN];
f4e59d46 113 extern struct filter_list_struct server_filter_list;
2d2150f6 114
af7eb67a
WD
115+extern char curr_dir[MAXPATHLEN];
116+
2d2150f6 117+int pre_checksum = 0;
d9a67109 118 int local_server = 0;
60a8bf36 119 int new_root_dir = 0;
d9a67109 120 mode_t orig_umask = 0;
7b80cd0e 121@@ -788,6 +792,7 @@ static void do_server_recv(int f_in, int
2d2150f6
WD
122 struct file_list *flist;
123 char *local_name = NULL;
124 char *dir = NULL;
125+ char olddir[sizeof curr_dir];
126 int save_verbose = verbose;
127
128 if (filesfrom_fd >= 0) {
7b80cd0e
WD
129@@ -836,6 +841,10 @@ static void do_server_recv(int f_in, int
130 init_hard_links();
131 #endif
2d2150f6
WD
132
133+ strlcpy(olddir, curr_dir, sizeof olddir);
d47d38c7 134+ if (always_checksum && !local_server && argc > 0)
de565f59 135+ pre_checksum = push_dir(argv[0], 0);
2d2150f6
WD
136+
137 flist = recv_file_list(f_in);
138 verbose = save_verbose;
139 if (!flist) {
7b80cd0e 140@@ -844,6 +853,9 @@ static void do_server_recv(int f_in, int
2d2150f6
WD
141 }
142 the_file_list = flist;
143
144+ if (pre_checksum)
145+ pop_dir(olddir);
146+
147 if (argc > 0)
148 local_name = get_local_name(flist,argv[0]);
149
7b80cd0e 150@@ -923,6 +935,7 @@ int client_run(int f_in, int f_out, pid_
2d2150f6
WD
151 {
152 struct file_list *flist = NULL;
153 int exit_code = 0, exit_code2 = 0;
154+ char olddir[sizeof curr_dir];
155 char *local_name = NULL;
156
157 cleanup_child_pid = pid;
7b80cd0e
WD
158@@ -1002,11 +1015,18 @@ int client_run(int f_in, int f_out, pid_
159 init_hard_links();
160 #endif
2d2150f6
WD
161
162+ strlcpy(olddir, curr_dir, sizeof olddir);
d47d38c7 163+ if (always_checksum && !local_server)
de565f59 164+ pre_checksum = push_dir(argv[0], 0);
2d2150f6
WD
165+
166 if (write_batch && !am_server)
167 start_write_batch(f_in);
168 flist = recv_file_list(f_in);
169 the_file_list = flist;
170
171+ if (pre_checksum)
172+ pop_dir(olddir);
173+
174 if (flist && flist->count > 0) {
175 local_name = get_local_name(flist, argv[0]);
176
9a7eef96
WD
177--- old/rsync.h
178+++ new/rsync.h
7b80cd0e 179@@ -67,6 +67,7 @@
1aa236e1 180 #define FLAG_HLINK_LAST (1<<7) /* receiver/generator */
7b80cd0e
WD
181 #define FLAG_HLINK_DONE (1<<8) /* receiver/generator */
182 #define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
183+#define FLAG_SUM_DIFFERS (1<<10)/* receiver/generator */
1aa236e1 184
7b80cd0e
WD
185 #define BITS_SET(val,bits) (((val) & (bits)) == (bits))
186 #define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))