Greetings,
Upon a suggestion to improve the --timelimit patch, I have also added a --stopat
option.
You can get the patch from this URL and/or cut/paste it from below.
http://www.terry.uga.edu/~jft/rsync-timelimit-stopat.patch.gz
Here are the details...
--timelimit=T
This option allows you to specify the maximum number of minutes
rsync will run for. This time starts when rsync starts to "con-
sider" which files need transferring.
--stopat=YYMMDDHHMMSS
This option allows you to specify at what time to stop rsync, in
yr-mon-day-hr-min-sec numeric format.
-John
diff -urN rsync-2.6.1pre-2/NEWS rsync-2.6.1pre-2_modified/NEWS
--- rsync-2.6.1pre-2/NEWS 2004-04-15 14:23:52.000000000 -0400
+++ rsync-2.6.1pre-2_modified/NEWS 2004-04-22 15:30:17.000000000 -0400
@@ -23,6 +23,13 @@
* Added a couple extra diffs in the "patches" dir, removed the
ones that got applied, and rebuilt the rest.
+ * Added --time-limit=T which will stop rsync after T number
+ of minutes
+
+ * Added --stopat=YYMMDDHHMMSS which will stio rsync at time
+ yr-mon-day-hr-min-sec
+
+
BUG FIXES:
* When -x (--one-file-system) is combined with -L (--copy-links)
diff -urN rsync-2.6.1pre-2/io.c rsync-2.6.1pre-2_modified/io.c
--- rsync-2.6.1pre-2/io.c 2004-01-16 11:31:47.000000000 -0500
+++ rsync-2.6.1pre-2_modified/io.c 2004-04-22 15:52:21.000000000 -0400
@@ -47,13 +47,14 @@
static int no_flush;
extern int bwlimit;
+extern int timelimit;
extern int verbose;
extern int io_timeout;
extern int am_server;
extern int am_daemon;
extern int am_sender;
extern struct stats stats;
-
+extern char *stopat;
const char phase_unknown[] = "unknown";
@@ -759,6 +760,58 @@
select(0, NULL, NULL, NULL, &tv);
}
+/**
+ When --timelimit is used, compare rsync_start_time and the current time and
+ return 1 when the timelimit has been reached.
+ **/
+static int has_timelimit_expired()
+{
+ struct timeval tv;
+ time_t start_time = 0;
+ time_t expiration_time = 0;
+
+ assert(timelimit > 0);
+
+ start_time = get_rsync_start_time();
+ assert( start_time > 0);
+
+ gettimeofday(&tv, NULL);
+ expiration_time = start_time + (timelimit * 60);
+
+ return ( tv.tv_sec > expiration_time ) ? 1 : 0;
+}
+
+/**
+ When --stopat is used, compare current stopat time and the current calendar
time,
+ and return 1 when the stopat time has been reached.
+ **/
+static int has_stopat_expired()
+{
+ static time_t stop_time_secs = 0;
+ time_t now = 0;
+ struct tm stopat_time;
+ char *valid_time = NULL;
+
+ assert(stopat != NULL);
+
+ if( 0 == stop_time_secs ) {
+ valid_time = strptime(stopat, "%y%m%d%H%M%S", &stopat_time);
+ if( NULL == valid_time ) {
+ rprintf(FERROR, "ERROR: invalid --stopat format: %s\n", stopat );
+ exit_cleanup(RERR_SYNTAX);
+ }
+ stop_time_secs = mktime( &stopat_time );
+ }
+
+ if( -1 == stop_time_secs ) {
+ rprintf(FERROR, "ERROR: mktime() returned -1\n" );
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ now = time(NULL);
+
+ return ( now > stop_time_secs ) ? 1 : 0;
+}
/**
* Write len bytes to the file descriptor @p fd.
@@ -772,6 +825,7 @@
fd_set w_fds, r_fds;
int fd_count, count;
struct timeval tv;
+ int time_expired = 0;
msg_list_push(NORMAL_FLUSH);
@@ -837,6 +891,19 @@
}
sleep_for_bwlimit(ret);
+
+ if( timelimit ) {
+ time_expired = has_timelimit_expired();
+ if( 1 == time_expired ) {
+ rprintf(FERROR, RSYNC_NAME ": \n%d minute time limit
exceeded.\n", timelimit);
+ exit_cleanup(RERR_PARTIAL);
+ }
+ }
+
+ if( stopat && has_stopat_expired() ) {
+ rprintf(FERROR, RSYNC_NAME ": \n%s stopat time exceeded.\n",
stopat);
+ exit_cleanup(RERR_PARTIAL);
+ }
total += ret;
diff -urN rsync-2.6.1pre-2/options.c rsync-2.6.1pre-2_modified/options.c
--- rsync-2.6.1pre-2/options.c 2004-04-17 13:07:23.000000000 -0400
+++ rsync-2.6.1pre-2_modified/options.c 2004-04-22 15:46:03.000000000 -0400
@@ -83,6 +83,7 @@
int copy_unsafe_links = 0;
int size_only = 0;
int bwlimit = 0;
+int timelimit = 0;
int delete_after = 0;
int only_existing = 0;
int opt_ignore_existing = 0;
@@ -142,6 +143,9 @@
* address, or a hostname. **/
char *bind_address;
+/** YYMMDDHHMMSS format for the --stopat */
+char *stopat;
+
static void print_rsync_version(enum logcode f)
{
@@ -288,6 +292,8 @@
rprintf(F," --log-format=FORMAT log file transfers using
specified format\n");
rprintf(F," --password-file=FILE get password from FILE\n");
rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per
second\n");
+ rprintf(F," --timelimit=T Stop rsync after T
minutes\n");
+ rprintf(F," --stopat=YYMMDDHHMMSS Stop rsync at time
yr-mon-day-hr-min-sec\n");
rprintf(F," --write-batch=PREFIX write batch fileset starting
with PREFIX\n");
rprintf(F," --read-batch=PREFIX read batch fileset starting with
PREFIX\n");
rprintf(F," -h, --help show this help screen\n");
@@ -377,6 +383,8 @@
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0
},
{"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0
},
{"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
+ {"timelimit", 0, POPT_ARG_INT, &timelimit, 0, 0, 0
},
+ {"stopat", 0, POPT_ARG_STRING, &stopat, 0, 0, 0 },
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0,
0 },
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0
},
{"hard-links", 'H', POPT_ARG_NONE,
&preserve_hard_links, 0, 0, 0 },
@@ -885,6 +893,18 @@
args[ac++] = arg;
}
+ if (timelimit) {
+ if (asprintf(&arg, "--timelimit=%d", timelimit) < 0)
+ goto oom;
+ args[ac++] = arg;
+ }
+
+ if (stopat) {
+ if (asprintf(&arg, "--stopat=%s", stopat) < 0)
+ goto oom;
+ args[ac++] = arg;
+ }
+
if (backup_dir) {
args[ac++] = "--backup-dir";
args[ac++] = backup_dir;
diff -urN rsync-2.6.1pre-2/proto.h rsync-2.6.1pre-2_modified/proto.h
--- rsync-2.6.1pre-2/proto.h 2004-04-14 19:33:30.000000000 -0400
+++ rsync-2.6.1pre-2_modified/proto.h 2004-04-22 15:36:33.000000000 -0400
@@ -267,6 +267,7 @@
int unsafe_symlink(const char *dest, const char *src);
char *timestring(time_t t);
int msleep(int t);
+time_t get_rsync_start_time(void);
int cmp_modtime(time_t file1, time_t file2);
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6);
void *_new_array(unsigned int size, unsigned long num);
diff -urN rsync-2.6.1pre-2/rsync.1 rsync-2.6.1pre-2_modified/rsync.1
--- rsync-2.6.1pre-2/rsync.1 2004-04-17 14:38:47.000000000 -0400
+++ rsync-2.6.1pre-2_modified/rsync.1 2004-04-22 15:36:04.000000000 -0400
@@ -383,6 +383,8 @@
--log-format=FORMAT log file transfers using specified format
--password-file=FILE get password from FILE
--bwlimit=KBPS limit I/O bandwidth, KBytes per second
+ --timelimit=T Stop rsync after T minutes
+ --stopat=YYMMDDHHMMSS Stop rsync at this given time
--write-batch=PREFIX write batch fileset starting with PREFIX
--read-batch=PREFIX read batch fileset starting with PREFIX
-h, --help show this help screen
@@ -1026,6 +1028,15 @@
transfer was too fast, it will wait before sending the next data block\&.
The
result is an average transfer rate equaling the specified limit\&. A value
of zero specifies no limit\&.
+.IP
+.IP "\fB--timelimit=T\fP"
+This option allows you to specify the maximum
+number of minutes rsync will run for\&. This time starts when rsync starts
+to "consider" which files need transferring\&.
+.IP
+.IP "\fB--stopat=YYMMDDHHMMSS\fP"
+This option allows you to specify at what time to stop rsync,
+in yr-mon-day-hr-min-sec numeric format\&.
.IP
.IP "\fB--write-batch=PREFIX\fP"
Generate a set of files that can be
diff -urN rsync-2.6.1pre-2/util.c rsync-2.6.1pre-2_modified/util.c
--- rsync-2.6.1pre-2/util.c 2004-04-17 13:06:03.000000000 -0400
+++ rsync-2.6.1pre-2_modified/util.c 2004-04-22 15:29:57.000000000 -0400
@@ -1050,6 +1050,22 @@
return True;
}
+/**
+ * Return the time that rsync is started, used by --time-limit
+ **/
+time_t get_rsync_start_time(void)
+{
+ static struct timeval tval;
+ static int has_set_rsync_start_time = 0;
+
+ if( ! has_set_rsync_start_time ) {
+ gettimeofday(&tval, NULL);
+ has_set_rsync_start_time = 1;
+ }
+
+ return tval.tv_sec;
+}
+
/**
* Determine if two file modification times are equivalent (either