]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/backup.c
Fix race condition between setip and the access to CLIENT::address()
[bacula/bacula] / bacula / src / dird / backup.c
index 116845789ddc729d947fea5ea33b24ccc9059a7f..47888eecc37f2939a2bb48d8bae532b5f13fc74a 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula(R) - The Network Backup Solution
 
-   Copyright (C) 2000-2015 Kern Sibbald
+   Copyright (C) 2000-2017 Kern Sibbald
 
    The original author of Bacula is Kern Sibbald, with contributions
    from many others, a complete list can be found in the file AUTHORS.
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   This notice must be preserved when any source code is 
+   This notice must be preserved when any source code is
    conveyed and/or propagated.
 
    Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
- *
  *   Bacula Director -- backup.c -- responsible for doing backup jobs
  *
  *     Kern Sibbald, March MM
@@ -28,7 +27,6 @@
  *     Open connection with File daemon and pass him commands
  *       to do the backup.
  *     When the File daemon finishes the job, update the DB.
- *
  */
 
 #include "bacula.h"
@@ -42,6 +40,12 @@ static char storaddr[]  = "storage address=%s port=%d ssl=%d\n";
 /* Responses received from File daemon */
 static char OKbackup[]   = "2000 OK backup\n";
 static char OKstore[]    = "2000 OK storage\n";
+/* After 17 Aug 2013 */
+static char newEndJob[]  = "2800 End Job TermCode=%d JobFiles=%u "
+                           "ReadBytes=%llu JobBytes=%llu Errors=%u "
+                           "VSS=%d Encrypt=%d "
+                           "CommBytes=%lld CompressCommBytes=%lld\n";
+/* Pre 17 Aug 2013 */
 static char EndJob[]     = "2800 End Job TermCode=%d JobFiles=%u "
                            "ReadBytes=%llu JobBytes=%llu Errors=%u "
                            "VSS=%d Encrypt=%d\n";
@@ -258,6 +262,11 @@ bool send_accurate_current_files(JCR *jcr)
       } else if (!jcr->rerunning) {
          return true;
       }
