]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
f92efb0e2da0f0155c33f046ef7ecaa25ce6d4f9
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2  *
3  *   Bacula Director -- restore.c -- responsible for restoring files
4  *
5  *     Kern Sibbald, November MM
6  *
7  *    This routine is run as a separate thread.  There may be more
8  *    work to be done to make it totally reentrant!!!!
9  * 
10  * Current implementation is Catalog verification only (i.e. no
11  *  verification versus tape).
12  *
13  *  Basic tasks done here:
14  *     Open DB
15  *     Open Message Channel with Storage daemon to tell him a job will be starting.
16  *     Open connection with File daemon and pass him commands
17  *       to do the restore.
18  *     Update the DB according to what files where restored????
19  *
20  *   Version $Id$
21  */
22
23 /*
24    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
25
26    This program is free software; you can redistribute it and/or
27    modify it under the terms of the GNU General Public License as
28    published by the Free Software Foundation; either version 2 of
29    the License, or (at your option) any later version.
30
31    This program is distributed in the hope that it will be useful,
32    but WITHOUT ANY WARRANTY; without even the implied warranty of
33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34    General Public License for more details.
35
36    You should have received a copy of the GNU General Public
37    License along with this program; if not, write to the Free
38    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
39    MA 02111-1307, USA.
40
41  */
42
43 #include "bacula.h"
44 #include "dird.h"
45
46 /* Commands sent to File daemon */
47 static char restorecmd[]   = "restore where=%s\n";
48 static char storaddr[]     = "storage address=%s port=%d\n";
49 static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";  
50
51 /* Responses received from File daemon */
52 static char OKrestore[]   = "2000 OK restore\n";
53 static char OKstore[]     = "2000 OK storage\n";
54 static char OKsession[]   = "2000 OK session\n";
55
56 /* Forward referenced functions */
57 static void restore_cleanup(JCR *jcr, int status);
58
59 /* External functions */
60
61 /* 
62  * Do a restore of the specified files
63  *    
64  *  Returns:  0 on failure
65  *            1 on success
66  */
67 int do_restore(JCR *jcr) 
68 {
69    char dt[MAX_TIME_LENGTH];
70    BSOCK   *fd;
71    JOB_DBR rjr;                       /* restore job record */
72
73
74    if (!get_or_create_client_record(jcr)) {
75       restore_cleanup(jcr, JS_ErrorTerminated);
76       return 0;
77    }
78
79    memset(&rjr, 0, sizeof(rjr));
80    jcr->jr.Level = 'F';            /* Full restore */
81    jcr->jr.StartTime = jcr->start_time;
82    if (!db_update_job_start_record(jcr->db, &jcr->jr)) {
83       Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
84       restore_cleanup(jcr, JS_ErrorTerminated);
85       return 0;
86    }
87    Dmsg0(20, "Updated job start record\n");
88    jcr->fname = (char *) get_pool_memory(PM_FNAME);
89
90    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
91
92    /*
93     * Find Job Record for Files to be restored
94     */
95    if (jcr->RestoreJobId != 0) {
96       rjr.JobId = jcr->RestoreJobId;     /* specified by UA */
97    } else {
98       rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */
99    }
100    if (!db_get_job_record(jcr->db, &rjr)) {
101       Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
102          db_strerror(jcr->db));
103       restore_cleanup(jcr, JS_ErrorTerminated);
104       return 0;
105    }
106    Dmsg3(20, "Got JobId=%d VolSessId=%ld, VolSesTime=%ld\n", 
107              rjr.JobId, rjr.VolSessionId, rjr.VolSessionTime);
108    Dmsg4(20, "StartFile=%ld, EndFile=%ld StartBlock=%ld EndBlock=%ld\n", 
109              rjr.StartFile, rjr.EndFile, rjr.StartBlock, rjr.EndBlock);
110
111    /*
112     * Now find the Volumes we will need for the Restore
113     */
114    jcr->VolumeName[0] = 0;
115    if (!db_get_job_volume_names(jcr->db, rjr.JobId, jcr->VolumeName) ||
116         jcr->VolumeName[0] == 0) {
117       Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"), 
118          rjr.JobId, db_strerror(jcr->db));
119       restore_cleanup(jcr, JS_ErrorTerminated);
120       return 0;
121    }
122    Dmsg1(20, "Got job Volume Names: %s\n", jcr->VolumeName);
123       
124
125    /* Print Job Start message */
126    bstrftime(dt, sizeof(dt), jcr->start_time);
127    Jmsg(jcr, M_INFO, 0, _("%s Start Restore Job %s Name=%s, Client=%s, FileSet=%s\n"), 
128       dt, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, 
129       jcr->fileset->hdr.name);
130
131    /*
132     * Open a message channel connection with the Storage
133     * daemon. This is to let him know that our client
134     * will be contacting him for a backup  session.
135     *
136     */
137    Dmsg0(10, "Open connection with storage daemon\n");
138    jcr->JobStatus = JS_Blocked;
139    /*
140     * Start conversation with Storage daemon  
141     */
142    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
143       restore_cleanup(jcr, JS_ErrorTerminated);
144       return 0;
145    }
146    /*
147     * Now start a job with the Storage daemon
148     */
149    if (!start_storage_daemon_job(jcr)) {
150       restore_cleanup(jcr, JS_ErrorTerminated);
151       return 0;
152    }
153    /*
154     * Now start a Storage daemon message thread
155     */
156    if (!start_storage_daemon_message_thread(jcr)) {
157       restore_cleanup(jcr, JS_ErrorTerminated);
158       return 0;
159    }
160    Dmsg0(50, "Storage daemon connection OK\n");
161
162    /* 
163     * Start conversation with File daemon  
164     */
165    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
166       restore_cleanup(jcr, JS_ErrorTerminated);
167       return 0;
168    }
169
170    fd = jcr->file_bsock;
171    jcr->JobStatus = JS_Running;
172
173    if (!send_include_list(jcr)) {
174       restore_cleanup(jcr, JS_ErrorTerminated);
175       return 0;
176    }
177
178    if (!send_exclude_list(jcr)) {
179       restore_cleanup(jcr, JS_ErrorTerminated);
180       return 0;
181    }
182
183    /* 
184     * send Storage daemon address to the File daemon,
185     *   then wait for File daemon to make connection
186     *   with Storage daemon.
187     */
188    jcr->JobStatus = JS_Blocked;
189    if (jcr->store->SDDport == 0) {
190       jcr->store->SDDport = jcr->store->SDport;
191    }
192    bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
193    Dmsg1(6, "dird>filed: %s\n", fd->msg);
194    if (!response(fd, OKstore, "Storage")) {
195       restore_cleanup(jcr, JS_ErrorTerminated);
196       return 0;
197    }
198    jcr->JobStatus = JS_Running;
199
200    /*
201     * Pass the VolSessionId, VolSessionTime, Start and
202     * end File and Blocks on the session command.
203     */
204    bnet_fsend(fd, sessioncmd, 
205              jcr->VolumeName,
206              rjr.VolSessionId, rjr.VolSessionTime, 
207              rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
208              rjr.EndBlock);
209    if (!response(fd, OKsession, "Session")) {
210       restore_cleanup(jcr, JS_ErrorTerminated);
211       return 0;
212    }
213
214    /* Send restore command */
215    if (jcr->RestoreWhere) {
216       bnet_fsend(fd, restorecmd, jcr->RestoreWhere);
217    } else {
218       bnet_fsend(fd, restorecmd,                               
219          jcr->job->RestoreWhere==NULL ? "" : jcr->job->RestoreWhere);
220    }
221    if (!response(fd, OKrestore, "Restore")) {
222       restore_cleanup(jcr, JS_ErrorTerminated);
223       return 0;
224    }
225
226    /* Wait for Job Termination */
227    /*** ****FIXME**** get job termination data */
228    Dmsg0(20, "wait for job termination\n");
229    while (bget_msg(fd, 0) >  0) {
230       Dmsg1(0, "dird<filed: %s\n", fd->msg);
231    }
232
233    restore_cleanup(jcr, JS_Terminated);
234
235    return 1;
236 }
237
238 /*
239  * Release resources allocated during restore.
240  *
241  */
242 static void restore_cleanup(JCR *jcr, int status) 
243 {
244    char dt[MAX_TIME_LENGTH];
245
246    Dmsg0(20, "In restore_cleanup\n");
247    jcr->JobStatus = status;
248
249    update_job_end_record(jcr);
250
251    bstrftime(dt, sizeof(dt), jcr->jr.EndTime);
252    Jmsg(jcr, M_INFO, 0, _("%s End Restore Job %s.\n\n"),
253       dt, jcr->Job);
254
255    Dmsg0(20, "Leaving restore_cleanup\n");
256 }