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 Also fixes a potential synchronization problem between the generator
9 and the receiver in read-batch mode. Should consider making the
10 sending of the index value the default for this pipe (it's currently
11 only sent in batch mode due to the sender not listening to the
12 generator to determine what files get updated).
14 You must run "make proto" before compiling.
16 --- orig/generator.c 2004-07-17 16:30:20
17 +++ generator.c 2004-07-17 15:50:09
18 @@ -251,11 +251,11 @@ static void generate_and_send_sums(struc
19 * out. It might be wrong.
21 static void recv_generator(char *fname, struct file_struct *file, int i,
23 + int f_out, int f_nameout)
28 - struct map_struct *mapbuf;
29 + struct map_struct *mapbuf = NULL;
32 char fnamecmpbuf[MAXPATHLEN];
33 @@ -398,9 +398,6 @@ static void recv_generator(char *fname,
40 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
43 @@ -418,8 +415,10 @@ static void recv_generator(char *fname,
44 statret = link_stat(fnamecmpbuf, &st, 0);
45 if (!S_ISREG(st.st_mode))
48 + if (statret == -1) {
50 + *fnamecmpbuf = '\0';
53 else if (link_dest && !dry_run) {
54 if (do_link(fnamecmpbuf, fname) != 0) {
55 @@ -427,22 +426,22 @@ static void recv_generator(char *fname,
56 rsyserr(FINFO, errno, "link %s => %s",
60 - fnamecmp = fnamecmpbuf;
61 + fnamecmp = fnamecmpbuf;
63 + *fnamecmpbuf = '\0';
67 fnamecmp = fnamecmpbuf;
70 + *fnamecmpbuf = '\0';
73 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
75 - if (errno == ENOENT) {
78 - write_sum_head(f_out, NULL);
79 - } else if (verbose > 1) {
80 + if (errno == ENOENT)
83 rsyserr(FERROR, errno,
84 "recv_generator: failed to open %s",
86 @@ -451,26 +450,23 @@ static void recv_generator(char *fname,
89 if (!S_ISREG(st.st_mode)) {
90 - if (delete_file(fname) != 0) {
91 + if (delete_file(fname) != 0)
95 /* now pretend the file didn't exist */
96 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
100 - write_sum_head(f_out, NULL);
103 + goto notify_others;
106 - if (opt_ignore_existing && fnamecmp == fname) {
107 + if (opt_ignore_existing && !*fnamecmpbuf) {
109 rprintf(FINFO,"%s exists\n",fname);
113 - if (update_only && fnamecmp == fname
114 + if (update_only && !*fnamecmpbuf
115 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
117 rprintf(FINFO,"%s is newer\n",fname);
118 @@ -478,21 +474,17 @@ static void recv_generator(char *fname,
121 if (skip_file(fname, file, &st)) {
122 - if (fnamecmp == fname)
124 set_perms(fname, file, &st, PERMS_REPORT);
129 - write_int(f_out,i);
133 - if (whole_file > 0) {
134 - write_int(f_out,i);
135 - write_sum_head(f_out, NULL);
137 + if (dry_run || whole_file) {
139 + goto notify_others;
142 + goto notify_others;
145 fd = do_open(fnamecmp, O_RDONLY, 0);
146 @@ -503,15 +495,12 @@ static void recv_generator(char *fname,
147 /* pretend the file didn't exist */
148 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
150 - write_int(f_out,i);
151 - write_sum_head(f_out, NULL);
154 + goto notify_others;
158 mapbuf = map_file(fd,st.st_size);
163 rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
164 @@ -521,16 +510,43 @@ static void recv_generator(char *fname,
166 rprintf(FINFO, "generating and sending sums for %d\n", i);
168 - write_int(f_out,i);
169 - generate_and_send_sums(mapbuf, st.st_size, f_out);
171 + if (f_nameout >= 0) {
172 + uchar lenbuf[3], *lb = lenbuf;
173 + int len = statret == -1 ? 0 : strlen(fnamecmpbuf);
175 + write_int(f_nameout, i);
177 +#if MAXPATHLEN > 0x7FFF
178 + *lb++ = len / 0x10000 + 0x80;
179 + *lb++ = len / 0x100;
181 + *lb++ = len / 0x100 + 0x80;
185 + write_buf(f_nameout, lenbuf, lb - lenbuf + 1);
187 + write_buf(f_nameout, fnamecmpbuf, len);
192 - unmap_file(mapbuf);
196 + write_int(f_out, i);
197 + if (statret == 0) {
198 + generate_and_send_sums(mapbuf, st.st_size, f_out);
202 + unmap_file(mapbuf);
203 + } else if (!dry_run)
204 + write_sum_head(f_out, NULL);
208 -void generate_files(int f_out, struct file_list *flist, char *local_name)
209 +void generate_files(int f_out, struct file_list *flist, char *local_name,
214 @@ -571,7 +587,7 @@ void generate_files(int f_out, struct fi
217 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
219 + file, i, f_out, f_nameout);
223 @@ -582,13 +598,15 @@ void generate_files(int f_out, struct fi
224 rprintf(FINFO,"generate_files phase=%d\n",phase);
226 write_int(f_out, -1);
228 + write_int(f_nameout, flist->count);
230 /* files can cycle through the system more than once
231 * to catch initial checksum errors */
232 while ((i = get_redo_num()) != -1) {
233 struct file_struct *file = flist->files[i];
234 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
236 + file, i, f_out, f_nameout);
240 @@ -596,6 +614,8 @@ void generate_files(int f_out, struct fi
241 rprintf(FINFO,"generate_files phase=%d\n",phase);
243 write_int(f_out, -1);
245 + write_int(f_nameout, flist->count);
247 if (preserve_hard_links)
249 @@ -607,7 +627,7 @@ void generate_files(int f_out, struct fi
250 if (!file->basename || !S_ISDIR(file->mode))
252 recv_generator(local_name ? local_name : f_name(file),
258 --- orig/main.c 2004-07-19 17:14:44
259 +++ main.c 2004-07-17 15:58:11
260 @@ -57,6 +57,7 @@ extern int filesfrom_fd;
261 extern pid_t cleanup_child_pid;
262 extern char *files_from;
263 extern char *remote_filesfrom_file;
264 +extern char *compare_dest;
265 extern char *rsync_path;
266 extern char *shell_cmd;
267 extern char *batch_name;
268 @@ -444,20 +445,21 @@ static int do_recv(int f_in,int f_out,st
273 + int error_pipe[2], name_pipe[2];
274 + int need_name_pipe = compare_dest || read_batch;
276 if (preserve_hard_links)
277 init_hard_links(flist);
280 /* I moved this here from recv_files() to prevent a race condition */
281 - if (recurse && delete_mode && !local_name && flist->count>0) {
282 + if (recurse && delete_mode && !local_name && flist->count > 0)
287 - if (fd_pair(error_pipe) < 0) {
288 - rprintf(FERROR,"error pipe failed in do_recv\n");
289 + if (fd_pair(error_pipe) < 0
290 + || (need_name_pipe && fd_pair(name_pipe) < 0)) {
291 + rprintf(FERROR, "fd_pair() failed in do_recv\n");
292 exit_cleanup(RERR_SOCKETIO);
295 @@ -465,6 +467,11 @@ static int do_recv(int f_in,int f_out,st
297 if ((pid = do_fork()) == 0) {
298 close(error_pipe[0]);
299 + if (need_name_pipe) {
300 + close(name_pipe[1]);
301 + set_blocking(name_pipe[0]);
307 @@ -474,7 +481,7 @@ static int do_recv(int f_in,int f_out,st
308 /* set place to send errors */
309 set_msg_fd_out(error_pipe[1]);
311 - recv_files(f_in,flist,local_name);
312 + recv_files(f_in, flist, local_name, name_pipe[0]);
313 io_flush(FULL_FLUSH);
316 @@ -492,6 +499,11 @@ static int do_recv(int f_in,int f_out,st
319 close(error_pipe[1]);
320 + if (need_name_pipe) {
321 + close(name_pipe[0]);
322 + set_nonblocking(name_pipe[1]);
328 @@ -499,7 +511,7 @@ static int do_recv(int f_in,int f_out,st
330 set_msg_fd_in(error_pipe[0]);
332 - generate_files(f_out, flist, local_name);
333 + generate_files(f_out, flist, local_name, name_pipe[1]);
335 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
337 --- orig/receiver.c 2004-07-19 17:06:10
338 +++ receiver.c 2004-07-19 16:44:39
339 @@ -28,6 +28,7 @@ extern int max_delete;
340 extern int csum_length;
341 extern struct stats stats;
343 +extern int read_batch;
344 extern int am_server;
345 extern int relative_paths;
346 extern int keep_dirlinks;
347 @@ -303,6 +304,30 @@ static int receive_data(int f_in,struct
351 +static char *read_gen_name(int fd, char *buf, char *realname)
353 + int len = read_byte(fd);
355 +#if MAXPATHLEN > 32767
357 + read_buf(fd, (char *)lenbuf, 2);
358 + len = (len & ~0x80) * 0x10000 + lenbuf[0] * 0x100 + lenbuf[1];
360 + len = (len & ~0x80) * 0x100 + read_byte(fd);
364 + if (len >= MAXPATHLEN) {
365 + rprintf(FERROR, "bogus data on generator name pipe\n");
366 + exit_cleanup(RERR_PROTOCOL);
368 + read_sbuf(fd, buf, len);
375 static void discard_receive_data(int f_in, OFF_T length)
377 receive_data(f_in, NULL, -1, NULL, length);
378 @@ -313,8 +338,10 @@ static void discard_receive_data(int f_i
379 * main routine for receiver process.
381 * Receiver process runs on the same host as the generator process. */
382 -int recv_files(int f_in, struct file_list *flist, char *local_name)
383 +int recv_files(int f_in, struct file_list *flist, char *local_name,
386 + int next_gen_i = -1;
389 char *fname, fbuf[MAXPATHLEN];
390 @@ -341,6 +368,17 @@ int recv_files(int f_in, struct file_lis
395 + if (next_gen_i < 0)
396 + next_gen_i = read_int(f_name_in);
397 + while (next_gen_i < flist->count) {
398 + read_gen_name(f_name_in, fnamecmpbuf,
400 + next_gen_i = read_int(f_name_in);
408 @@ -383,7 +421,26 @@ int recv_files(int f_in, struct file_lis
410 rprintf(FINFO,"recv_files(%s)\n",fname);
414 + if (next_gen_i < 0)
415 + next_gen_i = read_int(f_name_in);
416 + while (i > next_gen_i) {
417 + read_gen_name(f_name_in, fnamecmpbuf, NULL);
418 + next_gen_i = read_int(f_name_in);
420 + if (i < next_gen_i) {
421 + rprintf(FINFO, "skipping update for \"%s\"\n",
423 + discard_receive_data(f_in, file->length);
429 + if (f_name_in >= 0)
430 + fnamecmp = read_gen_name(f_name_in, fnamecmpbuf, fname);
434 if (server_exclude_list.head
435 && check_exclude(&server_exclude_list, fname,
436 @@ -400,14 +457,6 @@ int recv_files(int f_in, struct file_lis
438 fd1 = do_open(fnamecmp, O_RDONLY, 0);
440 - if (fd1 == -1 && compare_dest != NULL) {
441 - /* try the file at compare_dest instead */
442 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
443 - compare_dest, fname);
444 - fnamecmp = fnamecmpbuf;
445 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
448 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
449 rsyserr(FERROR, errno, "fstat %s failed",
450 full_fname(fnamecmp));