]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Remove new bnet_sig
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2  *   Bacula Director -- restore.c -- responsible for restoring files
3  *
4  *     Kern Sibbald, November MM
5  *
6  *    This routine is run as a separate thread.
7  *
8  * Current implementation is Catalog verification only (i.e. no
9  *  verification versus tape).
10  *
11  *  Basic tasks done here:
12  *     Open DB
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
15  *       to do the restore.
16  *     Update the DB according to what files where restored????
17  *
18  *   Version $Id$
19  */
20 /*
21    Copyright (C) 2000-2005 Kern Sibbald
22
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.
27
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.
32
33  */
34
35
36 #include "bacula.h"
37 #include "dird.h"
38
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";
42
43 /* Responses received from File daemon */
44 static char OKrestore[]   = "2000 OK restore\n";
45 static char OKstore[]     = "2000 OK storage\n";
46
47 /*
48  * Do a restore of the specified files
49  *
50  *  Returns:  0 on failure
51  *            1 on success
52  */
53 bool do_restore(JCR *jcr)
54 {
55    BSOCK   *fd;
56    JOB_DBR rjr;                       /* restore job record */
57
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);
63       return false;
64    }
65    Dmsg0(20, "Updated job start record\n");
66
67    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
68
69    if (!jcr->RestoreBootstrap) {
70       Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without bootstrap file.\n"));
71       restore_cleanup(jcr, JS_ErrorTerminated);
72       return false;
73    }
74
75
76    /* Print Job Start message */
77    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
78
79    /*
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.
83     *
84     */
85    Dmsg0(10, "Open connection with storage daemon\n");
86    set_jcr_job_status(jcr, JS_WaitSD);
87    /*
88     * Start conversation with Storage daemon
89     */
90    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
91       restore_cleanup(jcr, JS_ErrorTerminated);
92       return false;
93    }
94    /*
95     * Now start a job with the Storage daemon
96     */
97    if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) {
98       restore_cleanup(jcr, JS_ErrorTerminated);
99       return false;
100    }
101    /*
102     * Now start a Storage daemon message thread
103     */
104    if (!start_storage_daemon_message_thread(jcr)) {
105       restore_cleanup(jcr, JS_ErrorTerminated);
106       return false;
107    }
108    Dmsg0(50, "Storage daemon connection OK\n");
109
110    /*
111     * Start conversation with File daemon
112     */
113    set_jcr_job_status(jcr, JS_WaitFD);
114    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
115       restore_cleanup(jcr, JS_ErrorTerminated);
116       return false;
117    }
118
119    fd = jcr->file_bsock;
120    set_jcr_job_status(jcr, JS_Running);
121
122    /*
123     * send Storage daemon address to the File daemon,
124     *   then wait for File daemon to make connection
125     *   with Storage daemon.
126     */
127    if (jcr->store->SDDport == 0) {
128       jcr->store->SDDport = jcr->store->SDport;
129    }
130    bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
131    Dmsg1(6, "dird>filed: %s\n", fd->msg);
132    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
133       restore_cleanup(jcr, JS_ErrorTerminated);
134       return false;
135    }
136
137    /*
138     * Send the bootstrap file -- what Volumes/files to restore
139     */
140    if (!send_bootstrap_file(jcr)) {
141       restore_cleanup(jcr, JS_ErrorTerminated);
142       return false;
143    }
144
145
146    if (!send_run_before_and_after_commands(jcr)) {
147       restore_cleanup(jcr, JS_ErrorTerminated);
148       return false;
149    }
150
151    /* Send restore command */
152    char replace, *where;
153    char empty = '\0';
154
155    if (jcr->replace != 0) {
156       replace = jcr->replace;
157    } else if (jcr->job->replace != 0) {
158       replace = jcr->job->replace;
159    } else {
160       replace = REPLACE_ALWAYS;       /* always replace */
161    }
162    if (jcr->where) {
163       where = jcr->where;             /* override */
164    } else if (jcr->job->RestoreWhere) {
165       where = jcr->job->RestoreWhere; /* no override take from job */
166    } else {
167       where = ∅                 /* None */
168    }
169    jcr->prefix_links = jcr->job->PrefixLinks;
170    bash_spaces(where);
171    bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
172    unbash_spaces(where);
173
174    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
175       restore_cleanup(jcr, JS_ErrorTerminated);
176       return false;
177    }
178
179    /* Wait for Job Termination */
180    int stat = wait_for_job_termination(jcr);
181    restore_cleanup(jcr, stat);
182
183    return true;
184 }
185
186 bool do_restore_init(JCR *jcr) 
187 {
188    return true;
189 }
190
191 /*
192  * Release resources allocated during restore.
193  *
194  */
195 void restore_cleanup(JCR *jcr, int TermCode)
196 {
197    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
198    char ec1[30], ec2[30], ec3[30];
199    char term_code[100], fd_term_msg[100], sd_term_msg[100];
200    const char *term_msg;
201    int msg_type;
202    double kbps;
203
204    Dmsg0(20, "In restore_cleanup\n");
205    dequeue_messages(jcr);             /* display any queued messages */
206    set_jcr_job_status(jcr, TermCode);
207
208    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
209       unlink(jcr->RestoreBootstrap);
210       jcr->unlink_bsr = false;
211    }
212
213    update_job_end_record(jcr);
214
215    msg_type = M_INFO;                 /* by default INFO message */
216    switch (TermCode) {
217    case JS_Terminated:
218       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
219          term_msg = _("Restore OK -- warning file count mismatch");
220       } else {
221          term_msg = _("Restore OK");
222       }
223       break;
224    case JS_FatalError:
225    case JS_ErrorTerminated:
226       term_msg = _("*** Restore Error ***");
227       msg_type = M_ERROR;          /* Generate error message */
228       if (jcr->store_bsock) {
229          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
230          if (jcr->SD_msg_chan) {
231             pthread_cancel(jcr->SD_msg_chan);
232          }
233       }
234       break;
235    case JS_Canceled:
236       term_msg = _("Restore Canceled");
237       if (jcr->store_bsock) {
238          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
239          if (jcr->SD_msg_chan) {
240             pthread_cancel(jcr->SD_msg_chan);
241          }
242       }
243       break;
244    default:
245       term_msg = term_code;
246       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
247       break;
248    }
249    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
250    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
251    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
252       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
253    } else {
254       kbps = 0;
255    }
256    if (kbps < 0.05) {
257       kbps = 0;
258    }
259
260    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
261    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
262
263    Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
264 "  JobId:                  %d\n"
265 "  Job:                    %s\n"
266 "  Client:                 %s\n"
267 "  Start time:             %s\n"
268 "  End time:               %s\n"
269 "  Files Expected:         %s\n"
270 "  Files Restored:         %s\n"
271 "  Bytes Restored:         %s\n"
272 "  Rate:                   %.1f KB/s\n"
273 "  FD Errors:              %d\n"
274 "  FD termination status:  %s\n"
275 "  SD termination status:  %s\n"
276 "  Termination:            %s\n\n"),
277         VERSION,
278         LSMDATE,
279         edt,
280         jcr->jr.JobId,
281         jcr->jr.Job,
282         jcr->client->hdr.name,
283         sdt,
284         edt,
285         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
286         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
287         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
288         (float)kbps,
289         jcr->Errors,
290         fd_term_msg,
291         sd_term_msg,
292         term_msg);
293
294    Dmsg0(20, "Leaving restore_cleanup\n");
295 }