]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/backup.c
Merge branch 'master' into basejobv3
[bacula/bacula] / bacula / src / dird / backup.c
index 80f11ab10883f47169014ee13992a8f5df822ba5..dd7d1fc59d7e2e7632332a2741f22bceac4e2854 100644 (file)
@@ -103,8 +103,40 @@ bool do_backup_init(JCR *jcr)
    return true;
 }
 
+/* Take all base jobs from job resource and find the
+ * last L_BASE jobid.
+ */
+static bool get_base_jobids(JCR *jcr, POOLMEM *jobids)
+{
+   JOB_DBR jr;
+   JOB *job;
+   JobId_t id;
+   char str_jobid[50];
+
+   if (!jcr->job->base) {
+      return false;             /* no base job, stop accurate */
+   }
+
+   memset(&jr, 0, sizeof(JOB_DBR));
+   jr.StartTime = jcr->jr.StartTime;
+
+   foreach_alist(job, jcr->job->base) {
+      bstrncpy(jr.Name, job->name(), sizeof(jr.Name));
+      db_get_base_jobid(jcr, jcr->db, &jr, &id);
+
+      if (id) {
+         if (jobids[0]) {
+            pm_strcat(jobids, ",");
+         }
+         pm_strcat(jobids, edit_uint64(id, str_jobid));
+      }
+   }
+
+   return *jobids != '\0';
+}
+
 /*
- * Foreach files in currrent list, send "/path/fname\0LStat" to FD
+ * Foreach files in currrent list, send "/path/fname\0LStat\0MD5" to FD
  */
 static int accurate_list_handler(void *ctx, int num_fields, char **row)
 {
@@ -114,8 +146,17 @@ static int accurate_list_handler(void *ctx, int num_fields, char **row)
       return 1;
    }
    
-   if (row[2] > 0) {            /* discard when file_index == 0 */
-      jcr->file_bsock->fsend("%s%s%c%s", row[0], row[1], 0, row[4]); 
+   if (row[2] == 0) {           /* discard when file_index == 0 */
+      return 0;
+   }
+
+   /* sending with checksum */
+   if (num_fields == 6 && row[5][0] && row[5][1]) { /* skip checksum = '0' */
+      jcr->file_bsock->fsend("%s%s%c%s%c%s", 
+                             row[0], row[1], 0, row[4], 0, row[5]); 
+   } else {
+      jcr->file_bsock->fsend("%s%s%c%s", 
+                             row[0], row[1], 0, row[4]); 
    }
    return 0;
 }
@@ -123,29 +164,50 @@ static int accurate_list_handler(void *ctx, int num_fields, char **row)
 /*
  * Send current file list to FD
  *    DIR -> FD : accurate files=xxxx
- *    DIR -> FD : /path/to/file\0Lstat
- *    DIR -> FD : /path/to/dir/\0Lstat
+ *    DIR -> FD : /path/to/file\0Lstat\0MD5
+ *    DIR -> FD : /path/to/dir/\0Lstat\0MD5
  *    ...
  *    DIR -> FD : EOD
  */
 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) || jcr->get_JobLevel()==L_FULL) {
+   if (!jcr->accurate || job_canceled(jcr)) {
+      return true;
+   }
+   /* In base level, no previous job is used */
+   if (jcr->get_JobLevel() == L_BASE) {
       return true;
    }
-   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
 
-   if (jobids.count == 0) {
-      Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
-      return false;
+   if (jcr->get_JobLevel() == L_FULL) {
+      /* On Full mode, if no previous base job, no accurate things */
+      if (!get_base_jobids(jcr, jobids)) {
+         goto bail_out;
+      }
+      jcr->HasBase = true;
+      Jmsg(jcr, M_INFO, 0, _("Using BaseJobId(s): %s\n"), jobids);
+
+   } 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 == 0) {
+         ret=false;
+         Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
+         goto bail_out;
+      }
    }
+
    if (jcr->JobId) {            /* display the message only for real jobs */
       Jmsg(jcr, M_INFO, 0, _("Sending Accurate information.\n"));
    }
+
    /* to be able to allocate the right size for htable */
    Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)", jobids.list);
    db_sql_query(jcr->db, buf.c_str(), db_list_handler, &nb);
@@ -156,14 +218,24 @@ bool send_accurate_current_files(JCR *jcr)
       Jmsg0(jcr, M_FATAL, 0, "Can't get batch sql connexion");
       return false;
    }
+   
+   if (jcr->HasBase) {
+      jcr->nb_base_files = str_to_int64(nb);
+      db_create_base_file_list(jcr, jcr->db, jobids);
+      db_get_base_file_list(jcr, jcr->db, 
+                            accurate_list_handler, (void *)jcr);
 
-   db_get_file_list(jcr, jcr->db_batch, jobids.list, accurate_list_handler, (void *)jcr);
+   } else {
+      db_get_file_list(jcr, jcr->db_batch, jobids, 
+                       accurate_list_handler, (void *)jcr);
+   } 
 
    /* TODO: close the batch connexion ? (can be used very soon) */
 
    jcr->file_bsock->signal(BNET_EOD);
 
-   return true;
+bail_out:
+   return ret;
 }
 
 /*
@@ -315,6 +387,13 @@ bool do_backup(JCR *jcr)
    /* Pickup Job termination data */
    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 (stat == JS_Terminated) {
       backup_cleanup(jcr, stat);
       return true;
@@ -542,6 +621,11 @@ void backup_cleanup(JCR *jcr, int TermCode)
    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
 
+   if (jcr->HasBase) {
+      Dmsg3(0, "Base files/Used files %lld/%lld=%.2f%%\n", jcr->nb_base_files, 
+            jcr->nb_base_files_used, 
+            jcr->nb_base_files_used*100.0/jcr->nb_base_files);
+   }
 // bmicrosleep(15, 0);                /* for debugging SIGHUP */
 
    Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"