]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/restore.c
Apply Preben 'Peppe' Guldberg <peppe@wielders.org>
[bacula/bacula] / bacula / src / dird / restore.c
index b40a5dc09c2c39197b03d8763d323683b4d12262..d8a894bf243408234540d56e1cfe9c6b857a0ba1 100644 (file)
@@ -3,8 +3,8 @@
  *
  *     Kern Sibbald, November MM
  *
- *    This routine is run as a separate thread.  
- * 
+ *    This routine is run as a separate thread.
+ *
  * Current implementation is Catalog verification only (i.e. no
  *  verification versus tape).
  *
@@ -19,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
@@ -44,7 +44,7 @@
 /* Commands sent to File daemon */
 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";  
+static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";
 
 /* Responses received from File daemon */
 static char OKrestore[]   = "2000 OK restore\n";
@@ -56,13 +56,13 @@ static void restore_cleanup(JCR *jcr, int status);
 
 /* External functions */
 
-/* 
+/*
  * Do a restore of the specified files
- *    
+ *
  *  Returns:  0 on failure
  *           1 on success
  */
-int do_restore(JCR *jcr) 
+int do_restore(JCR *jcr)
 {
    BSOCK   *fd;
    JOB_DBR rjr;                      /* restore job record */
@@ -73,10 +73,9 @@ 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));
+      Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
@@ -85,9 +84,10 @@ int do_restore(JCR *jcr)
 
    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
 
-   /* 
+   /*
     * The following code is kept temporarily for compatibility.
     * It is the predecessor to the Bootstrap file.
+    *  DEPRECATED
     */
    if (!jcr->RestoreBootstrap) {
       /*
@@ -99,7 +99,7 @@ int do_restore(JCR *jcr)
         rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */
       }
       if (!db_get_job_record(jcr, jcr->db, &rjr)) {
-         Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
+        Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
            db_strerror(jcr->db));
         restore_cleanup(jcr, JS_ErrorTerminated);
         return 0;
@@ -111,14 +111,14 @@ 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;
       }
       Dmsg1(20, "Got job Volume Names: %s\n", jcr->VolumeName);
    }
-      
+
 
    /* Print Job Start message */
    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
@@ -132,7 +132,7 @@ int do_restore(JCR *jcr)
    Dmsg0(10, "Open connection with storage daemon\n");
    set_jcr_job_status(jcr, JS_WaitSD);
    /*
-    * Start conversation with Storage daemon  
+    * Start conversation with Storage daemon
     */
    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
@@ -154,8 +154,8 @@ int do_restore(JCR *jcr)
    }
    Dmsg0(50, "Storage daemon connection OK\n");
 
-   /* 
-    * Start conversation with File daemon  
+   /*
+    * Start conversation with File daemon
     */
    set_jcr_job_status(jcr, JS_WaitFD);
    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
@@ -176,7 +176,7 @@ int do_restore(JCR *jcr)
       return 0;
    }
 
-   /* 
+   /*
     * send Storage daemon address to the File daemon,
     *  then wait for File daemon to make connection
     *  with Storage daemon.
@@ -191,7 +191,7 @@ int do_restore(JCR *jcr)
       return 0;
    }
 
-   /* 
+   /*
     * Send the bootstrap file -- what Volumes/files to restore
     */
    if (!send_bootstrap_file(jcr)) {
@@ -199,18 +199,18 @@ int do_restore(JCR *jcr)
       return 0;
    }
 
-   /* 
-    * The following code is deprecated  
+   /*
+    * The following code is deprecated
     */
    if (!jcr->RestoreBootstrap) {
       /*
        * Pass the VolSessionId, VolSessionTime, Start and
        * end File and Blocks on the session command.
        */
-      bnet_fsend(fd, sessioncmd, 
+      bnet_fsend(fd, sessioncmd,
                jcr->VolumeName,
-               rjr.VolSessionId, rjr.VolSessionTime, 
-               rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
+               rjr.VolSessionId, rjr.VolSessionTime,
+               rjr.StartFile, rjr.EndFile, rjr.StartBlock,
                rjr.EndBlock);
       if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
         restore_cleanup(jcr, JS_ErrorTerminated);
@@ -225,6 +225,7 @@ int do_restore(JCR *jcr)
 
    /* Send restore command */
    char replace, *where;
+   char empty = '\0';
 
    if (jcr->replace != 0) {
       replace = jcr->replace;
@@ -238,7 +239,7 @@ int do_restore(JCR *jcr)
    } else if (jcr->job->RestoreWhere) {
       where = jcr->job->RestoreWhere; /* no override take from job */
    } else {
-      where = "";                     /* None */
+      where = &empty;                /* None */
    }
    jcr->prefix_links = jcr->job->PrefixLinks;
    bash_spaces(where);
@@ -264,13 +265,14 @@ 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 ec1[30], ec2[30], ec3[30];
    char term_code[100], fd_term_msg[100], sd_term_msg[100];
-   char *term_msg;
+   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);
@@ -278,22 +280,30 @@ static void restore_cleanup(JCR *jcr, int TermCode)
    msg_type = M_INFO;                /* by default INFO message */
    switch (TermCode) {
    case JS_Terminated:
-      term_msg = _("Restore OK");
+      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 ***"); 
+      term_msg = _("*** Restore Error ***");
       msg_type = M_ERROR;         /* Generate error message */
       if (jcr->store_bsock) {
         bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-        pthread_cancel(jcr->SD_msg_chan);
+        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);
-        pthread_cancel(jcr->SD_msg_chan);
+        if (jcr->SD_msg_chan) {
+           pthread_cancel(jcr->SD_msg_chan);
+        }
       }
       break;
    default:
@@ -301,8 +311,8 @@ static void restore_cleanup(JCR *jcr, int TermCode)
       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
       break;
    }
-   bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime);
-   bstrftime(edt, sizeof(edt), jcr->jr.EndTime);
+   bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
+   bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
    } else {
@@ -315,27 +325,29 @@ static void restore_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));
 
-   Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\
-JobId:                  %d\n\
-Job:                    %s\n\
-Client:                 %s\n\
-Start time:             %s\n\
-End time:               %s\n\
-Files Restored:         %s\n\
-Bytes Restored:         %s\n\
-Rate:                   %.1f KB/s\n\
-Non-fatal FD Errors:    %d\n\
-FD termination status:  %s\n\
-SD termination status:  %s\n\
-Termination:            %s\n\n"),
+   Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n"
+"  JobId:                  %d\n"
+"  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,
        jcr->jr.Job,
        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,