/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
static char filesetcmd[] = "fileset%s\n"; /* set full fileset */
static char jobcmd[] = "JobId=%s Job=%s SDid=%u SDtime=%u Authorization=%s\n";
/* Note, mtime_only is not used here -- implemented as file option */
-static char levelcmd[] = "level = %s%s mtime_only=%d\n";
+static char levelcmd[] = "level = %s%s%s mtime_only=%d\n";
static char runscript[] = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n";
static char runbeforenow[]= "RunBeforeNow\n";
void get_level_since_time(JCR *jcr, char *since, int since_len)
{
int JobLevel;
+ bool have_full;
+ bool do_full = false;
+ bool do_diff = false;
+ time_t now;
+ utime_t full_time;
+ utime_t diff_time;
since[0] = 0;
- if (jcr->cloned) {
- if (jcr->stime && jcr->stime[0]) {
- bstrncpy(since, _(", since="), since_len);
- bstrncat(since, jcr->stime, since_len);
- }
+ /* If job cloned and a since time already given, use it */
+ if (jcr->cloned && jcr->stime && jcr->stime[0]) {
+ bstrncpy(since, _(", since="), since_len);
+ bstrncat(since, jcr->stime, since_len);
return;
}
+ /* Make sure stime buffer is allocated */
if (!jcr->stime) {
jcr->stime = get_pool_memory(PM_MESSAGE);
}
jcr->stime[0] = 0;
- /* Lookup the last FULL backup job to get the time/date for a
+ /*
+ * Lookup the last FULL backup job to get the time/date for a
* differential or incremental save.
*/
switch (jcr->JobLevel) {
case L_DIFFERENTIAL:
case L_INCREMENTAL:
- /* Look up start time of last job */
- jcr->jr.JobId = 0; /* flag for db_find_job_start time */
- if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
- /* No job found, so upgrade this one to Full */
+ POOLMEM *stime = get_pool_memory(PM_MESSAGE);
+ /* Look up start time of last Full job */
+ now = time(NULL);
+ jcr->jr.JobId = 0; /* flag to return since time */
+ have_full = db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime);
+ /* If there was a successful job, make sure it is recent enough */
+ if (jcr->JobLevel == L_INCREMENTAL && have_full && jcr->job->MaxDiffInterval > 0) {
+ /* Lookup last diff job */
+ if (db_find_last_job_start_time(jcr, jcr->db, &jcr->jr, &stime, L_DIFFERENTIAL)) {
+ diff_time = str_to_utime(stime);
+ do_diff = ((now - diff_time) <= jcr->job->MaxDiffInterval);
+ }
+ }
+ if (have_full && jcr->job->MaxFullInterval > 0 &&
+ db_find_last_job_start_time(jcr, jcr->db, &jcr->jr, &stime, L_FULL)) {
+ full_time = str_to_utime(stime);
+ do_full = ((now - full_time) <= jcr->job->MaxFullInterval);
+ }
+ free_pool_memory(stime);
+
+ if (!have_full || do_full) {
+ /* No recent Full job found, so upgrade this one to Full */
Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found in catalog. Doing FULL backup.\n"));
bsnprintf(since, since_len, _(" (upgraded from %s)"),
level_to_str(jcr->JobLevel));
jcr->JobLevel = jcr->jr.JobLevel = L_FULL;
+ } else if (do_diff) {
+ /* No recent diff job found, so upgrade this one to Full */
+ Jmsg(jcr, M_INFO, 0, _("No prior or suitable Differential backup found in catalog. Doing Differential backup.\n"));
+ bsnprintf(since, since_len, _(" (upgraded from %s)"),
+ level_to_str(jcr->JobLevel));
+ jcr->JobLevel = jcr->jr.JobLevel = L_DIFFERENTIAL;
} else {
if (jcr->job->rerun_failed_levels) {
if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, jcr->stime, JobLevel)) {
char ed1[50];
stime = str_to_utime(jcr->stime);
- fd->fsend(levelcmd, NT_("since_utime "), edit_uint64(stime, ed1), 0);
+ fd->fsend(levelcmd, "", NT_("since_utime "), edit_uint64(stime, ed1), 0);
while (bget_dirmsg(fd) >= 0) { /* allow him to poll us to sync clocks */
Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg);
}
}
-
/*
* Send level command to FD.
* Used for backup jobs and estimate command.
bool send_level_command(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
+ const char *accurate=jcr->job->accurate?"accurate_":"";
+ const char *not_accurate="";
/*
* Send Level command to File daemon
*/
switch (jcr->JobLevel) {
case L_BASE:
- fd->fsend(levelcmd, "base", " ", 0);
+ fd->fsend(levelcmd, not_accurate, "base", " ", 0);
break;
/* L_NONE is the console, sending something off to the FD */
case L_NONE:
case L_FULL:
- fd->fsend(levelcmd, "full", " ", 0);
+ fd->fsend(levelcmd, not_accurate, "full", " ", 0);
break;
case L_DIFFERENTIAL:
- fd->fsend(levelcmd, "differential", " ", 0);
+ fd->fsend(levelcmd, accurate, "differential", " ", 0);
send_since_time(jcr);
break;
case L_INCREMENTAL:
- fd->fsend(levelcmd, "incremental", " ", 0);
+ fd->fsend(levelcmd, accurate, "incremental", " ", 0);
send_since_time(jcr);
break;
case L_SINCE:
if (fo->plugin) {
fd->fsend("G %s\n", fo->plugin);
}
+ if (fo->ignoredir) {
+ bnet_fsend(fd, "Z %s\n", fo->ignoredir);
+ }
if (fo->reader) {
fd->fsend("D %s\n", fo->reader);
}