+
+   } else if (jcr->is_JobLevel(L_VERIFY_DATA)) {
+      char ed1[50];
+      jobids.add(edit_uint64(jcr->previous_jr.JobId, ed1));
+
    } else {
       /* For Incr/Diff level, we search for older jobs */
       db_get_accurate_jobids(jcr, jcr->db, &jcr->jr, &jobids);
@@ -347,6 +356,7 @@ bool send_client_addr_to_sd(JCR *jcr)
 {
    int tls_need = BNET_TLS_NONE;
    BSOCK *sd = jcr->store_bsock;
+   POOL_MEM buf;
 
    /* TLS Requirement for the client */
    if (jcr->client->tls_enable) {
@@ -359,7 +369,7 @@ bool send_client_addr_to_sd(JCR *jcr)
    /*
     * Send Client address to the SD
     */
-   sd->fsend(clientaddr, jcr->client->address, jcr->client->FDport, tls_need);
+   sd->fsend(clientaddr, jcr->client->address(buf.addr()), jcr->client->FDport, tls_need);
    if (!response(jcr, sd, OKclient, "Client", DISPLAY_ERROR)) {
       return false;
    }
@@ -659,6 +669,8 @@ int wait_for_job_termination(JCR *jcr, int timeout)
    uint32_t JobWarnings = 0;
    uint64_t ReadBytes = 0;
    uint64_t JobBytes = 0;
+   uint64_t CommBytes = 0;
+   uint64_t CommCompressedBytes = 0;
    int VSS = 0;                 /* or Snapshot on Unix */
    int Encrypt = 0;
    btimer_t *tid=NULL;
@@ -669,10 +681,13 @@ int wait_for_job_termination(JCR *jcr, int timeout)
       }
       /* Wait for Client to terminate */
       while ((n = bget_dirmsg(fd)) >= 0) {
-         if (!fd_ok && 
-              (sscanf(fd->msg, EndJob, &jcr->FDJobStatus, &JobFiles,
+         if (!fd_ok &&
+             (sscanf(fd->msg, newEndJob, &jcr->FDJobStatus, &JobFiles,
+                     &ReadBytes, &JobBytes, &JobErrors, &VSS, &Encrypt,
+                     &CommBytes, &CommCompressedBytes) == 9 ||
+              sscanf(fd->msg, EndJob, &jcr->FDJobStatus, &JobFiles,
                      &ReadBytes, &JobBytes, &JobErrors, &VSS, &Encrypt) == 7 ||
-               sscanf(fd->msg, OldEndJob, &jcr->FDJobStatus, &JobFiles,
+              sscanf(fd->msg, OldEndJob, &jcr->FDJobStatus, &JobFiles,
                      &ReadBytes, &JobBytes, &JobErrors) == 5)) {
             fd_ok = true;
             jcr->setJobStatus(jcr->FDJobStatus);
@@ -722,6 +737,8 @@ int wait_for_job_termination(JCR *jcr, int timeout)
       jcr->ReadBytes = ReadBytes;
       jcr->JobBytes = JobBytes;
       jcr->JobWarnings = JobWarnings;
+      jcr->CommBytes = CommBytes;
+      jcr->CommCompressedBytes = CommCompressedBytes;
       jcr->Snapshot = VSS;
       jcr->Encrypt = Encrypt;
    } else if (jcr->getJobStatus() != JS_Canceled) {
@@ -753,9 +770,9 @@ void backup_cleanup(JCR *jcr, int TermCode)
    char sdt[50], edt[50], schedt[50];
    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30];
    char ec6[30], ec7[30], ec8[30], ec9[30], ec10[30], elapsed[50];
-   char data_compress[200];
-   char term_code[100], fd_term_msg[100], sd_term_msg[100];
-   const char *term_msg;
+   char data_compress[200], comm_compress[200];
+   char fd_term_msg[100], sd_term_msg[100];
+   POOL_MEM term_msg;
    int msg_type = M_INFO;
    MEDIA_DBR mr;
    CLIENT_DBR cr;
@@ -764,6 +781,8 @@ void backup_cleanup(JCR *jcr, int TermCode)
    POOL_MEM base_info;
    POOL_MEM vol_info;
 
+   remove_dummy_jobmedia_records(jcr);
+
    if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
       vbackup_cleanup(jcr, TermCode);
       return;
@@ -772,6 +791,18 @@ void backup_cleanup(JCR *jcr, int TermCode)
    Dmsg2(100, "Enter backup_cleanup %d %c\n", TermCode, TermCode);
    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;
+   }
+#endif
+
    update_job_end(jcr, TermCode);
 
    if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
@@ -798,20 +829,21 @@ void backup_cleanup(JCR *jcr, int TermCode)
    switch (jcr->JobStatus) {
       case JS_Terminated:
          if (jcr->JobErrors || jcr->SDErrors) {
-            term_msg = _("Backup OK -- with warnings");
+            Mmsg(term_msg, _("Backup OK -- %s"), jcr->StatusErrMsg[0] ? jcr->StatusErrMsg : _("with warnings"));
+
          } else {
-            term_msg = _("Backup OK");
+            Mmsg(term_msg, _("Backup OK"));
          }
          break;
       case JS_Incomplete:
-         term_msg = _("Backup failed -- incomplete");
+         Mmsg(term_msg, _("Backup failed -- incomplete"));
          break;
       case JS_Warnings:
-         term_msg = _("Backup OK -- with warnings");
+         Mmsg(term_msg, _("Backup OK -- %s"), jcr->StatusErrMsg[0] ? jcr->StatusErrMsg : _("with warnings"));
          break;
       case JS_FatalError:
       case JS_ErrorTerminated:
-         term_msg = _("*** Backup Error ***");
+         Mmsg(term_msg, _("*** Backup Error ***"));
          msg_type = M_ERROR;          /* Generate error message */
          if (jcr->store_bsock) {
             jcr->store_bsock->signal(BNET_TERMINATE);
@@ -821,7 +853,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
          }
          break;
       case JS_Canceled:
-         term_msg = _("Backup Canceled");
+         Mmsg(term_msg, _("Backup Canceled"));
          if (jcr->store_bsock) {
             jcr->store_bsock->signal(BNET_TERMINATE);
             if (jcr->SD_msg_chan_started) {
@@ -830,8 +862,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
          }
          break;
       default:
-         term_msg = term_code;
-         sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus);
+         Mmsg(term_msg, _("Inappropriate term code: %c\n"), jcr->JobStatus);
          break;
    }
    bstrftimes(schedt, sizeof(schedt), jcr->jr.SchedTime);
@@ -839,10 +870,9 @@ void backup_cleanup(JCR *jcr, int TermCode)
    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
    RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
    if (RunTime <= 0) {
-      kbps = 0;
-   } else {
-      kbps = ((double)jcr->jr.JobBytes) / (1000.0 * (double)RunTime);
+      RunTime = 1;
    }
+   kbps = ((double)jcr->jr.JobBytes) / (1000.0 * (double)RunTime);
    if (!db_get_job_volume_names(jcr, jcr->db, jcr->jr.JobId, &jcr->VolumeName)) {
       /*
        * Note, if the job has erred, most likely it did not write any
@@ -872,6 +902,20 @@ void backup_cleanup(JCR *jcr, int TermCode)
             compression, ratio);
       }
    }
+   if (jcr->CommBytes == 0 || jcr->CommCompressedBytes == 0) {
+      bstrncpy(comm_compress, "None", sizeof(comm_compress));
+   } else {
+      compression = (double)100 - 100.0 * ((double)jcr->CommCompressedBytes / (double)jcr->CommBytes);
+      if (compression < 0.5) {
+         bstrncpy(comm_compress, "None", sizeof(comm_compress));
+      } else {
+         ratio = (double)jcr->CommBytes / (double)jcr->CommCompressedBytes;
+         bsnprintf(comm_compress, sizeof(comm_compress), "%.1f%% %.1f:1",
+            compression, ratio);
+      }
+      Dmsg2(200, "=== CommCompressed=%lld CommBytes=%lld\n",
+         jcr->CommCompressedBytes, jcr->CommBytes);
+   }
    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
 
@@ -917,6 +961,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
 "  SD Bytes Written:       %s (%sB)\n"
 "  Rate:                   %.1f KB/s\n"
 "  Software Compression:   %s\n"
+"  Comm Line Compression:  %s\n"
 "%s"                                         /* Basefile info */
 "  Snapshot/VSS:           %s\n"
 "  Encryption:             %s\n"
@@ -953,6 +998,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
         edit_uint64_with_suffix(jcr->SDJobBytes, ec6),
         kbps,
         data_compress,
+        comm_compress,
         base_info.c_str(),
         jcr->Snapshot?_("yes"):_("no"),
         jcr->Encrypt?_("yes"):_("no"),
@@ -965,7 +1011,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
         jcr->SDErrors,
         fd_term_msg,
         sd_term_msg,
-        term_msg);
+        term_msg.c_str());
 
    Dmsg0(100, "Leave backup_cleanup()\n");
 }
@@ -979,7 +1025,8 @@ void update_bootstrap_file(JCR *jcr)
       BPIPE *bpipe = NULL;
       int got_pipe = 0;
       POOLMEM *fname = get_pool_memory(PM_FNAME);
-      fname = edit_job_codes(jcr, fname, jcr->job->WriteBootstrap, "");
+      fname = edit_job_codes(jcr, fname, jcr->job->WriteBootstrap, "",
+                             job_code_callback_director);
 
       VOL_PARAMS *VolParams = NULL;
       int VolCount;
@@ -991,7 +1038,7 @@ void update_bootstrap_file(JCR *jcr)
          fd = bpipe ? bpipe->wfd : NULL;
       } else {
          /* ***FIXME*** handle BASE */
-         fd = fopen(fname, jcr->is_JobLevel(L_FULL)?"w+b":"a+b");
+         fd = bfopen(fname, jcr->is_JobLevel(L_FULL)?"w+b":"a+b");
       }
       if (fd) {
          VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId,