X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Fdird%2Frestore.c;h=082877a878c6f66274a4205329058e65094feeda;hb=7ebf8f564b27ca8448a9a7365ba73b130ae69c21;hp=464a27363895d81af97e579f147a5261dbffaf3b;hpb=ba0ddc011c5e8d5488ef79cdcef2643927fc5539;p=bacula%2Fbacula diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 464a273638..082877a878 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,19 +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"; /* Forward referenced functions */ static void restore_cleanup(JCR *jcr, int status); -static int send_bootstrap_file(JCR *jcr); /* External functions */ @@ -68,20 +64,18 @@ static int send_bootstrap_file(JCR *jcr); */ int do_restore(JCR *jcr) { - char dt[MAX_TIME_LENGTH]; BSOCK *fd; JOB_DBR rjr; /* restore job record */ - if (!get_or_create_client_record(jcr)) { restore_cleanup(jcr, JS_ErrorTerminated); return 0; } 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; @@ -94,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) { /* @@ -104,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); @@ -115,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)); @@ -127,10 +122,7 @@ int do_restore(JCR *jcr) /* Print Job Start message */ - bstrftime(dt, sizeof(dt), jcr->start_time); - Jmsg(jcr, M_INFO, 0, _("%s Start Restore Job %s Name=%s, Client=%s, FileSet=%s\n"), - dt, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, - jcr->fileset->hdr.name); + Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job); /* * Open a message channel connection with the Storage @@ -139,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 */ @@ -166,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); @@ -184,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 @@ -223,32 +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(0, "dirdmsg); - } - - restore_cleanup(jcr, JS_Terminated); + int stat = wait_for_job_termination(jcr); + restore_cleanup(jcr, stat); return 1; } @@ -257,52 +262,96 @@ int do_restore(JCR *jcr) * Release resources allocated during restore. * */ -static void restore_cleanup(JCR *jcr, int status) +static void restore_cleanup(JCR *jcr, int TermCode) { - char dt[MAX_TIME_LENGTH]; + char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH]; + char ec1[30], ec2[30], ec3[30]; + 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 = status; + set_jcr_job_status(jcr, TermCode); update_job_end_record(jcr); - bstrftime(dt, sizeof(dt), jcr->jr.EndTime); - Jmsg(jcr, M_INFO, 0, _("%s End Restore Job %s.\n\n"), - dt, jcr->Job); - - 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; + msg_type = M_INFO; /* by default INFO message */ + switch (TermCode) { + 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); + 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); + 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; } - 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); + bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime); + bstrftime(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 { + kbps = 0; } - bnet_sig(fd, BNET_EOD); - fclose(bs); - if (!response(fd, OKbootstrap, "Bootstrap")) { - jcr->JobStatus = JS_ErrorTerminated; - return 0; + if (kbps < 0.05) { + kbps = 0; } - return 1; + + 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 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->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"); }