]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/restore.c
Massive SD calling sequence reorganization
[bacula/bacula] / bacula / src / dird / restore.c
index 513218ae252bc2ece23546a13636da6c01e99ee1..fa541d84cdade1f613a0a021e9372c517155820b 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *
  *   Bacula Director -- restore.c -- responsible for restoring files
  *
  *     Kern Sibbald, November MM
@@ -20,7 +19,7 @@
  */
 
 /*
-   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
@@ -43,7 +42,7 @@
 #include "dird.h"
 
 /* Commands sent to File daemon */
-static char restorecmd[]   = "restore replace=%c where=%s\n";
+static char restorecmd[]   = "restore replace=%c prelinks=%d where=%s\n";
 static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
 static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";  
 
@@ -51,12 +50,9 @@ static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";
 static char OKrestore[]   = "2000 OK restore\n";
 static char OKstore[]     = "2000 OK storage\n";
 static char OKsession[]   = "2000 OK session\n";
-static char OKbootstrap[] = "2000 OK bootstrap\n";
-static char EndRestore[]  = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%" lld "\n";
 
 /* Forward referenced functions */
 static void restore_cleanup(JCR *jcr, int status);
-static int send_bootstrap_file(JCR *jcr);
 
 /* External functions */
 
@@ -70,8 +66,6 @@ int do_restore(JCR *jcr)
 {
    BSOCK   *fd;
    JOB_DBR rjr;                      /* restore job record */
-   int ok = FALSE;
-
 
    if (!get_or_create_client_record(jcr)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
@@ -79,8 +73,7 @@ int do_restore(JCR *jcr)
    }
 
    memset(&rjr, 0, sizeof(rjr));
-   jcr->jr.Level = 'F';            /* Full restore */
-   jcr->jr.StartTime = jcr->start_time;
+   jcr->jr.JobLevel = L_FULL;        /* Full restore */
    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
       Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
       restore_cleanup(jcr, JS_ErrorTerminated);
@@ -94,6 +87,7 @@ int do_restore(JCR *jcr)
    /* 
     * The following code is kept temporarily for compatibility.
     * It is the predecessor to the Bootstrap file.
+    *  DEPRECATED
     */
    if (!jcr->RestoreBootstrap) {
       /*
@@ -117,7 +111,7 @@ int do_restore(JCR *jcr)
       jcr->VolumeName[0] = 0;
       if (!db_get_job_volume_names(jcr, jcr->db, rjr.JobId, &jcr->VolumeName) ||
           jcr->VolumeName[0] == 0) {
-         Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"), 
+         Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume names for restore Job %d. %s"), 
            rjr.JobId, db_strerror(jcr->db));
         restore_cleanup(jcr, JS_ErrorTerminated);
         return 0;
@@ -136,7 +130,7 @@ int do_restore(JCR *jcr)
     *
     */
    Dmsg0(10, "Open connection with storage daemon\n");
-   set_jcr_job_status(jcr, JS_Blocked);
+   set_jcr_job_status(jcr, JS_WaitSD);
    /*
     * Start conversation with Storage daemon  
     */
@@ -163,6 +157,7 @@ int do_restore(JCR *jcr)
    /* 
     * Start conversation with File daemon  
     */
+   set_jcr_job_status(jcr, JS_WaitFD);
    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
@@ -186,17 +181,15 @@ int do_restore(JCR *jcr)
     *  then wait for File daemon to make connection
     *  with Storage daemon.
     */
-   set_jcr_job_status(jcr, JS_Blocked);
    if (jcr->store->SDDport == 0) {
       jcr->store->SDDport = jcr->store->SDport;
    }
    bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
    Dmsg1(6, "dird>filed: %s\n", fd->msg);
-   if (!response(fd, OKstore, "Storage", 1)) {
+   if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
-   set_jcr_job_status(jcr, JS_Running);
 
    /* 
     * Send the bootstrap file -- what Volumes/files to restore
@@ -219,15 +212,21 @@ int do_restore(JCR *jcr)
                rjr.VolSessionId, rjr.VolSessionTime, 
                rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
                rjr.EndBlock);
-      if (!response(fd, OKsession, "Session", 1)) {
+      if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
         restore_cleanup(jcr, JS_ErrorTerminated);
         return 0;
       }
    }
 
+   if (!send_run_before_and_after_commands(jcr)) {
+      restore_cleanup(jcr, JS_ErrorTerminated);
+      return 0;
+   }
+
    /* Send restore command */
    char replace, *where;
-
+   char empty = '\0';
+   
    if (jcr->replace != 0) {
       replace = jcr->replace;
    } else if (jcr->job->replace != 0) {
@@ -235,40 +234,26 @@ int do_restore(JCR *jcr)
    } else {
       replace = REPLACE_ALWAYS;       /* always replace */
    }
-   if (jcr->RestoreWhere) {
-      where = jcr->RestoreWhere;      /* override */
+   if (jcr->where) {
+      where = jcr->where;            /* override */
    } else if (jcr->job->RestoreWhere) {
       where = jcr->job->RestoreWhere; /* no override take from job */
    } else {
-      where = "";                     /* None */
+      where = ∅                /* None */
    }
+   jcr->prefix_links = jcr->job->PrefixLinks;
    bash_spaces(where);
-   bnet_fsend(fd, restorecmd, replace, where);
+   bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
    unbash_spaces(where);
 
-   if (!response(fd, OKrestore, "Restore", 1)) {
+   if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
 
    /* Wait for Job Termination */
-   Dmsg0(20, "wait for job termination\n");
-   while (bget_msg(fd, 0) >= 0) {
-      Dmsg1(100, "dird<filed: %s\n", fd->msg);
-      if (sscanf(fd->msg, EndRestore, &jcr->FDJobStatus, &jcr->JobFiles,
-         &jcr->JobBytes) == 3) {
-        ok = TRUE;
-      }
-   }
-
-   if (is_bnet_error(fd)) {
-      Jmsg(jcr, M_FATAL, 0, _("Network error during RESTORE command. ERR=%s\n"),
-         bnet_strerror(fd));
-   }
-   bnet_sig(fd, BNET_TERMINATE);   /* tell Client we are terminating */
-
-
-   restore_cleanup(jcr, ok?jcr->FDJobStatus:JS_ErrorTerminated);
+   int stat = wait_for_job_termination(jcr);
+   restore_cleanup(jcr, stat);
 
    return 1;
 }
@@ -280,51 +265,65 @@ int do_restore(JCR *jcr)
 static void restore_cleanup(JCR *jcr, int TermCode)
 {
    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
-   char ec1[30], ec2[30];
-   char term_code[100], fd_term_msg[100];
-   char *term_msg;
+   char ec1[30], ec2[30], ec3[30];
+   char term_code[100], fd_term_msg[100], sd_term_msg[100];
+   const char *term_msg;
    int msg_type;
    double kbps;
 
    Dmsg0(20, "In restore_cleanup\n");
+   dequeue_messages(jcr);            /* display any queued messages */
    set_jcr_job_status(jcr, TermCode);
 
    update_job_end_record(jcr);
 
    msg_type = M_INFO;                /* by default INFO message */
    switch (TermCode) {
-      case JS_Terminated:
+   case JS_Terminated:
+      if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
+         term_msg = _("Restore OK -- warning file count mismatch");
+      } else {
          term_msg = _("Restore OK");
-        break;
-      case JS_FatalError:
-      case JS_ErrorTerminated:
-         term_msg = _("*** Restore Error ***"); 
-        msg_type = M_ERROR;          /* Generate error message */
-        if (jcr->store_bsock) {
-           bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+      }
+      break;
+   case JS_FatalError:
+   case JS_ErrorTerminated:
+      term_msg = _("*** Restore Error ***"); 
+      msg_type = M_ERROR;         /* Generate error message */
+      if (jcr->store_bsock) {
+        bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+        if (jcr->SD_msg_chan) {
            pthread_cancel(jcr->SD_msg_chan);
         }
-        break;
-      case JS_Canceled:
-         term_msg = _("Restore Canceled");
-        if (jcr->store_bsock) {
-           bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+      }
+      break;
+   case JS_Canceled:
+      term_msg = _("Restore Canceled");
+      if (jcr->store_bsock) {
+        bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+        if (jcr->SD_msg_chan) {
            pthread_cancel(jcr->SD_msg_chan);
         }
-        break;
-      default:
-        term_msg = term_code;
-         sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
-        break;
+      }
+      break;
+   default:
+      term_msg = term_code;
+      sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
+      break;
    }
    bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime);
    bstrftime(edt, sizeof(edt), jcr->jr.EndTime);
-   kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
+   if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
+      kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
+   } else {
+      kbps = 0;
+   }
    if (kbps < 0.05) {
       kbps = 0;
    }
 
    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
+   jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
 
    Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\
 JobId:                  %d\n\
@@ -332,10 +331,13 @@ Job:                    %s\n\
 Client:                 %s\n\
 Start time:             %s\n\
 End time:               %s\n\
+Files Expected:         %s\n\
 Files Restored:         %s\n\
 Bytes Restored:         %s\n\
 Rate:                   %.1f KB/s\n\
+FD Errors:              %d\n\
 FD termination status:  %s\n\
+SD termination status:  %s\n\
 Termination:            %s\n\n"),
        edt,
        jcr->jr.JobId,
@@ -343,45 +345,14 @@ Termination:            %s\n\n"),
        jcr->client->hdr.name,
        sdt,
        edt,
-       edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec1),
-       edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
+       edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
+       edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
+       edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
        (float)kbps,
+       jcr->Errors,
        fd_term_msg,
+       sd_term_msg,
        term_msg);
 
    Dmsg0(20, "Leaving restore_cleanup\n");
 }
-
-static int send_bootstrap_file(JCR *jcr)
-{
-   FILE *bs;
-   char buf[1000];
-   BSOCK *fd = jcr->file_bsock;
-   char *bootstrap = "bootstrap\n";
-
-   Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
-   if (!jcr->RestoreBootstrap) {
-      return 1;
-   }
-   bs = fopen(jcr->RestoreBootstrap, "r");
-   if (!bs) {
-      Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), 
-        jcr->RestoreBootstrap, strerror(errno));
-      set_jcr_job_status(jcr, JS_ErrorTerminated);
-      return 0;
-   }
-   strcpy(fd->msg, bootstrap); 
-   fd->msglen = strlen(fd->msg);
-   bnet_send(fd);
-   while (fgets(buf, sizeof(buf), bs)) {
-      fd->msglen = Mmsg(&fd->msg, "%s", buf);
-      bnet_send(fd);      
-   }
-   bnet_sig(fd, BNET_EOD);
-   fclose(bs);
-   if (!response(fd, OKbootstrap, "Bootstrap", 1)) {
-      set_jcr_job_status(jcr, JS_ErrorTerminated);
-      return 0;
-   }
-   return 1;
-}