/*
* rcopy-repeatedly
+ *
+ * You say rcopy-repeatedly local-file user@host:remote-file
+ * and it polls for changes to local-file and copies them to
+ * remote-file. rcopy-repeatedly must be installed at the far end.
+ * You can copy in either direction but not between two remote
+ * locations.
+ *
+ * Limitations:
+ * * Cannot cope with files which are modified between us opening
+ * and statting them for the first time; if the file shrinks
+ * we may bomb out. Workaround: use rename-in-place.
+ * * When transferring large files, bandwidth limiter will
+ * be `lumpy' as the whole file is transferred and then we
+ * sleep.
+ * * Cannot copy between two local files. Workaround: a symlink
+ * (but presumably there was some reason you weren't doing that)
+ * * No ability to synchronise more than just exactly one file
+ * * Polls. It would be nice to use inotify or something.
+ *
+ * Inherent limitations:
+ * * Can only copy plain files.
+ *
+ * See the --help for options.
*/
-
+
+/*
+ * rcopy-repeatedly is
+ * Copyright (C) 2008 Ian Jackson <ian@davenant.greenend.org.uk>
+ * and the option parser we use is
+ * Copyright (C) 1994,1995 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this file; if not, consult the Free Software
+ * Foundation's website at www.fsf.org, or the GNU Project website at
+ * www.gnu.org.
+ */
+
/*
* protocol is:
* server sends banner
static FILE *commsi, *commso;
-static double max_bw_prop_mean= 0.2;
-static double max_bw_prop_burst= 0.8;
+static double max_bw_prop= 0.2;
static int txblocksz= INT_MAX, verbose=1;
static int min_interval_usec= 100000; /* 100ms */
* since we regard the subprocess as `down' */
static int udchar;
-static double stream_allow_secsperbyte= 1/1e6; /* for initial transfer */
static char mainbuf[65536]; /* must be at least 2^16 */
double elapsed= mgettime_elapsed(ts_sendstart, &ts_buf);
double secsperbyte_observed= elapsed / bytes;
- stream_allow_secsperbyte=
- secsperbyte_observed * max_bw_prop_mean / max_bw_prop_burst;
-
- double min_update= elapsed / max_bw_prop_mean;
+ double min_update= elapsed / max_bw_prop;
if (min_update > 1e3) min_update= 1e3;
int min_update_usec= min_update * 1e6;
- if (*interval_usec_update > min_update_usec)
+ if (*interval_usec_update < min_update_usec)
*interval_usec_update= min_update_usec;
- verbosespinprintf("%12lluby %10.3fs %13.2fkby/s",
+ verbosespinprintf("%12lluby %10.3fs %13.2fkby/s %8dms",
(unsigned long long)bytes, elapsed,
- 1e-3/secsperbyte_observed);
+ 1e-3/secsperbyte_observed, *interval_usec_update/1000);
}
static void copyfile(FILE *sf, copyfile_die_fn *sdie, const char *sxi,
now= l < sizeof(mainbuf) ? l : sizeof(mainbuf);
if (now > txblocksz) now= txblocksz;
+ r= fread(mainbuf,1,now,sf); if (r!=now) sdie(sf,sxi);
+ r= fwrite(mainbuf,1,now,df); if (r!=now) ddie(df,dxi);
+ l -= now;
+ done += now;
+
if (verbose) {
fprintf(stderr," %3d%% \r",
(int)(done*100.0/lstart));
flushstderr();
}
-
- if (amsender) {
- double elapsed_want= now * stream_allow_secsperbyte;
- double elapsed= mgettime_elapsed(ts_last, &ts_last);
- double needwait= elapsed_want - elapsed;
- if (needwait > 1) needwait= 1;
- if (needwait > 0) usleep(ceil(needwait * 1e6));
- }
-
- r= fread(mainbuf,1,now,sf); if (r!=now) sdie(sf,sxi);
- r= fwrite(mainbuf,1,now,df); if (r!=now) ddie(df,dxi);
- l -= now;
- done += now;
}
}
if (!f) {
if (errno!=ENOENT) diee("could not access source file `%s'",filename);
if (told != told_remove) {
- verbosespinprintf(" ENOENT ");
+ verbosespinprintf
+ (" ENOENT ");
sendbyte(REPLMSG_RM);
told= told_remove;
}
" --help\n"
" --quiet | -q\n"
"options for bandwidth (and cpu time) control:\n"
- " --max-bandwidth-percent-mean (default %d)\n"
- " --max-bandwidth-percent-burst (default %d)\n"
+ " --max-bandwidth-percent (default %d)\n"
" --tx-block-size (default/max %d)\n"
" --min-interval-usec (default %d)\n"
"options for finding programs:\n"
" --rsh-program (default: $RCOPY_REPEATEDLY_RSH or $RSYNC_RSH or ssh)\n"
"options passed to server side via ssh:\n"
" --receiver --sender, bandwidth control options\n",
- (int)(max_bw_prop_mean*100), (int)(max_bw_prop_burst*100),
- (int)sizeof(mainbuf), min_interval_usec);
+ (int)(max_bw_prop*100), (int)sizeof(mainbuf), min_interval_usec);
}
static const struct cmdinfo cmdinfos[]= {
{ "help", .call= of_help },
- { "max-bandwidth-percent-mean", 0,1,.call=of_bw,.parg=&max_bw_prop_mean },
- { "max-bandwidth-percent-burst",0,1,.call=of_bw,.parg=&max_bw_prop_burst },
+ { "max-bandwidth-percent", 0,1,.call=of_bw,.parg=&max_bw_prop },
{ "tx-block-size",0, 1,.call=of_server_int, .parg=&txblocksz },
{ "min-interval-usec",0, 1,.call=of_server_int, .parg=&min_interval_usec },
{ "rcopy-repeatedly",0, 1, .sassignto=&rcopy_repeatedly_program },
if (!rsh_program) rsh_program= getenv("RSYNC_RSH");
if (!rsh_program) rsh_program= "ssh";
- if (max_bw_prop_burst / max_bw_prop_mean < 1.1)
- badusage("max bandwidth prop burst must be at least 1.1x"
- " max bandwidth prop mean");
-
if (txblocksz<1) badusage("transmit block size must be at least 1");
if (min_interval_usec<0) badusage("minimum update interval may not be -ve");