]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/mac.c
kes Add back code to open tape device nonblocking, but if rewind fails
[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    Copyright (C) 2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "stored.h"
26
27 /* Import functions */
28 extern char Job_end[];   
29
30 /* Forward referenced subroutines */
31 static bool record_cb(DCR *dcr, DEV_RECORD *rec);
32
33
34 /*
35  *  Read Data and send to File Daemon
36  *   Returns: false on failure
37  *            true  on success
38  */
39 bool do_mac(JCR *jcr)
40 {
41    bool ok = true;
42    BSOCK *dir = jcr->dir_bsock;
43    const char *Type;
44    char ec1[50];
45    DEVICE *dev;
46
47    switch(jcr->JobType) {
48    case JT_MIGRATE:
49       Type = "Migration";
50       break;
51    case JT_ARCHIVE:
52       Type = "Archive";
53       break;
54    case JT_COPY:
55       Type = "Copy";
56       break;
57    default:
58       Type = "Unknown";
59       break;
60    }
61
62
63    Dmsg0(20, "Start read data.\n");
64
65    if (!jcr->read_dcr || !jcr->dcr) {
66       Jmsg(jcr, M_FATAL, 0, _("Read and write devices not properly initialized.\n"));
67       goto bail_out;
68    }
69    Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
70
71
72    create_restore_volume_list(jcr);
73    if (jcr->NumVolumes == 0) {
74       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type);
75       goto bail_out;
76    }
77
78    Dmsg3(200, "Found %d volumes names for %s. First=%s\n", jcr->NumVolumes,
79       jcr->VolList->VolumeName, Type);
80
81    /* Ready devices for reading and writing */
82    if (!acquire_device_for_read(jcr->read_dcr) ||
83        !acquire_device_for_append(jcr->dcr)) {
84       set_jcr_job_status(jcr, JS_ErrorTerminated);
85       goto bail_out;
86    }
87
88    Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->dcr->dev->file, jcr->dcr->dev->block_num);
89      
90
91    set_jcr_job_status(jcr, JS_Running);
92    dir_send_job_status(jcr);
93
94    jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
95    jcr->run_time = time(NULL);
96
97    ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
98    goto ok_out;
99
100 bail_out:
101    ok = false;
102
103 ok_out:
104    if (jcr->dcr) {
105       dev = jcr->dcr->dev;
106       if (ok || dev->can_write()) {
107          /* Flush out final partial block of this session */
108          if (!write_block_to_device(jcr->dcr)) {
109             Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
110                   dev->print_name(), dev->bstrerror());
111             Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
112             ok = false;
113          }
114          Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num);
115       }  
116
117
118       if (ok && dev->is_dvd()) {
119          ok = dvd_close_job(jcr->dcr);   /* do DVD cleanup if any */
120       }
121       /* Release the device -- and send final Vol info to DIR */
122       release_device(jcr->dcr);
123    }
124
125    if (jcr->read_dcr) {
126       if (!release_device(jcr->read_dcr)) {
127          ok = false;
128       }
129    }
130
131    free_restore_volume_list(jcr);
132
133
134    if (!ok || job_canceled(jcr)) {
135       discard_attribute_spool(jcr);
136    } else {
137       commit_attribute_spool(jcr);
138    }
139
140    dir_send_job_status(jcr);          /* update director */
141
142
143    Dmsg0(30, "Done reading.\n");
144    jcr->end_time = time(NULL);
145    dequeue_messages(jcr);             /* send any queued messages */
146    if (ok) {
147       set_jcr_job_status(jcr, JS_Terminated);
148    }
149    generate_daemon_event(jcr, "JobEnd");
150    bnet_fsend(dir, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
151       edit_uint64(jcr->JobBytes, ec1));
152    Dmsg4(200, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1); 
153        
154    bnet_sig(dir, BNET_EOD);           /* send EOD to Director daemon */
155
156    return ok;
157 }
158
159 /*
160  * Called here for each record from read_records()
161  *  Returns: true if OK
162  *           false if error
163  */
164 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
165 {
166    JCR *jcr = dcr->jcr;
167    DEVICE *dev = jcr->dcr->dev;
168    char buf1[100], buf2[100];
169    int32_t stream;   
170    
171    /* If label and not for us, discard it */
172    if (rec->FileIndex < 0 && rec->match_stat <= 0) {
173       return true;
174    }
175    /* We want to write SOS_LABEL and EOS_LABEL discard all others */
176    switch (rec->FileIndex) {                        
177    case PRE_LABEL:
178    case VOL_LABEL:
179    case EOT_LABEL:
180    case EOM_LABEL:
181       return true;                    /* don't write vol labels */
182    }
183    /*
184     * Modify record SessionId and SessionTime to correspond to
185     * output.
186     */
187    rec->VolSessionId = jcr->VolSessionId;
188    rec->VolSessionTime = jcr->VolSessionTime;
189    Dmsg5(200, "before write_rec JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
190       jcr->JobId,
191       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
192       stream_to_ascii(buf1, rec->Stream,rec->FileIndex), rec->data_len);
193
194    while (!write_record_to_block(jcr->dcr->block, rec)) {
195       Dmsg4(200, "!write_record_to_block blkpos=%u:%u len=%d rem=%d\n", 
196             dev->file, dev->block_num, rec->data_len, rec->remainder);
197       if (!write_block_to_device(jcr->dcr)) {
198          Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
199             dev->print_name(), dev->bstrerror());
200          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
201                dev->print_name(), dev->bstrerror());
202          return false;
203       }
204       Dmsg2(200, "===== Wrote block new pos %u:%u\n", dev->file, dev->block_num);
205    }
206    jcr->JobBytes += rec->data_len;   /* increment bytes this job */
207    if (rec->FileIndex > 0) {
208       jcr->JobFiles = rec->FileIndex;
209    } else {
210       return true;                    /* don't send LABELs to Dir */
211    }
212    Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
213       jcr->JobId,
214       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
215       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
216
217    /* Send attributes and digest to Director for Catalog */
218    stream = rec->Stream;
219    if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX ||
220        crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
221       if (!jcr->no_attributes) {
222          if (are_attributes_spooled(jcr)) {
223             jcr->dir_bsock->spool = true;
224          }
225          Dmsg0(850, "Send attributes to dir.\n");
226          if (!dir_update_file_attributes(jcr->dcr, rec)) {
227             jcr->dir_bsock->spool = false;
228             Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
229                bnet_strerror(jcr->dir_bsock));
230             return false;
231          }
232          jcr->dir_bsock->spool = false;
233       }
234    }
235
236    return true;
237 }