X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Frestore.c;h=6dfb15ef140cd47dcdfc9b08f2a3a2aa2f357a09;hb=482a36a5cbcbb346ca00c424210ef153451e7214;hp=974bde208e07eff58d67c3cbebaed97cd6cf066c;hpb=c71cea19ab440d3a10815042a38cc9121c6061f2;p=bacula%2Fbacula diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 974bde208e..6dfb15ef14 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -1,11 +1,9 @@ /* - * * Bacula Director -- restore.c -- responsible for restoring files * * Kern Sibbald, November MM * - * This routine is run as a separate thread. There may be more - * work to be done to make it totally reentrant!!!! + * This routine is run as a separate thread. * * Current implementation is Catalog verification only (i.e. no * verification versus tape). @@ -21,7 +19,7 @@ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2003 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,20 +42,17 @@ #include "dird.h" /* Commands sent to File daemon */ -static char restorecmd[] = "restore where=%s\n"; -static char storaddr[] = "storage address=%s port=%d\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"; /* Responses received from File daemon */ 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 */ @@ -71,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); @@ -80,9 +73,9 @@ int do_restore(JCR *jcr) } memset(&rjr, 0, sizeof(rjr)); - jcr->jr.Level = 'F'; /* Full restore */ + jcr->jr.Level = L_FULL; /* Full restore */ jcr->jr.StartTime = jcr->start_time; - if (!db_update_job_start_record(jcr->db, &jcr->jr)) { + 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); return 0; @@ -95,6 +88,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) { /* @@ -105,7 +99,7 @@ int do_restore(JCR *jcr) } else { rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */ } - if (!db_get_job_record(jcr->db, &rjr)) { + if (!db_get_job_record(jcr, jcr->db, &rjr)) { Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId, db_strerror(jcr->db)); restore_cleanup(jcr, JS_ErrorTerminated); @@ -116,7 +110,7 @@ int do_restore(JCR *jcr) * Now find the Volumes we will need for the Restore */ jcr->VolumeName[0] = 0; - if (!db_get_job_volume_names(jcr->db, rjr.JobId, &jcr->VolumeName) || + 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"), rjr.JobId, db_strerror(jcr->db)); @@ -137,7 +131,7 @@ int do_restore(JCR *jcr) * */ Dmsg0(10, "Open connection with storage daemon\n"); - jcr->JobStatus = JS_Blocked; + set_jcr_job_status(jcr, JS_WaitSD); /* * Start conversation with Storage daemon */ @@ -164,13 +158,14 @@ 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; } fd = jcr->file_bsock; - jcr->JobStatus = JS_Running; + set_jcr_job_status(jcr, JS_Running); if (!send_include_list(jcr)) { restore_cleanup(jcr, JS_ErrorTerminated); @@ -182,23 +177,20 @@ 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. */ - jcr->JobStatus = 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")) { + if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) { restore_cleanup(jcr, JS_ErrorTerminated); return 0; } - jcr->JobStatus = JS_Running; /* * Send the bootstrap file -- what Volumes/files to restore @@ -221,36 +213,47 @@ int do_restore(JCR *jcr) rjr.VolSessionId, rjr.VolSessionTime, rjr.StartFile, rjr.EndFile, rjr.StartBlock, rjr.EndBlock); - if (!response(fd, OKsession, "Session")) { + 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 */ - if (jcr->RestoreWhere) { - bnet_fsend(fd, restorecmd, jcr->RestoreWhere); + char replace, *where; + + if (jcr->replace != 0) { + replace = jcr->replace; + } else if (jcr->job->replace != 0) { + replace = jcr->job->replace; } else { - bnet_fsend(fd, restorecmd, - jcr->job->RestoreWhere ? jcr->job->RestoreWhere : ""); + replace = REPLACE_ALWAYS; /* always replace */ } - if (!response(fd, OKrestore, "Restore")) { + if (jcr->where) { + where = jcr->where; /* override */ + } else if (jcr->job->RestoreWhere) { + where = jcr->job->RestoreWhere; /* no override take from job */ + } else { + where = ""; /* None */ + } + jcr->prefix_links = jcr->job->PrefixLinks; + bash_spaces(where); + bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where); + unbash_spaces(where); + + if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) { restore_cleanup(jcr, JS_ErrorTerminated); return 0; } /* Wait for Job Termination */ - /*** ****FIXME**** get job termination status */ - Dmsg0(20, "wait for job termination\n"); - while (bget_msg(fd, 0) > 0) { - Dmsg1(100, "dirdmsg); - if (sscanf(fd->msg, EndRestore, &jcr->JobStatus, &jcr->JobFiles, - &jcr->JobBytes) == 3) { - ok = TRUE; - } - } - - restore_cleanup(jcr, ok?jcr->JobStatus:JS_ErrorTerminated); + int stat = wait_for_job_termination(jcr); + restore_cleanup(jcr, stat); return 1; } @@ -263,47 +266,57 @@ 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]; + char term_code[100], fd_term_msg[100], sd_term_msg[100]; char *term_msg; int msg_type; double kbps; Dmsg0(20, "In restore_cleanup\n"); - jcr->JobStatus = TermCode; + set_jcr_job_status(jcr, TermCode); update_job_end_record(jcr); msg_type = M_INFO; /* by default INFO message */ switch (TermCode) { - case JS_Terminated: - 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); - pthread_cancel(jcr->SD_msg_chan); - } - break; - case JS_Cancelled: - term_msg = _("Restore Cancelled"); - if (jcr->store_bsock) { - bnet_sig(jcr->store_bsock, BNET_TERMINATE); - pthread_cancel(jcr->SD_msg_chan); - } - break; - default: - term_msg = term_code; - sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode); - break; + case JS_Terminated: + 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); + 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); + } + 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, _("%s\n\ + Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\ JobId: %d\n\ Job: %s\n\ Client: %s\n\ @@ -312,6 +325,9 @@ 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"), edt, jcr->jr.JobId, @@ -319,44 +335,13 @@ Termination: %s\n\n"), jcr->client->hdr.name, sdt, edt, - edit_uint64_with_commas(jcr->jr.JobFiles, ec1), + edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec1), edit_uint64_with_commas(jcr->jr.JobBytes, ec2), (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)); - jcr->JobStatus = 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")) { - jcr->JobStatus = JS_ErrorTerminated; - return 0; - } - return 1; -}