2 * Bacula Director -- restore.c -- responsible for restoring files
4 * Kern Sibbald, November MM
6 * This routine is run as a separate thread.
8 * Current implementation is Catalog verification only (i.e. no
9 * verification versus tape).
11 * Basic tasks done here:
13 * Open Message Channel with Storage daemon to tell him a job will be starting.
14 * Open connection with File daemon and pass him commands
16 * Update the DB according to what files where restored????
21 Copyright (C) 2000-2006 Kern Sibbald
23 This program is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License
25 version 2 as amended with additional clauses defined in the
26 file LICENSE in the main source directory.
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 the file LICENSE for additional details.
39 /* Commands sent to File daemon */
40 static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
41 static char storaddr[] = "storage address=%s port=%d ssl=0\n";
43 /* Responses received from File daemon */
44 static char OKrestore[] = "2000 OK restore\n";
45 static char OKstore[] = "2000 OK storage\n";
48 * Do a restore of the specified files
50 * Returns: 0 on failure
53 bool do_restore(JCR *jcr)
56 JOB_DBR rjr; /* restore job record */
58 memset(&rjr, 0, sizeof(rjr));
59 jcr->jr.JobLevel = L_FULL; /* Full restore */
60 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
61 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
62 restore_cleanup(jcr, JS_ErrorTerminated);
65 Dmsg0(20, "Updated job start record\n");
67 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
69 if (!jcr->RestoreBootstrap) {
70 Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without bootstrap file.\n"));
71 restore_cleanup(jcr, JS_ErrorTerminated);
76 /* Print Job Start message */
77 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
80 * Open a message channel connection with the Storage
81 * daemon. This is to let him know that our client
82 * will be contacting him for a backup session.
85 Dmsg0(10, "Open connection with storage daemon\n");
86 set_jcr_job_status(jcr, JS_WaitSD);
88 * Start conversation with Storage daemon
90 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
91 restore_cleanup(jcr, JS_ErrorTerminated);
95 * Now start a job with the Storage daemon
97 if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) {
98 restore_cleanup(jcr, JS_ErrorTerminated);
102 * Now start a Storage daemon message thread
104 if (!start_storage_daemon_message_thread(jcr)) {
105 restore_cleanup(jcr, JS_ErrorTerminated);
108 Dmsg0(50, "Storage daemon connection OK\n");
110 if (!bnet_fsend(jcr->store_bsock, "run")) {
115 * Start conversation with File daemon
117 set_jcr_job_status(jcr, JS_WaitFD);
118 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
119 restore_cleanup(jcr, JS_ErrorTerminated);
123 fd = jcr->file_bsock;
124 set_jcr_job_status(jcr, JS_Running);
127 * send Storage daemon address to the File daemon,
128 * then wait for File daemon to make connection
129 * with Storage daemon.
131 if (jcr->store->SDDport == 0) {
132 jcr->store->SDDport = jcr->store->SDport;
134 bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
135 Dmsg1(6, "dird>filed: %s\n", fd->msg);
136 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
137 restore_cleanup(jcr, JS_ErrorTerminated);
142 * Send the bootstrap file -- what Volumes/files to restore
144 if (!send_bootstrap_file(jcr)) {
145 restore_cleanup(jcr, JS_ErrorTerminated);
150 if (!send_run_before_and_after_commands(jcr)) {
151 restore_cleanup(jcr, JS_ErrorTerminated);
155 /* Send restore command */
156 char replace, *where;
159 if (jcr->replace != 0) {
160 replace = jcr->replace;
161 } else if (jcr->job->replace != 0) {
162 replace = jcr->job->replace;
164 replace = REPLACE_ALWAYS; /* always replace */
167 where = jcr->where; /* override */
168 } else if (jcr->job->RestoreWhere) {
169 where = jcr->job->RestoreWhere; /* no override take from job */
171 where = ∅ /* None */
173 jcr->prefix_links = jcr->job->PrefixLinks;
175 bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
176 unbash_spaces(where);
178 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
179 restore_cleanup(jcr, JS_ErrorTerminated);
183 /* Wait for Job Termination */
184 int stat = wait_for_job_termination(jcr);
185 restore_cleanup(jcr, stat);
190 bool do_restore_init(JCR *jcr)
196 * Release resources allocated during restore.
199 void restore_cleanup(JCR *jcr, int TermCode)
201 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
202 char ec1[30], ec2[30], ec3[30];
203 char term_code[100], fd_term_msg[100], sd_term_msg[100];
204 const char *term_msg;
208 Dmsg0(20, "In restore_cleanup\n");
209 dequeue_messages(jcr); /* display any queued messages */
210 set_jcr_job_status(jcr, TermCode);
212 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
213 unlink(jcr->RestoreBootstrap);
214 jcr->unlink_bsr = false;
217 update_job_end_record(jcr);
219 msg_type = M_INFO; /* by default INFO message */
222 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
223 term_msg = _("Restore OK -- warning file count mismatch");
225 term_msg = _("Restore OK");
229 case JS_ErrorTerminated:
230 term_msg = _("*** Restore Error ***");
231 msg_type = M_ERROR; /* Generate error message */
232 if (jcr->store_bsock) {
233 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
234 if (jcr->SD_msg_chan) {
235 pthread_cancel(jcr->SD_msg_chan);
240 term_msg = _("Restore Canceled");
241 if (jcr->store_bsock) {
242 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
243 if (jcr->SD_msg_chan) {
244 pthread_cancel(jcr->SD_msg_chan);
249 term_msg = term_code;
250 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
253 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
254 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
255 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
256 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
264 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
265 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
267 Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
273 " Files Expected: %s\n"
274 " Files Restored: %s\n"
275 " Bytes Restored: %s\n"
278 " FD termination status: %s\n"
279 " SD termination status: %s\n"
280 " Termination: %s\n\n"),
286 jcr->client->hdr.name,
289 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
290 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
291 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
298 Dmsg0(20, "Leaving restore_cleanup\n");