]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/mac.c
kes Implement --without-qwt
[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 John Walker.
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, and copy 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->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    set_start_vol_position(jcr->dcr);
112
113    ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
114    goto ok_out;
115
116 bail_out:
117    ok = false;
118
119 ok_out:
120    if (jcr->dcr) {
121       dev = jcr->dcr->dev;
122       if (ok || dev->can_write()) {
123          /* Flush out final partial block of this session */
124          if (!write_block_to_device(jcr->dcr)) {
125             Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
126                   dev->print_name(), dev->bstrerror());
127             Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
128             ok = false;
129          }
130          Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num);
131       }  
132
133       if (!ok) {
134          discard_data_spool(jcr->dcr);
135       } else {
136          /* Note: if commit is OK, the device will remain locked */
137          commit_data_spool(jcr->dcr);
138       }
139
140       if (ok && dev->is_dvd()) {
141          ok = dvd_close_job(jcr->dcr);   /* do DVD cleanup if any */
142       }
143       /* Release the device -- and send final Vol info to DIR */
144       release_device(jcr->dcr);
145
146       if (!ok || job_canceled(jcr)) {
147          discard_attribute_spool(jcr);
148       } else {
149          commit_attribute_spool(jcr);
150       }
151    }
152
153    if (jcr->read_dcr) {
154       if (!release_device(jcr->read_dcr)) {
155          ok = false;
156       }
157    }
158
159    free_restore_volume_list(jcr);
160
161    dir_send_job_status(jcr);          /* update director */
162
163
164    Dmsg0(30, "Done reading.\n");
165    jcr->end_time = time(NULL);
166    dequeue_messages(jcr);             /* send any queued messages */
167    if (ok) {
168       set_jcr_job_status(jcr, JS_Terminated);
169    }
170    generate_daemon_event(jcr, "JobEnd");
171    dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
172       edit_uint64(jcr->JobBytes, ec1));
173    Dmsg4(200, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1); 
174        
175    dir->signal(BNET_EOD);             /* send EOD to Director daemon */
176
177    return ok;
178 }
179
180 /*
181  * Called here for each record from read_records()
182  *  Returns: true if OK
183  *           false if error
184  */
185 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
186 {
187    JCR *jcr = dcr->jcr;
188    DEVICE *dev = jcr->dcr->dev;
189    char buf1[100], buf2[100];
190    int32_t stream;   
191    
192    /* If label and not for us, discard it */
193    if (rec->FileIndex < 0 && rec->match_stat <= 0) {
194       return true;
195    }
196    /* We want to write SOS_LABEL and EOS_LABEL discard all others */
197    switch (rec->FileIndex) {                        
198    case PRE_LABEL:
199    case VOL_LABEL:
200    case EOT_LABEL:
201    case EOM_LABEL:
202       return true;                    /* don't write vol labels */
203    }
204    /*
205     * Modify record SessionId and SessionTime to correspond to
206     * output.
207     */
208    rec->VolSessionId = jcr->VolSessionId;
209    rec->VolSessionTime = jcr->VolSessionTime;
210    Dmsg5(200, "before write_rec JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
211       jcr->JobId,
212       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
213       stream_to_ascii(buf1, rec->Stream,rec->FileIndex), rec->data_len);
214
215    while (!write_record_to_block(jcr->dcr->block, rec)) {
216       Dmsg4(200, "!write_record_to_block blkpos=%u:%u len=%d rem=%d\n", 
217             dev->file, dev->block_num, rec->data_len, rec->remainder);
218       if (!write_block_to_device(jcr->dcr)) {
219          Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
220             dev->print_name(), dev->bstrerror());
221          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
222                dev->print_name(), dev->bstrerror());
223          return false;
224       }
225       Dmsg2(200, "===== Wrote block new pos %u:%u\n", dev->file, dev->block_num);
226    }
227    jcr->JobBytes += rec->data_len;   /* increment bytes this job */
228    if (rec->FileIndex > 0) {
229       jcr->JobFiles = rec->FileIndex;
230    } else {
231       return true;                    /* don't send LABELs to Dir */
232    }
233    Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
234       jcr->JobId,
235       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
236       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
237
238    /* Send attributes and digest to Director for Catalog */
239    stream = rec->Stream;
240    if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX ||
241        crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
242       if (!jcr->no_attributes) {
243          BSOCK *dir = jcr->dir_bsock;
244          if (are_attributes_spooled(jcr)) {
245             dir->set_spooling();
246          }
247          Dmsg0(850, "Send attributes to dir.\n");
248          if (!dir_update_file_attributes(jcr->dcr, rec)) {
249             dir->clear_spooling();
250             Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
251                dir->bstrerror());
252             return false;
253          }
254          dir->clear_spooling();
255       }
256    }
257
258    return true;
259 }