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";
46 static char OKbootstrap[] = "2000 OK bootstrap\n";
49 * Do a restore of the specified files
51 * Returns: 0 on failure
54 bool do_restore(JCR *jcr)
57 JOB_DBR rjr; /* restore job record */
59 free_wstorage(jcr); /* we don't write */
61 memset(&rjr, 0, sizeof(rjr));
62 jcr->jr.JobLevel = L_FULL; /* Full restore */
63 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
64 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
65 restore_cleanup(jcr, JS_ErrorTerminated);
68 Dmsg0(20, "Updated job start record\n");
70 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
72 if (!jcr->RestoreBootstrap) {
73 Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
74 "You probably ran a restore job directly. All restore jobs must\n"
75 "be run using the restore command.\n"));
76 restore_cleanup(jcr, JS_ErrorTerminated);
81 /* Print Job Start message */
82 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
85 * Open a message channel connection with the Storage
86 * daemon. This is to let him know that our client
87 * will be contacting him for a backup session.
90 Dmsg0(10, "Open connection with storage daemon\n");
91 set_jcr_job_status(jcr, JS_WaitSD);
93 * Start conversation with Storage daemon
95 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
96 restore_cleanup(jcr, JS_ErrorTerminated);
100 * Now start a job with the Storage daemon
102 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
103 restore_cleanup(jcr, JS_ErrorTerminated);
106 if (!bnet_fsend(jcr->store_bsock, "run")) {
110 * Now start a Storage daemon message thread
112 if (!start_storage_daemon_message_thread(jcr)) {
113 restore_cleanup(jcr, JS_ErrorTerminated);
116 Dmsg0(50, "Storage daemon connection OK\n");
120 * Start conversation with File daemon
122 set_jcr_job_status(jcr, JS_WaitFD);
123 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
124 restore_cleanup(jcr, JS_ErrorTerminated);
128 fd = jcr->file_bsock;
129 set_jcr_job_status(jcr, JS_Running);
132 * send Storage daemon address to the File daemon,
133 * then wait for File daemon to make connection
134 * with Storage daemon.
136 if (jcr->rstore->SDDport == 0) {
137 jcr->rstore->SDDport = jcr->rstore->SDport;
139 bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport);
140 Dmsg1(6, "dird>filed: %s\n", fd->msg);
141 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
142 restore_cleanup(jcr, JS_ErrorTerminated);
147 * Send the bootstrap file -- what Volumes/files to restore
149 if (!send_bootstrap_file(jcr, fd) ||
150 !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
151 restore_cleanup(jcr, JS_ErrorTerminated);
156 if (!send_runscripts_commands(jcr)) {
157 restore_cleanup(jcr, JS_ErrorTerminated);
161 /* Send restore command */
162 char replace, *where;
165 if (jcr->replace != 0) {
166 replace = jcr->replace;
167 } else if (jcr->job->replace != 0) {
168 replace = jcr->job->replace;
170 replace = REPLACE_ALWAYS; /* always replace */
173 where = jcr->where; /* override */
174 } else if (jcr->job->RestoreWhere) {
175 where = jcr->job->RestoreWhere; /* no override take from job */
177 where = ∅ /* None */
179 jcr->prefix_links = jcr->job->PrefixLinks;
181 bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
182 unbash_spaces(where);
184 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
185 restore_cleanup(jcr, JS_ErrorTerminated);
189 /* Wait for Job Termination */
190 int stat = wait_for_job_termination(jcr);
191 restore_cleanup(jcr, stat);
196 bool do_restore_init(JCR *jcr)
203 * Release resources allocated during restore.
206 void restore_cleanup(JCR *jcr, int TermCode)
208 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
209 char ec1[30], ec2[30], ec3[30];
210 char term_code[100], fd_term_msg[100], sd_term_msg[100];
211 const char *term_msg;
215 Dmsg0(20, "In restore_cleanup\n");
216 dequeue_messages(jcr); /* display any queued messages */
217 set_jcr_job_status(jcr, TermCode);
219 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
220 unlink(jcr->RestoreBootstrap);
221 jcr->unlink_bsr = false;
224 update_job_end_record(jcr);
226 msg_type = M_INFO; /* by default INFO message */
229 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
230 term_msg = _("Restore OK -- warning file count mismatch");
232 term_msg = _("Restore OK");
236 case JS_ErrorTerminated:
237 term_msg = _("*** Restore Error ***");
238 msg_type = M_ERROR; /* Generate error message */
239 if (jcr->store_bsock) {
240 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
241 if (jcr->SD_msg_chan) {
242 pthread_cancel(jcr->SD_msg_chan);
247 term_msg = _("Restore Canceled");
248 if (jcr->store_bsock) {
249 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
250 if (jcr->SD_msg_chan) {
251 pthread_cancel(jcr->SD_msg_chan);
256 term_msg = term_code;
257 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
260 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
261 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
262 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
263 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
271 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
272 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
274 Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
280 " Files Expected: %s\n"
281 " Files Restored: %s\n"
282 " Bytes Restored: %s\n"
285 " FD termination status: %s\n"
286 " SD termination status: %s\n"
287 " Termination: %s\n\n"),
293 jcr->client->hdr.name,
296 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
297 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
298 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
305 Dmsg0(20, "Leaving restore_cleanup\n");