Fixed a failing hunk.
[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
9c85142a 19@@ -33,6 +33,7 @@ extern int am_generator;
dd0d95fa 20 extern int inc_recurse;
2d2150f6
WD
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;
9c85142a 27@@ -955,6 +956,15 @@ static struct file_struct *recv_file_ent
7c15d5aa
WD
28 memcpy(bp, F_SUM(first), checksum_len);
29 } else
30 read_buf(f, bp, checksum_len);
ffc18846 31+ if (pre_checksum && bp != tmp_sum) {
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
ffc18846 42 #ifdef SUPPORT_ACLS
9a7eef96
WD
43--- old/generator.c
44+++ new/generator.c
9c85142a 45@@ -73,6 +73,7 @@ extern int protocol_version;
fc068916 46 extern int file_total;
2d2150f6
WD
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[];
8f0fca7a 53@@ -618,7 +619,8 @@ void itemize(const char *fnamecmp, struc
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;
8f0fca7a 63@@ -627,6 +629,8 @@ int unchanged_file(char *fn, struct file
2d2150f6 64 of the file time to determine whether to sync */
fc068916 65 if (always_checksum > 0 && S_ISREG(st->st_mode)) {
87a38eea 66 char sum[MAX_DIGEST_LEN];
2d2150f6
WD
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 }
8f0fca7a 72@@ -847,7 +851,7 @@ static int try_dests_reg(struct file_str
f20eb450
WD
73 match_level = 1;
74 /* FALL THROUGH */
75 case 1:
ffc18846
WD
76- if (!unchanged_file(cmpbuf, file, &sxp->st))
77+ if (!unchanged_file(cmpbuf, 0, file, &sxp->st))
f20eb450
WD
78 continue;
79 best_match = j;
80 match_level = 2;
9c85142a 81@@ -1575,7 +1579,7 @@ static void recv_generator(char *fname,
2d2150f6
WD
82 ;
83 else if (fnamecmp_type == FNAMECMP_FUZZY)
84 ;
ffc18846
WD
85- else if (unchanged_file(fnamecmp, file, &sx.st)) {
86+ else if (unchanged_file(fnamecmp, fnamecmp_type, file, &sx.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
9c85142a 92@@ -392,7 +392,7 @@ int hard_link_check(struct file_struct *
7b80cd0e
WD
93 }
94 break;
95 }
ffc18846
WD
96- if (!unchanged_file(cmpbuf, file, &alt_sx.st))
97+ if (!unchanged_file(cmpbuf, 0, file, &alt_sx.st))
7b80cd0e
WD
98 continue;
99 statret = 1;
ffc18846 100 if (unchanged_attrs(cmpbuf, file, &alt_sx))
9a7eef96
WD
101--- old/main.c
102+++ new/main.c
9c85142a 103@@ -45,6 +45,7 @@ extern int module_id;
fc068916
WD
104 extern int copy_links;
105 extern int copy_dirlinks;
2d2150f6 106 extern int keep_dirlinks;
fc068916 107+extern int always_checksum;
2d2150f6
WD
108 extern int preserve_hard_links;
109 extern int protocol_version;
fc068916 110 extern int file_total;
9c85142a 111@@ -72,6 +73,9 @@ extern char *password_file;
60a8bf36 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;
9c85142a 121@@ -792,6 +796,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) {
9c85142a 129@@ -838,6 +843,10 @@ static void do_server_recv(int f_in, int
7c15d5aa
WD
130 filesfrom_fd = -1;
131 }
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);
2d2150f6 138 if (!flist) {
fc068916 139 rprintf(FERROR,"server_recv: recv_file_list error\n");
9c85142a 140@@ -847,6 +856,9 @@ static void do_server_recv(int f_in, int
fc068916
WD
141 recv_additional_file_list(f_in);
142 verbose = save_verbose;
2d2150f6
WD
143
144+ if (pre_checksum)
145+ pop_dir(olddir);
146+
147 if (argc > 0)
148 local_name = get_local_name(flist,argv[0]);
149
9c85142a 150@@ -926,6 +938,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;
9c85142a 158@@ -1006,12 +1019,19 @@ int client_run(int f_in, int f_out, pid_
7c15d5aa
WD
159 filesfrom_fd = -1;
160 }
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);
dd0d95fa 169 if (inc_recurse && file_total == 1)
fc068916 170 recv_additional_file_list(f_in);
2d2150f6
WD
171
172+ if (pre_checksum)
173+ pop_dir(olddir);
174+
9c85142a 175 if (flist && flist->used > 0) {
2d2150f6
WD
176 local_name = get_local_name(flist, argv[0]);
177
9a7eef96
WD
178--- old/rsync.h
179+++ new/rsync.h
9c85142a 180@@ -71,6 +71,7 @@
7b80cd0e
WD
181 #define FLAG_HLINK_DONE (1<<8) /* receiver/generator */
182 #define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
8f0fca7a
WD
183 #define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
184+#define FLAG_SUM_DIFFERS (1<<11)/* receiver/generator */
1aa236e1 185
fc068916
WD
186 /* These flags are passed to functions but not stored. */
187