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(200, "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 Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->dcr->dev->file, jcr->dcr->dev->block_num);
91 set_jcr_job_status(jcr, JS_Running);
92 dir_send_job_status(jcr);
94 jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
95 jcr->run_time = time(NULL);
97 ok = read_records(jcr->read_dcr, record_cb, mount_next_read_volume);
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"));
114 Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num);
118 if (ok && dev->is_dvd()) {
119 ok = dvd_close_job(jcr->dcr); /* do DVD cleanup if any */
121 /* Release the device -- and send final Vol info to DIR */
122 release_device(jcr->dcr);
126 if (!release_device(jcr->read_dcr)) {
131 free_restore_volume_list(jcr);
134 if (!ok || job_canceled(jcr)) {
135 discard_attribute_spool(jcr);
137 commit_attribute_spool(jcr);
140 dir_send_job_status(jcr); /* update director */
143 Dmsg0(30, "Done reading.\n");
144 jcr->end_time = time(NULL);
145 dequeue_messages(jcr); /* send any queued messages */
147 set_jcr_job_status(jcr, JS_Terminated);
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);
154 bnet_sig(dir, BNET_EOD); /* send EOD to Director daemon */
160 * Called here for each record from read_records()
161 * Returns: true if OK
164 static bool record_cb(DCR *dcr, DEV_RECORD *rec)
167 DEVICE *dev = jcr->dcr->dev;
168 char buf1[100], buf2[100];
171 /* If label and not for us, discard it */
172 if (rec->FileIndex < 0 && rec->match_stat <= 0) {
175 /* We want to write SOS_LABEL and EOS_LABEL discard all others */
176 switch (rec->FileIndex) {
181 return true; /* don't write vol labels */
184 * Modify record SessionId and SessionTime to correspond to
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",
191 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
192 stream_to_ascii(buf1, rec->Stream,rec->FileIndex), rec->data_len);
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());
204 Dmsg2(200, "===== Wrote block new pos %u:%u\n", dev->file, dev->block_num);
206 jcr->JobBytes += rec->data_len; /* increment bytes this job */
207 if (rec->FileIndex > 0) {
208 jcr->JobFiles = rec->FileIndex;
210 return true; /* don't send LABELs to Dir */
212 Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
214 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
215 stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
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;
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));
232 jcr->dir_bsock->spool = false;