]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/mac.c
======================= Warning ==========================
[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    jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
89    jcr->run_time = time(NULL);
90
91    ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
92    goto ok_out;
93
94 bail_out:
95    ok = false;
96
97 ok_out:
98    if (jcr->dcr) {
99       dev = jcr->dcr->dev;
100       if (ok || dev->can_write()) {
101          /* Flush out final partial block of this session */
102          if (!write_block_to_device(jcr->dcr)) {
103             Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
104                   dev->print_name(), dev->bstrerror());
105             Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
106             ok = false;
107          }
108       }  
109
110
111       if (ok && dev->is_dvd()) {
112          ok = dvd_close_job(jcr->dcr);   /* do DVD cleanup if any */
113       }
114       /* Release the device -- and send final Vol info to DIR */
115       release_device(jcr->dcr);
116    }
117
118    if (jcr->read_dcr) {
119       if (!release_device(jcr->read_dcr)) {
120          ok = false;
121       }
122    }
123
124    free_restore_volume_list(jcr);
125
126
127    if (!ok || job_canceled(jcr)) {
128       discard_attribute_spool(jcr);
129    } else {
130       commit_attribute_spool(jcr);
131    }
132
133    dir_send_job_status(jcr);          /* update director */
134
135
136    Dmsg0(30, "Done reading.\n");
137    jcr->end_time = time(NULL);
138    dequeue_messages(jcr);             /* send any queued messages */
139    if (ok) {
140       set_jcr_job_status(jcr, JS_Terminated);
141    }
142    generate_daemon_event(jcr, "JobEnd");
143    bnet_fsend(dir, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
144       edit_uint64(jcr->JobBytes, ec1));
145    Dmsg4(400, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1); 
146        
147    bnet_sig(dir, BNET_EOD);           /* send EOD to Director daemon */
148
149    return ok;
150 }
151
152 /*
153  * Called here for each record from read_records()
154  *  Returns: true if OK
155  *           false if error
156  */
157 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
158 {
159    bool ok = true;
160    JCR *jcr = dcr->jcr;
161    char buf1[100], buf2[100];
162    int32_t stream;   
163    
164    /* We want to write SOS_LABEL and EOS_LABEL */
165    switch (rec->FileIndex) {                        
166    case PRE_LABEL:
167    case VOL_LABEL:
168    case EOT_LABEL:
169    case EOM_LABEL:
170       return true;                    /* don't write vol labels */
171    }
172    rec->VolSessionId = jcr->VolSessionId;
173    rec->VolSessionTime = jcr->VolSessionTime;
174    Dmsg4(850, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
175       rec->FileIndex, rec->VolSessionId, 
176       stream_to_ascii(buf1, rec->Stream,rec->FileIndex),
177       rec->data_len);
178
179    while (!write_record_to_block(jcr->dcr->block, rec)) {
180       Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
181                  rec->remainder);
182       if (!write_block_to_device(jcr->dcr)) {
183          DEVICE *dev = jcr->dcr->dev;
184          Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
185             dev->print_name(), dev->bstrerror());
186          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
187                dev->print_name(), dev->bstrerror());
188          return false;
189       }
190    }
191    jcr->JobBytes += rec->data_len;   /* increment bytes this job */
192    if (rec->FileIndex > 0) {
193       jcr->JobFiles = rec->FileIndex;
194    } else {
195       return ok;                      /* don't send LABELs to Dir */
196    }
197    Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
198       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
199       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
200
201    /* Send attributes and digest to Director for Catalog */
202    stream = rec->Stream;
203    if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX ||
204        crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
205       if (!jcr->no_attributes) {
206          if (are_attributes_spooled(jcr)) {
207             jcr->dir_bsock->spool = true;
208          }
209          Dmsg0(850, "Send attributes to dir.\n");
210          if (!dir_update_file_attributes(jcr->dcr, rec)) {
211             jcr->dir_bsock->spool = false;
212             Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
213                bnet_strerror(jcr->dir_bsock));
214             return false;
215          }
216          jcr->dir_bsock->spool = false;
217       }
218    }
219
220    return ok;
221 }