Updated.
[rsync/rsync-patches.git] / g2r-basis-filename.diff
... / ...
CommitLineData
1Added a pipe from the generator to the receiver that communicates
2what basis file we used to generate the file data (if it was not
3the default name). This optimizes away the basis-file search in
4the receiver and makes future options that do more basis-file
5searching more efficient (such as the --fuzzy option and the
6support for multiple --compare-dest options).
7
8Also fixes a potential synchronization problem between the generator
9and the receiver in read-batch mode. Should consider making the
10sending of the index value the default for this pipe (it's currently
11only sent in batch mode due to the sender not listening to the
12generator to determine what files get updated).
13
14You must run "make proto" before compiling.
15
16--- orig/generator.c 2004-07-20 21:36:07
17+++ generator.c 2004-07-17 15:50:09
18@@ -258,9 +258,9 @@ static void generate_and_send_sums(int f
19 * out. It might be wrong.
20 */
21 static void recv_generator(char *fname, struct file_struct *file, int i,
22- int f_out)
23+ int f_out, int f_nameout)
24 {
25- int fd;
26+ int fd = -1;
27 STRUCT_STAT st;
28 int statret;
29 char *fnamecmp;
30@@ -404,9 +404,6 @@ static void recv_generator(char *fname,
31 }
32 #endif
33
34- if (read_batch)
35- return;
36-
37 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
38 return;
39
40@@ -424,8 +421,10 @@ static void recv_generator(char *fname,
41 statret = link_stat(fnamecmpbuf, &st, 0);
42 if (!S_ISREG(st.st_mode))
43 statret = -1;
44- if (statret == -1)
45+ if (statret == -1) {
46 errno = saveerrno;
47+ *fnamecmpbuf = '\0';
48+ }
49 #if HAVE_LINK
50 else if (link_dest && !dry_run) {
51 if (do_link(fnamecmpbuf, fname) != 0) {
52@@ -433,22 +432,22 @@ static void recv_generator(char *fname,
53 rsyserr(FINFO, errno, "link %s => %s",
54 fnamecmpbuf, fname);
55 }
56- }
57- fnamecmp = fnamecmpbuf;
58+ fnamecmp = fnamecmpbuf;
59+ } else
60+ *fnamecmpbuf = '\0';
61 }
62 #endif
63 else
64 fnamecmp = fnamecmpbuf;
65- }
66+ } else
67+ *fnamecmpbuf = '\0';
68
69 if (statret == -1) {
70 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
71 return;
72- if (errno == ENOENT) {
73- write_int(f_out,i);
74- if (!dry_run)
75- write_sum_head(f_out, NULL);
76- } else if (verbose > 1) {
77+ if (errno == ENOENT)
78+ goto notify_others;
79+ if (verbose > 1) {
80 rsyserr(FERROR, errno,
81 "recv_generator: failed to open %s",
82 full_fname(fname));
83@@ -457,26 +456,23 @@ static void recv_generator(char *fname,
84 }
85
86 if (!S_ISREG(st.st_mode)) {
87- if (delete_file(fname) != 0) {
88+ if (delete_file(fname) != 0)
89 return;
90- }
91
92 /* now pretend the file didn't exist */
93 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
94 return;
95- write_int(f_out,i);
96- if (!dry_run)
97- write_sum_head(f_out, NULL);
98- return;
99+ statret = -1;
100+ goto notify_others;
101 }
102
103- if (opt_ignore_existing && fnamecmp == fname) {
104+ if (opt_ignore_existing && !*fnamecmpbuf) {
105 if (verbose > 1)
106 rprintf(FINFO,"%s exists\n",fname);
107 return;
108 }
109
110- if (update_only && fnamecmp == fname
111+ if (update_only && !*fnamecmpbuf
112 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
113 if (verbose > 1)
114 rprintf(FINFO,"%s is newer\n",fname);
115@@ -484,21 +480,17 @@ static void recv_generator(char *fname,
116 }
117
118 if (skip_file(fname, file, &st)) {
119- if (fnamecmp == fname)
120+ if (!*fnamecmpbuf)
121 set_perms(fname, file, &st, PERMS_REPORT);
122 return;
123 }
124
125- if (dry_run) {
126- write_int(f_out,i);
127- return;
128- }
129-
130- if (whole_file > 0) {
131- write_int(f_out,i);
132- write_sum_head(f_out, NULL);
133- return;
134+ if (dry_run || whole_file) {
135+ statret = -1;
136+ goto notify_others;
137 }
138+ if (read_batch)
139+ goto notify_others;
140
141 /* open the file */
142 fd = do_open(fnamecmp, O_RDONLY, 0);
143@@ -509,9 +501,8 @@ static void recv_generator(char *fname,
144 /* pretend the file didn't exist */
145 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
146 return;
147- write_int(f_out,i);
148- write_sum_head(f_out, NULL);
149- return;
150+ statret = -1;
151+ goto notify_others;
152 }
153
154 if (verbose > 3) {
155@@ -522,14 +513,41 @@ static void recv_generator(char *fname,
156 if (verbose > 2)
157 rprintf(FINFO, "generating and sending sums for %d\n", i);
158
159- write_int(f_out,i);
160- generate_and_send_sums(fd, st.st_size, f_out);
161+notify_others:
162+ if (f_nameout >= 0) {
163+ uchar lenbuf[3], *lb = lenbuf;
164+ int len = statret == -1 ? 0 : strlen(fnamecmpbuf);
165+ if (read_batch)
166+ write_int(f_nameout, i);
167+ if (len > 0x7F) {
168+#if MAXPATHLEN > 0x7FFF
169+ *lb++ = len / 0x10000 + 0x80;
170+ *lb++ = len / 0x100;
171+#else
172+ *lb++ = len / 0x100 + 0x80;
173+#endif
174+ }
175+ *lb = len;
176+ write_buf(f_nameout, lenbuf, lb - lenbuf + 1);
177+ if (len)
178+ write_buf(f_nameout, fnamecmpbuf, len);
179+ }
180
181- close(fd);
182+ if (read_batch)
183+ return;
184+
185+ write_int(f_out, i);
186+ if (statret == 0) {
187+ generate_and_send_sums(fd, st.st_size, f_out);
188+
189+ close(fd);
190+ } else if (!dry_run)
191+ write_sum_head(f_out, NULL);
192 }
193
194
195-void generate_files(int f_out, struct file_list *flist, char *local_name)
196+void generate_files(int f_out, struct file_list *flist, char *local_name,
197+ int f_nameout)
198 {
199 int i;
200 int phase = 0;
201@@ -570,7 +588,7 @@ void generate_files(int f_out, struct fi
202 }
203
204 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
205- file, i, f_out);
206+ file, i, f_out, f_nameout);
207 }
208
209 phase++;
210@@ -581,13 +599,15 @@ void generate_files(int f_out, struct fi
211 rprintf(FINFO,"generate_files phase=%d\n",phase);
212
213 write_int(f_out, -1);
214+ if (read_batch)
215+ write_int(f_nameout, flist->count);
216
217 /* files can cycle through the system more than once
218 * to catch initial checksum errors */
219 while ((i = get_redo_num()) != -1) {
220 struct file_struct *file = flist->files[i];
221 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
222- file, i, f_out);
223+ file, i, f_out, f_nameout);
224 }
225
226 phase++;
227@@ -595,6 +615,8 @@ void generate_files(int f_out, struct fi
228 rprintf(FINFO,"generate_files phase=%d\n",phase);
229
230 write_int(f_out, -1);
231+ if (read_batch)
232+ write_int(f_nameout, flist->count);
233
234 if (preserve_hard_links)
235 do_hard_links();
236@@ -606,7 +628,7 @@ void generate_files(int f_out, struct fi
237 if (!file->basename || !S_ISDIR(file->mode))
238 continue;
239 recv_generator(local_name ? local_name : f_name(file),
240- file, i, -1);
241+ file, i, -1, -1);
242 }
243
244 if (verbose > 2)
245--- orig/main.c 2004-07-19 17:14:44
246+++ main.c 2004-07-17 15:58:11
247@@ -57,6 +57,7 @@ extern int filesfrom_fd;
248 extern pid_t cleanup_child_pid;
249 extern char *files_from;
250 extern char *remote_filesfrom_file;
251+extern char *compare_dest;
252 extern char *rsync_path;
253 extern char *shell_cmd;
254 extern char *batch_name;
255@@ -444,20 +445,21 @@ static int do_recv(int f_in,int f_out,st
256 {
257 int pid;
258 int status = 0;
259- int error_pipe[2];
260+ int error_pipe[2], name_pipe[2];
261+ int need_name_pipe = compare_dest || read_batch;
262
263 if (preserve_hard_links)
264 init_hard_links(flist);
265
266 if (!delete_after) {
267 /* I moved this here from recv_files() to prevent a race condition */
268- if (recurse && delete_mode && !local_name && flist->count>0) {
269+ if (recurse && delete_mode && !local_name && flist->count > 0)
270 delete_files(flist);
271- }
272 }
273
274- if (fd_pair(error_pipe) < 0) {
275- rprintf(FERROR,"error pipe failed in do_recv\n");
276+ if (fd_pair(error_pipe) < 0
277+ || (need_name_pipe && fd_pair(name_pipe) < 0)) {
278+ rprintf(FERROR, "fd_pair() failed in do_recv\n");
279 exit_cleanup(RERR_SOCKETIO);
280 }
281
282@@ -465,6 +467,11 @@ static int do_recv(int f_in,int f_out,st
283
284 if ((pid = do_fork()) == 0) {
285 close(error_pipe[0]);
286+ if (need_name_pipe) {
287+ close(name_pipe[1]);
288+ set_blocking(name_pipe[0]);
289+ } else
290+ name_pipe[0] = -1;
291 if (f_in != f_out)
292 close(f_out);
293
294@@ -474,7 +481,7 @@ static int do_recv(int f_in,int f_out,st
295 /* set place to send errors */
296 set_msg_fd_out(error_pipe[1]);
297
298- recv_files(f_in,flist,local_name);
299+ recv_files(f_in, flist, local_name, name_pipe[0]);
300 io_flush(FULL_FLUSH);
301 report(f_in);
302
303@@ -492,6 +499,11 @@ static int do_recv(int f_in,int f_out,st
304 stop_write_batch();
305
306 close(error_pipe[1]);
307+ if (need_name_pipe) {
308+ close(name_pipe[0]);
309+ set_nonblocking(name_pipe[1]);
310+ } else
311+ name_pipe[1] = -1;
312 if (f_in != f_out)
313 close(f_in);
314
315@@ -499,7 +511,7 @@ static int do_recv(int f_in,int f_out,st
316
317 set_msg_fd_in(error_pipe[0]);
318
319- generate_files(f_out, flist, local_name);
320+ generate_files(f_out, flist, local_name, name_pipe[1]);
321
322 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
323 report(-1);
324--- orig/receiver.c 2004-07-20 21:36:07
325+++ receiver.c 2004-07-19 16:44:39
326@@ -28,6 +28,7 @@ extern int max_delete;
327 extern int csum_length;
328 extern struct stats stats;
329 extern int dry_run;
330+extern int read_batch;
331 extern int am_server;
332 extern int relative_paths;
333 extern int keep_dirlinks;
334@@ -318,6 +319,30 @@ static int receive_data(int f_in, char *
335 }
336
337
338+static char *read_gen_name(int fd, char *buf, char *realname)
339+{
340+ int len = read_byte(fd);
341+ if (len & 0x80) {
342+#if MAXPATHLEN > 32767
343+ uchar lenbuf[2];
344+ read_buf(fd, (char *)lenbuf, 2);
345+ len = (len & ~0x80) * 0x10000 + lenbuf[0] * 0x100 + lenbuf[1];
346+#else
347+ len = (len & ~0x80) * 0x100 + read_byte(fd);
348+#endif
349+ }
350+ if (len) {
351+ if (len >= MAXPATHLEN) {
352+ rprintf(FERROR, "bogus data on generator name pipe\n");
353+ exit_cleanup(RERR_PROTOCOL);
354+ }
355+ read_sbuf(fd, buf, len);
356+ return buf;
357+ }
358+ return realname;
359+}
360+
361+
362 static void discard_receive_data(int f_in, OFF_T length)
363 {
364 receive_data(f_in, NULL, -1, 0, NULL, -1, length);
365@@ -328,8 +353,10 @@ static void discard_receive_data(int f_i
366 * main routine for receiver process.
367 *
368 * Receiver process runs on the same host as the generator process. */
369-int recv_files(int f_in, struct file_list *flist, char *local_name)
370+int recv_files(int f_in, struct file_list *flist, char *local_name,
371+ int f_name_in)
372 {
373+ int next_gen_i = -1;
374 int fd1,fd2;
375 STRUCT_STAT st;
376 char *fname, fbuf[MAXPATHLEN];
377@@ -355,6 +382,17 @@ int recv_files(int f_in, struct file_lis
378
379 i = read_int(f_in);
380 if (i == -1) {
381+ if (read_batch) {
382+ if (next_gen_i < 0)
383+ next_gen_i = read_int(f_name_in);
384+ while (next_gen_i < flist->count) {
385+ read_gen_name(f_name_in, fnamecmpbuf,
386+ NULL);
387+ next_gen_i = read_int(f_name_in);
388+ }
389+ next_gen_i = -1;
390+ }
391+
392 if (phase)
393 break;
394
395@@ -397,7 +435,26 @@ int recv_files(int f_in, struct file_lis
396 if (verbose > 2)
397 rprintf(FINFO,"recv_files(%s)\n",fname);
398
399- fnamecmp = fname;
400+ if (read_batch) {
401+ if (next_gen_i < 0)
402+ next_gen_i = read_int(f_name_in);
403+ while (i > next_gen_i) {
404+ read_gen_name(f_name_in, fnamecmpbuf, NULL);
405+ next_gen_i = read_int(f_name_in);
406+ }
407+ if (i < next_gen_i) {
408+ rprintf(FINFO, "skipping update for \"%s\"\n",
409+ fname);
410+ discard_receive_data(f_in, file->length);
411+ continue;
412+ }
413+ next_gen_i = -1;
414+ }
415+
416+ if (f_name_in >= 0)
417+ fnamecmp = read_gen_name(f_name_in, fnamecmpbuf, fname);
418+ else
419+ fnamecmp = fname;
420
421 if (server_exclude_list.head
422 && check_exclude(&server_exclude_list, fname,
423@@ -414,14 +471,6 @@ int recv_files(int f_in, struct file_lis
424 /* open the file */
425 fd1 = do_open(fnamecmp, O_RDONLY, 0);
426
427- if (fd1 == -1 && compare_dest != NULL) {
428- /* try the file at compare_dest instead */
429- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
430- compare_dest, fname);
431- fnamecmp = fnamecmpbuf;
432- fd1 = do_open(fnamecmp, O_RDONLY, 0);
433- }
434-
435 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
436 rsyserr(FERROR, errno, "fstat %s failed",
437 full_fname(fnamecmp));