1 Added a pipe from the generator to the receiver that communicates
2 what basis file we used to generate the file data (if it was not
3 the default name). This optimizes away the basis-file search in
4 the receiver and makes future options that do more basis-file
5 searching more efficient (such as the --fuzzy option and the
6 support for multiple --compare-dest options).
8 You must run "make proto" before compiling.
10 --- orig/generator.c 2004-09-07 21:45:30
11 +++ generator.c 2004-09-07 21:55:02
12 @@ -254,14 +254,15 @@ static void generate_and_send_sums(int f
13 * out. It might be wrong.
15 static void recv_generator(char *fname, struct file_struct *file, int i,
17 + int f_out, int f_out_name)
20 + int fd = -1, f_copy;
21 STRUCT_STAT st, partial_st;
22 struct file_struct *back_file;
23 int statret, stat_errno;
24 char *fnamecmp, *partialptr, *backupptr;
25 char fnamecmpbuf[MAXPATHLEN];
26 + uchar fnamecmp_type;
30 @@ -423,6 +424,7 @@ static void recv_generator(char *fname,
34 + fnamecmp_type = G2R_FNAME;
36 if (statret == -1 && compare_dest != NULL) {
37 /* try the file at compare_dest instead */
38 @@ -439,10 +441,14 @@ static void recv_generator(char *fname,
41 fnamecmp = fnamecmpbuf;
47 fnamecmp = fnamecmpbuf;
53 @@ -465,11 +471,9 @@ static void recv_generator(char *fname,
55 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
57 - if (stat_errno == ENOENT) {
59 - if (!dry_run && !read_batch)
60 - write_sum_head(f_out, NULL);
61 - } else if (verbose > 1) {
62 + if (stat_errno == ENOENT)
65 rsyserr(FERROR, stat_errno,
66 "recv_generator: failed to stat %s",
68 @@ -477,13 +481,13 @@ static void recv_generator(char *fname,
72 - if (opt_ignore_existing && fnamecmp == fname) {
73 + if (opt_ignore_existing && fnamecmp_type == G2R_FNAME) {
75 rprintf(FINFO, "%s exists\n", safe_fname(fname));
79 - if (update_only && fnamecmp == fname
80 + if (update_only && fnamecmp_type == G2R_FNAME
81 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
83 rprintf(FINFO, "%s is newer\n", safe_fname(fname));
84 @@ -491,26 +495,23 @@ static void recv_generator(char *fname,
87 if (skip_file(fnamecmp, file, &st)) {
88 - if (fnamecmp == fname)
89 + if (fnamecmp_type == G2R_FNAME)
90 set_perms(fname, file, &st, PERMS_REPORT);
95 - if (dry_run || read_batch) {
100 - if (whole_file > 0) {
101 - write_int(f_out,i);
102 - write_sum_head(f_out, NULL);
104 + if (dry_run || whole_file) {
106 + goto notify_others;
109 + goto notify_others;
113 fnamecmp = partialptr;
114 + fnamecmp_type = G2R_PARTIAL_DIR;
118 @@ -523,9 +524,8 @@ prepare_to_open:
119 /* pretend the file didn't exist */
120 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
122 - write_int(f_out,i);
123 - write_sum_head(f_out, NULL);
126 + goto notify_others;
129 if (inplace && make_backups) {
130 @@ -552,6 +552,7 @@ prepare_to_open:
134 + fnamecmp_type = G2R_BACKUP;
138 @@ -566,20 +567,33 @@ prepare_to_open:
140 rprintf(FINFO, "generating and sending sums for %d\n", i);
142 - write_int(f_out,i);
143 - generate_and_send_sums(fd, st.st_size, f_out, f_copy);
147 - set_perms(backupptr, back_file, NULL, 0);
150 + if (f_out_name >= 0) {
151 + write_byte(f_out_name, fnamecmp_type);
152 + io_flush(NORMAL_FLUSH); /* XXX make this more efficient! */
156 + write_int(f_out, i);
158 + if (dry_run || read_batch)
161 + if (statret == 0) {
162 + generate_and_send_sums(fd, st.st_size, f_out, f_copy);
167 + set_perms(backupptr, back_file, NULL, 0);
171 + write_sum_head(f_out, NULL);
175 -void generate_files(int f_out, struct file_list *flist, char *local_name)
176 +void generate_files(int f_out, struct file_list *flist, char *local_name,
181 @@ -620,7 +634,7 @@ void generate_files(int f_out, struct fi
184 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
186 + file, i, f_out, f_out_name);
190 @@ -637,7 +651,7 @@ void generate_files(int f_out, struct fi
191 while ((i = get_redo_num()) != -1) {
192 struct file_struct *file = flist->files[i];
193 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
195 + file, i, f_out, f_out_name);
199 @@ -656,7 +670,7 @@ void generate_files(int f_out, struct fi
200 if (!file->basename || !S_ISDIR(file->mode))
202 recv_generator(local_name ? local_name : f_name(file),
208 --- orig/main.c 2004-08-05 18:24:21
209 +++ main.c 2004-07-22 00:10:43
210 @@ -59,6 +59,7 @@ extern int filesfrom_fd;
211 extern pid_t cleanup_child_pid;
212 extern char *files_from;
213 extern char *remote_filesfrom_file;
214 +extern char *compare_dest;
215 extern char *rsync_path;
216 extern char *shell_cmd;
217 extern char *batch_name;
218 @@ -461,7 +462,8 @@ static int do_recv(int f_in,int f_out,st
223 + int error_pipe[2], name_pipe[2];
224 + BOOL need_name_pipe = compare_dest && !dry_run;
226 /* The receiving side mustn't obey this, or an existing symlink that
227 * points to an identical file won't be replaced by the referent. */
228 @@ -476,8 +478,9 @@ static int do_recv(int f_in,int f_out,st
232 - if (fd_pair(error_pipe) < 0) {
233 - rprintf(FERROR,"error pipe failed in do_recv\n");
234 + if (fd_pair(error_pipe) < 0
235 + || (need_name_pipe && fd_pair(name_pipe) < 0)) {
236 + rprintf(FERROR, "fd_pair() failed in do_recv\n");
237 exit_cleanup(RERR_SOCKETIO);
240 @@ -485,6 +488,11 @@ static int do_recv(int f_in,int f_out,st
242 if ((pid = do_fork()) == 0) {
243 close(error_pipe[0]);
244 + if (need_name_pipe) {
245 + close(name_pipe[1]);
246 + set_blocking(name_pipe[0]);
252 @@ -494,7 +502,7 @@ static int do_recv(int f_in,int f_out,st
253 /* set place to send errors */
254 set_msg_fd_out(error_pipe[1]);
256 - recv_files(f_in,flist,local_name);
257 + recv_files(f_in, flist, local_name, name_pipe[0]);
258 io_flush(FULL_FLUSH);
261 @@ -513,6 +521,11 @@ static int do_recv(int f_in,int f_out,st
264 close(error_pipe[1]);
265 + if (need_name_pipe) {
266 + close(name_pipe[0]);
267 + set_nonblocking(name_pipe[1]);
273 @@ -520,7 +533,7 @@ static int do_recv(int f_in,int f_out,st
275 set_msg_fd_in(error_pipe[0]);
277 - generate_files(f_out, flist, local_name);
278 + generate_files(f_out, flist, local_name, name_pipe[1]);
280 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
282 --- orig/receiver.c 2004-09-07 21:45:30
283 +++ receiver.c 2004-09-07 21:57:20
284 @@ -333,7 +333,8 @@ static void discard_receive_data(int f_i
285 * main routine for receiver process.
287 * Receiver process runs on the same host as the generator process. */
288 -int recv_files(int f_in, struct file_list *flist, char *local_name)
289 +int recv_files(int f_in, struct file_list *flist, char *local_name,
294 @@ -362,8 +363,13 @@ int recv_files(int f_in, struct file_lis
298 - if (next_gen_i != flist->count)
299 - while (read_int(batch_gen_fd) != -1) {}
300 + if (next_gen_i != flist->count) {
303 + && next_gen_i >= 0)
304 + read_byte(f_in_name);
305 + } while (read_int(batch_gen_fd) != -1);
310 @@ -411,6 +417,8 @@ int recv_files(int f_in, struct file_lis
313 while (i > next_gen_i) {
314 + if (f_in_name >= 0 && next_gen_i >= 0)
315 + read_byte(f_in_name);
316 next_gen_i = read_int(batch_gen_fd);
317 if (next_gen_i == -1)
318 next_gen_i = flist->count;
319 @@ -421,6 +429,7 @@ int recv_files(int f_in, struct file_lis
320 discard_receive_data(f_in, file->length);
326 if (server_exclude_list.head
327 @@ -430,35 +439,31 @@ int recv_files(int f_in, struct file_lis
328 exit_cleanup(RERR_PROTOCOL);
332 - if ((partialptr = partial_dir_fname(fname)) != NULL)
333 - fnamecmp = partialptr;
335 + partialptr = partial_dir ? partial_dir_fname(fname) : fname;
337 + if (f_in_name >= 0) {
338 + switch (read_byte(f_in_name)) {
342 + case G2R_PARTIAL_DIR:
343 + fnamecmp = partialptr ? partialptr : fname;
346 + fnamecmp = get_backup_name(fname);
349 + pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
350 + compare_dest, fname);
351 + fnamecmp = fnamecmpbuf;
355 - fnamecmp = partialptr = fname;
357 - if (inplace && make_backups) {
358 - if (!(fnamecmp = get_backup_name(fname)))
359 - fnamecmp = partialptr;
364 fd1 = do_open(fnamecmp, O_RDONLY, 0);
366 - if (fd1 == -1 && fnamecmp != fname) {
368 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
371 - if (fd1 == -1 && compare_dest != NULL) {
372 - /* try the file at compare_dest instead */
373 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
374 - compare_dest, fname);
375 - fnamecmp = fnamecmpbuf;
376 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
379 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
380 rsyserr(FERROR, errno, "fstat %s failed",
381 full_fname(fnamecmp));
382 --- orig/rsync.h 2004-08-03 15:41:32
383 +++ rsync.h 2004-09-07 21:52:22
385 #define PDIR_CREATE 1
386 #define PDIR_DELETE 0
388 +#define G2R_FNAME 0x80
389 +#define G2R_PARTIAL_DIR 0x81
390 +#define G2R_BACKUP 0x82
393 /* Log-message categories. FLOG is only used on the daemon side to
394 * output messages to the log file. */