2 * Read code for Storage daemon
4 * Kern Sibbald, November MM
9 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public
22 License along with this program; if not, write to the Free
23 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
31 /* Forward referenced subroutines */
33 /* Variables used by Child process */
34 /* Global statistics */
35 /* Note, these probably should be in shared memory so that
36 * they are truly global for all processes
38 extern struct s_shm *shm; /* shared memory structure */
39 extern int FiledDataChan; /* File daemon data channel (port) */
42 /* Responses sent to the File daemon */
43 static char OK_data[] = "3000 OK data\n";
44 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
48 * Read Data and send to File Daemon
49 * Returns: 0 on failure
52 int do_read_data(JCR *jcr)
55 BSOCK *fd_sock = jcr->file_bsock;
61 SESSION_LABEL sessrec; /* session record */
63 Dmsg0(20, "Start read data.\n");
65 dev = jcr->device->dev;
66 memset(&sessrec, 0, sizeof(sessrec));
68 /* Tell File daemon we will send data */
69 bnet_fsend(fd_sock, OK_data);
70 Dmsg1(10, "bstored>filed: %s\n", fd_sock->msg);
74 if (!bnet_set_buffer_size(ds, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_READ)) {
79 Dmsg1(20, "Begin read device=%s\n", dev_name(dev));
81 block = new_block(dev);
85 Dmsg1(20, "Found %d volumes names to restore.\n", jcr->NumVolumes);
88 * Ready device for reading, and read records
90 if (!acquire_device_for_read(jcr, dev, block)) {
97 free_pool_memory(rec->data);
98 rec->data = ds->msg; /* use socket message buffer */
99 hdr = get_pool_memory(PM_MESSAGE);
102 * Read records, apply BSR filtering, and return any that are
106 if (job_cancelled(jcr)) {
111 Dmsg1(500, "Main read_record. rem=%d\n", rec->remainder);
113 if (!read_block_from_device(dev, block)) {
114 Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder);
115 if (dev->state & ST_EOT) {
116 if (!mount_next_read_volume(jcr, dev, block)) {
121 if (dev->state & ST_EOF) {
122 Dmsg0(90, "Got End of File. Trying again ...\n");
123 continue; /* End of File */
125 if (dev->state & ST_SHORT) {
130 for (rec->state=0; !is_block_empty(rec); ) {
132 if (!read_record_from_block(block, rec)) {
136 * At this point, we have at least a record header.
137 * Now decide if we want this record or not, but remember
138 * before accessing the record, we may need to read again to
142 /* Some sort of label? */
143 if (rec->FileIndex < 0) {
145 memset(&sessrec, 0, sizeof(sessrec));
146 switch (rec->FileIndex) {
148 rtype = "Fresh Volume Label";
151 rtype = "Volume Label";
152 unser_volume_label(dev, rec);
155 rtype = "Begin Session";
156 unser_session_label(&sessrec, rec);
159 rtype = "End Session";
162 rtype = "End of Media";
168 Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
169 rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
171 Dmsg1(40, "Got label = %d\n", rec->FileIndex);
172 if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
173 Dmsg0(40, "Get EOM LABEL\n");
175 break; /* yes, get out */
178 continue; /* ignore other labels */
179 } /* end if label record */
181 /* Match BSR against current record */
183 if (!match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec)) {
184 Dmsg0(50, "BSR rejected record\n");
189 /* Old way, deprecated */
190 if (rec->VolSessionId != jcr->read_VolSessionId ||
191 rec->VolSessionTime != jcr->read_VolSessionTime) {
192 Dmsg0(50, "Ignore record ids not equal\n");
194 continue; /* ignore */
198 if (is_partial_record(rec)) {
199 break; /* Go read full record */
202 /* Generate Header parameters and send to File daemon
203 * Note, we build header in hdr buffer to avoid wiping
204 * out the data record
207 if (!bnet_fsend(ds, rec_header, rec->VolSessionId, rec->VolSessionTime,
208 rec->FileIndex, rec->Stream, rec->data_len)) {
209 Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg);
215 Dmsg1(30, ">filed: Hdr=%s\n", ds->msg);
218 hdr = ds->msg; /* restore hdr buffer */
219 ds->msg = rec->data; /* restore data record address */
221 /* Send data record to File daemon */
222 ds->msglen = rec->data_len;
223 Dmsg1(40, ">filed: send %d bytes data.\n", ds->msglen);
224 if (!bnet_send(ds)) {
225 Dmsg1(000, "Error sending to FD. ERR=%s\n", bnet_strerror(ds));
226 Dmsg1(100, "Hdr=%s\n", hdr);
227 Dmsg1(100, "data=%s\n", ds->msg);
228 Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
235 /* Send end of data to FD */
236 bnet_sig(ds, BNET_EOD);
238 if (!release_device(jcr, dev, block)) {
241 free_pool_memory(hdr);
243 rec->data = NULL; /* previously released */
246 Dmsg0(30, "Done reading.\n");