*
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
static int restore_cmd(JCR *jcr);
static int storage_cmd(JCR *jcr);
static int session_cmd(JCR *jcr);
-static int response(JCR *jcr, BSOCK *sd, char *resp, char *cmd);
+static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
static void filed_free_jcr(JCR *jcr);
static int open_sd_read_session(JCR *jcr);
static int send_bootstrap_file(JCR *jcr);
static int runbefore_cmd(JCR *jcr);
static int runafter_cmd(JCR *jcr);
-static int run_cmd(JCR *jcr, char *cmd, char *name);
+static int run_cmd(JCR *jcr, char *cmd, const char *name);
/* Exported functions */
static char OKrestore[] = "2000 OK restore\n";
static char OKsession[] = "2000 OK session\n";
static char OKstore[] = "2000 OK storage\n";
-static char OKjob[] = "2000 OK Job " HOST_OS "," DISTNAME "," DISTVER;
+static char OKjob[] = "2000 OK Job %s,%s,%s";
static char OKsetdebug[] = "2000 OK setdebug=%d\n";
static char BADjob[] = "2901 Bad Job\n";
static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s JobBytes=%s Errors=%u\n";
P(cjcr->mutex);
cjcr->store_bsock->timed_out = 1;
cjcr->store_bsock->terminated = 1;
-#ifndef HAVE_CYGWIN
+#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL);
#endif
V(cjcr->mutex);
}
set_jcr_job_status(cjcr, JS_Canceled);
free_jcr(cjcr);
- bnet_fsend(dir, "2001 Job %s marked to be canceled.\n", Job);
+ bnet_fsend(dir, _("2001 Job %s marked to be canceled.\n"), Job);
}
} else {
- bnet_fsend(dir, "2902 Error scanning cancel command.\n");
+ bnet_fsend(dir, _("2902 Error scanning cancel command.\n"));
}
bnet_sig(dir, BNET_EOD);
return 1;
static int setdebug_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- int level;
+ int level, trace_flag;
Dmsg1(110, "setdebug_cmd: %s", dir->msg);
- if (sscanf(dir->msg, "setdebug=%d", &level) != 1 || level < 0) {
+ if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
pm_strcpy(&jcr->errmsg, dir->msg);
bnet_fsend(dir, "2991 Bad setdebug command: %s\n", jcr->errmsg);
return 0;
}
debug_level = level;
+ set_trace(trace_flag);
return bnet_fsend(dir, OKsetdebug, level);
}
jcr->sd_auth_key = bstrdup(sd_auth_key);
free_pool_memory(sd_auth_key);
Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
- return bnet_fsend(dir, OKjob);
+ return bnet_fsend(dir, OKjob, HOST_OS, DISTNAME, DISTVER);
}
static int runbefore_cmd(JCR *jcr)
return bnet_fsend(dir, OKRunAfter);
}
-static int run_cmd(JCR *jcr, char *cmd, char *name)
+static int run_cmd(JCR *jcr, char *cmd, const char *name)
{
POOLMEM *ecmd = get_pool_memory(PM_FNAME);
int status;
switch (*p) {
case '|':
+ p++; /* skip over | */
fn = get_pool_memory(PM_FNAME);
fn = edit_job_codes(jcr, fn, p, "");
bpipe = open_bpipe(fn, 0, "r");
static int level_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- POOLMEM *level;
+ POOLMEM *level, *buf = NULL;
struct tm tm;
time_t mtime;
int mtime_only;
level = get_memory(dir->msglen+1);
Dmsg1(110, "level_cmd: %s", dir->msg);
if (sscanf(dir->msg, "level = %s ", level) != 1) {
- pm_strcpy(&jcr->errmsg, dir->msg);
- Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
- free_memory(level);
- return 0;
+ goto bail_out;
}
/* Base backup requested? */
if (strcmp(level, "base") == 0) {
/*
* Backup requested since <date> <time>
* This form is also used for incremental and differential
+ * This code is deprecated. See since_utime for new code.
*/
} else if (strcmp(level, "since") == 0) {
jcr->JobLevel = L_SINCE;
if (sscanf(dir->msg, "level = since %d-%d-%d %d:%d:%d mtime_only=%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &mtime_only) != 7) {
- pm_strcpy(&jcr->errmsg, dir->msg);
- Jmsg1(jcr, M_FATAL, 0, _("Bad scan of date/time: %s\n"), jcr->errmsg);
- free_memory(level);
- return 0;
+ goto bail_out;
}
tm.tm_year -= 1900;
tm.tm_mon -= 1;
Dmsg2(100, "Got since time: %s mtime_only=%d\n", ctime(&mtime), mtime_only);
jcr->incremental = 1; /* set incremental or decremental backup */
jcr->mtime = mtime; /* set since time */
- jcr->mtime_only = mtime_only; /* and what to compare */
+ /*
+ * We get his UTC since time, then sync the clocks and correct it
+ * to agree with our clock.
+ */
+ } else if (strcmp(level, "since_utime") == 0) {
+ buf = get_memory(dir->msglen+1);
+ utime_t since_time, adj;
+ btime_t his_time, bt_start, rt=0, bt_adj=0;
+ jcr->JobLevel = L_SINCE;
+ if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
+ buf, &mtime_only) != 2) {
+ goto bail_out;
+ }
+ since_time = str_to_uint64(buf); /* this is the since time */
+ char ed1[50], ed2[50];
+ /*
+ * Sync clocks by polling him for the time. We take
+ * 10 samples of his time throwing out the first two.
+ */
+ for (int i=0; i<10; i++) {
+ bt_start = get_current_btime();
+ bnet_sig(dir, BNET_BTIME); /* poll for time */
+ if (bnet_recv(dir) <= 0) { /* get response */
+ goto bail_out;
+ }
+ if (sscanf(dir->msg, "btime %s", buf) != 1) {
+ goto bail_out;
+ }
+ if (i < 2) { /* toss first two results */
+ continue;
+ }
+ his_time = str_to_uint64(buf);
+ rt = get_current_btime() - bt_start; /* compute round trip time */
+ bt_adj -= his_time - bt_start - rt/2;
+ Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
+ }
+
+ bt_adj = bt_adj / 8; /* compute average time */
+ Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
+ adj = btime_to_utime(bt_adj);
+ since_time += adj; /* adjust for clock difference */
+ if (adj != 0) {
+ Jmsg(jcr, M_INFO, 0, _("Since time adjusted by %d seconds.\n"), adj);
+ }
+ bnet_sig(dir, BNET_EOD);
+
+ Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
+ jcr->incremental = 1; /* set incremental or decremental backup */
+ jcr->mtime = since_time; /* set since time */
} else {
Jmsg1(jcr, M_FATAL, 0, "Unknown backup level: %s\n", level);
free_memory(level);
return 0;
}
free_memory(level);
+ if (buf) {
+ free_memory(buf);
+ }
return bnet_fsend(dir, OKlevel);
+
+bail_out:
+ pm_strcpy(&jcr->errmsg, dir->msg);
+ Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
+ free_memory(level);
+ if (buf) {
+ free_memory(buf);
+ }
+ return 0;
}
/*
bail_out:
+ if (jcr->Errors) {
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
/* Send termination status back to Dir */
bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
edit_uint64(jcr->ReadBytes, ed1),
* Returns: 0 on failure
* 1 on success
*/
-int response(JCR *jcr, BSOCK *sd, char *resp, char *cmd)
+int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
{
if (sd->errors) {
return 0;