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-08-03 15:41:32
11 +++ generator.c 2004-07-30 07:18:03
12 @@ -249,13 +249,13 @@ 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)
22 int statret, stat_errno;
24 - char fnamecmpbuf[MAXPATHLEN];
25 + char *fnamecmp, fnamecmpbuf[MAXPATHLEN];
26 + uchar fnamecmp_type;
30 @@ -411,6 +411,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 @@ -427,10 +428,14 @@ static void recv_generator(char *fname,
41 fnamecmp = fnamecmpbuf;
47 fnamecmp = fnamecmpbuf;
53 @@ -445,11 +450,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 @@ -457,13 +460,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 @@ -471,21 +474,17 @@ 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);
94 - if (dry_run || read_batch) {
99 - if (whole_file > 0) {
100 - write_int(f_out,i);
101 - write_sum_head(f_out, NULL);
103 + if (dry_run || whole_file) {
105 + goto notify_others;
108 + goto notify_others;
112 @@ -494,6 +493,7 @@ static void recv_generator(char *fname,
113 && S_ISREG(st2.st_mode)) {
115 fnamecmp = partialptr;
116 + fnamecmp_type = G2R_PARTIAL_DIR;
120 @@ -506,9 +506,8 @@ static void recv_generator(char *fname,
121 /* pretend the file didn't exist */
122 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
124 - write_int(f_out,i);
125 - write_sum_head(f_out, NULL);
128 + goto notify_others;
132 @@ -519,14 +518,28 @@ static void recv_generator(char *fname,
134 rprintf(FINFO, "generating and sending sums for %d\n", i);
136 - write_int(f_out,i);
137 - generate_and_send_sums(fd, st.st_size, f_out);
139 + if (f_out_name >= 0) {
140 + write_byte(f_out_name, fnamecmp_type);
141 + io_flush(NORMAL_FLUSH); /* XXX make this more efficient! */
144 + write_int(f_out, i);
147 + if (dry_run || read_batch)
150 + if (statret == 0) {
151 + generate_and_send_sums(fd, st.st_size, f_out);
155 + write_sum_head(f_out, NULL);
159 -void generate_files(int f_out, struct file_list *flist, char *local_name)
160 +void generate_files(int f_out, struct file_list *flist, char *local_name,
165 @@ -567,7 +580,7 @@ void generate_files(int f_out, struct fi
168 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
170 + file, i, f_out, f_out_name);
174 @@ -584,7 +597,7 @@ void generate_files(int f_out, struct fi
175 while ((i = get_redo_num()) != -1) {
176 struct file_struct *file = flist->files[i];
177 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
179 + file, i, f_out, f_out_name);
183 @@ -603,7 +616,7 @@ void generate_files(int f_out, struct fi
184 if (!file->basename || !S_ISDIR(file->mode))
186 recv_generator(local_name ? local_name : f_name(file),
192 --- orig/main.c 2004-07-31 16:41:04
193 +++ main.c 2004-07-22 00:10:43
194 @@ -59,6 +59,7 @@ extern int filesfrom_fd;
195 extern pid_t cleanup_child_pid;
196 extern char *files_from;
197 extern char *remote_filesfrom_file;
198 +extern char *compare_dest;
199 extern char *rsync_path;
200 extern char *shell_cmd;
201 extern char *batch_name;
202 @@ -457,7 +458,8 @@ static int do_recv(int f_in,int f_out,st
207 + int error_pipe[2], name_pipe[2];
208 + BOOL need_name_pipe = compare_dest && !dry_run;
210 /* The receiving side mustn't obey this, or an existing symlink that
211 * points to an identical file won't be replaced by the referent. */
212 @@ -472,8 +474,9 @@ static int do_recv(int f_in,int f_out,st
216 - if (fd_pair(error_pipe) < 0) {
217 - rprintf(FERROR,"error pipe failed in do_recv\n");
218 + if (fd_pair(error_pipe) < 0
219 + || (need_name_pipe && fd_pair(name_pipe) < 0)) {
220 + rprintf(FERROR, "fd_pair() failed in do_recv\n");
221 exit_cleanup(RERR_SOCKETIO);
224 @@ -481,6 +484,11 @@ static int do_recv(int f_in,int f_out,st
226 if ((pid = do_fork()) == 0) {
227 close(error_pipe[0]);
228 + if (need_name_pipe) {
229 + close(name_pipe[1]);
230 + set_blocking(name_pipe[0]);
236 @@ -490,7 +498,7 @@ static int do_recv(int f_in,int f_out,st
237 /* set place to send errors */
238 set_msg_fd_out(error_pipe[1]);
240 - recv_files(f_in,flist,local_name);
241 + recv_files(f_in, flist, local_name, name_pipe[0]);
242 io_flush(FULL_FLUSH);
245 @@ -509,6 +517,11 @@ static int do_recv(int f_in,int f_out,st
248 close(error_pipe[1]);
249 + if (need_name_pipe) {
250 + close(name_pipe[0]);
251 + set_nonblocking(name_pipe[1]);
257 @@ -516,7 +529,7 @@ static int do_recv(int f_in,int f_out,st
259 set_msg_fd_in(error_pipe[0]);
261 - generate_files(f_out, flist, local_name);
262 + generate_files(f_out, flist, local_name, name_pipe[1]);
264 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
266 --- orig/receiver.c 2004-08-03 15:34:32
267 +++ receiver.c 2004-07-30 07:17:48
268 @@ -333,7 +333,8 @@ static void discard_receive_data(int f_i
269 * main routine for receiver process.
271 * Receiver process runs on the same host as the generator process. */
272 -int recv_files(int f_in, struct file_list *flist, char *local_name)
273 +int recv_files(int f_in, struct file_list *flist, char *local_name,
278 @@ -362,8 +363,13 @@ int recv_files(int f_in, struct file_lis
282 - if (next_gen_i != flist->count)
283 - while (read_int(batch_gen_fd) != -1) {}
284 + if (next_gen_i != flist->count) {
287 + && next_gen_i >= 0)
288 + read_byte(f_in_name);
289 + } while (read_int(batch_gen_fd) != -1);
294 @@ -411,6 +417,8 @@ int recv_files(int f_in, struct file_lis
297 while (i > next_gen_i) {
298 + if (f_in_name >= 0 && next_gen_i >= 0)
299 + read_byte(f_in_name);
300 next_gen_i = read_int(batch_gen_fd);
301 if (next_gen_i == -1)
302 next_gen_i = flist->count;
303 @@ -421,6 +429,7 @@ int recv_files(int f_in, struct file_lis
304 discard_receive_data(f_in, file->length);
310 if (server_exclude_list.head
311 @@ -430,30 +439,28 @@ int recv_files(int f_in, struct file_lis
312 exit_cleanup(RERR_PROTOCOL);
316 - if ((partialptr = partial_dir_fname(fname)) != NULL)
317 - fnamecmp = partialptr;
319 + partialptr = partial_dir ? partial_dir_fname(fname) : fname;
321 + if (f_in_name >= 0) {
322 + switch (read_byte(f_in_name)) {
326 + case G2R_PARTIAL_DIR:
327 + fnamecmp = partialptr ? partialptr : fname;
330 + pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
331 + compare_dest, fname);
332 + fnamecmp = fnamecmpbuf;
336 - fnamecmp = partialptr = fname;
340 fd1 = do_open(fnamecmp, O_RDONLY, 0);
342 - if (fd1 == -1 && fnamecmp != fname) {
344 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
347 - if (fd1 == -1 && compare_dest != NULL) {
348 - /* try the file at compare_dest instead */
349 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
350 - compare_dest, fname);
351 - fnamecmp = fnamecmpbuf;
352 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
355 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
356 rsyserr(FERROR, errno, "fstat %s failed",
357 full_fname(fnamecmp));
358 --- orig/rsync.h 2004-08-03 15:41:32
359 +++ rsync.h 2004-07-30 07:16:38
361 #define PDIR_CREATE 1
362 #define PDIR_DELETE 0
364 +#define G2R_FNAME 0x80
365 +#define G2R_PARTIAL_DIR 0x81
368 /* Log-message categories. FLOG is only used on the daemon side to
369 * output messages to the log file. */