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