/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 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.
* to do the backup.
* When the File daemon finishes the job, update the DB.
*
- * Version $Id$
*/
#include "bacula.h"
#include "ua.h"
/* Commands sent to File daemon */
-static char backupcmd[] = "backup\n";
+static char backupcmd[] = "backup FileIndex=%ld\n";
static char storaddr[] = "storage address=%s port=%d ssl=%d\n";
/* Responses received from File daemon */
bool do_backup_init(JCR *jcr)
{
- if (jcr->getJobLevel() == L_VIRTUAL_FULL) {
+ if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
return do_vbackup_init(jcr);
}
free_rstorage(jcr); /* we don't read so release */
/*
* Foreach files in currrent list, send "/path/fname\0LStat\0MD5\0Delta" to FD
* row[0]=Path, row[1]=Filename, row[2]=FileIndex
- * row[3]=JobId row[4]=LStat row[5]=MarkId row[6]=MD5
+ * row[3]=JobId row[4]=LStat row[5]=DeltaSeq row[6]=MD5
*/
static int accurate_list_handler(void *ctx, int num_fields, char **row)
{
have_basejob_option = in_block = jcr->HasBase;
break;
case 'C': /* Accurate keyword */
- in_block = (jcr->getJobLevel() != L_FULL);
+ in_block = !jcr->is_JobLevel(L_FULL);
break;
case ':': /* End of keyword */
in_block = false;
bool send_accurate_current_files(JCR *jcr)
{
POOL_MEM buf;
- bool ret=true;
db_list_ctx jobids;
db_list_ctx nb;
- if (!jcr->accurate || job_canceled(jcr)) {
+ /* In base level, no previous job is used and no restart incomplete jobs */
+ if (jcr->is_canceled() || jcr->is_JobLevel(L_BASE)) {
return true;
}
- /* In base level, no previous job is used */
- if (jcr->getJobLevel() == L_BASE) {
+ if (!jcr->accurate) {
return true;
}
-
- if (jcr->getJobLevel() == L_FULL) {
+
+ if (jcr->is_JobLevel(L_FULL)) {
/* On Full mode, if no previous base job, no accurate things */
- if (!get_base_jobids(jcr, &jobids)) {
- goto bail_out;
+ if (get_base_jobids(jcr, &jobids)) {
+ jcr->HasBase = true;
+ Jmsg(jcr, M_INFO, 0, _("Using BaseJobId(s): %s\n"), jobids.list);
+ } else {
+ return true;
}
- jcr->HasBase = true;
- Jmsg(jcr, M_INFO, 0, _("Using BaseJobId(s): %s\n"), jobids.list);
-
} else {
/* For Incr/Diff level, we search for older jobs */
db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
/* We are in Incr/Diff, but no Full to build the accurate list... */
if (jobids.count == 0) {
- ret=false;
Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
- goto bail_out;
+ return false; /* fail */
}
}
if (!db_open_batch_connexion(jcr, jcr->db)) {
Jmsg0(jcr, M_FATAL, 0, "Can't get batch sql connexion");
- return false;
+ return false; /* Fail */
}
if (jcr->HasBase) {
accurate_list_handler, (void *)jcr);
}
- /* TODO: close the batch connexion ? (can be used very soon) */
+ /* TODO: close the batch connection ? (can be used very soon) */
jcr->file_bsock->signal(BNET_EOD);
-
-bail_out:
- return ret;
+ return true;
}
/*
BSOCK *fd;
STORE *store;
char ed1[100];
+ db_int64_ctx job;
+ POOL_MEM buf;
- if (jcr->getJobLevel() == L_VIRTUAL_FULL) {
+ if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
return do_vbackup(jcr);
}
* to avoid two threads from using the BSOCK structure at
* the same time.
*/
- if (!bnet_fsend(jcr->store_bsock, "run")) {
+ if (!jcr->store_bsock->fsend("run")) {
return false;
}
jcr->setJobStatus(JS_Running);
fd = jcr->file_bsock;
- if (!send_include_list(jcr)) {
+ if (!send_level_command(jcr)) {
goto bail_out;
}
- if (!send_exclude_list(jcr)) {
+ if (!send_include_list(jcr)) {
goto bail_out;
}
- if (!send_level_command(jcr)) {
+ if (!send_exclude_list(jcr)) {
goto bail_out;
}
- /* TODO: See priority with bandwidth parameter */
- if (jcr->job->max_bandwidth > 0) {
- jcr->max_bandwidth = jcr->job->max_bandwidth;
- } else if (jcr->client->max_bandwidth > 0) {
- jcr->max_bandwidth = jcr->client->max_bandwidth;
- }
-
- if (jcr->max_bandwidth > 0) {
- send_bwlimit(jcr, jcr->Job); /* Old clients don't have this command */
- }
-
/*
* send Storage daemon address to the File daemon
*/
* all files to FD.
*/
if (!send_accurate_current_files(jcr)) {
- goto bail_out;
+ goto bail_out; /* error */
}
/* Send backup command */
- fd->fsend(backupcmd);
+ fd->fsend(backupcmd, jcr->JobFiles);
+ Dmsg1(100, ">filed: %s", fd->msg);
if (!response(jcr, fd, OKbackup, "backup", DISPLAY_ERROR)) {
goto bail_out;
}
stat = wait_for_job_termination(jcr);
db_write_batch_file_records(jcr); /* used by bulk batch file insert */
- if (jcr->HasBase &&
- !db_commit_base_file_attributes_record(jcr, jcr->db))
- {
- Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
+ if (jcr->HasBase && !db_commit_base_file_attributes_record(jcr, jcr->db)) {
+ Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
}
if (stat == JS_Terminated) {
}
if (is_bnet_error(fd)) {
+ int i = 0;
Jmsg(jcr, M_FATAL, 0, _("Network error with FD during %s: ERR=%s\n"),
job_type_to_str(jcr->getJobType()), fd->bstrerror());
+ while (i++ < 10 && jcr->job->RescheduleIncompleteJobs && jcr->is_canceled()) {
+ bmicrosleep(3, 0);
+ }
+
}
fd->signal(BNET_TERMINATE); /* tell Client we are terminating */
}
- /* Force cancel in SD if failing */
- if (job_canceled(jcr) || !fd_ok) {
+ /*
+ * Force cancel in SD if failing, but not for Incomplete jobs
+ * so that we let the SD despool.
+ */
+ Dmsg5(100, "cancel=%d fd_ok=%d FDJS=%d JS=%d SDJS=%d\n", jcr->is_canceled(), fd_ok, jcr->FDJobStatus,
+ jcr->JobStatus, jcr->SDJobStatus);
+ if (jcr->is_canceled() || (!jcr->job->RescheduleIncompleteJobs && !fd_ok)) {
+ Dmsg4(100, "fd_ok=%d FDJS=%d JS=%d SDJS=%d\n", fd_ok, jcr->FDJobStatus,
+ jcr->JobStatus, jcr->SDJobStatus);
cancel_storage_daemon_job(jcr);
}
utime_t RunTime;
POOL_MEM base_info;
- if (jcr->getJobLevel() == L_VIRTUAL_FULL) {
+ if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
vbackup_cleanup(jcr, TermCode);
return;
}
Dmsg2(100, "Enter backup_cleanup %d %c\n", TermCode, TermCode);
- memset(&mr, 0, sizeof(mr));
memset(&cr, 0, sizeof(cr));
#ifdef xxxx
+ /* The current implementation of the JS_Warning status is not
+ * completed. SQL part looks to be ok, but the code is using
+ * JS_Terminated almost everywhere instead of (JS_Terminated || JS_Warning)
+ * as we do with is_canceled()
+ */
if (jcr->getJobStatus() == JS_Terminated &&
(jcr->JobErrors || jcr->SDErrors || jcr->JobWarnings)) {
TermCode = JS_Warnings;
term_msg = _("Backup OK");
}
break;
+ case JS_Incomplete:
+ term_msg = _("Backup failed -- incomplete");
+ break;
case JS_Warnings:
term_msg = _("Backup OK -- with warnings");
break;
fd = bpipe ? bpipe->wfd : NULL;
} else {
/* ***FIXME*** handle BASE */
- fd = fopen(fname, jcr->getJobLevel()==L_FULL?"w+b":"a+b");
+ fd = fopen(fname, jcr->is_JobLevel(L_FULL)?"w+b":"a+b");
}
if (fd) {
VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId,