2 * SD -- mac.c -- responsible for doing
3 * migration, archive, and copy jobs.
5 * Kern Sibbald, January MMVI
10 Copyright (C) 2006 Kern Sibbald
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.
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.
27 /* Import functions */
28 extern char Job_end[];
30 /* Forward referenced subroutines */
31 static bool record_cb(DCR *dcr, DEV_RECORD *rec);
35 * Read Data and send to File Daemon
36 * Returns: false on failure
42 BSOCK *dir = jcr->dir_bsock;
47 switch(jcr->JobType) {
63 Dmsg0(20, "Start read data.\n");
65 if (!jcr->read_dcr || !jcr->dcr) {
66 Jmsg(jcr, M_FATAL, 0, _("Read and write devices not properly initialized.\n"));
69 Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
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);
78 Dmsg3(000, "Found %d volumes names for %s. First=%s\n", jcr->NumVolumes,
79 jcr->VolList->VolumeName, Type);
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);
88 jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
89 jcr->run_time = time(NULL);
91 ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
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"));
111 if (ok && dev->is_dvd()) {
112 ok = dvd_close_job(jcr->dcr); /* do DVD cleanup if any */
114 /* Release the device -- and send final Vol info to DIR */
115 release_device(jcr->dcr);
119 if (!release_device(jcr->read_dcr)) {
124 free_restore_volume_list(jcr);
127 if (!ok || job_canceled(jcr)) {
128 discard_attribute_spool(jcr);
130 commit_attribute_spool(jcr);
133 dir_send_job_status(jcr); /* update director */
136 Dmsg0(30, "Done reading.\n");
137 jcr->end_time = time(NULL);
138 dequeue_messages(jcr); /* send any queued messages */
140 set_jcr_job_status(jcr, JS_Terminated);
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);
147 bnet_sig(dir, BNET_EOD); /* send EOD to Director daemon */
153 * Called here for each record from read_records()
154 * Returns: true if OK
157 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
161 char buf1[100], buf2[100];
164 /* We want to write SOS_LABEL and EOS_LABEL */
165 switch (rec->FileIndex) {
170 return true; /* don't write vol labels */
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),
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,
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());
191 jcr->JobBytes += rec->data_len; /* increment bytes this job */
192 if (rec->FileIndex > 0) {
193 jcr->JobFiles = rec->FileIndex;
195 return ok; /* don't send LABELs to Dir */
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);
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;
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));
216 jcr->dir_bsock->spool = false;