]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/mac.c
Move setting JobLevel and JobType into a method, which should
[bacula/bacula] / bacula / src / stored / mac.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2006-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * SD -- mac.c --  responsible for doing
30  *     migration, archive, copy, and virtual backup jobs.
31  *
32  *     Kern Sibbald, January MMVI
33  *
34  *   Version $Id$
35  */
36
37 #include "bacula.h"
38 #include "stored.h"
39
40 /* Import functions */
41 extern char Job_end[];   
42
43 /* Forward referenced subroutines */
44 static bool record_cb(DCR *dcr, DEV_RECORD *rec);
45
46
47 /*
48  *  Read Data and send to File Daemon
49  *   Returns: false on failure
50  *            true  on success
51  */
52 bool do_mac(JCR *jcr)
53 {
54    bool ok = true;
55    BSOCK *dir = jcr->dir_bsock;
56    const char *Type;
57    char ec1[50];
58    DEVICE *dev;
59
60    switch(jcr->get_JobType()) {
61    case JT_MIGRATE:
62       Type = "Migration";
63       break;
64    case JT_ARCHIVE:
65       Type = "Archive";
66       break;
67    case JT_COPY:
68       Type = "Copy";
69       break;
70    case JT_BACKUP:
71       Type = "Virtual Backup";
72       break;
73    default:
74       Type = "Unknown";
75       break;
76    }
77
78
79    Dmsg0(20, "Start read data.\n");
80
81    if (!jcr->read_dcr || !jcr->dcr) {
82       Jmsg(jcr, M_FATAL, 0, _("Read and write devices not properly initialized.\n"));
83       goto bail_out;
84    }
85    Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
86
87
88    create_restore_volume_list(jcr);
89    if (jcr->NumReadVolumes == 0) {
90       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type);
91       goto bail_out;
92    }
93
94    Dmsg3(200, "Found %d volumes names for %s. First=%s\n", jcr->NumReadVolumes,
95       jcr->VolList->VolumeName, Type);
96
97    /* Ready devices for reading and writing */
98    if (!acquire_device_for_read(jcr->read_dcr) ||
99        !acquire_device_for_append(jcr->dcr)) {
100       set_jcr_job_status(jcr, JS_ErrorTerminated);
101       goto bail_out;
102    }
103
104    Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->dcr->dev->file, jcr->dcr->dev->block_num);
105      
106    set_jcr_job_status(jcr, JS_Running);
107    dir_send_job_status(jcr);
108
109    begin_data_spool(jcr->dcr);
110    begin_attribute_spool(jcr);
111
112    jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
113    jcr->run_time = time(NULL);
114    set_start_vol_position(jcr->dcr);
115
116    ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
117    goto ok_out;
118
119 bail_out:
120    ok = false;
121
122 ok_out:
123    if (jcr->dcr) {
124       dev = jcr->dcr->dev;
125       if (ok || dev->can_write()) {
126          /* Flush out final partial block of this session */
127          if (!write_block_to_device(jcr->dcr)) {
128             Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
129                   dev->print_name(), dev->bstrerror());
130             Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
131             ok = false;
132          }
133          Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num);
134       }  
135
136       if (!ok) {
137          discard_data_spool(jcr->dcr);
138       } else {
139          /* Note: if commit is OK, the device will remain locked */
140          commit_data_spool(jcr->dcr);
141       }
142
143       if (ok && dev->is_dvd()) {
144          ok = dvd_close_job(jcr->dcr);   /* do DVD cleanup if any */
145       }
146       /* Release the device -- and send final Vol info to DIR */
147       release_device(jcr->dcr);
148
149       if (!ok || job_canceled(jcr)) {
150          discard_attribute_spool(jcr);
151       } else {
152          commit_attribute_spool(jcr);
153       }
154    }
155
156    if (jcr->read_dcr) {
157       if (!release_device(jcr->read_dcr)) {
158          ok = false;
159       }
160    }
161
162    free_restore_volume_list(jcr);
163
164    dir_send_job_status(jcr);          /* update director */
165
166
167    Dmsg0(30, "Done reading.\n");
168    jcr->end_time = time(NULL);
169    dequeue_messages(jcr);             /* send any queued messages */
170    if (ok) {
171       set_jcr_job_status(jcr, JS_Terminated);
172    }
173    generate_daemon_event(jcr, "JobEnd");
174    dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
175       edit_uint64(jcr->JobBytes, ec1));
176    Dmsg4(200, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1); 
177        
178    dir->signal(BNET_EOD);             /* send EOD to Director daemon */
179
180    return ok;
181 }
182
183 /*
184  * Called here for each record from read_records()
185  *  Returns: true if OK
186  *           false if error
187  */
188 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
189 {
190    JCR *jcr = dcr->jcr;
191    DEVICE *dev = jcr->dcr->dev;
192    char buf1[100], buf2[100];
193    int32_t stream;   
194    
195    /* If label and not for us, discard it */
196    if (rec->FileIndex < 0 && rec->match_stat <= 0) {
197       return true;
198    }
199    /* We want to write SOS_LABEL and EOS_LABEL discard all others */
200    switch (rec->FileIndex) {                        
201    case PRE_LABEL:
202    case VOL_LABEL:
203    case EOT_LABEL:
204    case EOM_LABEL:
205       return true;                    /* don't write vol labels */
206    }
207    /*
208     * Modify record SessionId and SessionTime to correspond to
209     * output.
210     */
211    rec->VolSessionId = jcr->VolSessionId;
212    rec->VolSessionTime = jcr->VolSessionTime;
213    Dmsg5(200, "before write_rec JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
214       jcr->JobId,
215       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
216       stream_to_ascii(buf1, rec->Stream,rec->FileIndex), rec->data_len);
217
218    while (!write_record_to_block(jcr->dcr->block, rec)) {
219       Dmsg4(200, "!write_record_to_block blkpos=%u:%u len=%d rem=%d\n", 
220             dev->file, dev->block_num, rec->data_len, rec->remainder);
221       if (!write_block_to_device(jcr->dcr)) {
222          Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
223             dev->print_name(), dev->bstrerror());
224          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
225                dev->print_name(), dev->bstrerror());
226          return false;
227       }
228       Dmsg2(200, "===== Wrote block new pos %u:%u\n", dev->file, dev->block_num);
229    }
230    jcr->JobBytes += rec->data_len;   /* increment bytes this job */
231    if (rec->FileIndex > 0) {
232       jcr->JobFiles = rec->FileIndex;
233    } else {
234       return true;                    /* don't send LABELs to Dir */
235    }
236    Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
237       jcr->JobId,
238       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
239       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
240
241    /* Send attributes and digest to Director for Catalog */
242    stream = rec->Stream;
243    if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX ||
244        crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
245       if (!jcr->no_attributes) {
246          BSOCK *dir = jcr->dir_bsock;
247          if (are_attributes_spooled(jcr)) {
248             dir->set_spooling();
249          }
250          Dmsg0(850, "Send attributes to dir.\n");
251          if (!dir_update_file_attributes(jcr->dcr, rec)) {
252             dir->clear_spooling();
253             Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
254                dir->bstrerror());
255             return false;
256          }
257          dir->clear_spooling();
258       }
259    }
260
261    return true;
262 }